Puyiiii commited on
Commit
e78147d
·
verified ·
1 Parent(s): 9eeebce

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/INSTALLER +1 -0
  2. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/LICENSE.txt +20 -0
  3. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/METADATA +92 -0
  4. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/RECORD +407 -0
  5. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/REQUESTED +0 -0
  6. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/WHEEL +5 -0
  7. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/entry_points.txt +5 -0
  8. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/top_level.txt +1 -0
  9. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/pkg_resources/__init__.py +0 -0
  10. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/pkg_resources/py31compat.py +23 -0
  11. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/__init__.py +26 -0
  12. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/compat/__init__.py +0 -0
  13. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py +6 -0
  14. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/providers.py +124 -0
  15. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/reporters.py +37 -0
  16. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/resolvers.py +473 -0
  17. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/structs.py +165 -0
  18. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py +0 -0
  19. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py +51 -0
  20. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py +24 -0
  21. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py +160 -0
  22. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/__init__.py +242 -0
  23. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_deprecation_warning.py +7 -0
  24. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_imp.py +82 -0
  25. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/__init__.py +0 -0
  26. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/more_itertools/__init__.py +4 -0
  27. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/more_itertools/more.py +0 -0
  28. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/more_itertools/recipes.py +620 -0
  29. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/ordered_set.py +488 -0
  30. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__about__.py +27 -0
  31. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__init__.py +26 -0
  32. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_compat.py +38 -0
  33. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_structures.py +86 -0
  34. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_typing.py +48 -0
  35. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/markers.py +328 -0
  36. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/requirements.py +145 -0
  37. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/specifiers.py +863 -0
  38. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/tags.py +751 -0
  39. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/utils.py +65 -0
  40. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/version.py +535 -0
  41. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/pyparsing.py +0 -0
  42. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/archive_util.py +205 -0
  43. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/build_meta.py +281 -0
  44. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/cli-32.exe +0 -0
  45. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/cli-64.exe +0 -0
  46. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/cli.exe +0 -0
  47. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/command/alias.py +78 -0
  48. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/command/bdist_egg.py +456 -0
  49. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/command/build_ext.py +328 -0
  50. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/command/easy_install.py +2290 -0
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/INSTALLER ADDED
@@ -0,0 +1 @@
 
 
1
+ pip
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2008-2021 The pip developers (see AUTHORS.txt file)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/METADATA ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.1
2
+ Name: pip
3
+ Version: 21.2.4
4
+ Summary: The PyPA recommended tool for installing Python packages.
5
+ Home-page: https://pip.pypa.io/
6
+ Author: The pip developers
7
+ Author-email: distutils-sig@python.org
8
+ License: MIT
9
+ Project-URL: Documentation, https://pip.pypa.io
10
+ Project-URL: Source, https://github.com/pypa/pip
11
+ Project-URL: Changelog, https://pip.pypa.io/en/stable/news/
12
+ Platform: UNKNOWN
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Topic :: Software Development :: Build Tools
17
+ Classifier: Programming Language :: Python
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.6
21
+ Classifier: Programming Language :: Python :: 3.7
22
+ Classifier: Programming Language :: Python :: 3.8
23
+ Classifier: Programming Language :: Python :: 3.9
24
+ Classifier: Programming Language :: Python :: Implementation :: CPython
25
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
26
+ Requires-Python: >=3.6
27
+ License-File: LICENSE.txt
28
+
29
+ pip - The Python Package Installer
30
+ ==================================
31
+
32
+ .. image:: https://img.shields.io/pypi/v/pip.svg
33
+ :target: https://pypi.org/project/pip/
34
+
35
+ .. image:: https://readthedocs.org/projects/pip/badge/?version=latest
36
+ :target: https://pip.pypa.io/en/latest
37
+
38
+ pip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes.
39
+
40
+ Please take a look at our documentation for how to install and use pip:
41
+
42
+ * `Installation`_
43
+ * `Usage`_
44
+
45
+ We release updates regularly, with a new version every 3 months. Find more details in our documentation:
46
+
47
+ * `Release notes`_
48
+ * `Release process`_
49
+
50
+ 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.
51
+
52
+ **Note**: pip 21.0, in January 2021, removed Python 2 support, per pip's `Python 2 support policy`_. Please migrate to Python 3.
53
+
54
+ If you find bugs, need help, or want to talk to the developers, please use our mailing lists or chat rooms:
55
+
56
+ * `Issue tracking`_
57
+ * `Discourse channel`_
58
+ * `User IRC`_
59
+
60
+ 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:
61
+
62
+ * `GitHub page`_
63
+ * `Development documentation`_
64
+ * `Development mailing list`_
65
+ * `Development IRC`_
66
+
67
+ Code of Conduct
68
+ ---------------
69
+
70
+ Everyone interacting in the pip project's codebases, issue trackers, chat
71
+ rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_.
72
+
73
+ .. _package installer: https://packaging.python.org/guides/tool-recommendations/
74
+ .. _Python Package Index: https://pypi.org
75
+ .. _Installation: https://pip.pypa.io/en/stable/installation/
76
+ .. _Usage: https://pip.pypa.io/en/stable/
77
+ .. _Release notes: https://pip.pypa.io/en/stable/news.html
78
+ .. _Release process: https://pip.pypa.io/en/latest/development/release-process/
79
+ .. _GitHub page: https://github.com/pypa/pip
80
+ .. _Development documentation: https://pip.pypa.io/en/latest/development
81
+ .. _made a big improvement to the heart of pip: https://pyfound.blogspot.com/2020/11/pip-20-3-new-resolver.html
82
+ .. _learn more: https://pip.pypa.io/en/latest/user_guide/#changes-to-the-pip-dependency-resolver-in-20-3-2020
83
+ .. _sign up for our user experience research studies: https://pyfound.blogspot.com/2020/03/new-pip-resolver-to-roll-out-this-year.html
84
+ .. _Python 2 support policy: https://pip.pypa.io/en/latest/development/release-process/#python-2-support
85
+ .. _Issue tracking: https://github.com/pypa/pip/issues
86
+ .. _Discourse channel: https://discuss.python.org/c/packaging
87
+ .. _Development mailing list: https://mail.python.org/mailman3/lists/distutils-sig.python.org/
88
+ .. _User IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa
89
+ .. _Development IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa-dev
90
+ .. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md
91
+
92
+
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/RECORD ADDED
@@ -0,0 +1,407 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ../../../bin/pip,sha256=tzObN17Wbm7g14pPEhnDImT6UTGg53jn4T9cDgS2jjA,272
2
+ ../../../bin/pip3,sha256=tzObN17Wbm7g14pPEhnDImT6UTGg53jn4T9cDgS2jjA,272
3
+ ../../../bin/pip3.9,sha256=tzObN17Wbm7g14pPEhnDImT6UTGg53jn4T9cDgS2jjA,272
4
+ pip-21.2.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
5
+ pip-21.2.4.dist-info/LICENSE.txt,sha256=I6c2HCsVgQKLxiO52ivSSZeryqR4Gs5q1ESjeUT42uE,1090
6
+ pip-21.2.4.dist-info/METADATA,sha256=PGCimuD-VsKv664Ne_9navMt6I9Ym_rm5p_u6Ykgfd4,4165
7
+ pip-21.2.4.dist-info/RECORD,,
8
+ pip-21.2.4.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ pip-21.2.4.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92
10
+ pip-21.2.4.dist-info/entry_points.txt,sha256=5ExSa1s54zSPNA_1epJn5SX06786S8k5YHwskMvVYzw,125
11
+ pip-21.2.4.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
12
+ pip/__init__.py,sha256=EkjFYKiNdO5r1TZT1K-GxPs3Bl2IdRXw75e7IVsKrmc,357
13
+ pip/__main__.py,sha256=mXwWDftNLMKfwVqKFWGE_uuBZvGSIiUELhLkeysIuZc,1198
14
+ pip/_internal/__init__.py,sha256=nnFCuxrPMgALrIDxSoy-H6Zj4W4UY60D-uL1aJyq0pc,573
15
+ pip/_internal/build_env.py,sha256=uqtt1F0185ctzme5UX43I6bFHVeORY7q-dyhpkk5NDE,10121
16
+ pip/_internal/cache.py,sha256=6VONtoReGZbBd7sqY1n6hwkdWC4iz3tmXwXwZjpjZKw,9958
17
+ pip/_internal/cli/__init__.py,sha256=FkHBgpxxb-_gd6r1FjnNhfMOzAUYyXoXKJ6abijfcFU,132
18
+ pip/_internal/cli/autocompletion.py,sha256=NK5yqe49SgExZOCFVEUT5Bf0QV2CuITGK27WSo2MWg8,6399
19
+ pip/_internal/cli/base_command.py,sha256=Dq5oXBXYd24GaHs1vPt6CfYgCl22V_4tLEJqfQyBrdE,7596
20
+ pip/_internal/cli/cmdoptions.py,sha256=xOqvgDNfpkMXVjy0mH3hI0HyczVD6wMuP8K44qsvbew,28283
21
+ pip/_internal/cli/command_context.py,sha256=a1pBBvvGLDiZ1Kw64_4tT6HmRTwYDoYy8JFgG5Czn7s,760
22
+ pip/_internal/cli/main.py,sha256=ioJ8IVlb2K1qLOxR-tXkee9lURhYV89CDM71MKag7YY,2472
23
+ pip/_internal/cli/main_parser.py,sha256=Q9TnytfuC5Z2JSjBFWVGtEdYLFy7rukNIb04movHdAo,2614
24
+ pip/_internal/cli/parser.py,sha256=CDXTuFr2UD8ozOlZYf1KDziQdo9-X_IaYOiUcyJQwrA,10788
25
+ pip/_internal/cli/progress_bars.py,sha256=ha8wowclY8_PaoM0cz4G6qK37zjnzuxQ-ydOtzx4EMI,8300
26
+ pip/_internal/cli/req_command.py,sha256=ZlxKFS9LtEbE1IRB6JyeUeYMe7lvKxVIzpdvag-BHok,16548
27
+ pip/_internal/cli/spinners.py,sha256=TFhjxtOnLeNJ5YmRvQm4eKPgPbJNkZiqO8jOXuxRaYU,5076
28
+ pip/_internal/cli/status_codes.py,sha256=sEFHUaUJbqv8iArL3HAtcztWZmGOFX01hTesSytDEh0,116
29
+ pip/_internal/commands/__init__.py,sha256=3f1ZVidEDfgmzAH7aypZLKOZUvUy7qxv4X1CiIZEN30,3776
30
+ pip/_internal/commands/cache.py,sha256=O1grQjTg6IRFs_8DxMH00583tmCR0ujqTMv_gZ0h0uU,7237
31
+ pip/_internal/commands/check.py,sha256=gPC6GTp7S9aK73IeZAW7Z6yxlMnWdMyDTq9er9nXpIY,1570
32
+ pip/_internal/commands/completion.py,sha256=4Uh_cg04qDmtmgLji-J4VJKZ8BaIBZy2_uTWLi8tiVk,2914
33
+ pip/_internal/commands/configuration.py,sha256=TK9VTXNJ5haVH0Dc_ylhqo6A9Q_GcNoNsAOMJff4MYY,8962
34
+ pip/_internal/commands/debug.py,sha256=f943fbrAUufQ7flAR2zHfI0oi_uqhJEEW7Fj_EiwB1Y,6647
35
+ pip/_internal/commands/download.py,sha256=VGyQ6TDLiqJqJXfJwr_D6ZuHnYfhmzZPQk1mRSQp3tQ,4949
36
+ pip/_internal/commands/freeze.py,sha256=x0-ia-MFrVvfYqe5p6yAWqzaK5AIi3SqqcXBJNvxXkg,2785
37
+ pip/_internal/commands/hash.py,sha256=Y5FQ_WgbuEFnJxyLZdNYP928BGWNyNm9ljIUr90R6tI,1664
38
+ pip/_internal/commands/help.py,sha256=F_IJkERv9gGfGC6YpBNYm_qs8xmBphUCfOuguNRSqLs,1132
39
+ pip/_internal/commands/index.py,sha256=xA5LSVy1kv-IAvsjIX6Wnk5ZHA0Y_m6AP9T5ZoUGs9o,4781
40
+ pip/_internal/commands/install.py,sha256=FV-qBbQ56TUEmLDtuWTMeNpD4aQtOpjBEi7ePqlEtSM,27493
41
+ pip/_internal/commands/list.py,sha256=fpG6_KYqtAEBV8uSlt_lfF7o1GTuS4UdobsZjVqZspQ,11753
42
+ pip/_internal/commands/search.py,sha256=P8GY077JmUwy7FiOgYJ1CPDsBPgmo7it-b14luquJN4,5543
43
+ pip/_internal/commands/show.py,sha256=2TxWaJ2saCDSVUVBoRYueijLiueid2DNOhZuM-jhGf0,7974
44
+ pip/_internal/commands/uninstall.py,sha256=0VQQMfPBTGSlWJn1RRgvYtJhSj7tQFYc3H1kOjrstRE,3480
45
+ pip/_internal/commands/wheel.py,sha256=UiH15NXfrJ9piFNg3oHm4n2Jyk9Ojv5q0MvrWbHB3Ac,6189
46
+ pip/_internal/configuration.py,sha256=QBLfhv-sbP-oR08NFxSYnv_mLB-SgtNOsWXAF9tDEcM,13725
47
+ pip/_internal/distributions/__init__.py,sha256=Hq6kt6gXBgjNit5hTTWLAzeCNOKoB-N0pGYSqehrli8,858
48
+ pip/_internal/distributions/base.py,sha256=GynlnVE3QLvNu4JvnxPO6D8IQSs_GAlFUabA6U-G-eU,1206
49
+ pip/_internal/distributions/installed.py,sha256=gT20WSniecOvKGMA-nCyq-4DcJlrIjv8jT-JEWyEOnA,645
50
+ pip/_internal/distributions/sdist.py,sha256=VBme1UNlCuH_wIoUHTZq9ngo2NpFWQXmJqnwUb3ZpTk,3862
51
+ pip/_internal/distributions/wheel.py,sha256=J7DNQvKS50pXfwXtetKZtLNgYzkEc8SAbaKQ5v6JHtA,1183
52
+ pip/_internal/exceptions.py,sha256=2JQJSS68oggR_ZIOA-h1U2DRADURbkQn9Nf4EZWZ834,13170
53
+ pip/_internal/index/__init__.py,sha256=vpt-JeTZefh8a-FC22ZeBSXFVbuBcXSGiILhQZJaNpQ,30
54
+ pip/_internal/index/collector.py,sha256=oH4XlYHvGMXePbjNhKZPpLI-NLBTXxpHRRZgQ85meNk,17645
55
+ pip/_internal/index/package_finder.py,sha256=Zzto_P1YPeTlBjJTlPgU8wjocQDJnLYZxUSR8JxVf1E,36138
56
+ pip/_internal/index/sources.py,sha256=SVyPitv08-Qalh2_Bk5diAJ9GAA_d-a93koouQodAG0,6557
57
+ pip/_internal/locations/__init__.py,sha256=8HvAnPCRi2Ln5yimpHRq8NVtsImh1KEvqsPhi4H56y0,13292
58
+ pip/_internal/locations/_distutils.py,sha256=Sk7tw8ZP1DWMYJ8MibABsa8IME2Ejv1PKeGlYQCBTZc,5871
59
+ pip/_internal/locations/_sysconfig.py,sha256=LQNKTJKyjVqxXaPntlBwdUqTG1xwYf6GVCKMbyRJx5M,7918
60
+ pip/_internal/locations/base.py,sha256=x5D1ONktmPJd8nnUTh-ELsAJ7fiXA-k-0a_vhfi2_Us,1579
61
+ pip/_internal/main.py,sha256=BZ0vkdqgpoteTo1A1Q8ovFe8EzgKFJWOUjPmIUQfGCY,351
62
+ pip/_internal/metadata/__init__.py,sha256=0XQDTWweYOV7kcMuzwoiCggu3wJearBNcK8JV9LXA6Y,1576
63
+ pip/_internal/metadata/base.py,sha256=oRj58fKGutZKZCslfQlKfrzuXI_0M4w1xVOluT3-6TQ,7928
64
+ pip/_internal/metadata/pkg_resources.py,sha256=xOYt6IluIDvVMgYX-QoZA3SFbToJlZDOVPRHVPJ2Uk4,5200
65
+ pip/_internal/models/__init__.py,sha256=3DHUd_qxpPozfzouoqa9g9ts1Czr5qaHfFxbnxriepM,63
66
+ pip/_internal/models/candidate.py,sha256=b2aiufhD5jZEI0zhEaMn_o1VRldVE2J-MPsqPpcY2Ds,946
67
+ pip/_internal/models/direct_url.py,sha256=x2-kAnrP18XAdOftYBStDNt3Zfd8sipef5h0h_efGvY,6262
68
+ pip/_internal/models/format_control.py,sha256=t5nmFD43huIFj0VchV6FuvlaRHfaMTotbBOTOPBsKeY,2557
69
+ pip/_internal/models/index.py,sha256=_U2imEWggevvcI7rhQCFZK0djsE-It13BJmvW9Ejmig,1058
70
+ pip/_internal/models/link.py,sha256=chRRuGqeE5w1XqidCrw6j-j8O-eeCmw-HUdYCR18HmQ,9809
71
+ pip/_internal/models/scheme.py,sha256=i2QGt5J96gMKC_Wm7xO587kibhhChUQoULhAFgPRxkE,738
72
+ pip/_internal/models/search_scope.py,sha256=mykEee0wDNCx9xZmQBtkgVaDiQVcDNqbjAZGqI1nm78,4474
73
+ pip/_internal/models/selection_prefs.py,sha256=OEoiP83Wpm7cUwjH7fnbRo7TzHl5D4y23W0JnZLXk_4,1877
74
+ pip/_internal/models/target_python.py,sha256=7iT4lbRtoNRkwsmLndysJ4Ic7Iwp_YyIII3doXeLD8c,3870
75
+ pip/_internal/models/wheel.py,sha256=Ec8fvPoSYeBX9cvBvffLM7gNRx23CrVud1dN3zJmBjc,3541
76
+ pip/_internal/network/__init__.py,sha256=jf6Tt5nV_7zkARBrKojIXItgejvoegVJVKUbhAa5Ioc,50
77
+ pip/_internal/network/auth.py,sha256=zq-fu-eK_EwiqjT0SVmMxuzyvhBlCdBGJi_fnOmcar8,11645
78
+ pip/_internal/network/cache.py,sha256=HoprMCecwd4IS2wDZowc9B_OpaBlFjJYJl4xOxvtuwU,2100
79
+ pip/_internal/network/download.py,sha256=VmiR-KKIBugShZS4JlD7N8mq3hErx-0fK-D8aTYU3Og,6016
80
+ pip/_internal/network/lazy_wheel.py,sha256=4szChUW2I9quggvjEoIhALezmiVVteescGh6TDUslaQ,7615
81
+ pip/_internal/network/session.py,sha256=3tJHNQCooM7bjLK1WP-q6tiJ84jtqkyrIdrYY84WR1A,16582
82
+ pip/_internal/network/utils.py,sha256=igLlTu_-q0LmL8FdJKq-Uj7AT_owrQ-T9FfyarkhK5U,4059
83
+ pip/_internal/network/xmlrpc.py,sha256=AzQgG4GgS152_cqmGr_Oz2MIXsCal-xfsis7fA7nmU0,1791
84
+ pip/_internal/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
85
+ pip/_internal/operations/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
86
+ pip/_internal/operations/build/metadata.py,sha256=jJp05Rrp0AMsQb7izDXbNGC1LtPNwOhHQj7cRM5324c,1165
87
+ pip/_internal/operations/build/metadata_legacy.py,sha256=ECMBhLEPEQv6PUUCpPCXW-wN9QRXdY45PNXJv7BZKTU,1917
88
+ pip/_internal/operations/build/wheel.py,sha256=WYLMxuxqN3ahJTQk2MI9hdmZKBpFyxHeNpUdO0PybxU,1106
89
+ pip/_internal/operations/build/wheel_legacy.py,sha256=NOJhTYMYljdbizFo_WjkaKGWG1SEZ6aByrBdCrrsZB8,3227
90
+ pip/_internal/operations/check.py,sha256=zEIdxyRL3vc7CQ1p8qkLFG-mjs-LjnaJDxOr1WI5Yp0,5295
91
+ pip/_internal/operations/freeze.py,sha256=TyLvXT4ZqpIi8x8X_TTsgBJ76IG54CidJlxGIHBbmBM,10556
92
+ pip/_internal/operations/install/__init__.py,sha256=mX7hyD2GNBO2mFGokDQ30r_GXv7Y_PLdtxcUv144e-s,51
93
+ pip/_internal/operations/install/editable_legacy.py,sha256=bjBObfE6sz3UmGI7y4-GCgKa2WmTgnWlFFU7b-i0sQs,1396
94
+ pip/_internal/operations/install/legacy.py,sha256=Wk_46sR7zDsh7vp4j63Hka4NTevQ617WdqJKt8_TuUQ,4405
95
+ pip/_internal/operations/install/wheel.py,sha256=4Y6rtOpPnjlvGkzYXP8HXzqJu1KHEuA6ExgHBdZnD6s,29466
96
+ pip/_internal/operations/prepare.py,sha256=jgnH7CIdoAhwnYOSpkESvhrJ1yr5TL2ZY5ojjSzRMZo,24848
97
+ pip/_internal/pyproject.py,sha256=Sl1dOQYazG9AsrE0TXWK2zVcDR_FROshCTwjKBRQsPE,7063
98
+ pip/_internal/req/__init__.py,sha256=lz4GFfzm5gsm0e8H98Wi6IPI14R2JdDMBc61-4F-0CY,2831
99
+ pip/_internal/req/constructors.py,sha256=35LRb-iaL01AlKBOO_2vrbKil6KI5Tl450NJwUvUnhk,15826
100
+ pip/_internal/req/req_file.py,sha256=TsBSr0LMVIYF7AqkwslyJxHPLstN0SMqKeVxciI2In4,17408
101
+ pip/_internal/req/req_install.py,sha256=jPfSPt-s3RoRCj6tYqvvHaxxIW1yr8KbiPRGbAyF3pU,31671
102
+ pip/_internal/req/req_set.py,sha256=NoPQztL1Z5HZEB3n2Wtst6KV51hMDAPe9AfdAUWmJLs,7572
103
+ pip/_internal/req/req_tracker.py,sha256=dJ3ql2C3VyaKUQN9kwbFvOPMxAvbTdblB0hKQ2f6Lns,4182
104
+ pip/_internal/req/req_uninstall.py,sha256=wBcGKaweIyi5RGPPpBqrrn62t8uP3frZmrUJ-qDeO0Y,23821
105
+ pip/_internal/resolution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
106
+ pip/_internal/resolution/base.py,sha256=yATwIW1VbJkwkFJIgG3JQafndFDSZ50smc-Ao9-SoxI,557
107
+ pip/_internal/resolution/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
108
+ pip/_internal/resolution/legacy/resolver.py,sha256=TZnGUay9WM2Uk0W3D48OA70U9cLYYGHxles1h9ELqSg,17552
109
+ pip/_internal/resolution/resolvelib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
110
+ pip/_internal/resolution/resolvelib/base.py,sha256=Yvgb2jf0l6S4C2rXAbjbpURYF6yjUgCdwDSrnpiZA8U,5290
111
+ pip/_internal/resolution/resolvelib/candidates.py,sha256=RgCvLf1meDecmw9lfhG_AU5tN9ufaC0EDrcVOR2hgiA,18842
112
+ pip/_internal/resolution/resolvelib/factory.py,sha256=N9telNB1arFV-4TqdGdh9KML8zfAWdMbqUSNip6HeEc,26859
113
+ pip/_internal/resolution/resolvelib/found_candidates.py,sha256=ES3PNACh3ONwGAghPip2Vbgyy_e4baKmeEEHVQiq47g,5285
114
+ pip/_internal/resolution/resolvelib/provider.py,sha256=fy139RDxPrsPmNLn6YrrjqhBOmeLY0aHEEdzZqS35aU,8420
115
+ pip/_internal/resolution/resolvelib/reporter.py,sha256=Z06Xa4d9dTWbHNvXIBtBxDn4DHeQmlyW9MJAojkC_iU,2600
116
+ pip/_internal/resolution/resolvelib/requirements.py,sha256=pcsnwz7txyDNZUEOWJOZEfivy3COWHPf_DIU7fwZ-Kk,5455
117
+ pip/_internal/resolution/resolvelib/resolver.py,sha256=Rry36d0uCKobfBnSPYMw8WStyNYtjAEFz3j6ZtBsbGQ,10523
118
+ pip/_internal/self_outdated_check.py,sha256=ivoUYaGuq-Ra_DvlZvPtHhgbY97NKHYuPGzrgN2G1A8,6484
119
+ pip/_internal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
120
+ pip/_internal/utils/_log.py,sha256=-jHLOE_THaZz5BFcCnoSL9EYAtJ0nXem49s9of4jvKw,1015
121
+ pip/_internal/utils/appdirs.py,sha256=CyH0arjhfR4kaeybXs5B1hxe66KeeCfssJhiRFxpFJk,1185
122
+ pip/_internal/utils/compat.py,sha256=ACyBfLgj3_XG-iA5omEDrXqDM0cQKzi8h8HRBInzG6Q,1884
123
+ pip/_internal/utils/compatibility_tags.py,sha256=h2P4U0ZCkWHwPYveBzFZA79it6agElRhm6yci7S8MCo,5454
124
+ pip/_internal/utils/datetime.py,sha256=m21Y3wAtQc-ji6Veb6k_M5g6A0ZyFI4egchTdnwh-pQ,242
125
+ pip/_internal/utils/deprecation.py,sha256=0bdiuvnAcAZMp1dDrwxK7uDgmJQDHVfb1790_ypO9U4,3200
126
+ pip/_internal/utils/direct_url_helpers.py,sha256=5ffB9GHoqalUvSU6C53lEFdUgYcWAbXJGfyCwGyIlrY,2994
127
+ pip/_internal/utils/distutils_args.py,sha256=mcAscyp80vTt3xAGTipnpgc83V-_wCvydNELVXLq7JI,1249
128
+ pip/_internal/utils/encoding.py,sha256=bdZ3YgUpaOEBI5MP4-DEXiQarCW3V0rxw1kRz-TaU1Q,1169
129
+ pip/_internal/utils/entrypoints.py,sha256=aPvCnQVi9Hdk35Kloww_D5ibjUpqxgqcJP8O9VuMZek,1055
130
+ pip/_internal/utils/filesystem.py,sha256=rrl-rY1w8TYyKYndUyZlE9ffkQyA4-jI9x_59zXkn5s,5893
131
+ pip/_internal/utils/filetypes.py,sha256=weviVbapHWVQ_8-K-PTQ_TnYL66kZi4SrVBTmRYZXLc,761
132
+ pip/_internal/utils/glibc.py,sha256=GM1Y2hWkOf_tumySGFg-iNbc7oilBQQrjczb_705CF8,3170
133
+ pip/_internal/utils/hashes.py,sha256=o1qQEkqe2AqsRm_JhLoM4hkxmVtewH0ZZpQ6EBObHuU,5167
134
+ pip/_internal/utils/inject_securetransport.py,sha256=tGl9Bgyt2IHKtB3b0B-6r3W2yYF3Og-PBe0647S3lZs,810
135
+ pip/_internal/utils/logging.py,sha256=E5VE1n-pqgdd5DajPQPKpmu7VpJVd7dAhhdjPZNsYjE,12344
136
+ pip/_internal/utils/misc.py,sha256=WhWMKbtoBWvGrqVMaPekKML-orsLnD2e0N83arjpYQw,23644
137
+ pip/_internal/utils/models.py,sha256=qCgYyUw2mIH1pombsJ3YQsMtONZgyJ4BGwO5MJnSC4c,1329
138
+ pip/_internal/utils/packaging.py,sha256=I1938AB7FprcVJJd6C0vSiMuCVajmrxZF55vX5j0bMo,2900
139
+ pip/_internal/utils/parallel.py,sha256=RZF4JddPEWVbkkPCknfvpqaLfm3Pmqd_ABoCHmV4lXs,3224
140
+ pip/_internal/utils/pkg_resources.py,sha256=jwH5JViPe-JlXLvLC0-ASfTTCRYvm0u9CwQGcWjxStI,1106
141
+ pip/_internal/utils/setuptools_build.py,sha256=xk9sRBjUyNTHs_TvEWebVWs1GfLPN208MzpSXr9Ok_A,5047
142
+ pip/_internal/utils/subprocess.py,sha256=7QOQPJj6ezIVsypJJrcyyq4-mJM9qUsOdOLq0_wUiAA,10043
143
+ pip/_internal/utils/temp_dir.py,sha256=9gs3N9GQeVXRVWjJIalSpH1uj8yQXPTzarb5n1_HMVo,7950
144
+ pip/_internal/utils/unpacking.py,sha256=_qYZgmq8b0rRAN2swXsf9VfPogrjShlsTvhRI2heBYI,9050
145
+ pip/_internal/utils/urls.py,sha256=O5f4VeKJ9cWt_CKqqKmiDTW48uOzo0UNb1QWPQ0n2TI,1798
146
+ pip/_internal/utils/virtualenv.py,sha256=iRTK-sD6bWpHqXcZ0ECfdpFLWatMOHFUVCIRa0L6Gu0,3564
147
+ pip/_internal/utils/wheel.py,sha256=DOIVZaXN7bMOAeMEqzIOZHGl4OFO-KGrEqBUB848DPo,6290
148
+ pip/_internal/vcs/__init__.py,sha256=UAqvzpbi0VbZo3Ub6skEeZAw-ooIZR-zX_WpCbxyCoU,596
149
+ pip/_internal/vcs/bazaar.py,sha256=Ay_vN-87vYSEzBqXT3RVwl40vlk56j3jy_AfQbMj4uo,2962
150
+ pip/_internal/vcs/git.py,sha256=VDSzQlkh1390xw6PMh6fneJAZyc1s9qHZgum3wO3DOU,17347
151
+ pip/_internal/vcs/mercurial.py,sha256=WwoTWZQdQN9FcUTINvIeb0Vt46UJ_lLdf2BAdea9Tic,5076
152
+ pip/_internal/vcs/subversion.py,sha256=FRMYx7q-b6skWuv6IU7tJyC8Jm8PPblMnH7WN_ucXWU,11866
153
+ pip/_internal/vcs/versioncontrol.py,sha256=jMKitwE4bQ45jOKKomBxgBypm2TcuDGWWdTUmPa-MUQ,23276
154
+ pip/_internal/wheel_builder.py,sha256=hW63ZmABr65rOiSRBHXu1jBUdEZw5LZiw0LaQBbz0lI,11740
155
+ pip/_vendor/__init__.py,sha256=eE_yoHELq6Kw--WqhAEcKkvHLKbmTR1-JX_Th1wcNZc,4703
156
+ pip/_vendor/appdirs.py,sha256=M6IYRJtdZgmSPCXCSMBRB0VT3P8MdFbWCDbSLrB2Ebg,25907
157
+ pip/_vendor/cachecontrol/__init__.py,sha256=pJtAaUxOsMPnytI1A3juAJkXYDr8krdSnsg4Yg3OBEg,302
158
+ pip/_vendor/cachecontrol/_cmd.py,sha256=URGE0KrA87QekCG3SGPatlSPT571dZTDjNa-ZXX3pDc,1295
159
+ pip/_vendor/cachecontrol/adapter.py,sha256=sSwaSYd93IIfCFU4tOMgSo6b2LCt_gBSaQUj8ktJFOA,4882
160
+ pip/_vendor/cachecontrol/cache.py,sha256=1fc4wJP8HYt1ycnJXeEw5pCpeBL2Cqxx6g9Fb0AYDWQ,805
161
+ pip/_vendor/cachecontrol/caches/__init__.py,sha256=-gHNKYvaeD0kOk5M74eOrsSgIKUtC6i6GfbmugGweEo,86
162
+ pip/_vendor/cachecontrol/caches/file_cache.py,sha256=nYVKsJtXh6gJXvdn1iWyrhxvkwpQrK-eKoMRzuiwkKk,4153
163
+ pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=HxelMpNCo-dYr2fiJDwM3hhhRmxUYtB5tXm1GpAAT4Y,856
164
+ pip/_vendor/cachecontrol/compat.py,sha256=kHNvMRdt6s_Xwqq_9qJmr9ou3wYMOMUMxPPcwNxT8Mc,695
165
+ pip/_vendor/cachecontrol/controller.py,sha256=CWEX3pedIM9s60suf4zZPtm_JvVgnvogMGK_OiBG5F8,14149
166
+ pip/_vendor/cachecontrol/filewrapper.py,sha256=vACKO8Llzu_ZWyjV1Fxn1MA4TGU60N5N3GSrAFdAY2Q,2533
167
+ pip/_vendor/cachecontrol/heuristics.py,sha256=BFGHJ3yQcxvZizfo90LLZ04T_Z5XSCXvFotrp7Us0sc,4070
168
+ pip/_vendor/cachecontrol/serialize.py,sha256=vIa4jvq4x_KSOLdEIedoknX2aXYHQujLDFV4-F21Dno,7091
169
+ pip/_vendor/cachecontrol/wrapper.py,sha256=5LX0uJwkNQUtYSEw3aGmGu9WY8wGipd81mJ8lG0d0M4,690
170
+ pip/_vendor/certifi/__init__.py,sha256=-b78tXibbl0qtgCzv9tc9v6ozwcNX915lT9Tf4a9lds,62
171
+ pip/_vendor/certifi/__main__.py,sha256=1k3Cr95vCxxGRGDljrW3wMdpZdL3Nhf0u1n-k2qdsCY,255
172
+ pip/_vendor/certifi/cacert.pem,sha256=3i-hfE2K5o3CBKG2tYt6ehJWk2fP64o6Th83fHPoPp4,259465
173
+ pip/_vendor/certifi/core.py,sha256=gOFd0zHYlx4krrLEn982esOtmz3djiG0BFSDhgjlvcI,2840
174
+ pip/_vendor/chardet/__init__.py,sha256=mWZaWmvZkhwfBEAT9O1Y6nRTfKzhT7FHhQTTAujbqUA,3271
175
+ pip/_vendor/chardet/big5freq.py,sha256=D_zK5GyzoVsRes0HkLJziltFQX0bKCLOrFe9_xDvO_8,31254
176
+ pip/_vendor/chardet/big5prober.py,sha256=kBxHbdetBpPe7xrlb-e990iot64g_eGSLd32lB7_h3M,1757
177
+ pip/_vendor/chardet/chardistribution.py,sha256=3woWS62KrGooKyqz4zQSnjFbJpa6V7g02daAibTwcl8,9411
178
+ pip/_vendor/chardet/charsetgroupprober.py,sha256=GZLReHP6FRRn43hvSOoGCxYamErKzyp6RgOQxVeC3kg,3839
179
+ pip/_vendor/chardet/charsetprober.py,sha256=KSmwJErjypyj0bRZmC5F5eM7c8YQgLYIjZXintZNstg,5110
180
+ pip/_vendor/chardet/cli/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
181
+ pip/_vendor/chardet/cli/chardetect.py,sha256=XK5zqjUG2a4-y6eLHZ8ThYcp6WWUrdlmELxNypcc2SE,2747
182
+ pip/_vendor/chardet/codingstatemachine.py,sha256=VYp_6cyyki5sHgXDSZnXW4q1oelHc3cu9AyQTX7uug8,3590
183
+ pip/_vendor/chardet/compat.py,sha256=40zr6wICZwknxyuLGGcIOPyve8DTebBCbbvttvnmp5Q,1200
184
+ pip/_vendor/chardet/cp949prober.py,sha256=TZ434QX8zzBsnUvL_8wm4AQVTZ2ZkqEEQL_lNw9f9ow,1855
185
+ pip/_vendor/chardet/enums.py,sha256=Aimwdb9as1dJKZaFNUH2OhWIVBVd6ZkJJ_WK5sNY8cU,1661
186
+ pip/_vendor/chardet/escprober.py,sha256=kkyqVg1Yw3DIOAMJ2bdlyQgUFQhuHAW8dUGskToNWSc,3950
187
+ pip/_vendor/chardet/escsm.py,sha256=RuXlgNvTIDarndvllNCk5WZBIpdCxQ0kcd9EAuxUh84,10510
188
+ pip/_vendor/chardet/eucjpprober.py,sha256=iD8Jdp0ISRjgjiVN7f0e8xGeQJ5GM2oeZ1dA8nbSeUw,3749
189
+ pip/_vendor/chardet/euckrfreq.py,sha256=-7GdmvgWez4-eO4SuXpa7tBiDi5vRXQ8WvdFAzVaSfo,13546
190
+ pip/_vendor/chardet/euckrprober.py,sha256=MqFMTQXxW4HbzIpZ9lKDHB3GN8SP4yiHenTmf8g_PxY,1748
191
+ pip/_vendor/chardet/euctwfreq.py,sha256=No1WyduFOgB5VITUA7PLyC5oJRNzRyMbBxaKI1l16MA,31621
192
+ pip/_vendor/chardet/euctwprober.py,sha256=13p6EP4yRaxqnP4iHtxHOJ6R2zxHq1_m8hTRjzVZ95c,1747
193
+ pip/_vendor/chardet/gb2312freq.py,sha256=JX8lsweKLmnCwmk8UHEQsLgkr_rP_kEbvivC4qPOrlc,20715
194
+ pip/_vendor/chardet/gb2312prober.py,sha256=gGvIWi9WhDjE-xQXHvNIyrnLvEbMAYgyUSZ65HUfylw,1754
195
+ pip/_vendor/chardet/hebrewprober.py,sha256=c3SZ-K7hvyzGY6JRAZxJgwJ_sUS9k0WYkvMY00YBYFo,13838
196
+ pip/_vendor/chardet/jisfreq.py,sha256=vpmJv2Bu0J8gnMVRPHMFefTRvo_ha1mryLig8CBwgOg,25777
197
+ pip/_vendor/chardet/jpcntx.py,sha256=PYlNqRUQT8LM3cT5FmHGP0iiscFlTWED92MALvBungo,19643
198
+ pip/_vendor/chardet/langbulgarianmodel.py,sha256=rk9CJpuxO0bObboJcv6gNgWuosYZmd8qEEds5y7DS_Y,105697
199
+ pip/_vendor/chardet/langgreekmodel.py,sha256=S-uNQ1ihC75yhBvSux24gLFZv3QyctMwC6OxLJdX-bw,99571
200
+ pip/_vendor/chardet/langhebrewmodel.py,sha256=DzPP6TPGG_-PV7tqspu_d8duueqm7uN-5eQ0aHUw1Gg,98776
201
+ pip/_vendor/chardet/langhungarianmodel.py,sha256=RtJH7DZdsmaHqyK46Kkmnk5wQHiJwJPPJSqqIlpeZRc,102498
202
+ pip/_vendor/chardet/langrussianmodel.py,sha256=THqJOhSxiTQcHboDNSc5yofc2koXXQFHFyjtyuntUfM,131180
203
+ pip/_vendor/chardet/langthaimodel.py,sha256=R1wXHnUMtejpw0JnH_JO8XdYasME6wjVqp1zP7TKLgg,103312
204
+ pip/_vendor/chardet/langturkishmodel.py,sha256=rfwanTptTwSycE4-P-QasPmzd-XVYgevytzjlEzBBu8,95946
205
+ pip/_vendor/chardet/latin1prober.py,sha256=S2IoORhFk39FEFOlSFWtgVybRiP6h7BlLldHVclNkU8,5370
206
+ pip/_vendor/chardet/mbcharsetprober.py,sha256=AR95eFH9vuqSfvLQZN-L5ijea25NOBCoXqw8s5O9xLQ,3413
207
+ pip/_vendor/chardet/mbcsgroupprober.py,sha256=h6TRnnYq2OxG1WdD5JOyxcdVpn7dG0q-vB8nWr5mbh4,2012
208
+ pip/_vendor/chardet/mbcssm.py,sha256=SY32wVIF3HzcjY3BaEspy9metbNSKxIIB0RKPn7tjpI,25481
209
+ pip/_vendor/chardet/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
210
+ pip/_vendor/chardet/metadata/languages.py,sha256=41tLq3eLSrBEbEVVQpVGFq9K7o1ln9b1HpY1l0hCUQo,19474
211
+ pip/_vendor/chardet/sbcharsetprober.py,sha256=nmyMyuxzG87DN6K3Rk2MUzJLMLR69MrWpdnHzOwVUwQ,6136
212
+ pip/_vendor/chardet/sbcsgroupprober.py,sha256=hqefQuXmiFyDBArOjujH6hd6WFXlOD1kWCsxDhjx5Vc,4309
213
+ pip/_vendor/chardet/sjisprober.py,sha256=IIt-lZj0WJqK4rmUZzKZP4GJlE8KUEtFYVuY96ek5MQ,3774
214
+ pip/_vendor/chardet/universaldetector.py,sha256=DpZTXCX0nUHXxkQ9sr4GZxGB_hveZ6hWt3uM94cgWKs,12503
215
+ pip/_vendor/chardet/utf8prober.py,sha256=IdD8v3zWOsB8OLiyPi-y_fqwipRFxV9Nc1eKBLSuIEw,2766
216
+ pip/_vendor/chardet/version.py,sha256=A4CILFAd8MRVG1HoXPp45iK9RLlWyV73a1EtwE8Tvn8,242
217
+ pip/_vendor/colorama/__init__.py,sha256=pCdErryzLSzDW5P-rRPBlPLqbBtIRNJB6cMgoeJns5k,239
218
+ pip/_vendor/colorama/ansi.py,sha256=Top4EeEuaQdBWdteKMEcGOTeKeF19Q-Wo_6_Cj5kOzQ,2522
219
+ pip/_vendor/colorama/ansitowin32.py,sha256=yV7CEmCb19MjnJKODZEEvMH_fnbJhwnpzo4sxZuGXmA,10517
220
+ pip/_vendor/colorama/initialise.py,sha256=PprovDNxMTrvoNHFcL2NZjpH2XzDc8BLxLxiErfUl4k,1915
221
+ pip/_vendor/colorama/win32.py,sha256=bJ8Il9jwaBN5BJ8bmN6FoYZ1QYuMKv2j8fGrXh7TJjw,5404
222
+ pip/_vendor/colorama/winterm.py,sha256=2y_2b7Zsv34feAsP67mLOVc-Bgq51mdYGo571VprlrM,6438
223
+ pip/_vendor/distlib/__init__.py,sha256=bHNWOvZsLE4ES9S4FEA8CyP-rDYzatVgp9GHbpTnb2I,581
224
+ pip/_vendor/distlib/_backport/__init__.py,sha256=bqS_dTOH6uW9iGgd0uzfpPjo6vZ4xpPZ7kyfZJ2vNaw,274
225
+ pip/_vendor/distlib/_backport/misc.py,sha256=KWecINdbFNOxSOP1fGF680CJnaC6S4fBRgEtaYTw0ig,971
226
+ pip/_vendor/distlib/_backport/shutil.py,sha256=IX_G2NPqwecJibkIDje04bqu0xpHkfSQ2GaGdEVqM5Y,25707
227
+ pip/_vendor/distlib/_backport/sysconfig.cfg,sha256=swZKxq9RY5e9r3PXCrlvQPMsvOdiWZBTHLEbqS8LJLU,2617
228
+ pip/_vendor/distlib/_backport/sysconfig.py,sha256=BQHFlb6pubCl_dvT1NjtzIthylofjKisox239stDg0U,26854
229
+ pip/_vendor/distlib/_backport/tarfile.py,sha256=Ihp7rXRcjbIKw8COm9wSePV9ARGXbSF9gGXAMn2Q-KU,92628
230
+ pip/_vendor/distlib/compat.py,sha256=ADA56xiAxar3mU6qemlBhNbsrFPosXRhO44RzsbJPqk,41408
231
+ pip/_vendor/distlib/database.py,sha256=Kl0YvPQKc4OcpVi7k5cFziydM1xOK8iqdxLGXgbZHV4,51059
232
+ pip/_vendor/distlib/index.py,sha256=UfcimNW19AB7IKWam4VaJbXuCBvArKfSxhV16EwavzE,20739
233
+ pip/_vendor/distlib/locators.py,sha256=AKlB3oZvfOTg4E0CtfwOzujFL19X5V4XUA4eHdKOu44,51965
234
+ pip/_vendor/distlib/manifest.py,sha256=nQEhYmgoreaBZzyFzwYsXxJARu3fo4EkunU163U16iE,14811
235
+ pip/_vendor/distlib/markers.py,sha256=OunMSH1SIbvLLt4z2VEERCll4WNlz2tDrg1mSXCNUj4,4344
236
+ pip/_vendor/distlib/metadata.py,sha256=vatoxFdmBr6ie-sTVXVNPOPG3uwMDWJTnEECnm7xDCw,39109
237
+ pip/_vendor/distlib/resources.py,sha256=LwbPksc0A1JMbi6XnuPdMBUn83X7BPuFNWqPGEKI698,10820
238
+ pip/_vendor/distlib/scripts.py,sha256=YD5_kioPD-qybYwQ4Gxyu-FR4ffxczy2gdBuU4II9qA,17248
239
+ pip/_vendor/distlib/t32.exe,sha256=NS3xBCVAld35JVFNmb-1QRyVtThukMrwZVeXn4LhaEQ,96768
240
+ pip/_vendor/distlib/t64.exe,sha256=oAqHes78rUWVM0OtVqIhUvequl_PKhAhXYQWnUf7zR0,105984
241
+ pip/_vendor/distlib/util.py,sha256=eIKKJ5Mp4unHMOVzixRIRxGq4ty5-h_PoFmZ_lpvkkM,67558
242
+ pip/_vendor/distlib/version.py,sha256=_geOv-cHoV-G8dQzKI8g6z8F0XeFeUqdJ_1G1K6iyrQ,23508
243
+ pip/_vendor/distlib/w32.exe,sha256=lJtnZdeUxTZWya_EW5DZos_K5rswRECGspIl8ZJCIXs,90112
244
+ pip/_vendor/distlib/w64.exe,sha256=0aRzoN2BO9NWW4ENy4_4vHkHR4qZTFZNVSAJJYlODTI,99840
245
+ pip/_vendor/distlib/wheel.py,sha256=W6aQQo2Si0CzWiCaqlS-Nu8CoHnDbmcGMqRxCHJmg_Q,43062
246
+ pip/_vendor/distro.py,sha256=xxMIh2a3KmippeWEHzynTdHT3_jZM0o-pos0dAWJROM,43628
247
+ pip/_vendor/html5lib/__init__.py,sha256=BYzcKCqeEii52xDrqBFruhnmtmkiuHXFyFh-cglQ8mk,1160
248
+ pip/_vendor/html5lib/_ihatexml.py,sha256=ifOwF7pXqmyThIXc3boWc96s4MDezqRrRVp7FwDYUFs,16728
249
+ pip/_vendor/html5lib/_inputstream.py,sha256=jErNASMlkgs7MpOM9Ve_VdLDJyFFweAjLuhVutZz33U,32353
250
+ pip/_vendor/html5lib/_tokenizer.py,sha256=04mgA2sNTniutl2fxFv-ei5bns4iRaPxVXXHh_HrV_4,77040
251
+ pip/_vendor/html5lib/_trie/__init__.py,sha256=nqfgO910329BEVJ5T4psVwQtjd2iJyEXQ2-X8c1YxwU,109
252
+ pip/_vendor/html5lib/_trie/_base.py,sha256=CaybYyMro8uERQYjby2tTeSUatnWDfWroUN9N7ety5w,1013
253
+ pip/_vendor/html5lib/_trie/py.py,sha256=wXmQLrZRf4MyWNyg0m3h81m9InhLR7GJ002mIIZh-8o,1775
254
+ pip/_vendor/html5lib/_utils.py,sha256=Dx9AKntksRjFT1veBj7I362pf5OgIaT0zglwq43RnfU,4931
255
+ pip/_vendor/html5lib/constants.py,sha256=Ll-yzLU_jcjyAI_h57zkqZ7aQWE5t5xA4y_jQgoUUhw,83464
256
+ pip/_vendor/html5lib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
257
+ pip/_vendor/html5lib/filters/alphabeticalattributes.py,sha256=lViZc2JMCclXi_5gduvmdzrRxtO5Xo9ONnbHBVCsykU,919
258
+ pip/_vendor/html5lib/filters/base.py,sha256=z-IU9ZAYjpsVsqmVt7kuWC63jR11hDMr6CVrvuao8W0,286
259
+ pip/_vendor/html5lib/filters/inject_meta_charset.py,sha256=egDXUEHXmAG9504xz0K6ALDgYkvUrC2q15YUVeNlVQg,2945
260
+ pip/_vendor/html5lib/filters/lint.py,sha256=jk6q56xY0ojiYfvpdP-OZSm9eTqcAdRqhCoPItemPYA,3643
261
+ pip/_vendor/html5lib/filters/optionaltags.py,sha256=8lWT75J0aBOHmPgfmqTHSfPpPMp01T84NKu0CRedxcE,10588
262
+ pip/_vendor/html5lib/filters/sanitizer.py,sha256=m6oGmkBhkGAnn2nV6D4hE78SCZ6WEnK9rKdZB3uXBIc,26897
263
+ pip/_vendor/html5lib/filters/whitespace.py,sha256=8eWqZxd4UC4zlFGW6iyY6f-2uuT8pOCSALc3IZt7_t4,1214
264
+ pip/_vendor/html5lib/html5parser.py,sha256=anr-aXre_ImfrkQ35c_rftKXxC80vJCREKe06Tq15HA,117186
265
+ pip/_vendor/html5lib/serializer.py,sha256=_PpvcZF07cwE7xr9uKkZqh5f4UEaI8ltCU2xPJzaTpk,15759
266
+ pip/_vendor/html5lib/treeadapters/__init__.py,sha256=A0rY5gXIe4bJOiSGRO_j_tFhngRBO8QZPzPtPw5dFzo,679
267
+ pip/_vendor/html5lib/treeadapters/genshi.py,sha256=CH27pAsDKmu4ZGkAUrwty7u0KauGLCZRLPMzaO3M5vo,1715
268
+ pip/_vendor/html5lib/treeadapters/sax.py,sha256=BKS8woQTnKiqeffHsxChUqL4q2ZR_wb5fc9MJ3zQC8s,1776
269
+ pip/_vendor/html5lib/treebuilders/__init__.py,sha256=AysSJyvPfikCMMsTVvaxwkgDieELD5dfR8FJIAuq7hY,3592
270
+ pip/_vendor/html5lib/treebuilders/base.py,sha256=z-o51vt9r_l2IDG5IioTOKGzZne4Fy3_Fc-7ztrOh4I,14565
271
+ pip/_vendor/html5lib/treebuilders/dom.py,sha256=22whb0C71zXIsai5mamg6qzBEiigcBIvaDy4Asw3at0,8925
272
+ pip/_vendor/html5lib/treebuilders/etree.py,sha256=w5ZFpKk6bAxnrwD2_BrF5EVC7vzz0L3LMi9Sxrbc_8w,12836
273
+ pip/_vendor/html5lib/treebuilders/etree_lxml.py,sha256=9gqDjs-IxsPhBYa5cpvv2FZ1KZlG83Giusy2lFmvIkE,14766
274
+ pip/_vendor/html5lib/treewalkers/__init__.py,sha256=OBPtc1TU5mGyy18QDMxKEyYEz0wxFUUNj5v0-XgmYhY,5719
275
+ pip/_vendor/html5lib/treewalkers/base.py,sha256=ouiOsuSzvI0KgzdWP8PlxIaSNs9falhbiinAEc_UIJY,7476
276
+ pip/_vendor/html5lib/treewalkers/dom.py,sha256=EHyFR8D8lYNnyDU9lx_IKigVJRyecUGua0mOi7HBukc,1413
277
+ pip/_vendor/html5lib/treewalkers/etree.py,sha256=xo1L5m9VtkfpFJK0pFmkLVajhqYYVisVZn3k9kYpPkI,4551
278
+ pip/_vendor/html5lib/treewalkers/etree_lxml.py,sha256=_b0LAVWLcVu9WaU_-w3D8f0IRSpCbjf667V-3NRdhTw,6357
279
+ pip/_vendor/html5lib/treewalkers/genshi.py,sha256=4D2PECZ5n3ZN3qu3jMl9yY7B81jnQApBQSVlfaIuYbA,2309
280
+ pip/_vendor/idna/__init__.py,sha256=KJQN1eQBr8iIK5SKrJ47lXvxG0BJ7Lm38W4zT0v_8lk,849
281
+ pip/_vendor/idna/codec.py,sha256=QsPFD3Je8gN17rfs14e7zTGRWlnL7bNf2ZqcHTRVYHs,3453
282
+ pip/_vendor/idna/compat.py,sha256=5A9xR04puRHCsyjBNewZlVSiarth7K1bZqyEOeob1fA,360
283
+ pip/_vendor/idna/core.py,sha256=icq2P13S6JMjoXgKhhd6ihhby7QsnZlNfniH6fLyf6U,12826
284
+ pip/_vendor/idna/idnadata.py,sha256=cl4x9RLdw1ZMtEEbvKwAsX-Id3AdIjO5U3HaoKM6VGs,42350
285
+ pip/_vendor/idna/intranges.py,sha256=EqgXwyATAn-CTACInqH9tYsYAitGB2VcQ50RZt_Cpjs,1933
286
+ pip/_vendor/idna/package_data.py,sha256=_028B4fvadRIaXMwMYjhuQPP3AxTIt1IRE7X6RDR4Mk,21
287
+ pip/_vendor/idna/uts46data.py,sha256=DGzwDQv8JijY17I_7ondo3stjFjNnjvVAbA-z0k1XOE,201849
288
+ pip/_vendor/msgpack/__init__.py,sha256=2gJwcsTIaAtCM0GMi2rU-_Y6kILeeQuqRkrQ22jSANc,1118
289
+ pip/_vendor/msgpack/_version.py,sha256=dFR03oACnj4lsKd1RnwD7BPMiVI_FMygdOL1TOBEw_U,20
290
+ pip/_vendor/msgpack/exceptions.py,sha256=dCTWei8dpkrMsQDcjQk74ATl9HsIBH0ybt8zOPNqMYc,1081
291
+ pip/_vendor/msgpack/ext.py,sha256=4l356Y4sVEcvCla2dh_cL57vh4GMhZfa3kuWHFHYz6A,6088
292
+ pip/_vendor/msgpack/fallback.py,sha256=Rpv1Ldey8f8ueRnQznD4ARKBn9dxM2PywVNkXI8IEeE,38026
293
+ pip/_vendor/packaging/__about__.py,sha256=p_OQloqH2saadcbUQmWEsWK857dI6_ff5E3aSiCqGFA,661
294
+ pip/_vendor/packaging/__init__.py,sha256=b9Kk5MF7KxhhLgcDmiUWukN-LatWFxPdNug0joPhHSk,497
295
+ pip/_vendor/packaging/_manylinux.py,sha256=XcbiXB-qcjv3bcohp6N98TMpOP4_j3m-iOA8ptK2GWY,11488
296
+ pip/_vendor/packaging/_musllinux.py,sha256=z5yeG1ygOPx4uUyLdqj-p8Dk5UBb5H_b0NIjW9yo8oA,4378
297
+ pip/_vendor/packaging/_structures.py,sha256=TMiAgFbdUOPmIfDIfiHc3KFhSJ8kMjof2QS5I-2NyQ8,1629
298
+ pip/_vendor/packaging/markers.py,sha256=AJBOcY8Oq0kYc570KuuPTkvuqjAlhufaE2c9sCUbm64,8487
299
+ pip/_vendor/packaging/requirements.py,sha256=NtDlPBtojpn1IUC85iMjPNsUmufjpSlwnNA-Xb4m5NA,4676
300
+ pip/_vendor/packaging/specifiers.py,sha256=MZ-fYcNL3u7pNrt-6g2EQO7AbRXkjc-SPEYwXMQbLmc,30964
301
+ pip/_vendor/packaging/tags.py,sha256=akIerYw8W0sz4OW9HHozgawWnbt2GGOPm3sviW0jowY,15714
302
+ pip/_vendor/packaging/utils.py,sha256=dJjeat3BS-TYn1RrUFVwufUMasbtzLfYRoy_HXENeFQ,4200
303
+ pip/_vendor/packaging/version.py,sha256=_fLRNrFrxYcHVfyo8vk9j8s6JM8N_xsSxVFr6RJyco8,14665
304
+ pip/_vendor/pep517/__init__.py,sha256=qDgVbDWpBYpTvtxA2tilifXlxwzOzRqIodLZdbyahyQ,130
305
+ pip/_vendor/pep517/build.py,sha256=MqN_W6o5a9oauTC0u6W5cILGFjf9x2BV9BdMLeY60hc,3469
306
+ pip/_vendor/pep517/check.py,sha256=AYG2yvpzmtsL810c75Z5-nhaXa7SxgK8APyw-_x53Ok,6096
307
+ pip/_vendor/pep517/colorlog.py,sha256=Tk9AuYm_cLF3BKTBoSTJt9bRryn0aFojIQOwbfVUTxQ,4098
308
+ pip/_vendor/pep517/compat.py,sha256=fw2Py6lqLwJLfp6MKmXvt1m4sbbgoU1D-_gcScvz8OU,1071
309
+ pip/_vendor/pep517/dirtools.py,sha256=2mkAkAL0mRz_elYFjRKuekTJVipH1zTn4tbf1EDev84,1129
310
+ pip/_vendor/pep517/envbuild.py,sha256=LcST0MASmcQNLOFqDPxDoS1kjkglx8F6eEhoBJ-DWkg,6112
311
+ pip/_vendor/pep517/in_process/__init__.py,sha256=MyWoAi8JHdcBv7yXuWpUSVADbx6LSB9rZh7kTIgdA8Y,563
312
+ pip/_vendor/pep517/in_process/_in_process.py,sha256=YJJf-qaL7BBVdgCHuMhTpx-LtwG1EIGVfly4rtusdiI,10833
313
+ pip/_vendor/pep517/meta.py,sha256=8mnM5lDnT4zXQpBTliJbRGfesH7iioHwozbDxALPS9Y,2463
314
+ pip/_vendor/pep517/wrappers.py,sha256=qCWfEUnbE5387PyQl7cT8xv4dDca4uNgro_0bnAO4Rk,13258
315
+ pip/_vendor/pkg_resources/__init__.py,sha256=XpGBfvS9fafA6bm5rx7vnxdxs7yqyoc_NnpzKApkJ64,108277
316
+ pip/_vendor/pkg_resources/py31compat.py,sha256=CRk8fkiPRDLsbi5pZcKsHI__Pbmh_94L8mr9Qy9Ab2U,562
317
+ pip/_vendor/progress/__init__.py,sha256=fcbQQXo5np2CoQyhSH5XprkicwLZNLePR3uIahznSO0,4857
318
+ pip/_vendor/progress/bar.py,sha256=QuDuVNcmXgpxtNtxO0Fq72xKigxABaVmxYGBw4J3Z_E,2854
319
+ pip/_vendor/progress/counter.py,sha256=MznyBrvPWrOlGe4MZAlGUb9q3aODe6_aNYeAE_VNoYA,1372
320
+ pip/_vendor/progress/spinner.py,sha256=k8JbDW94T0-WXuXfxZIFhdoNPYp3jfnpXqBnfRv5fGs,1380
321
+ pip/_vendor/pyparsing.py,sha256=J1b4z3S_KwyJW7hKGnoN-hXW9pgMIzIP6QThyY5yJq4,273394
322
+ pip/_vendor/requests/__init__.py,sha256=g4Bh1QYh6JKjMS4YLobx0uOLq-41sINaXjvbhX2VI8g,5113
323
+ pip/_vendor/requests/__version__.py,sha256=PZEyPTSIN_jRIAIB51wV7pw81m3qAw0InSR7OrKZUnE,441
324
+ pip/_vendor/requests/_internal_utils.py,sha256=Zx3PnEUccyfsB-ie11nZVAW8qClJy0gx1qNME7rgT18,1096
325
+ pip/_vendor/requests/adapters.py,sha256=e-bmKEApNVqFdylxuMJJfiaHdlmS_zhWhIMEzlHvGuc,21548
326
+ pip/_vendor/requests/api.py,sha256=hjuoP79IAEmX6Dysrw8t032cLfwLHxbI_wM4gC5G9t0,6402
327
+ pip/_vendor/requests/auth.py,sha256=OMoJIVKyRLy9THr91y8rxysZuclwPB-K1Xg1zBomUhQ,10207
328
+ pip/_vendor/requests/certs.py,sha256=nXRVq9DtGmv_1AYbwjTu9UrgAcdJv05ZvkNeaoLOZxY,465
329
+ pip/_vendor/requests/compat.py,sha256=LQWuCR4qXk6w7-qQopXyz0WNHUdAD40k0mKnaAEf1-g,2045
330
+ pip/_vendor/requests/cookies.py,sha256=Y-bKX6TvW3FnYlE6Au0SXtVVWcaNdFvuAwQxw-G0iTI,18430
331
+ pip/_vendor/requests/exceptions.py,sha256=dwIi512RCDqXJ2T81nLC88mqPNhUFnOI_CgKKDXhTO8,3250
332
+ pip/_vendor/requests/help.py,sha256=dyhe3lcmHXnFCzDiZVjcGmVvvO_jtsfAm-AC542ndw8,3972
333
+ pip/_vendor/requests/hooks.py,sha256=QReGyy0bRcr5rkwCuObNakbYsc7EkiKeBwG4qHekr2Q,757
334
+ pip/_vendor/requests/models.py,sha256=9_LS_t1t6HbbaWFE3ZkxGmmHN2V8BgxziiOU84rrQ50,34924
335
+ pip/_vendor/requests/packages.py,sha256=njJmVifY4aSctuW3PP5EFRCxjEwMRDO6J_feG2dKWsI,695
336
+ pip/_vendor/requests/sessions.py,sha256=57O4ud9yRL6eLYh-dtFbqC1kO4d_EwZcCgYXEkujlfs,30168
337
+ pip/_vendor/requests/status_codes.py,sha256=gT79Pbs_cQjBgp-fvrUgg1dn2DQO32bDj4TInjnMPSc,4188
338
+ pip/_vendor/requests/structures.py,sha256=msAtr9mq1JxHd-JRyiILfdFlpbJwvvFuP3rfUQT_QxE,3005
339
+ pip/_vendor/requests/utils.py,sha256=U_-i6WxLw-67KEij43xHbcvL0DdeQ5Jbd4hfifWJzQY,31394
340
+ pip/_vendor/resolvelib/__init__.py,sha256=uoW0dgWCDwApX59mRffoPISkZGGk_UZ1It_PY4o_PaE,537
341
+ pip/_vendor/resolvelib/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
342
+ pip/_vendor/resolvelib/compat/collections_abc.py,sha256=uy8xUZ-NDEw916tugUXm8HgwCGiMO0f-RcdnpkfXfOs,156
343
+ pip/_vendor/resolvelib/providers.py,sha256=bfzFDZd7UqkkAS7lUM_HeYbA-HzjKfDlle_pn_79vio,5638
344
+ pip/_vendor/resolvelib/reporters.py,sha256=hQvvXuuEBOyEWO8KDfLsWKVjX55UFMAUwO0YZMNpzAw,1364
345
+ pip/_vendor/resolvelib/resolvers.py,sha256=wT83PHiBWRCklL-nLJ1-8sk2B3yBI06Rse1H11crOsI,17225
346
+ pip/_vendor/resolvelib/structs.py,sha256=IVIYof6sA_N4ZEiE1C1UhzTX495brCNnyCdgq6CYq28,4794
347
+ pip/_vendor/six.py,sha256=TOOfQi7nFGfMrIvtdr6wX4wyHH8M7aknmuLfo2cBBrM,34549
348
+ pip/_vendor/tenacity/__init__.py,sha256=GLLsTFD4Bd5VDgTR6mU_FxyOsrxc48qONorVaRebeD4,18257
349
+ pip/_vendor/tenacity/_asyncio.py,sha256=HEb0BVJEeBJE9P-m9XBxh1KcaF96BwoeqkJCL5sbVcQ,3314
350
+ pip/_vendor/tenacity/_utils.py,sha256=-y68scDcyoqvTJuJJ0GTfjdSCljEYlbCYvgk7nM4NdM,1944
351
+ pip/_vendor/tenacity/after.py,sha256=dlmyxxFy2uqpLXDr838DiEd7jgv2AGthsWHGYcGYsaI,1496
352
+ pip/_vendor/tenacity/before.py,sha256=7XtvRmO0dRWUp8SVn24OvIiGFj8-4OP5muQRUiWgLh0,1376
353
+ pip/_vendor/tenacity/before_sleep.py,sha256=ThyDvqKU5yle_IvYQz_b6Tp6UjUS0PhVp6zgqYl9U6Y,1908
354
+ pip/_vendor/tenacity/nap.py,sha256=fRWvnz1aIzbIq9Ap3gAkAZgDH6oo5zxMrU6ZOVByq0I,1383
355
+ pip/_vendor/tenacity/retry.py,sha256=62R71W59bQjuNyFKsDM7hE2aEkEPtwNBRA0tnsEvgSk,6645
356
+ pip/_vendor/tenacity/stop.py,sha256=sKHmHaoSaW6sKu3dTxUVKr1-stVkY7lw4Y9yjZU30zQ,2790
357
+ pip/_vendor/tenacity/tornadoweb.py,sha256=E8lWO2nwe6dJgoB-N2HhQprYLDLB_UdSgFnv-EN6wKE,2145
358
+ pip/_vendor/tenacity/wait.py,sha256=e_Saa6I2tsNLpCL1t9897wN2fGb0XQMQlE4bU2t9V2w,6691
359
+ pip/_vendor/tomli/__init__.py,sha256=z1Elt0nLAqU5Y0DOn9p__8QnLWavlEOpRyQikdYgKro,230
360
+ pip/_vendor/tomli/_parser.py,sha256=50BD4o9YbzFAGAYyZLqZC8F81DQ7iWWyJnrHNwBKa6A,22415
361
+ pip/_vendor/tomli/_re.py,sha256=5GPfgXKteg7wRFCF-DzlkAPI2ilHbkMK2-JC49F-AJQ,2681
362
+ pip/_vendor/urllib3/__init__.py,sha256=j3yzHIbmW7CS-IKQJ9-PPQf_YKO8EOAey_rMW0UR7us,2763
363
+ pip/_vendor/urllib3/_collections.py,sha256=Rp1mVyBgc_UlAcp6M3at1skJBXR5J43NawRTvW2g_XY,10811
364
+ pip/_vendor/urllib3/_version.py,sha256=6fJAIPnJkT0m9wzVjHrFcq5wYt65dStDpaRcjj5ugoo,63
365
+ pip/_vendor/urllib3/connection.py,sha256=kAlubwsW33FUSUroPSVHMF_Zzv-uzX_BwUFMXX9Pt8c,18754
366
+ pip/_vendor/urllib3/connectionpool.py,sha256=jXNmm4y3LJWYgteNeGcYJx8-0k7bzKRU__AVTXzaIak,37131
367
+ pip/_vendor/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
368
+ pip/_vendor/urllib3/contrib/_appengine_environ.py,sha256=bDbyOEhW2CKLJcQqAKAyrEHN-aklsyHFKq6vF8ZFsmk,957
369
+ pip/_vendor/urllib3/contrib/_securetransport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
370
+ pip/_vendor/urllib3/contrib/_securetransport/bindings.py,sha256=eRy1Mj-wpg7sR6-OSvnSV4jUbjMT464dLN_CWxbIRVw,17649
371
+ pip/_vendor/urllib3/contrib/_securetransport/low_level.py,sha256=lgIdsSycqfB0Xm5BiJzXGeIKT7ybCQMFPJAgkcwPa1s,13908
372
+ pip/_vendor/urllib3/contrib/appengine.py,sha256=lfzpHFmJiO82shClLEm3QB62SYgHWnjpZOH_2JhU5Tc,11034
373
+ pip/_vendor/urllib3/contrib/ntlmpool.py,sha256=ej9gGvfAb2Gt00lafFp45SIoRz-QwrQ4WChm6gQmAlM,4538
374
+ pip/_vendor/urllib3/contrib/pyopenssl.py,sha256=lYIxGFWTosqbfLnkZXOBg7igY71iRvM3NUOaD0stUQ8,16891
375
+ pip/_vendor/urllib3/contrib/securetransport.py,sha256=TN5q9dKZ0Sd5_vW9baRzEAEItdJ-4VlHWmAUrlcJNfo,34434
376
+ pip/_vendor/urllib3/contrib/socks.py,sha256=aRi9eWXo9ZEb95XUxef4Z21CFlnnjbEiAo9HOseoMt4,7097
377
+ pip/_vendor/urllib3/exceptions.py,sha256=0Mnno3KHTNfXRfY7638NufOPkUb6mXOm-Lqj-4x2w8A,8217
378
+ pip/_vendor/urllib3/fields.py,sha256=kvLDCg_JmH1lLjUUEY_FLS8UhY7hBvDPuVETbY8mdrM,8579
379
+ pip/_vendor/urllib3/filepost.py,sha256=5b_qqgRHVlL7uLtdAYBzBh-GHmU5AfJVt_2N0XS3PeY,2440
380
+ pip/_vendor/urllib3/packages/__init__.py,sha256=h4BLhD4tLaBx1adaDtKXfupsgqY0wWLXb_f1_yVlV6A,108
381
+ pip/_vendor/urllib3/packages/backports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
382
+ pip/_vendor/urllib3/packages/backports/makefile.py,sha256=nbzt3i0agPVP07jqqgjhaYjMmuAi_W5E0EywZivVO8E,1417
383
+ pip/_vendor/urllib3/packages/six.py,sha256=1LVW7ljqRirFlfExjwl-v1B7vSAUNTmzGMs-qays2zg,34666
384
+ pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py,sha256=ZVMwCkHx-py8ERsxxM3Il-MiREZktV-8iLBmCfRRHI4,927
385
+ pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py,sha256=6dZ-q074g7XhsJ27MFCgkct8iVNZB3sMZvKhf-KUVy0,5679
386
+ pip/_vendor/urllib3/poolmanager.py,sha256=whzlX6UTEgODMOCy0ZDMUONRBCz5wyIM8Z9opXAY-Lk,19763
387
+ pip/_vendor/urllib3/request.py,sha256=ZFSIqX0C6WizixecChZ3_okyu7BEv0lZu1VT0s6h4SM,5985
388
+ pip/_vendor/urllib3/response.py,sha256=hGhGBh7TkEkh_IQg5C1W_xuPNrgIKv5BUXPyE-q0LuE,28203
389
+ pip/_vendor/urllib3/util/__init__.py,sha256=JEmSmmqqLyaw8P51gUImZh8Gwg9i1zSe-DoqAitn2nc,1155
390
+ pip/_vendor/urllib3/util/connection.py,sha256=KykjNIXzUZEzeKEOpl5xvKs6IsESXP9o9eTrjE0W_Ys,4920
391
+ pip/_vendor/urllib3/util/proxy.py,sha256=FGipAEnvZteyldXNjce4DEB7YzwU-a5lep8y5S0qHQg,1604
392
+ pip/_vendor/urllib3/util/queue.py,sha256=nRgX8_eX-_VkvxoX096QWoz8Ps0QHUAExILCY_7PncM,498
393
+ pip/_vendor/urllib3/util/request.py,sha256=NnzaEKQ1Pauw5MFMV6HmgEMHITf0Aua9fQuzi2uZzGc,4123
394
+ pip/_vendor/urllib3/util/response.py,sha256=GJpg3Egi9qaJXRwBh5wv-MNuRWan5BIu40oReoxWP28,3510
395
+ pip/_vendor/urllib3/util/retry.py,sha256=tOWfZpLsuc7Vbk5nWpMwkHdMoXCp90IAvH4xtjSDRqQ,21391
396
+ pip/_vendor/urllib3/util/ssl_.py,sha256=X4-AqW91aYPhPx6-xbf66yHFQKbqqfC_5Zt4WkLX1Hc,17177
397
+ pip/_vendor/urllib3/util/ssltransport.py,sha256=F_UncOXGcc-MgeWFTA1H4QCt_RRNQXRbF6onje3SyHY,6931
398
+ pip/_vendor/urllib3/util/timeout.py,sha256=QSbBUNOB9yh6AnDn61SrLQ0hg5oz0I9-uXEG91AJuIg,10003
399
+ pip/_vendor/urllib3/util/url.py,sha256=QVEzcbHipbXyCWwH6R4K4TR-N8T4LM55WEMwNUTBmLE,14047
400
+ pip/_vendor/urllib3/util/wait.py,sha256=3MUKRSAUJDB2tgco7qRUskW0zXGAWYvRRE4Q1_6xlLs,5404
401
+ pip/_vendor/vendor.txt,sha256=GuFhR0DHZazrSYZyoY7j3X3T_mGJh-ky2opcZ-A7ezo,364
402
+ pip/_vendor/webencodings/__init__.py,sha256=qOBJIuPy_4ByYH6W_bNgJF-qYQ2DoU-dKsDu5yRWCXg,10579
403
+ pip/_vendor/webencodings/labels.py,sha256=4AO_KxTddqGtrL9ns7kAPjb0CcN6xsCIxbK37HY9r3E,8979
404
+ pip/_vendor/webencodings/mklabels.py,sha256=GYIeywnpaLnP0GSic8LFWgd0UVvO_l1Nc6YoF-87R_4,1305
405
+ pip/_vendor/webencodings/tests.py,sha256=OtGLyjhNY1fvkW1GvLJ_FV9ZoqC9Anyjr7q3kxTbzNs,6563
406
+ pip/_vendor/webencodings/x_user_defined.py,sha256=yOqWSdmpytGfUgh_Z6JYgDNhoc-BAHyyeeT15Fr42tM,4307
407
+ pip/py.typed,sha256=EBVvvPRTn_eIpz5e5QztSCdrMX7Qwd7VP93RSoIlZ2I,286
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/REQUESTED ADDED
File without changes
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/WHEEL ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.36.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/entry_points.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ [console_scripts]
2
+ pip = pip._internal.cli.main:main
3
+ pip3 = pip._internal.cli.main:main
4
+ pip3.9 = pip._internal.cli.main:main
5
+
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip-21.2.4.dist-info/top_level.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ pip
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/pkg_resources/__init__.py ADDED
The diff for this file is too large to render. See raw diff
 
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/pkg_resources/py31compat.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import errno
3
+ import sys
4
+
5
+ from pip._vendor import six
6
+
7
+
8
+ def _makedirs_31(path, exist_ok=False):
9
+ try:
10
+ os.makedirs(path)
11
+ except OSError as exc:
12
+ if not exist_ok or exc.errno != errno.EEXIST:
13
+ raise
14
+
15
+
16
+ # rely on compatibility behavior until mode considerations
17
+ # and exists_ok considerations are disentangled.
18
+ # See https://github.com/pypa/setuptools/pull/1083#issuecomment-315168663
19
+ needs_makedirs = (
20
+ six.PY2 or
21
+ (3, 4) <= sys.version_info < (3, 4, 1)
22
+ )
23
+ makedirs = _makedirs_31 if needs_makedirs else os.makedirs
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __all__ = [
2
+ "__version__",
3
+ "AbstractProvider",
4
+ "AbstractResolver",
5
+ "BaseReporter",
6
+ "InconsistentCandidate",
7
+ "Resolver",
8
+ "RequirementsConflicted",
9
+ "ResolutionError",
10
+ "ResolutionImpossible",
11
+ "ResolutionTooDeep",
12
+ ]
13
+
14
+ __version__ = "0.7.1"
15
+
16
+
17
+ from .providers import AbstractProvider, AbstractResolver
18
+ from .reporters import BaseReporter
19
+ from .resolvers import (
20
+ InconsistentCandidate,
21
+ RequirementsConflicted,
22
+ Resolver,
23
+ ResolutionError,
24
+ ResolutionImpossible,
25
+ ResolutionTooDeep,
26
+ )
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/compat/__init__.py ADDED
File without changes
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ __all__ = ["Mapping", "Sequence"]
2
+
3
+ try:
4
+ from collections.abc import Mapping, Sequence
5
+ except ImportError:
6
+ from collections import Mapping, Sequence
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/providers.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class AbstractProvider(object):
2
+ """Delegate class to provide requirement interface for the resolver."""
3
+
4
+ def identify(self, requirement_or_candidate):
5
+ """Given a requirement, return an identifier for it.
6
+
7
+ This is used to identify a requirement, e.g. whether two requirements
8
+ should have their specifier parts merged.
9
+ """
10
+ raise NotImplementedError
11
+
12
+ def get_preference(self, identifier, resolutions, candidates, information):
13
+ """Produce a sort key for given requirement based on preference.
14
+
15
+ The preference is defined as "I think this requirement should be
16
+ resolved first". The lower the return value is, the more preferred
17
+ this group of arguments is.
18
+
19
+ :param identifier: An identifier as returned by ``identify()``. This
20
+ identifies the dependency matches of which should be returned.
21
+ :param resolutions: Mapping of candidates currently pinned by the
22
+ resolver. Each key is an identifier, and the value a candidate.
23
+ The candidate may conflict with requirements from ``information``.
24
+ :param candidates: Mapping of each dependency's possible candidates.
25
+ Each value is an iterator of candidates.
26
+ :param information: Mapping of requirement information of each package.
27
+ Each value is an iterator of *requirement information*.
28
+
29
+ A *requirement information* instance is a named tuple with two members:
30
+
31
+ * ``requirement`` specifies a requirement contributing to the current
32
+ list of candidates.
33
+ * ``parent`` specifies the candidate that provides (dependend on) the
34
+ requirement, or ``None`` to indicate a root requirement.
35
+
36
+ The preference could depend on a various of issues, including (not
37
+ necessarily in this order):
38
+
39
+ * Is this package pinned in the current resolution result?
40
+ * How relaxed is the requirement? Stricter ones should probably be
41
+ worked on first? (I don't know, actually.)
42
+ * How many possibilities are there to satisfy this requirement? Those
43
+ with few left should likely be worked on first, I guess?
44
+ * Are there any known conflicts for this requirement? We should
45
+ probably work on those with the most known conflicts.
46
+
47
+ A sortable value should be returned (this will be used as the ``key``
48
+ parameter of the built-in sorting function). The smaller the value is,
49
+ the more preferred this requirement is (i.e. the sorting function
50
+ is called with ``reverse=False``).
51
+ """
52
+ raise NotImplementedError
53
+
54
+ def find_matches(self, identifier, requirements, incompatibilities):
55
+ """Find all possible candidates that satisfy given constraints.
56
+
57
+ :param identifier: An identifier as returned by ``identify()``. This
58
+ identifies the dependency matches of which should be returned.
59
+ :param requirements: A mapping of requirements that all returned
60
+ candidates must satisfy. Each key is an identifier, and the value
61
+ an iterator of requirements for that dependency.
62
+ :param incompatibilities: A mapping of known incompatibilities of
63
+ each dependency. Each key is an identifier, and the value an
64
+ iterator of incompatibilities known to the resolver. All
65
+ incompatibilities *must* be excluded from the return value.
66
+
67
+ This should try to get candidates based on the requirements' types.
68
+ For VCS, local, and archive requirements, the one-and-only match is
69
+ returned, and for a "named" requirement, the index(es) should be
70
+ consulted to find concrete candidates for this requirement.
71
+
72
+ The return value should produce candidates ordered by preference; the
73
+ most preferred candidate should come first. The return type may be one
74
+ of the following:
75
+
76
+ * A callable that returns an iterator that yields candidates.
77
+ * An collection of candidates.
78
+ * An iterable of candidates. This will be consumed immediately into a
79
+ list of candidates.
80
+ """
81
+ raise NotImplementedError
82
+
83
+ def is_satisfied_by(self, requirement, candidate):
84
+ """Whether the given requirement can be satisfied by a candidate.
85
+
86
+ The candidate is guarenteed to have been generated from the
87
+ requirement.
88
+
89
+ A boolean should be returned to indicate whether ``candidate`` is a
90
+ viable solution to the requirement.
91
+ """
92
+ raise NotImplementedError
93
+
94
+ def get_dependencies(self, candidate):
95
+ """Get dependencies of a candidate.
96
+
97
+ This should return a collection of requirements that `candidate`
98
+ specifies as its dependencies.
99
+ """
100
+ raise NotImplementedError
101
+
102
+
103
+ class AbstractResolver(object):
104
+ """The thing that performs the actual resolution work."""
105
+
106
+ base_exception = Exception
107
+
108
+ def __init__(self, provider, reporter):
109
+ self.provider = provider
110
+ self.reporter = reporter
111
+
112
+ def resolve(self, requirements, **kwargs):
113
+ """Take a collection of constraints, spit out the resolution result.
114
+
115
+ This returns a representation of the final resolution state, with one
116
+ guarenteed attribute ``mapping`` that contains resolved candidates as
117
+ values. The keys are their respective identifiers.
118
+
119
+ :param requirements: A collection of constraints.
120
+ :param kwargs: Additional keyword arguments that subclasses may accept.
121
+
122
+ :raises: ``self.base_exception`` or its subclass.
123
+ """
124
+ raise NotImplementedError
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/reporters.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class BaseReporter(object):
2
+ """Delegate class to provider progress reporting for the resolver."""
3
+
4
+ def starting(self):
5
+ """Called before the resolution actually starts."""
6
+
7
+ def starting_round(self, index):
8
+ """Called before each round of resolution starts.
9
+
10
+ The index is zero-based.
11
+ """
12
+
13
+ def ending_round(self, index, state):
14
+ """Called before each round of resolution ends.
15
+
16
+ This is NOT called if the resolution ends at this round. Use `ending`
17
+ if you want to report finalization. The index is zero-based.
18
+ """
19
+
20
+ def ending(self, state):
21
+ """Called before the resolution ends successfully."""
22
+
23
+ def adding_requirement(self, requirement, parent):
24
+ """Called when adding a new requirement into the resolve criteria.
25
+
26
+ :param requirement: The additional requirement to be applied to filter
27
+ the available candidaites.
28
+ :param parent: The candidate that requires ``requirement`` as a
29
+ dependency, or None if ``requirement`` is one of the root
30
+ requirements passed in from ``Resolver.resolve()``.
31
+ """
32
+
33
+ def backtracking(self, candidate):
34
+ """Called when rejecting a candidate during backtracking."""
35
+
36
+ def pinning(self, candidate):
37
+ """Called when adding a candidate to the potential solution."""
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/resolvers.py ADDED
@@ -0,0 +1,473 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import collections
2
+ import operator
3
+
4
+ from .providers import AbstractResolver
5
+ from .structs import DirectedGraph, IteratorMapping, build_iter_view
6
+
7
+
8
+ RequirementInformation = collections.namedtuple(
9
+ "RequirementInformation", ["requirement", "parent"]
10
+ )
11
+
12
+
13
+ class ResolverException(Exception):
14
+ """A base class for all exceptions raised by this module.
15
+
16
+ Exceptions derived by this class should all be handled in this module. Any
17
+ bubbling pass the resolver should be treated as a bug.
18
+ """
19
+
20
+
21
+ class RequirementsConflicted(ResolverException):
22
+ def __init__(self, criterion):
23
+ super(RequirementsConflicted, self).__init__(criterion)
24
+ self.criterion = criterion
25
+
26
+ def __str__(self):
27
+ return "Requirements conflict: {}".format(
28
+ ", ".join(repr(r) for r in self.criterion.iter_requirement()),
29
+ )
30
+
31
+
32
+ class InconsistentCandidate(ResolverException):
33
+ def __init__(self, candidate, criterion):
34
+ super(InconsistentCandidate, self).__init__(candidate, criterion)
35
+ self.candidate = candidate
36
+ self.criterion = criterion
37
+
38
+ def __str__(self):
39
+ return "Provided candidate {!r} does not satisfy {}".format(
40
+ self.candidate,
41
+ ", ".join(repr(r) for r in self.criterion.iter_requirement()),
42
+ )
43
+
44
+
45
+ class Criterion(object):
46
+ """Representation of possible resolution results of a package.
47
+
48
+ This holds three attributes:
49
+
50
+ * `information` is a collection of `RequirementInformation` pairs.
51
+ Each pair is a requirement contributing to this criterion, and the
52
+ candidate that provides the requirement.
53
+ * `incompatibilities` is a collection of all known not-to-work candidates
54
+ to exclude from consideration.
55
+ * `candidates` is a collection containing all possible candidates deducted
56
+ from the union of contributing requirements and known incompatibilities.
57
+ It should never be empty, except when the criterion is an attribute of a
58
+ raised `RequirementsConflicted` (in which case it is always empty).
59
+
60
+ .. note::
61
+ This class is intended to be externally immutable. **Do not** mutate
62
+ any of its attribute containers.
63
+ """
64
+
65
+ def __init__(self, candidates, information, incompatibilities):
66
+ self.candidates = candidates
67
+ self.information = information
68
+ self.incompatibilities = incompatibilities
69
+
70
+ def __repr__(self):
71
+ requirements = ", ".join(
72
+ "({!r}, via={!r})".format(req, parent)
73
+ for req, parent in self.information
74
+ )
75
+ return "Criterion({})".format(requirements)
76
+
77
+ def iter_requirement(self):
78
+ return (i.requirement for i in self.information)
79
+
80
+ def iter_parent(self):
81
+ return (i.parent for i in self.information)
82
+
83
+
84
+ class ResolutionError(ResolverException):
85
+ pass
86
+
87
+
88
+ class ResolutionImpossible(ResolutionError):
89
+ def __init__(self, causes):
90
+ super(ResolutionImpossible, self).__init__(causes)
91
+ # causes is a list of RequirementInformation objects
92
+ self.causes = causes
93
+
94
+
95
+ class ResolutionTooDeep(ResolutionError):
96
+ def __init__(self, round_count):
97
+ super(ResolutionTooDeep, self).__init__(round_count)
98
+ self.round_count = round_count
99
+
100
+
101
+ # Resolution state in a round.
102
+ State = collections.namedtuple("State", "mapping criteria")
103
+
104
+
105
+ class Resolution(object):
106
+ """Stateful resolution object.
107
+
108
+ This is designed as a one-off object that holds information to kick start
109
+ the resolution process, and holds the results afterwards.
110
+ """
111
+
112
+ def __init__(self, provider, reporter):
113
+ self._p = provider
114
+ self._r = reporter
115
+ self._states = []
116
+
117
+ @property
118
+ def state(self):
119
+ try:
120
+ return self._states[-1]
121
+ except IndexError:
122
+ raise AttributeError("state")
123
+
124
+ def _push_new_state(self):
125
+ """Push a new state into history.
126
+
127
+ This new state will be used to hold resolution results of the next
128
+ coming round.
129
+ """
130
+ base = self._states[-1]
131
+ state = State(
132
+ mapping=base.mapping.copy(),
133
+ criteria=base.criteria.copy(),
134
+ )
135
+ self._states.append(state)
136
+
137
+ def _add_to_criteria(self, criteria, requirement, parent):
138
+ self._r.adding_requirement(requirement=requirement, parent=parent)
139
+
140
+ identifier = self._p.identify(requirement_or_candidate=requirement)
141
+ criterion = criteria.get(identifier)
142
+ if criterion:
143
+ incompatibilities = list(criterion.incompatibilities)
144
+ else:
145
+ incompatibilities = []
146
+
147
+ matches = self._p.find_matches(
148
+ identifier=identifier,
149
+ requirements=IteratorMapping(
150
+ criteria,
151
+ operator.methodcaller("iter_requirement"),
152
+ {identifier: [requirement]},
153
+ ),
154
+ incompatibilities=IteratorMapping(
155
+ criteria,
156
+ operator.attrgetter("incompatibilities"),
157
+ {identifier: incompatibilities},
158
+ ),
159
+ )
160
+
161
+ if criterion:
162
+ information = list(criterion.information)
163
+ information.append(RequirementInformation(requirement, parent))
164
+ else:
165
+ information = [RequirementInformation(requirement, parent)]
166
+
167
+ criterion = Criterion(
168
+ candidates=build_iter_view(matches),
169
+ information=information,
170
+ incompatibilities=incompatibilities,
171
+ )
172
+ if not criterion.candidates:
173
+ raise RequirementsConflicted(criterion)
174
+ criteria[identifier] = criterion
175
+
176
+ def _get_preference(self, name):
177
+ return self._p.get_preference(
178
+ identifier=name,
179
+ resolutions=self.state.mapping,
180
+ candidates=IteratorMapping(
181
+ self.state.criteria,
182
+ operator.attrgetter("candidates"),
183
+ ),
184
+ information=IteratorMapping(
185
+ self.state.criteria,
186
+ operator.attrgetter("information"),
187
+ ),
188
+ )
189
+
190
+ def _is_current_pin_satisfying(self, name, criterion):
191
+ try:
192
+ current_pin = self.state.mapping[name]
193
+ except KeyError:
194
+ return False
195
+ return all(
196
+ self._p.is_satisfied_by(requirement=r, candidate=current_pin)
197
+ for r in criterion.iter_requirement()
198
+ )
199
+
200
+ def _get_updated_criteria(self, candidate):
201
+ criteria = self.state.criteria.copy()
202
+ for requirement in self._p.get_dependencies(candidate=candidate):
203
+ self._add_to_criteria(criteria, requirement, parent=candidate)
204
+ return criteria
205
+
206
+ def _attempt_to_pin_criterion(self, name):
207
+ criterion = self.state.criteria[name]
208
+
209
+ causes = []
210
+ for candidate in criterion.candidates:
211
+ try:
212
+ criteria = self._get_updated_criteria(candidate)
213
+ except RequirementsConflicted as e:
214
+ causes.append(e.criterion)
215
+ continue
216
+
217
+ # Check the newly-pinned candidate actually works. This should
218
+ # always pass under normal circumstances, but in the case of a
219
+ # faulty provider, we will raise an error to notify the implementer
220
+ # to fix find_matches() and/or is_satisfied_by().
221
+ satisfied = all(
222
+ self._p.is_satisfied_by(requirement=r, candidate=candidate)
223
+ for r in criterion.iter_requirement()
224
+ )
225
+ if not satisfied:
226
+ raise InconsistentCandidate(candidate, criterion)
227
+
228
+ self._r.pinning(candidate=candidate)
229
+ self.state.criteria.update(criteria)
230
+
231
+ # Put newly-pinned candidate at the end. This is essential because
232
+ # backtracking looks at this mapping to get the last pin.
233
+ self.state.mapping.pop(name, None)
234
+ self.state.mapping[name] = candidate
235
+
236
+ return []
237
+
238
+ # All candidates tried, nothing works. This criterion is a dead
239
+ # end, signal for backtracking.
240
+ return causes
241
+
242
+ def _backtrack(self):
243
+ """Perform backtracking.
244
+
245
+ When we enter here, the stack is like this::
246
+
247
+ [ state Z ]
248
+ [ state Y ]
249
+ [ state X ]
250
+ .... earlier states are irrelevant.
251
+
252
+ 1. No pins worked for Z, so it does not have a pin.
253
+ 2. We want to reset state Y to unpinned, and pin another candidate.
254
+ 3. State X holds what state Y was before the pin, but does not
255
+ have the incompatibility information gathered in state Y.
256
+
257
+ Each iteration of the loop will:
258
+
259
+ 1. Discard Z.
260
+ 2. Discard Y but remember its incompatibility information gathered
261
+ previously, and the failure we're dealing with right now.
262
+ 3. Push a new state Y' based on X, and apply the incompatibility
263
+ information from Y to Y'.
264
+ 4a. If this causes Y' to conflict, we need to backtrack again. Make Y'
265
+ the new Z and go back to step 2.
266
+ 4b. If the incompatibilities apply cleanly, end backtracking.
267
+ """
268
+ while len(self._states) >= 3:
269
+ # Remove the state that triggered backtracking.
270
+ del self._states[-1]
271
+
272
+ # Retrieve the last candidate pin and known incompatibilities.
273
+ broken_state = self._states.pop()
274
+ name, candidate = broken_state.mapping.popitem()
275
+ incompatibilities_from_broken = [
276
+ (k, list(v.incompatibilities))
277
+ for k, v in broken_state.criteria.items()
278
+ ]
279
+
280
+ # Also mark the newly known incompatibility.
281
+ incompatibilities_from_broken.append((name, [candidate]))
282
+
283
+ self._r.backtracking(candidate=candidate)
284
+
285
+ # Create a new state from the last known-to-work one, and apply
286
+ # the previously gathered incompatibility information.
287
+ def _patch_criteria():
288
+ for k, incompatibilities in incompatibilities_from_broken:
289
+ if not incompatibilities:
290
+ continue
291
+ try:
292
+ criterion = self.state.criteria[k]
293
+ except KeyError:
294
+ continue
295
+ matches = self._p.find_matches(
296
+ identifier=k,
297
+ requirements=IteratorMapping(
298
+ self.state.criteria,
299
+ operator.methodcaller("iter_requirement"),
300
+ ),
301
+ incompatibilities=IteratorMapping(
302
+ self.state.criteria,
303
+ operator.attrgetter("incompatibilities"),
304
+ {k: incompatibilities},
305
+ ),
306
+ )
307
+ candidates = build_iter_view(matches)
308
+ if not candidates:
309
+ return False
310
+ incompatibilities.extend(criterion.incompatibilities)
311
+ self.state.criteria[k] = Criterion(
312
+ candidates=candidates,
313
+ information=list(criterion.information),
314
+ incompatibilities=incompatibilities,
315
+ )
316
+ return True
317
+
318
+ self._push_new_state()
319
+ success = _patch_criteria()
320
+
321
+ # It works! Let's work on this new state.
322
+ if success:
323
+ return True
324
+
325
+ # State does not work after applying known incompatibilities.
326
+ # Try the still previous state.
327
+
328
+ # No way to backtrack anymore.
329
+ return False
330
+
331
+ def resolve(self, requirements, max_rounds):
332
+ if self._states:
333
+ raise RuntimeError("already resolved")
334
+
335
+ self._r.starting()
336
+
337
+ # Initialize the root state.
338
+ self._states = [State(mapping=collections.OrderedDict(), criteria={})]
339
+ for r in requirements:
340
+ try:
341
+ self._add_to_criteria(self.state.criteria, r, parent=None)
342
+ except RequirementsConflicted as e:
343
+ raise ResolutionImpossible(e.criterion.information)
344
+
345
+ # The root state is saved as a sentinel so the first ever pin can have
346
+ # something to backtrack to if it fails. The root state is basically
347
+ # pinning the virtual "root" package in the graph.
348
+ self._push_new_state()
349
+
350
+ for round_index in range(max_rounds):
351
+ self._r.starting_round(index=round_index)
352
+
353
+ unsatisfied_names = [
354
+ key
355
+ for key, criterion in self.state.criteria.items()
356
+ if not self._is_current_pin_satisfying(key, criterion)
357
+ ]
358
+
359
+ # All criteria are accounted for. Nothing more to pin, we are done!
360
+ if not unsatisfied_names:
361
+ self._r.ending(state=self.state)
362
+ return self.state
363
+
364
+ # Choose the most preferred unpinned criterion to try.
365
+ name = min(unsatisfied_names, key=self._get_preference)
366
+ failure_causes = self._attempt_to_pin_criterion(name)
367
+
368
+ if failure_causes:
369
+ # Backtrack if pinning fails. The backtrack process puts us in
370
+ # an unpinned state, so we can work on it in the next round.
371
+ success = self._backtrack()
372
+
373
+ # Dead ends everywhere. Give up.
374
+ if not success:
375
+ causes = [i for c in failure_causes for i in c.information]
376
+ raise ResolutionImpossible(causes)
377
+ else:
378
+ # Pinning was successful. Push a new state to do another pin.
379
+ self._push_new_state()
380
+
381
+ self._r.ending_round(index=round_index, state=self.state)
382
+
383
+ raise ResolutionTooDeep(max_rounds)
384
+
385
+
386
+ def _has_route_to_root(criteria, key, all_keys, connected):
387
+ if key in connected:
388
+ return True
389
+ if key not in criteria:
390
+ return False
391
+ for p in criteria[key].iter_parent():
392
+ try:
393
+ pkey = all_keys[id(p)]
394
+ except KeyError:
395
+ continue
396
+ if pkey in connected:
397
+ connected.add(key)
398
+ return True
399
+ if _has_route_to_root(criteria, pkey, all_keys, connected):
400
+ connected.add(key)
401
+ return True
402
+ return False
403
+
404
+
405
+ Result = collections.namedtuple("Result", "mapping graph criteria")
406
+
407
+
408
+ def _build_result(state):
409
+ mapping = state.mapping
410
+ all_keys = {id(v): k for k, v in mapping.items()}
411
+ all_keys[id(None)] = None
412
+
413
+ graph = DirectedGraph()
414
+ graph.add(None) # Sentinel as root dependencies' parent.
415
+
416
+ connected = {None}
417
+ for key, criterion in state.criteria.items():
418
+ if not _has_route_to_root(state.criteria, key, all_keys, connected):
419
+ continue
420
+ if key not in graph:
421
+ graph.add(key)
422
+ for p in criterion.iter_parent():
423
+ try:
424
+ pkey = all_keys[id(p)]
425
+ except KeyError:
426
+ continue
427
+ if pkey not in graph:
428
+ graph.add(pkey)
429
+ graph.connect(pkey, key)
430
+
431
+ return Result(
432
+ mapping={k: v for k, v in mapping.items() if k in connected},
433
+ graph=graph,
434
+ criteria=state.criteria,
435
+ )
436
+
437
+
438
+ class Resolver(AbstractResolver):
439
+ """The thing that performs the actual resolution work."""
440
+
441
+ base_exception = ResolverException
442
+
443
+ def resolve(self, requirements, max_rounds=100):
444
+ """Take a collection of constraints, spit out the resolution result.
445
+
446
+ The return value is a representation to the final resolution result. It
447
+ is a tuple subclass with three public members:
448
+
449
+ * `mapping`: A dict of resolved candidates. Each key is an identifier
450
+ of a requirement (as returned by the provider's `identify` method),
451
+ and the value is the resolved candidate.
452
+ * `graph`: A `DirectedGraph` instance representing the dependency tree.
453
+ The vertices are keys of `mapping`, and each edge represents *why*
454
+ a particular package is included. A special vertex `None` is
455
+ included to represent parents of user-supplied requirements.
456
+ * `criteria`: A dict of "criteria" that hold detailed information on
457
+ how edges in the graph are derived. Each key is an identifier of a
458
+ requirement, and the value is a `Criterion` instance.
459
+
460
+ The following exceptions may be raised if a resolution cannot be found:
461
+
462
+ * `ResolutionImpossible`: A resolution cannot be found for the given
463
+ combination of requirements. The `causes` attribute of the
464
+ exception is a list of (requirement, parent), giving the
465
+ requirements that could not be satisfied.
466
+ * `ResolutionTooDeep`: The dependency tree is too deeply nested and
467
+ the resolver gave up. This is usually caused by a circular
468
+ dependency, but you can try to resolve this by increasing the
469
+ `max_rounds` argument.
470
+ """
471
+ resolution = Resolution(self.provider, self.reporter)
472
+ state = resolution.resolve(requirements, max_rounds=max_rounds)
473
+ return _build_result(state)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/resolvelib/structs.py ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import itertools
2
+
3
+ from .compat import collections_abc
4
+
5
+
6
+ class DirectedGraph(object):
7
+ """A graph structure with directed edges."""
8
+
9
+ def __init__(self):
10
+ self._vertices = set()
11
+ self._forwards = {} # <key> -> Set[<key>]
12
+ self._backwards = {} # <key> -> Set[<key>]
13
+
14
+ def __iter__(self):
15
+ return iter(self._vertices)
16
+
17
+ def __len__(self):
18
+ return len(self._vertices)
19
+
20
+ def __contains__(self, key):
21
+ return key in self._vertices
22
+
23
+ def copy(self):
24
+ """Return a shallow copy of this graph."""
25
+ other = DirectedGraph()
26
+ other._vertices = set(self._vertices)
27
+ other._forwards = {k: set(v) for k, v in self._forwards.items()}
28
+ other._backwards = {k: set(v) for k, v in self._backwards.items()}
29
+ return other
30
+
31
+ def add(self, key):
32
+ """Add a new vertex to the graph."""
33
+ if key in self._vertices:
34
+ raise ValueError("vertex exists")
35
+ self._vertices.add(key)
36
+ self._forwards[key] = set()
37
+ self._backwards[key] = set()
38
+
39
+ def remove(self, key):
40
+ """Remove a vertex from the graph, disconnecting all edges from/to it."""
41
+ self._vertices.remove(key)
42
+ for f in self._forwards.pop(key):
43
+ self._backwards[f].remove(key)
44
+ for t in self._backwards.pop(key):
45
+ self._forwards[t].remove(key)
46
+
47
+ def connected(self, f, t):
48
+ return f in self._backwards[t] and t in self._forwards[f]
49
+
50
+ def connect(self, f, t):
51
+ """Connect two existing vertices.
52
+
53
+ Nothing happens if the vertices are already connected.
54
+ """
55
+ if t not in self._vertices:
56
+ raise KeyError(t)
57
+ self._forwards[f].add(t)
58
+ self._backwards[t].add(f)
59
+
60
+ def iter_edges(self):
61
+ for f, children in self._forwards.items():
62
+ for t in children:
63
+ yield f, t
64
+
65
+ def iter_children(self, key):
66
+ return iter(self._forwards[key])
67
+
68
+ def iter_parents(self, key):
69
+ return iter(self._backwards[key])
70
+
71
+
72
+ class IteratorMapping(collections_abc.Mapping):
73
+ def __init__(self, mapping, accessor, appends=None):
74
+ self._mapping = mapping
75
+ self._accessor = accessor
76
+ self._appends = appends or {}
77
+
78
+ def __repr__(self):
79
+ return "IteratorMapping({!r}, {!r}, {!r})".format(
80
+ self._mapping,
81
+ self._accessor,
82
+ self._appends,
83
+ )
84
+
85
+ def __bool__(self):
86
+ return bool(self._mapping or self._appends)
87
+
88
+ __nonzero__ = __bool__ # XXX: Python 2.
89
+
90
+ def __contains__(self, key):
91
+ return key in self._mapping or key in self._appends
92
+
93
+ def __getitem__(self, k):
94
+ try:
95
+ v = self._mapping[k]
96
+ except KeyError:
97
+ return iter(self._appends[k])
98
+ return itertools.chain(self._accessor(v), self._appends.get(k, ()))
99
+
100
+ def __iter__(self):
101
+ more = (k for k in self._appends if k not in self._mapping)
102
+ return itertools.chain(self._mapping, more)
103
+
104
+ def __len__(self):
105
+ more = sum(1 for k in self._appends if k not in self._mapping)
106
+ return len(self._mapping) + more
107
+
108
+
109
+ class _FactoryIterableView(object):
110
+ """Wrap an iterator factory returned by `find_matches()`.
111
+
112
+ Calling `iter()` on this class would invoke the underlying iterator
113
+ factory, making it a "collection with ordering" that can be iterated
114
+ through multiple times, but lacks random access methods presented in
115
+ built-in Python sequence types.
116
+ """
117
+
118
+ def __init__(self, factory):
119
+ self._factory = factory
120
+
121
+ def __repr__(self):
122
+ return "{}({})".format(type(self).__name__, list(self._factory()))
123
+
124
+ def __bool__(self):
125
+ try:
126
+ next(self._factory())
127
+ except StopIteration:
128
+ return False
129
+ return True
130
+
131
+ __nonzero__ = __bool__ # XXX: Python 2.
132
+
133
+ def __iter__(self):
134
+ return self._factory()
135
+
136
+
137
+ class _SequenceIterableView(object):
138
+ """Wrap an iterable returned by find_matches().
139
+
140
+ This is essentially just a proxy to the underlying sequence that provides
141
+ the same interface as `_FactoryIterableView`.
142
+ """
143
+
144
+ def __init__(self, sequence):
145
+ self._sequence = sequence
146
+
147
+ def __repr__(self):
148
+ return "{}({})".format(type(self).__name__, self._sequence)
149
+
150
+ def __bool__(self):
151
+ return bool(self._sequence)
152
+
153
+ __nonzero__ = __bool__ # XXX: Python 2.
154
+
155
+ def __iter__(self):
156
+ return iter(self._sequence)
157
+
158
+
159
+ def build_iter_view(matches):
160
+ """Build an iterable view from the value returned by `find_matches()`."""
161
+ if callable(matches):
162
+ return _FactoryIterableView(matches)
163
+ if not isinstance(matches, collections_abc.Sequence):
164
+ matches = list(matches)
165
+ return _SequenceIterableView(matches)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py ADDED
File without changes
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ backports.makefile
4
+ ~~~~~~~~~~~~~~~~~~
5
+
6
+ Backports the Python 3 ``socket.makefile`` method for use with anything that
7
+ wants to create a "fake" socket object.
8
+ """
9
+ import io
10
+ from socket import SocketIO
11
+
12
+
13
+ def backport_makefile(
14
+ self, mode="r", buffering=None, encoding=None, errors=None, newline=None
15
+ ):
16
+ """
17
+ Backport of ``socket.makefile`` from Python 3.5.
18
+ """
19
+ if not set(mode) <= {"r", "w", "b"}:
20
+ raise ValueError("invalid mode %r (only r, w, b allowed)" % (mode,))
21
+ writing = "w" in mode
22
+ reading = "r" in mode or not writing
23
+ assert reading or writing
24
+ binary = "b" in mode
25
+ rawmode = ""
26
+ if reading:
27
+ rawmode += "r"
28
+ if writing:
29
+ rawmode += "w"
30
+ raw = SocketIO(self, rawmode)
31
+ self._makefile_refs += 1
32
+ if buffering is None:
33
+ buffering = -1
34
+ if buffering < 0:
35
+ buffering = io.DEFAULT_BUFFER_SIZE
36
+ if buffering == 0:
37
+ if not binary:
38
+ raise ValueError("unbuffered streams must be binary")
39
+ return raw
40
+ if reading and writing:
41
+ buffer = io.BufferedRWPair(raw, raw, buffering)
42
+ elif reading:
43
+ buffer = io.BufferedReader(raw, buffering)
44
+ else:
45
+ assert writing
46
+ buffer = io.BufferedWriter(raw, buffering)
47
+ if binary:
48
+ return buffer
49
+ text = io.TextIOWrapper(buffer, encoding, errors, newline)
50
+ text.mode = mode
51
+ return text
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+
3
+ try:
4
+ # Our match_hostname function is the same as 3.10's, so we only want to
5
+ # import the match_hostname function if it's at least that good.
6
+ # We also fallback on Python 3.10+ because our code doesn't emit
7
+ # deprecation warnings and is the same as Python 3.10 otherwise.
8
+ if sys.version_info < (3, 5) or sys.version_info >= (3, 10):
9
+ raise ImportError("Fallback to vendored code")
10
+
11
+ from ssl import CertificateError, match_hostname
12
+ except ImportError:
13
+ try:
14
+ # Backport of the function from a pypi module
15
+ from backports.ssl_match_hostname import ( # type: ignore
16
+ CertificateError,
17
+ match_hostname,
18
+ )
19
+ except ImportError:
20
+ # Our vendored copy
21
+ from ._implementation import CertificateError, match_hostname # type: ignore
22
+
23
+ # Not needed, but documenting what we provide.
24
+ __all__ = ("CertificateError", "match_hostname")
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """The match_hostname() function from Python 3.3.3, essential when using SSL."""
2
+
3
+ # Note: This file is under the PSF license as the code comes from the python
4
+ # stdlib. http://docs.python.org/3/license.html
5
+
6
+ import re
7
+ import sys
8
+
9
+ # ipaddress has been backported to 2.6+ in pypi. If it is installed on the
10
+ # system, use it to handle IPAddress ServerAltnames (this was added in
11
+ # python-3.5) otherwise only do DNS matching. This allows
12
+ # backports.ssl_match_hostname to continue to be used in Python 2.7.
13
+ try:
14
+ import ipaddress
15
+ except ImportError:
16
+ ipaddress = None
17
+
18
+ __version__ = "3.5.0.1"
19
+
20
+
21
+ class CertificateError(ValueError):
22
+ pass
23
+
24
+
25
+ def _dnsname_match(dn, hostname, max_wildcards=1):
26
+ """Matching according to RFC 6125, section 6.4.3
27
+
28
+ http://tools.ietf.org/html/rfc6125#section-6.4.3
29
+ """
30
+ pats = []
31
+ if not dn:
32
+ return False
33
+
34
+ # Ported from python3-syntax:
35
+ # leftmost, *remainder = dn.split(r'.')
36
+ parts = dn.split(r".")
37
+ leftmost = parts[0]
38
+ remainder = parts[1:]
39
+
40
+ wildcards = leftmost.count("*")
41
+ if wildcards > max_wildcards:
42
+ # Issue #17980: avoid denials of service by refusing more
43
+ # than one wildcard per fragment. A survey of established
44
+ # policy among SSL implementations showed it to be a
45
+ # reasonable choice.
46
+ raise CertificateError(
47
+ "too many wildcards in certificate DNS name: " + repr(dn)
48
+ )
49
+
50
+ # speed up common case w/o wildcards
51
+ if not wildcards:
52
+ return dn.lower() == hostname.lower()
53
+
54
+ # RFC 6125, section 6.4.3, subitem 1.
55
+ # The client SHOULD NOT attempt to match a presented identifier in which
56
+ # the wildcard character comprises a label other than the left-most label.
57
+ if leftmost == "*":
58
+ # When '*' is a fragment by itself, it matches a non-empty dotless
59
+ # fragment.
60
+ pats.append("[^.]+")
61
+ elif leftmost.startswith("xn--") or hostname.startswith("xn--"):
62
+ # RFC 6125, section 6.4.3, subitem 3.
63
+ # The client SHOULD NOT attempt to match a presented identifier
64
+ # where the wildcard character is embedded within an A-label or
65
+ # U-label of an internationalized domain name.
66
+ pats.append(re.escape(leftmost))
67
+ else:
68
+ # Otherwise, '*' matches any dotless string, e.g. www*
69
+ pats.append(re.escape(leftmost).replace(r"\*", "[^.]*"))
70
+
71
+ # add the remaining fragments, ignore any wildcards
72
+ for frag in remainder:
73
+ pats.append(re.escape(frag))
74
+
75
+ pat = re.compile(r"\A" + r"\.".join(pats) + r"\Z", re.IGNORECASE)
76
+ return pat.match(hostname)
77
+
78
+
79
+ def _to_unicode(obj):
80
+ if isinstance(obj, str) and sys.version_info < (3,):
81
+ obj = unicode(obj, encoding="ascii", errors="strict")
82
+ return obj
83
+
84
+
85
+ def _ipaddress_match(ipname, host_ip):
86
+ """Exact matching of IP addresses.
87
+
88
+ RFC 6125 explicitly doesn't define an algorithm for this
89
+ (section 1.7.2 - "Out of Scope").
90
+ """
91
+ # OpenSSL may add a trailing newline to a subjectAltName's IP address
92
+ # Divergence from upstream: ipaddress can't handle byte str
93
+ ip = ipaddress.ip_address(_to_unicode(ipname).rstrip())
94
+ return ip == host_ip
95
+
96
+
97
+ def match_hostname(cert, hostname):
98
+ """Verify that *cert* (in decoded format as returned by
99
+ SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125
100
+ rules are followed, but IP addresses are not accepted for *hostname*.
101
+
102
+ CertificateError is raised on failure. On success, the function
103
+ returns nothing.
104
+ """
105
+ if not cert:
106
+ raise ValueError(
107
+ "empty or no certificate, match_hostname needs a "
108
+ "SSL socket or SSL context with either "
109
+ "CERT_OPTIONAL or CERT_REQUIRED"
110
+ )
111
+ try:
112
+ # Divergence from upstream: ipaddress can't handle byte str
113
+ host_ip = ipaddress.ip_address(_to_unicode(hostname))
114
+ except ValueError:
115
+ # Not an IP address (common case)
116
+ host_ip = None
117
+ except UnicodeError:
118
+ # Divergence from upstream: Have to deal with ipaddress not taking
119
+ # byte strings. addresses should be all ascii, so we consider it not
120
+ # an ipaddress in this case
121
+ host_ip = None
122
+ except AttributeError:
123
+ # Divergence from upstream: Make ipaddress library optional
124
+ if ipaddress is None:
125
+ host_ip = None
126
+ else:
127
+ raise
128
+ dnsnames = []
129
+ san = cert.get("subjectAltName", ())
130
+ for key, value in san:
131
+ if key == "DNS":
132
+ if host_ip is None and _dnsname_match(value, hostname):
133
+ return
134
+ dnsnames.append(value)
135
+ elif key == "IP Address":
136
+ if host_ip is not None and _ipaddress_match(value, host_ip):
137
+ return
138
+ dnsnames.append(value)
139
+ if not dnsnames:
140
+ # The subject is only checked when there is no dNSName entry
141
+ # in subjectAltName
142
+ for sub in cert.get("subject", ()):
143
+ for key, value in sub:
144
+ # XXX according to RFC 2818, the most specific Common Name
145
+ # must be used.
146
+ if key == "commonName":
147
+ if _dnsname_match(value, hostname):
148
+ return
149
+ dnsnames.append(value)
150
+ if len(dnsnames) > 1:
151
+ raise CertificateError(
152
+ "hostname %r "
153
+ "doesn't match either of %s" % (hostname, ", ".join(map(repr, dnsnames)))
154
+ )
155
+ elif len(dnsnames) == 1:
156
+ raise CertificateError("hostname %r doesn't match %r" % (hostname, dnsnames[0]))
157
+ else:
158
+ raise CertificateError(
159
+ "no appropriate commonName or subjectAltName fields were found"
160
+ )
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/__init__.py ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Extensions to the 'distutils' for large or complex distributions"""
2
+
3
+ from fnmatch import fnmatchcase
4
+ import functools
5
+ import os
6
+ import re
7
+
8
+ import _distutils_hack.override # noqa: F401
9
+
10
+ import distutils.core
11
+ from distutils.errors import DistutilsOptionError
12
+ from distutils.util import convert_path
13
+
14
+ from ._deprecation_warning import SetuptoolsDeprecationWarning
15
+
16
+ import setuptools.version
17
+ from setuptools.extension import Extension
18
+ from setuptools.dist import Distribution
19
+ from setuptools.depends import Require
20
+ from . import monkey
21
+
22
+
23
+ __all__ = [
24
+ 'setup',
25
+ 'Distribution',
26
+ 'Command',
27
+ 'Extension',
28
+ 'Require',
29
+ 'SetuptoolsDeprecationWarning',
30
+ 'find_packages',
31
+ 'find_namespace_packages',
32
+ ]
33
+
34
+ __version__ = setuptools.version.__version__
35
+
36
+ bootstrap_install_from = None
37
+
38
+
39
+ class PackageFinder:
40
+ """
41
+ Generate a list of all Python packages found within a directory
42
+ """
43
+
44
+ @classmethod
45
+ def find(cls, where='.', exclude=(), include=('*',)):
46
+ """Return a list all Python packages found within directory 'where'
47
+
48
+ 'where' is the root directory which will be searched for packages. It
49
+ should be supplied as a "cross-platform" (i.e. URL-style) path; it will
50
+ be converted to the appropriate local path syntax.
51
+
52
+ 'exclude' is a sequence of package names to exclude; '*' can be used
53
+ as a wildcard in the names, such that 'foo.*' will exclude all
54
+ subpackages of 'foo' (but not 'foo' itself).
55
+
56
+ 'include' is a sequence of package names to include. If it's
57
+ specified, only the named packages will be included. If it's not
58
+ specified, all found packages will be included. 'include' can contain
59
+ shell style wildcard patterns just like 'exclude'.
60
+ """
61
+
62
+ return list(
63
+ cls._find_packages_iter(
64
+ convert_path(where),
65
+ cls._build_filter('ez_setup', '*__pycache__', *exclude),
66
+ cls._build_filter(*include),
67
+ )
68
+ )
69
+
70
+ @classmethod
71
+ def _find_packages_iter(cls, where, exclude, include):
72
+ """
73
+ All the packages found in 'where' that pass the 'include' filter, but
74
+ not the 'exclude' filter.
75
+ """
76
+ for root, dirs, files in os.walk(where, followlinks=True):
77
+ # Copy dirs to iterate over it, then empty dirs.
78
+ all_dirs = dirs[:]
79
+ dirs[:] = []
80
+
81
+ for dir in all_dirs:
82
+ full_path = os.path.join(root, dir)
83
+ rel_path = os.path.relpath(full_path, where)
84
+ package = rel_path.replace(os.path.sep, '.')
85
+
86
+ # Skip directory trees that are not valid packages
87
+ if '.' in dir or not cls._looks_like_package(full_path):
88
+ continue
89
+
90
+ # Should this package be included?
91
+ if include(package) and not exclude(package):
92
+ yield package
93
+
94
+ # Keep searching subdirectories, as there may be more packages
95
+ # down there, even if the parent was excluded.
96
+ dirs.append(dir)
97
+
98
+ @staticmethod
99
+ def _looks_like_package(path):
100
+ """Does a directory look like a package?"""
101
+ return os.path.isfile(os.path.join(path, '__init__.py'))
102
+
103
+ @staticmethod
104
+ def _build_filter(*patterns):
105
+ """
106
+ Given a list of patterns, return a callable that will be true only if
107
+ the input matches at least one of the patterns.
108
+ """
109
+ return lambda name: any(fnmatchcase(name, pat=pat) for pat in patterns)
110
+
111
+
112
+ class PEP420PackageFinder(PackageFinder):
113
+ @staticmethod
114
+ def _looks_like_package(path):
115
+ return True
116
+
117
+
118
+ find_packages = PackageFinder.find
119
+ find_namespace_packages = PEP420PackageFinder.find
120
+
121
+
122
+ def _install_setup_requires(attrs):
123
+ # Note: do not use `setuptools.Distribution` directly, as
124
+ # our PEP 517 backend patch `distutils.core.Distribution`.
125
+ class MinimalDistribution(distutils.core.Distribution):
126
+ """
127
+ A minimal version of a distribution for supporting the
128
+ fetch_build_eggs interface.
129
+ """
130
+
131
+ def __init__(self, attrs):
132
+ _incl = 'dependency_links', 'setup_requires'
133
+ filtered = {k: attrs[k] for k in set(_incl) & set(attrs)}
134
+ distutils.core.Distribution.__init__(self, filtered)
135
+
136
+ def finalize_options(self):
137
+ """
138
+ Disable finalize_options to avoid building the working set.
139
+ Ref #2158.
140
+ """
141
+
142
+ dist = MinimalDistribution(attrs)
143
+
144
+ # Honor setup.cfg's options.
145
+ dist.parse_config_files(ignore_option_errors=True)
146
+ if dist.setup_requires:
147
+ dist.fetch_build_eggs(dist.setup_requires)
148
+
149
+
150
+ def setup(**attrs):
151
+ # Make sure we have any requirements needed to interpret 'attrs'.
152
+ _install_setup_requires(attrs)
153
+ return distutils.core.setup(**attrs)
154
+
155
+
156
+ setup.__doc__ = distutils.core.setup.__doc__
157
+
158
+
159
+ _Command = monkey.get_unpatched(distutils.core.Command)
160
+
161
+
162
+ class Command(_Command):
163
+ __doc__ = _Command.__doc__
164
+
165
+ command_consumes_arguments = False
166
+
167
+ def __init__(self, dist, **kw):
168
+ """
169
+ Construct the command for dist, updating
170
+ vars(self) with any keyword parameters.
171
+ """
172
+ _Command.__init__(self, dist)
173
+ vars(self).update(kw)
174
+
175
+ def _ensure_stringlike(self, option, what, default=None):
176
+ val = getattr(self, option)
177
+ if val is None:
178
+ setattr(self, option, default)
179
+ return default
180
+ elif not isinstance(val, str):
181
+ raise DistutilsOptionError(
182
+ "'%s' must be a %s (got `%s`)" % (option, what, val)
183
+ )
184
+ return val
185
+
186
+ def ensure_string_list(self, option):
187
+ r"""Ensure that 'option' is a list of strings. If 'option' is
188
+ currently a string, we split it either on /,\s*/ or /\s+/, so
189
+ "foo bar baz", "foo,bar,baz", and "foo, bar baz" all become
190
+ ["foo", "bar", "baz"].
191
+ """
192
+ val = getattr(self, option)
193
+ if val is None:
194
+ return
195
+ elif isinstance(val, str):
196
+ setattr(self, option, re.split(r',\s*|\s+', val))
197
+ else:
198
+ if isinstance(val, list):
199
+ ok = all(isinstance(v, str) for v in val)
200
+ else:
201
+ ok = False
202
+ if not ok:
203
+ raise DistutilsOptionError(
204
+ "'%s' must be a list of strings (got %r)" % (option, val)
205
+ )
206
+
207
+ def reinitialize_command(self, command, reinit_subcommands=0, **kw):
208
+ cmd = _Command.reinitialize_command(self, command, reinit_subcommands)
209
+ vars(cmd).update(kw)
210
+ return cmd
211
+
212
+
213
+ def _find_all_simple(path):
214
+ """
215
+ Find all files under 'path'
216
+ """
217
+ results = (
218
+ os.path.join(base, file)
219
+ for base, dirs, files in os.walk(path, followlinks=True)
220
+ for file in files
221
+ )
222
+ return filter(os.path.isfile, results)
223
+
224
+
225
+ def findall(dir=os.curdir):
226
+ """
227
+ Find all files under 'dir' and return the list of full filenames.
228
+ Unless dir is '.', return full filenames with dir prepended.
229
+ """
230
+ files = _find_all_simple(dir)
231
+ if dir == os.curdir:
232
+ make_rel = functools.partial(os.path.relpath, start=dir)
233
+ files = map(make_rel, files)
234
+ return list(files)
235
+
236
+
237
+ class sic(str):
238
+ """Treat this string as-is (https://en.wikipedia.org/wiki/Sic)"""
239
+
240
+
241
+ # Apply monkey patches
242
+ monkey.patch_all()
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_deprecation_warning.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ class SetuptoolsDeprecationWarning(Warning):
2
+ """
3
+ Base class for warning deprecations in ``setuptools``
4
+
5
+ This class is not derived from ``DeprecationWarning``, and as such is
6
+ visible by default.
7
+ """
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_imp.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Re-implementation of find_module and get_frozen_object
3
+ from the deprecated imp module.
4
+ """
5
+
6
+ import os
7
+ import importlib.util
8
+ import importlib.machinery
9
+
10
+ from .py34compat import module_from_spec
11
+
12
+
13
+ PY_SOURCE = 1
14
+ PY_COMPILED = 2
15
+ C_EXTENSION = 3
16
+ C_BUILTIN = 6
17
+ PY_FROZEN = 7
18
+
19
+
20
+ def find_spec(module, paths):
21
+ finder = (
22
+ importlib.machinery.PathFinder().find_spec
23
+ if isinstance(paths, list) else
24
+ importlib.util.find_spec
25
+ )
26
+ return finder(module, paths)
27
+
28
+
29
+ def find_module(module, paths=None):
30
+ """Just like 'imp.find_module()', but with package support"""
31
+ spec = find_spec(module, paths)
32
+ if spec is None:
33
+ raise ImportError("Can't find %s" % module)
34
+ if not spec.has_location and hasattr(spec, 'submodule_search_locations'):
35
+ spec = importlib.util.spec_from_loader('__init__.py', spec.loader)
36
+
37
+ kind = -1
38
+ file = None
39
+ static = isinstance(spec.loader, type)
40
+ if spec.origin == 'frozen' or static and issubclass(
41
+ spec.loader, importlib.machinery.FrozenImporter):
42
+ kind = PY_FROZEN
43
+ path = None # imp compabilty
44
+ suffix = mode = '' # imp compatibility
45
+ elif spec.origin == 'built-in' or static and issubclass(
46
+ spec.loader, importlib.machinery.BuiltinImporter):
47
+ kind = C_BUILTIN
48
+ path = None # imp compabilty
49
+ suffix = mode = '' # imp compatibility
50
+ elif spec.has_location:
51
+ path = spec.origin
52
+ suffix = os.path.splitext(path)[1]
53
+ mode = 'r' if suffix in importlib.machinery.SOURCE_SUFFIXES else 'rb'
54
+
55
+ if suffix in importlib.machinery.SOURCE_SUFFIXES:
56
+ kind = PY_SOURCE
57
+ elif suffix in importlib.machinery.BYTECODE_SUFFIXES:
58
+ kind = PY_COMPILED
59
+ elif suffix in importlib.machinery.EXTENSION_SUFFIXES:
60
+ kind = C_EXTENSION
61
+
62
+ if kind in {PY_SOURCE, PY_COMPILED}:
63
+ file = open(path, mode)
64
+ else:
65
+ path = None
66
+ suffix = mode = ''
67
+
68
+ return file, path, (suffix, mode, kind)
69
+
70
+
71
+ def get_frozen_object(module, paths=None):
72
+ spec = find_spec(module, paths)
73
+ if not spec:
74
+ raise ImportError("Can't find %s" % module)
75
+ return spec.loader.get_code(module)
76
+
77
+
78
+ def get_module(module, paths, info):
79
+ spec = find_spec(module, paths)
80
+ if not spec:
81
+ raise ImportError("Can't find %s" % module)
82
+ return module_from_spec(spec)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/__init__.py ADDED
File without changes
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/more_itertools/__init__.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ from .more import * # noqa
2
+ from .recipes import * # noqa
3
+
4
+ __version__ = '8.8.0'
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/more_itertools/more.py ADDED
The diff for this file is too large to render. See raw diff
 
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/more_itertools/recipes.py ADDED
@@ -0,0 +1,620 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Imported from the recipes section of the itertools documentation.
2
+
3
+ All functions taken from the recipes section of the itertools library docs
4
+ [1]_.
5
+ Some backward-compatible usability improvements have been made.
6
+
7
+ .. [1] http://docs.python.org/library/itertools.html#recipes
8
+
9
+ """
10
+ import warnings
11
+ from collections import deque
12
+ from itertools import (
13
+ chain,
14
+ combinations,
15
+ count,
16
+ cycle,
17
+ groupby,
18
+ islice,
19
+ repeat,
20
+ starmap,
21
+ tee,
22
+ zip_longest,
23
+ )
24
+ import operator
25
+ from random import randrange, sample, choice
26
+
27
+ __all__ = [
28
+ 'all_equal',
29
+ 'consume',
30
+ 'convolve',
31
+ 'dotproduct',
32
+ 'first_true',
33
+ 'flatten',
34
+ 'grouper',
35
+ 'iter_except',
36
+ 'ncycles',
37
+ 'nth',
38
+ 'nth_combination',
39
+ 'padnone',
40
+ 'pad_none',
41
+ 'pairwise',
42
+ 'partition',
43
+ 'powerset',
44
+ 'prepend',
45
+ 'quantify',
46
+ 'random_combination_with_replacement',
47
+ 'random_combination',
48
+ 'random_permutation',
49
+ 'random_product',
50
+ 'repeatfunc',
51
+ 'roundrobin',
52
+ 'tabulate',
53
+ 'tail',
54
+ 'take',
55
+ 'unique_everseen',
56
+ 'unique_justseen',
57
+ ]
58
+
59
+
60
+ def take(n, iterable):
61
+ """Return first *n* items of the iterable as a list.
62
+
63
+ >>> take(3, range(10))
64
+ [0, 1, 2]
65
+
66
+ If there are fewer than *n* items in the iterable, all of them are
67
+ returned.
68
+
69
+ >>> take(10, range(3))
70
+ [0, 1, 2]
71
+
72
+ """
73
+ return list(islice(iterable, n))
74
+
75
+
76
+ def tabulate(function, start=0):
77
+ """Return an iterator over the results of ``func(start)``,
78
+ ``func(start + 1)``, ``func(start + 2)``...
79
+
80
+ *func* should be a function that accepts one integer argument.
81
+
82
+ If *start* is not specified it defaults to 0. It will be incremented each
83
+ time the iterator is advanced.
84
+
85
+ >>> square = lambda x: x ** 2
86
+ >>> iterator = tabulate(square, -3)
87
+ >>> take(4, iterator)
88
+ [9, 4, 1, 0]
89
+
90
+ """
91
+ return map(function, count(start))
92
+
93
+
94
+ def tail(n, iterable):
95
+ """Return an iterator over the last *n* items of *iterable*.
96
+
97
+ >>> t = tail(3, 'ABCDEFG')
98
+ >>> list(t)
99
+ ['E', 'F', 'G']
100
+
101
+ """
102
+ return iter(deque(iterable, maxlen=n))
103
+
104
+
105
+ def consume(iterator, n=None):
106
+ """Advance *iterable* by *n* steps. If *n* is ``None``, consume it
107
+ entirely.
108
+
109
+ Efficiently exhausts an iterator without returning values. Defaults to
110
+ consuming the whole iterator, but an optional second argument may be
111
+ provided to limit consumption.
112
+
113
+ >>> i = (x for x in range(10))
114
+ >>> next(i)
115
+ 0
116
+ >>> consume(i, 3)
117
+ >>> next(i)
118
+ 4
119
+ >>> consume(i)
120
+ >>> next(i)
121
+ Traceback (most recent call last):
122
+ File "<stdin>", line 1, in <module>
123
+ StopIteration
124
+
125
+ If the iterator has fewer items remaining than the provided limit, the
126
+ whole iterator will be consumed.
127
+
128
+ >>> i = (x for x in range(3))
129
+ >>> consume(i, 5)
130
+ >>> next(i)
131
+ Traceback (most recent call last):
132
+ File "<stdin>", line 1, in <module>
133
+ StopIteration
134
+
135
+ """
136
+ # Use functions that consume iterators at C speed.
137
+ if n is None:
138
+ # feed the entire iterator into a zero-length deque
139
+ deque(iterator, maxlen=0)
140
+ else:
141
+ # advance to the empty slice starting at position n
142
+ next(islice(iterator, n, n), None)
143
+
144
+
145
+ def nth(iterable, n, default=None):
146
+ """Returns the nth item or a default value.
147
+
148
+ >>> l = range(10)
149
+ >>> nth(l, 3)
150
+ 3
151
+ >>> nth(l, 20, "zebra")
152
+ 'zebra'
153
+
154
+ """
155
+ return next(islice(iterable, n, None), default)
156
+
157
+
158
+ def all_equal(iterable):
159
+ """
160
+ Returns ``True`` if all the elements are equal to each other.
161
+
162
+ >>> all_equal('aaaa')
163
+ True
164
+ >>> all_equal('aaab')
165
+ False
166
+
167
+ """
168
+ g = groupby(iterable)
169
+ return next(g, True) and not next(g, False)
170
+
171
+
172
+ def quantify(iterable, pred=bool):
173
+ """Return the how many times the predicate is true.
174
+
175
+ >>> quantify([True, False, True])
176
+ 2
177
+
178
+ """
179
+ return sum(map(pred, iterable))
180
+
181
+
182
+ def pad_none(iterable):
183
+ """Returns the sequence of elements and then returns ``None`` indefinitely.
184
+
185
+ >>> take(5, pad_none(range(3)))
186
+ [0, 1, 2, None, None]
187
+
188
+ Useful for emulating the behavior of the built-in :func:`map` function.
189
+
190
+ See also :func:`padded`.
191
+
192
+ """
193
+ return chain(iterable, repeat(None))
194
+
195
+
196
+ padnone = pad_none
197
+
198
+
199
+ def ncycles(iterable, n):
200
+ """Returns the sequence elements *n* times
201
+
202
+ >>> list(ncycles(["a", "b"], 3))
203
+ ['a', 'b', 'a', 'b', 'a', 'b']
204
+
205
+ """
206
+ return chain.from_iterable(repeat(tuple(iterable), n))
207
+
208
+
209
+ def dotproduct(vec1, vec2):
210
+ """Returns the dot product of the two iterables.
211
+
212
+ >>> dotproduct([10, 10], [20, 20])
213
+ 400
214
+
215
+ """
216
+ return sum(map(operator.mul, vec1, vec2))
217
+
218
+
219
+ def flatten(listOfLists):
220
+ """Return an iterator flattening one level of nesting in a list of lists.
221
+
222
+ >>> list(flatten([[0, 1], [2, 3]]))
223
+ [0, 1, 2, 3]
224
+
225
+ See also :func:`collapse`, which can flatten multiple levels of nesting.
226
+
227
+ """
228
+ return chain.from_iterable(listOfLists)
229
+
230
+
231
+ def repeatfunc(func, times=None, *args):
232
+ """Call *func* with *args* repeatedly, returning an iterable over the
233
+ results.
234
+
235
+ If *times* is specified, the iterable will terminate after that many
236
+ repetitions:
237
+
238
+ >>> from operator import add
239
+ >>> times = 4
240
+ >>> args = 3, 5
241
+ >>> list(repeatfunc(add, times, *args))
242
+ [8, 8, 8, 8]
243
+
244
+ If *times* is ``None`` the iterable will not terminate:
245
+
246
+ >>> from random import randrange
247
+ >>> times = None
248
+ >>> args = 1, 11
249
+ >>> take(6, repeatfunc(randrange, times, *args)) # doctest:+SKIP
250
+ [2, 4, 8, 1, 8, 4]
251
+
252
+ """
253
+ if times is None:
254
+ return starmap(func, repeat(args))
255
+ return starmap(func, repeat(args, times))
256
+
257
+
258
+ def _pairwise(iterable):
259
+ """Returns an iterator of paired items, overlapping, from the original
260
+
261
+ >>> take(4, pairwise(count()))
262
+ [(0, 1), (1, 2), (2, 3), (3, 4)]
263
+
264
+ On Python 3.10 and above, this is an alias for :func:`itertools.pairwise`.
265
+
266
+ """
267
+ a, b = tee(iterable)
268
+ next(b, None)
269
+ yield from zip(a, b)
270
+
271
+
272
+ try:
273
+ from itertools import pairwise as itertools_pairwise
274
+ except ImportError:
275
+ pairwise = _pairwise
276
+ else:
277
+
278
+ def pairwise(iterable):
279
+ yield from itertools_pairwise(iterable)
280
+
281
+ pairwise.__doc__ = _pairwise.__doc__
282
+
283
+
284
+ def grouper(iterable, n, fillvalue=None):
285
+ """Collect data into fixed-length chunks or blocks.
286
+
287
+ >>> list(grouper('ABCDEFG', 3, 'x'))
288
+ [('A', 'B', 'C'), ('D', 'E', 'F'), ('G', 'x', 'x')]
289
+
290
+ """
291
+ if isinstance(iterable, int):
292
+ warnings.warn(
293
+ "grouper expects iterable as first parameter", DeprecationWarning
294
+ )
295
+ n, iterable = iterable, n
296
+ args = [iter(iterable)] * n
297
+ return zip_longest(fillvalue=fillvalue, *args)
298
+
299
+
300
+ def roundrobin(*iterables):
301
+ """Yields an item from each iterable, alternating between them.
302
+
303
+ >>> list(roundrobin('ABC', 'D', 'EF'))
304
+ ['A', 'D', 'E', 'B', 'F', 'C']
305
+
306
+ This function produces the same output as :func:`interleave_longest`, but
307
+ may perform better for some inputs (in particular when the number of
308
+ iterables is small).
309
+
310
+ """
311
+ # Recipe credited to George Sakkis
312
+ pending = len(iterables)
313
+ nexts = cycle(iter(it).__next__ for it in iterables)
314
+ while pending:
315
+ try:
316
+ for next in nexts:
317
+ yield next()
318
+ except StopIteration:
319
+ pending -= 1
320
+ nexts = cycle(islice(nexts, pending))
321
+
322
+
323
+ def partition(pred, iterable):
324
+ """
325
+ Returns a 2-tuple of iterables derived from the input iterable.
326
+ The first yields the items that have ``pred(item) == False``.
327
+ The second yields the items that have ``pred(item) == True``.
328
+
329
+ >>> is_odd = lambda x: x % 2 != 0
330
+ >>> iterable = range(10)
331
+ >>> even_items, odd_items = partition(is_odd, iterable)
332
+ >>> list(even_items), list(odd_items)
333
+ ([0, 2, 4, 6, 8], [1, 3, 5, 7, 9])
334
+
335
+ If *pred* is None, :func:`bool` is used.
336
+
337
+ >>> iterable = [0, 1, False, True, '', ' ']
338
+ >>> false_items, true_items = partition(None, iterable)
339
+ >>> list(false_items), list(true_items)
340
+ ([0, False, ''], [1, True, ' '])
341
+
342
+ """
343
+ if pred is None:
344
+ pred = bool
345
+
346
+ evaluations = ((pred(x), x) for x in iterable)
347
+ t1, t2 = tee(evaluations)
348
+ return (
349
+ (x for (cond, x) in t1 if not cond),
350
+ (x for (cond, x) in t2 if cond),
351
+ )
352
+
353
+
354
+ def powerset(iterable):
355
+ """Yields all possible subsets of the iterable.
356
+
357
+ >>> list(powerset([1, 2, 3]))
358
+ [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
359
+
360
+ :func:`powerset` will operate on iterables that aren't :class:`set`
361
+ instances, so repeated elements in the input will produce repeated elements
362
+ in the output. Use :func:`unique_everseen` on the input to avoid generating
363
+ duplicates:
364
+
365
+ >>> seq = [1, 1, 0]
366
+ >>> list(powerset(seq))
367
+ [(), (1,), (1,), (0,), (1, 1), (1, 0), (1, 0), (1, 1, 0)]
368
+ >>> from more_itertools import unique_everseen
369
+ >>> list(powerset(unique_everseen(seq)))
370
+ [(), (1,), (0,), (1, 0)]
371
+
372
+ """
373
+ s = list(iterable)
374
+ return chain.from_iterable(combinations(s, r) for r in range(len(s) + 1))
375
+
376
+
377
+ def unique_everseen(iterable, key=None):
378
+ """
379
+ Yield unique elements, preserving order.
380
+
381
+ >>> list(unique_everseen('AAAABBBCCDAABBB'))
382
+ ['A', 'B', 'C', 'D']
383
+ >>> list(unique_everseen('ABBCcAD', str.lower))
384
+ ['A', 'B', 'C', 'D']
385
+
386
+ Sequences with a mix of hashable and unhashable items can be used.
387
+ The function will be slower (i.e., `O(n^2)`) for unhashable items.
388
+
389
+ Remember that ``list`` objects are unhashable - you can use the *key*
390
+ parameter to transform the list to a tuple (which is hashable) to
391
+ avoid a slowdown.
392
+
393
+ >>> iterable = ([1, 2], [2, 3], [1, 2])
394
+ >>> list(unique_everseen(iterable)) # Slow
395
+ [[1, 2], [2, 3]]
396
+ >>> list(unique_everseen(iterable, key=tuple)) # Faster
397
+ [[1, 2], [2, 3]]
398
+
399
+ Similary, you may want to convert unhashable ``set`` objects with
400
+ ``key=frozenset``. For ``dict`` objects,
401
+ ``key=lambda x: frozenset(x.items())`` can be used.
402
+
403
+ """
404
+ seenset = set()
405
+ seenset_add = seenset.add
406
+ seenlist = []
407
+ seenlist_add = seenlist.append
408
+ use_key = key is not None
409
+
410
+ for element in iterable:
411
+ k = key(element) if use_key else element
412
+ try:
413
+ if k not in seenset:
414
+ seenset_add(k)
415
+ yield element
416
+ except TypeError:
417
+ if k not in seenlist:
418
+ seenlist_add(k)
419
+ yield element
420
+
421
+
422
+ def unique_justseen(iterable, key=None):
423
+ """Yields elements in order, ignoring serial duplicates
424
+
425
+ >>> list(unique_justseen('AAAABBBCCDAABBB'))
426
+ ['A', 'B', 'C', 'D', 'A', 'B']
427
+ >>> list(unique_justseen('ABBCcAD', str.lower))
428
+ ['A', 'B', 'C', 'A', 'D']
429
+
430
+ """
431
+ return map(next, map(operator.itemgetter(1), groupby(iterable, key)))
432
+
433
+
434
+ def iter_except(func, exception, first=None):
435
+ """Yields results from a function repeatedly until an exception is raised.
436
+
437
+ Converts a call-until-exception interface to an iterator interface.
438
+ Like ``iter(func, sentinel)``, but uses an exception instead of a sentinel
439
+ to end the loop.
440
+
441
+ >>> l = [0, 1, 2]
442
+ >>> list(iter_except(l.pop, IndexError))
443
+ [2, 1, 0]
444
+
445
+ """
446
+ try:
447
+ if first is not None:
448
+ yield first()
449
+ while 1:
450
+ yield func()
451
+ except exception:
452
+ pass
453
+
454
+
455
+ def first_true(iterable, default=None, pred=None):
456
+ """
457
+ Returns the first true value in the iterable.
458
+
459
+ If no true value is found, returns *default*
460
+
461
+ If *pred* is not None, returns the first item for which
462
+ ``pred(item) == True`` .
463
+
464
+ >>> first_true(range(10))
465
+ 1
466
+ >>> first_true(range(10), pred=lambda x: x > 5)
467
+ 6
468
+ >>> first_true(range(10), default='missing', pred=lambda x: x > 9)
469
+ 'missing'
470
+
471
+ """
472
+ return next(filter(pred, iterable), default)
473
+
474
+
475
+ def random_product(*args, repeat=1):
476
+ """Draw an item at random from each of the input iterables.
477
+
478
+ >>> random_product('abc', range(4), 'XYZ') # doctest:+SKIP
479
+ ('c', 3, 'Z')
480
+
481
+ If *repeat* is provided as a keyword argument, that many items will be
482
+ drawn from each iterable.
483
+
484
+ >>> random_product('abcd', range(4), repeat=2) # doctest:+SKIP
485
+ ('a', 2, 'd', 3)
486
+
487
+ This equivalent to taking a random selection from
488
+ ``itertools.product(*args, **kwarg)``.
489
+
490
+ """
491
+ pools = [tuple(pool) for pool in args] * repeat
492
+ return tuple(choice(pool) for pool in pools)
493
+
494
+
495
+ def random_permutation(iterable, r=None):
496
+ """Return a random *r* length permutation of the elements in *iterable*.
497
+
498
+ If *r* is not specified or is ``None``, then *r* defaults to the length of
499
+ *iterable*.
500
+
501
+ >>> random_permutation(range(5)) # doctest:+SKIP
502
+ (3, 4, 0, 1, 2)
503
+
504
+ This equivalent to taking a random selection from
505
+ ``itertools.permutations(iterable, r)``.
506
+
507
+ """
508
+ pool = tuple(iterable)
509
+ r = len(pool) if r is None else r
510
+ return tuple(sample(pool, r))
511
+
512
+
513
+ def random_combination(iterable, r):
514
+ """Return a random *r* length subsequence of the elements in *iterable*.
515
+
516
+ >>> random_combination(range(5), 3) # doctest:+SKIP
517
+ (2, 3, 4)
518
+
519
+ This equivalent to taking a random selection from
520
+ ``itertools.combinations(iterable, r)``.
521
+
522
+ """
523
+ pool = tuple(iterable)
524
+ n = len(pool)
525
+ indices = sorted(sample(range(n), r))
526
+ return tuple(pool[i] for i in indices)
527
+
528
+
529
+ def random_combination_with_replacement(iterable, r):
530
+ """Return a random *r* length subsequence of elements in *iterable*,
531
+ allowing individual elements to be repeated.
532
+
533
+ >>> random_combination_with_replacement(range(3), 5) # doctest:+SKIP
534
+ (0, 0, 1, 2, 2)
535
+
536
+ This equivalent to taking a random selection from
537
+ ``itertools.combinations_with_replacement(iterable, r)``.
538
+
539
+ """
540
+ pool = tuple(iterable)
541
+ n = len(pool)
542
+ indices = sorted(randrange(n) for i in range(r))
543
+ return tuple(pool[i] for i in indices)
544
+
545
+
546
+ def nth_combination(iterable, r, index):
547
+ """Equivalent to ``list(combinations(iterable, r))[index]``.
548
+
549
+ The subsequences of *iterable* that are of length *r* can be ordered
550
+ lexicographically. :func:`nth_combination` computes the subsequence at
551
+ sort position *index* directly, without computing the previous
552
+ subsequences.
553
+
554
+ >>> nth_combination(range(5), 3, 5)
555
+ (0, 3, 4)
556
+
557
+ ``ValueError`` will be raised If *r* is negative or greater than the length
558
+ of *iterable*.
559
+ ``IndexError`` will be raised if the given *index* is invalid.
560
+ """
561
+ pool = tuple(iterable)
562
+ n = len(pool)
563
+ if (r < 0) or (r > n):
564
+ raise ValueError
565
+
566
+ c = 1
567
+ k = min(r, n - r)
568
+ for i in range(1, k + 1):
569
+ c = c * (n - k + i) // i
570
+
571
+ if index < 0:
572
+ index += c
573
+
574
+ if (index < 0) or (index >= c):
575
+ raise IndexError
576
+
577
+ result = []
578
+ while r:
579
+ c, n, r = c * r // n, n - 1, r - 1
580
+ while index >= c:
581
+ index -= c
582
+ c, n = c * (n - r) // n, n - 1
583
+ result.append(pool[-1 - n])
584
+
585
+ return tuple(result)
586
+
587
+
588
+ def prepend(value, iterator):
589
+ """Yield *value*, followed by the elements in *iterator*.
590
+
591
+ >>> value = '0'
592
+ >>> iterator = ['1', '2', '3']
593
+ >>> list(prepend(value, iterator))
594
+ ['0', '1', '2', '3']
595
+
596
+ To prepend multiple values, see :func:`itertools.chain`
597
+ or :func:`value_chain`.
598
+
599
+ """
600
+ return chain([value], iterator)
601
+
602
+
603
+ def convolve(signal, kernel):
604
+ """Convolve the iterable *signal* with the iterable *kernel*.
605
+
606
+ >>> signal = (1, 2, 3, 4, 5)
607
+ >>> kernel = [3, 2, 1]
608
+ >>> list(convolve(signal, kernel))
609
+ [3, 8, 14, 20, 26, 14, 5]
610
+
611
+ Note: the input arguments are not interchangeable, as the *kernel*
612
+ is immediately consumed and stored.
613
+
614
+ """
615
+ kernel = tuple(kernel)[::-1]
616
+ n = len(kernel)
617
+ window = deque([0], maxlen=n) * n
618
+ for x in chain(signal, repeat(0, n - 1)):
619
+ window.append(x)
620
+ yield sum(map(operator.mul, kernel, window))
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/ordered_set.py ADDED
@@ -0,0 +1,488 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ An OrderedSet is a custom MutableSet that remembers its order, so that every
3
+ entry has an index that can be looked up.
4
+
5
+ Based on a recipe originally posted to ActiveState Recipes by Raymond Hettiger,
6
+ and released under the MIT license.
7
+ """
8
+ import itertools as it
9
+ from collections import deque
10
+
11
+ try:
12
+ # Python 3
13
+ from collections.abc import MutableSet, Sequence
14
+ except ImportError:
15
+ # Python 2.7
16
+ from collections import MutableSet, Sequence
17
+
18
+ SLICE_ALL = slice(None)
19
+ __version__ = "3.1"
20
+
21
+
22
+ def is_iterable(obj):
23
+ """
24
+ Are we being asked to look up a list of things, instead of a single thing?
25
+ We check for the `__iter__` attribute so that this can cover types that
26
+ don't have to be known by this module, such as NumPy arrays.
27
+
28
+ Strings, however, should be considered as atomic values to look up, not
29
+ iterables. The same goes for tuples, since they are immutable and therefore
30
+ valid entries.
31
+
32
+ We don't need to check for the Python 2 `unicode` type, because it doesn't
33
+ have an `__iter__` attribute anyway.
34
+ """
35
+ return (
36
+ hasattr(obj, "__iter__")
37
+ and not isinstance(obj, str)
38
+ and not isinstance(obj, tuple)
39
+ )
40
+
41
+
42
+ class OrderedSet(MutableSet, Sequence):
43
+ """
44
+ An OrderedSet is a custom MutableSet that remembers its order, so that
45
+ every entry has an index that can be looked up.
46
+
47
+ Example:
48
+ >>> OrderedSet([1, 1, 2, 3, 2])
49
+ OrderedSet([1, 2, 3])
50
+ """
51
+
52
+ def __init__(self, iterable=None):
53
+ self.items = []
54
+ self.map = {}
55
+ if iterable is not None:
56
+ self |= iterable
57
+
58
+ def __len__(self):
59
+ """
60
+ Returns the number of unique elements in the ordered set
61
+
62
+ Example:
63
+ >>> len(OrderedSet([]))
64
+ 0
65
+ >>> len(OrderedSet([1, 2]))
66
+ 2
67
+ """
68
+ return len(self.items)
69
+
70
+ def __getitem__(self, index):
71
+ """
72
+ Get the item at a given index.
73
+
74
+ If `index` is a slice, you will get back that slice of items, as a
75
+ new OrderedSet.
76
+
77
+ If `index` is a list or a similar iterable, you'll get a list of
78
+ items corresponding to those indices. This is similar to NumPy's
79
+ "fancy indexing". The result is not an OrderedSet because you may ask
80
+ for duplicate indices, and the number of elements returned should be
81
+ the number of elements asked for.
82
+
83
+ Example:
84
+ >>> oset = OrderedSet([1, 2, 3])
85
+ >>> oset[1]
86
+ 2
87
+ """
88
+ if isinstance(index, slice) and index == SLICE_ALL:
89
+ return self.copy()
90
+ elif is_iterable(index):
91
+ return [self.items[i] for i in index]
92
+ elif hasattr(index, "__index__") or isinstance(index, slice):
93
+ result = self.items[index]
94
+ if isinstance(result, list):
95
+ return self.__class__(result)
96
+ else:
97
+ return result
98
+ else:
99
+ raise TypeError("Don't know how to index an OrderedSet by %r" % index)
100
+
101
+ def copy(self):
102
+ """
103
+ Return a shallow copy of this object.
104
+
105
+ Example:
106
+ >>> this = OrderedSet([1, 2, 3])
107
+ >>> other = this.copy()
108
+ >>> this == other
109
+ True
110
+ >>> this is other
111
+ False
112
+ """
113
+ return self.__class__(self)
114
+
115
+ def __getstate__(self):
116
+ if len(self) == 0:
117
+ # The state can't be an empty list.
118
+ # We need to return a truthy value, or else __setstate__ won't be run.
119
+ #
120
+ # This could have been done more gracefully by always putting the state
121
+ # in a tuple, but this way is backwards- and forwards- compatible with
122
+ # previous versions of OrderedSet.
123
+ return (None,)
124
+ else:
125
+ return list(self)
126
+
127
+ def __setstate__(self, state):
128
+ if state == (None,):
129
+ self.__init__([])
130
+ else:
131
+ self.__init__(state)
132
+
133
+ def __contains__(self, key):
134
+ """
135
+ Test if the item is in this ordered set
136
+
137
+ Example:
138
+ >>> 1 in OrderedSet([1, 3, 2])
139
+ True
140
+ >>> 5 in OrderedSet([1, 3, 2])
141
+ False
142
+ """
143
+ return key in self.map
144
+
145
+ def add(self, key):
146
+ """
147
+ Add `key` as an item to this OrderedSet, then return its index.
148
+
149
+ If `key` is already in the OrderedSet, return the index it already
150
+ had.
151
+
152
+ Example:
153
+ >>> oset = OrderedSet()
154
+ >>> oset.append(3)
155
+ 0
156
+ >>> print(oset)
157
+ OrderedSet([3])
158
+ """
159
+ if key not in self.map:
160
+ self.map[key] = len(self.items)
161
+ self.items.append(key)
162
+ return self.map[key]
163
+
164
+ append = add
165
+
166
+ def update(self, sequence):
167
+ """
168
+ Update the set with the given iterable sequence, then return the index
169
+ of the last element inserted.
170
+
171
+ Example:
172
+ >>> oset = OrderedSet([1, 2, 3])
173
+ >>> oset.update([3, 1, 5, 1, 4])
174
+ 4
175
+ >>> print(oset)
176
+ OrderedSet([1, 2, 3, 5, 4])
177
+ """
178
+ item_index = None
179
+ try:
180
+ for item in sequence:
181
+ item_index = self.add(item)
182
+ except TypeError:
183
+ raise ValueError(
184
+ "Argument needs to be an iterable, got %s" % type(sequence)
185
+ )
186
+ return item_index
187
+
188
+ def index(self, key):
189
+ """
190
+ Get the index of a given entry, raising an IndexError if it's not
191
+ present.
192
+
193
+ `key` can be an iterable of entries that is not a string, in which case
194
+ this returns a list of indices.
195
+
196
+ Example:
197
+ >>> oset = OrderedSet([1, 2, 3])
198
+ >>> oset.index(2)
199
+ 1
200
+ """
201
+ if is_iterable(key):
202
+ return [self.index(subkey) for subkey in key]
203
+ return self.map[key]
204
+
205
+ # Provide some compatibility with pd.Index
206
+ get_loc = index
207
+ get_indexer = index
208
+
209
+ def pop(self):
210
+ """
211
+ Remove and return the last element from the set.
212
+
213
+ Raises KeyError if the set is empty.
214
+
215
+ Example:
216
+ >>> oset = OrderedSet([1, 2, 3])
217
+ >>> oset.pop()
218
+ 3
219
+ """
220
+ if not self.items:
221
+ raise KeyError("Set is empty")
222
+
223
+ elem = self.items[-1]
224
+ del self.items[-1]
225
+ del self.map[elem]
226
+ return elem
227
+
228
+ def discard(self, key):
229
+ """
230
+ Remove an element. Do not raise an exception if absent.
231
+
232
+ The MutableSet mixin uses this to implement the .remove() method, which
233
+ *does* raise an error when asked to remove a non-existent item.
234
+
235
+ Example:
236
+ >>> oset = OrderedSet([1, 2, 3])
237
+ >>> oset.discard(2)
238
+ >>> print(oset)
239
+ OrderedSet([1, 3])
240
+ >>> oset.discard(2)
241
+ >>> print(oset)
242
+ OrderedSet([1, 3])
243
+ """
244
+ if key in self:
245
+ i = self.map[key]
246
+ del self.items[i]
247
+ del self.map[key]
248
+ for k, v in self.map.items():
249
+ if v >= i:
250
+ self.map[k] = v - 1
251
+
252
+ def clear(self):
253
+ """
254
+ Remove all items from this OrderedSet.
255
+ """
256
+ del self.items[:]
257
+ self.map.clear()
258
+
259
+ def __iter__(self):
260
+ """
261
+ Example:
262
+ >>> list(iter(OrderedSet([1, 2, 3])))
263
+ [1, 2, 3]
264
+ """
265
+ return iter(self.items)
266
+
267
+ def __reversed__(self):
268
+ """
269
+ Example:
270
+ >>> list(reversed(OrderedSet([1, 2, 3])))
271
+ [3, 2, 1]
272
+ """
273
+ return reversed(self.items)
274
+
275
+ def __repr__(self):
276
+ if not self:
277
+ return "%s()" % (self.__class__.__name__,)
278
+ return "%s(%r)" % (self.__class__.__name__, list(self))
279
+
280
+ def __eq__(self, other):
281
+ """
282
+ Returns true if the containers have the same items. If `other` is a
283
+ Sequence, then order is checked, otherwise it is ignored.
284
+
285
+ Example:
286
+ >>> oset = OrderedSet([1, 3, 2])
287
+ >>> oset == [1, 3, 2]
288
+ True
289
+ >>> oset == [1, 2, 3]
290
+ False
291
+ >>> oset == [2, 3]
292
+ False
293
+ >>> oset == OrderedSet([3, 2, 1])
294
+ False
295
+ """
296
+ # In Python 2 deque is not a Sequence, so treat it as one for
297
+ # consistent behavior with Python 3.
298
+ if isinstance(other, (Sequence, deque)):
299
+ # Check that this OrderedSet contains the same elements, in the
300
+ # same order, as the other object.
301
+ return list(self) == list(other)
302
+ try:
303
+ other_as_set = set(other)
304
+ except TypeError:
305
+ # If `other` can't be converted into a set, it's not equal.
306
+ return False
307
+ else:
308
+ return set(self) == other_as_set
309
+
310
+ def union(self, *sets):
311
+ """
312
+ Combines all unique items.
313
+ Each items order is defined by its first appearance.
314
+
315
+ Example:
316
+ >>> oset = OrderedSet.union(OrderedSet([3, 1, 4, 1, 5]), [1, 3], [2, 0])
317
+ >>> print(oset)
318
+ OrderedSet([3, 1, 4, 5, 2, 0])
319
+ >>> oset.union([8, 9])
320
+ OrderedSet([3, 1, 4, 5, 2, 0, 8, 9])
321
+ >>> oset | {10}
322
+ OrderedSet([3, 1, 4, 5, 2, 0, 10])
323
+ """
324
+ cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet
325
+ containers = map(list, it.chain([self], sets))
326
+ items = it.chain.from_iterable(containers)
327
+ return cls(items)
328
+
329
+ def __and__(self, other):
330
+ # the parent implementation of this is backwards
331
+ return self.intersection(other)
332
+
333
+ def intersection(self, *sets):
334
+ """
335
+ Returns elements in common between all sets. Order is defined only
336
+ by the first set.
337
+
338
+ Example:
339
+ >>> oset = OrderedSet.intersection(OrderedSet([0, 1, 2, 3]), [1, 2, 3])
340
+ >>> print(oset)
341
+ OrderedSet([1, 2, 3])
342
+ >>> oset.intersection([2, 4, 5], [1, 2, 3, 4])
343
+ OrderedSet([2])
344
+ >>> oset.intersection()
345
+ OrderedSet([1, 2, 3])
346
+ """
347
+ cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet
348
+ if sets:
349
+ common = set.intersection(*map(set, sets))
350
+ items = (item for item in self if item in common)
351
+ else:
352
+ items = self
353
+ return cls(items)
354
+
355
+ def difference(self, *sets):
356
+ """
357
+ Returns all elements that are in this set but not the others.
358
+
359
+ Example:
360
+ >>> OrderedSet([1, 2, 3]).difference(OrderedSet([2]))
361
+ OrderedSet([1, 3])
362
+ >>> OrderedSet([1, 2, 3]).difference(OrderedSet([2]), OrderedSet([3]))
363
+ OrderedSet([1])
364
+ >>> OrderedSet([1, 2, 3]) - OrderedSet([2])
365
+ OrderedSet([1, 3])
366
+ >>> OrderedSet([1, 2, 3]).difference()
367
+ OrderedSet([1, 2, 3])
368
+ """
369
+ cls = self.__class__
370
+ if sets:
371
+ other = set.union(*map(set, sets))
372
+ items = (item for item in self if item not in other)
373
+ else:
374
+ items = self
375
+ return cls(items)
376
+
377
+ def issubset(self, other):
378
+ """
379
+ Report whether another set contains this set.
380
+
381
+ Example:
382
+ >>> OrderedSet([1, 2, 3]).issubset({1, 2})
383
+ False
384
+ >>> OrderedSet([1, 2, 3]).issubset({1, 2, 3, 4})
385
+ True
386
+ >>> OrderedSet([1, 2, 3]).issubset({1, 4, 3, 5})
387
+ False
388
+ """
389
+ if len(self) > len(other): # Fast check for obvious cases
390
+ return False
391
+ return all(item in other for item in self)
392
+
393
+ def issuperset(self, other):
394
+ """
395
+ Report whether this set contains another set.
396
+
397
+ Example:
398
+ >>> OrderedSet([1, 2]).issuperset([1, 2, 3])
399
+ False
400
+ >>> OrderedSet([1, 2, 3, 4]).issuperset({1, 2, 3})
401
+ True
402
+ >>> OrderedSet([1, 4, 3, 5]).issuperset({1, 2, 3})
403
+ False
404
+ """
405
+ if len(self) < len(other): # Fast check for obvious cases
406
+ return False
407
+ return all(item in self for item in other)
408
+
409
+ def symmetric_difference(self, other):
410
+ """
411
+ Return the symmetric difference of two OrderedSets as a new set.
412
+ That is, the new set will contain all elements that are in exactly
413
+ one of the sets.
414
+
415
+ Their order will be preserved, with elements from `self` preceding
416
+ elements from `other`.
417
+
418
+ Example:
419
+ >>> this = OrderedSet([1, 4, 3, 5, 7])
420
+ >>> other = OrderedSet([9, 7, 1, 3, 2])
421
+ >>> this.symmetric_difference(other)
422
+ OrderedSet([4, 5, 9, 2])
423
+ """
424
+ cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet
425
+ diff1 = cls(self).difference(other)
426
+ diff2 = cls(other).difference(self)
427
+ return diff1.union(diff2)
428
+
429
+ def _update_items(self, items):
430
+ """
431
+ Replace the 'items' list of this OrderedSet with a new one, updating
432
+ self.map accordingly.
433
+ """
434
+ self.items = items
435
+ self.map = {item: idx for (idx, item) in enumerate(items)}
436
+
437
+ def difference_update(self, *sets):
438
+ """
439
+ Update this OrderedSet to remove items from one or more other sets.
440
+
441
+ Example:
442
+ >>> this = OrderedSet([1, 2, 3])
443
+ >>> this.difference_update(OrderedSet([2, 4]))
444
+ >>> print(this)
445
+ OrderedSet([1, 3])
446
+
447
+ >>> this = OrderedSet([1, 2, 3, 4, 5])
448
+ >>> this.difference_update(OrderedSet([2, 4]), OrderedSet([1, 4, 6]))
449
+ >>> print(this)
450
+ OrderedSet([3, 5])
451
+ """
452
+ items_to_remove = set()
453
+ for other in sets:
454
+ items_to_remove |= set(other)
455
+ self._update_items([item for item in self.items if item not in items_to_remove])
456
+
457
+ def intersection_update(self, other):
458
+ """
459
+ Update this OrderedSet to keep only items in another set, preserving
460
+ their order in this set.
461
+
462
+ Example:
463
+ >>> this = OrderedSet([1, 4, 3, 5, 7])
464
+ >>> other = OrderedSet([9, 7, 1, 3, 2])
465
+ >>> this.intersection_update(other)
466
+ >>> print(this)
467
+ OrderedSet([1, 3, 7])
468
+ """
469
+ other = set(other)
470
+ self._update_items([item for item in self.items if item in other])
471
+
472
+ def symmetric_difference_update(self, other):
473
+ """
474
+ Update this OrderedSet to remove items from another set, then
475
+ add items from the other set that were not present in this set.
476
+
477
+ Example:
478
+ >>> this = OrderedSet([1, 4, 3, 5, 7])
479
+ >>> other = OrderedSet([9, 7, 1, 3, 2])
480
+ >>> this.symmetric_difference_update(other)
481
+ >>> print(this)
482
+ OrderedSet([4, 5, 9, 2])
483
+ """
484
+ items_to_add = [item for item in other if item not in self]
485
+ items_to_remove = set(other)
486
+ self._update_items(
487
+ [item for item in self.items if item not in items_to_remove] + items_to_add
488
+ )
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__about__.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+ from __future__ import absolute_import, division, print_function
5
+
6
+ __all__ = [
7
+ "__title__",
8
+ "__summary__",
9
+ "__uri__",
10
+ "__version__",
11
+ "__author__",
12
+ "__email__",
13
+ "__license__",
14
+ "__copyright__",
15
+ ]
16
+
17
+ __title__ = "packaging"
18
+ __summary__ = "Core utilities for Python packages"
19
+ __uri__ = "https://github.com/pypa/packaging"
20
+
21
+ __version__ = "20.4"
22
+
23
+ __author__ = "Donald Stufft and individual contributors"
24
+ __email__ = "donald@stufft.io"
25
+
26
+ __license__ = "BSD-2-Clause or Apache-2.0"
27
+ __copyright__ = "Copyright 2014-2019 %s" % __author__
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+ from __future__ import absolute_import, division, print_function
5
+
6
+ from .__about__ import (
7
+ __author__,
8
+ __copyright__,
9
+ __email__,
10
+ __license__,
11
+ __summary__,
12
+ __title__,
13
+ __uri__,
14
+ __version__,
15
+ )
16
+
17
+ __all__ = [
18
+ "__title__",
19
+ "__summary__",
20
+ "__uri__",
21
+ "__version__",
22
+ "__author__",
23
+ "__email__",
24
+ "__license__",
25
+ "__copyright__",
26
+ ]
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_compat.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+ from __future__ import absolute_import, division, print_function
5
+
6
+ import sys
7
+
8
+ from ._typing import TYPE_CHECKING
9
+
10
+ if TYPE_CHECKING: # pragma: no cover
11
+ from typing import Any, Dict, Tuple, Type
12
+
13
+
14
+ PY2 = sys.version_info[0] == 2
15
+ PY3 = sys.version_info[0] == 3
16
+
17
+ # flake8: noqa
18
+
19
+ if PY3:
20
+ string_types = (str,)
21
+ else:
22
+ string_types = (basestring,)
23
+
24
+
25
+ def with_metaclass(meta, *bases):
26
+ # type: (Type[Any], Tuple[Type[Any], ...]) -> Any
27
+ """
28
+ Create a base class with a metaclass.
29
+ """
30
+ # This requires a bit of explanation: the basic idea is to make a dummy
31
+ # metaclass for one level of class instantiation that replaces itself with
32
+ # the actual metaclass.
33
+ class metaclass(meta): # type: ignore
34
+ def __new__(cls, name, this_bases, d):
35
+ # type: (Type[Any], str, Tuple[Any], Dict[Any, Any]) -> Any
36
+ return meta(name, bases, d)
37
+
38
+ return type.__new__(metaclass, "temporary_class", (), {})
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_structures.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+ from __future__ import absolute_import, division, print_function
5
+
6
+
7
+ class InfinityType(object):
8
+ def __repr__(self):
9
+ # type: () -> str
10
+ return "Infinity"
11
+
12
+ def __hash__(self):
13
+ # type: () -> int
14
+ return hash(repr(self))
15
+
16
+ def __lt__(self, other):
17
+ # type: (object) -> bool
18
+ return False
19
+
20
+ def __le__(self, other):
21
+ # type: (object) -> bool
22
+ return False
23
+
24
+ def __eq__(self, other):
25
+ # type: (object) -> bool
26
+ return isinstance(other, self.__class__)
27
+
28
+ def __ne__(self, other):
29
+ # type: (object) -> bool
30
+ return not isinstance(other, self.__class__)
31
+
32
+ def __gt__(self, other):
33
+ # type: (object) -> bool
34
+ return True
35
+
36
+ def __ge__(self, other):
37
+ # type: (object) -> bool
38
+ return True
39
+
40
+ def __neg__(self):
41
+ # type: (object) -> NegativeInfinityType
42
+ return NegativeInfinity
43
+
44
+
45
+ Infinity = InfinityType()
46
+
47
+
48
+ class NegativeInfinityType(object):
49
+ def __repr__(self):
50
+ # type: () -> str
51
+ return "-Infinity"
52
+
53
+ def __hash__(self):
54
+ # type: () -> int
55
+ return hash(repr(self))
56
+
57
+ def __lt__(self, other):
58
+ # type: (object) -> bool
59
+ return True
60
+
61
+ def __le__(self, other):
62
+ # type: (object) -> bool
63
+ return True
64
+
65
+ def __eq__(self, other):
66
+ # type: (object) -> bool
67
+ return isinstance(other, self.__class__)
68
+
69
+ def __ne__(self, other):
70
+ # type: (object) -> bool
71
+ return not isinstance(other, self.__class__)
72
+
73
+ def __gt__(self, other):
74
+ # type: (object) -> bool
75
+ return False
76
+
77
+ def __ge__(self, other):
78
+ # type: (object) -> bool
79
+ return False
80
+
81
+ def __neg__(self):
82
+ # type: (object) -> InfinityType
83
+ return Infinity
84
+
85
+
86
+ NegativeInfinity = NegativeInfinityType()
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_typing.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """For neatly implementing static typing in packaging.
2
+
3
+ `mypy` - the static type analysis tool we use - uses the `typing` module, which
4
+ provides core functionality fundamental to mypy's functioning.
5
+
6
+ Generally, `typing` would be imported at runtime and used in that fashion -
7
+ it acts as a no-op at runtime and does not have any run-time overhead by
8
+ design.
9
+
10
+ As it turns out, `typing` is not vendorable - it uses separate sources for
11
+ Python 2/Python 3. Thus, this codebase can not expect it to be present.
12
+ To work around this, mypy allows the typing import to be behind a False-y
13
+ optional to prevent it from running at runtime and type-comments can be used
14
+ to remove the need for the types to be accessible directly during runtime.
15
+
16
+ This module provides the False-y guard in a nicely named fashion so that a
17
+ curious maintainer can reach here to read this.
18
+
19
+ In packaging, all static-typing related imports should be guarded as follows:
20
+
21
+ from packaging._typing import TYPE_CHECKING
22
+
23
+ if TYPE_CHECKING:
24
+ from typing import ...
25
+
26
+ Ref: https://github.com/python/mypy/issues/3216
27
+ """
28
+
29
+ __all__ = ["TYPE_CHECKING", "cast"]
30
+
31
+ # The TYPE_CHECKING constant defined by the typing module is False at runtime
32
+ # but True while type checking.
33
+ if False: # pragma: no cover
34
+ from typing import TYPE_CHECKING
35
+ else:
36
+ TYPE_CHECKING = False
37
+
38
+ # typing's cast syntax requires calling typing.cast at runtime, but we don't
39
+ # want to import typing at runtime. Here, we inform the type checkers that
40
+ # we're importing `typing.cast` as `cast` and re-implement typing.cast's
41
+ # runtime behavior in a block that is ignored by type checkers.
42
+ if TYPE_CHECKING: # pragma: no cover
43
+ # not executed at runtime
44
+ from typing import cast
45
+ else:
46
+ # executed at runtime
47
+ def cast(type_, value): # noqa
48
+ return value
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/markers.py ADDED
@@ -0,0 +1,328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+ from __future__ import absolute_import, division, print_function
5
+
6
+ import operator
7
+ import os
8
+ import platform
9
+ import sys
10
+
11
+ from setuptools.extern.pyparsing import ParseException, ParseResults, stringStart, stringEnd
12
+ from setuptools.extern.pyparsing import ZeroOrMore, Group, Forward, QuotedString
13
+ from setuptools.extern.pyparsing import Literal as L # noqa
14
+
15
+ from ._compat import string_types
16
+ from ._typing import TYPE_CHECKING
17
+ from .specifiers import Specifier, InvalidSpecifier
18
+
19
+ if TYPE_CHECKING: # pragma: no cover
20
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
21
+
22
+ Operator = Callable[[str, str], bool]
23
+
24
+
25
+ __all__ = [
26
+ "InvalidMarker",
27
+ "UndefinedComparison",
28
+ "UndefinedEnvironmentName",
29
+ "Marker",
30
+ "default_environment",
31
+ ]
32
+
33
+
34
+ class InvalidMarker(ValueError):
35
+ """
36
+ An invalid marker was found, users should refer to PEP 508.
37
+ """
38
+
39
+
40
+ class UndefinedComparison(ValueError):
41
+ """
42
+ An invalid operation was attempted on a value that doesn't support it.
43
+ """
44
+
45
+
46
+ class UndefinedEnvironmentName(ValueError):
47
+ """
48
+ A name was attempted to be used that does not exist inside of the
49
+ environment.
50
+ """
51
+
52
+
53
+ class Node(object):
54
+ def __init__(self, value):
55
+ # type: (Any) -> None
56
+ self.value = value
57
+
58
+ def __str__(self):
59
+ # type: () -> str
60
+ return str(self.value)
61
+
62
+ def __repr__(self):
63
+ # type: () -> str
64
+ return "<{0}({1!r})>".format(self.__class__.__name__, str(self))
65
+
66
+ def serialize(self):
67
+ # type: () -> str
68
+ raise NotImplementedError
69
+
70
+
71
+ class Variable(Node):
72
+ def serialize(self):
73
+ # type: () -> str
74
+ return str(self)
75
+
76
+
77
+ class Value(Node):
78
+ def serialize(self):
79
+ # type: () -> str
80
+ return '"{0}"'.format(self)
81
+
82
+
83
+ class Op(Node):
84
+ def serialize(self):
85
+ # type: () -> str
86
+ return str(self)
87
+
88
+
89
+ VARIABLE = (
90
+ L("implementation_version")
91
+ | L("platform_python_implementation")
92
+ | L("implementation_name")
93
+ | L("python_full_version")
94
+ | L("platform_release")
95
+ | L("platform_version")
96
+ | L("platform_machine")
97
+ | L("platform_system")
98
+ | L("python_version")
99
+ | L("sys_platform")
100
+ | L("os_name")
101
+ | L("os.name") # PEP-345
102
+ | L("sys.platform") # PEP-345
103
+ | L("platform.version") # PEP-345
104
+ | L("platform.machine") # PEP-345
105
+ | L("platform.python_implementation") # PEP-345
106
+ | L("python_implementation") # undocumented setuptools legacy
107
+ | L("extra") # PEP-508
108
+ )
109
+ ALIASES = {
110
+ "os.name": "os_name",
111
+ "sys.platform": "sys_platform",
112
+ "platform.version": "platform_version",
113
+ "platform.machine": "platform_machine",
114
+ "platform.python_implementation": "platform_python_implementation",
115
+ "python_implementation": "platform_python_implementation",
116
+ }
117
+ VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0])))
118
+
119
+ VERSION_CMP = (
120
+ L("===") | L("==") | L(">=") | L("<=") | L("!=") | L("~=") | L(">") | L("<")
121
+ )
122
+
123
+ MARKER_OP = VERSION_CMP | L("not in") | L("in")
124
+ MARKER_OP.setParseAction(lambda s, l, t: Op(t[0]))
125
+
126
+ MARKER_VALUE = QuotedString("'") | QuotedString('"')
127
+ MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0]))
128
+
129
+ BOOLOP = L("and") | L("or")
130
+
131
+ MARKER_VAR = VARIABLE | MARKER_VALUE
132
+
133
+ MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR)
134
+ MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0]))
135
+
136
+ LPAREN = L("(").suppress()
137
+ RPAREN = L(")").suppress()
138
+
139
+ MARKER_EXPR = Forward()
140
+ MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN)
141
+ MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR)
142
+
143
+ MARKER = stringStart + MARKER_EXPR + stringEnd
144
+
145
+
146
+ def _coerce_parse_result(results):
147
+ # type: (Union[ParseResults, List[Any]]) -> List[Any]
148
+ if isinstance(results, ParseResults):
149
+ return [_coerce_parse_result(i) for i in results]
150
+ else:
151
+ return results
152
+
153
+
154
+ def _format_marker(marker, first=True):
155
+ # type: (Union[List[str], Tuple[Node, ...], str], Optional[bool]) -> str
156
+
157
+ assert isinstance(marker, (list, tuple, string_types))
158
+
159
+ # Sometimes we have a structure like [[...]] which is a single item list
160
+ # where the single item is itself it's own list. In that case we want skip
161
+ # the rest of this function so that we don't get extraneous () on the
162
+ # outside.
163
+ if (
164
+ isinstance(marker, list)
165
+ and len(marker) == 1
166
+ and isinstance(marker[0], (list, tuple))
167
+ ):
168
+ return _format_marker(marker[0])
169
+
170
+ if isinstance(marker, list):
171
+ inner = (_format_marker(m, first=False) for m in marker)
172
+ if first:
173
+ return " ".join(inner)
174
+ else:
175
+ return "(" + " ".join(inner) + ")"
176
+ elif isinstance(marker, tuple):
177
+ return " ".join([m.serialize() for m in marker])
178
+ else:
179
+ return marker
180
+
181
+
182
+ _operators = {
183
+ "in": lambda lhs, rhs: lhs in rhs,
184
+ "not in": lambda lhs, rhs: lhs not in rhs,
185
+ "<": operator.lt,
186
+ "<=": operator.le,
187
+ "==": operator.eq,
188
+ "!=": operator.ne,
189
+ ">=": operator.ge,
190
+ ">": operator.gt,
191
+ } # type: Dict[str, Operator]
192
+
193
+
194
+ def _eval_op(lhs, op, rhs):
195
+ # type: (str, Op, str) -> bool
196
+ try:
197
+ spec = Specifier("".join([op.serialize(), rhs]))
198
+ except InvalidSpecifier:
199
+ pass
200
+ else:
201
+ return spec.contains(lhs)
202
+
203
+ oper = _operators.get(op.serialize()) # type: Optional[Operator]
204
+ if oper is None:
205
+ raise UndefinedComparison(
206
+ "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs)
207
+ )
208
+
209
+ return oper(lhs, rhs)
210
+
211
+
212
+ class Undefined(object):
213
+ pass
214
+
215
+
216
+ _undefined = Undefined()
217
+
218
+
219
+ def _get_env(environment, name):
220
+ # type: (Dict[str, str], str) -> str
221
+ value = environment.get(name, _undefined) # type: Union[str, Undefined]
222
+
223
+ if isinstance(value, Undefined):
224
+ raise UndefinedEnvironmentName(
225
+ "{0!r} does not exist in evaluation environment.".format(name)
226
+ )
227
+
228
+ return value
229
+
230
+
231
+ def _evaluate_markers(markers, environment):
232
+ # type: (List[Any], Dict[str, str]) -> bool
233
+ groups = [[]] # type: List[List[bool]]
234
+
235
+ for marker in markers:
236
+ assert isinstance(marker, (list, tuple, string_types))
237
+
238
+ if isinstance(marker, list):
239
+ groups[-1].append(_evaluate_markers(marker, environment))
240
+ elif isinstance(marker, tuple):
241
+ lhs, op, rhs = marker
242
+
243
+ if isinstance(lhs, Variable):
244
+ lhs_value = _get_env(environment, lhs.value)
245
+ rhs_value = rhs.value
246
+ else:
247
+ lhs_value = lhs.value
248
+ rhs_value = _get_env(environment, rhs.value)
249
+
250
+ groups[-1].append(_eval_op(lhs_value, op, rhs_value))
251
+ else:
252
+ assert marker in ["and", "or"]
253
+ if marker == "or":
254
+ groups.append([])
255
+
256
+ return any(all(item) for item in groups)
257
+
258
+
259
+ def format_full_version(info):
260
+ # type: (sys._version_info) -> str
261
+ version = "{0.major}.{0.minor}.{0.micro}".format(info)
262
+ kind = info.releaselevel
263
+ if kind != "final":
264
+ version += kind[0] + str(info.serial)
265
+ return version
266
+
267
+
268
+ def default_environment():
269
+ # type: () -> Dict[str, str]
270
+ if hasattr(sys, "implementation"):
271
+ # Ignoring the `sys.implementation` reference for type checking due to
272
+ # mypy not liking that the attribute doesn't exist in Python 2.7 when
273
+ # run with the `--py27` flag.
274
+ iver = format_full_version(sys.implementation.version) # type: ignore
275
+ implementation_name = sys.implementation.name # type: ignore
276
+ else:
277
+ iver = "0"
278
+ implementation_name = ""
279
+
280
+ return {
281
+ "implementation_name": implementation_name,
282
+ "implementation_version": iver,
283
+ "os_name": os.name,
284
+ "platform_machine": platform.machine(),
285
+ "platform_release": platform.release(),
286
+ "platform_system": platform.system(),
287
+ "platform_version": platform.version(),
288
+ "python_full_version": platform.python_version(),
289
+ "platform_python_implementation": platform.python_implementation(),
290
+ "python_version": ".".join(platform.python_version_tuple()[:2]),
291
+ "sys_platform": sys.platform,
292
+ }
293
+
294
+
295
+ class Marker(object):
296
+ def __init__(self, marker):
297
+ # type: (str) -> None
298
+ try:
299
+ self._markers = _coerce_parse_result(MARKER.parseString(marker))
300
+ except ParseException as e:
301
+ err_str = "Invalid marker: {0!r}, parse error at {1!r}".format(
302
+ marker, marker[e.loc : e.loc + 8]
303
+ )
304
+ raise InvalidMarker(err_str)
305
+
306
+ def __str__(self):
307
+ # type: () -> str
308
+ return _format_marker(self._markers)
309
+
310
+ def __repr__(self):
311
+ # type: () -> str
312
+ return "<Marker({0!r})>".format(str(self))
313
+
314
+ def evaluate(self, environment=None):
315
+ # type: (Optional[Dict[str, str]]) -> bool
316
+ """Evaluate a marker.
317
+
318
+ Return the boolean from evaluating the given marker against the
319
+ environment. environment is an optional argument to override all or
320
+ part of the determined environment.
321
+
322
+ The environment is determined from the current Python process.
323
+ """
324
+ current_environment = default_environment()
325
+ if environment is not None:
326
+ current_environment.update(environment)
327
+
328
+ return _evaluate_markers(self._markers, current_environment)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/requirements.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+ from __future__ import absolute_import, division, print_function
5
+
6
+ import string
7
+ import re
8
+
9
+ from setuptools.extern.pyparsing import stringStart, stringEnd, originalTextFor, ParseException
10
+ from setuptools.extern.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine
11
+ from setuptools.extern.pyparsing import Literal as L # noqa
12
+ from urllib import parse as urlparse
13
+
14
+ from ._typing import TYPE_CHECKING
15
+ from .markers import MARKER_EXPR, Marker
16
+ from .specifiers import LegacySpecifier, Specifier, SpecifierSet
17
+
18
+ if TYPE_CHECKING: # pragma: no cover
19
+ from typing import List
20
+
21
+
22
+ class InvalidRequirement(ValueError):
23
+ """
24
+ An invalid requirement was found, users should refer to PEP 508.
25
+ """
26
+
27
+
28
+ ALPHANUM = Word(string.ascii_letters + string.digits)
29
+
30
+ LBRACKET = L("[").suppress()
31
+ RBRACKET = L("]").suppress()
32
+ LPAREN = L("(").suppress()
33
+ RPAREN = L(")").suppress()
34
+ COMMA = L(",").suppress()
35
+ SEMICOLON = L(";").suppress()
36
+ AT = L("@").suppress()
37
+
38
+ PUNCTUATION = Word("-_.")
39
+ IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM)
40
+ IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END))
41
+
42
+ NAME = IDENTIFIER("name")
43
+ EXTRA = IDENTIFIER
44
+
45
+ URI = Regex(r"[^ ]+")("url")
46
+ URL = AT + URI
47
+
48
+ EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA)
49
+ EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras")
50
+
51
+ VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE)
52
+ VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE)
53
+
54
+ VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY
55
+ VERSION_MANY = Combine(
56
+ VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), joinString=",", adjacent=False
57
+ )("_raw_spec")
58
+ _VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY))
59
+ _VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or "")
60
+
61
+ VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier")
62
+ VERSION_SPEC.setParseAction(lambda s, l, t: t[1])
63
+
64
+ MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker")
65
+ MARKER_EXPR.setParseAction(
66
+ lambda s, l, t: Marker(s[t._original_start : t._original_end])
67
+ )
68
+ MARKER_SEPARATOR = SEMICOLON
69
+ MARKER = MARKER_SEPARATOR + MARKER_EXPR
70
+
71
+ VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER)
72
+ URL_AND_MARKER = URL + Optional(MARKER)
73
+
74
+ NAMED_REQUIREMENT = NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER)
75
+
76
+ REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd
77
+ # setuptools.extern.pyparsing isn't thread safe during initialization, so we do it eagerly, see
78
+ # issue #104
79
+ REQUIREMENT.parseString("x[]")
80
+
81
+
82
+ class Requirement(object):
83
+ """Parse a requirement.
84
+
85
+ Parse a given requirement string into its parts, such as name, specifier,
86
+ URL, and extras. Raises InvalidRequirement on a badly-formed requirement
87
+ string.
88
+ """
89
+
90
+ # TODO: Can we test whether something is contained within a requirement?
91
+ # If so how do we do that? Do we need to test against the _name_ of
92
+ # the thing as well as the version? What about the markers?
93
+ # TODO: Can we normalize the name and extra name?
94
+
95
+ def __init__(self, requirement_string):
96
+ # type: (str) -> None
97
+ try:
98
+ req = REQUIREMENT.parseString(requirement_string)
99
+ except ParseException as e:
100
+ raise InvalidRequirement(
101
+ 'Parse error at "{0!r}": {1}'.format(
102
+ requirement_string[e.loc : e.loc + 8], e.msg
103
+ )
104
+ )
105
+
106
+ self.name = req.name
107
+ if req.url:
108
+ parsed_url = urlparse.urlparse(req.url)
109
+ if parsed_url.scheme == "file":
110
+ if urlparse.urlunparse(parsed_url) != req.url:
111
+ raise InvalidRequirement("Invalid URL given")
112
+ elif not (parsed_url.scheme and parsed_url.netloc) or (
113
+ not parsed_url.scheme and not parsed_url.netloc
114
+ ):
115
+ raise InvalidRequirement("Invalid URL: {0}".format(req.url))
116
+ self.url = req.url
117
+ else:
118
+ self.url = None
119
+ self.extras = set(req.extras.asList() if req.extras else [])
120
+ self.specifier = SpecifierSet(req.specifier)
121
+ self.marker = req.marker if req.marker else None
122
+
123
+ def __str__(self):
124
+ # type: () -> str
125
+ parts = [self.name] # type: List[str]
126
+
127
+ if self.extras:
128
+ parts.append("[{0}]".format(",".join(sorted(self.extras))))
129
+
130
+ if self.specifier:
131
+ parts.append(str(self.specifier))
132
+
133
+ if self.url:
134
+ parts.append("@ {0}".format(self.url))
135
+ if self.marker:
136
+ parts.append(" ")
137
+
138
+ if self.marker:
139
+ parts.append("; {0}".format(self.marker))
140
+
141
+ return "".join(parts)
142
+
143
+ def __repr__(self):
144
+ # type: () -> str
145
+ return "<Requirement({0!r})>".format(str(self))
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/specifiers.py ADDED
@@ -0,0 +1,863 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+ from __future__ import absolute_import, division, print_function
5
+
6
+ import abc
7
+ import functools
8
+ import itertools
9
+ import re
10
+
11
+ from ._compat import string_types, with_metaclass
12
+ from ._typing import TYPE_CHECKING
13
+ from .utils import canonicalize_version
14
+ from .version import Version, LegacyVersion, parse
15
+
16
+ if TYPE_CHECKING: # pragma: no cover
17
+ from typing import (
18
+ List,
19
+ Dict,
20
+ Union,
21
+ Iterable,
22
+ Iterator,
23
+ Optional,
24
+ Callable,
25
+ Tuple,
26
+ FrozenSet,
27
+ )
28
+
29
+ ParsedVersion = Union[Version, LegacyVersion]
30
+ UnparsedVersion = Union[Version, LegacyVersion, str]
31
+ CallableOperator = Callable[[ParsedVersion, str], bool]
32
+
33
+
34
+ class InvalidSpecifier(ValueError):
35
+ """
36
+ An invalid specifier was found, users should refer to PEP 440.
37
+ """
38
+
39
+
40
+ class BaseSpecifier(with_metaclass(abc.ABCMeta, object)): # type: ignore
41
+ @abc.abstractmethod
42
+ def __str__(self):
43
+ # type: () -> str
44
+ """
45
+ Returns the str representation of this Specifier like object. This
46
+ should be representative of the Specifier itself.
47
+ """
48
+
49
+ @abc.abstractmethod
50
+ def __hash__(self):
51
+ # type: () -> int
52
+ """
53
+ Returns a hash value for this Specifier like object.
54
+ """
55
+
56
+ @abc.abstractmethod
57
+ def __eq__(self, other):
58
+ # type: (object) -> bool
59
+ """
60
+ Returns a boolean representing whether or not the two Specifier like
61
+ objects are equal.
62
+ """
63
+
64
+ @abc.abstractmethod
65
+ def __ne__(self, other):
66
+ # type: (object) -> bool
67
+ """
68
+ Returns a boolean representing whether or not the two Specifier like
69
+ objects are not equal.
70
+ """
71
+
72
+ @abc.abstractproperty
73
+ def prereleases(self):
74
+ # type: () -> Optional[bool]
75
+ """
76
+ Returns whether or not pre-releases as a whole are allowed by this
77
+ specifier.
78
+ """
79
+
80
+ @prereleases.setter
81
+ def prereleases(self, value):
82
+ # type: (bool) -> None
83
+ """
84
+ Sets whether or not pre-releases as a whole are allowed by this
85
+ specifier.
86
+ """
87
+
88
+ @abc.abstractmethod
89
+ def contains(self, item, prereleases=None):
90
+ # type: (str, Optional[bool]) -> bool
91
+ """
92
+ Determines if the given item is contained within this specifier.
93
+ """
94
+
95
+ @abc.abstractmethod
96
+ def filter(self, iterable, prereleases=None):
97
+ # type: (Iterable[UnparsedVersion], Optional[bool]) -> Iterable[UnparsedVersion]
98
+ """
99
+ Takes an iterable of items and filters them so that only items which
100
+ are contained within this specifier are allowed in it.
101
+ """
102
+
103
+
104
+ class _IndividualSpecifier(BaseSpecifier):
105
+
106
+ _operators = {} # type: Dict[str, str]
107
+
108
+ def __init__(self, spec="", prereleases=None):
109
+ # type: (str, Optional[bool]) -> None
110
+ match = self._regex.search(spec)
111
+ if not match:
112
+ raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec))
113
+
114
+ self._spec = (
115
+ match.group("operator").strip(),
116
+ match.group("version").strip(),
117
+ ) # type: Tuple[str, str]
118
+
119
+ # Store whether or not this Specifier should accept prereleases
120
+ self._prereleases = prereleases
121
+
122
+ def __repr__(self):
123
+ # type: () -> str
124
+ pre = (
125
+ ", prereleases={0!r}".format(self.prereleases)
126
+ if self._prereleases is not None
127
+ else ""
128
+ )
129
+
130
+ return "<{0}({1!r}{2})>".format(self.__class__.__name__, str(self), pre)
131
+
132
+ def __str__(self):
133
+ # type: () -> str
134
+ return "{0}{1}".format(*self._spec)
135
+
136
+ @property
137
+ def _canonical_spec(self):
138
+ # type: () -> Tuple[str, Union[Version, str]]
139
+ return self._spec[0], canonicalize_version(self._spec[1])
140
+
141
+ def __hash__(self):
142
+ # type: () -> int
143
+ return hash(self._canonical_spec)
144
+
145
+ def __eq__(self, other):
146
+ # type: (object) -> bool
147
+ if isinstance(other, string_types):
148
+ try:
149
+ other = self.__class__(str(other))
150
+ except InvalidSpecifier:
151
+ return NotImplemented
152
+ elif not isinstance(other, self.__class__):
153
+ return NotImplemented
154
+
155
+ return self._canonical_spec == other._canonical_spec
156
+
157
+ def __ne__(self, other):
158
+ # type: (object) -> bool
159
+ if isinstance(other, string_types):
160
+ try:
161
+ other = self.__class__(str(other))
162
+ except InvalidSpecifier:
163
+ return NotImplemented
164
+ elif not isinstance(other, self.__class__):
165
+ return NotImplemented
166
+
167
+ return self._spec != other._spec
168
+
169
+ def _get_operator(self, op):
170
+ # type: (str) -> CallableOperator
171
+ operator_callable = getattr(
172
+ self, "_compare_{0}".format(self._operators[op])
173
+ ) # type: CallableOperator
174
+ return operator_callable
175
+
176
+ def _coerce_version(self, version):
177
+ # type: (UnparsedVersion) -> ParsedVersion
178
+ if not isinstance(version, (LegacyVersion, Version)):
179
+ version = parse(version)
180
+ return version
181
+
182
+ @property
183
+ def operator(self):
184
+ # type: () -> str
185
+ return self._spec[0]
186
+
187
+ @property
188
+ def version(self):
189
+ # type: () -> str
190
+ return self._spec[1]
191
+
192
+ @property
193
+ def prereleases(self):
194
+ # type: () -> Optional[bool]
195
+ return self._prereleases
196
+
197
+ @prereleases.setter
198
+ def prereleases(self, value):
199
+ # type: (bool) -> None
200
+ self._prereleases = value
201
+
202
+ def __contains__(self, item):
203
+ # type: (str) -> bool
204
+ return self.contains(item)
205
+
206
+ def contains(self, item, prereleases=None):
207
+ # type: (UnparsedVersion, Optional[bool]) -> bool
208
+
209
+ # Determine if prereleases are to be allowed or not.
210
+ if prereleases is None:
211
+ prereleases = self.prereleases
212
+
213
+ # Normalize item to a Version or LegacyVersion, this allows us to have
214
+ # a shortcut for ``"2.0" in Specifier(">=2")
215
+ normalized_item = self._coerce_version(item)
216
+
217
+ # Determine if we should be supporting prereleases in this specifier
218
+ # or not, if we do not support prereleases than we can short circuit
219
+ # logic if this version is a prereleases.
220
+ if normalized_item.is_prerelease and not prereleases:
221
+ return False
222
+
223
+ # Actually do the comparison to determine if this item is contained
224
+ # within this Specifier or not.
225
+ operator_callable = self._get_operator(self.operator) # type: CallableOperator
226
+ return operator_callable(normalized_item, self.version)
227
+
228
+ def filter(self, iterable, prereleases=None):
229
+ # type: (Iterable[UnparsedVersion], Optional[bool]) -> Iterable[UnparsedVersion]
230
+
231
+ yielded = False
232
+ found_prereleases = []
233
+
234
+ kw = {"prereleases": prereleases if prereleases is not None else True}
235
+
236
+ # Attempt to iterate over all the values in the iterable and if any of
237
+ # them match, yield them.
238
+ for version in iterable:
239
+ parsed_version = self._coerce_version(version)
240
+
241
+ if self.contains(parsed_version, **kw):
242
+ # If our version is a prerelease, and we were not set to allow
243
+ # prereleases, then we'll store it for later incase nothing
244
+ # else matches this specifier.
245
+ if parsed_version.is_prerelease and not (
246
+ prereleases or self.prereleases
247
+ ):
248
+ found_prereleases.append(version)
249
+ # Either this is not a prerelease, or we should have been
250
+ # accepting prereleases from the beginning.
251
+ else:
252
+ yielded = True
253
+ yield version
254
+
255
+ # Now that we've iterated over everything, determine if we've yielded
256
+ # any values, and if we have not and we have any prereleases stored up
257
+ # then we will go ahead and yield the prereleases.
258
+ if not yielded and found_prereleases:
259
+ for version in found_prereleases:
260
+ yield version
261
+
262
+
263
+ class LegacySpecifier(_IndividualSpecifier):
264
+
265
+ _regex_str = r"""
266
+ (?P<operator>(==|!=|<=|>=|<|>))
267
+ \s*
268
+ (?P<version>
269
+ [^,;\s)]* # Since this is a "legacy" specifier, and the version
270
+ # string can be just about anything, we match everything
271
+ # except for whitespace, a semi-colon for marker support,
272
+ # a closing paren since versions can be enclosed in
273
+ # them, and a comma since it's a version separator.
274
+ )
275
+ """
276
+
277
+ _regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)
278
+
279
+ _operators = {
280
+ "==": "equal",
281
+ "!=": "not_equal",
282
+ "<=": "less_than_equal",
283
+ ">=": "greater_than_equal",
284
+ "<": "less_than",
285
+ ">": "greater_than",
286
+ }
287
+
288
+ def _coerce_version(self, version):
289
+ # type: (Union[ParsedVersion, str]) -> LegacyVersion
290
+ if not isinstance(version, LegacyVersion):
291
+ version = LegacyVersion(str(version))
292
+ return version
293
+
294
+ def _compare_equal(self, prospective, spec):
295
+ # type: (LegacyVersion, str) -> bool
296
+ return prospective == self._coerce_version(spec)
297
+
298
+ def _compare_not_equal(self, prospective, spec):
299
+ # type: (LegacyVersion, str) -> bool
300
+ return prospective != self._coerce_version(spec)
301
+
302
+ def _compare_less_than_equal(self, prospective, spec):
303
+ # type: (LegacyVersion, str) -> bool
304
+ return prospective <= self._coerce_version(spec)
305
+
306
+ def _compare_greater_than_equal(self, prospective, spec):
307
+ # type: (LegacyVersion, str) -> bool
308
+ return prospective >= self._coerce_version(spec)
309
+
310
+ def _compare_less_than(self, prospective, spec):
311
+ # type: (LegacyVersion, str) -> bool
312
+ return prospective < self._coerce_version(spec)
313
+
314
+ def _compare_greater_than(self, prospective, spec):
315
+ # type: (LegacyVersion, str) -> bool
316
+ return prospective > self._coerce_version(spec)
317
+
318
+
319
+ def _require_version_compare(
320
+ fn # type: (Callable[[Specifier, ParsedVersion, str], bool])
321
+ ):
322
+ # type: (...) -> Callable[[Specifier, ParsedVersion, str], bool]
323
+ @functools.wraps(fn)
324
+ def wrapped(self, prospective, spec):
325
+ # type: (Specifier, ParsedVersion, str) -> bool
326
+ if not isinstance(prospective, Version):
327
+ return False
328
+ return fn(self, prospective, spec)
329
+
330
+ return wrapped
331
+
332
+
333
+ class Specifier(_IndividualSpecifier):
334
+
335
+ _regex_str = r"""
336
+ (?P<operator>(~=|==|!=|<=|>=|<|>|===))
337
+ (?P<version>
338
+ (?:
339
+ # The identity operators allow for an escape hatch that will
340
+ # do an exact string match of the version you wish to install.
341
+ # This will not be parsed by PEP 440 and we cannot determine
342
+ # any semantic meaning from it. This operator is discouraged
343
+ # but included entirely as an escape hatch.
344
+ (?<====) # Only match for the identity operator
345
+ \s*
346
+ [^\s]* # We just match everything, except for whitespace
347
+ # since we are only testing for strict identity.
348
+ )
349
+ |
350
+ (?:
351
+ # The (non)equality operators allow for wild card and local
352
+ # versions to be specified so we have to define these two
353
+ # operators separately to enable that.
354
+ (?<===|!=) # Only match for equals and not equals
355
+
356
+ \s*
357
+ v?
358
+ (?:[0-9]+!)? # epoch
359
+ [0-9]+(?:\.[0-9]+)* # release
360
+ (?: # pre release
361
+ [-_\.]?
362
+ (a|b|c|rc|alpha|beta|pre|preview)
363
+ [-_\.]?
364
+ [0-9]*
365
+ )?
366
+ (?: # post release
367
+ (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
368
+ )?
369
+
370
+ # You cannot use a wild card and a dev or local version
371
+ # together so group them with a | and make them optional.
372
+ (?:
373
+ (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
374
+ (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local
375
+ |
376
+ \.\* # Wild card syntax of .*
377
+ )?
378
+ )
379
+ |
380
+ (?:
381
+ # The compatible operator requires at least two digits in the
382
+ # release segment.
383
+ (?<=~=) # Only match for the compatible operator
384
+
385
+ \s*
386
+ v?
387
+ (?:[0-9]+!)? # epoch
388
+ [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *)
389
+ (?: # pre release
390
+ [-_\.]?
391
+ (a|b|c|rc|alpha|beta|pre|preview)
392
+ [-_\.]?
393
+ [0-9]*
394
+ )?
395
+ (?: # post release
396
+ (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
397
+ )?
398
+ (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
399
+ )
400
+ |
401
+ (?:
402
+ # All other operators only allow a sub set of what the
403
+ # (non)equality operators do. Specifically they do not allow
404
+ # local versions to be specified nor do they allow the prefix
405
+ # matching wild cards.
406
+ (?<!==|!=|~=) # We have special cases for these
407
+ # operators so we want to make sure they
408
+ # don't match here.
409
+
410
+ \s*
411
+ v?
412
+ (?:[0-9]+!)? # epoch
413
+ [0-9]+(?:\.[0-9]+)* # release
414
+ (?: # pre release
415
+ [-_\.]?
416
+ (a|b|c|rc|alpha|beta|pre|preview)
417
+ [-_\.]?
418
+ [0-9]*
419
+ )?
420
+ (?: # post release
421
+ (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
422
+ )?
423
+ (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
424
+ )
425
+ )
426
+ """
427
+
428
+ _regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)
429
+
430
+ _operators = {
431
+ "~=": "compatible",
432
+ "==": "equal",
433
+ "!=": "not_equal",
434
+ "<=": "less_than_equal",
435
+ ">=": "greater_than_equal",
436
+ "<": "less_than",
437
+ ">": "greater_than",
438
+ "===": "arbitrary",
439
+ }
440
+
441
+ @_require_version_compare
442
+ def _compare_compatible(self, prospective, spec):
443
+ # type: (ParsedVersion, str) -> bool
444
+
445
+ # Compatible releases have an equivalent combination of >= and ==. That
446
+ # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to
447
+ # implement this in terms of the other specifiers instead of
448
+ # implementing it ourselves. The only thing we need to do is construct
449
+ # the other specifiers.
450
+
451
+ # We want everything but the last item in the version, but we want to
452
+ # ignore post and dev releases and we want to treat the pre-release as
453
+ # it's own separate segment.
454
+ prefix = ".".join(
455
+ list(
456
+ itertools.takewhile(
457
+ lambda x: (not x.startswith("post") and not x.startswith("dev")),
458
+ _version_split(spec),
459
+ )
460
+ )[:-1]
461
+ )
462
+
463
+ # Add the prefix notation to the end of our string
464
+ prefix += ".*"
465
+
466
+ return self._get_operator(">=")(prospective, spec) and self._get_operator("==")(
467
+ prospective, prefix
468
+ )
469
+
470
+ @_require_version_compare
471
+ def _compare_equal(self, prospective, spec):
472
+ # type: (ParsedVersion, str) -> bool
473
+
474
+ # We need special logic to handle prefix matching
475
+ if spec.endswith(".*"):
476
+ # In the case of prefix matching we want to ignore local segment.
477
+ prospective = Version(prospective.public)
478
+ # Split the spec out by dots, and pretend that there is an implicit
479
+ # dot in between a release segment and a pre-release segment.
480
+ split_spec = _version_split(spec[:-2]) # Remove the trailing .*
481
+
482
+ # Split the prospective version out by dots, and pretend that there
483
+ # is an implicit dot in between a release segment and a pre-release
484
+ # segment.
485
+ split_prospective = _version_split(str(prospective))
486
+
487
+ # Shorten the prospective version to be the same length as the spec
488
+ # so that we can determine if the specifier is a prefix of the
489
+ # prospective version or not.
490
+ shortened_prospective = split_prospective[: len(split_spec)]
491
+
492
+ # Pad out our two sides with zeros so that they both equal the same
493
+ # length.
494
+ padded_spec, padded_prospective = _pad_version(
495
+ split_spec, shortened_prospective
496
+ )
497
+
498
+ return padded_prospective == padded_spec
499
+ else:
500
+ # Convert our spec string into a Version
501
+ spec_version = Version(spec)
502
+
503
+ # If the specifier does not have a local segment, then we want to
504
+ # act as if the prospective version also does not have a local
505
+ # segment.
506
+ if not spec_version.local:
507
+ prospective = Version(prospective.public)
508
+
509
+ return prospective == spec_version
510
+
511
+ @_require_version_compare
512
+ def _compare_not_equal(self, prospective, spec):
513
+ # type: (ParsedVersion, str) -> bool
514
+ return not self._compare_equal(prospective, spec)
515
+
516
+ @_require_version_compare
517
+ def _compare_less_than_equal(self, prospective, spec):
518
+ # type: (ParsedVersion, str) -> bool
519
+
520
+ # NB: Local version identifiers are NOT permitted in the version
521
+ # specifier, so local version labels can be universally removed from
522
+ # the prospective version.
523
+ return Version(prospective.public) <= Version(spec)
524
+
525
+ @_require_version_compare
526
+ def _compare_greater_than_equal(self, prospective, spec):
527
+ # type: (ParsedVersion, str) -> bool
528
+
529
+ # NB: Local version identifiers are NOT permitted in the version
530
+ # specifier, so local version labels can be universally removed from
531
+ # the prospective version.
532
+ return Version(prospective.public) >= Version(spec)
533
+
534
+ @_require_version_compare
535
+ def _compare_less_than(self, prospective, spec_str):
536
+ # type: (ParsedVersion, str) -> bool
537
+
538
+ # Convert our spec to a Version instance, since we'll want to work with
539
+ # it as a version.
540
+ spec = Version(spec_str)
541
+
542
+ # Check to see if the prospective version is less than the spec
543
+ # version. If it's not we can short circuit and just return False now
544
+ # instead of doing extra unneeded work.
545
+ if not prospective < spec:
546
+ return False
547
+
548
+ # This special case is here so that, unless the specifier itself
549
+ # includes is a pre-release version, that we do not accept pre-release
550
+ # versions for the version mentioned in the specifier (e.g. <3.1 should
551
+ # not match 3.1.dev0, but should match 3.0.dev0).
552
+ if not spec.is_prerelease and prospective.is_prerelease:
553
+ if Version(prospective.base_version) == Version(spec.base_version):
554
+ return False
555
+
556
+ # If we've gotten to here, it means that prospective version is both
557
+ # less than the spec version *and* it's not a pre-release of the same
558
+ # version in the spec.
559
+ return True
560
+
561
+ @_require_version_compare
562
+ def _compare_greater_than(self, prospective, spec_str):
563
+ # type: (ParsedVersion, str) -> bool
564
+
565
+ # Convert our spec to a Version instance, since we'll want to work with
566
+ # it as a version.
567
+ spec = Version(spec_str)
568
+
569
+ # Check to see if the prospective version is greater than the spec
570
+ # version. If it's not we can short circuit and just return False now
571
+ # instead of doing extra unneeded work.
572
+ if not prospective > spec:
573
+ return False
574
+
575
+ # This special case is here so that, unless the specifier itself
576
+ # includes is a post-release version, that we do not accept
577
+ # post-release versions for the version mentioned in the specifier
578
+ # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0).
579
+ if not spec.is_postrelease and prospective.is_postrelease:
580
+ if Version(prospective.base_version) == Version(spec.base_version):
581
+ return False
582
+
583
+ # Ensure that we do not allow a local version of the version mentioned
584
+ # in the specifier, which is technically greater than, to match.
585
+ if prospective.local is not None:
586
+ if Version(prospective.base_version) == Version(spec.base_version):
587
+ return False
588
+
589
+ # If we've gotten to here, it means that prospective version is both
590
+ # greater than the spec version *and* it's not a pre-release of the
591
+ # same version in the spec.
592
+ return True
593
+
594
+ def _compare_arbitrary(self, prospective, spec):
595
+ # type: (Version, str) -> bool
596
+ return str(prospective).lower() == str(spec).lower()
597
+
598
+ @property
599
+ def prereleases(self):
600
+ # type: () -> bool
601
+
602
+ # If there is an explicit prereleases set for this, then we'll just
603
+ # blindly use that.
604
+ if self._prereleases is not None:
605
+ return self._prereleases
606
+
607
+ # Look at all of our specifiers and determine if they are inclusive
608
+ # operators, and if they are if they are including an explicit
609
+ # prerelease.
610
+ operator, version = self._spec
611
+ if operator in ["==", ">=", "<=", "~=", "==="]:
612
+ # The == specifier can include a trailing .*, if it does we
613
+ # want to remove before parsing.
614
+ if operator == "==" and version.endswith(".*"):
615
+ version = version[:-2]
616
+
617
+ # Parse the version, and if it is a pre-release than this
618
+ # specifier allows pre-releases.
619
+ if parse(version).is_prerelease:
620
+ return True
621
+
622
+ return False
623
+
624
+ @prereleases.setter
625
+ def prereleases(self, value):
626
+ # type: (bool) -> None
627
+ self._prereleases = value
628
+
629
+
630
+ _prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$")
631
+
632
+
633
+ def _version_split(version):
634
+ # type: (str) -> List[str]
635
+ result = [] # type: List[str]
636
+ for item in version.split("."):
637
+ match = _prefix_regex.search(item)
638
+ if match:
639
+ result.extend(match.groups())
640
+ else:
641
+ result.append(item)
642
+ return result
643
+
644
+
645
+ def _pad_version(left, right):
646
+ # type: (List[str], List[str]) -> Tuple[List[str], List[str]]
647
+ left_split, right_split = [], []
648
+
649
+ # Get the release segment of our versions
650
+ left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left)))
651
+ right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right)))
652
+
653
+ # Get the rest of our versions
654
+ left_split.append(left[len(left_split[0]) :])
655
+ right_split.append(right[len(right_split[0]) :])
656
+
657
+ # Insert our padding
658
+ left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0])))
659
+ right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0])))
660
+
661
+ return (list(itertools.chain(*left_split)), list(itertools.chain(*right_split)))
662
+
663
+
664
+ class SpecifierSet(BaseSpecifier):
665
+ def __init__(self, specifiers="", prereleases=None):
666
+ # type: (str, Optional[bool]) -> None
667
+
668
+ # Split on , to break each individual specifier into it's own item, and
669
+ # strip each item to remove leading/trailing whitespace.
670
+ split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()]
671
+
672
+ # Parsed each individual specifier, attempting first to make it a
673
+ # Specifier and falling back to a LegacySpecifier.
674
+ parsed = set()
675
+ for specifier in split_specifiers:
676
+ try:
677
+ parsed.add(Specifier(specifier))
678
+ except InvalidSpecifier:
679
+ parsed.add(LegacySpecifier(specifier))
680
+
681
+ # Turn our parsed specifiers into a frozen set and save them for later.
682
+ self._specs = frozenset(parsed)
683
+
684
+ # Store our prereleases value so we can use it later to determine if
685
+ # we accept prereleases or not.
686
+ self._prereleases = prereleases
687
+
688
+ def __repr__(self):
689
+ # type: () -> str
690
+ pre = (
691
+ ", prereleases={0!r}".format(self.prereleases)
692
+ if self._prereleases is not None
693
+ else ""
694
+ )
695
+
696
+ return "<SpecifierSet({0!r}{1})>".format(str(self), pre)
697
+
698
+ def __str__(self):
699
+ # type: () -> str
700
+ return ",".join(sorted(str(s) for s in self._specs))
701
+
702
+ def __hash__(self):
703
+ # type: () -> int
704
+ return hash(self._specs)
705
+
706
+ def __and__(self, other):
707
+ # type: (Union[SpecifierSet, str]) -> SpecifierSet
708
+ if isinstance(other, string_types):
709
+ other = SpecifierSet(other)
710
+ elif not isinstance(other, SpecifierSet):
711
+ return NotImplemented
712
+
713
+ specifier = SpecifierSet()
714
+ specifier._specs = frozenset(self._specs | other._specs)
715
+
716
+ if self._prereleases is None and other._prereleases is not None:
717
+ specifier._prereleases = other._prereleases
718
+ elif self._prereleases is not None and other._prereleases is None:
719
+ specifier._prereleases = self._prereleases
720
+ elif self._prereleases == other._prereleases:
721
+ specifier._prereleases = self._prereleases
722
+ else:
723
+ raise ValueError(
724
+ "Cannot combine SpecifierSets with True and False prerelease "
725
+ "overrides."
726
+ )
727
+
728
+ return specifier
729
+
730
+ def __eq__(self, other):
731
+ # type: (object) -> bool
732
+ if isinstance(other, (string_types, _IndividualSpecifier)):
733
+ other = SpecifierSet(str(other))
734
+ elif not isinstance(other, SpecifierSet):
735
+ return NotImplemented
736
+
737
+ return self._specs == other._specs
738
+
739
+ def __ne__(self, other):
740
+ # type: (object) -> bool
741
+ if isinstance(other, (string_types, _IndividualSpecifier)):
742
+ other = SpecifierSet(str(other))
743
+ elif not isinstance(other, SpecifierSet):
744
+ return NotImplemented
745
+
746
+ return self._specs != other._specs
747
+
748
+ def __len__(self):
749
+ # type: () -> int
750
+ return len(self._specs)
751
+
752
+ def __iter__(self):
753
+ # type: () -> Iterator[FrozenSet[_IndividualSpecifier]]
754
+ return iter(self._specs)
755
+
756
+ @property
757
+ def prereleases(self):
758
+ # type: () -> Optional[bool]
759
+
760
+ # If we have been given an explicit prerelease modifier, then we'll
761
+ # pass that through here.
762
+ if self._prereleases is not None:
763
+ return self._prereleases
764
+
765
+ # If we don't have any specifiers, and we don't have a forced value,
766
+ # then we'll just return None since we don't know if this should have
767
+ # pre-releases or not.
768
+ if not self._specs:
769
+ return None
770
+
771
+ # Otherwise we'll see if any of the given specifiers accept
772
+ # prereleases, if any of them do we'll return True, otherwise False.
773
+ return any(s.prereleases for s in self._specs)
774
+
775
+ @prereleases.setter
776
+ def prereleases(self, value):
777
+ # type: (bool) -> None
778
+ self._prereleases = value
779
+
780
+ def __contains__(self, item):
781
+ # type: (Union[ParsedVersion, str]) -> bool
782
+ return self.contains(item)
783
+
784
+ def contains(self, item, prereleases=None):
785
+ # type: (Union[ParsedVersion, str], Optional[bool]) -> bool
786
+
787
+ # Ensure that our item is a Version or LegacyVersion instance.
788
+ if not isinstance(item, (LegacyVersion, Version)):
789
+ item = parse(item)
790
+
791
+ # Determine if we're forcing a prerelease or not, if we're not forcing
792
+ # one for this particular filter call, then we'll use whatever the
793
+ # SpecifierSet thinks for whether or not we should support prereleases.
794
+ if prereleases is None:
795
+ prereleases = self.prereleases
796
+
797
+ # We can determine if we're going to allow pre-releases by looking to
798
+ # see if any of the underlying items supports them. If none of them do
799
+ # and this item is a pre-release then we do not allow it and we can
800
+ # short circuit that here.
801
+ # Note: This means that 1.0.dev1 would not be contained in something
802
+ # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0
803
+ if not prereleases and item.is_prerelease:
804
+ return False
805
+
806
+ # We simply dispatch to the underlying specs here to make sure that the
807
+ # given version is contained within all of them.
808
+ # Note: This use of all() here means that an empty set of specifiers
809
+ # will always return True, this is an explicit design decision.
810
+ return all(s.contains(item, prereleases=prereleases) for s in self._specs)
811
+
812
+ def filter(
813
+ self,
814
+ iterable, # type: Iterable[Union[ParsedVersion, str]]
815
+ prereleases=None, # type: Optional[bool]
816
+ ):
817
+ # type: (...) -> Iterable[Union[ParsedVersion, str]]
818
+
819
+ # Determine if we're forcing a prerelease or not, if we're not forcing
820
+ # one for this particular filter call, then we'll use whatever the
821
+ # SpecifierSet thinks for whether or not we should support prereleases.
822
+ if prereleases is None:
823
+ prereleases = self.prereleases
824
+
825
+ # If we have any specifiers, then we want to wrap our iterable in the
826
+ # filter method for each one, this will act as a logical AND amongst
827
+ # each specifier.
828
+ if self._specs:
829
+ for spec in self._specs:
830
+ iterable = spec.filter(iterable, prereleases=bool(prereleases))
831
+ return iterable
832
+ # If we do not have any specifiers, then we need to have a rough filter
833
+ # which will filter out any pre-releases, unless there are no final
834
+ # releases, and which will filter out LegacyVersion in general.
835
+ else:
836
+ filtered = [] # type: List[Union[ParsedVersion, str]]
837
+ found_prereleases = [] # type: List[Union[ParsedVersion, str]]
838
+
839
+ for item in iterable:
840
+ # Ensure that we some kind of Version class for this item.
841
+ if not isinstance(item, (LegacyVersion, Version)):
842
+ parsed_version = parse(item)
843
+ else:
844
+ parsed_version = item
845
+
846
+ # Filter out any item which is parsed as a LegacyVersion
847
+ if isinstance(parsed_version, LegacyVersion):
848
+ continue
849
+
850
+ # Store any item which is a pre-release for later unless we've
851
+ # already found a final version or we are accepting prereleases
852
+ if parsed_version.is_prerelease and not prereleases:
853
+ if not filtered:
854
+ found_prereleases.append(item)
855
+ else:
856
+ filtered.append(item)
857
+
858
+ # If we've found no items except for pre-releases, then we'll go
859
+ # ahead and use the pre-releases
860
+ if not filtered and found_prereleases and prereleases is None:
861
+ return found_prereleases
862
+
863
+ return filtered
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/tags.py ADDED
@@ -0,0 +1,751 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+
5
+ from __future__ import absolute_import
6
+
7
+ import distutils.util
8
+
9
+ try:
10
+ from importlib.machinery import EXTENSION_SUFFIXES
11
+ except ImportError: # pragma: no cover
12
+ import imp
13
+
14
+ EXTENSION_SUFFIXES = [x[0] for x in imp.get_suffixes()]
15
+ del imp
16
+ import logging
17
+ import os
18
+ import platform
19
+ import re
20
+ import struct
21
+ import sys
22
+ import sysconfig
23
+ import warnings
24
+
25
+ from ._typing import TYPE_CHECKING, cast
26
+
27
+ if TYPE_CHECKING: # pragma: no cover
28
+ from typing import (
29
+ Dict,
30
+ FrozenSet,
31
+ IO,
32
+ Iterable,
33
+ Iterator,
34
+ List,
35
+ Optional,
36
+ Sequence,
37
+ Tuple,
38
+ Union,
39
+ )
40
+
41
+ PythonVersion = Sequence[int]
42
+ MacVersion = Tuple[int, int]
43
+ GlibcVersion = Tuple[int, int]
44
+
45
+
46
+ logger = logging.getLogger(__name__)
47
+
48
+ INTERPRETER_SHORT_NAMES = {
49
+ "python": "py", # Generic.
50
+ "cpython": "cp",
51
+ "pypy": "pp",
52
+ "ironpython": "ip",
53
+ "jython": "jy",
54
+ } # type: Dict[str, str]
55
+
56
+
57
+ _32_BIT_INTERPRETER = sys.maxsize <= 2 ** 32
58
+
59
+
60
+ class Tag(object):
61
+ """
62
+ A representation of the tag triple for a wheel.
63
+
64
+ Instances are considered immutable and thus are hashable. Equality checking
65
+ is also supported.
66
+ """
67
+
68
+ __slots__ = ["_interpreter", "_abi", "_platform"]
69
+
70
+ def __init__(self, interpreter, abi, platform):
71
+ # type: (str, str, str) -> None
72
+ self._interpreter = interpreter.lower()
73
+ self._abi = abi.lower()
74
+ self._platform = platform.lower()
75
+
76
+ @property
77
+ def interpreter(self):
78
+ # type: () -> str
79
+ return self._interpreter
80
+
81
+ @property
82
+ def abi(self):
83
+ # type: () -> str
84
+ return self._abi
85
+
86
+ @property
87
+ def platform(self):
88
+ # type: () -> str
89
+ return self._platform
90
+
91
+ def __eq__(self, other):
92
+ # type: (object) -> bool
93
+ if not isinstance(other, Tag):
94
+ return NotImplemented
95
+
96
+ return (
97
+ (self.platform == other.platform)
98
+ and (self.abi == other.abi)
99
+ and (self.interpreter == other.interpreter)
100
+ )
101
+
102
+ def __hash__(self):
103
+ # type: () -> int
104
+ return hash((self._interpreter, self._abi, self._platform))
105
+
106
+ def __str__(self):
107
+ # type: () -> str
108
+ return "{}-{}-{}".format(self._interpreter, self._abi, self._platform)
109
+
110
+ def __repr__(self):
111
+ # type: () -> str
112
+ return "<{self} @ {self_id}>".format(self=self, self_id=id(self))
113
+
114
+
115
+ def parse_tag(tag):
116
+ # type: (str) -> FrozenSet[Tag]
117
+ """
118
+ Parses the provided tag (e.g. `py3-none-any`) into a frozenset of Tag instances.
119
+
120
+ Returning a set is required due to the possibility that the tag is a
121
+ compressed tag set.
122
+ """
123
+ tags = set()
124
+ interpreters, abis, platforms = tag.split("-")
125
+ for interpreter in interpreters.split("."):
126
+ for abi in abis.split("."):
127
+ for platform_ in platforms.split("."):
128
+ tags.add(Tag(interpreter, abi, platform_))
129
+ return frozenset(tags)
130
+
131
+
132
+ def _warn_keyword_parameter(func_name, kwargs):
133
+ # type: (str, Dict[str, bool]) -> bool
134
+ """
135
+ Backwards-compatibility with Python 2.7 to allow treating 'warn' as keyword-only.
136
+ """
137
+ if not kwargs:
138
+ return False
139
+ elif len(kwargs) > 1 or "warn" not in kwargs:
140
+ kwargs.pop("warn", None)
141
+ arg = next(iter(kwargs.keys()))
142
+ raise TypeError(
143
+ "{}() got an unexpected keyword argument {!r}".format(func_name, arg)
144
+ )
145
+ return kwargs["warn"]
146
+
147
+
148
+ def _get_config_var(name, warn=False):
149
+ # type: (str, bool) -> Union[int, str, None]
150
+ value = sysconfig.get_config_var(name)
151
+ if value is None and warn:
152
+ logger.debug(
153
+ "Config variable '%s' is unset, Python ABI tag may be incorrect", name
154
+ )
155
+ return value
156
+
157
+
158
+ def _normalize_string(string):
159
+ # type: (str) -> str
160
+ return string.replace(".", "_").replace("-", "_")
161
+
162
+
163
+ def _abi3_applies(python_version):
164
+ # type: (PythonVersion) -> bool
165
+ """
166
+ Determine if the Python version supports abi3.
167
+
168
+ PEP 384 was first implemented in Python 3.2.
169
+ """
170
+ return len(python_version) > 1 and tuple(python_version) >= (3, 2)
171
+
172
+
173
+ def _cpython_abis(py_version, warn=False):
174
+ # type: (PythonVersion, bool) -> List[str]
175
+ py_version = tuple(py_version) # To allow for version comparison.
176
+ abis = []
177
+ version = _version_nodot(py_version[:2])
178
+ debug = pymalloc = ucs4 = ""
179
+ with_debug = _get_config_var("Py_DEBUG", warn)
180
+ has_refcount = hasattr(sys, "gettotalrefcount")
181
+ # Windows doesn't set Py_DEBUG, so checking for support of debug-compiled
182
+ # extension modules is the best option.
183
+ # https://github.com/pypa/pip/issues/3383#issuecomment-173267692
184
+ has_ext = "_d.pyd" in EXTENSION_SUFFIXES
185
+ if with_debug or (with_debug is None and (has_refcount or has_ext)):
186
+ debug = "d"
187
+ if py_version < (3, 8):
188
+ with_pymalloc = _get_config_var("WITH_PYMALLOC", warn)
189
+ if with_pymalloc or with_pymalloc is None:
190
+ pymalloc = "m"
191
+ if py_version < (3, 3):
192
+ unicode_size = _get_config_var("Py_UNICODE_SIZE", warn)
193
+ if unicode_size == 4 or (
194
+ unicode_size is None and sys.maxunicode == 0x10FFFF
195
+ ):
196
+ ucs4 = "u"
197
+ elif debug:
198
+ # Debug builds can also load "normal" extension modules.
199
+ # We can also assume no UCS-4 or pymalloc requirement.
200
+ abis.append("cp{version}".format(version=version))
201
+ abis.insert(
202
+ 0,
203
+ "cp{version}{debug}{pymalloc}{ucs4}".format(
204
+ version=version, debug=debug, pymalloc=pymalloc, ucs4=ucs4
205
+ ),
206
+ )
207
+ return abis
208
+
209
+
210
+ def cpython_tags(
211
+ python_version=None, # type: Optional[PythonVersion]
212
+ abis=None, # type: Optional[Iterable[str]]
213
+ platforms=None, # type: Optional[Iterable[str]]
214
+ **kwargs # type: bool
215
+ ):
216
+ # type: (...) -> Iterator[Tag]
217
+ """
218
+ Yields the tags for a CPython interpreter.
219
+
220
+ The tags consist of:
221
+ - cp<python_version>-<abi>-<platform>
222
+ - cp<python_version>-abi3-<platform>
223
+ - cp<python_version>-none-<platform>
224
+ - cp<less than python_version>-abi3-<platform> # Older Python versions down to 3.2.
225
+
226
+ If python_version only specifies a major version then user-provided ABIs and
227
+ the 'none' ABItag will be used.
228
+
229
+ If 'abi3' or 'none' are specified in 'abis' then they will be yielded at
230
+ their normal position and not at the beginning.
231
+ """
232
+ warn = _warn_keyword_parameter("cpython_tags", kwargs)
233
+ if not python_version:
234
+ python_version = sys.version_info[:2]
235
+
236
+ interpreter = "cp{}".format(_version_nodot(python_version[:2]))
237
+
238
+ if abis is None:
239
+ if len(python_version) > 1:
240
+ abis = _cpython_abis(python_version, warn)
241
+ else:
242
+ abis = []
243
+ abis = list(abis)
244
+ # 'abi3' and 'none' are explicitly handled later.
245
+ for explicit_abi in ("abi3", "none"):
246
+ try:
247
+ abis.remove(explicit_abi)
248
+ except ValueError:
249
+ pass
250
+
251
+ platforms = list(platforms or _platform_tags())
252
+ for abi in abis:
253
+ for platform_ in platforms:
254
+ yield Tag(interpreter, abi, platform_)
255
+ if _abi3_applies(python_version):
256
+ for tag in (Tag(interpreter, "abi3", platform_) for platform_ in platforms):
257
+ yield tag
258
+ for tag in (Tag(interpreter, "none", platform_) for platform_ in platforms):
259
+ yield tag
260
+
261
+ if _abi3_applies(python_version):
262
+ for minor_version in range(python_version[1] - 1, 1, -1):
263
+ for platform_ in platforms:
264
+ interpreter = "cp{version}".format(
265
+ version=_version_nodot((python_version[0], minor_version))
266
+ )
267
+ yield Tag(interpreter, "abi3", platform_)
268
+
269
+
270
+ def _generic_abi():
271
+ # type: () -> Iterator[str]
272
+ abi = sysconfig.get_config_var("SOABI")
273
+ if abi:
274
+ yield _normalize_string(abi)
275
+
276
+
277
+ def generic_tags(
278
+ interpreter=None, # type: Optional[str]
279
+ abis=None, # type: Optional[Iterable[str]]
280
+ platforms=None, # type: Optional[Iterable[str]]
281
+ **kwargs # type: bool
282
+ ):
283
+ # type: (...) -> Iterator[Tag]
284
+ """
285
+ Yields the tags for a generic interpreter.
286
+
287
+ The tags consist of:
288
+ - <interpreter>-<abi>-<platform>
289
+
290
+ The "none" ABI will be added if it was not explicitly provided.
291
+ """
292
+ warn = _warn_keyword_parameter("generic_tags", kwargs)
293
+ if not interpreter:
294
+ interp_name = interpreter_name()
295
+ interp_version = interpreter_version(warn=warn)
296
+ interpreter = "".join([interp_name, interp_version])
297
+ if abis is None:
298
+ abis = _generic_abi()
299
+ platforms = list(platforms or _platform_tags())
300
+ abis = list(abis)
301
+ if "none" not in abis:
302
+ abis.append("none")
303
+ for abi in abis:
304
+ for platform_ in platforms:
305
+ yield Tag(interpreter, abi, platform_)
306
+
307
+
308
+ def _py_interpreter_range(py_version):
309
+ # type: (PythonVersion) -> Iterator[str]
310
+ """
311
+ Yields Python versions in descending order.
312
+
313
+ After the latest version, the major-only version will be yielded, and then
314
+ all previous versions of that major version.
315
+ """
316
+ if len(py_version) > 1:
317
+ yield "py{version}".format(version=_version_nodot(py_version[:2]))
318
+ yield "py{major}".format(major=py_version[0])
319
+ if len(py_version) > 1:
320
+ for minor in range(py_version[1] - 1, -1, -1):
321
+ yield "py{version}".format(version=_version_nodot((py_version[0], minor)))
322
+
323
+
324
+ def compatible_tags(
325
+ python_version=None, # type: Optional[PythonVersion]
326
+ interpreter=None, # type: Optional[str]
327
+ platforms=None, # type: Optional[Iterable[str]]
328
+ ):
329
+ # type: (...) -> Iterator[Tag]
330
+ """
331
+ Yields the sequence of tags that are compatible with a specific version of Python.
332
+
333
+ The tags consist of:
334
+ - py*-none-<platform>
335
+ - <interpreter>-none-any # ... if `interpreter` is provided.
336
+ - py*-none-any
337
+ """
338
+ if not python_version:
339
+ python_version = sys.version_info[:2]
340
+ platforms = list(platforms or _platform_tags())
341
+ for version in _py_interpreter_range(python_version):
342
+ for platform_ in platforms:
343
+ yield Tag(version, "none", platform_)
344
+ if interpreter:
345
+ yield Tag(interpreter, "none", "any")
346
+ for version in _py_interpreter_range(python_version):
347
+ yield Tag(version, "none", "any")
348
+
349
+
350
+ def _mac_arch(arch, is_32bit=_32_BIT_INTERPRETER):
351
+ # type: (str, bool) -> str
352
+ if not is_32bit:
353
+ return arch
354
+
355
+ if arch.startswith("ppc"):
356
+ return "ppc"
357
+
358
+ return "i386"
359
+
360
+
361
+ def _mac_binary_formats(version, cpu_arch):
362
+ # type: (MacVersion, str) -> List[str]
363
+ formats = [cpu_arch]
364
+ if cpu_arch == "x86_64":
365
+ if version < (10, 4):
366
+ return []
367
+ formats.extend(["intel", "fat64", "fat32"])
368
+
369
+ elif cpu_arch == "i386":
370
+ if version < (10, 4):
371
+ return []
372
+ formats.extend(["intel", "fat32", "fat"])
373
+
374
+ elif cpu_arch == "ppc64":
375
+ # TODO: Need to care about 32-bit PPC for ppc64 through 10.2?
376
+ if version > (10, 5) or version < (10, 4):
377
+ return []
378
+ formats.append("fat64")
379
+
380
+ elif cpu_arch == "ppc":
381
+ if version > (10, 6):
382
+ return []
383
+ formats.extend(["fat32", "fat"])
384
+
385
+ formats.append("universal")
386
+ return formats
387
+
388
+
389
+ def mac_platforms(version=None, arch=None):
390
+ # type: (Optional[MacVersion], Optional[str]) -> Iterator[str]
391
+ """
392
+ Yields the platform tags for a macOS system.
393
+
394
+ The `version` parameter is a two-item tuple specifying the macOS version to
395
+ generate platform tags for. The `arch` parameter is the CPU architecture to
396
+ generate platform tags for. Both parameters default to the appropriate value
397
+ for the current system.
398
+ """
399
+ version_str, _, cpu_arch = platform.mac_ver() # type: ignore
400
+ if version is None:
401
+ version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2])))
402
+ else:
403
+ version = version
404
+ if arch is None:
405
+ arch = _mac_arch(cpu_arch)
406
+ else:
407
+ arch = arch
408
+ for minor_version in range(version[1], -1, -1):
409
+ compat_version = version[0], minor_version
410
+ binary_formats = _mac_binary_formats(compat_version, arch)
411
+ for binary_format in binary_formats:
412
+ yield "macosx_{major}_{minor}_{binary_format}".format(
413
+ major=compat_version[0],
414
+ minor=compat_version[1],
415
+ binary_format=binary_format,
416
+ )
417
+
418
+
419
+ # From PEP 513.
420
+ def _is_manylinux_compatible(name, glibc_version):
421
+ # type: (str, GlibcVersion) -> bool
422
+ # Check for presence of _manylinux module.
423
+ try:
424
+ import _manylinux # noqa
425
+
426
+ return bool(getattr(_manylinux, name + "_compatible"))
427
+ except (ImportError, AttributeError):
428
+ # Fall through to heuristic check below.
429
+ pass
430
+
431
+ return _have_compatible_glibc(*glibc_version)
432
+
433
+
434
+ def _glibc_version_string():
435
+ # type: () -> Optional[str]
436
+ # Returns glibc version string, or None if not using glibc.
437
+ return _glibc_version_string_confstr() or _glibc_version_string_ctypes()
438
+
439
+
440
+ def _glibc_version_string_confstr():
441
+ # type: () -> Optional[str]
442
+ """
443
+ Primary implementation of glibc_version_string using os.confstr.
444
+ """
445
+ # os.confstr is quite a bit faster than ctypes.DLL. It's also less likely
446
+ # to be broken or missing. This strategy is used in the standard library
447
+ # platform module.
448
+ # https://github.com/python/cpython/blob/fcf1d003bf4f0100c9d0921ff3d70e1127ca1b71/Lib/platform.py#L175-L183
449
+ try:
450
+ # os.confstr("CS_GNU_LIBC_VERSION") returns a string like "glibc 2.17".
451
+ version_string = os.confstr( # type: ignore[attr-defined] # noqa: F821
452
+ "CS_GNU_LIBC_VERSION"
453
+ )
454
+ assert version_string is not None
455
+ _, version = version_string.split() # type: Tuple[str, str]
456
+ except (AssertionError, AttributeError, OSError, ValueError):
457
+ # os.confstr() or CS_GNU_LIBC_VERSION not available (or a bad value)...
458
+ return None
459
+ return version
460
+
461
+
462
+ def _glibc_version_string_ctypes():
463
+ # type: () -> Optional[str]
464
+ """
465
+ Fallback implementation of glibc_version_string using ctypes.
466
+ """
467
+ try:
468
+ import ctypes
469
+ except ImportError:
470
+ return None
471
+
472
+ # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen
473
+ # manpage says, "If filename is NULL, then the returned handle is for the
474
+ # main program". This way we can let the linker do the work to figure out
475
+ # which libc our process is actually using.
476
+ #
477
+ # Note: typeshed is wrong here so we are ignoring this line.
478
+ process_namespace = ctypes.CDLL(None) # type: ignore
479
+ try:
480
+ gnu_get_libc_version = process_namespace.gnu_get_libc_version
481
+ except AttributeError:
482
+ # Symbol doesn't exist -> therefore, we are not linked to
483
+ # glibc.
484
+ return None
485
+
486
+ # Call gnu_get_libc_version, which returns a string like "2.5"
487
+ gnu_get_libc_version.restype = ctypes.c_char_p
488
+ version_str = gnu_get_libc_version() # type: str
489
+ # py2 / py3 compatibility:
490
+ if not isinstance(version_str, str):
491
+ version_str = version_str.decode("ascii")
492
+
493
+ return version_str
494
+
495
+
496
+ # Separated out from have_compatible_glibc for easier unit testing.
497
+ def _check_glibc_version(version_str, required_major, minimum_minor):
498
+ # type: (str, int, int) -> bool
499
+ # Parse string and check against requested version.
500
+ #
501
+ # We use a regexp instead of str.split because we want to discard any
502
+ # random junk that might come after the minor version -- this might happen
503
+ # in patched/forked versions of glibc (e.g. Linaro's version of glibc
504
+ # uses version strings like "2.20-2014.11"). See gh-3588.
505
+ m = re.match(r"(?P<major>[0-9]+)\.(?P<minor>[0-9]+)", version_str)
506
+ if not m:
507
+ warnings.warn(
508
+ "Expected glibc version with 2 components major.minor,"
509
+ " got: %s" % version_str,
510
+ RuntimeWarning,
511
+ )
512
+ return False
513
+ return (
514
+ int(m.group("major")) == required_major
515
+ and int(m.group("minor")) >= minimum_minor
516
+ )
517
+
518
+
519
+ def _have_compatible_glibc(required_major, minimum_minor):
520
+ # type: (int, int) -> bool
521
+ version_str = _glibc_version_string()
522
+ if version_str is None:
523
+ return False
524
+ return _check_glibc_version(version_str, required_major, minimum_minor)
525
+
526
+
527
+ # Python does not provide platform information at sufficient granularity to
528
+ # identify the architecture of the running executable in some cases, so we
529
+ # determine it dynamically by reading the information from the running
530
+ # process. This only applies on Linux, which uses the ELF format.
531
+ class _ELFFileHeader(object):
532
+ # https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header
533
+ class _InvalidELFFileHeader(ValueError):
534
+ """
535
+ An invalid ELF file header was found.
536
+ """
537
+
538
+ ELF_MAGIC_NUMBER = 0x7F454C46
539
+ ELFCLASS32 = 1
540
+ ELFCLASS64 = 2
541
+ ELFDATA2LSB = 1
542
+ ELFDATA2MSB = 2
543
+ EM_386 = 3
544
+ EM_S390 = 22
545
+ EM_ARM = 40
546
+ EM_X86_64 = 62
547
+ EF_ARM_ABIMASK = 0xFF000000
548
+ EF_ARM_ABI_VER5 = 0x05000000
549
+ EF_ARM_ABI_FLOAT_HARD = 0x00000400
550
+
551
+ def __init__(self, file):
552
+ # type: (IO[bytes]) -> None
553
+ def unpack(fmt):
554
+ # type: (str) -> int
555
+ try:
556
+ (result,) = struct.unpack(
557
+ fmt, file.read(struct.calcsize(fmt))
558
+ ) # type: (int, )
559
+ except struct.error:
560
+ raise _ELFFileHeader._InvalidELFFileHeader()
561
+ return result
562
+
563
+ self.e_ident_magic = unpack(">I")
564
+ if self.e_ident_magic != self.ELF_MAGIC_NUMBER:
565
+ raise _ELFFileHeader._InvalidELFFileHeader()
566
+ self.e_ident_class = unpack("B")
567
+ if self.e_ident_class not in {self.ELFCLASS32, self.ELFCLASS64}:
568
+ raise _ELFFileHeader._InvalidELFFileHeader()
569
+ self.e_ident_data = unpack("B")
570
+ if self.e_ident_data not in {self.ELFDATA2LSB, self.ELFDATA2MSB}:
571
+ raise _ELFFileHeader._InvalidELFFileHeader()
572
+ self.e_ident_version = unpack("B")
573
+ self.e_ident_osabi = unpack("B")
574
+ self.e_ident_abiversion = unpack("B")
575
+ self.e_ident_pad = file.read(7)
576
+ format_h = "<H" if self.e_ident_data == self.ELFDATA2LSB else ">H"
577
+ format_i = "<I" if self.e_ident_data == self.ELFDATA2LSB else ">I"
578
+ format_q = "<Q" if self.e_ident_data == self.ELFDATA2LSB else ">Q"
579
+ format_p = format_i if self.e_ident_class == self.ELFCLASS32 else format_q
580
+ self.e_type = unpack(format_h)
581
+ self.e_machine = unpack(format_h)
582
+ self.e_version = unpack(format_i)
583
+ self.e_entry = unpack(format_p)
584
+ self.e_phoff = unpack(format_p)
585
+ self.e_shoff = unpack(format_p)
586
+ self.e_flags = unpack(format_i)
587
+ self.e_ehsize = unpack(format_h)
588
+ self.e_phentsize = unpack(format_h)
589
+ self.e_phnum = unpack(format_h)
590
+ self.e_shentsize = unpack(format_h)
591
+ self.e_shnum = unpack(format_h)
592
+ self.e_shstrndx = unpack(format_h)
593
+
594
+
595
+ def _get_elf_header():
596
+ # type: () -> Optional[_ELFFileHeader]
597
+ try:
598
+ with open(sys.executable, "rb") as f:
599
+ elf_header = _ELFFileHeader(f)
600
+ except (IOError, OSError, TypeError, _ELFFileHeader._InvalidELFFileHeader):
601
+ return None
602
+ return elf_header
603
+
604
+
605
+ def _is_linux_armhf():
606
+ # type: () -> bool
607
+ # hard-float ABI can be detected from the ELF header of the running
608
+ # process
609
+ # https://static.docs.arm.com/ihi0044/g/aaelf32.pdf
610
+ elf_header = _get_elf_header()
611
+ if elf_header is None:
612
+ return False
613
+ result = elf_header.e_ident_class == elf_header.ELFCLASS32
614
+ result &= elf_header.e_ident_data == elf_header.ELFDATA2LSB
615
+ result &= elf_header.e_machine == elf_header.EM_ARM
616
+ result &= (
617
+ elf_header.e_flags & elf_header.EF_ARM_ABIMASK
618
+ ) == elf_header.EF_ARM_ABI_VER5
619
+ result &= (
620
+ elf_header.e_flags & elf_header.EF_ARM_ABI_FLOAT_HARD
621
+ ) == elf_header.EF_ARM_ABI_FLOAT_HARD
622
+ return result
623
+
624
+
625
+ def _is_linux_i686():
626
+ # type: () -> bool
627
+ elf_header = _get_elf_header()
628
+ if elf_header is None:
629
+ return False
630
+ result = elf_header.e_ident_class == elf_header.ELFCLASS32
631
+ result &= elf_header.e_ident_data == elf_header.ELFDATA2LSB
632
+ result &= elf_header.e_machine == elf_header.EM_386
633
+ return result
634
+
635
+
636
+ def _have_compatible_manylinux_abi(arch):
637
+ # type: (str) -> bool
638
+ if arch == "armv7l":
639
+ return _is_linux_armhf()
640
+ if arch == "i686":
641
+ return _is_linux_i686()
642
+ return True
643
+
644
+
645
+ def _linux_platforms(is_32bit=_32_BIT_INTERPRETER):
646
+ # type: (bool) -> Iterator[str]
647
+ linux = _normalize_string(distutils.util.get_platform())
648
+ if is_32bit:
649
+ if linux == "linux_x86_64":
650
+ linux = "linux_i686"
651
+ elif linux == "linux_aarch64":
652
+ linux = "linux_armv7l"
653
+ manylinux_support = []
654
+ _, arch = linux.split("_", 1)
655
+ if _have_compatible_manylinux_abi(arch):
656
+ if arch in {"x86_64", "i686", "aarch64", "armv7l", "ppc64", "ppc64le", "s390x"}:
657
+ manylinux_support.append(
658
+ ("manylinux2014", (2, 17))
659
+ ) # CentOS 7 w/ glibc 2.17 (PEP 599)
660
+ if arch in {"x86_64", "i686"}:
661
+ manylinux_support.append(
662
+ ("manylinux2010", (2, 12))
663
+ ) # CentOS 6 w/ glibc 2.12 (PEP 571)
664
+ manylinux_support.append(
665
+ ("manylinux1", (2, 5))
666
+ ) # CentOS 5 w/ glibc 2.5 (PEP 513)
667
+ manylinux_support_iter = iter(manylinux_support)
668
+ for name, glibc_version in manylinux_support_iter:
669
+ if _is_manylinux_compatible(name, glibc_version):
670
+ yield linux.replace("linux", name)
671
+ break
672
+ # Support for a later manylinux implies support for an earlier version.
673
+ for name, _ in manylinux_support_iter:
674
+ yield linux.replace("linux", name)
675
+ yield linux
676
+
677
+
678
+ def _generic_platforms():
679
+ # type: () -> Iterator[str]
680
+ yield _normalize_string(distutils.util.get_platform())
681
+
682
+
683
+ def _platform_tags():
684
+ # type: () -> Iterator[str]
685
+ """
686
+ Provides the platform tags for this installation.
687
+ """
688
+ if platform.system() == "Darwin":
689
+ return mac_platforms()
690
+ elif platform.system() == "Linux":
691
+ return _linux_platforms()
692
+ else:
693
+ return _generic_platforms()
694
+
695
+
696
+ def interpreter_name():
697
+ # type: () -> str
698
+ """
699
+ Returns the name of the running interpreter.
700
+ """
701
+ try:
702
+ name = sys.implementation.name # type: ignore
703
+ except AttributeError: # pragma: no cover
704
+ # Python 2.7 compatibility.
705
+ name = platform.python_implementation().lower()
706
+ return INTERPRETER_SHORT_NAMES.get(name) or name
707
+
708
+
709
+ def interpreter_version(**kwargs):
710
+ # type: (bool) -> str
711
+ """
712
+ Returns the version of the running interpreter.
713
+ """
714
+ warn = _warn_keyword_parameter("interpreter_version", kwargs)
715
+ version = _get_config_var("py_version_nodot", warn=warn)
716
+ if version:
717
+ version = str(version)
718
+ else:
719
+ version = _version_nodot(sys.version_info[:2])
720
+ return version
721
+
722
+
723
+ def _version_nodot(version):
724
+ # type: (PythonVersion) -> str
725
+ if any(v >= 10 for v in version):
726
+ sep = "_"
727
+ else:
728
+ sep = ""
729
+ return sep.join(map(str, version))
730
+
731
+
732
+ def sys_tags(**kwargs):
733
+ # type: (bool) -> Iterator[Tag]
734
+ """
735
+ Returns the sequence of tag triples for the running interpreter.
736
+
737
+ The order of the sequence corresponds to priority order for the
738
+ interpreter, from most to least important.
739
+ """
740
+ warn = _warn_keyword_parameter("sys_tags", kwargs)
741
+
742
+ interp_name = interpreter_name()
743
+ if interp_name == "cp":
744
+ for tag in cpython_tags(warn=warn):
745
+ yield tag
746
+ else:
747
+ for tag in generic_tags():
748
+ yield tag
749
+
750
+ for tag in compatible_tags():
751
+ yield tag
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/utils.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+ from __future__ import absolute_import, division, print_function
5
+
6
+ import re
7
+
8
+ from ._typing import TYPE_CHECKING, cast
9
+ from .version import InvalidVersion, Version
10
+
11
+ if TYPE_CHECKING: # pragma: no cover
12
+ from typing import NewType, Union
13
+
14
+ NormalizedName = NewType("NormalizedName", str)
15
+
16
+ _canonicalize_regex = re.compile(r"[-_.]+")
17
+
18
+
19
+ def canonicalize_name(name):
20
+ # type: (str) -> NormalizedName
21
+ # This is taken from PEP 503.
22
+ value = _canonicalize_regex.sub("-", name).lower()
23
+ return cast("NormalizedName", value)
24
+
25
+
26
+ def canonicalize_version(_version):
27
+ # type: (str) -> Union[Version, str]
28
+ """
29
+ This is very similar to Version.__str__, but has one subtle difference
30
+ with the way it handles the release segment.
31
+ """
32
+
33
+ try:
34
+ version = Version(_version)
35
+ except InvalidVersion:
36
+ # Legacy versions cannot be normalized
37
+ return _version
38
+
39
+ parts = []
40
+
41
+ # Epoch
42
+ if version.epoch != 0:
43
+ parts.append("{0}!".format(version.epoch))
44
+
45
+ # Release segment
46
+ # NB: This strips trailing '.0's to normalize
47
+ parts.append(re.sub(r"(\.0)+$", "", ".".join(str(x) for x in version.release)))
48
+
49
+ # Pre-release
50
+ if version.pre is not None:
51
+ parts.append("".join(str(x) for x in version.pre))
52
+
53
+ # Post-release
54
+ if version.post is not None:
55
+ parts.append(".post{0}".format(version.post))
56
+
57
+ # Development release
58
+ if version.dev is not None:
59
+ parts.append(".dev{0}".format(version.dev))
60
+
61
+ # Local version segment
62
+ if version.local is not None:
63
+ parts.append("+{0}".format(version.local))
64
+
65
+ return "".join(parts)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/version.py ADDED
@@ -0,0 +1,535 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+ from __future__ import absolute_import, division, print_function
5
+
6
+ import collections
7
+ import itertools
8
+ import re
9
+
10
+ from ._structures import Infinity, NegativeInfinity
11
+ from ._typing import TYPE_CHECKING
12
+
13
+ if TYPE_CHECKING: # pragma: no cover
14
+ from typing import Callable, Iterator, List, Optional, SupportsInt, Tuple, Union
15
+
16
+ from ._structures import InfinityType, NegativeInfinityType
17
+
18
+ InfiniteTypes = Union[InfinityType, NegativeInfinityType]
19
+ PrePostDevType = Union[InfiniteTypes, Tuple[str, int]]
20
+ SubLocalType = Union[InfiniteTypes, int, str]
21
+ LocalType = Union[
22
+ NegativeInfinityType,
23
+ Tuple[
24
+ Union[
25
+ SubLocalType,
26
+ Tuple[SubLocalType, str],
27
+ Tuple[NegativeInfinityType, SubLocalType],
28
+ ],
29
+ ...,
30
+ ],
31
+ ]
32
+ CmpKey = Tuple[
33
+ int, Tuple[int, ...], PrePostDevType, PrePostDevType, PrePostDevType, LocalType
34
+ ]
35
+ LegacyCmpKey = Tuple[int, Tuple[str, ...]]
36
+ VersionComparisonMethod = Callable[
37
+ [Union[CmpKey, LegacyCmpKey], Union[CmpKey, LegacyCmpKey]], bool
38
+ ]
39
+
40
+ __all__ = ["parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"]
41
+
42
+
43
+ _Version = collections.namedtuple(
44
+ "_Version", ["epoch", "release", "dev", "pre", "post", "local"]
45
+ )
46
+
47
+
48
+ def parse(version):
49
+ # type: (str) -> Union[LegacyVersion, Version]
50
+ """
51
+ Parse the given version string and return either a :class:`Version` object
52
+ or a :class:`LegacyVersion` object depending on if the given version is
53
+ a valid PEP 440 version or a legacy version.
54
+ """
55
+ try:
56
+ return Version(version)
57
+ except InvalidVersion:
58
+ return LegacyVersion(version)
59
+
60
+
61
+ class InvalidVersion(ValueError):
62
+ """
63
+ An invalid version was found, users should refer to PEP 440.
64
+ """
65
+
66
+
67
+ class _BaseVersion(object):
68
+ _key = None # type: Union[CmpKey, LegacyCmpKey]
69
+
70
+ def __hash__(self):
71
+ # type: () -> int
72
+ return hash(self._key)
73
+
74
+ def __lt__(self, other):
75
+ # type: (_BaseVersion) -> bool
76
+ return self._compare(other, lambda s, o: s < o)
77
+
78
+ def __le__(self, other):
79
+ # type: (_BaseVersion) -> bool
80
+ return self._compare(other, lambda s, o: s <= o)
81
+
82
+ def __eq__(self, other):
83
+ # type: (object) -> bool
84
+ return self._compare(other, lambda s, o: s == o)
85
+
86
+ def __ge__(self, other):
87
+ # type: (_BaseVersion) -> bool
88
+ return self._compare(other, lambda s, o: s >= o)
89
+
90
+ def __gt__(self, other):
91
+ # type: (_BaseVersion) -> bool
92
+ return self._compare(other, lambda s, o: s > o)
93
+
94
+ def __ne__(self, other):
95
+ # type: (object) -> bool
96
+ return self._compare(other, lambda s, o: s != o)
97
+
98
+ def _compare(self, other, method):
99
+ # type: (object, VersionComparisonMethod) -> Union[bool, NotImplemented]
100
+ if not isinstance(other, _BaseVersion):
101
+ return NotImplemented
102
+
103
+ return method(self._key, other._key)
104
+
105
+
106
+ class LegacyVersion(_BaseVersion):
107
+ def __init__(self, version):
108
+ # type: (str) -> None
109
+ self._version = str(version)
110
+ self._key = _legacy_cmpkey(self._version)
111
+
112
+ def __str__(self):
113
+ # type: () -> str
114
+ return self._version
115
+
116
+ def __repr__(self):
117
+ # type: () -> str
118
+ return "<LegacyVersion({0})>".format(repr(str(self)))
119
+
120
+ @property
121
+ def public(self):
122
+ # type: () -> str
123
+ return self._version
124
+
125
+ @property
126
+ def base_version(self):
127
+ # type: () -> str
128
+ return self._version
129
+
130
+ @property
131
+ def epoch(self):
132
+ # type: () -> int
133
+ return -1
134
+
135
+ @property
136
+ def release(self):
137
+ # type: () -> None
138
+ return None
139
+
140
+ @property
141
+ def pre(self):
142
+ # type: () -> None
143
+ return None
144
+
145
+ @property
146
+ def post(self):
147
+ # type: () -> None
148
+ return None
149
+
150
+ @property
151
+ def dev(self):
152
+ # type: () -> None
153
+ return None
154
+
155
+ @property
156
+ def local(self):
157
+ # type: () -> None
158
+ return None
159
+
160
+ @property
161
+ def is_prerelease(self):
162
+ # type: () -> bool
163
+ return False
164
+
165
+ @property
166
+ def is_postrelease(self):
167
+ # type: () -> bool
168
+ return False
169
+
170
+ @property
171
+ def is_devrelease(self):
172
+ # type: () -> bool
173
+ return False
174
+
175
+
176
+ _legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE)
177
+
178
+ _legacy_version_replacement_map = {
179
+ "pre": "c",
180
+ "preview": "c",
181
+ "-": "final-",
182
+ "rc": "c",
183
+ "dev": "@",
184
+ }
185
+
186
+
187
+ def _parse_version_parts(s):
188
+ # type: (str) -> Iterator[str]
189
+ for part in _legacy_version_component_re.split(s):
190
+ part = _legacy_version_replacement_map.get(part, part)
191
+
192
+ if not part or part == ".":
193
+ continue
194
+
195
+ if part[:1] in "0123456789":
196
+ # pad for numeric comparison
197
+ yield part.zfill(8)
198
+ else:
199
+ yield "*" + part
200
+
201
+ # ensure that alpha/beta/candidate are before final
202
+ yield "*final"
203
+
204
+
205
+ def _legacy_cmpkey(version):
206
+ # type: (str) -> LegacyCmpKey
207
+
208
+ # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch
209
+ # greater than or equal to 0. This will effectively put the LegacyVersion,
210
+ # which uses the defacto standard originally implemented by setuptools,
211
+ # as before all PEP 440 versions.
212
+ epoch = -1
213
+
214
+ # This scheme is taken from pkg_resources.parse_version setuptools prior to
215
+ # it's adoption of the packaging library.
216
+ parts = [] # type: List[str]
217
+ for part in _parse_version_parts(version.lower()):
218
+ if part.startswith("*"):
219
+ # remove "-" before a prerelease tag
220
+ if part < "*final":
221
+ while parts and parts[-1] == "*final-":
222
+ parts.pop()
223
+
224
+ # remove trailing zeros from each series of numeric parts
225
+ while parts and parts[-1] == "00000000":
226
+ parts.pop()
227
+
228
+ parts.append(part)
229
+
230
+ return epoch, tuple(parts)
231
+
232
+
233
+ # Deliberately not anchored to the start and end of the string, to make it
234
+ # easier for 3rd party code to reuse
235
+ VERSION_PATTERN = r"""
236
+ v?
237
+ (?:
238
+ (?:(?P<epoch>[0-9]+)!)? # epoch
239
+ (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment
240
+ (?P<pre> # pre-release
241
+ [-_\.]?
242
+ (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview))
243
+ [-_\.]?
244
+ (?P<pre_n>[0-9]+)?
245
+ )?
246
+ (?P<post> # post release
247
+ (?:-(?P<post_n1>[0-9]+))
248
+ |
249
+ (?:
250
+ [-_\.]?
251
+ (?P<post_l>post|rev|r)
252
+ [-_\.]?
253
+ (?P<post_n2>[0-9]+)?
254
+ )
255
+ )?
256
+ (?P<dev> # dev release
257
+ [-_\.]?
258
+ (?P<dev_l>dev)
259
+ [-_\.]?
260
+ (?P<dev_n>[0-9]+)?
261
+ )?
262
+ )
263
+ (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version
264
+ """
265
+
266
+
267
+ class Version(_BaseVersion):
268
+
269
+ _regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
270
+
271
+ def __init__(self, version):
272
+ # type: (str) -> None
273
+
274
+ # Validate the version and parse it into pieces
275
+ match = self._regex.search(version)
276
+ if not match:
277
+ raise InvalidVersion("Invalid version: '{0}'".format(version))
278
+
279
+ # Store the parsed out pieces of the version
280
+ self._version = _Version(
281
+ epoch=int(match.group("epoch")) if match.group("epoch") else 0,
282
+ release=tuple(int(i) for i in match.group("release").split(".")),
283
+ pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
284
+ post=_parse_letter_version(
285
+ match.group("post_l"), match.group("post_n1") or match.group("post_n2")
286
+ ),
287
+ dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
288
+ local=_parse_local_version(match.group("local")),
289
+ )
290
+
291
+ # Generate a key which will be used for sorting
292
+ self._key = _cmpkey(
293
+ self._version.epoch,
294
+ self._version.release,
295
+ self._version.pre,
296
+ self._version.post,
297
+ self._version.dev,
298
+ self._version.local,
299
+ )
300
+
301
+ def __repr__(self):
302
+ # type: () -> str
303
+ return "<Version({0})>".format(repr(str(self)))
304
+
305
+ def __str__(self):
306
+ # type: () -> str
307
+ parts = []
308
+
309
+ # Epoch
310
+ if self.epoch != 0:
311
+ parts.append("{0}!".format(self.epoch))
312
+
313
+ # Release segment
314
+ parts.append(".".join(str(x) for x in self.release))
315
+
316
+ # Pre-release
317
+ if self.pre is not None:
318
+ parts.append("".join(str(x) for x in self.pre))
319
+
320
+ # Post-release
321
+ if self.post is not None:
322
+ parts.append(".post{0}".format(self.post))
323
+
324
+ # Development release
325
+ if self.dev is not None:
326
+ parts.append(".dev{0}".format(self.dev))
327
+
328
+ # Local version segment
329
+ if self.local is not None:
330
+ parts.append("+{0}".format(self.local))
331
+
332
+ return "".join(parts)
333
+
334
+ @property
335
+ def epoch(self):
336
+ # type: () -> int
337
+ _epoch = self._version.epoch # type: int
338
+ return _epoch
339
+
340
+ @property
341
+ def release(self):
342
+ # type: () -> Tuple[int, ...]
343
+ _release = self._version.release # type: Tuple[int, ...]
344
+ return _release
345
+
346
+ @property
347
+ def pre(self):
348
+ # type: () -> Optional[Tuple[str, int]]
349
+ _pre = self._version.pre # type: Optional[Tuple[str, int]]
350
+ return _pre
351
+
352
+ @property
353
+ def post(self):
354
+ # type: () -> Optional[Tuple[str, int]]
355
+ return self._version.post[1] if self._version.post else None
356
+
357
+ @property
358
+ def dev(self):
359
+ # type: () -> Optional[Tuple[str, int]]
360
+ return self._version.dev[1] if self._version.dev else None
361
+
362
+ @property
363
+ def local(self):
364
+ # type: () -> Optional[str]
365
+ if self._version.local:
366
+ return ".".join(str(x) for x in self._version.local)
367
+ else:
368
+ return None
369
+
370
+ @property
371
+ def public(self):
372
+ # type: () -> str
373
+ return str(self).split("+", 1)[0]
374
+
375
+ @property
376
+ def base_version(self):
377
+ # type: () -> str
378
+ parts = []
379
+
380
+ # Epoch
381
+ if self.epoch != 0:
382
+ parts.append("{0}!".format(self.epoch))
383
+
384
+ # Release segment
385
+ parts.append(".".join(str(x) for x in self.release))
386
+
387
+ return "".join(parts)
388
+
389
+ @property
390
+ def is_prerelease(self):
391
+ # type: () -> bool
392
+ return self.dev is not None or self.pre is not None
393
+
394
+ @property
395
+ def is_postrelease(self):
396
+ # type: () -> bool
397
+ return self.post is not None
398
+
399
+ @property
400
+ def is_devrelease(self):
401
+ # type: () -> bool
402
+ return self.dev is not None
403
+
404
+ @property
405
+ def major(self):
406
+ # type: () -> int
407
+ return self.release[0] if len(self.release) >= 1 else 0
408
+
409
+ @property
410
+ def minor(self):
411
+ # type: () -> int
412
+ return self.release[1] if len(self.release) >= 2 else 0
413
+
414
+ @property
415
+ def micro(self):
416
+ # type: () -> int
417
+ return self.release[2] if len(self.release) >= 3 else 0
418
+
419
+
420
+ def _parse_letter_version(
421
+ letter, # type: str
422
+ number, # type: Union[str, bytes, SupportsInt]
423
+ ):
424
+ # type: (...) -> Optional[Tuple[str, int]]
425
+
426
+ if letter:
427
+ # We consider there to be an implicit 0 in a pre-release if there is
428
+ # not a numeral associated with it.
429
+ if number is None:
430
+ number = 0
431
+
432
+ # We normalize any letters to their lower case form
433
+ letter = letter.lower()
434
+
435
+ # We consider some words to be alternate spellings of other words and
436
+ # in those cases we want to normalize the spellings to our preferred
437
+ # spelling.
438
+ if letter == "alpha":
439
+ letter = "a"
440
+ elif letter == "beta":
441
+ letter = "b"
442
+ elif letter in ["c", "pre", "preview"]:
443
+ letter = "rc"
444
+ elif letter in ["rev", "r"]:
445
+ letter = "post"
446
+
447
+ return letter, int(number)
448
+ if not letter and number:
449
+ # We assume if we are given a number, but we are not given a letter
450
+ # then this is using the implicit post release syntax (e.g. 1.0-1)
451
+ letter = "post"
452
+
453
+ return letter, int(number)
454
+
455
+ return None
456
+
457
+
458
+ _local_version_separators = re.compile(r"[\._-]")
459
+
460
+
461
+ def _parse_local_version(local):
462
+ # type: (str) -> Optional[LocalType]
463
+ """
464
+ Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
465
+ """
466
+ if local is not None:
467
+ return tuple(
468
+ part.lower() if not part.isdigit() else int(part)
469
+ for part in _local_version_separators.split(local)
470
+ )
471
+ return None
472
+
473
+
474
+ def _cmpkey(
475
+ epoch, # type: int
476
+ release, # type: Tuple[int, ...]
477
+ pre, # type: Optional[Tuple[str, int]]
478
+ post, # type: Optional[Tuple[str, int]]
479
+ dev, # type: Optional[Tuple[str, int]]
480
+ local, # type: Optional[Tuple[SubLocalType]]
481
+ ):
482
+ # type: (...) -> CmpKey
483
+
484
+ # When we compare a release version, we want to compare it with all of the
485
+ # trailing zeros removed. So we'll use a reverse the list, drop all the now
486
+ # leading zeros until we come to something non zero, then take the rest
487
+ # re-reverse it back into the correct order and make it a tuple and use
488
+ # that for our sorting key.
489
+ _release = tuple(
490
+ reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
491
+ )
492
+
493
+ # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
494
+ # We'll do this by abusing the pre segment, but we _only_ want to do this
495
+ # if there is not a pre or a post segment. If we have one of those then
496
+ # the normal sorting rules will handle this case correctly.
497
+ if pre is None and post is None and dev is not None:
498
+ _pre = NegativeInfinity # type: PrePostDevType
499
+ # Versions without a pre-release (except as noted above) should sort after
500
+ # those with one.
501
+ elif pre is None:
502
+ _pre = Infinity
503
+ else:
504
+ _pre = pre
505
+
506
+ # Versions without a post segment should sort before those with one.
507
+ if post is None:
508
+ _post = NegativeInfinity # type: PrePostDevType
509
+
510
+ else:
511
+ _post = post
512
+
513
+ # Versions without a development segment should sort after those with one.
514
+ if dev is None:
515
+ _dev = Infinity # type: PrePostDevType
516
+
517
+ else:
518
+ _dev = dev
519
+
520
+ if local is None:
521
+ # Versions without a local segment should sort before those with one.
522
+ _local = NegativeInfinity # type: LocalType
523
+ else:
524
+ # Versions with a local segment need that segment parsed to implement
525
+ # the sorting rules in PEP440.
526
+ # - Alpha numeric segments sort before numeric segments
527
+ # - Alpha numeric segments sort lexicographically
528
+ # - Numeric segments sort numerically
529
+ # - Shorter versions sort before longer versions when the prefixes
530
+ # match exactly
531
+ _local = tuple(
532
+ (i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
533
+ )
534
+
535
+ return epoch, _release, _pre, _post, _dev, _local
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/_vendor/pyparsing.py ADDED
The diff for this file is too large to render. See raw diff
 
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/archive_util.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Utilities for extracting common archive formats"""
2
+
3
+ import zipfile
4
+ import tarfile
5
+ import os
6
+ import shutil
7
+ import posixpath
8
+ import contextlib
9
+ from distutils.errors import DistutilsError
10
+
11
+ from pkg_resources import ensure_directory
12
+
13
+ __all__ = [
14
+ "unpack_archive", "unpack_zipfile", "unpack_tarfile", "default_filter",
15
+ "UnrecognizedFormat", "extraction_drivers", "unpack_directory",
16
+ ]
17
+
18
+
19
+ class UnrecognizedFormat(DistutilsError):
20
+ """Couldn't recognize the archive type"""
21
+
22
+
23
+ def default_filter(src, dst):
24
+ """The default progress/filter callback; returns True for all files"""
25
+ return dst
26
+
27
+
28
+ def unpack_archive(
29
+ filename, extract_dir, progress_filter=default_filter,
30
+ drivers=None):
31
+ """Unpack `filename` to `extract_dir`, or raise ``UnrecognizedFormat``
32
+
33
+ `progress_filter` is a function taking two arguments: a source path
34
+ internal to the archive ('/'-separated), and a filesystem path where it
35
+ will be extracted. The callback must return the desired extract path
36
+ (which may be the same as the one passed in), or else ``None`` to skip
37
+ that file or directory. The callback can thus be used to report on the
38
+ progress of the extraction, as well as to filter the items extracted or
39
+ alter their extraction paths.
40
+
41
+ `drivers`, if supplied, must be a non-empty sequence of functions with the
42
+ same signature as this function (minus the `drivers` argument), that raise
43
+ ``UnrecognizedFormat`` if they do not support extracting the designated
44
+ archive type. The `drivers` are tried in sequence until one is found that
45
+ does not raise an error, or until all are exhausted (in which case
46
+ ``UnrecognizedFormat`` is raised). If you do not supply a sequence of
47
+ drivers, the module's ``extraction_drivers`` constant will be used, which
48
+ means that ``unpack_zipfile`` and ``unpack_tarfile`` will be tried, in that
49
+ order.
50
+ """
51
+ for driver in drivers or extraction_drivers:
52
+ try:
53
+ driver(filename, extract_dir, progress_filter)
54
+ except UnrecognizedFormat:
55
+ continue
56
+ else:
57
+ return
58
+ else:
59
+ raise UnrecognizedFormat(
60
+ "Not a recognized archive type: %s" % filename
61
+ )
62
+
63
+
64
+ def unpack_directory(filename, extract_dir, progress_filter=default_filter):
65
+ """"Unpack" a directory, using the same interface as for archives
66
+
67
+ Raises ``UnrecognizedFormat`` if `filename` is not a directory
68
+ """
69
+ if not os.path.isdir(filename):
70
+ raise UnrecognizedFormat("%s is not a directory" % filename)
71
+
72
+ paths = {
73
+ filename: ('', extract_dir),
74
+ }
75
+ for base, dirs, files in os.walk(filename):
76
+ src, dst = paths[base]
77
+ for d in dirs:
78
+ paths[os.path.join(base, d)] = src + d + '/', os.path.join(dst, d)
79
+ for f in files:
80
+ target = os.path.join(dst, f)
81
+ target = progress_filter(src + f, target)
82
+ if not target:
83
+ # skip non-files
84
+ continue
85
+ ensure_directory(target)
86
+ f = os.path.join(base, f)
87
+ shutil.copyfile(f, target)
88
+ shutil.copystat(f, target)
89
+
90
+
91
+ def unpack_zipfile(filename, extract_dir, progress_filter=default_filter):
92
+ """Unpack zip `filename` to `extract_dir`
93
+
94
+ Raises ``UnrecognizedFormat`` if `filename` is not a zipfile (as determined
95
+ by ``zipfile.is_zipfile()``). See ``unpack_archive()`` for an explanation
96
+ of the `progress_filter` argument.
97
+ """
98
+
99
+ if not zipfile.is_zipfile(filename):
100
+ raise UnrecognizedFormat("%s is not a zip file" % (filename,))
101
+
102
+ with zipfile.ZipFile(filename) as z:
103
+ for info in z.infolist():
104
+ name = info.filename
105
+
106
+ # don't extract absolute paths or ones with .. in them
107
+ if name.startswith('/') or '..' in name.split('/'):
108
+ continue
109
+
110
+ target = os.path.join(extract_dir, *name.split('/'))
111
+ target = progress_filter(name, target)
112
+ if not target:
113
+ continue
114
+ if name.endswith('/'):
115
+ # directory
116
+ ensure_directory(target)
117
+ else:
118
+ # file
119
+ ensure_directory(target)
120
+ data = z.read(info.filename)
121
+ with open(target, 'wb') as f:
122
+ f.write(data)
123
+ unix_attributes = info.external_attr >> 16
124
+ if unix_attributes:
125
+ os.chmod(target, unix_attributes)
126
+
127
+
128
+ def _resolve_tar_file_or_dir(tar_obj, tar_member_obj):
129
+ """Resolve any links and extract link targets as normal files."""
130
+ while tar_member_obj is not None and (
131
+ tar_member_obj.islnk() or tar_member_obj.issym()):
132
+ linkpath = tar_member_obj.linkname
133
+ if tar_member_obj.issym():
134
+ base = posixpath.dirname(tar_member_obj.name)
135
+ linkpath = posixpath.join(base, linkpath)
136
+ linkpath = posixpath.normpath(linkpath)
137
+ tar_member_obj = tar_obj._getmember(linkpath)
138
+
139
+ is_file_or_dir = (
140
+ tar_member_obj is not None and
141
+ (tar_member_obj.isfile() or tar_member_obj.isdir())
142
+ )
143
+ if is_file_or_dir:
144
+ return tar_member_obj
145
+
146
+ raise LookupError('Got unknown file type')
147
+
148
+
149
+ def _iter_open_tar(tar_obj, extract_dir, progress_filter):
150
+ """Emit member-destination pairs from a tar archive."""
151
+ # don't do any chowning!
152
+ tar_obj.chown = lambda *args: None
153
+
154
+ with contextlib.closing(tar_obj):
155
+ for member in tar_obj:
156
+ name = member.name
157
+ # don't extract absolute paths or ones with .. in them
158
+ if name.startswith('/') or '..' in name.split('/'):
159
+ continue
160
+
161
+ prelim_dst = os.path.join(extract_dir, *name.split('/'))
162
+
163
+ try:
164
+ member = _resolve_tar_file_or_dir(tar_obj, member)
165
+ except LookupError:
166
+ continue
167
+
168
+ final_dst = progress_filter(name, prelim_dst)
169
+ if not final_dst:
170
+ continue
171
+
172
+ if final_dst.endswith(os.sep):
173
+ final_dst = final_dst[:-1]
174
+
175
+ yield member, final_dst
176
+
177
+
178
+ def unpack_tarfile(filename, extract_dir, progress_filter=default_filter):
179
+ """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir`
180
+
181
+ Raises ``UnrecognizedFormat`` if `filename` is not a tarfile (as determined
182
+ by ``tarfile.open()``). See ``unpack_archive()`` for an explanation
183
+ of the `progress_filter` argument.
184
+ """
185
+ try:
186
+ tarobj = tarfile.open(filename)
187
+ except tarfile.TarError as e:
188
+ raise UnrecognizedFormat(
189
+ "%s is not a compressed or uncompressed tar file" % (filename,)
190
+ ) from e
191
+
192
+ for member, final_dst in _iter_open_tar(
193
+ tarobj, extract_dir, progress_filter,
194
+ ):
195
+ try:
196
+ # XXX Ugh
197
+ tarobj._extract_member(member, final_dst)
198
+ except tarfile.ExtractError:
199
+ # chown/chmod/mkfifo/mknode/makedev failed
200
+ pass
201
+
202
+ return True
203
+
204
+
205
+ extraction_drivers = unpack_directory, unpack_zipfile, unpack_tarfile
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/build_meta.py ADDED
@@ -0,0 +1,281 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """A PEP 517 interface to setuptools
2
+
3
+ Previously, when a user or a command line tool (let's call it a "frontend")
4
+ needed to make a request of setuptools to take a certain action, for
5
+ example, generating a list of installation requirements, the frontend would
6
+ would call "setup.py egg_info" or "setup.py bdist_wheel" on the command line.
7
+
8
+ PEP 517 defines a different method of interfacing with setuptools. Rather
9
+ than calling "setup.py" directly, the frontend should:
10
+
11
+ 1. Set the current directory to the directory with a setup.py file
12
+ 2. Import this module into a safe python interpreter (one in which
13
+ setuptools can potentially set global variables or crash hard).
14
+ 3. Call one of the functions defined in PEP 517.
15
+
16
+ What each function does is defined in PEP 517. However, here is a "casual"
17
+ definition of the functions (this definition should not be relied on for
18
+ bug reports or API stability):
19
+
20
+ - `build_wheel`: build a wheel in the folder and return the basename
21
+ - `get_requires_for_build_wheel`: get the `setup_requires` to build
22
+ - `prepare_metadata_for_build_wheel`: get the `install_requires`
23
+ - `build_sdist`: build an sdist in the folder and return the basename
24
+ - `get_requires_for_build_sdist`: get the `setup_requires` to build
25
+
26
+ Again, this is not a formal definition! Just a "taste" of the module.
27
+ """
28
+
29
+ import io
30
+ import os
31
+ import sys
32
+ import tokenize
33
+ import shutil
34
+ import contextlib
35
+ import tempfile
36
+
37
+ import setuptools
38
+ import distutils
39
+
40
+ from pkg_resources import parse_requirements
41
+
42
+ __all__ = ['get_requires_for_build_sdist',
43
+ 'get_requires_for_build_wheel',
44
+ 'prepare_metadata_for_build_wheel',
45
+ 'build_wheel',
46
+ 'build_sdist',
47
+ '__legacy__',
48
+ 'SetupRequirementsError']
49
+
50
+
51
+ class SetupRequirementsError(BaseException):
52
+ def __init__(self, specifiers):
53
+ self.specifiers = specifiers
54
+
55
+
56
+ class Distribution(setuptools.dist.Distribution):
57
+ def fetch_build_eggs(self, specifiers):
58
+ specifier_list = list(map(str, parse_requirements(specifiers)))
59
+
60
+ raise SetupRequirementsError(specifier_list)
61
+
62
+ @classmethod
63
+ @contextlib.contextmanager
64
+ def patch(cls):
65
+ """
66
+ Replace
67
+ distutils.dist.Distribution with this class
68
+ for the duration of this context.
69
+ """
70
+ orig = distutils.core.Distribution
71
+ distutils.core.Distribution = cls
72
+ try:
73
+ yield
74
+ finally:
75
+ distutils.core.Distribution = orig
76
+
77
+
78
+ @contextlib.contextmanager
79
+ def no_install_setup_requires():
80
+ """Temporarily disable installing setup_requires
81
+
82
+ Under PEP 517, the backend reports build dependencies to the frontend,
83
+ and the frontend is responsible for ensuring they're installed.
84
+ So setuptools (acting as a backend) should not try to install them.
85
+ """
86
+ orig = setuptools._install_setup_requires
87
+ setuptools._install_setup_requires = lambda attrs: None
88
+ try:
89
+ yield
90
+ finally:
91
+ setuptools._install_setup_requires = orig
92
+
93
+
94
+ def _get_immediate_subdirectories(a_dir):
95
+ return [name for name in os.listdir(a_dir)
96
+ if os.path.isdir(os.path.join(a_dir, name))]
97
+
98
+
99
+ def _file_with_extension(directory, extension):
100
+ matching = (
101
+ f for f in os.listdir(directory)
102
+ if f.endswith(extension)
103
+ )
104
+ try:
105
+ file, = matching
106
+ except ValueError:
107
+ raise ValueError(
108
+ 'No distribution was found. Ensure that `setup.py` '
109
+ 'is not empty and that it calls `setup()`.')
110
+ return file
111
+
112
+
113
+ def _open_setup_script(setup_script):
114
+ if not os.path.exists(setup_script):
115
+ # Supply a default setup.py
116
+ return io.StringIO(u"from setuptools import setup; setup()")
117
+
118
+ return getattr(tokenize, 'open', open)(setup_script)
119
+
120
+
121
+ class _BuildMetaBackend(object):
122
+
123
+ def _fix_config(self, config_settings):
124
+ config_settings = config_settings or {}
125
+ config_settings.setdefault('--global-option', [])
126
+ return config_settings
127
+
128
+ def _get_build_requires(self, config_settings, requirements):
129
+ config_settings = self._fix_config(config_settings)
130
+
131
+ sys.argv = sys.argv[:1] + ['egg_info'] + \
132
+ config_settings["--global-option"]
133
+ try:
134
+ with Distribution.patch():
135
+ self.run_setup()
136
+ except SetupRequirementsError as e:
137
+ requirements += e.specifiers
138
+
139
+ return requirements
140
+
141
+ def run_setup(self, setup_script='setup.py'):
142
+ # Note that we can reuse our build directory between calls
143
+ # Correctness comes first, then optimization later
144
+ __file__ = setup_script
145
+ __name__ = '__main__'
146
+
147
+ with _open_setup_script(__file__) as f:
148
+ code = f.read().replace(r'\r\n', r'\n')
149
+
150
+ exec(compile(code, __file__, 'exec'), locals())
151
+
152
+ def get_requires_for_build_wheel(self, config_settings=None):
153
+ config_settings = self._fix_config(config_settings)
154
+ return self._get_build_requires(
155
+ config_settings, requirements=['wheel'])
156
+
157
+ def get_requires_for_build_sdist(self, config_settings=None):
158
+ config_settings = self._fix_config(config_settings)
159
+ return self._get_build_requires(config_settings, requirements=[])
160
+
161
+ def prepare_metadata_for_build_wheel(self, metadata_directory,
162
+ config_settings=None):
163
+ sys.argv = sys.argv[:1] + [
164
+ 'dist_info', '--egg-base', metadata_directory]
165
+ with no_install_setup_requires():
166
+ self.run_setup()
167
+
168
+ dist_info_directory = metadata_directory
169
+ while True:
170
+ dist_infos = [f for f in os.listdir(dist_info_directory)
171
+ if f.endswith('.dist-info')]
172
+
173
+ if (
174
+ len(dist_infos) == 0 and
175
+ len(_get_immediate_subdirectories(dist_info_directory)) == 1
176
+ ):
177
+
178
+ dist_info_directory = os.path.join(
179
+ dist_info_directory, os.listdir(dist_info_directory)[0])
180
+ continue
181
+
182
+ assert len(dist_infos) == 1
183
+ break
184
+
185
+ # PEP 517 requires that the .dist-info directory be placed in the
186
+ # metadata_directory. To comply, we MUST copy the directory to the root
187
+ if dist_info_directory != metadata_directory:
188
+ shutil.move(
189
+ os.path.join(dist_info_directory, dist_infos[0]),
190
+ metadata_directory)
191
+ shutil.rmtree(dist_info_directory, ignore_errors=True)
192
+
193
+ return dist_infos[0]
194
+
195
+ def _build_with_temp_dir(self, setup_command, result_extension,
196
+ result_directory, config_settings):
197
+ config_settings = self._fix_config(config_settings)
198
+ result_directory = os.path.abspath(result_directory)
199
+
200
+ # Build in a temporary directory, then copy to the target.
201
+ os.makedirs(result_directory, exist_ok=True)
202
+ with tempfile.TemporaryDirectory(dir=result_directory) as tmp_dist_dir:
203
+ sys.argv = (sys.argv[:1] + setup_command +
204
+ ['--dist-dir', tmp_dist_dir] +
205
+ config_settings["--global-option"])
206
+ with no_install_setup_requires():
207
+ self.run_setup()
208
+
209
+ result_basename = _file_with_extension(
210
+ tmp_dist_dir, result_extension)
211
+ result_path = os.path.join(result_directory, result_basename)
212
+ if os.path.exists(result_path):
213
+ # os.rename will fail overwriting on non-Unix.
214
+ os.remove(result_path)
215
+ os.rename(os.path.join(tmp_dist_dir, result_basename), result_path)
216
+
217
+ return result_basename
218
+
219
+ def build_wheel(self, wheel_directory, config_settings=None,
220
+ metadata_directory=None):
221
+ return self._build_with_temp_dir(['bdist_wheel'], '.whl',
222
+ wheel_directory, config_settings)
223
+
224
+ def build_sdist(self, sdist_directory, config_settings=None):
225
+ return self._build_with_temp_dir(['sdist', '--formats', 'gztar'],
226
+ '.tar.gz', sdist_directory,
227
+ config_settings)
228
+
229
+
230
+ class _BuildMetaLegacyBackend(_BuildMetaBackend):
231
+ """Compatibility backend for setuptools
232
+
233
+ This is a version of setuptools.build_meta that endeavors
234
+ to maintain backwards
235
+ compatibility with pre-PEP 517 modes of invocation. It
236
+ exists as a temporary
237
+ bridge between the old packaging mechanism and the new
238
+ packaging mechanism,
239
+ and will eventually be removed.
240
+ """
241
+ def run_setup(self, setup_script='setup.py'):
242
+ # In order to maintain compatibility with scripts assuming that
243
+ # the setup.py script is in a directory on the PYTHONPATH, inject
244
+ # '' into sys.path. (pypa/setuptools#1642)
245
+ sys_path = list(sys.path) # Save the original path
246
+
247
+ script_dir = os.path.dirname(os.path.abspath(setup_script))
248
+ if script_dir not in sys.path:
249
+ sys.path.insert(0, script_dir)
250
+
251
+ # Some setup.py scripts (e.g. in pygame and numpy) use sys.argv[0] to
252
+ # get the directory of the source code. They expect it to refer to the
253
+ # setup.py script.
254
+ sys_argv_0 = sys.argv[0]
255
+ sys.argv[0] = setup_script
256
+
257
+ try:
258
+ super(_BuildMetaLegacyBackend,
259
+ self).run_setup(setup_script=setup_script)
260
+ finally:
261
+ # While PEP 517 frontends should be calling each hook in a fresh
262
+ # subprocess according to the standard (and thus it should not be
263
+ # strictly necessary to restore the old sys.path), we'll restore
264
+ # the original path so that the path manipulation does not persist
265
+ # within the hook after run_setup is called.
266
+ sys.path[:] = sys_path
267
+ sys.argv[0] = sys_argv_0
268
+
269
+
270
+ # The primary backend
271
+ _BACKEND = _BuildMetaBackend()
272
+
273
+ get_requires_for_build_wheel = _BACKEND.get_requires_for_build_wheel
274
+ get_requires_for_build_sdist = _BACKEND.get_requires_for_build_sdist
275
+ prepare_metadata_for_build_wheel = _BACKEND.prepare_metadata_for_build_wheel
276
+ build_wheel = _BACKEND.build_wheel
277
+ build_sdist = _BACKEND.build_sdist
278
+
279
+
280
+ # The legacy backend
281
+ __legacy__ = _BuildMetaLegacyBackend()
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/cli-32.exe ADDED
Binary file (65.5 kB). View file
 
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/cli-64.exe ADDED
Binary file (74.8 kB). View file
 
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/cli.exe ADDED
Binary file (65.5 kB). View file
 
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/command/alias.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from distutils.errors import DistutilsOptionError
2
+
3
+ from setuptools.command.setopt import edit_config, option_base, config_file
4
+
5
+
6
+ def shquote(arg):
7
+ """Quote an argument for later parsing by shlex.split()"""
8
+ for c in '"', "'", "\\", "#":
9
+ if c in arg:
10
+ return repr(arg)
11
+ if arg.split() != [arg]:
12
+ return repr(arg)
13
+ return arg
14
+
15
+
16
+ class alias(option_base):
17
+ """Define a shortcut that invokes one or more commands"""
18
+
19
+ description = "define a shortcut to invoke one or more commands"
20
+ command_consumes_arguments = True
21
+
22
+ user_options = [
23
+ ('remove', 'r', 'remove (unset) the alias'),
24
+ ] + option_base.user_options
25
+
26
+ boolean_options = option_base.boolean_options + ['remove']
27
+
28
+ def initialize_options(self):
29
+ option_base.initialize_options(self)
30
+ self.args = None
31
+ self.remove = None
32
+
33
+ def finalize_options(self):
34
+ option_base.finalize_options(self)
35
+ if self.remove and len(self.args) != 1:
36
+ raise DistutilsOptionError(
37
+ "Must specify exactly one argument (the alias name) when "
38
+ "using --remove"
39
+ )
40
+
41
+ def run(self):
42
+ aliases = self.distribution.get_option_dict('aliases')
43
+
44
+ if not self.args:
45
+ print("Command Aliases")
46
+ print("---------------")
47
+ for alias in aliases:
48
+ print("setup.py alias", format_alias(alias, aliases))
49
+ return
50
+
51
+ elif len(self.args) == 1:
52
+ alias, = self.args
53
+ if self.remove:
54
+ command = None
55
+ elif alias in aliases:
56
+ print("setup.py alias", format_alias(alias, aliases))
57
+ return
58
+ else:
59
+ print("No alias definition found for %r" % alias)
60
+ return
61
+ else:
62
+ alias = self.args[0]
63
+ command = ' '.join(map(shquote, self.args[1:]))
64
+
65
+ edit_config(self.filename, {'aliases': {alias: command}}, self.dry_run)
66
+
67
+
68
+ def format_alias(name, aliases):
69
+ source, command = aliases[name]
70
+ if source == config_file('global'):
71
+ source = '--global-config '
72
+ elif source == config_file('user'):
73
+ source = '--user-config '
74
+ elif source == config_file('local'):
75
+ source = ''
76
+ else:
77
+ source = '--filename=%r' % source
78
+ return source + name + ' ' + command
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/command/bdist_egg.py ADDED
@@ -0,0 +1,456 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """setuptools.command.bdist_egg
2
+
3
+ Build .egg distributions"""
4
+
5
+ from distutils.dir_util import remove_tree, mkpath
6
+ from distutils import log
7
+ from types import CodeType
8
+ import sys
9
+ import os
10
+ import re
11
+ import textwrap
12
+ import marshal
13
+
14
+ from pkg_resources import get_build_platform, Distribution, ensure_directory
15
+ from setuptools.extension import Library
16
+ from setuptools import Command
17
+
18
+ from sysconfig import get_path, get_python_version
19
+
20
+
21
+ def _get_purelib():
22
+ return get_path("purelib")
23
+
24
+
25
+ def strip_module(filename):
26
+ if '.' in filename:
27
+ filename = os.path.splitext(filename)[0]
28
+ if filename.endswith('module'):
29
+ filename = filename[:-6]
30
+ return filename
31
+
32
+
33
+ def sorted_walk(dir):
34
+ """Do os.walk in a reproducible way,
35
+ independent of indeterministic filesystem readdir order
36
+ """
37
+ for base, dirs, files in os.walk(dir):
38
+ dirs.sort()
39
+ files.sort()
40
+ yield base, dirs, files
41
+
42
+
43
+ def write_stub(resource, pyfile):
44
+ _stub_template = textwrap.dedent("""
45
+ def __bootstrap__():
46
+ global __bootstrap__, __loader__, __file__
47
+ import sys, pkg_resources, importlib.util
48
+ __file__ = pkg_resources.resource_filename(__name__, %r)
49
+ __loader__ = None; del __bootstrap__, __loader__
50
+ spec = importlib.util.spec_from_file_location(__name__,__file__)
51
+ mod = importlib.util.module_from_spec(spec)
52
+ spec.loader.exec_module(mod)
53
+ __bootstrap__()
54
+ """).lstrip()
55
+ with open(pyfile, 'w') as f:
56
+ f.write(_stub_template % resource)
57
+
58
+
59
+ class bdist_egg(Command):
60
+ description = "create an \"egg\" distribution"
61
+
62
+ user_options = [
63
+ ('bdist-dir=', 'b',
64
+ "temporary directory for creating the distribution"),
65
+ ('plat-name=', 'p', "platform name to embed in generated filenames "
66
+ "(default: %s)" % get_build_platform()),
67
+ ('exclude-source-files', None,
68
+ "remove all .py files from the generated egg"),
69
+ ('keep-temp', 'k',
70
+ "keep the pseudo-installation tree around after " +
71
+ "creating the distribution archive"),
72
+ ('dist-dir=', 'd',
73
+ "directory to put final built distributions in"),
74
+ ('skip-build', None,
75
+ "skip rebuilding everything (for testing/debugging)"),
76
+ ]
77
+
78
+ boolean_options = [
79
+ 'keep-temp', 'skip-build', 'exclude-source-files'
80
+ ]
81
+
82
+ def initialize_options(self):
83
+ self.bdist_dir = None
84
+ self.plat_name = None
85
+ self.keep_temp = 0
86
+ self.dist_dir = None
87
+ self.skip_build = 0
88
+ self.egg_output = None
89
+ self.exclude_source_files = None
90
+
91
+ def finalize_options(self):
92
+ ei_cmd = self.ei_cmd = self.get_finalized_command("egg_info")
93
+ self.egg_info = ei_cmd.egg_info
94
+
95
+ if self.bdist_dir is None:
96
+ bdist_base = self.get_finalized_command('bdist').bdist_base
97
+ self.bdist_dir = os.path.join(bdist_base, 'egg')
98
+
99
+ if self.plat_name is None:
100
+ self.plat_name = get_build_platform()
101
+
102
+ self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
103
+
104
+ if self.egg_output is None:
105
+
106
+ # Compute filename of the output egg
107
+ basename = Distribution(
108
+ None, None, ei_cmd.egg_name, ei_cmd.egg_version,
109
+ get_python_version(),
110
+ self.distribution.has_ext_modules() and self.plat_name
111
+ ).egg_name()
112
+
113
+ self.egg_output = os.path.join(self.dist_dir, basename + '.egg')
114
+
115
+ def do_install_data(self):
116
+ # Hack for packages that install data to install's --install-lib
117
+ self.get_finalized_command('install').install_lib = self.bdist_dir
118
+
119
+ site_packages = os.path.normcase(os.path.realpath(_get_purelib()))
120
+ old, self.distribution.data_files = self.distribution.data_files, []
121
+
122
+ for item in old:
123
+ if isinstance(item, tuple) and len(item) == 2:
124
+ if os.path.isabs(item[0]):
125
+ realpath = os.path.realpath(item[0])
126
+ normalized = os.path.normcase(realpath)
127
+ if normalized == site_packages or normalized.startswith(
128
+ site_packages + os.sep
129
+ ):
130
+ item = realpath[len(site_packages) + 1:], item[1]
131
+ # XXX else: raise ???
132
+ self.distribution.data_files.append(item)
133
+
134
+ try:
135
+ log.info("installing package data to %s", self.bdist_dir)
136
+ self.call_command('install_data', force=0, root=None)
137
+ finally:
138
+ self.distribution.data_files = old
139
+
140
+ def get_outputs(self):
141
+ return [self.egg_output]
142
+
143
+ def call_command(self, cmdname, **kw):
144
+ """Invoke reinitialized command `cmdname` with keyword args"""
145
+ for dirname in INSTALL_DIRECTORY_ATTRS:
146
+ kw.setdefault(dirname, self.bdist_dir)
147
+ kw.setdefault('skip_build', self.skip_build)
148
+ kw.setdefault('dry_run', self.dry_run)
149
+ cmd = self.reinitialize_command(cmdname, **kw)
150
+ self.run_command(cmdname)
151
+ return cmd
152
+
153
+ def run(self): # noqa: C901 # is too complex (14) # FIXME
154
+ # Generate metadata first
155
+ self.run_command("egg_info")
156
+ # We run install_lib before install_data, because some data hacks
157
+ # pull their data path from the install_lib command.
158
+ log.info("installing library code to %s", self.bdist_dir)
159
+ instcmd = self.get_finalized_command('install')
160
+ old_root = instcmd.root
161
+ instcmd.root = None
162
+ if self.distribution.has_c_libraries() and not self.skip_build:
163
+ self.run_command('build_clib')
164
+ cmd = self.call_command('install_lib', warn_dir=0)
165
+ instcmd.root = old_root
166
+
167
+ all_outputs, ext_outputs = self.get_ext_outputs()
168
+ self.stubs = []
169
+ to_compile = []
170
+ for (p, ext_name) in enumerate(ext_outputs):
171
+ filename, ext = os.path.splitext(ext_name)
172
+ pyfile = os.path.join(self.bdist_dir, strip_module(filename) +
173
+ '.py')
174
+ self.stubs.append(pyfile)
175
+ log.info("creating stub loader for %s", ext_name)
176
+ if not self.dry_run:
177
+ write_stub(os.path.basename(ext_name), pyfile)
178
+ to_compile.append(pyfile)
179
+ ext_outputs[p] = ext_name.replace(os.sep, '/')
180
+
181
+ if to_compile:
182
+ cmd.byte_compile(to_compile)
183
+ if self.distribution.data_files:
184
+ self.do_install_data()
185
+
186
+ # Make the EGG-INFO directory
187
+ archive_root = self.bdist_dir
188
+ egg_info = os.path.join(archive_root, 'EGG-INFO')
189
+ self.mkpath(egg_info)
190
+ if self.distribution.scripts:
191
+ script_dir = os.path.join(egg_info, 'scripts')
192
+ log.info("installing scripts to %s", script_dir)
193
+ self.call_command('install_scripts', install_dir=script_dir,
194
+ no_ep=1)
195
+
196
+ self.copy_metadata_to(egg_info)
197
+ native_libs = os.path.join(egg_info, "native_libs.txt")
198
+ if all_outputs:
199
+ log.info("writing %s", native_libs)
200
+ if not self.dry_run:
201
+ ensure_directory(native_libs)
202
+ libs_file = open(native_libs, 'wt')
203
+ libs_file.write('\n'.join(all_outputs))
204
+ libs_file.write('\n')
205
+ libs_file.close()
206
+ elif os.path.isfile(native_libs):
207
+ log.info("removing %s", native_libs)
208
+ if not self.dry_run:
209
+ os.unlink(native_libs)
210
+
211
+ write_safety_flag(
212
+ os.path.join(archive_root, 'EGG-INFO'), self.zip_safe()
213
+ )
214
+
215
+ if os.path.exists(os.path.join(self.egg_info, 'depends.txt')):
216
+ log.warn(
217
+ "WARNING: 'depends.txt' will not be used by setuptools 0.6!\n"
218
+ "Use the install_requires/extras_require setup() args instead."
219
+ )
220
+
221
+ if self.exclude_source_files:
222
+ self.zap_pyfiles()
223
+
224
+ # Make the archive
225
+ make_zipfile(self.egg_output, archive_root, verbose=self.verbose,
226
+ dry_run=self.dry_run, mode=self.gen_header())
227
+ if not self.keep_temp:
228
+ remove_tree(self.bdist_dir, dry_run=self.dry_run)
229
+
230
+ # Add to 'Distribution.dist_files' so that the "upload" command works
231
+ getattr(self.distribution, 'dist_files', []).append(
232
+ ('bdist_egg', get_python_version(), self.egg_output))
233
+
234
+ def zap_pyfiles(self):
235
+ log.info("Removing .py files from temporary directory")
236
+ for base, dirs, files in walk_egg(self.bdist_dir):
237
+ for name in files:
238
+ path = os.path.join(base, name)
239
+
240
+ if name.endswith('.py'):
241
+ log.debug("Deleting %s", path)
242
+ os.unlink(path)
243
+
244
+ if base.endswith('__pycache__'):
245
+ path_old = path
246
+
247
+ pattern = r'(?P<name>.+)\.(?P<magic>[^.]+)\.pyc'
248
+ m = re.match(pattern, name)
249
+ path_new = os.path.join(
250
+ base, os.pardir, m.group('name') + '.pyc')
251
+ log.info(
252
+ "Renaming file from [%s] to [%s]"
253
+ % (path_old, path_new))
254
+ try:
255
+ os.remove(path_new)
256
+ except OSError:
257
+ pass
258
+ os.rename(path_old, path_new)
259
+
260
+ def zip_safe(self):
261
+ safe = getattr(self.distribution, 'zip_safe', None)
262
+ if safe is not None:
263
+ return safe
264
+ log.warn("zip_safe flag not set; analyzing archive contents...")
265
+ return analyze_egg(self.bdist_dir, self.stubs)
266
+
267
+ def gen_header(self):
268
+ return 'w'
269
+
270
+ def copy_metadata_to(self, target_dir):
271
+ "Copy metadata (egg info) to the target_dir"
272
+ # normalize the path (so that a forward-slash in egg_info will
273
+ # match using startswith below)
274
+ norm_egg_info = os.path.normpath(self.egg_info)
275
+ prefix = os.path.join(norm_egg_info, '')
276
+ for path in self.ei_cmd.filelist.files:
277
+ if path.startswith(prefix):
278
+ target = os.path.join(target_dir, path[len(prefix):])
279
+ ensure_directory(target)
280
+ self.copy_file(path, target)
281
+
282
+ def get_ext_outputs(self):
283
+ """Get a list of relative paths to C extensions in the output distro"""
284
+
285
+ all_outputs = []
286
+ ext_outputs = []
287
+
288
+ paths = {self.bdist_dir: ''}
289
+ for base, dirs, files in sorted_walk(self.bdist_dir):
290
+ for filename in files:
291
+ if os.path.splitext(filename)[1].lower() in NATIVE_EXTENSIONS:
292
+ all_outputs.append(paths[base] + filename)
293
+ for filename in dirs:
294
+ paths[os.path.join(base, filename)] = (paths[base] +
295
+ filename + '/')
296
+
297
+ if self.distribution.has_ext_modules():
298
+ build_cmd = self.get_finalized_command('build_ext')
299
+ for ext in build_cmd.extensions:
300
+ if isinstance(ext, Library):
301
+ continue
302
+ fullname = build_cmd.get_ext_fullname(ext.name)
303
+ filename = build_cmd.get_ext_filename(fullname)
304
+ if not os.path.basename(filename).startswith('dl-'):
305
+ if os.path.exists(os.path.join(self.bdist_dir, filename)):
306
+ ext_outputs.append(filename)
307
+
308
+ return all_outputs, ext_outputs
309
+
310
+
311
+ NATIVE_EXTENSIONS = dict.fromkeys('.dll .so .dylib .pyd'.split())
312
+
313
+
314
+ def walk_egg(egg_dir):
315
+ """Walk an unpacked egg's contents, skipping the metadata directory"""
316
+ walker = sorted_walk(egg_dir)
317
+ base, dirs, files = next(walker)
318
+ if 'EGG-INFO' in dirs:
319
+ dirs.remove('EGG-INFO')
320
+ yield base, dirs, files
321
+ for bdf in walker:
322
+ yield bdf
323
+
324
+
325
+ def analyze_egg(egg_dir, stubs):
326
+ # check for existing flag in EGG-INFO
327
+ for flag, fn in safety_flags.items():
328
+ if os.path.exists(os.path.join(egg_dir, 'EGG-INFO', fn)):
329
+ return flag
330
+ if not can_scan():
331
+ return False
332
+ safe = True
333
+ for base, dirs, files in walk_egg(egg_dir):
334
+ for name in files:
335
+ if name.endswith('.py') or name.endswith('.pyw'):
336
+ continue
337
+ elif name.endswith('.pyc') or name.endswith('.pyo'):
338
+ # always scan, even if we already know we're not safe
339
+ safe = scan_module(egg_dir, base, name, stubs) and safe
340
+ return safe
341
+
342
+
343
+ def write_safety_flag(egg_dir, safe):
344
+ # Write or remove zip safety flag file(s)
345
+ for flag, fn in safety_flags.items():
346
+ fn = os.path.join(egg_dir, fn)
347
+ if os.path.exists(fn):
348
+ if safe is None or bool(safe) != flag:
349
+ os.unlink(fn)
350
+ elif safe is not None and bool(safe) == flag:
351
+ f = open(fn, 'wt')
352
+ f.write('\n')
353
+ f.close()
354
+
355
+
356
+ safety_flags = {
357
+ True: 'zip-safe',
358
+ False: 'not-zip-safe',
359
+ }
360
+
361
+
362
+ def scan_module(egg_dir, base, name, stubs):
363
+ """Check whether module possibly uses unsafe-for-zipfile stuff"""
364
+
365
+ filename = os.path.join(base, name)
366
+ if filename[:-1] in stubs:
367
+ return True # Extension module
368
+ pkg = base[len(egg_dir) + 1:].replace(os.sep, '.')
369
+ module = pkg + (pkg and '.' or '') + os.path.splitext(name)[0]
370
+ if sys.version_info < (3, 7):
371
+ skip = 12 # skip magic & date & file size
372
+ else:
373
+ skip = 16 # skip magic & reserved? & date & file size
374
+ f = open(filename, 'rb')
375
+ f.read(skip)
376
+ code = marshal.load(f)
377
+ f.close()
378
+ safe = True
379
+ symbols = dict.fromkeys(iter_symbols(code))
380
+ for bad in ['__file__', '__path__']:
381
+ if bad in symbols:
382
+ log.warn("%s: module references %s", module, bad)
383
+ safe = False
384
+ if 'inspect' in symbols:
385
+ for bad in [
386
+ 'getsource', 'getabsfile', 'getsourcefile', 'getfile'
387
+ 'getsourcelines', 'findsource', 'getcomments', 'getframeinfo',
388
+ 'getinnerframes', 'getouterframes', 'stack', 'trace'
389
+ ]:
390
+ if bad in symbols:
391
+ log.warn("%s: module MAY be using inspect.%s", module, bad)
392
+ safe = False
393
+ return safe
394
+
395
+
396
+ def iter_symbols(code):
397
+ """Yield names and strings used by `code` and its nested code objects"""
398
+ for name in code.co_names:
399
+ yield name
400
+ for const in code.co_consts:
401
+ if isinstance(const, str):
402
+ yield const
403
+ elif isinstance(const, CodeType):
404
+ for name in iter_symbols(const):
405
+ yield name
406
+
407
+
408
+ def can_scan():
409
+ if not sys.platform.startswith('java') and sys.platform != 'cli':
410
+ # CPython, PyPy, etc.
411
+ return True
412
+ log.warn("Unable to analyze compiled code on this platform.")
413
+ log.warn("Please ask the author to include a 'zip_safe'"
414
+ " setting (either True or False) in the package's setup.py")
415
+
416
+
417
+ # Attribute names of options for commands that might need to be convinced to
418
+ # install to the egg build directory
419
+
420
+ INSTALL_DIRECTORY_ATTRS = [
421
+ 'install_lib', 'install_dir', 'install_data', 'install_base'
422
+ ]
423
+
424
+
425
+ def make_zipfile(zip_filename, base_dir, verbose=0, dry_run=0, compress=True,
426
+ mode='w'):
427
+ """Create a zip file from all the files under 'base_dir'. The output
428
+ zip file will be named 'base_dir' + ".zip". Uses either the "zipfile"
429
+ Python module (if available) or the InfoZIP "zip" utility (if installed
430
+ and found on the default search path). If neither tool is available,
431
+ raises DistutilsExecError. Returns the name of the output zip file.
432
+ """
433
+ import zipfile
434
+
435
+ mkpath(os.path.dirname(zip_filename), dry_run=dry_run)
436
+ log.info("creating '%s' and adding '%s' to it", zip_filename, base_dir)
437
+
438
+ def visit(z, dirname, names):
439
+ for name in names:
440
+ path = os.path.normpath(os.path.join(dirname, name))
441
+ if os.path.isfile(path):
442
+ p = path[len(base_dir) + 1:]
443
+ if not dry_run:
444
+ z.write(path, p)
445
+ log.debug("adding '%s'", p)
446
+
447
+ compression = zipfile.ZIP_DEFLATED if compress else zipfile.ZIP_STORED
448
+ if not dry_run:
449
+ z = zipfile.ZipFile(zip_filename, mode, compression=compression)
450
+ for dirname, dirs, files in sorted_walk(base_dir):
451
+ visit(z, dirname, files)
452
+ z.close()
453
+ else:
454
+ for dirname, dirs, files in sorted_walk(base_dir):
455
+ visit(None, dirname, files)
456
+ return zip_filename
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/command/build_ext.py ADDED
@@ -0,0 +1,328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import itertools
4
+ from importlib.machinery import EXTENSION_SUFFIXES
5
+ from distutils.command.build_ext import build_ext as _du_build_ext
6
+ from distutils.file_util import copy_file
7
+ from distutils.ccompiler import new_compiler
8
+ from distutils.sysconfig import customize_compiler, get_config_var
9
+ from distutils.errors import DistutilsError
10
+ from distutils import log
11
+
12
+ from setuptools.extension import Library
13
+
14
+ try:
15
+ # Attempt to use Cython for building extensions, if available
16
+ from Cython.Distutils.build_ext import build_ext as _build_ext
17
+ # Additionally, assert that the compiler module will load
18
+ # also. Ref #1229.
19
+ __import__('Cython.Compiler.Main')
20
+ except ImportError:
21
+ _build_ext = _du_build_ext
22
+
23
+ # make sure _config_vars is initialized
24
+ get_config_var("LDSHARED")
25
+ from distutils.sysconfig import _config_vars as _CONFIG_VARS # noqa
26
+
27
+
28
+ def _customize_compiler_for_shlib(compiler):
29
+ if sys.platform == "darwin":
30
+ # building .dylib requires additional compiler flags on OSX; here we
31
+ # temporarily substitute the pyconfig.h variables so that distutils'
32
+ # 'customize_compiler' uses them before we build the shared libraries.
33
+ tmp = _CONFIG_VARS.copy()
34
+ try:
35
+ # XXX Help! I don't have any idea whether these are right...
36
+ _CONFIG_VARS['LDSHARED'] = (
37
+ "gcc -Wl,-x -dynamiclib -undefined dynamic_lookup")
38
+ _CONFIG_VARS['CCSHARED'] = " -dynamiclib"
39
+ _CONFIG_VARS['SO'] = ".dylib"
40
+ customize_compiler(compiler)
41
+ finally:
42
+ _CONFIG_VARS.clear()
43
+ _CONFIG_VARS.update(tmp)
44
+ else:
45
+ customize_compiler(compiler)
46
+
47
+
48
+ have_rtld = False
49
+ use_stubs = False
50
+ libtype = 'shared'
51
+
52
+ if sys.platform == "darwin":
53
+ use_stubs = True
54
+ elif os.name != 'nt':
55
+ try:
56
+ import dl
57
+ use_stubs = have_rtld = hasattr(dl, 'RTLD_NOW')
58
+ except ImportError:
59
+ pass
60
+
61
+
62
+ def if_dl(s):
63
+ return s if have_rtld else ''
64
+
65
+
66
+ def get_abi3_suffix():
67
+ """Return the file extension for an abi3-compliant Extension()"""
68
+ for suffix in EXTENSION_SUFFIXES:
69
+ if '.abi3' in suffix: # Unix
70
+ return suffix
71
+ elif suffix == '.pyd': # Windows
72
+ return suffix
73
+
74
+
75
+ class build_ext(_build_ext):
76
+ def run(self):
77
+ """Build extensions in build directory, then copy if --inplace"""
78
+ old_inplace, self.inplace = self.inplace, 0
79
+ _build_ext.run(self)
80
+ self.inplace = old_inplace
81
+ if old_inplace:
82
+ self.copy_extensions_to_source()
83
+
84
+ def copy_extensions_to_source(self):
85
+ build_py = self.get_finalized_command('build_py')
86
+ for ext in self.extensions:
87
+ fullname = self.get_ext_fullname(ext.name)
88
+ filename = self.get_ext_filename(fullname)
89
+ modpath = fullname.split('.')
90
+ package = '.'.join(modpath[:-1])
91
+ package_dir = build_py.get_package_dir(package)
92
+ dest_filename = os.path.join(package_dir,
93
+ os.path.basename(filename))
94
+ src_filename = os.path.join(self.build_lib, filename)
95
+
96
+ # Always copy, even if source is older than destination, to ensure
97
+ # that the right extensions for the current Python/platform are
98
+ # used.
99
+ copy_file(
100
+ src_filename, dest_filename, verbose=self.verbose,
101
+ dry_run=self.dry_run
102
+ )
103
+ if ext._needs_stub:
104
+ self.write_stub(package_dir or os.curdir, ext, True)
105
+
106
+ def get_ext_filename(self, fullname):
107
+ so_ext = os.getenv('SETUPTOOLS_EXT_SUFFIX')
108
+ if so_ext:
109
+ filename = os.path.join(*fullname.split('.')) + so_ext
110
+ else:
111
+ filename = _build_ext.get_ext_filename(self, fullname)
112
+ so_ext = get_config_var('EXT_SUFFIX')
113
+
114
+ if fullname in self.ext_map:
115
+ ext = self.ext_map[fullname]
116
+ use_abi3 = getattr(ext, 'py_limited_api') and get_abi3_suffix()
117
+ if use_abi3:
118
+ filename = filename[:-len(so_ext)]
119
+ so_ext = get_abi3_suffix()
120
+ filename = filename + so_ext
121
+ if isinstance(ext, Library):
122
+ fn, ext = os.path.splitext(filename)
123
+ return self.shlib_compiler.library_filename(fn, libtype)
124
+ elif use_stubs and ext._links_to_dynamic:
125
+ d, fn = os.path.split(filename)
126
+ return os.path.join(d, 'dl-' + fn)
127
+ return filename
128
+
129
+ def initialize_options(self):
130
+ _build_ext.initialize_options(self)
131
+ self.shlib_compiler = None
132
+ self.shlibs = []
133
+ self.ext_map = {}
134
+
135
+ def finalize_options(self):
136
+ _build_ext.finalize_options(self)
137
+ self.extensions = self.extensions or []
138
+ self.check_extensions_list(self.extensions)
139
+ self.shlibs = [ext for ext in self.extensions
140
+ if isinstance(ext, Library)]
141
+ if self.shlibs:
142
+ self.setup_shlib_compiler()
143
+ for ext in self.extensions:
144
+ ext._full_name = self.get_ext_fullname(ext.name)
145
+ for ext in self.extensions:
146
+ fullname = ext._full_name
147
+ self.ext_map[fullname] = ext
148
+
149
+ # distutils 3.1 will also ask for module names
150
+ # XXX what to do with conflicts?
151
+ self.ext_map[fullname.split('.')[-1]] = ext
152
+
153
+ ltd = self.shlibs and self.links_to_dynamic(ext) or False
154
+ ns = ltd and use_stubs and not isinstance(ext, Library)
155
+ ext._links_to_dynamic = ltd
156
+ ext._needs_stub = ns
157
+ filename = ext._file_name = self.get_ext_filename(fullname)
158
+ libdir = os.path.dirname(os.path.join(self.build_lib, filename))
159
+ if ltd and libdir not in ext.library_dirs:
160
+ ext.library_dirs.append(libdir)
161
+ if ltd and use_stubs and os.curdir not in ext.runtime_library_dirs:
162
+ ext.runtime_library_dirs.append(os.curdir)
163
+
164
+ def setup_shlib_compiler(self):
165
+ compiler = self.shlib_compiler = new_compiler(
166
+ compiler=self.compiler, dry_run=self.dry_run, force=self.force
167
+ )
168
+ _customize_compiler_for_shlib(compiler)
169
+
170
+ if self.include_dirs is not None:
171
+ compiler.set_include_dirs(self.include_dirs)
172
+ if self.define is not None:
173
+ # 'define' option is a list of (name,value) tuples
174
+ for (name, value) in self.define:
175
+ compiler.define_macro(name, value)
176
+ if self.undef is not None:
177
+ for macro in self.undef:
178
+ compiler.undefine_macro(macro)
179
+ if self.libraries is not None:
180
+ compiler.set_libraries(self.libraries)
181
+ if self.library_dirs is not None:
182
+ compiler.set_library_dirs(self.library_dirs)
183
+ if self.rpath is not None:
184
+ compiler.set_runtime_library_dirs(self.rpath)
185
+ if self.link_objects is not None:
186
+ compiler.set_link_objects(self.link_objects)
187
+
188
+ # hack so distutils' build_extension() builds a library instead
189
+ compiler.link_shared_object = link_shared_object.__get__(compiler)
190
+
191
+ def get_export_symbols(self, ext):
192
+ if isinstance(ext, Library):
193
+ return ext.export_symbols
194
+ return _build_ext.get_export_symbols(self, ext)
195
+
196
+ def build_extension(self, ext):
197
+ ext._convert_pyx_sources_to_lang()
198
+ _compiler = self.compiler
199
+ try:
200
+ if isinstance(ext, Library):
201
+ self.compiler = self.shlib_compiler
202
+ _build_ext.build_extension(self, ext)
203
+ if ext._needs_stub:
204
+ cmd = self.get_finalized_command('build_py').build_lib
205
+ self.write_stub(cmd, ext)
206
+ finally:
207
+ self.compiler = _compiler
208
+
209
+ def links_to_dynamic(self, ext):
210
+ """Return true if 'ext' links to a dynamic lib in the same package"""
211
+ # XXX this should check to ensure the lib is actually being built
212
+ # XXX as dynamic, and not just using a locally-found version or a
213
+ # XXX static-compiled version
214
+ libnames = dict.fromkeys([lib._full_name for lib in self.shlibs])
215
+ pkg = '.'.join(ext._full_name.split('.')[:-1] + [''])
216
+ return any(pkg + libname in libnames for libname in ext.libraries)
217
+
218
+ def get_outputs(self):
219
+ return _build_ext.get_outputs(self) + self.__get_stubs_outputs()
220
+
221
+ def __get_stubs_outputs(self):
222
+ # assemble the base name for each extension that needs a stub
223
+ ns_ext_bases = (
224
+ os.path.join(self.build_lib, *ext._full_name.split('.'))
225
+ for ext in self.extensions
226
+ if ext._needs_stub
227
+ )
228
+ # pair each base with the extension
229
+ pairs = itertools.product(ns_ext_bases, self.__get_output_extensions())
230
+ return list(base + fnext for base, fnext in pairs)
231
+
232
+ def __get_output_extensions(self):
233
+ yield '.py'
234
+ yield '.pyc'
235
+ if self.get_finalized_command('build_py').optimize:
236
+ yield '.pyo'
237
+
238
+ def write_stub(self, output_dir, ext, compile=False):
239
+ log.info("writing stub loader for %s to %s", ext._full_name,
240
+ output_dir)
241
+ stub_file = (os.path.join(output_dir, *ext._full_name.split('.')) +
242
+ '.py')
243
+ if compile and os.path.exists(stub_file):
244
+ raise DistutilsError(stub_file + " already exists! Please delete.")
245
+ if not self.dry_run:
246
+ f = open(stub_file, 'w')
247
+ f.write(
248
+ '\n'.join([
249
+ "def __bootstrap__():",
250
+ " global __bootstrap__, __file__, __loader__",
251
+ " import sys, os, pkg_resources, importlib.util" +
252
+ if_dl(", dl"),
253
+ " __file__ = pkg_resources.resource_filename"
254
+ "(__name__,%r)"
255
+ % os.path.basename(ext._file_name),
256
+ " del __bootstrap__",
257
+ " if '__loader__' in globals():",
258
+ " del __loader__",
259
+ if_dl(" old_flags = sys.getdlopenflags()"),
260
+ " old_dir = os.getcwd()",
261
+ " try:",
262
+ " os.chdir(os.path.dirname(__file__))",
263
+ if_dl(" sys.setdlopenflags(dl.RTLD_NOW)"),
264
+ " spec = importlib.util.spec_from_file_location(",
265
+ " __name__, __file__)",
266
+ " mod = importlib.util.module_from_spec(spec)",
267
+ " spec.loader.exec_module(mod)",
268
+ " finally:",
269
+ if_dl(" sys.setdlopenflags(old_flags)"),
270
+ " os.chdir(old_dir)",
271
+ "__bootstrap__()",
272
+ "" # terminal \n
273
+ ])
274
+ )
275
+ f.close()
276
+ if compile:
277
+ from distutils.util import byte_compile
278
+
279
+ byte_compile([stub_file], optimize=0,
280
+ force=True, dry_run=self.dry_run)
281
+ optimize = self.get_finalized_command('install_lib').optimize
282
+ if optimize > 0:
283
+ byte_compile([stub_file], optimize=optimize,
284
+ force=True, dry_run=self.dry_run)
285
+ if os.path.exists(stub_file) and not self.dry_run:
286
+ os.unlink(stub_file)
287
+
288
+
289
+ if use_stubs or os.name == 'nt':
290
+ # Build shared libraries
291
+ #
292
+ def link_shared_object(
293
+ self, objects, output_libname, output_dir=None, libraries=None,
294
+ library_dirs=None, runtime_library_dirs=None, export_symbols=None,
295
+ debug=0, extra_preargs=None, extra_postargs=None, build_temp=None,
296
+ target_lang=None):
297
+ self.link(
298
+ self.SHARED_LIBRARY, objects, output_libname,
299
+ output_dir, libraries, library_dirs, runtime_library_dirs,
300
+ export_symbols, debug, extra_preargs, extra_postargs,
301
+ build_temp, target_lang
302
+ )
303
+ else:
304
+ # Build static libraries everywhere else
305
+ libtype = 'static'
306
+
307
+ def link_shared_object(
308
+ self, objects, output_libname, output_dir=None, libraries=None,
309
+ library_dirs=None, runtime_library_dirs=None, export_symbols=None,
310
+ debug=0, extra_preargs=None, extra_postargs=None, build_temp=None,
311
+ target_lang=None):
312
+ # XXX we need to either disallow these attrs on Library instances,
313
+ # or warn/abort here if set, or something...
314
+ # libraries=None, library_dirs=None, runtime_library_dirs=None,
315
+ # export_symbols=None, extra_preargs=None, extra_postargs=None,
316
+ # build_temp=None
317
+
318
+ assert output_dir is None # distutils build_ext doesn't pass this
319
+ output_dir, filename = os.path.split(output_libname)
320
+ basename, ext = os.path.splitext(filename)
321
+ if self.library_filename("x").startswith('lib'):
322
+ # strip 'lib' prefix; this is kludgy if some platform uses
323
+ # a different prefix
324
+ basename = basename[3:]
325
+
326
+ self.create_static_lib(
327
+ objects, basename, output_dir, debug, target_lang
328
+ )
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/setuptools/command/easy_install.py ADDED
@@ -0,0 +1,2290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Easy Install
3
+ ------------
4
+
5
+ A tool for doing automatic download/extract/build of distutils-based Python
6
+ packages. For detailed documentation, see the accompanying EasyInstall.txt
7
+ file, or visit the `EasyInstall home page`__.
8
+
9
+ __ https://setuptools.readthedocs.io/en/latest/deprecated/easy_install.html
10
+
11
+ """
12
+
13
+ from glob import glob
14
+ from distutils.util import get_platform
15
+ from distutils.util import convert_path, subst_vars
16
+ from distutils.errors import (
17
+ DistutilsArgError, DistutilsOptionError,
18
+ DistutilsError, DistutilsPlatformError,
19
+ )
20
+ from distutils.command.install import INSTALL_SCHEMES, SCHEME_KEYS
21
+ from distutils import log, dir_util
22
+ from distutils.command.build_scripts import first_line_re
23
+ from distutils.spawn import find_executable
24
+ import sys
25
+ import os
26
+ import zipimport
27
+ import shutil
28
+ import tempfile
29
+ import zipfile
30
+ import re
31
+ import stat
32
+ import random
33
+ import textwrap
34
+ import warnings
35
+ import site
36
+ import struct
37
+ import contextlib
38
+ import subprocess
39
+ import shlex
40
+ import io
41
+ import configparser
42
+
43
+
44
+ from sysconfig import get_config_vars, get_path
45
+
46
+ from setuptools import SetuptoolsDeprecationWarning
47
+
48
+ from setuptools import Command
49
+ from setuptools.sandbox import run_setup
50
+ from setuptools.command import setopt
51
+ from setuptools.archive_util import unpack_archive
52
+ from setuptools.package_index import (
53
+ PackageIndex, parse_requirement_arg, URL_SCHEME,
54
+ )
55
+ from setuptools.command import bdist_egg, egg_info
56
+ from setuptools.wheel import Wheel
57
+ from pkg_resources import (
58
+ yield_lines, normalize_path, resource_string, ensure_directory,
59
+ get_distribution, find_distributions, Environment, Requirement,
60
+ Distribution, PathMetadata, EggMetadata, WorkingSet, DistributionNotFound,
61
+ VersionConflict, DEVELOP_DIST,
62
+ )
63
+ import pkg_resources
64
+
65
+ # Turn on PEP440Warnings
66
+ warnings.filterwarnings("default", category=pkg_resources.PEP440Warning)
67
+
68
+ __all__ = [
69
+ 'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg',
70
+ 'get_exe_prefixes',
71
+ ]
72
+
73
+
74
+ def is_64bit():
75
+ return struct.calcsize("P") == 8
76
+
77
+
78
+ def samefile(p1, p2):
79
+ """
80
+ Determine if two paths reference the same file.
81
+
82
+ Augments os.path.samefile to work on Windows and
83
+ suppresses errors if the path doesn't exist.
84
+ """
85
+ both_exist = os.path.exists(p1) and os.path.exists(p2)
86
+ use_samefile = hasattr(os.path, 'samefile') and both_exist
87
+ if use_samefile:
88
+ return os.path.samefile(p1, p2)
89
+ norm_p1 = os.path.normpath(os.path.normcase(p1))
90
+ norm_p2 = os.path.normpath(os.path.normcase(p2))
91
+ return norm_p1 == norm_p2
92
+
93
+
94
+ def _to_bytes(s):
95
+ return s.encode('utf8')
96
+
97
+
98
+ def isascii(s):
99
+ try:
100
+ s.encode('ascii')
101
+ return True
102
+ except UnicodeError:
103
+ return False
104
+
105
+
106
+ def _one_liner(text):
107
+ return textwrap.dedent(text).strip().replace('\n', '; ')
108
+
109
+
110
+ class easy_install(Command):
111
+ """Manage a download/build/install process"""
112
+ description = "Find/get/install Python packages"
113
+ command_consumes_arguments = True
114
+
115
+ user_options = [
116
+ ('prefix=', None, "installation prefix"),
117
+ ("zip-ok", "z", "install package as a zipfile"),
118
+ ("multi-version", "m", "make apps have to require() a version"),
119
+ ("upgrade", "U", "force upgrade (searches PyPI for latest versions)"),
120
+ ("install-dir=", "d", "install package to DIR"),
121
+ ("script-dir=", "s", "install scripts to DIR"),
122
+ ("exclude-scripts", "x", "Don't install scripts"),
123
+ ("always-copy", "a", "Copy all needed packages to install dir"),
124
+ ("index-url=", "i", "base URL of Python Package Index"),
125
+ ("find-links=", "f", "additional URL(s) to search for packages"),
126
+ ("build-directory=", "b",
127
+ "download/extract/build in DIR; keep the results"),
128
+ ('optimize=', 'O',
129
+ "also compile with optimization: -O1 for \"python -O\", "
130
+ "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
131
+ ('record=', None,
132
+ "filename in which to record list of installed files"),
133
+ ('always-unzip', 'Z', "don't install as a zipfile, no matter what"),
134
+ ('site-dirs=', 'S', "list of directories where .pth files work"),
135
+ ('editable', 'e', "Install specified packages in editable form"),
136
+ ('no-deps', 'N', "don't install dependencies"),
137
+ ('allow-hosts=', 'H', "pattern(s) that hostnames must match"),
138
+ ('local-snapshots-ok', 'l',
139
+ "allow building eggs from local checkouts"),
140
+ ('version', None, "print version information and exit"),
141
+ ('no-find-links', None,
142
+ "Don't load find-links defined in packages being installed"),
143
+ ('user', None, "install in user site-package '%s'" % site.USER_SITE)
144
+ ]
145
+ boolean_options = [
146
+ 'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy',
147
+ 'editable',
148
+ 'no-deps', 'local-snapshots-ok', 'version',
149
+ 'user'
150
+ ]
151
+
152
+ negative_opt = {'always-unzip': 'zip-ok'}
153
+ create_index = PackageIndex
154
+
155
+ def initialize_options(self):
156
+ # the --user option seems to be an opt-in one,
157
+ # so the default should be False.
158
+ self.user = 0
159
+ self.zip_ok = self.local_snapshots_ok = None
160
+ self.install_dir = self.script_dir = self.exclude_scripts = None
161
+ self.index_url = None
162
+ self.find_links = None
163
+ self.build_directory = None
164
+ self.args = None
165
+ self.optimize = self.record = None
166
+ self.upgrade = self.always_copy = self.multi_version = None
167
+ self.editable = self.no_deps = self.allow_hosts = None
168
+ self.root = self.prefix = self.no_report = None
169
+ self.version = None
170
+ self.install_purelib = None # for pure module distributions
171
+ self.install_platlib = None # non-pure (dists w/ extensions)
172
+ self.install_headers = None # for C/C++ headers
173
+ self.install_lib = None # set to either purelib or platlib
174
+ self.install_scripts = None
175
+ self.install_data = None
176
+ self.install_base = None
177
+ self.install_platbase = None
178
+ if site.ENABLE_USER_SITE:
179
+ self.install_userbase = site.USER_BASE
180
+ self.install_usersite = site.USER_SITE
181
+ else:
182
+ self.install_userbase = None
183
+ self.install_usersite = None
184
+ self.no_find_links = None
185
+
186
+ # Options not specifiable via command line
187
+ self.package_index = None
188
+ self.pth_file = self.always_copy_from = None
189
+ self.site_dirs = None
190
+ self.installed_projects = {}
191
+ # Always read easy_install options, even if we are subclassed, or have
192
+ # an independent instance created. This ensures that defaults will
193
+ # always come from the standard configuration file(s)' "easy_install"
194
+ # section, even if this is a "develop" or "install" command, or some
195
+ # other embedding.
196
+ self._dry_run = None
197
+ self.verbose = self.distribution.verbose
198
+ self.distribution._set_command_options(
199
+ self, self.distribution.get_option_dict('easy_install')
200
+ )
201
+
202
+ def delete_blockers(self, blockers):
203
+ extant_blockers = (
204
+ filename for filename in blockers
205
+ if os.path.exists(filename) or os.path.islink(filename)
206
+ )
207
+ list(map(self._delete_path, extant_blockers))
208
+
209
+ def _delete_path(self, path):
210
+ log.info("Deleting %s", path)
211
+ if self.dry_run:
212
+ return
213
+
214
+ is_tree = os.path.isdir(path) and not os.path.islink(path)
215
+ remover = rmtree if is_tree else os.unlink
216
+ remover(path)
217
+
218
+ @staticmethod
219
+ def _render_version():
220
+ """
221
+ Render the Setuptools version and installation details, then exit.
222
+ """
223
+ ver = '{}.{}'.format(*sys.version_info)
224
+ dist = get_distribution('setuptools')
225
+ tmpl = 'setuptools {dist.version} from {dist.location} (Python {ver})'
226
+ print(tmpl.format(**locals()))
227
+ raise SystemExit()
228
+
229
+ def finalize_options(self): # noqa: C901 # is too complex (25) # FIXME
230
+ self.version and self._render_version()
231
+
232
+ py_version = sys.version.split()[0]
233
+ prefix, exec_prefix = get_config_vars('prefix', 'exec_prefix')
234
+
235
+ self.config_vars = {
236
+ 'dist_name': self.distribution.get_name(),
237
+ 'dist_version': self.distribution.get_version(),
238
+ 'dist_fullname': self.distribution.get_fullname(),
239
+ 'py_version': py_version,
240
+ 'py_version_short': py_version[0:3],
241
+ 'py_version_nodot': py_version[0] + py_version[2],
242
+ 'sys_prefix': prefix,
243
+ 'prefix': prefix,
244
+ 'sys_exec_prefix': exec_prefix,
245
+ 'exec_prefix': exec_prefix,
246
+ # Only python 3.2+ has abiflags
247
+ 'abiflags': getattr(sys, 'abiflags', ''),
248
+ }
249
+
250
+ if site.ENABLE_USER_SITE:
251
+ self.config_vars['userbase'] = self.install_userbase
252
+ self.config_vars['usersite'] = self.install_usersite
253
+
254
+ elif self.user:
255
+ log.warn("WARNING: The user site-packages directory is disabled.")
256
+
257
+ self._fix_install_dir_for_user_site()
258
+
259
+ self.expand_basedirs()
260
+ self.expand_dirs()
261
+
262
+ self._expand(
263
+ 'install_dir', 'script_dir', 'build_directory',
264
+ 'site_dirs',
265
+ )
266
+ # If a non-default installation directory was specified, default the
267
+ # script directory to match it.
268
+ if self.script_dir is None:
269
+ self.script_dir = self.install_dir
270
+
271
+ if self.no_find_links is None:
272
+ self.no_find_links = False
273
+
274
+ # Let install_dir get set by install_lib command, which in turn
275
+ # gets its info from the install command, and takes into account
276
+ # --prefix and --home and all that other crud.
277
+ self.set_undefined_options(
278
+ 'install_lib', ('install_dir', 'install_dir')
279
+ )
280
+ # Likewise, set default script_dir from 'install_scripts.install_dir'
281
+ self.set_undefined_options(
282
+ 'install_scripts', ('install_dir', 'script_dir')
283
+ )
284
+
285
+ if self.user and self.install_purelib:
286
+ self.install_dir = self.install_purelib
287
+ self.script_dir = self.install_scripts
288
+ # default --record from the install command
289
+ self.set_undefined_options('install', ('record', 'record'))
290
+ # Should this be moved to the if statement below? It's not used
291
+ # elsewhere
292
+ normpath = map(normalize_path, sys.path)
293
+ self.all_site_dirs = get_site_dirs()
294
+ if self.site_dirs is not None:
295
+ site_dirs = [
296
+ os.path.expanduser(s.strip()) for s in
297
+ self.site_dirs.split(',')
298
+ ]
299
+ for d in site_dirs:
300
+ if not os.path.isdir(d):
301
+ log.warn("%s (in --site-dirs) does not exist", d)
302
+ elif normalize_path(d) not in normpath:
303
+ raise DistutilsOptionError(
304
+ d + " (in --site-dirs) is not on sys.path"
305
+ )
306
+ else:
307
+ self.all_site_dirs.append(normalize_path(d))
308
+ if not self.editable:
309
+ self.check_site_dir()
310
+ self.index_url = self.index_url or "https://pypi.org/simple/"
311
+ self.shadow_path = self.all_site_dirs[:]
312
+ for path_item in self.install_dir, normalize_path(self.script_dir):
313
+ if path_item not in self.shadow_path:
314
+ self.shadow_path.insert(0, path_item)
315
+
316
+ if self.allow_hosts is not None:
317
+ hosts = [s.strip() for s in self.allow_hosts.split(',')]
318
+ else:
319
+ hosts = ['*']
320
+ if self.package_index is None:
321
+ self.package_index = self.create_index(
322
+ self.index_url, search_path=self.shadow_path, hosts=hosts,
323
+ )
324
+ self.local_index = Environment(self.shadow_path + sys.path)
325
+
326
+ if self.find_links is not None:
327
+ if isinstance(self.find_links, str):
328
+ self.find_links = self.find_links.split()
329
+ else:
330
+ self.find_links = []
331
+ if self.local_snapshots_ok:
332
+ self.package_index.scan_egg_links(self.shadow_path + sys.path)
333
+ if not self.no_find_links:
334
+ self.package_index.add_find_links(self.find_links)
335
+ self.set_undefined_options('install_lib', ('optimize', 'optimize'))
336
+ if not isinstance(self.optimize, int):
337
+ try:
338
+ self.optimize = int(self.optimize)
339
+ if not (0 <= self.optimize <= 2):
340
+ raise ValueError
341
+ except ValueError as e:
342
+ raise DistutilsOptionError(
343
+ "--optimize must be 0, 1, or 2"
344
+ ) from e
345
+
346
+ if self.editable and not self.build_directory:
347
+ raise DistutilsArgError(
348
+ "Must specify a build directory (-b) when using --editable"
349
+ )
350
+ if not self.args:
351
+ raise DistutilsArgError(
352
+ "No urls, filenames, or requirements specified (see --help)")
353
+
354
+ self.outputs = []
355
+
356
+ def _fix_install_dir_for_user_site(self):
357
+ """
358
+ Fix the install_dir if "--user" was used.
359
+ """
360
+ if not self.user or not site.ENABLE_USER_SITE:
361
+ return
362
+
363
+ self.create_home_path()
364
+ if self.install_userbase is None:
365
+ msg = "User base directory is not specified"
366
+ raise DistutilsPlatformError(msg)
367
+ self.install_base = self.install_platbase = self.install_userbase
368
+ scheme_name = os.name.replace('posix', 'unix') + '_user'
369
+ self.select_scheme(scheme_name)
370
+
371
+ def _expand_attrs(self, attrs):
372
+ for attr in attrs:
373
+ val = getattr(self, attr)
374
+ if val is not None:
375
+ if os.name == 'posix' or os.name == 'nt':
376
+ val = os.path.expanduser(val)
377
+ val = subst_vars(val, self.config_vars)
378
+ setattr(self, attr, val)
379
+
380
+ def expand_basedirs(self):
381
+ """Calls `os.path.expanduser` on install_base, install_platbase and
382
+ root."""
383
+ self._expand_attrs(['install_base', 'install_platbase', 'root'])
384
+
385
+ def expand_dirs(self):
386
+ """Calls `os.path.expanduser` on install dirs."""
387
+ dirs = [
388
+ 'install_purelib',
389
+ 'install_platlib',
390
+ 'install_lib',
391
+ 'install_headers',
392
+ 'install_scripts',
393
+ 'install_data',
394
+ ]
395
+ self._expand_attrs(dirs)
396
+
397
+ def run(self, show_deprecation=True):
398
+ if show_deprecation:
399
+ self.announce(
400
+ "WARNING: The easy_install command is deprecated "
401
+ "and will be removed in a future version.",
402
+ log.WARN,
403
+ )
404
+ if self.verbose != self.distribution.verbose:
405
+ log.set_verbosity(self.verbose)
406
+ try:
407
+ for spec in self.args:
408
+ self.easy_install(spec, not self.no_deps)
409
+ if self.record:
410
+ outputs = self.outputs
411
+ if self.root: # strip any package prefix
412
+ root_len = len(self.root)
413
+ for counter in range(len(outputs)):
414
+ outputs[counter] = outputs[counter][root_len:]
415
+ from distutils import file_util
416
+
417
+ self.execute(
418
+ file_util.write_file, (self.record, outputs),
419
+ "writing list of installed files to '%s'" %
420
+ self.record
421
+ )
422
+ self.warn_deprecated_options()
423
+ finally:
424
+ log.set_verbosity(self.distribution.verbose)
425
+
426
+ def pseudo_tempname(self):
427
+ """Return a pseudo-tempname base in the install directory.
428
+ This code is intentionally naive; if a malicious party can write to
429
+ the target directory you're already in deep doodoo.
430
+ """
431
+ try:
432
+ pid = os.getpid()
433
+ except Exception:
434
+ pid = random.randint(0, sys.maxsize)
435
+ return os.path.join(self.install_dir, "test-easy-install-%s" % pid)
436
+
437
+ def warn_deprecated_options(self):
438
+ pass
439
+
440
+ def check_site_dir(self): # noqa: C901 # is too complex (12) # FIXME
441
+ """Verify that self.install_dir is .pth-capable dir, if needed"""
442
+
443
+ instdir = normalize_path(self.install_dir)
444
+ pth_file = os.path.join(instdir, 'easy-install.pth')
445
+
446
+ if not os.path.exists(instdir):
447
+ try:
448
+ os.makedirs(instdir)
449
+ except (OSError, IOError):
450
+ self.cant_write_to_target()
451
+
452
+ # Is it a configured, PYTHONPATH, implicit, or explicit site dir?
453
+ is_site_dir = instdir in self.all_site_dirs
454
+
455
+ if not is_site_dir and not self.multi_version:
456
+ # No? Then directly test whether it does .pth file processing
457
+ is_site_dir = self.check_pth_processing()
458
+ else:
459
+ # make sure we can write to target dir
460
+ testfile = self.pseudo_tempname() + '.write-test'
461
+ test_exists = os.path.exists(testfile)
462
+ try:
463
+ if test_exists:
464
+ os.unlink(testfile)
465
+ open(testfile, 'w').close()
466
+ os.unlink(testfile)
467
+ except (OSError, IOError):
468
+ self.cant_write_to_target()
469
+
470
+ if not is_site_dir and not self.multi_version:
471
+ # Can't install non-multi to non-site dir with easy_install
472
+ pythonpath = os.environ.get('PYTHONPATH', '')
473
+ log.warn(self.__no_default_msg, self.install_dir, pythonpath)
474
+
475
+ if is_site_dir:
476
+ if self.pth_file is None:
477
+ self.pth_file = PthDistributions(pth_file, self.all_site_dirs)
478
+ else:
479
+ self.pth_file = None
480
+
481
+ if self.multi_version and not os.path.exists(pth_file):
482
+ self.pth_file = None # don't create a .pth file
483
+ self.install_dir = instdir
484
+
485
+ __cant_write_msg = textwrap.dedent("""
486
+ can't create or remove files in install directory
487
+
488
+ The following error occurred while trying to add or remove files in the
489
+ installation directory:
490
+
491
+ %s
492
+
493
+ The installation directory you specified (via --install-dir, --prefix, or
494
+ the distutils default setting) was:
495
+
496
+ %s
497
+ """).lstrip() # noqa
498
+
499
+ __not_exists_id = textwrap.dedent("""
500
+ This directory does not currently exist. Please create it and try again, or
501
+ choose a different installation directory (using the -d or --install-dir
502
+ option).
503
+ """).lstrip() # noqa
504
+
505
+ __access_msg = textwrap.dedent("""
506
+ Perhaps your account does not have write access to this directory? If the
507
+ installation directory is a system-owned directory, you may need to sign in
508
+ as the administrator or "root" account. If you do not have administrative
509
+ access to this machine, you may wish to choose a different installation
510
+ directory, preferably one that is listed in your PYTHONPATH environment
511
+ variable.
512
+
513
+ For information on other options, you may wish to consult the
514
+ documentation at:
515
+
516
+ https://setuptools.readthedocs.io/en/latest/deprecated/easy_install.html
517
+
518
+ Please make the appropriate changes for your system and try again.
519
+ """).lstrip() # noqa
520
+
521
+ def cant_write_to_target(self):
522
+ msg = self.__cant_write_msg % (sys.exc_info()[1], self.install_dir,)
523
+
524
+ if not os.path.exists(self.install_dir):
525
+ msg += '\n' + self.__not_exists_id
526
+ else:
527
+ msg += '\n' + self.__access_msg
528
+ raise DistutilsError(msg)
529
+
530
+ def check_pth_processing(self):
531
+ """Empirically verify whether .pth files are supported in inst. dir"""
532
+ instdir = self.install_dir
533
+ log.info("Checking .pth file support in %s", instdir)
534
+ pth_file = self.pseudo_tempname() + ".pth"
535
+ ok_file = pth_file + '.ok'
536
+ ok_exists = os.path.exists(ok_file)
537
+ tmpl = _one_liner("""
538
+ import os
539
+ f = open({ok_file!r}, 'w')
540
+ f.write('OK')
541
+ f.close()
542
+ """) + '\n'
543
+ try:
544
+ if ok_exists:
545
+ os.unlink(ok_file)
546
+ dirname = os.path.dirname(ok_file)
547
+ os.makedirs(dirname, exist_ok=True)
548
+ f = open(pth_file, 'w')
549
+ except (OSError, IOError):
550
+ self.cant_write_to_target()
551
+ else:
552
+ try:
553
+ f.write(tmpl.format(**locals()))
554
+ f.close()
555
+ f = None
556
+ executable = sys.executable
557
+ if os.name == 'nt':
558
+ dirname, basename = os.path.split(executable)
559
+ alt = os.path.join(dirname, 'pythonw.exe')
560
+ use_alt = (
561
+ basename.lower() == 'python.exe' and
562
+ os.path.exists(alt)
563
+ )
564
+ if use_alt:
565
+ # use pythonw.exe to avoid opening a console window
566
+ executable = alt
567
+
568
+ from distutils.spawn import spawn
569
+
570
+ spawn([executable, '-E', '-c', 'pass'], 0)
571
+
572
+ if os.path.exists(ok_file):
573
+ log.info(
574
+ "TEST PASSED: %s appears to support .pth files",
575
+ instdir
576
+ )
577
+ return True
578
+ finally:
579
+ if f:
580
+ f.close()
581
+ if os.path.exists(ok_file):
582
+ os.unlink(ok_file)
583
+ if os.path.exists(pth_file):
584
+ os.unlink(pth_file)
585
+ if not self.multi_version:
586
+ log.warn("TEST FAILED: %s does NOT support .pth files", instdir)
587
+ return False
588
+
589
+ def install_egg_scripts(self, dist):
590
+ """Write all the scripts for `dist`, unless scripts are excluded"""
591
+ if not self.exclude_scripts and dist.metadata_isdir('scripts'):
592
+ for script_name in dist.metadata_listdir('scripts'):
593
+ if dist.metadata_isdir('scripts/' + script_name):
594
+ # The "script" is a directory, likely a Python 3
595
+ # __pycache__ directory, so skip it.
596
+ continue
597
+ self.install_script(
598
+ dist, script_name,
599
+ dist.get_metadata('scripts/' + script_name)
600
+ )
601
+ self.install_wrapper_scripts(dist)
602
+
603
+ def add_output(self, path):
604
+ if os.path.isdir(path):
605
+ for base, dirs, files in os.walk(path):
606
+ for filename in files:
607
+ self.outputs.append(os.path.join(base, filename))
608
+ else:
609
+ self.outputs.append(path)
610
+
611
+ def not_editable(self, spec):
612
+ if self.editable:
613
+ raise DistutilsArgError(
614
+ "Invalid argument %r: you can't use filenames or URLs "
615
+ "with --editable (except via the --find-links option)."
616
+ % (spec,)
617
+ )
618
+
619
+ def check_editable(self, spec):
620
+ if not self.editable:
621
+ return
622
+
623
+ if os.path.exists(os.path.join(self.build_directory, spec.key)):
624
+ raise DistutilsArgError(
625
+ "%r already exists in %s; can't do a checkout there" %
626
+ (spec.key, self.build_directory)
627
+ )
628
+
629
+ @contextlib.contextmanager
630
+ def _tmpdir(self):
631
+ tmpdir = tempfile.mkdtemp(prefix=u"easy_install-")
632
+ try:
633
+ # cast to str as workaround for #709 and #710 and #712
634
+ yield str(tmpdir)
635
+ finally:
636
+ os.path.exists(tmpdir) and rmtree(tmpdir)
637
+
638
+ def easy_install(self, spec, deps=False):
639
+ with self._tmpdir() as tmpdir:
640
+ if not isinstance(spec, Requirement):
641
+ if URL_SCHEME(spec):
642
+ # It's a url, download it to tmpdir and process
643
+ self.not_editable(spec)
644
+ dl = self.package_index.download(spec, tmpdir)
645
+ return self.install_item(None, dl, tmpdir, deps, True)
646
+
647
+ elif os.path.exists(spec):
648
+ # Existing file or directory, just process it directly
649
+ self.not_editable(spec)
650
+ return self.install_item(None, spec, tmpdir, deps, True)
651
+ else:
652
+ spec = parse_requirement_arg(spec)
653
+
654
+ self.check_editable(spec)
655
+ dist = self.package_index.fetch_distribution(
656
+ spec, tmpdir, self.upgrade, self.editable,
657
+ not self.always_copy, self.local_index
658
+ )
659
+ if dist is None:
660
+ msg = "Could not find suitable distribution for %r" % spec
661
+ if self.always_copy:
662
+ msg += " (--always-copy skips system and development eggs)"
663
+ raise DistutilsError(msg)
664
+ elif dist.precedence == DEVELOP_DIST:
665
+ # .egg-info dists don't need installing, just process deps
666
+ self.process_distribution(spec, dist, deps, "Using")
667
+ return dist
668
+ else:
669
+ return self.install_item(spec, dist.location, tmpdir, deps)
670
+
671
+ def install_item(self, spec, download, tmpdir, deps, install_needed=False):
672
+
673
+ # Installation is also needed if file in tmpdir or is not an egg
674
+ install_needed = install_needed or self.always_copy
675
+ install_needed = install_needed or os.path.dirname(download) == tmpdir
676
+ install_needed = install_needed or not download.endswith('.egg')
677
+ install_needed = install_needed or (
678
+ self.always_copy_from is not None and
679
+ os.path.dirname(normalize_path(download)) ==
680
+ normalize_path(self.always_copy_from)
681
+ )
682
+
683
+ if spec and not install_needed:
684
+ # at this point, we know it's a local .egg, we just don't know if
685
+ # it's already installed.
686
+ for dist in self.local_index[spec.project_name]:
687
+ if dist.location == download:
688
+ break
689
+ else:
690
+ install_needed = True # it's not in the local index
691
+
692
+ log.info("Processing %s", os.path.basename(download))
693
+
694
+ if install_needed:
695
+ dists = self.install_eggs(spec, download, tmpdir)
696
+ for dist in dists:
697
+ self.process_distribution(spec, dist, deps)
698
+ else:
699
+ dists = [self.egg_distribution(download)]
700
+ self.process_distribution(spec, dists[0], deps, "Using")
701
+
702
+ if spec is not None:
703
+ for dist in dists:
704
+ if dist in spec:
705
+ return dist
706
+
707
+ def select_scheme(self, name):
708
+ """Sets the install directories by applying the install schemes."""
709
+ # it's the caller's problem if they supply a bad name!
710
+ scheme = INSTALL_SCHEMES[name]
711
+ for key in SCHEME_KEYS:
712
+ attrname = 'install_' + key
713
+ if getattr(self, attrname) is None:
714
+ setattr(self, attrname, scheme[key])
715
+
716
+ # FIXME: 'easy_install.process_distribution' is too complex (12)
717
+ def process_distribution( # noqa: C901
718
+ self, requirement, dist, deps=True, *info,
719
+ ):
720
+ self.update_pth(dist)
721
+ self.package_index.add(dist)
722
+ if dist in self.local_index[dist.key]:
723
+ self.local_index.remove(dist)
724
+ self.local_index.add(dist)
725
+ self.install_egg_scripts(dist)
726
+ self.installed_projects[dist.key] = dist
727
+ log.info(self.installation_report(requirement, dist, *info))
728
+ if (dist.has_metadata('dependency_links.txt') and
729
+ not self.no_find_links):
730
+ self.package_index.add_find_links(
731
+ dist.get_metadata_lines('dependency_links.txt')
732
+ )
733
+ if not deps and not self.always_copy:
734
+ return
735
+ elif requirement is not None and dist.key != requirement.key:
736
+ log.warn("Skipping dependencies for %s", dist)
737
+ return # XXX this is not the distribution we were looking for
738
+ elif requirement is None or dist not in requirement:
739
+ # if we wound up with a different version, resolve what we've got
740
+ distreq = dist.as_requirement()
741
+ requirement = Requirement(str(distreq))
742
+ log.info("Processing dependencies for %s", requirement)
743
+ try:
744
+ distros = WorkingSet([]).resolve(
745
+ [requirement], self.local_index, self.easy_install
746
+ )
747
+ except DistributionNotFound as e:
748
+ raise DistutilsError(str(e)) from e
749
+ except VersionConflict as e:
750
+ raise DistutilsError(e.report()) from e
751
+ if self.always_copy or self.always_copy_from:
752
+ # Force all the relevant distros to be copied or activated
753
+ for dist in distros:
754
+ if dist.key not in self.installed_projects:
755
+ self.easy_install(dist.as_requirement())
756
+ log.info("Finished processing dependencies for %s", requirement)
757
+
758
+ def should_unzip(self, dist):
759
+ if self.zip_ok is not None:
760
+ return not self.zip_ok
761
+ if dist.has_metadata('not-zip-safe'):
762
+ return True
763
+ if not dist.has_metadata('zip-safe'):
764
+ return True
765
+ return False
766
+
767
+ def maybe_move(self, spec, dist_filename, setup_base):
768
+ dst = os.path.join(self.build_directory, spec.key)
769
+ if os.path.exists(dst):
770
+ msg = (
771
+ "%r already exists in %s; build directory %s will not be kept"
772
+ )
773
+ log.warn(msg, spec.key, self.build_directory, setup_base)
774
+ return setup_base
775
+ if os.path.isdir(dist_filename):
776
+ setup_base = dist_filename
777
+ else:
778
+ if os.path.dirname(dist_filename) == setup_base:
779
+ os.unlink(dist_filename) # get it out of the tmp dir
780
+ contents = os.listdir(setup_base)
781
+ if len(contents) == 1:
782
+ dist_filename = os.path.join(setup_base, contents[0])
783
+ if os.path.isdir(dist_filename):
784
+ # if the only thing there is a directory, move it instead
785
+ setup_base = dist_filename
786
+ ensure_directory(dst)
787
+ shutil.move(setup_base, dst)
788
+ return dst
789
+
790
+ def install_wrapper_scripts(self, dist):
791
+ if self.exclude_scripts:
792
+ return
793
+ for args in ScriptWriter.best().get_args(dist):
794
+ self.write_script(*args)
795
+
796
+ def install_script(self, dist, script_name, script_text, dev_path=None):
797
+ """Generate a legacy script wrapper and install it"""
798
+ spec = str(dist.as_requirement())
799
+ is_script = is_python_script(script_text, script_name)
800
+
801
+ if is_script:
802
+ body = self._load_template(dev_path) % locals()
803
+ script_text = ScriptWriter.get_header(script_text) + body
804
+ self.write_script(script_name, _to_bytes(script_text), 'b')
805
+
806
+ @staticmethod
807
+ def _load_template(dev_path):
808
+ """
809
+ There are a couple of template scripts in the package. This
810
+ function loads one of them and prepares it for use.
811
+ """
812
+ # See https://github.com/pypa/setuptools/issues/134 for info
813
+ # on script file naming and downstream issues with SVR4
814
+ name = 'script.tmpl'
815
+ if dev_path:
816
+ name = name.replace('.tmpl', ' (dev).tmpl')
817
+
818
+ raw_bytes = resource_string('setuptools', name)
819
+ return raw_bytes.decode('utf-8')
820
+
821
+ def write_script(self, script_name, contents, mode="t", blockers=()):
822
+ """Write an executable file to the scripts directory"""
823
+ self.delete_blockers( # clean up old .py/.pyw w/o a script
824
+ [os.path.join(self.script_dir, x) for x in blockers]
825
+ )
826
+ log.info("Installing %s script to %s", script_name, self.script_dir)
827
+ target = os.path.join(self.script_dir, script_name)
828
+ self.add_output(target)
829
+
830
+ if self.dry_run:
831
+ return
832
+
833
+ mask = current_umask()
834
+ ensure_directory(target)
835
+ if os.path.exists(target):
836
+ os.unlink(target)
837
+ with open(target, "w" + mode) as f:
838
+ f.write(contents)
839
+ chmod(target, 0o777 - mask)
840
+
841
+ def install_eggs(self, spec, dist_filename, tmpdir):
842
+ # .egg dirs or files are already built, so just return them
843
+ installer_map = {
844
+ '.egg': self.install_egg,
845
+ '.exe': self.install_exe,
846
+ '.whl': self.install_wheel,
847
+ }
848
+ try:
849
+ install_dist = installer_map[
850
+ dist_filename.lower()[-4:]
851
+ ]
852
+ except KeyError:
853
+ pass
854
+ else:
855
+ return [install_dist(dist_filename, tmpdir)]
856
+
857
+ # Anything else, try to extract and build
858
+ setup_base = tmpdir
859
+ if os.path.isfile(dist_filename) and not dist_filename.endswith('.py'):
860
+ unpack_archive(dist_filename, tmpdir, self.unpack_progress)
861
+ elif os.path.isdir(dist_filename):
862
+ setup_base = os.path.abspath(dist_filename)
863
+
864
+ if (setup_base.startswith(tmpdir) # something we downloaded
865
+ and self.build_directory and spec is not None):
866
+ setup_base = self.maybe_move(spec, dist_filename, setup_base)
867
+
868
+ # Find the setup.py file
869
+ setup_script = os.path.join(setup_base, 'setup.py')
870
+
871
+ if not os.path.exists(setup_script):
872
+ setups = glob(os.path.join(setup_base, '*', 'setup.py'))
873
+ if not setups:
874
+ raise DistutilsError(
875
+ "Couldn't find a setup script in %s" %
876
+ os.path.abspath(dist_filename)
877
+ )
878
+ if len(setups) > 1:
879
+ raise DistutilsError(
880
+ "Multiple setup scripts in %s" %
881
+ os.path.abspath(dist_filename)
882
+ )
883
+ setup_script = setups[0]
884
+
885
+ # Now run it, and return the result
886
+ if self.editable:
887
+ log.info(self.report_editable(spec, setup_script))
888
+ return []
889
+ else:
890
+ return self.build_and_install(setup_script, setup_base)
891
+
892
+ def egg_distribution(self, egg_path):
893
+ if os.path.isdir(egg_path):
894
+ metadata = PathMetadata(egg_path, os.path.join(egg_path,
895
+ 'EGG-INFO'))
896
+ else:
897
+ metadata = EggMetadata(zipimport.zipimporter(egg_path))
898
+ return Distribution.from_filename(egg_path, metadata=metadata)
899
+
900
+ # FIXME: 'easy_install.install_egg' is too complex (11)
901
+ def install_egg(self, egg_path, tmpdir): # noqa: C901
902
+ destination = os.path.join(
903
+ self.install_dir,
904
+ os.path.basename(egg_path),
905
+ )
906
+ destination = os.path.abspath(destination)
907
+ if not self.dry_run:
908
+ ensure_directory(destination)
909
+
910
+ dist = self.egg_distribution(egg_path)
911
+ if not samefile(egg_path, destination):
912
+ if os.path.isdir(destination) and not os.path.islink(destination):
913
+ dir_util.remove_tree(destination, dry_run=self.dry_run)
914
+ elif os.path.exists(destination):
915
+ self.execute(
916
+ os.unlink,
917
+ (destination,),
918
+ "Removing " + destination,
919
+ )
920
+ try:
921
+ new_dist_is_zipped = False
922
+ if os.path.isdir(egg_path):
923
+ if egg_path.startswith(tmpdir):
924
+ f, m = shutil.move, "Moving"
925
+ else:
926
+ f, m = shutil.copytree, "Copying"
927
+ elif self.should_unzip(dist):
928
+ self.mkpath(destination)
929
+ f, m = self.unpack_and_compile, "Extracting"
930
+ else:
931
+ new_dist_is_zipped = True
932
+ if egg_path.startswith(tmpdir):
933
+ f, m = shutil.move, "Moving"
934
+ else:
935
+ f, m = shutil.copy2, "Copying"
936
+ self.execute(
937
+ f,
938
+ (egg_path, destination),
939
+ (m + " %s to %s") % (
940
+ os.path.basename(egg_path),
941
+ os.path.dirname(destination)
942
+ ),
943
+ )
944
+ update_dist_caches(
945
+ destination,
946
+ fix_zipimporter_caches=new_dist_is_zipped,
947
+ )
948
+ except Exception:
949
+ update_dist_caches(destination, fix_zipimporter_caches=False)
950
+ raise
951
+
952
+ self.add_output(destination)
953
+ return self.egg_distribution(destination)
954
+
955
+ def install_exe(self, dist_filename, tmpdir):
956
+ # See if it's valid, get data
957
+ cfg = extract_wininst_cfg(dist_filename)
958
+ if cfg is None:
959
+ raise DistutilsError(
960
+ "%s is not a valid distutils Windows .exe" % dist_filename
961
+ )
962
+ # Create a dummy distribution object until we build the real distro
963
+ dist = Distribution(
964
+ None,
965
+ project_name=cfg.get('metadata', 'name'),
966
+ version=cfg.get('metadata', 'version'), platform=get_platform(),
967
+ )
968
+
969
+ # Convert the .exe to an unpacked egg
970
+ egg_path = os.path.join(tmpdir, dist.egg_name() + '.egg')
971
+ dist.location = egg_path
972
+ egg_tmp = egg_path + '.tmp'
973
+ _egg_info = os.path.join(egg_tmp, 'EGG-INFO')
974
+ pkg_inf = os.path.join(_egg_info, 'PKG-INFO')
975
+ ensure_directory(pkg_inf) # make sure EGG-INFO dir exists
976
+ dist._provider = PathMetadata(egg_tmp, _egg_info) # XXX
977
+ self.exe_to_egg(dist_filename, egg_tmp)
978
+
979
+ # Write EGG-INFO/PKG-INFO
980
+ if not os.path.exists(pkg_inf):
981
+ f = open(pkg_inf, 'w')
982
+ f.write('Metadata-Version: 1.0\n')
983
+ for k, v in cfg.items('metadata'):
984
+ if k != 'target_version':
985
+ f.write('%s: %s\n' % (k.replace('_', '-').title(), v))
986
+ f.close()
987
+ script_dir = os.path.join(_egg_info, 'scripts')
988
+ # delete entry-point scripts to avoid duping
989
+ self.delete_blockers([
990
+ os.path.join(script_dir, args[0])
991
+ for args in ScriptWriter.get_args(dist)
992
+ ])
993
+ # Build .egg file from tmpdir
994
+ bdist_egg.make_zipfile(
995
+ egg_path, egg_tmp, verbose=self.verbose, dry_run=self.dry_run,
996
+ )
997
+ # install the .egg
998
+ return self.install_egg(egg_path, tmpdir)
999
+
1000
+ # FIXME: 'easy_install.exe_to_egg' is too complex (12)
1001
+ def exe_to_egg(self, dist_filename, egg_tmp): # noqa: C901
1002
+ """Extract a bdist_wininst to the directories an egg would use"""
1003
+ # Check for .pth file and set up prefix translations
1004
+ prefixes = get_exe_prefixes(dist_filename)
1005
+ to_compile = []
1006
+ native_libs = []
1007
+ top_level = {}
1008
+
1009
+ def process(src, dst):
1010
+ s = src.lower()
1011
+ for old, new in prefixes:
1012
+ if s.startswith(old):
1013
+ src = new + src[len(old):]
1014
+ parts = src.split('/')
1015
+ dst = os.path.join(egg_tmp, *parts)
1016
+ dl = dst.lower()
1017
+ if dl.endswith('.pyd') or dl.endswith('.dll'):
1018
+ parts[-1] = bdist_egg.strip_module(parts[-1])
1019
+ top_level[os.path.splitext(parts[0])[0]] = 1
1020
+ native_libs.append(src)
1021
+ elif dl.endswith('.py') and old != 'SCRIPTS/':
1022
+ top_level[os.path.splitext(parts[0])[0]] = 1
1023
+ to_compile.append(dst)
1024
+ return dst
1025
+ if not src.endswith('.pth'):
1026
+ log.warn("WARNING: can't process %s", src)
1027
+ return None
1028
+
1029
+ # extract, tracking .pyd/.dll->native_libs and .py -> to_compile
1030
+ unpack_archive(dist_filename, egg_tmp, process)
1031
+ stubs = []
1032
+ for res in native_libs:
1033
+ if res.lower().endswith('.pyd'): # create stubs for .pyd's
1034
+ parts = res.split('/')
1035
+ resource = parts[-1]
1036
+ parts[-1] = bdist_egg.strip_module(parts[-1]) + '.py'
1037
+ pyfile = os.path.join(egg_tmp, *parts)
1038
+ to_compile.append(pyfile)
1039
+ stubs.append(pyfile)
1040
+ bdist_egg.write_stub(resource, pyfile)
1041
+ self.byte_compile(to_compile) # compile .py's
1042
+ bdist_egg.write_safety_flag(
1043
+ os.path.join(egg_tmp, 'EGG-INFO'),
1044
+ bdist_egg.analyze_egg(egg_tmp, stubs)) # write zip-safety flag
1045
+
1046
+ for name in 'top_level', 'native_libs':
1047
+ if locals()[name]:
1048
+ txt = os.path.join(egg_tmp, 'EGG-INFO', name + '.txt')
1049
+ if not os.path.exists(txt):
1050
+ f = open(txt, 'w')
1051
+ f.write('\n'.join(locals()[name]) + '\n')
1052
+ f.close()
1053
+
1054
+ def install_wheel(self, wheel_path, tmpdir):
1055
+ wheel = Wheel(wheel_path)
1056
+ assert wheel.is_compatible()
1057
+ destination = os.path.join(self.install_dir, wheel.egg_name())
1058
+ destination = os.path.abspath(destination)
1059
+ if not self.dry_run:
1060
+ ensure_directory(destination)
1061
+ if os.path.isdir(destination) and not os.path.islink(destination):
1062
+ dir_util.remove_tree(destination, dry_run=self.dry_run)
1063
+ elif os.path.exists(destination):
1064
+ self.execute(
1065
+ os.unlink,
1066
+ (destination,),
1067
+ "Removing " + destination,
1068
+ )
1069
+ try:
1070
+ self.execute(
1071
+ wheel.install_as_egg,
1072
+ (destination,),
1073
+ ("Installing %s to %s") % (
1074
+ os.path.basename(wheel_path),
1075
+ os.path.dirname(destination)
1076
+ ),
1077
+ )
1078
+ finally:
1079
+ update_dist_caches(destination, fix_zipimporter_caches=False)
1080
+ self.add_output(destination)
1081
+ return self.egg_distribution(destination)
1082
+
1083
+ __mv_warning = textwrap.dedent("""
1084
+ Because this distribution was installed --multi-version, before you can
1085
+ import modules from this package in an application, you will need to
1086
+ 'import pkg_resources' and then use a 'require()' call similar to one of
1087
+ these examples, in order to select the desired version:
1088
+
1089
+ pkg_resources.require("%(name)s") # latest installed version
1090
+ pkg_resources.require("%(name)s==%(version)s") # this exact version
1091
+ pkg_resources.require("%(name)s>=%(version)s") # this version or higher
1092
+ """).lstrip() # noqa
1093
+
1094
+ __id_warning = textwrap.dedent("""
1095
+ Note also that the installation directory must be on sys.path at runtime for
1096
+ this to work. (e.g. by being the application's script directory, by being on
1097
+ PYTHONPATH, or by being added to sys.path by your code.)
1098
+ """) # noqa
1099
+
1100
+ def installation_report(self, req, dist, what="Installed"):
1101
+ """Helpful installation message for display to package users"""
1102
+ msg = "\n%(what)s %(eggloc)s%(extras)s"
1103
+ if self.multi_version and not self.no_report:
1104
+ msg += '\n' + self.__mv_warning
1105
+ if self.install_dir not in map(normalize_path, sys.path):
1106
+ msg += '\n' + self.__id_warning
1107
+
1108
+ eggloc = dist.location
1109
+ name = dist.project_name
1110
+ version = dist.version
1111
+ extras = '' # TODO: self.report_extras(req, dist)
1112
+ return msg % locals()
1113
+
1114
+ __editable_msg = textwrap.dedent("""
1115
+ Extracted editable version of %(spec)s to %(dirname)s
1116
+
1117
+ If it uses setuptools in its setup script, you can activate it in
1118
+ "development" mode by going to that directory and running::
1119
+
1120
+ %(python)s setup.py develop
1121
+
1122
+ See the setuptools documentation for the "develop" command for more info.
1123
+ """).lstrip() # noqa
1124
+
1125
+ def report_editable(self, spec, setup_script):
1126
+ dirname = os.path.dirname(setup_script)
1127
+ python = sys.executable
1128
+ return '\n' + self.__editable_msg % locals()
1129
+
1130
+ def run_setup(self, setup_script, setup_base, args):
1131
+ sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg)
1132
+ sys.modules.setdefault('distutils.command.egg_info', egg_info)
1133
+
1134
+ args = list(args)
1135
+ if self.verbose > 2:
1136
+ v = 'v' * (self.verbose - 1)
1137
+ args.insert(0, '-' + v)
1138
+ elif self.verbose < 2:
1139
+ args.insert(0, '-q')
1140
+ if self.dry_run:
1141
+ args.insert(0, '-n')
1142
+ log.info(
1143
+ "Running %s %s", setup_script[len(setup_base) + 1:], ' '.join(args)
1144
+ )
1145
+ try:
1146
+ run_setup(setup_script, args)
1147
+ except SystemExit as v:
1148
+ raise DistutilsError(
1149
+ "Setup script exited with %s" % (v.args[0],)
1150
+ ) from v
1151
+
1152
+ def build_and_install(self, setup_script, setup_base):
1153
+ args = ['bdist_egg', '--dist-dir']
1154
+
1155
+ dist_dir = tempfile.mkdtemp(
1156
+ prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script)
1157
+ )
1158
+ try:
1159
+ self._set_fetcher_options(os.path.dirname(setup_script))
1160
+ args.append(dist_dir)
1161
+
1162
+ self.run_setup(setup_script, setup_base, args)
1163
+ all_eggs = Environment([dist_dir])
1164
+ eggs = []
1165
+ for key in all_eggs:
1166
+ for dist in all_eggs[key]:
1167
+ eggs.append(self.install_egg(dist.location, setup_base))
1168
+ if not eggs and not self.dry_run:
1169
+ log.warn("No eggs found in %s (setup script problem?)",
1170
+ dist_dir)
1171
+ return eggs
1172
+ finally:
1173
+ rmtree(dist_dir)
1174
+ log.set_verbosity(self.verbose) # restore our log verbosity
1175
+
1176
+ def _set_fetcher_options(self, base):
1177
+ """
1178
+ When easy_install is about to run bdist_egg on a source dist, that
1179
+ source dist might have 'setup_requires' directives, requiring
1180
+ additional fetching. Ensure the fetcher options given to easy_install
1181
+ are available to that command as well.
1182
+ """
1183
+ # find the fetch options from easy_install and write them out
1184
+ # to the setup.cfg file.
1185
+ ei_opts = self.distribution.get_option_dict('easy_install').copy()
1186
+ fetch_directives = (
1187
+ 'find_links', 'site_dirs', 'index_url', 'optimize', 'allow_hosts',
1188
+ )
1189
+ fetch_options = {}
1190
+ for key, val in ei_opts.items():
1191
+ if key not in fetch_directives:
1192
+ continue
1193
+ fetch_options[key] = val[1]
1194
+ # create a settings dictionary suitable for `edit_config`
1195
+ settings = dict(easy_install=fetch_options)
1196
+ cfg_filename = os.path.join(base, 'setup.cfg')
1197
+ setopt.edit_config(cfg_filename, settings)
1198
+
1199
+ def update_pth(self, dist): # noqa: C901 # is too complex (11) # FIXME
1200
+ if self.pth_file is None:
1201
+ return
1202
+
1203
+ for d in self.pth_file[dist.key]: # drop old entries
1204
+ if not self.multi_version and d.location == dist.location:
1205
+ continue
1206
+
1207
+ log.info("Removing %s from easy-install.pth file", d)
1208
+ self.pth_file.remove(d)
1209
+ if d.location in self.shadow_path:
1210
+ self.shadow_path.remove(d.location)
1211
+
1212
+ if not self.multi_version:
1213
+ if dist.location in self.pth_file.paths:
1214
+ log.info(
1215
+ "%s is already the active version in easy-install.pth",
1216
+ dist,
1217
+ )
1218
+ else:
1219
+ log.info("Adding %s to easy-install.pth file", dist)
1220
+ self.pth_file.add(dist) # add new entry
1221
+ if dist.location not in self.shadow_path:
1222
+ self.shadow_path.append(dist.location)
1223
+
1224
+ if self.dry_run:
1225
+ return
1226
+
1227
+ self.pth_file.save()
1228
+
1229
+ if dist.key != 'setuptools':
1230
+ return
1231
+
1232
+ # Ensure that setuptools itself never becomes unavailable!
1233
+ # XXX should this check for latest version?
1234
+ filename = os.path.join(self.install_dir, 'setuptools.pth')
1235
+ if os.path.islink(filename):
1236
+ os.unlink(filename)
1237
+ with open(filename, 'wt') as f:
1238
+ f.write(self.pth_file.make_relative(dist.location) + '\n')
1239
+
1240
+ def unpack_progress(self, src, dst):
1241
+ # Progress filter for unpacking
1242
+ log.debug("Unpacking %s to %s", src, dst)
1243
+ return dst # only unpack-and-compile skips files for dry run
1244
+
1245
+ def unpack_and_compile(self, egg_path, destination):
1246
+ to_compile = []
1247
+ to_chmod = []
1248
+
1249
+ def pf(src, dst):
1250
+ if dst.endswith('.py') and not src.startswith('EGG-INFO/'):
1251
+ to_compile.append(dst)
1252
+ elif dst.endswith('.dll') or dst.endswith('.so'):
1253
+ to_chmod.append(dst)
1254
+ self.unpack_progress(src, dst)
1255
+ return not self.dry_run and dst or None
1256
+
1257
+ unpack_archive(egg_path, destination, pf)
1258
+ self.byte_compile(to_compile)
1259
+ if not self.dry_run:
1260
+ for f in to_chmod:
1261
+ mode = ((os.stat(f)[stat.ST_MODE]) | 0o555) & 0o7755
1262
+ chmod(f, mode)
1263
+
1264
+ def byte_compile(self, to_compile):
1265
+ if sys.dont_write_bytecode:
1266
+ return
1267
+
1268
+ from distutils.util import byte_compile
1269
+
1270
+ try:
1271
+ # try to make the byte compile messages quieter
1272
+ log.set_verbosity(self.verbose - 1)
1273
+
1274
+ byte_compile(to_compile, optimize=0, force=1, dry_run=self.dry_run)
1275
+ if self.optimize:
1276
+ byte_compile(
1277
+ to_compile, optimize=self.optimize, force=1,
1278
+ dry_run=self.dry_run,
1279
+ )
1280
+ finally:
1281
+ log.set_verbosity(self.verbose) # restore original verbosity
1282
+
1283
+ __no_default_msg = textwrap.dedent("""
1284
+ bad install directory or PYTHONPATH
1285
+
1286
+ You are attempting to install a package to a directory that is not
1287
+ on PYTHONPATH and which Python does not read ".pth" files from. The
1288
+ installation directory you specified (via --install-dir, --prefix, or
1289
+ the distutils default setting) was:
1290
+
1291
+ %s
1292
+
1293
+ and your PYTHONPATH environment variable currently contains:
1294
+
1295
+ %r
1296
+
1297
+ Here are some of your options for correcting the problem:
1298
+
1299
+ * You can choose a different installation directory, i.e., one that is
1300
+ on PYTHONPATH or supports .pth files
1301
+
1302
+ * You can add the installation directory to the PYTHONPATH environment
1303
+ variable. (It must then also be on PYTHONPATH whenever you run
1304
+ Python and want to use the package(s) you are installing.)
1305
+
1306
+ * You can set up the installation directory to support ".pth" files by
1307
+ using one of the approaches described here:
1308
+
1309
+ https://setuptools.readthedocs.io/en/latest/deprecated/easy_install.html#custom-installation-locations
1310
+
1311
+
1312
+ Please make the appropriate changes for your system and try again.
1313
+ """).strip()
1314
+
1315
+ def create_home_path(self):
1316
+ """Create directories under ~."""
1317
+ if not self.user:
1318
+ return
1319
+ home = convert_path(os.path.expanduser("~"))
1320
+ for name, path in self.config_vars.items():
1321
+ if path.startswith(home) and not os.path.isdir(path):
1322
+ self.debug_print("os.makedirs('%s', 0o700)" % path)
1323
+ os.makedirs(path, 0o700)
1324
+
1325
+ INSTALL_SCHEMES = dict(
1326
+ posix=dict(
1327
+ install_dir='$base/lib/python$py_version_short/site-packages',
1328
+ script_dir='$base/bin',
1329
+ ),
1330
+ )
1331
+
1332
+ DEFAULT_SCHEME = dict(
1333
+ install_dir='$base/Lib/site-packages',
1334
+ script_dir='$base/Scripts',
1335
+ )
1336
+
1337
+ def _expand(self, *attrs):
1338
+ config_vars = self.get_finalized_command('install').config_vars
1339
+
1340
+ if self.prefix:
1341
+ # Set default install_dir/scripts from --prefix
1342
+ config_vars = config_vars.copy()
1343
+ config_vars['base'] = self.prefix
1344
+ scheme = self.INSTALL_SCHEMES.get(os.name, self.DEFAULT_SCHEME)
1345
+ for attr, val in scheme.items():
1346
+ if getattr(self, attr, None) is None:
1347
+ setattr(self, attr, val)
1348
+
1349
+ from distutils.util import subst_vars
1350
+
1351
+ for attr in attrs:
1352
+ val = getattr(self, attr)
1353
+ if val is not None:
1354
+ val = subst_vars(val, config_vars)
1355
+ if os.name == 'posix':
1356
+ val = os.path.expanduser(val)
1357
+ setattr(self, attr, val)
1358
+
1359
+
1360
+ def _pythonpath():
1361
+ items = os.environ.get('PYTHONPATH', '').split(os.pathsep)
1362
+ return filter(None, items)
1363
+
1364
+
1365
+ def get_site_dirs():
1366
+ """
1367
+ Return a list of 'site' dirs
1368
+ """
1369
+
1370
+ sitedirs = []
1371
+
1372
+ # start with PYTHONPATH
1373
+ sitedirs.extend(_pythonpath())
1374
+
1375
+ prefixes = [sys.prefix]
1376
+ if sys.exec_prefix != sys.prefix:
1377
+ prefixes.append(sys.exec_prefix)
1378
+ for prefix in prefixes:
1379
+ if not prefix:
1380
+ continue
1381
+
1382
+ if sys.platform in ('os2emx', 'riscos'):
1383
+ sitedirs.append(os.path.join(prefix, "Lib", "site-packages"))
1384
+ elif os.sep == '/':
1385
+ sitedirs.extend([
1386
+ os.path.join(
1387
+ prefix,
1388
+ "lib",
1389
+ "python{}.{}".format(*sys.version_info),
1390
+ "site-packages",
1391
+ ),
1392
+ os.path.join(prefix, "lib", "site-python"),
1393
+ ])
1394
+ else:
1395
+ sitedirs.extend([
1396
+ prefix,
1397
+ os.path.join(prefix, "lib", "site-packages"),
1398
+ ])
1399
+ if sys.platform != 'darwin':
1400
+ continue
1401
+
1402
+ # for framework builds *only* we add the standard Apple
1403
+ # locations. Currently only per-user, but /Library and
1404
+ # /Network/Library could be added too
1405
+ if 'Python.framework' not in prefix:
1406
+ continue
1407
+
1408
+ home = os.environ.get('HOME')
1409
+ if not home:
1410
+ continue
1411
+
1412
+ home_sp = os.path.join(
1413
+ home,
1414
+ 'Library',
1415
+ 'Python',
1416
+ '{}.{}'.format(*sys.version_info),
1417
+ 'site-packages',
1418
+ )
1419
+ sitedirs.append(home_sp)
1420
+ lib_paths = get_path('purelib'), get_path('platlib')
1421
+
1422
+ sitedirs.extend(s for s in lib_paths if s not in sitedirs)
1423
+
1424
+ if site.ENABLE_USER_SITE:
1425
+ sitedirs.append(site.USER_SITE)
1426
+
1427
+ with contextlib.suppress(AttributeError):
1428
+ sitedirs.extend(site.getsitepackages())
1429
+
1430
+ sitedirs = list(map(normalize_path, sitedirs))
1431
+
1432
+ return sitedirs
1433
+
1434
+
1435
+ def expand_paths(inputs): # noqa: C901 # is too complex (11) # FIXME
1436
+ """Yield sys.path directories that might contain "old-style" packages"""
1437
+
1438
+ seen = {}
1439
+
1440
+ for dirname in inputs:
1441
+ dirname = normalize_path(dirname)
1442
+ if dirname in seen:
1443
+ continue
1444
+
1445
+ seen[dirname] = 1
1446
+ if not os.path.isdir(dirname):
1447
+ continue
1448
+
1449
+ files = os.listdir(dirname)
1450
+ yield dirname, files
1451
+
1452
+ for name in files:
1453
+ if not name.endswith('.pth'):
1454
+ # We only care about the .pth files
1455
+ continue
1456
+ if name in ('easy-install.pth', 'setuptools.pth'):
1457
+ # Ignore .pth files that we control
1458
+ continue
1459
+
1460
+ # Read the .pth file
1461
+ f = open(os.path.join(dirname, name))
1462
+ lines = list(yield_lines(f))
1463
+ f.close()
1464
+
1465
+ # Yield existing non-dupe, non-import directory lines from it
1466
+ for line in lines:
1467
+ if line.startswith("import"):
1468
+ continue
1469
+
1470
+ line = normalize_path(line.rstrip())
1471
+ if line in seen:
1472
+ continue
1473
+
1474
+ seen[line] = 1
1475
+ if not os.path.isdir(line):
1476
+ continue
1477
+
1478
+ yield line, os.listdir(line)
1479
+
1480
+
1481
+ def extract_wininst_cfg(dist_filename):
1482
+ """Extract configuration data from a bdist_wininst .exe
1483
+
1484
+ Returns a configparser.RawConfigParser, or None
1485
+ """
1486
+ f = open(dist_filename, 'rb')
1487
+ try:
1488
+ endrec = zipfile._EndRecData(f)
1489
+ if endrec is None:
1490
+ return None
1491
+
1492
+ prepended = (endrec[9] - endrec[5]) - endrec[6]
1493
+ if prepended < 12: # no wininst data here
1494
+ return None
1495
+ f.seek(prepended - 12)
1496
+
1497
+ tag, cfglen, bmlen = struct.unpack("<iii", f.read(12))
1498
+ if tag not in (0x1234567A, 0x1234567B):
1499
+ return None # not a valid tag
1500
+
1501
+ f.seek(prepended - (12 + cfglen))
1502
+ init = {'version': '', 'target_version': ''}
1503
+ cfg = configparser.RawConfigParser(init)
1504
+ try:
1505
+ part = f.read(cfglen)
1506
+ # Read up to the first null byte.
1507
+ config = part.split(b'\0', 1)[0]
1508
+ # Now the config is in bytes, but for RawConfigParser, it should
1509
+ # be text, so decode it.
1510
+ config = config.decode(sys.getfilesystemencoding())
1511
+ cfg.readfp(io.StringIO(config))
1512
+ except configparser.Error:
1513
+ return None
1514
+ if not cfg.has_section('metadata') or not cfg.has_section('Setup'):
1515
+ return None
1516
+ return cfg
1517
+
1518
+ finally:
1519
+ f.close()
1520
+
1521
+
1522
+ def get_exe_prefixes(exe_filename):
1523
+ """Get exe->egg path translations for a given .exe file"""
1524
+
1525
+ prefixes = [
1526
+ ('PURELIB/', ''),
1527
+ ('PLATLIB/pywin32_system32', ''),
1528
+ ('PLATLIB/', ''),
1529
+ ('SCRIPTS/', 'EGG-INFO/scripts/'),
1530
+ ('DATA/lib/site-packages', ''),
1531
+ ]
1532
+ z = zipfile.ZipFile(exe_filename)
1533
+ try:
1534
+ for info in z.infolist():
1535
+ name = info.filename
1536
+ parts = name.split('/')
1537
+ if len(parts) == 3 and parts[2] == 'PKG-INFO':
1538
+ if parts[1].endswith('.egg-info'):
1539
+ prefixes.insert(0, ('/'.join(parts[:2]), 'EGG-INFO/'))
1540
+ break
1541
+ if len(parts) != 2 or not name.endswith('.pth'):
1542
+ continue
1543
+ if name.endswith('-nspkg.pth'):
1544
+ continue
1545
+ if parts[0].upper() in ('PURELIB', 'PLATLIB'):
1546
+ contents = z.read(name).decode()
1547
+ for pth in yield_lines(contents):
1548
+ pth = pth.strip().replace('\\', '/')
1549
+ if not pth.startswith('import'):
1550
+ prefixes.append((('%s/%s/' % (parts[0], pth)), ''))
1551
+ finally:
1552
+ z.close()
1553
+ prefixes = [(x.lower(), y) for x, y in prefixes]
1554
+ prefixes.sort()
1555
+ prefixes.reverse()
1556
+ return prefixes
1557
+
1558
+
1559
+ class PthDistributions(Environment):
1560
+ """A .pth file with Distribution paths in it"""
1561
+
1562
+ dirty = False
1563
+
1564
+ def __init__(self, filename, sitedirs=()):
1565
+ self.filename = filename
1566
+ self.sitedirs = list(map(normalize_path, sitedirs))
1567
+ self.basedir = normalize_path(os.path.dirname(self.filename))
1568
+ self._load()
1569
+ Environment.__init__(self, [], None, None)
1570
+ for path in yield_lines(self.paths):
1571
+ list(map(self.add, find_distributions(path, True)))
1572
+
1573
+ def _load(self):
1574
+ self.paths = []
1575
+ saw_import = False
1576
+ seen = dict.fromkeys(self.sitedirs)
1577
+ if os.path.isfile(self.filename):
1578
+ f = open(self.filename, 'rt')
1579
+ for line in f:
1580
+ if line.startswith('import'):
1581
+ saw_import = True
1582
+ continue
1583
+ path = line.rstrip()
1584
+ self.paths.append(path)
1585
+ if not path.strip() or path.strip().startswith('#'):
1586
+ continue
1587
+ # skip non-existent paths, in case somebody deleted a package
1588
+ # manually, and duplicate paths as well
1589
+ path = self.paths[-1] = normalize_path(
1590
+ os.path.join(self.basedir, path)
1591
+ )
1592
+ if not os.path.exists(path) or path in seen:
1593
+ self.paths.pop() # skip it
1594
+ self.dirty = True # we cleaned up, so we're dirty now :)
1595
+ continue
1596
+ seen[path] = 1
1597
+ f.close()
1598
+
1599
+ if self.paths and not saw_import:
1600
+ self.dirty = True # ensure anything we touch has import wrappers
1601
+ while self.paths and not self.paths[-1].strip():
1602
+ self.paths.pop()
1603
+
1604
+ def save(self):
1605
+ """Write changed .pth file back to disk"""
1606
+ if not self.dirty:
1607
+ return
1608
+
1609
+ rel_paths = list(map(self.make_relative, self.paths))
1610
+ if rel_paths:
1611
+ log.debug("Saving %s", self.filename)
1612
+ lines = self._wrap_lines(rel_paths)
1613
+ data = '\n'.join(lines) + '\n'
1614
+
1615
+ if os.path.islink(self.filename):
1616
+ os.unlink(self.filename)
1617
+ with open(self.filename, 'wt') as f:
1618
+ f.write(data)
1619
+
1620
+ elif os.path.exists(self.filename):
1621
+ log.debug("Deleting empty %s", self.filename)
1622
+ os.unlink(self.filename)
1623
+
1624
+ self.dirty = False
1625
+
1626
+ @staticmethod
1627
+ def _wrap_lines(lines):
1628
+ return lines
1629
+
1630
+ def add(self, dist):
1631
+ """Add `dist` to the distribution map"""
1632
+ new_path = (
1633
+ dist.location not in self.paths and (
1634
+ dist.location not in self.sitedirs or
1635
+ # account for '.' being in PYTHONPATH
1636
+ dist.location == os.getcwd()
1637
+ )
1638
+ )
1639
+ if new_path:
1640
+ self.paths.append(dist.location)
1641
+ self.dirty = True
1642
+ Environment.add(self, dist)
1643
+
1644
+ def remove(self, dist):
1645
+ """Remove `dist` from the distribution map"""
1646
+ while dist.location in self.paths:
1647
+ self.paths.remove(dist.location)
1648
+ self.dirty = True
1649
+ Environment.remove(self, dist)
1650
+
1651
+ def make_relative(self, path):
1652
+ npath, last = os.path.split(normalize_path(path))
1653
+ baselen = len(self.basedir)
1654
+ parts = [last]
1655
+ sep = os.altsep == '/' and '/' or os.sep
1656
+ while len(npath) >= baselen:
1657
+ if npath == self.basedir:
1658
+ parts.append(os.curdir)
1659
+ parts.reverse()
1660
+ return sep.join(parts)
1661
+ npath, last = os.path.split(npath)
1662
+ parts.append(last)
1663
+ else:
1664
+ return path
1665
+
1666
+
1667
+ class RewritePthDistributions(PthDistributions):
1668
+ @classmethod
1669
+ def _wrap_lines(cls, lines):
1670
+ yield cls.prelude
1671
+ for line in lines:
1672
+ yield line
1673
+ yield cls.postlude
1674
+
1675
+ prelude = _one_liner("""
1676
+ import sys
1677
+ sys.__plen = len(sys.path)
1678
+ """)
1679
+ postlude = _one_liner("""
1680
+ import sys
1681
+ new = sys.path[sys.__plen:]
1682
+ del sys.path[sys.__plen:]
1683
+ p = getattr(sys, '__egginsert', 0)
1684
+ sys.path[p:p] = new
1685
+ sys.__egginsert = p + len(new)
1686
+ """)
1687
+
1688
+
1689
+ if os.environ.get('SETUPTOOLS_SYS_PATH_TECHNIQUE', 'raw') == 'rewrite':
1690
+ PthDistributions = RewritePthDistributions
1691
+
1692
+
1693
+ def _first_line_re():
1694
+ """
1695
+ Return a regular expression based on first_line_re suitable for matching
1696
+ strings.
1697
+ """
1698
+ if isinstance(first_line_re.pattern, str):
1699
+ return first_line_re
1700
+
1701
+ # first_line_re in Python >=3.1.4 and >=3.2.1 is a bytes pattern.
1702
+ return re.compile(first_line_re.pattern.decode())
1703
+
1704
+
1705
+ def auto_chmod(func, arg, exc):
1706
+ if func in [os.unlink, os.remove] and os.name == 'nt':
1707
+ chmod(arg, stat.S_IWRITE)
1708
+ return func(arg)
1709
+ et, ev, _ = sys.exc_info()
1710
+ # TODO: This code doesn't make sense. What is it trying to do?
1711
+ raise (ev[0], ev[1] + (" %s %s" % (func, arg)))
1712
+
1713
+
1714
+ def update_dist_caches(dist_path, fix_zipimporter_caches):
1715
+ """
1716
+ Fix any globally cached `dist_path` related data
1717
+
1718
+ `dist_path` should be a path of a newly installed egg distribution (zipped
1719
+ or unzipped).
1720
+
1721
+ sys.path_importer_cache contains finder objects that have been cached when
1722
+ importing data from the original distribution. Any such finders need to be
1723
+ cleared since the replacement distribution might be packaged differently,
1724
+ e.g. a zipped egg distribution might get replaced with an unzipped egg
1725
+ folder or vice versa. Having the old finders cached may then cause Python
1726
+ to attempt loading modules from the replacement distribution using an
1727
+ incorrect loader.
1728
+
1729
+ zipimport.zipimporter objects are Python loaders charged with importing
1730
+ data packaged inside zip archives. If stale loaders referencing the
1731
+ original distribution, are left behind, they can fail to load modules from
1732
+ the replacement distribution. E.g. if an old zipimport.zipimporter instance
1733
+ is used to load data from a new zipped egg archive, it may cause the
1734
+ operation to attempt to locate the requested data in the wrong location -
1735
+ one indicated by the original distribution's zip archive directory
1736
+ information. Such an operation may then fail outright, e.g. report having
1737
+ read a 'bad local file header', or even worse, it may fail silently &
1738
+ return invalid data.
1739
+
1740
+ zipimport._zip_directory_cache contains cached zip archive directory
1741
+ information for all existing zipimport.zipimporter instances and all such
1742
+ instances connected to the same archive share the same cached directory
1743
+ information.
1744
+
1745
+ If asked, and the underlying Python implementation allows it, we can fix
1746
+ all existing zipimport.zipimporter instances instead of having to track
1747
+ them down and remove them one by one, by updating their shared cached zip
1748
+ archive directory information. This, of course, assumes that the
1749
+ replacement distribution is packaged as a zipped egg.
1750
+
1751
+ If not asked to fix existing zipimport.zipimporter instances, we still do
1752
+ our best to clear any remaining zipimport.zipimporter related cached data
1753
+ that might somehow later get used when attempting to load data from the new
1754
+ distribution and thus cause such load operations to fail. Note that when
1755
+ tracking down such remaining stale data, we can not catch every conceivable
1756
+ usage from here, and we clear only those that we know of and have found to
1757
+ cause problems if left alive. Any remaining caches should be updated by
1758
+ whomever is in charge of maintaining them, i.e. they should be ready to
1759
+ handle us replacing their zip archives with new distributions at runtime.
1760
+
1761
+ """
1762
+ # There are several other known sources of stale zipimport.zipimporter
1763
+ # instances that we do not clear here, but might if ever given a reason to
1764
+ # do so:
1765
+ # * Global setuptools pkg_resources.working_set (a.k.a. 'master working
1766
+ # set') may contain distributions which may in turn contain their
1767
+ # zipimport.zipimporter loaders.
1768
+ # * Several zipimport.zipimporter loaders held by local variables further
1769
+ # up the function call stack when running the setuptools installation.
1770
+ # * Already loaded modules may have their __loader__ attribute set to the
1771
+ # exact loader instance used when importing them. Python 3.4 docs state
1772
+ # that this information is intended mostly for introspection and so is
1773
+ # not expected to cause us problems.
1774
+ normalized_path = normalize_path(dist_path)
1775
+ _uncache(normalized_path, sys.path_importer_cache)
1776
+ if fix_zipimporter_caches:
1777
+ _replace_zip_directory_cache_data(normalized_path)
1778
+ else:
1779
+ # Here, even though we do not want to fix existing and now stale
1780
+ # zipimporter cache information, we still want to remove it. Related to
1781
+ # Python's zip archive directory information cache, we clear each of
1782
+ # its stale entries in two phases:
1783
+ # 1. Clear the entry so attempting to access zip archive information
1784
+ # via any existing stale zipimport.zipimporter instances fails.
1785
+ # 2. Remove the entry from the cache so any newly constructed
1786
+ # zipimport.zipimporter instances do not end up using old stale
1787
+ # zip archive directory information.
1788
+ # This whole stale data removal step does not seem strictly necessary,
1789
+ # but has been left in because it was done before we started replacing
1790
+ # the zip archive directory information cache content if possible, and
1791
+ # there are no relevant unit tests that we can depend on to tell us if
1792
+ # this is really needed.
1793
+ _remove_and_clear_zip_directory_cache_data(normalized_path)
1794
+
1795
+
1796
+ def _collect_zipimporter_cache_entries(normalized_path, cache):
1797
+ """
1798
+ Return zipimporter cache entry keys related to a given normalized path.
1799
+
1800
+ Alternative path spellings (e.g. those using different character case or
1801
+ those using alternative path separators) related to the same path are
1802
+ included. Any sub-path entries are included as well, i.e. those
1803
+ corresponding to zip archives embedded in other zip archives.
1804
+
1805
+ """
1806
+ result = []
1807
+ prefix_len = len(normalized_path)
1808
+ for p in cache:
1809
+ np = normalize_path(p)
1810
+ if (np.startswith(normalized_path) and
1811
+ np[prefix_len:prefix_len + 1] in (os.sep, '')):
1812
+ result.append(p)
1813
+ return result
1814
+
1815
+
1816
+ def _update_zipimporter_cache(normalized_path, cache, updater=None):
1817
+ """
1818
+ Update zipimporter cache data for a given normalized path.
1819
+
1820
+ Any sub-path entries are processed as well, i.e. those corresponding to zip
1821
+ archives embedded in other zip archives.
1822
+
1823
+ Given updater is a callable taking a cache entry key and the original entry
1824
+ (after already removing the entry from the cache), and expected to update
1825
+ the entry and possibly return a new one to be inserted in its place.
1826
+ Returning None indicates that the entry should not be replaced with a new
1827
+ one. If no updater is given, the cache entries are simply removed without
1828
+ any additional processing, the same as if the updater simply returned None.
1829
+
1830
+ """
1831
+ for p in _collect_zipimporter_cache_entries(normalized_path, cache):
1832
+ # N.B. pypy's custom zipimport._zip_directory_cache implementation does
1833
+ # not support the complete dict interface:
1834
+ # * Does not support item assignment, thus not allowing this function
1835
+ # to be used only for removing existing cache entries.
1836
+ # * Does not support the dict.pop() method, forcing us to use the
1837
+ # get/del patterns instead. For more detailed information see the
1838
+ # following links:
1839
+ # https://github.com/pypa/setuptools/issues/202#issuecomment-202913420
1840
+ # http://bit.ly/2h9itJX
1841
+ old_entry = cache[p]
1842
+ del cache[p]
1843
+ new_entry = updater and updater(p, old_entry)
1844
+ if new_entry is not None:
1845
+ cache[p] = new_entry
1846
+
1847
+
1848
+ def _uncache(normalized_path, cache):
1849
+ _update_zipimporter_cache(normalized_path, cache)
1850
+
1851
+
1852
+ def _remove_and_clear_zip_directory_cache_data(normalized_path):
1853
+ def clear_and_remove_cached_zip_archive_directory_data(path, old_entry):
1854
+ old_entry.clear()
1855
+
1856
+ _update_zipimporter_cache(
1857
+ normalized_path, zipimport._zip_directory_cache,
1858
+ updater=clear_and_remove_cached_zip_archive_directory_data)
1859
+
1860
+
1861
+ # PyPy Python implementation does not allow directly writing to the
1862
+ # zipimport._zip_directory_cache and so prevents us from attempting to correct
1863
+ # its content. The best we can do there is clear the problematic cache content
1864
+ # and have PyPy repopulate it as needed. The downside is that if there are any
1865
+ # stale zipimport.zipimporter instances laying around, attempting to use them
1866
+ # will fail due to not having its zip archive directory information available
1867
+ # instead of being automatically corrected to use the new correct zip archive
1868
+ # directory information.
1869
+ if '__pypy__' in sys.builtin_module_names:
1870
+ _replace_zip_directory_cache_data = \
1871
+ _remove_and_clear_zip_directory_cache_data
1872
+ else:
1873
+
1874
+ def _replace_zip_directory_cache_data(normalized_path):
1875
+ def replace_cached_zip_archive_directory_data(path, old_entry):
1876
+ # N.B. In theory, we could load the zip directory information just
1877
+ # once for all updated path spellings, and then copy it locally and
1878
+ # update its contained path strings to contain the correct
1879
+ # spelling, but that seems like a way too invasive move (this cache
1880
+ # structure is not officially documented anywhere and could in
1881
+ # theory change with new Python releases) for no significant
1882
+ # benefit.
1883
+ old_entry.clear()
1884
+ zipimport.zipimporter(path)
1885
+ old_entry.update(zipimport._zip_directory_cache[path])
1886
+ return old_entry
1887
+
1888
+ _update_zipimporter_cache(
1889
+ normalized_path, zipimport._zip_directory_cache,
1890
+ updater=replace_cached_zip_archive_directory_data)
1891
+
1892
+
1893
+ def is_python(text, filename='<string>'):
1894
+ "Is this string a valid Python script?"
1895
+ try:
1896
+ compile(text, filename, 'exec')
1897
+ except (SyntaxError, TypeError):
1898
+ return False
1899
+ else:
1900
+ return True
1901
+
1902
+
1903
+ def is_sh(executable):
1904
+ """Determine if the specified executable is a .sh (contains a #! line)"""
1905
+ try:
1906
+ with io.open(executable, encoding='latin-1') as fp:
1907
+ magic = fp.read(2)
1908
+ except (OSError, IOError):
1909
+ return executable
1910
+ return magic == '#!'
1911
+
1912
+
1913
+ def nt_quote_arg(arg):
1914
+ """Quote a command line argument according to Windows parsing rules"""
1915
+ return subprocess.list2cmdline([arg])
1916
+
1917
+
1918
+ def is_python_script(script_text, filename):
1919
+ """Is this text, as a whole, a Python script? (as opposed to shell/bat/etc.
1920
+ """
1921
+ if filename.endswith('.py') or filename.endswith('.pyw'):
1922
+ return True # extension says it's Python
1923
+ if is_python(script_text, filename):
1924
+ return True # it's syntactically valid Python
1925
+ if script_text.startswith('#!'):
1926
+ # It begins with a '#!' line, so check if 'python' is in it somewhere
1927
+ return 'python' in script_text.splitlines()[0].lower()
1928
+
1929
+ return False # Not any Python I can recognize
1930
+
1931
+
1932
+ try:
1933
+ from os import chmod as _chmod
1934
+ except ImportError:
1935
+ # Jython compatibility
1936
+ def _chmod(*args):
1937
+ pass
1938
+
1939
+
1940
+ def chmod(path, mode):
1941
+ log.debug("changing mode of %s to %o", path, mode)
1942
+ try:
1943
+ _chmod(path, mode)
1944
+ except os.error as e:
1945
+ log.debug("chmod failed: %s", e)
1946
+
1947
+
1948
+ class CommandSpec(list):
1949
+ """
1950
+ A command spec for a #! header, specified as a list of arguments akin to
1951
+ those passed to Popen.
1952
+ """
1953
+
1954
+ options = []
1955
+ split_args = dict()
1956
+
1957
+ @classmethod
1958
+ def best(cls):
1959
+ """
1960
+ Choose the best CommandSpec class based on environmental conditions.
1961
+ """
1962
+ return cls
1963
+
1964
+ @classmethod
1965
+ def _sys_executable(cls):
1966
+ _default = os.path.normpath(sys.executable)
1967
+ return os.environ.get('__PYVENV_LAUNCHER__', _default)
1968
+
1969
+ @classmethod
1970
+ def from_param(cls, param):
1971
+ """
1972
+ Construct a CommandSpec from a parameter to build_scripts, which may
1973
+ be None.
1974
+ """
1975
+ if isinstance(param, cls):
1976
+ return param
1977
+ if isinstance(param, list):
1978
+ return cls(param)
1979
+ if param is None:
1980
+ return cls.from_environment()
1981
+ # otherwise, assume it's a string.
1982
+ return cls.from_string(param)
1983
+
1984
+ @classmethod
1985
+ def from_environment(cls):
1986
+ return cls([cls._sys_executable()])
1987
+
1988
+ @classmethod
1989
+ def from_string(cls, string):
1990
+ """
1991
+ Construct a command spec from a simple string representing a command
1992
+ line parseable by shlex.split.
1993
+ """
1994
+ items = shlex.split(string, **cls.split_args)
1995
+ return cls(items)
1996
+
1997
+ def install_options(self, script_text):
1998
+ self.options = shlex.split(self._extract_options(script_text))
1999
+ cmdline = subprocess.list2cmdline(self)
2000
+ if not isascii(cmdline):
2001
+ self.options[:0] = ['-x']
2002
+
2003
+ @staticmethod
2004
+ def _extract_options(orig_script):
2005
+ """
2006
+ Extract any options from the first line of the script.
2007
+ """
2008
+ first = (orig_script + '\n').splitlines()[0]
2009
+ match = _first_line_re().match(first)
2010
+ options = match.group(1) or '' if match else ''
2011
+ return options.strip()
2012
+
2013
+ def as_header(self):
2014
+ return self._render(self + list(self.options))
2015
+
2016
+ @staticmethod
2017
+ def _strip_quotes(item):
2018
+ _QUOTES = '"\''
2019
+ for q in _QUOTES:
2020
+ if item.startswith(q) and item.endswith(q):
2021
+ return item[1:-1]
2022
+ return item
2023
+
2024
+ @staticmethod
2025
+ def _render(items):
2026
+ cmdline = subprocess.list2cmdline(
2027
+ CommandSpec._strip_quotes(item.strip()) for item in items)
2028
+ return '#!' + cmdline + '\n'
2029
+
2030
+
2031
+ # For pbr compat; will be removed in a future version.
2032
+ sys_executable = CommandSpec._sys_executable()
2033
+
2034
+
2035
+ class WindowsCommandSpec(CommandSpec):
2036
+ split_args = dict(posix=False)
2037
+
2038
+
2039
+ class ScriptWriter:
2040
+ """
2041
+ Encapsulates behavior around writing entry point scripts for console and
2042
+ gui apps.
2043
+ """
2044
+
2045
+ template = textwrap.dedent(r"""
2046
+ # EASY-INSTALL-ENTRY-SCRIPT: %(spec)r,%(group)r,%(name)r
2047
+ import re
2048
+ import sys
2049
+
2050
+ # for compatibility with easy_install; see #2198
2051
+ __requires__ = %(spec)r
2052
+
2053
+ try:
2054
+ from importlib.metadata import distribution
2055
+ except ImportError:
2056
+ try:
2057
+ from importlib_metadata import distribution
2058
+ except ImportError:
2059
+ from pkg_resources import load_entry_point
2060
+
2061
+
2062
+ def importlib_load_entry_point(spec, group, name):
2063
+ dist_name, _, _ = spec.partition('==')
2064
+ matches = (
2065
+ entry_point
2066
+ for entry_point in distribution(dist_name).entry_points
2067
+ if entry_point.group == group and entry_point.name == name
2068
+ )
2069
+ return next(matches).load()
2070
+
2071
+
2072
+ globals().setdefault('load_entry_point', importlib_load_entry_point)
2073
+
2074
+
2075
+ if __name__ == '__main__':
2076
+ sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
2077
+ sys.exit(load_entry_point(%(spec)r, %(group)r, %(name)r)())
2078
+ """).lstrip()
2079
+
2080
+ command_spec_class = CommandSpec
2081
+
2082
+ @classmethod
2083
+ def get_script_args(cls, dist, executable=None, wininst=False):
2084
+ # for backward compatibility
2085
+ warnings.warn("Use get_args", EasyInstallDeprecationWarning)
2086
+ writer = (WindowsScriptWriter if wininst else ScriptWriter).best()
2087
+ header = cls.get_script_header("", executable, wininst)
2088
+ return writer.get_args(dist, header)
2089
+
2090
+ @classmethod
2091
+ def get_script_header(cls, script_text, executable=None, wininst=False):
2092
+ # for backward compatibility
2093
+ warnings.warn(
2094
+ "Use get_header", EasyInstallDeprecationWarning, stacklevel=2)
2095
+ if wininst:
2096
+ executable = "python.exe"
2097
+ return cls.get_header(script_text, executable)
2098
+
2099
+ @classmethod
2100
+ def get_args(cls, dist, header=None):
2101
+ """
2102
+ Yield write_script() argument tuples for a distribution's
2103
+ console_scripts and gui_scripts entry points.
2104
+ """
2105
+ if header is None:
2106
+ header = cls.get_header()
2107
+ spec = str(dist.as_requirement())
2108
+ for type_ in 'console', 'gui':
2109
+ group = type_ + '_scripts'
2110
+ for name, ep in dist.get_entry_map(group).items():
2111
+ cls._ensure_safe_name(name)
2112
+ script_text = cls.template % locals()
2113
+ args = cls._get_script_args(type_, name, header, script_text)
2114
+ for res in args:
2115
+ yield res
2116
+
2117
+ @staticmethod
2118
+ def _ensure_safe_name(name):
2119
+ """
2120
+ Prevent paths in *_scripts entry point names.
2121
+ """
2122
+ has_path_sep = re.search(r'[\\/]', name)
2123
+ if has_path_sep:
2124
+ raise ValueError("Path separators not allowed in script names")
2125
+
2126
+ @classmethod
2127
+ def get_writer(cls, force_windows):
2128
+ # for backward compatibility
2129
+ warnings.warn("Use best", EasyInstallDeprecationWarning)
2130
+ return WindowsScriptWriter.best() if force_windows else cls.best()
2131
+
2132
+ @classmethod
2133
+ def best(cls):
2134
+ """
2135
+ Select the best ScriptWriter for this environment.
2136
+ """
2137
+ if sys.platform == 'win32' or (os.name == 'java' and os._name == 'nt'):
2138
+ return WindowsScriptWriter.best()
2139
+ else:
2140
+ return cls
2141
+
2142
+ @classmethod
2143
+ def _get_script_args(cls, type_, name, header, script_text):
2144
+ # Simply write the stub with no extension.
2145
+ yield (name, header + script_text)
2146
+
2147
+ @classmethod
2148
+ def get_header(cls, script_text="", executable=None):
2149
+ """Create a #! line, getting options (if any) from script_text"""
2150
+ cmd = cls.command_spec_class.best().from_param(executable)
2151
+ cmd.install_options(script_text)
2152
+ return cmd.as_header()
2153
+
2154
+
2155
+ class WindowsScriptWriter(ScriptWriter):
2156
+ command_spec_class = WindowsCommandSpec
2157
+
2158
+ @classmethod
2159
+ def get_writer(cls):
2160
+ # for backward compatibility
2161
+ warnings.warn("Use best", EasyInstallDeprecationWarning)
2162
+ return cls.best()
2163
+
2164
+ @classmethod
2165
+ def best(cls):
2166
+ """
2167
+ Select the best ScriptWriter suitable for Windows
2168
+ """
2169
+ writer_lookup = dict(
2170
+ executable=WindowsExecutableLauncherWriter,
2171
+ natural=cls,
2172
+ )
2173
+ # for compatibility, use the executable launcher by default
2174
+ launcher = os.environ.get('SETUPTOOLS_LAUNCHER', 'executable')
2175
+ return writer_lookup[launcher]
2176
+
2177
+ @classmethod
2178
+ def _get_script_args(cls, type_, name, header, script_text):
2179
+ "For Windows, add a .py extension"
2180
+ ext = dict(console='.pya', gui='.pyw')[type_]
2181
+ if ext not in os.environ['PATHEXT'].lower().split(';'):
2182
+ msg = (
2183
+ "{ext} not listed in PATHEXT; scripts will not be "
2184
+ "recognized as executables."
2185
+ ).format(**locals())
2186
+ warnings.warn(msg, UserWarning)
2187
+ old = ['.pya', '.py', '-script.py', '.pyc', '.pyo', '.pyw', '.exe']
2188
+ old.remove(ext)
2189
+ header = cls._adjust_header(type_, header)
2190
+ blockers = [name + x for x in old]
2191
+ yield name + ext, header + script_text, 't', blockers
2192
+
2193
+ @classmethod
2194
+ def _adjust_header(cls, type_, orig_header):
2195
+ """
2196
+ Make sure 'pythonw' is used for gui and 'python' is used for
2197
+ console (regardless of what sys.executable is).
2198
+ """
2199
+ pattern = 'pythonw.exe'
2200
+ repl = 'python.exe'
2201
+ if type_ == 'gui':
2202
+ pattern, repl = repl, pattern
2203
+ pattern_ob = re.compile(re.escape(pattern), re.IGNORECASE)
2204
+ new_header = pattern_ob.sub(string=orig_header, repl=repl)
2205
+ return new_header if cls._use_header(new_header) else orig_header
2206
+
2207
+ @staticmethod
2208
+ def _use_header(new_header):
2209
+ """
2210
+ Should _adjust_header use the replaced header?
2211
+
2212
+ On non-windows systems, always use. On
2213
+ Windows systems, only use the replaced header if it resolves
2214
+ to an executable on the system.
2215
+ """
2216
+ clean_header = new_header[2:-1].strip('"')
2217
+ return sys.platform != 'win32' or find_executable(clean_header)
2218
+
2219
+
2220
+ class WindowsExecutableLauncherWriter(WindowsScriptWriter):
2221
+ @classmethod
2222
+ def _get_script_args(cls, type_, name, header, script_text):
2223
+ """
2224
+ For Windows, add a .py extension and an .exe launcher
2225
+ """
2226
+ if type_ == 'gui':
2227
+ launcher_type = 'gui'
2228
+ ext = '-script.pyw'
2229
+ old = ['.pyw']
2230
+ else:
2231
+ launcher_type = 'cli'
2232
+ ext = '-script.py'
2233
+ old = ['.py', '.pyc', '.pyo']
2234
+ hdr = cls._adjust_header(type_, header)
2235
+ blockers = [name + x for x in old]
2236
+ yield (name + ext, hdr + script_text, 't', blockers)
2237
+ yield (
2238
+ name + '.exe', get_win_launcher(launcher_type),
2239
+ 'b' # write in binary mode
2240
+ )
2241
+ if not is_64bit():
2242
+ # install a manifest for the launcher to prevent Windows
2243
+ # from detecting it as an installer (which it will for
2244
+ # launchers like easy_install.exe). Consider only
2245
+ # adding a manifest for launchers detected as installers.
2246
+ # See Distribute #143 for details.
2247
+ m_name = name + '.exe.manifest'
2248
+ yield (m_name, load_launcher_manifest(name), 't')
2249
+
2250
+
2251
+ # for backward-compatibility
2252
+ get_script_args = ScriptWriter.get_script_args
2253
+ get_script_header = ScriptWriter.get_script_header
2254
+
2255
+
2256
+ def get_win_launcher(type):
2257
+ """
2258
+ Load the Windows launcher (executable) suitable for launching a script.
2259
+
2260
+ `type` should be either 'cli' or 'gui'
2261
+
2262
+ Returns the executable as a byte string.
2263
+ """
2264
+ launcher_fn = '%s.exe' % type
2265
+ if is_64bit():
2266
+ launcher_fn = launcher_fn.replace(".", "-64.")
2267
+ else:
2268
+ launcher_fn = launcher_fn.replace(".", "-32.")
2269
+ return resource_string('setuptools', launcher_fn)
2270
+
2271
+
2272
+ def load_launcher_manifest(name):
2273
+ manifest = pkg_resources.resource_string(__name__, 'launcher manifest.xml')
2274
+ return manifest.decode('utf-8') % vars()
2275
+
2276
+
2277
+ def rmtree(path, ignore_errors=False, onerror=auto_chmod):
2278
+ return shutil.rmtree(path, ignore_errors, onerror)
2279
+
2280
+
2281
+ def current_umask():
2282
+ tmp = os.umask(0o022)
2283
+ os.umask(tmp)
2284
+ return tmp
2285
+
2286
+
2287
+ class EasyInstallDeprecationWarning(SetuptoolsDeprecationWarning):
2288
+ """
2289
+ Warning for EasyInstall deprecations, bypassing suppression.
2290
+ """