mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1680802: Bump vendored virtualenv package r=firefox-build-system-reviewers,sheehan,glandium
The `wheel` package was failing with Mac Big Sur. It's been updated, but our `virtualenv` package has its own vendored `wheel` package that is out-of-date. This updates `virtualenv` to "20.2.2". This should solve "assert len(base_version) == 2" and "would build wheel with unsupported tag" errors. Differential Revision: https://phabricator.services.mozilla.com/D99482
This commit is contained in:
parent
945b23f181
commit
eafc0381ea
2
third_party/python/virtualenv/__main__.py
vendored
2
third_party/python/virtualenv/__main__.py
vendored
@ -4,7 +4,7 @@ import sys
|
||||
import zipfile
|
||||
|
||||
ABS_HERE = os.path.abspath(os.path.dirname(__file__))
|
||||
NEW_IMPORT_SYSTEM = sys.version_info[0:2] > (3, 4)
|
||||
NEW_IMPORT_SYSTEM = sys.version_info[0] == 3
|
||||
|
||||
|
||||
class VersionPlatformSelect(object):
|
||||
|
@ -1,6 +1,6 @@
|
||||
filelock.py,sha256=5DQTtOaQq7-vgLkZzvOhqhVMh_umfydWgSA8Vuzmf8M,13229
|
||||
filelock-3.0.12.dist-info/LICENSE,sha256=iNm062BXnBkew5HKBMFhMFctfu3EqG2qWL8oxuFMm80,1210
|
||||
filelock-3.0.12.dist-info/METADATA,sha256=gjzbv9nxtD-Rj2ysjUuG7SLZCHUQl5hMy68Jij8soPw,4343
|
||||
filelock-3.0.12.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
|
||||
filelock-3.0.12.dist-info/WHEEL,sha256=EVRjI69F5qVjm_YgqcTXPnTAv3BfSUr0WVAHuSP3Xoo,92
|
||||
filelock-3.0.12.dist-info/top_level.txt,sha256=NDrf9i5BNogz4hEdsr6Hi7Ws3TlSSKY4Q2Y9_-i2GwU,9
|
||||
filelock-3.0.12.dist-info/RECORD,,
|
||||
|
@ -1,5 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.34.2)
|
||||
Generator: bdist_wheel (0.35.1)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
importlib_metadata/__init__.py,sha256=phnrEcGP-8cF-_ZZ5peJL4cUVAANOK0CpSWC-0-IVAs,18961
|
||||
importlib_metadata/_compat.py,sha256=DnM55BbJKFCcZmJOkArmyO76-0g7pA6HEfzSYWXN88k,4417
|
||||
importlib_metadata/docs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_metadata/docs/changelog.rst,sha256=6EZfl84T0SQHzAXNlTiTegG0cBTa9wiMt0od0ht2n_8,8739
|
||||
importlib_metadata/docs/conf.py,sha256=m-b6Mju5gFkpSHh-lyJ4iwqf_8t4LjYYFRumtutQSZc,5578
|
||||
importlib_metadata/docs/index.rst,sha256=rbXrDkLAKLIDccqME5u9CCMEfMKprqzQOkIOuwOnfz4,1907
|
||||
importlib_metadata/docs/using.rst,sha256=k_L4Hwwsf10ap9xWejyC-_gLz_WtvRfDOzuJA3o7Zw0,9504
|
||||
importlib_metadata/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_metadata/tests/fixtures.py,sha256=Ua_PqyqBhFqkkNGFsXtgMah6vXKQjeqKo1KhhzYdn-w,5752
|
||||
importlib_metadata/tests/test_api.py,sha256=YMAGTsRENrtvpw2CSLmRndJMBeT4q_M0GSe-QsnnMZ4,5544
|
||||
importlib_metadata/tests/test_integration.py,sha256=ykJpwjSkVwvWHG4gUw4RUrZzU_7JKX8vZyPf_kFIrLE,1579
|
||||
importlib_metadata/tests/test_main.py,sha256=dcsDqyxTRtard2j5ysDDvVwfK6vvXdRtZCaQ0QljSR8,9026
|
||||
importlib_metadata/tests/test_zip.py,sha256=lOCNPyfJSm9nz0-2RQndM7OQV-_gRjJzyRnvMqXqRSI,2675
|
||||
importlib_metadata/tests/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_metadata/tests/data/example-21.12-py3-none-any.whl,sha256=I-kYufETid-tDYyR8f1OFJ3t5u_Io23k0cbQxJTUN4I,1455
|
||||
importlib_metadata/tests/data/example-21.12-py3.6.egg,sha256=-EeugFAijkdUO9xyQHTZkQwZoFXK0_QxICBj6R5AAJo,1497
|
||||
importlib_metadata-1.7.0.dist-info/LICENSE,sha256=wNe6dAchmJ1VvVB8D9oTc-gHHadCuaSBAev36sYEM6U,571
|
||||
importlib_metadata-1.7.0.dist-info/METADATA,sha256=AvM2AcUhNbF_2Yyo8ttyVBCh_qGbRHaRE3MVgrHYDVw,2144
|
||||
importlib_metadata-1.7.0.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110
|
||||
importlib_metadata-1.7.0.dist-info/top_level.txt,sha256=CO3fD9yylANiXkrMo4qHLV_mqXL2sC5JFKgt1yWAT-A,19
|
||||
importlib_metadata-1.7.0.dist-info/RECORD,,
|
@ -1,10 +1,10 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: importlib-metadata
|
||||
Version: 1.7.0
|
||||
Version: 2.1.1
|
||||
Summary: Read metadata from Python packages
|
||||
Home-page: http://importlib-metadata.readthedocs.io/
|
||||
Author: Barry Warsaw
|
||||
Author-email: barry@python.org
|
||||
Author: Jason R. Coombs
|
||||
Author-email: jaraco@jaraco.com
|
||||
License: Apache Software License
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 3 - Alpha
|
||||
@ -24,14 +24,21 @@ Requires-Dist: rst.linker ; extra == 'docs'
|
||||
Provides-Extra: testing
|
||||
Requires-Dist: packaging ; extra == 'testing'
|
||||
Requires-Dist: pep517 ; extra == 'testing'
|
||||
Requires-Dist: unittest2 ; (python_version < "3") and extra == 'testing'
|
||||
Requires-Dist: importlib-resources (>=1.3) ; (python_version < "3.9") and extra == 'testing'
|
||||
|
||||
=========================
|
||||
``importlib_metadata``
|
||||
=========================
|
||||
|
||||
``importlib_metadata`` is a library to access the metadata for a Python
|
||||
package. It is intended to be ported to Python 3.8.
|
||||
``importlib_metadata`` is a library to access the metadata for a
|
||||
Python package.
|
||||
|
||||
As of Python 3.8, this functionality has been added to the
|
||||
`Python standard library
|
||||
<https://docs.python.org/3/library/importlib.metadata.html>`_.
|
||||
This package supplies backports of that functionality including
|
||||
improvements added to subsequent Python versions.
|
||||
|
||||
|
||||
Usage
|
||||
@ -58,9 +65,9 @@ tools (or other conforming packages). It does not support:
|
||||
Project details
|
||||
===============
|
||||
|
||||
* Project home: https://gitlab.com/python-devs/importlib_metadata
|
||||
* Report bugs at: https://gitlab.com/python-devs/importlib_metadata/issues
|
||||
* Code hosting: https://gitlab.com/python-devs/importlib_metadata.git
|
||||
* Documentation: http://importlib_metadata.readthedocs.io/
|
||||
* Project home: https://github.com/python/importlib_metadata
|
||||
* Report bugs at: https://github.com/python/importlib_metadata/issues
|
||||
* Code hosting: https://github.com/python/importlib_metadata
|
||||
* Documentation: https://importlib_metadata.readthedocs.io/
|
||||
|
||||
|
@ -0,0 +1,7 @@
|
||||
importlib_metadata/__init__.py,sha256=uaN7KDLs3-irvgwsxg4VZIuY3ZEo3jhu1dShjE7fR88,19587
|
||||
importlib_metadata/_compat.py,sha256=DnM55BbJKFCcZmJOkArmyO76-0g7pA6HEfzSYWXN88k,4417
|
||||
importlib_metadata-2.1.1.dist-info/LICENSE,sha256=wNe6dAchmJ1VvVB8D9oTc-gHHadCuaSBAev36sYEM6U,571
|
||||
importlib_metadata-2.1.1.dist-info/METADATA,sha256=gBf5nX-Ff6_Ue9dSH4dkWg2FCNHHtQrs6mhunTAac8k,2421
|
||||
importlib_metadata-2.1.1.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110
|
||||
importlib_metadata-2.1.1.dist-info/top_level.txt,sha256=CO3fD9yylANiXkrMo4qHLV_mqXL2sC5JFKgt1yWAT-A,19
|
||||
importlib_metadata-2.1.1.dist-info/RECORD,,
|
@ -462,43 +462,67 @@ class FastPath:
|
||||
for child in names
|
||||
)
|
||||
|
||||
def is_egg(self, search):
|
||||
base = self.base
|
||||
return (
|
||||
base == search.versionless_egg_name
|
||||
or base.startswith(search.prefix)
|
||||
and base.endswith('.egg'))
|
||||
|
||||
def search(self, name):
|
||||
for child in self.children():
|
||||
n_low = child.lower()
|
||||
if (n_low in name.exact_matches
|
||||
or n_low.startswith(name.prefix)
|
||||
and n_low.endswith(name.suffixes)
|
||||
# legacy case:
|
||||
or self.is_egg(name) and n_low == 'egg-info'):
|
||||
yield self.joinpath(child)
|
||||
return (
|
||||
self.joinpath(child)
|
||||
for child in self.children()
|
||||
if name.matches(child, self.base)
|
||||
)
|
||||
|
||||
|
||||
class Prepared:
|
||||
"""
|
||||
A prepared search for metadata on a possibly-named package.
|
||||
"""
|
||||
normalized = ''
|
||||
prefix = ''
|
||||
normalized = None
|
||||
suffixes = '.dist-info', '.egg-info'
|
||||
exact_matches = [''][:0]
|
||||
versionless_egg_name = ''
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
if name is None:
|
||||
return
|
||||
self.normalized = name.lower().replace('-', '_')
|
||||
self.prefix = self.normalized + '-'
|
||||
self.normalized = self.normalize(name)
|
||||
self.exact_matches = [
|
||||
self.normalized + suffix for suffix in self.suffixes]
|
||||
self.versionless_egg_name = self.normalized + '.egg'
|
||||
|
||||
@staticmethod
|
||||
def normalize(name):
|
||||
"""
|
||||
PEP 503 normalization plus dashes as underscores.
|
||||
"""
|
||||
return re.sub(r"[-_.]+", "-", name).lower().replace('-', '_')
|
||||
|
||||
@staticmethod
|
||||
def legacy_normalize(name):
|
||||
"""
|
||||
Normalize the package name as found in the convention in
|
||||
older packaging tools versions and specs.
|
||||
"""
|
||||
return name.lower().replace('-', '_')
|
||||
|
||||
def matches(self, cand, base):
|
||||
low = cand.lower()
|
||||
pre, ext = os.path.splitext(low)
|
||||
name, sep, rest = pre.partition('-')
|
||||
return (
|
||||
low in self.exact_matches
|
||||
or ext in self.suffixes and (
|
||||
not self.normalized or
|
||||
name.replace('.', '_') == self.normalized
|
||||
)
|
||||
# legacy case:
|
||||
or self.is_egg(base) and low == 'egg-info'
|
||||
)
|
||||
|
||||
def is_egg(self, base):
|
||||
normalized = self.legacy_normalize(self.name or '')
|
||||
prefix = normalized + '-' if normalized else ''
|
||||
versionless_egg_name = normalized + '.egg' if self.name else ''
|
||||
return (
|
||||
base == versionless_egg_name
|
||||
or base.startswith(prefix)
|
||||
and base.endswith('.egg'))
|
||||
|
||||
|
||||
@install
|
||||
@ -618,6 +642,3 @@ def requires(distribution_name):
|
||||
packaging.requirement.Requirement.
|
||||
"""
|
||||
return distribution(distribution_name).requires
|
||||
|
||||
|
||||
__version__ = version(__name__)
|
@ -0,0 +1,13 @@
|
||||
Copyright 2017-2019 Jason R. Coombs, Barry Warsaw
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -0,0 +1,94 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: importlib-metadata
|
||||
Version: 3.1.1
|
||||
Summary: Read metadata from Python packages
|
||||
Home-page: https://github.com/python/importlib_metadata
|
||||
Author: Jason R. Coombs
|
||||
Author-email: jaraco@jaraco.com
|
||||
License: UNKNOWN
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: Apache Software License
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3 :: Only
|
||||
Requires-Python: >=3.6
|
||||
Requires-Dist: zipp (>=0.5)
|
||||
Provides-Extra: docs
|
||||
Requires-Dist: sphinx ; extra == 'docs'
|
||||
Requires-Dist: jaraco.packaging (>=3.2) ; extra == 'docs'
|
||||
Requires-Dist: rst.linker (>=1.9) ; extra == 'docs'
|
||||
Provides-Extra: testing
|
||||
Requires-Dist: pytest (!=3.7.3,>=3.5) ; extra == 'testing'
|
||||
Requires-Dist: pytest-checkdocs (>=1.2.3) ; extra == 'testing'
|
||||
Requires-Dist: pytest-flake8 ; extra == 'testing'
|
||||
Requires-Dist: pytest-cov ; extra == 'testing'
|
||||
Requires-Dist: jaraco.test (>=3.2.0) ; extra == 'testing'
|
||||
Requires-Dist: packaging ; extra == 'testing'
|
||||
Requires-Dist: pep517 ; extra == 'testing'
|
||||
Requires-Dist: pyfakefs ; extra == 'testing'
|
||||
Requires-Dist: flufl.flake8 ; extra == 'testing'
|
||||
Requires-Dist: pytest-black (>=0.3.7) ; (platform_python_implementation != "PyPy") and extra == 'testing'
|
||||
Requires-Dist: pytest-mypy ; (platform_python_implementation != "PyPy") and extra == 'testing'
|
||||
Requires-Dist: importlib-resources (>=1.3) ; (python_version < "3.9") and extra == 'testing'
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/importlib_metadata.svg
|
||||
:target: `PyPI link`_
|
||||
|
||||
.. image:: https://img.shields.io/pypi/pyversions/importlib_metadata.svg
|
||||
:target: `PyPI link`_
|
||||
|
||||
.. _PyPI link: https://pypi.org/project/importlib_metadata
|
||||
|
||||
.. image:: https://github.com/python/importlib_metadata/workflows/Automated%20Tests/badge.svg
|
||||
:target: https://github.com/python/importlib_metadata/actions?query=workflow%3A%22Automated+Tests%22
|
||||
:alt: Automated Tests
|
||||
|
||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||
:target: https://github.com/psf/black
|
||||
:alt: Code style: Black
|
||||
|
||||
.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest
|
||||
:target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest
|
||||
|
||||
|
||||
``importlib_metadata`` is a library to access the metadata for a
|
||||
Python package.
|
||||
|
||||
As of Python 3.8, this functionality has been added to the
|
||||
`Python standard library
|
||||
<https://docs.python.org/3/library/importlib.metadata.html>`_.
|
||||
This package supplies backports of that functionality including
|
||||
improvements added to subsequent Python versions.
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
See the `online documentation <https://importlib_metadata.readthedocs.io/>`_
|
||||
for usage details.
|
||||
|
||||
`Finder authors
|
||||
<https://docs.python.org/3/reference/import.html#finders-and-loaders>`_ can
|
||||
also add support for custom package installers. See the above documentation
|
||||
for details.
|
||||
|
||||
|
||||
Caveats
|
||||
=======
|
||||
|
||||
This project primarily supports third-party packages installed by PyPA
|
||||
tools (or other conforming packages). It does not support:
|
||||
|
||||
- Packages in the stdlib.
|
||||
- Packages installed without metadata.
|
||||
|
||||
Project details
|
||||
===============
|
||||
|
||||
* Project home: https://github.com/python/importlib_metadata
|
||||
* Report bugs at: https://github.com/python/importlib_metadata/issues
|
||||
* Code hosting: https://github.com/python/importlib_metadata
|
||||
* Documentation: https://importlib_metadata.readthedocs.io/
|
||||
|
||||
|
@ -0,0 +1,7 @@
|
||||
importlib_metadata/__init__.py,sha256=QM4Oo096u6JYeokkDUwHgazI_h3o0w9tISPjHtVko_U,19266
|
||||
importlib_metadata/_compat.py,sha256=OS4joET_vaQClxhumw0NWYdS5N3FX1Ii895aZXLpQaA,2028
|
||||
importlib_metadata-3.1.1.dist-info/LICENSE,sha256=wNe6dAchmJ1VvVB8D9oTc-gHHadCuaSBAev36sYEM6U,571
|
||||
importlib_metadata-3.1.1.dist-info/METADATA,sha256=rdblRVlpAdjDcYkqWhn2yVNwrpBqpamdKvxrgA6EWE0,3442
|
||||
importlib_metadata-3.1.1.dist-info/WHEEL,sha256=gm79cMopkncyn0iSnI0vQNiDJ8t9on0H4_iz-CrpXMk,92
|
||||
importlib_metadata-3.1.1.dist-info/top_level.txt,sha256=CO3fD9yylANiXkrMo4qHLV_mqXL2sC5JFKgt1yWAT-A,19
|
||||
importlib_metadata-3.1.1.dist-info/RECORD,,
|
@ -1,5 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.34.2)
|
||||
Generator: bdist_wheel (0.36.0)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
@ -0,0 +1 @@
|
||||
importlib_metadata
|
@ -0,0 +1,631 @@
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import abc
|
||||
import csv
|
||||
import sys
|
||||
import zipp
|
||||
import email
|
||||
import pathlib
|
||||
import operator
|
||||
import functools
|
||||
import itertools
|
||||
import posixpath
|
||||
import collections
|
||||
|
||||
from ._compat import (
|
||||
NullFinder,
|
||||
PyPy_repr,
|
||||
install,
|
||||
)
|
||||
|
||||
from configparser import ConfigParser
|
||||
from contextlib import suppress
|
||||
from importlib import import_module
|
||||
from importlib.abc import MetaPathFinder
|
||||
from itertools import starmap
|
||||
|
||||
|
||||
__all__ = [
|
||||
'Distribution',
|
||||
'DistributionFinder',
|
||||
'PackageNotFoundError',
|
||||
'distribution',
|
||||
'distributions',
|
||||
'entry_points',
|
||||
'files',
|
||||
'metadata',
|
||||
'requires',
|
||||
'version',
|
||||
]
|
||||
|
||||
|
||||
class PackageNotFoundError(ModuleNotFoundError):
|
||||
"""The package was not found."""
|
||||
|
||||
def __str__(self):
|
||||
tmpl = "No package metadata was found for {self.name}"
|
||||
return tmpl.format(**locals())
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
(name,) = self.args
|
||||
return name
|
||||
|
||||
|
||||
class EntryPoint(
|
||||
PyPy_repr, collections.namedtuple('EntryPointBase', 'name value group')
|
||||
):
|
||||
"""An entry point as defined by Python packaging conventions.
|
||||
|
||||
See `the packaging docs on entry points
|
||||
<https://packaging.python.org/specifications/entry-points/>`_
|
||||
for more information.
|
||||
"""
|
||||
|
||||
pattern = re.compile(
|
||||
r'(?P<module>[\w.]+)\s*'
|
||||
r'(:\s*(?P<attr>[\w.]+))?\s*'
|
||||
r'(?P<extras>\[.*\])?\s*$'
|
||||
)
|
||||
"""
|
||||
A regular expression describing the syntax for an entry point,
|
||||
which might look like:
|
||||
|
||||
- module
|
||||
- package.module
|
||||
- package.module:attribute
|
||||
- package.module:object.attribute
|
||||
- package.module:attr [extra1, extra2]
|
||||
|
||||
Other combinations are possible as well.
|
||||
|
||||
The expression is lenient about whitespace around the ':',
|
||||
following the attr, and following any extras.
|
||||
"""
|
||||
|
||||
def load(self):
|
||||
"""Load the entry point from its definition. If only a module
|
||||
is indicated by the value, return that module. Otherwise,
|
||||
return the named object.
|
||||
"""
|
||||
match = self.pattern.match(self.value)
|
||||
module = import_module(match.group('module'))
|
||||
attrs = filter(None, (match.group('attr') or '').split('.'))
|
||||
return functools.reduce(getattr, attrs, module)
|
||||
|
||||
@property
|
||||
def module(self):
|
||||
match = self.pattern.match(self.value)
|
||||
return match.group('module')
|
||||
|
||||
@property
|
||||
def attr(self):
|
||||
match = self.pattern.match(self.value)
|
||||
return match.group('attr')
|
||||
|
||||
@property
|
||||
def extras(self):
|
||||
match = self.pattern.match(self.value)
|
||||
return list(re.finditer(r'\w+', match.group('extras') or ''))
|
||||
|
||||
@classmethod
|
||||
def _from_config(cls, config):
|
||||
return [
|
||||
cls(name, value, group)
|
||||
for group in config.sections()
|
||||
for name, value in config.items(group)
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def _from_text(cls, text):
|
||||
config = ConfigParser(delimiters='=')
|
||||
# case sensitive: https://stackoverflow.com/q/1611799/812183
|
||||
config.optionxform = str
|
||||
try:
|
||||
config.read_string(text)
|
||||
except AttributeError: # pragma: nocover
|
||||
# Python 2 has no read_string
|
||||
config.readfp(io.StringIO(text))
|
||||
return EntryPoint._from_config(config)
|
||||
|
||||
def __iter__(self):
|
||||
"""
|
||||
Supply iter so one may construct dicts of EntryPoints easily.
|
||||
"""
|
||||
return iter((self.name, self))
|
||||
|
||||
def __reduce__(self):
|
||||
return (
|
||||
self.__class__,
|
||||
(self.name, self.value, self.group),
|
||||
)
|
||||
|
||||
|
||||
class PackagePath(pathlib.PurePosixPath):
|
||||
"""A reference to a path in a package"""
|
||||
|
||||
def read_text(self, encoding='utf-8'):
|
||||
with self.locate().open(encoding=encoding) as stream:
|
||||
return stream.read()
|
||||
|
||||
def read_binary(self):
|
||||
with self.locate().open('rb') as stream:
|
||||
return stream.read()
|
||||
|
||||
def locate(self):
|
||||
"""Return a path-like object for this path"""
|
||||
return self.dist.locate_file(self)
|
||||
|
||||
|
||||
class FileHash:
|
||||
def __init__(self, spec):
|
||||
self.mode, _, self.value = spec.partition('=')
|
||||
|
||||
def __repr__(self):
|
||||
return '<FileHash mode: {} value: {}>'.format(self.mode, self.value)
|
||||
|
||||
|
||||
class Distribution:
|
||||
"""A Python distribution package."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def read_text(self, filename):
|
||||
"""Attempt to load metadata file given by the name.
|
||||
|
||||
:param filename: The name of the file in the distribution info.
|
||||
:return: The text if found, otherwise None.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def locate_file(self, path):
|
||||
"""
|
||||
Given a path to a file in this distribution, return a path
|
||||
to it.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_name(cls, name):
|
||||
"""Return the Distribution for the given package name.
|
||||
|
||||
:param name: The name of the distribution package to search for.
|
||||
:return: The Distribution instance (or subclass thereof) for the named
|
||||
package, if found.
|
||||
:raises PackageNotFoundError: When the named package's distribution
|
||||
metadata cannot be found.
|
||||
"""
|
||||
for resolver in cls._discover_resolvers():
|
||||
dists = resolver(DistributionFinder.Context(name=name))
|
||||
dist = next(iter(dists), None)
|
||||
if dist is not None:
|
||||
return dist
|
||||
else:
|
||||
raise PackageNotFoundError(name)
|
||||
|
||||
@classmethod
|
||||
def discover(cls, **kwargs):
|
||||
"""Return an iterable of Distribution objects for all packages.
|
||||
|
||||
Pass a ``context`` or pass keyword arguments for constructing
|
||||
a context.
|
||||
|
||||
:context: A ``DistributionFinder.Context`` object.
|
||||
:return: Iterable of Distribution objects for all packages.
|
||||
"""
|
||||
context = kwargs.pop('context', None)
|
||||
if context and kwargs:
|
||||
raise ValueError("cannot accept context and kwargs")
|
||||
context = context or DistributionFinder.Context(**kwargs)
|
||||
return itertools.chain.from_iterable(
|
||||
resolver(context) for resolver in cls._discover_resolvers()
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def at(path):
|
||||
"""Return a Distribution for the indicated metadata path
|
||||
|
||||
:param path: a string or path-like object
|
||||
:return: a concrete Distribution instance for the path
|
||||
"""
|
||||
return PathDistribution(pathlib.Path(path))
|
||||
|
||||
@staticmethod
|
||||
def _discover_resolvers():
|
||||
"""Search the meta_path for resolvers."""
|
||||
declared = (
|
||||
getattr(finder, 'find_distributions', None) for finder in sys.meta_path
|
||||
)
|
||||
return filter(None, declared)
|
||||
|
||||
@classmethod
|
||||
def _local(cls, root='.'):
|
||||
from pep517 import build, meta
|
||||
|
||||
system = build.compat_system(root)
|
||||
builder = functools.partial(
|
||||
meta.build,
|
||||
source_dir=root,
|
||||
system=system,
|
||||
)
|
||||
return PathDistribution(zipp.Path(meta.build_as_zip(builder)))
|
||||
|
||||
@property
|
||||
def metadata(self):
|
||||
"""Return the parsed metadata for this Distribution.
|
||||
|
||||
The returned object will have keys that name the various bits of
|
||||
metadata. See PEP 566 for details.
|
||||
"""
|
||||
text = (
|
||||
self.read_text('METADATA')
|
||||
or self.read_text('PKG-INFO')
|
||||
# This last clause is here to support old egg-info files. Its
|
||||
# effect is to just end up using the PathDistribution's self._path
|
||||
# (which points to the egg-info file) attribute unchanged.
|
||||
or self.read_text('')
|
||||
)
|
||||
return email.message_from_string(text)
|
||||
|
||||
@property
|
||||
def version(self):
|
||||
"""Return the 'Version' metadata for the distribution package."""
|
||||
return self.metadata['Version']
|
||||
|
||||
@property
|
||||
def entry_points(self):
|
||||
return EntryPoint._from_text(self.read_text('entry_points.txt'))
|
||||
|
||||
@property
|
||||
def files(self):
|
||||
"""Files in this distribution.
|
||||
|
||||
:return: List of PackagePath for this distribution or None
|
||||
|
||||
Result is `None` if the metadata file that enumerates files
|
||||
(i.e. RECORD for dist-info or SOURCES.txt for egg-info) is
|
||||
missing.
|
||||
Result may be empty if the metadata exists but is empty.
|
||||
"""
|
||||
file_lines = self._read_files_distinfo() or self._read_files_egginfo()
|
||||
|
||||
def make_file(name, hash=None, size_str=None):
|
||||
result = PackagePath(name)
|
||||
result.hash = FileHash(hash) if hash else None
|
||||
result.size = int(size_str) if size_str else None
|
||||
result.dist = self
|
||||
return result
|
||||
|
||||
return file_lines and list(starmap(make_file, csv.reader(file_lines)))
|
||||
|
||||
def _read_files_distinfo(self):
|
||||
"""
|
||||
Read the lines of RECORD
|
||||
"""
|
||||
text = self.read_text('RECORD')
|
||||
return text and text.splitlines()
|
||||
|
||||
def _read_files_egginfo(self):
|
||||
"""
|
||||
SOURCES.txt might contain literal commas, so wrap each line
|
||||
in quotes.
|
||||
"""
|
||||
text = self.read_text('SOURCES.txt')
|
||||
return text and map('"{}"'.format, text.splitlines())
|
||||
|
||||
@property
|
||||
def requires(self):
|
||||
"""Generated requirements specified for this Distribution"""
|
||||
reqs = self._read_dist_info_reqs() or self._read_egg_info_reqs()
|
||||
return reqs and list(reqs)
|
||||
|
||||
def _read_dist_info_reqs(self):
|
||||
return self.metadata.get_all('Requires-Dist')
|
||||
|
||||
def _read_egg_info_reqs(self):
|
||||
source = self.read_text('requires.txt')
|
||||
return source and self._deps_from_requires_text(source)
|
||||
|
||||
@classmethod
|
||||
def _deps_from_requires_text(cls, source):
|
||||
section_pairs = cls._read_sections(source.splitlines())
|
||||
sections = {
|
||||
section: list(map(operator.itemgetter('line'), results))
|
||||
for section, results in itertools.groupby(
|
||||
section_pairs, operator.itemgetter('section')
|
||||
)
|
||||
}
|
||||
return cls._convert_egg_info_reqs_to_simple_reqs(sections)
|
||||
|
||||
@staticmethod
|
||||
def _read_sections(lines):
|
||||
section = None
|
||||
for line in filter(None, lines):
|
||||
section_match = re.match(r'\[(.*)\]$', line)
|
||||
if section_match:
|
||||
section = section_match.group(1)
|
||||
continue
|
||||
yield locals()
|
||||
|
||||
@staticmethod
|
||||
def _convert_egg_info_reqs_to_simple_reqs(sections):
|
||||
"""
|
||||
Historically, setuptools would solicit and store 'extra'
|
||||
requirements, including those with environment markers,
|
||||
in separate sections. More modern tools expect each
|
||||
dependency to be defined separately, with any relevant
|
||||
extras and environment markers attached directly to that
|
||||
requirement. This method converts the former to the
|
||||
latter. See _test_deps_from_requires_text for an example.
|
||||
"""
|
||||
|
||||
def make_condition(name):
|
||||
return name and 'extra == "{name}"'.format(name=name)
|
||||
|
||||
def parse_condition(section):
|
||||
section = section or ''
|
||||
extra, sep, markers = section.partition(':')
|
||||
if extra and markers:
|
||||
markers = '({markers})'.format(markers=markers)
|
||||
conditions = list(filter(None, [markers, make_condition(extra)]))
|
||||
return '; ' + ' and '.join(conditions) if conditions else ''
|
||||
|
||||
for section, deps in sections.items():
|
||||
for dep in deps:
|
||||
yield dep + parse_condition(section)
|
||||
|
||||
|
||||
class DistributionFinder(MetaPathFinder):
|
||||
"""
|
||||
A MetaPathFinder capable of discovering installed distributions.
|
||||
"""
|
||||
|
||||
class Context:
|
||||
"""
|
||||
Keyword arguments presented by the caller to
|
||||
``distributions()`` or ``Distribution.discover()``
|
||||
to narrow the scope of a search for distributions
|
||||
in all DistributionFinders.
|
||||
|
||||
Each DistributionFinder may expect any parameters
|
||||
and should attempt to honor the canonical
|
||||
parameters defined below when appropriate.
|
||||
"""
|
||||
|
||||
name = None
|
||||
"""
|
||||
Specific name for which a distribution finder should match.
|
||||
A name of ``None`` matches all distributions.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
vars(self).update(kwargs)
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
"""
|
||||
The path that a distribution finder should search.
|
||||
|
||||
Typically refers to Python package paths and defaults
|
||||
to ``sys.path``.
|
||||
"""
|
||||
return vars(self).get('path', sys.path)
|
||||
|
||||
@abc.abstractmethod
|
||||
def find_distributions(self, context=Context()):
|
||||
"""
|
||||
Find distributions.
|
||||
|
||||
Return an iterable of all Distribution instances capable of
|
||||
loading the metadata for packages matching the ``context``,
|
||||
a DistributionFinder.Context instance.
|
||||
"""
|
||||
|
||||
|
||||
class FastPath:
|
||||
"""
|
||||
Micro-optimized class for searching a path for
|
||||
children.
|
||||
"""
|
||||
|
||||
def __init__(self, root):
|
||||
self.root = str(root)
|
||||
self.base = os.path.basename(self.root).lower()
|
||||
|
||||
def joinpath(self, child):
|
||||
return pathlib.Path(self.root, child)
|
||||
|
||||
def children(self):
|
||||
with suppress(Exception):
|
||||
return os.listdir(self.root or '')
|
||||
with suppress(Exception):
|
||||
return self.zip_children()
|
||||
return []
|
||||
|
||||
def zip_children(self):
|
||||
zip_path = zipp.Path(self.root)
|
||||
names = zip_path.root.namelist()
|
||||
self.joinpath = zip_path.joinpath
|
||||
|
||||
return dict.fromkeys(child.split(posixpath.sep, 1)[0] for child in names)
|
||||
|
||||
def search(self, name):
|
||||
return (
|
||||
self.joinpath(child)
|
||||
for child in self.children()
|
||||
if name.matches(child, self.base)
|
||||
)
|
||||
|
||||
|
||||
class Prepared:
|
||||
"""
|
||||
A prepared search for metadata on a possibly-named package.
|
||||
"""
|
||||
|
||||
normalized = None
|
||||
suffixes = '.dist-info', '.egg-info'
|
||||
exact_matches = [''][:0]
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
if name is None:
|
||||
return
|
||||
self.normalized = self.normalize(name)
|
||||
self.exact_matches = [self.normalized + suffix for suffix in self.suffixes]
|
||||
|
||||
@staticmethod
|
||||
def normalize(name):
|
||||
"""
|
||||
PEP 503 normalization plus dashes as underscores.
|
||||
"""
|
||||
return re.sub(r"[-_.]+", "-", name).lower().replace('-', '_')
|
||||
|
||||
@staticmethod
|
||||
def legacy_normalize(name):
|
||||
"""
|
||||
Normalize the package name as found in the convention in
|
||||
older packaging tools versions and specs.
|
||||
"""
|
||||
return name.lower().replace('-', '_')
|
||||
|
||||
def matches(self, cand, base):
|
||||
low = cand.lower()
|
||||
pre, ext = os.path.splitext(low)
|
||||
name, sep, rest = pre.partition('-')
|
||||
return (
|
||||
low in self.exact_matches
|
||||
or ext in self.suffixes
|
||||
and (not self.normalized or name.replace('.', '_') == self.normalized)
|
||||
# legacy case:
|
||||
or self.is_egg(base)
|
||||
and low == 'egg-info'
|
||||
)
|
||||
|
||||
def is_egg(self, base):
|
||||
normalized = self.legacy_normalize(self.name or '')
|
||||
prefix = normalized + '-' if normalized else ''
|
||||
versionless_egg_name = normalized + '.egg' if self.name else ''
|
||||
return (
|
||||
base == versionless_egg_name
|
||||
or base.startswith(prefix)
|
||||
and base.endswith('.egg')
|
||||
)
|
||||
|
||||
|
||||
@install
|
||||
class MetadataPathFinder(NullFinder, DistributionFinder):
|
||||
"""A degenerate finder for distribution packages on the file system.
|
||||
|
||||
This finder supplies only a find_distributions() method for versions
|
||||
of Python that do not have a PathFinder find_distributions().
|
||||
"""
|
||||
|
||||
def find_distributions(self, context=DistributionFinder.Context()):
|
||||
"""
|
||||
Find distributions.
|
||||
|
||||
Return an iterable of all Distribution instances capable of
|
||||
loading the metadata for packages matching ``context.name``
|
||||
(or all names if ``None`` indicated) along the paths in the list
|
||||
of directories ``context.path``.
|
||||
"""
|
||||
found = self._search_paths(context.name, context.path)
|
||||
return map(PathDistribution, found)
|
||||
|
||||
@classmethod
|
||||
def _search_paths(cls, name, paths):
|
||||
"""Find metadata directories in paths heuristically."""
|
||||
return itertools.chain.from_iterable(
|
||||
path.search(Prepared(name)) for path in map(FastPath, paths)
|
||||
)
|
||||
|
||||
|
||||
class PathDistribution(Distribution):
|
||||
def __init__(self, path):
|
||||
"""Construct a distribution from a path to the metadata directory.
|
||||
|
||||
:param path: A pathlib.Path or similar object supporting
|
||||
.joinpath(), __div__, .parent, and .read_text().
|
||||
"""
|
||||
self._path = path
|
||||
|
||||
def read_text(self, filename):
|
||||
with suppress(
|
||||
FileNotFoundError,
|
||||
IsADirectoryError,
|
||||
KeyError,
|
||||
NotADirectoryError,
|
||||
PermissionError,
|
||||
):
|
||||
return self._path.joinpath(filename).read_text(encoding='utf-8')
|
||||
|
||||
read_text.__doc__ = Distribution.read_text.__doc__
|
||||
|
||||
def locate_file(self, path):
|
||||
return self._path.parent / path
|
||||
|
||||
|
||||
def distribution(distribution_name):
|
||||
"""Get the ``Distribution`` instance for the named package.
|
||||
|
||||
:param distribution_name: The name of the distribution package as a string.
|
||||
:return: A ``Distribution`` instance (or subclass thereof).
|
||||
"""
|
||||
return Distribution.from_name(distribution_name)
|
||||
|
||||
|
||||
def distributions(**kwargs):
|
||||
"""Get all ``Distribution`` instances in the current environment.
|
||||
|
||||
:return: An iterable of ``Distribution`` instances.
|
||||
"""
|
||||
return Distribution.discover(**kwargs)
|
||||
|
||||
|
||||
def metadata(distribution_name):
|
||||
"""Get the metadata for the named package.
|
||||
|
||||
:param distribution_name: The name of the distribution package to query.
|
||||
:return: An email.Message containing the parsed metadata.
|
||||
"""
|
||||
return Distribution.from_name(distribution_name).metadata
|
||||
|
||||
|
||||
def version(distribution_name):
|
||||
"""Get the version string for the named package.
|
||||
|
||||
:param distribution_name: The name of the distribution package to query.
|
||||
:return: The version string for the package as defined in the package's
|
||||
"Version" metadata key.
|
||||
"""
|
||||
return distribution(distribution_name).version
|
||||
|
||||
|
||||
def entry_points():
|
||||
"""Return EntryPoint objects for all installed packages.
|
||||
|
||||
:return: EntryPoint objects for all installed packages.
|
||||
"""
|
||||
eps = itertools.chain.from_iterable(dist.entry_points for dist in distributions())
|
||||
by_group = operator.attrgetter('group')
|
||||
ordered = sorted(eps, key=by_group)
|
||||
grouped = itertools.groupby(ordered, by_group)
|
||||
return {group: tuple(eps) for group, eps in grouped}
|
||||
|
||||
|
||||
def files(distribution_name):
|
||||
"""Return a list of files for the named package.
|
||||
|
||||
:param distribution_name: The name of the distribution package to query.
|
||||
:return: List of files composing the distribution.
|
||||
"""
|
||||
return distribution(distribution_name).files
|
||||
|
||||
|
||||
def requires(distribution_name):
|
||||
"""
|
||||
Return a list of requirements for the named package.
|
||||
|
||||
:return: An iterator of requirements, suitable for
|
||||
packaging.requirement.Requirement.
|
||||
"""
|
||||
return distribution(distribution_name).requires
|
@ -0,0 +1,75 @@
|
||||
import sys
|
||||
|
||||
|
||||
__all__ = ['install', 'NullFinder', 'PyPy_repr']
|
||||
|
||||
|
||||
def install(cls):
|
||||
"""
|
||||
Class decorator for installation on sys.meta_path.
|
||||
|
||||
Adds the backport DistributionFinder to sys.meta_path and
|
||||
attempts to disable the finder functionality of the stdlib
|
||||
DistributionFinder.
|
||||
"""
|
||||
sys.meta_path.append(cls())
|
||||
disable_stdlib_finder()
|
||||
return cls
|
||||
|
||||
|
||||
def disable_stdlib_finder():
|
||||
"""
|
||||
Give the backport primacy for discovering path-based distributions
|
||||
by monkey-patching the stdlib O_O.
|
||||
|
||||
See #91 for more background for rationale on this sketchy
|
||||
behavior.
|
||||
"""
|
||||
|
||||
def matches(finder):
|
||||
return getattr(
|
||||
finder, '__module__', None
|
||||
) == '_frozen_importlib_external' and hasattr(finder, 'find_distributions')
|
||||
|
||||
for finder in filter(matches, sys.meta_path): # pragma: nocover
|
||||
del finder.find_distributions
|
||||
|
||||
|
||||
class NullFinder:
|
||||
"""
|
||||
A "Finder" (aka "MetaClassFinder") that never finds any modules,
|
||||
but may find distributions.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def find_spec(*args, **kwargs):
|
||||
return None
|
||||
|
||||
# In Python 2, the import system requires finders
|
||||
# to have a find_module() method, but this usage
|
||||
# is deprecated in Python 3 in favor of find_spec().
|
||||
# For the purposes of this finder (i.e. being present
|
||||
# on sys.meta_path but having no other import
|
||||
# system functionality), the two methods are identical.
|
||||
find_module = find_spec
|
||||
|
||||
|
||||
class PyPy_repr:
|
||||
"""
|
||||
Override repr for EntryPoint objects on PyPy to avoid __iter__ access.
|
||||
Ref #97, #102.
|
||||
"""
|
||||
|
||||
affected = hasattr(sys, 'pypy_version_info')
|
||||
|
||||
def __compat_repr__(self): # pragma: nocover
|
||||
def make_param(name):
|
||||
value = getattr(self, name)
|
||||
return '{name}={value!r}'.format(**locals())
|
||||
|
||||
params = ', '.join(map(make_param, self._fields))
|
||||
return 'EntryPoint({params})'.format(**locals())
|
||||
|
||||
if affected: # pragma: nocover
|
||||
__repr__ = __compat_repr__
|
||||
del affected
|
@ -1,41 +0,0 @@
|
||||
from . import abc
|
||||
|
||||
from ._compat import Path, ZipPath
|
||||
|
||||
|
||||
class FileReader(abc.TraversableResources):
|
||||
def __init__(self, loader):
|
||||
self.path = Path(loader.path).parent
|
||||
|
||||
def resource_path(self, resource):
|
||||
"""
|
||||
Return the file system path to prevent
|
||||
`resources.path()` from creating a temporary
|
||||
copy.
|
||||
"""
|
||||
return str(self.path.joinpath(resource))
|
||||
|
||||
def files(self):
|
||||
return self.path
|
||||
|
||||
|
||||
class ZipReader(abc.TraversableResources):
|
||||
def __init__(self, loader, module):
|
||||
_, _, name = module.rpartition('.')
|
||||
prefix = loader.prefix.replace('\\', '/') + name + '/'
|
||||
self.path = ZipPath(loader.archive, prefix)
|
||||
|
||||
def open_resource(self, resource):
|
||||
try:
|
||||
return super().open_resource(resource)
|
||||
except KeyError as exc:
|
||||
raise FileNotFoundError(exc.args[0])
|
||||
|
||||
def is_resource(self, path):
|
||||
# workaround for `zipfile.Path.is_file` returning true
|
||||
# for non-existent paths.
|
||||
target = self.files().joinpath(path)
|
||||
return target.is_file() and target.exists()
|
||||
|
||||
def files(self):
|
||||
return self.path
|
@ -1,11 +1,12 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: importlib-resources
|
||||
Version: 3.0.0
|
||||
Version: 3.2.1
|
||||
Summary: Read resources from Python packages
|
||||
Home-page: http://importlib-resources.readthedocs.io/
|
||||
Home-page: https://github.com/python/importlib_resources
|
||||
Author: Barry Warsaw
|
||||
Author-email: barry@python.org
|
||||
License: UNKNOWN
|
||||
Project-URL: Documentation, https://importlib-resources.readthedocs.io/
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
@ -24,10 +25,6 @@ Requires-Dist: sphinx ; extra == 'docs'
|
||||
Requires-Dist: rst.linker ; extra == 'docs'
|
||||
Requires-Dist: jaraco.packaging ; extra == 'docs'
|
||||
|
||||
=========================
|
||||
``importlib_resources``
|
||||
=========================
|
||||
|
||||
``importlib_resources`` is a backport of Python standard library
|
||||
`importlib.resources
|
||||
<https://docs.python.org/3.9/library/importlib.html#module-importlib.resources>`_
|
||||
@ -42,12 +39,3 @@ reading resources included in packages easier, with more stable and consistent
|
||||
semantics.
|
||||
|
||||
|
||||
Project details
|
||||
===============
|
||||
|
||||
* Project home: https://gitlab.com/python-devs/importlib_resources
|
||||
* Report bugs at: https://gitlab.com/python-devs/importlib_resources/issues
|
||||
* Code hosting: https://gitlab.com/python-devs/importlib_resources.git
|
||||
* Documentation: https://importlib-resources.readthedocs.io/
|
||||
|
||||
|
@ -1,19 +1,22 @@
|
||||
importlib_resources/__init__.py,sha256=hswDmLAH0IUlLWwmdHXPN2mgus2bk5IwDP-BFzg7VKo,977
|
||||
importlib_resources/_common.py,sha256=jXVqgKZ1bt8IbZiErvjIeb69BjqsMSCSt9AwV4bHnE8,3157
|
||||
importlib_resources/_compat.py,sha256=5nvS1tAZIl_6VqrFSScNVW2wtBGaRXGxcpDXMskruoA,3233
|
||||
importlib_resources/_common.py,sha256=RN8cXOZtlygvlbyTewd-ni9wC1hwXpfbZnrl7kbx0nI,3121
|
||||
importlib_resources/_compat.py,sha256=NDCXOf1097aDJJx-_pQ0UIktzVx2G1aPIQTRFGx0FHI,3694
|
||||
importlib_resources/_py2.py,sha256=G9M5mv1ILl8NARGdNX0v9_F_Hb4HUKCS-FCNK63Ajvw,4146
|
||||
importlib_resources/_py3.py,sha256=2wJYfjLG8nd9mT1HLBtX96m6zlu9-Tocte9wFl9q_bY,5474
|
||||
importlib_resources/_py3.py,sha256=5_FhUUHWFG1c3HcLrmDy65ZFB7EYxmHfOV3ybv4uTHM,5710
|
||||
importlib_resources/abc.py,sha256=6PX4Nprv39YnAht3NymhHIuSso0ocAKqDJZf-A6BgIw,3894
|
||||
importlib_resources/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/readers.py,sha256=S0DsGQB1li6w5USiZQtiy-5HXe4UAxt-zmKo8QlAxsI,1155
|
||||
importlib_resources/readers.py,sha256=fGuSBoMeeERUVrscN9Grhp0s-wKMy7nMVbCx92vIlGs,3674
|
||||
importlib_resources/trees.py,sha256=U3FlQSI5--eF4AdzOjBvW4xnjL21OFX8ivk82Quwv_M,117
|
||||
importlib_resources/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/_compat.py,sha256=geKWJe8UGXjC181JxmtxR3A_o5VrR4yxolS0xbnxMlw,801
|
||||
importlib_resources/tests/py27compat.py,sha256=9lDJkGV2swPVQJg6isOorRNFWuP6KeoWd4D2bFNmzLI,965
|
||||
importlib_resources/tests/test_files.py,sha256=91rf4C74_aJsKNSt-a-03slVpY9QSAuCbogFWnsaPjE,1017
|
||||
importlib_resources/tests/test_open.py,sha256=yDXmTGXQspByj6WU0prnoVwab1yWWEA3fwz_XIx7TQU,2288
|
||||
importlib_resources/tests/test_open.py,sha256=pIYWvuTDpQOJKX0SEuOKGotssZcEeY_xNPDqLGCvP_U,2565
|
||||
importlib_resources/tests/test_path.py,sha256=GnUOu-338o9offnC8xwbXjH9JIQJpD7JujgQkGB106Q,1548
|
||||
importlib_resources/tests/test_read.py,sha256=DpA7tzxSQlU0_YQuWibB3E5PDL9fQUdzeKoEUGnAx78,2046
|
||||
importlib_resources/tests/test_resource.py,sha256=X77DzU2BRoM6d59iEh74zDHHw3pKOBGLCg3lP3dH4BI,6467
|
||||
importlib_resources/tests/util.py,sha256=f0RZU-RkEkybJjXRd7C5HcWMsoLFRWJL4FIUF1CJ2wo,6980
|
||||
importlib_resources/tests/test_reader.py,sha256=yEO0xyrYDcGRmsBC6A1n99GXiTZpVvp-uGA313s6aao,4638
|
||||
importlib_resources/tests/test_resource.py,sha256=GbrMeHJ74N6KJG38TDodCp--nsRnFHXJc7NrAEqUPaU,8766
|
||||
importlib_resources/tests/util.py,sha256=8hBFwqIZRJFNvkboEB7aWsCqTtgUjlWI_iQ0KV158Yk,5914
|
||||
importlib_resources/tests/data01/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data01/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4
|
||||
importlib_resources/tests/data01/utf-16.file,sha256=t5q9qhxX0rYqItBOM8D3ylwG-RHrnOYteTLtQr6sF7g,44
|
||||
@ -25,16 +28,15 @@ importlib_resources/tests/data02/one/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeu
|
||||
importlib_resources/tests/data02/one/resource1.txt,sha256=10flKac7c-XXFzJ3t-AB5MJjlBy__dSZvPE_dOm2q6U,13
|
||||
importlib_resources/tests/data02/two/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data02/two/resource2.txt,sha256=lt2jbN3TMn9QiFKM832X39bU_62UptDdUkoYzkvEbl0,13
|
||||
importlib_resources/tests/data03/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data03/namespace/resource1.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data03/namespace/portion1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data03/namespace/portion2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/namespacedata01/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4
|
||||
importlib_resources/tests/namespacedata01/utf-16.file,sha256=t5q9qhxX0rYqItBOM8D3ylwG-RHrnOYteTLtQr6sF7g,44
|
||||
importlib_resources/tests/namespacedata01/utf-8.file,sha256=kwWgYG4yQ-ZF2X_WA66EjYPmxJRn-w8aSOiS9e8tKYY,20
|
||||
importlib_resources/tests/zipdata01/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/zipdata01/ziptestdata.zip,sha256=AYf51fj80OKCRis93v2DlZjt5rM-VQOPptSHJbFtkXw,1131
|
||||
importlib_resources/tests/zipdata02/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/zipdata02/ziptestdata.zip,sha256=e6HXvTEObXvJcNxyX5I8tu5M8_6mSN8ALahHfqE7ADA,698
|
||||
importlib_resources-3.0.0.dist-info/LICENSE,sha256=uWRjFdYGataJX2ziXk048ItUglQmjng3GWBALaWA36U,568
|
||||
importlib_resources-3.0.0.dist-info/METADATA,sha256=BIalQpWJG-Av5ZUNQXdFsv6M8s8EdYiymu6GaoEL1Rk,2100
|
||||
importlib_resources-3.0.0.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110
|
||||
importlib_resources-3.0.0.dist-info/top_level.txt,sha256=fHIjHU1GZwAjvcydpmUnUrTnbvdiWjG4OEVZK8by0TQ,20
|
||||
importlib_resources-3.0.0.dist-info/RECORD,,
|
||||
importlib_resources-3.2.1.dist-info/LICENSE,sha256=uWRjFdYGataJX2ziXk048ItUglQmjng3GWBALaWA36U,568
|
||||
importlib_resources-3.2.1.dist-info/METADATA,sha256=d_tMNLHsZ_lPU-wq04MWr0yEfpwbNFKgfO_CU5GCC9g,1783
|
||||
importlib_resources-3.2.1.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110
|
||||
importlib_resources-3.2.1.dist-info/top_level.txt,sha256=fHIjHU1GZwAjvcydpmUnUrTnbvdiWjG4OEVZK8by0TQ,20
|
||||
importlib_resources-3.2.1.dist-info/RECORD,,
|
@ -1,5 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.34.2)
|
||||
Generator: bdist_wheel (0.35.1)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
@ -93,6 +93,7 @@ def _tempfile(reader, suffix=''):
|
||||
try:
|
||||
os.write(fd, reader())
|
||||
os.close(fd)
|
||||
del reader
|
||||
yield Path(raw_path)
|
||||
finally:
|
||||
try:
|
||||
@ -102,14 +103,12 @@ def _tempfile(reader, suffix=''):
|
||||
|
||||
|
||||
@singledispatch
|
||||
@contextlib.contextmanager
|
||||
def as_file(path):
|
||||
"""
|
||||
Given a Traversable object, return that object as a
|
||||
path on the local file system in a context manager.
|
||||
"""
|
||||
with _tempfile(path.read_bytes, suffix=path.name) as local:
|
||||
yield local
|
||||
return _tempfile(path.read_bytes, suffix=path.name)
|
||||
|
||||
|
||||
@as_file.register(Path)
|
@ -36,6 +36,12 @@ except NameError:
|
||||
FileNotFoundError = OSError # type: ignore
|
||||
|
||||
|
||||
try:
|
||||
NotADirectoryError = NotADirectoryError # type: ignore
|
||||
except NameError:
|
||||
NotADirectoryError = OSError # type: ignore
|
||||
|
||||
|
||||
try:
|
||||
from zipfile import Path as ZipPath # type: ignore
|
||||
except ImportError:
|
||||
@ -93,6 +99,10 @@ class LoaderAdapter:
|
||||
with suppress(AttributeError):
|
||||
return readers.ZipReader(spec.loader, spec.name)
|
||||
|
||||
def _namespace_reader(spec):
|
||||
with suppress(AttributeError, ValueError):
|
||||
return readers.NamespaceReader(spec.submodule_search_locations)
|
||||
|
||||
def _available_reader(spec):
|
||||
with suppress(AttributeError):
|
||||
return spec.loader.get_resource_reader(spec.name)
|
||||
@ -106,6 +116,8 @@ class LoaderAdapter:
|
||||
_native_reader(self.spec) or
|
||||
# local ZipReader if a zip module
|
||||
_zip_reader(self.spec) or
|
||||
# local NamespaceReader if a namespace module
|
||||
_namespace_reader(self.spec) or
|
||||
# local FileReader
|
||||
readers.FileReader(self)
|
||||
)
|
@ -1,8 +1,9 @@
|
||||
import os
|
||||
import sys
|
||||
import io
|
||||
|
||||
from . import _common
|
||||
from contextlib import contextmanager, suppress
|
||||
from contextlib import suppress
|
||||
from importlib.abc import ResourceLoader
|
||||
from io import BytesIO, TextIOWrapper
|
||||
from pathlib import Path
|
||||
@ -10,6 +11,8 @@ from types import ModuleType
|
||||
from typing import Iterable, Iterator, Optional, Set, Union # noqa: F401
|
||||
from typing import cast
|
||||
from typing.io import BinaryIO, TextIO
|
||||
from collections.abc import Sequence
|
||||
from ._compat import singledispatch
|
||||
|
||||
if False: # TYPE_CHECKING
|
||||
from typing import ContextManager
|
||||
@ -30,27 +33,29 @@ def open_binary(package: Package, resource: Resource) -> BinaryIO:
|
||||
return reader.open_resource(resource)
|
||||
# Using pathlib doesn't work well here due to the lack of 'strict'
|
||||
# argument for pathlib.Path.resolve() prior to Python 3.6.
|
||||
absolute_package_path = os.path.abspath(
|
||||
package.__spec__.origin or 'non-existent file')
|
||||
package_path = os.path.dirname(absolute_package_path)
|
||||
full_path = os.path.join(package_path, resource)
|
||||
try:
|
||||
return open(full_path, mode='rb')
|
||||
except OSError:
|
||||
# Just assume the loader is a resource loader; all the relevant
|
||||
# importlib.machinery loaders are and an AttributeError for
|
||||
# get_data() will make it clear what is needed from the loader.
|
||||
loader = cast(ResourceLoader, package.__spec__.loader)
|
||||
data = None
|
||||
if hasattr(package.__spec__.loader, 'get_data'):
|
||||
with suppress(OSError):
|
||||
data = loader.get_data(full_path)
|
||||
if data is None:
|
||||
package_name = package.__spec__.name
|
||||
message = '{!r} resource not found in {!r}'.format(
|
||||
resource, package_name)
|
||||
raise FileNotFoundError(message)
|
||||
return BytesIO(data)
|
||||
if package.__spec__.submodule_search_locations is not None:
|
||||
paths = package.__spec__.submodule_search_locations
|
||||
elif package.__spec__.origin is not None:
|
||||
paths = [os.path.dirname(os.path.abspath(package.__spec__.origin))]
|
||||
|
||||
for package_path in paths:
|
||||
full_path = os.path.join(package_path, resource)
|
||||
try:
|
||||
return open(full_path, mode='rb')
|
||||
except OSError:
|
||||
# Just assume the loader is a resource loader; all the relevant
|
||||
# importlib.machinery loaders are and an AttributeError for
|
||||
# get_data() will make it clear what is needed from the loader.
|
||||
loader = cast(ResourceLoader, package.__spec__.loader)
|
||||
data = None
|
||||
if hasattr(package.__spec__.loader, 'get_data'):
|
||||
with suppress(OSError):
|
||||
data = loader.get_data(full_path)
|
||||
if data is not None:
|
||||
return BytesIO(data)
|
||||
|
||||
raise FileNotFoundError('{!r} resource not found in {!r}'.format(
|
||||
resource, package.__spec__.name))
|
||||
|
||||
|
||||
def open_text(package: Package,
|
||||
@ -94,22 +99,26 @@ def path(
|
||||
"""
|
||||
reader = _common.get_resource_reader(_common.get_package(package))
|
||||
return (
|
||||
_path_from_reader(reader, resource)
|
||||
_path_from_reader(reader, _common.normalize_path(resource))
|
||||
if reader else
|
||||
_common.as_file(
|
||||
_common.files(package).joinpath(_common.normalize_path(resource)))
|
||||
)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def _path_from_reader(reader, resource):
|
||||
norm_resource = _common.normalize_path(resource)
|
||||
return _path_from_resource_path(reader, resource) or \
|
||||
_path_from_open_resource(reader, resource)
|
||||
|
||||
|
||||
def _path_from_resource_path(reader, resource):
|
||||
with suppress(FileNotFoundError):
|
||||
yield Path(reader.resource_path(norm_resource))
|
||||
return
|
||||
opener_reader = reader.open_resource(norm_resource)
|
||||
with _common._tempfile(opener_reader.read, suffix=norm_resource) as res:
|
||||
yield res
|
||||
return Path(reader.resource_path(resource))
|
||||
|
||||
|
||||
def _path_from_open_resource(reader, resource):
|
||||
saved = io.BytesIO(reader.open_resource(resource).read())
|
||||
return _common._tempfile(saved.read, suffix=resource)
|
||||
|
||||
|
||||
def is_resource(package: Package, name: str) -> bool:
|
||||
@ -138,13 +147,18 @@ def contents(package: Package) -> Iterable[str]:
|
||||
package = _common.get_package(package)
|
||||
reader = _common.get_resource_reader(package)
|
||||
if reader is not None:
|
||||
return reader.contents()
|
||||
# Is the package a namespace package? By definition, namespace packages
|
||||
# cannot have resources.
|
||||
namespace = (
|
||||
package.__spec__.origin is None or
|
||||
package.__spec__.origin == 'namespace'
|
||||
)
|
||||
if namespace or not package.__spec__.has_location:
|
||||
return ()
|
||||
return list(item.name for item in _common.from_package(package).iterdir())
|
||||
return _ensure_sequence(reader.contents())
|
||||
transversable = _common.from_package(package)
|
||||
if transversable.is_dir():
|
||||
return list(item.name for item in transversable.iterdir())
|
||||
return []
|
||||
|
||||
|
||||
@singledispatch
|
||||
def _ensure_sequence(iterable):
|
||||
return list(iterable)
|
||||
|
||||
|
||||
@_ensure_sequence.register(Sequence)
|
||||
def _(iterable):
|
||||
return iterable
|
@ -0,0 +1,123 @@
|
||||
import os.path
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from . import abc
|
||||
|
||||
from ._compat import Path, ZipPath
|
||||
from ._compat import FileNotFoundError, NotADirectoryError
|
||||
|
||||
|
||||
class FileReader(abc.TraversableResources):
|
||||
def __init__(self, loader):
|
||||
self.path = Path(loader.path).parent
|
||||
|
||||
def resource_path(self, resource):
|
||||
"""
|
||||
Return the file system path to prevent
|
||||
`resources.path()` from creating a temporary
|
||||
copy.
|
||||
"""
|
||||
return str(self.path.joinpath(resource))
|
||||
|
||||
def files(self):
|
||||
return self.path
|
||||
|
||||
|
||||
class ZipReader(abc.TraversableResources):
|
||||
def __init__(self, loader, module):
|
||||
_, _, name = module.rpartition('.')
|
||||
self.prefix = loader.prefix.replace('\\', '/') + name + '/'
|
||||
self.archive = loader.archive
|
||||
|
||||
def open_resource(self, resource):
|
||||
try:
|
||||
return super().open_resource(resource)
|
||||
except KeyError as exc:
|
||||
raise FileNotFoundError(exc.args[0])
|
||||
|
||||
def is_resource(self, path):
|
||||
# workaround for `zipfile.Path.is_file` returning true
|
||||
# for non-existent paths.
|
||||
target = self.files().joinpath(path)
|
||||
return target.is_file() and target.exists()
|
||||
|
||||
def files(self):
|
||||
return ZipPath(self.archive, self.prefix)
|
||||
|
||||
|
||||
class MultiplexedPath(abc.Traversable):
|
||||
"""
|
||||
Given a series of Traversable objects, implement a merged
|
||||
version of the interface across all objects. Useful for
|
||||
namespace packages which may be multihomed at a single
|
||||
name.
|
||||
"""
|
||||
def __init__(self, *paths):
|
||||
paths = list(OrderedDict.fromkeys(paths)) # remove duplicates
|
||||
self._paths = list(map(Path, paths))
|
||||
if not self._paths:
|
||||
message = 'MultiplexedPath must contain at least one path'
|
||||
raise FileNotFoundError(message)
|
||||
if any(not path.is_dir() for path in self._paths):
|
||||
raise NotADirectoryError(
|
||||
'MultiplexedPath only supports directories')
|
||||
|
||||
def iterdir(self):
|
||||
visited = []
|
||||
for path in self._paths:
|
||||
for file in path.iterdir():
|
||||
if file.name in visited:
|
||||
continue
|
||||
visited.append(file.name)
|
||||
yield file
|
||||
|
||||
def read_bytes(self):
|
||||
raise FileNotFoundError('{} is not a file'.format(self))
|
||||
|
||||
def read_text(self, *args, **kwargs):
|
||||
raise FileNotFoundError('{} is not a file'.format(self))
|
||||
|
||||
def is_dir(self):
|
||||
return True
|
||||
|
||||
def is_file(self):
|
||||
return False
|
||||
|
||||
def joinpath(self, child):
|
||||
# first try to find child in current paths
|
||||
for file in self.iterdir():
|
||||
if file.name == child:
|
||||
return file
|
||||
# if it does not exist, construct it with the first path
|
||||
return self._paths[0] / child
|
||||
|
||||
__truediv__ = joinpath
|
||||
|
||||
def open(self, *args, **kwargs):
|
||||
raise FileNotFoundError('{} is not a file'.format(self))
|
||||
|
||||
def name(self):
|
||||
return os.path.basename(self._paths[0])
|
||||
|
||||
def __repr__(self):
|
||||
return 'MultiplexedPath({})'.format(
|
||||
', '.join("'{}'".format(path) for path in self._paths))
|
||||
|
||||
|
||||
class NamespaceReader(abc.TraversableResources):
|
||||
def __init__(self, namespace_path):
|
||||
if 'NamespacePath' not in str(namespace_path):
|
||||
raise ValueError('Invalid path')
|
||||
self.path = MultiplexedPath(*list(namespace_path))
|
||||
|
||||
def resource_path(self, resource):
|
||||
"""
|
||||
Return the file system path to prevent
|
||||
`resources.path()` from creating a temporary
|
||||
copy.
|
||||
"""
|
||||
return str(self.path.joinpath(resource))
|
||||
|
||||
def files(self):
|
||||
return self.path
|
@ -0,0 +1,13 @@
|
||||
Copyright 2017-2019 Brett Cannon, Barry Warsaw
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -0,0 +1,41 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: importlib-resources
|
||||
Version: 3.3.0
|
||||
Summary: Read resources from Python packages
|
||||
Home-page: https://github.com/python/importlib_resources
|
||||
Author: Barry Warsaw
|
||||
Author-email: barry@python.org
|
||||
License: UNKNOWN
|
||||
Project-URL: Documentation, https://importlib-resources.readthedocs.io/
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: Apache Software License
|
||||
Classifier: Topic :: Software Development :: Libraries
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7
|
||||
Requires-Dist: pathlib2 ; python_version < "3"
|
||||
Requires-Dist: contextlib2 ; python_version < "3"
|
||||
Requires-Dist: singledispatch ; python_version < "3.4"
|
||||
Requires-Dist: typing ; python_version < "3.5"
|
||||
Requires-Dist: zipp (>=0.4) ; python_version < "3.8"
|
||||
Provides-Extra: docs
|
||||
Requires-Dist: sphinx ; extra == 'docs'
|
||||
Requires-Dist: rst.linker ; extra == 'docs'
|
||||
Requires-Dist: jaraco.packaging ; extra == 'docs'
|
||||
|
||||
``importlib_resources`` is a backport of Python standard library
|
||||
`importlib.resources
|
||||
<https://docs.python.org/3.9/library/importlib.html#module-importlib.resources>`_
|
||||
module for Python 2.7, and 3.4 through 3.8. Users of Python 3.9 and beyond
|
||||
should use the standard library module, since for these versions,
|
||||
``importlib_resources`` just delegates to that module.
|
||||
|
||||
The key goal of this module is to replace parts of `pkg_resources
|
||||
<https://setuptools.readthedocs.io/en/latest/pkg_resources.html>`_ with a
|
||||
solution in Python's stdlib that relies on well-defined APIs. This makes
|
||||
reading resources included in packages easier, with more stable and consistent
|
||||
semantics.
|
||||
|
||||
|
@ -0,0 +1,42 @@
|
||||
importlib_resources/__init__.py,sha256=hswDmLAH0IUlLWwmdHXPN2mgus2bk5IwDP-BFzg7VKo,977
|
||||
importlib_resources/_common.py,sha256=RN8cXOZtlygvlbyTewd-ni9wC1hwXpfbZnrl7kbx0nI,3121
|
||||
importlib_resources/_compat.py,sha256=NDCXOf1097aDJJx-_pQ0UIktzVx2G1aPIQTRFGx0FHI,3694
|
||||
importlib_resources/_py2.py,sha256=G9M5mv1ILl8NARGdNX0v9_F_Hb4HUKCS-FCNK63Ajvw,4146
|
||||
importlib_resources/_py3.py,sha256=Bc-p0UYfPVWXFJ21HLNfVvbVrPJFXBA0g80rqPInkq8,5564
|
||||
importlib_resources/abc.py,sha256=6PX4Nprv39YnAht3NymhHIuSso0ocAKqDJZf-A6BgIw,3894
|
||||
importlib_resources/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/readers.py,sha256=fGuSBoMeeERUVrscN9Grhp0s-wKMy7nMVbCx92vIlGs,3674
|
||||
importlib_resources/trees.py,sha256=U3FlQSI5--eF4AdzOjBvW4xnjL21OFX8ivk82Quwv_M,117
|
||||
importlib_resources/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/_compat.py,sha256=geKWJe8UGXjC181JxmtxR3A_o5VrR4yxolS0xbnxMlw,801
|
||||
importlib_resources/tests/py27compat.py,sha256=9lDJkGV2swPVQJg6isOorRNFWuP6KeoWd4D2bFNmzLI,965
|
||||
importlib_resources/tests/test_files.py,sha256=91rf4C74_aJsKNSt-a-03slVpY9QSAuCbogFWnsaPjE,1017
|
||||
importlib_resources/tests/test_open.py,sha256=pIYWvuTDpQOJKX0SEuOKGotssZcEeY_xNPDqLGCvP_U,2565
|
||||
importlib_resources/tests/test_path.py,sha256=GnUOu-338o9offnC8xwbXjH9JIQJpD7JujgQkGB106Q,1548
|
||||
importlib_resources/tests/test_read.py,sha256=DpA7tzxSQlU0_YQuWibB3E5PDL9fQUdzeKoEUGnAx78,2046
|
||||
importlib_resources/tests/test_reader.py,sha256=yEO0xyrYDcGRmsBC6A1n99GXiTZpVvp-uGA313s6aao,4638
|
||||
importlib_resources/tests/test_resource.py,sha256=GbrMeHJ74N6KJG38TDodCp--nsRnFHXJc7NrAEqUPaU,8766
|
||||
importlib_resources/tests/util.py,sha256=8hBFwqIZRJFNvkboEB7aWsCqTtgUjlWI_iQ0KV158Yk,5914
|
||||
importlib_resources/tests/data01/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data01/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4
|
||||
importlib_resources/tests/data01/utf-16.file,sha256=t5q9qhxX0rYqItBOM8D3ylwG-RHrnOYteTLtQr6sF7g,44
|
||||
importlib_resources/tests/data01/utf-8.file,sha256=kwWgYG4yQ-ZF2X_WA66EjYPmxJRn-w8aSOiS9e8tKYY,20
|
||||
importlib_resources/tests/data01/subdirectory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data01/subdirectory/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4
|
||||
importlib_resources/tests/data02/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data02/one/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data02/one/resource1.txt,sha256=10flKac7c-XXFzJ3t-AB5MJjlBy__dSZvPE_dOm2q6U,13
|
||||
importlib_resources/tests/data02/two/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/data02/two/resource2.txt,sha256=lt2jbN3TMn9QiFKM832X39bU_62UptDdUkoYzkvEbl0,13
|
||||
importlib_resources/tests/namespacedata01/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4
|
||||
importlib_resources/tests/namespacedata01/utf-16.file,sha256=t5q9qhxX0rYqItBOM8D3ylwG-RHrnOYteTLtQr6sF7g,44
|
||||
importlib_resources/tests/namespacedata01/utf-8.file,sha256=kwWgYG4yQ-ZF2X_WA66EjYPmxJRn-w8aSOiS9e8tKYY,20
|
||||
importlib_resources/tests/zipdata01/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/zipdata01/ziptestdata.zip,sha256=AYf51fj80OKCRis93v2DlZjt5rM-VQOPptSHJbFtkXw,1131
|
||||
importlib_resources/tests/zipdata02/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
importlib_resources/tests/zipdata02/ziptestdata.zip,sha256=e6HXvTEObXvJcNxyX5I8tu5M8_6mSN8ALahHfqE7ADA,698
|
||||
importlib_resources-3.3.0.dist-info/LICENSE,sha256=uWRjFdYGataJX2ziXk048ItUglQmjng3GWBALaWA36U,568
|
||||
importlib_resources-3.3.0.dist-info/METADATA,sha256=GxPMbCwUwlCuHNCiPJvP4IC_mTKqP4b_W7UqqNidcF4,1791
|
||||
importlib_resources-3.3.0.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110
|
||||
importlib_resources-3.3.0.dist-info/top_level.txt,sha256=fHIjHU1GZwAjvcydpmUnUrTnbvdiWjG4OEVZK8by0TQ,20
|
||||
importlib_resources-3.3.0.dist-info/RECORD,,
|
@ -1,5 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.34.2)
|
||||
Generator: bdist_wheel (0.35.1)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
@ -0,0 +1 @@
|
||||
importlib_resources
|
@ -0,0 +1,53 @@
|
||||
"""Read resources contained within a package."""
|
||||
|
||||
import sys
|
||||
|
||||
from ._common import (
|
||||
as_file, files,
|
||||
)
|
||||
|
||||
# For compatibility. Ref #88.
|
||||
# Also requires hook-importlib_resources.py (Ref #101).
|
||||
__import__('importlib_resources.trees')
|
||||
|
||||
|
||||
__all__ = [
|
||||
'Package',
|
||||
'Resource',
|
||||
'ResourceReader',
|
||||
'as_file',
|
||||
'contents',
|
||||
'files',
|
||||
'is_resource',
|
||||
'open_binary',
|
||||
'open_text',
|
||||
'path',
|
||||
'read_binary',
|
||||
'read_text',
|
||||
]
|
||||
|
||||
|
||||
if sys.version_info >= (3,):
|
||||
from importlib_resources._py3 import (
|
||||
Package,
|
||||
Resource,
|
||||
contents,
|
||||
is_resource,
|
||||
open_binary,
|
||||
open_text,
|
||||
path,
|
||||
read_binary,
|
||||
read_text,
|
||||
)
|
||||
from importlib_resources.abc import ResourceReader
|
||||
else:
|
||||
from importlib_resources._py2 import (
|
||||
contents,
|
||||
is_resource,
|
||||
open_binary,
|
||||
open_text,
|
||||
path,
|
||||
read_binary,
|
||||
read_text,
|
||||
)
|
||||
del __all__[:3]
|
@ -0,0 +1,120 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
import contextlib
|
||||
import types
|
||||
import importlib
|
||||
|
||||
from ._compat import (
|
||||
Path, FileNotFoundError,
|
||||
singledispatch, package_spec,
|
||||
)
|
||||
|
||||
if False: # TYPE_CHECKING
|
||||
from typing import Union, Any, Optional
|
||||
from .abc import ResourceReader
|
||||
Package = Union[types.ModuleType, str]
|
||||
|
||||
|
||||
def files(package):
|
||||
"""
|
||||
Get a Traversable resource from a package
|
||||
"""
|
||||
return from_package(get_package(package))
|
||||
|
||||
|
||||
def normalize_path(path):
|
||||
# type: (Any) -> str
|
||||
"""Normalize a path by ensuring it is a string.
|
||||
|
||||
If the resulting string contains path separators, an exception is raised.
|
||||
"""
|
||||
str_path = str(path)
|
||||
parent, file_name = os.path.split(str_path)
|
||||
if parent:
|
||||
raise ValueError('{!r} must be only a file name'.format(path))
|
||||
return file_name
|
||||
|
||||
|
||||
def get_resource_reader(package):
|
||||
# type: (types.ModuleType) -> Optional[ResourceReader]
|
||||
"""
|
||||
Return the package's loader if it's a ResourceReader.
|
||||
"""
|
||||
# We can't use
|
||||
# a issubclass() check here because apparently abc.'s __subclasscheck__()
|
||||
# hook wants to create a weak reference to the object, but
|
||||
# zipimport.zipimporter does not support weak references, resulting in a
|
||||
# TypeError. That seems terrible.
|
||||
spec = package.__spec__
|
||||
reader = getattr(spec.loader, 'get_resource_reader', None)
|
||||
if reader is None:
|
||||
return None
|
||||
return reader(spec.name)
|
||||
|
||||
|
||||
def resolve(cand):
|
||||
# type: (Package) -> types.ModuleType
|
||||
return (
|
||||
cand if isinstance(cand, types.ModuleType)
|
||||
else importlib.import_module(cand)
|
||||
)
|
||||
|
||||
|
||||
def get_package(package):
|
||||
# type: (Package) -> types.ModuleType
|
||||
"""Take a package name or module object and return the module.
|
||||
|
||||
Raise an exception if the resolved module is not a package.
|
||||
"""
|
||||
resolved = resolve(package)
|
||||
if package_spec(resolved).submodule_search_locations is None:
|
||||
raise TypeError('{!r} is not a package'.format(package))
|
||||
return resolved
|
||||
|
||||
|
||||
def from_package(package):
|
||||
"""
|
||||
Return a Traversable object for the given package.
|
||||
|
||||
"""
|
||||
spec = package_spec(package)
|
||||
reader = spec.loader.get_resource_reader(spec.name)
|
||||
return reader.files()
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _tempfile(reader, suffix=''):
|
||||
# Not using tempfile.NamedTemporaryFile as it leads to deeper 'try'
|
||||
# blocks due to the need to close the temporary file to work on Windows
|
||||
# properly.
|
||||
fd, raw_path = tempfile.mkstemp(suffix=suffix)
|
||||
try:
|
||||
os.write(fd, reader())
|
||||
os.close(fd)
|
||||
del reader
|
||||
yield Path(raw_path)
|
||||
finally:
|
||||
try:
|
||||
os.remove(raw_path)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
|
||||
@singledispatch
|
||||
def as_file(path):
|
||||
"""
|
||||
Given a Traversable object, return that object as a
|
||||
path on the local file system in a context manager.
|
||||
"""
|
||||
return _tempfile(path.read_bytes, suffix=path.name)
|
||||
|
||||
|
||||
@as_file.register(Path)
|
||||
@contextlib.contextmanager
|
||||
def _(path):
|
||||
"""
|
||||
Degenerate behavior for pathlib.Path objects.
|
||||
"""
|
||||
yield path
|
@ -0,0 +1,139 @@
|
||||
from __future__ import absolute_import
|
||||
import sys
|
||||
|
||||
# flake8: noqa
|
||||
|
||||
if sys.version_info > (3,5):
|
||||
from pathlib import Path, PurePath
|
||||
else:
|
||||
from pathlib2 import Path, PurePath # type: ignore
|
||||
|
||||
|
||||
if sys.version_info > (3,):
|
||||
from contextlib import suppress
|
||||
else:
|
||||
from contextlib2 import suppress # type: ignore
|
||||
|
||||
|
||||
try:
|
||||
from functools import singledispatch
|
||||
except ImportError:
|
||||
from singledispatch import singledispatch # type: ignore
|
||||
|
||||
|
||||
try:
|
||||
from abc import ABC # type: ignore
|
||||
except ImportError:
|
||||
from abc import ABCMeta
|
||||
|
||||
class ABC(object): # type: ignore
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
|
||||
try:
|
||||
FileNotFoundError = FileNotFoundError # type: ignore
|
||||
except NameError:
|
||||
FileNotFoundError = OSError # type: ignore
|
||||
|
||||
|
||||
try:
|
||||
NotADirectoryError = NotADirectoryError # type: ignore
|
||||
except NameError:
|
||||
NotADirectoryError = OSError # type: ignore
|
||||
|
||||
|
||||
try:
|
||||
from zipfile import Path as ZipPath # type: ignore
|
||||
except ImportError:
|
||||
from zipp import Path as ZipPath # type: ignore
|
||||
|
||||
|
||||
try:
|
||||
from typing import runtime_checkable # type: ignore
|
||||
except ImportError:
|
||||
def runtime_checkable(cls): # type: ignore
|
||||
return cls
|
||||
|
||||
|
||||
try:
|
||||
from typing import Protocol # type: ignore
|
||||
except ImportError:
|
||||
Protocol = ABC # type: ignore
|
||||
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
class PackageSpec:
|
||||
def __init__(self, **kwargs):
|
||||
vars(self).update(kwargs)
|
||||
|
||||
|
||||
class TraversableResourcesAdapter:
|
||||
def __init__(self, spec):
|
||||
self.spec = spec
|
||||
self.loader = LoaderAdapter(spec)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.spec, name)
|
||||
|
||||
|
||||
class LoaderAdapter:
|
||||
"""
|
||||
Adapt loaders to provide TraversableResources and other
|
||||
compatibility.
|
||||
"""
|
||||
def __init__(self, spec):
|
||||
self.spec = spec
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
# Python < 3
|
||||
return self.spec.origin
|
||||
|
||||
def get_resource_reader(self, name):
|
||||
# Python < 3.9
|
||||
from . import readers
|
||||
|
||||
def _zip_reader(spec):
|
||||
with suppress(AttributeError):
|
||||
return readers.ZipReader(spec.loader, spec.name)
|
||||
|
||||
def _namespace_reader(spec):
|
||||
with suppress(AttributeError, ValueError):
|
||||
return readers.NamespaceReader(spec.submodule_search_locations)
|
||||
|
||||
def _available_reader(spec):
|
||||
with suppress(AttributeError):
|
||||
return spec.loader.get_resource_reader(spec.name)
|
||||
|
||||
def _native_reader(spec):
|
||||
reader = _available_reader(spec)
|
||||
return reader if hasattr(reader, 'files') else None
|
||||
|
||||
return (
|
||||
# native reader if it supplies 'files'
|
||||
_native_reader(self.spec) or
|
||||
# local ZipReader if a zip module
|
||||
_zip_reader(self.spec) or
|
||||
# local NamespaceReader if a namespace module
|
||||
_namespace_reader(self.spec) or
|
||||
# local FileReader
|
||||
readers.FileReader(self)
|
||||
)
|
||||
|
||||
|
||||
def package_spec(package):
|
||||
"""
|
||||
Construct a minimal package spec suitable for
|
||||
matching the interfaces this library relies upon
|
||||
in later Python versions.
|
||||
"""
|
||||
spec = getattr(package, '__spec__', None) or \
|
||||
PackageSpec(
|
||||
origin=package.__file__,
|
||||
loader=getattr(package, '__loader__', None),
|
||||
name=package.__name__,
|
||||
submodule_search_locations=getattr(package, '__path__', None),
|
||||
)
|
||||
return TraversableResourcesAdapter(spec)
|
@ -0,0 +1,107 @@
|
||||
import os
|
||||
import errno
|
||||
|
||||
from . import _common
|
||||
from ._compat import FileNotFoundError
|
||||
from io import BytesIO, TextIOWrapper, open as io_open
|
||||
|
||||
|
||||
def open_binary(package, resource):
|
||||
"""Return a file-like object opened for binary reading of the resource."""
|
||||
resource = _common.normalize_path(resource)
|
||||
package = _common.get_package(package)
|
||||
# Using pathlib doesn't work well here due to the lack of 'strict' argument
|
||||
# for pathlib.Path.resolve() prior to Python 3.6.
|
||||
package_path = os.path.dirname(package.__file__)
|
||||
relative_path = os.path.join(package_path, resource)
|
||||
full_path = os.path.abspath(relative_path)
|
||||
try:
|
||||
return io_open(full_path, 'rb')
|
||||
except IOError:
|
||||
# This might be a package in a zip file. zipimport provides a loader
|
||||
# with a functioning get_data() method, however we have to strip the
|
||||
# archive (i.e. the .zip file's name) off the front of the path. This
|
||||
# is because the zipimport loader in Python 2 doesn't actually follow
|
||||
# PEP 302. It should allow the full path, but actually requires that
|
||||
# the path be relative to the zip file.
|
||||
try:
|
||||
loader = package.__loader__
|
||||
full_path = relative_path[len(loader.archive)+1:]
|
||||
data = loader.get_data(full_path)
|
||||
except (IOError, AttributeError):
|
||||
package_name = package.__name__
|
||||
message = '{!r} resource not found in {!r}'.format(
|
||||
resource, package_name)
|
||||
raise FileNotFoundError(message)
|
||||
return BytesIO(data)
|
||||
|
||||
|
||||
def open_text(package, resource, encoding='utf-8', errors='strict'):
|
||||
"""Return a file-like object opened for text reading of the resource."""
|
||||
return TextIOWrapper(
|
||||
open_binary(package, resource), encoding=encoding, errors=errors)
|
||||
|
||||
|
||||
def read_binary(package, resource):
|
||||
"""Return the binary contents of the resource."""
|
||||
with open_binary(package, resource) as fp:
|
||||
return fp.read()
|
||||
|
||||
|
||||
def read_text(package, resource, encoding='utf-8', errors='strict'):
|
||||
"""Return the decoded string of the resource.
|
||||
|
||||
The decoding-related arguments have the same semantics as those of
|
||||
bytes.decode().
|
||||
"""
|
||||
with open_text(package, resource, encoding, errors) as fp:
|
||||
return fp.read()
|
||||
|
||||
|
||||
def path(package, resource):
|
||||
"""A context manager providing a file path object to the resource.
|
||||
|
||||
If the resource does not already exist on its own on the file system,
|
||||
a temporary file will be created. If the file was created, the file
|
||||
will be deleted upon exiting the context manager (no exception is
|
||||
raised if the file was deleted prior to the context manager
|
||||
exiting).
|
||||
"""
|
||||
path = _common.files(package).joinpath(_common.normalize_path(resource))
|
||||
if not path.is_file():
|
||||
raise FileNotFoundError(path)
|
||||
return _common.as_file(path)
|
||||
|
||||
|
||||
def is_resource(package, name):
|
||||
"""True if name is a resource inside package.
|
||||
|
||||
Directories are *not* resources.
|
||||
"""
|
||||
package = _common.get_package(package)
|
||||
_common.normalize_path(name)
|
||||
try:
|
||||
package_contents = set(contents(package))
|
||||
except OSError as error:
|
||||
if error.errno not in (errno.ENOENT, errno.ENOTDIR):
|
||||
# We won't hit this in the Python 2 tests, so it'll appear
|
||||
# uncovered. We could mock os.listdir() to return a non-ENOENT or
|
||||
# ENOTDIR, but then we'd have to depend on another external
|
||||
# library since Python 2 doesn't have unittest.mock. It's not
|
||||
# worth it.
|
||||
raise # pragma: nocover
|
||||
return False
|
||||
if name not in package_contents:
|
||||
return False
|
||||
return (_common.from_package(package) / name).is_file()
|
||||
|
||||
|
||||
def contents(package):
|
||||
"""Return an iterable of entries in `package`.
|
||||
|
||||
Note that not all entries are resources. Specifically, directories are
|
||||
not considered resources. Use `is_resource()` on each entry returned here
|
||||
to check if it is a resource or not.
|
||||
"""
|
||||
package = _common.get_package(package)
|
||||
return list(item.name for item in _common.from_package(package).iterdir())
|
@ -0,0 +1,160 @@
|
||||
import os
|
||||
import io
|
||||
|
||||
from . import _common
|
||||
from contextlib import suppress
|
||||
from importlib.abc import ResourceLoader
|
||||
from io import BytesIO, TextIOWrapper
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
from typing import Iterable, Iterator, Optional, Set, Union # noqa: F401
|
||||
from typing import cast
|
||||
from typing.io import BinaryIO, TextIO
|
||||
from collections.abc import Sequence
|
||||
from functools import singledispatch
|
||||
|
||||
if False: # TYPE_CHECKING
|
||||
from typing import ContextManager
|
||||
|
||||
Package = Union[ModuleType, str]
|
||||
Resource = Union[str, os.PathLike]
|
||||
|
||||
|
||||
def open_binary(package: Package, resource: Resource) -> BinaryIO:
|
||||
"""Return a file-like object opened for binary reading of the resource."""
|
||||
resource = _common.normalize_path(resource)
|
||||
package = _common.get_package(package)
|
||||
reader = _common.get_resource_reader(package)
|
||||
if reader is not None:
|
||||
return reader.open_resource(resource)
|
||||
# Using pathlib doesn't work well here due to the lack of 'strict'
|
||||
# argument for pathlib.Path.resolve() prior to Python 3.6.
|
||||
if package.__spec__.submodule_search_locations is not None:
|
||||
paths = package.__spec__.submodule_search_locations
|
||||
elif package.__spec__.origin is not None:
|
||||
paths = [os.path.dirname(os.path.abspath(package.__spec__.origin))]
|
||||
|
||||
for package_path in paths:
|
||||
full_path = os.path.join(package_path, resource)
|
||||
try:
|
||||
return open(full_path, mode='rb')
|
||||
except OSError:
|
||||
# Just assume the loader is a resource loader; all the relevant
|
||||
# importlib.machinery loaders are and an AttributeError for
|
||||
# get_data() will make it clear what is needed from the loader.
|
||||
loader = cast(ResourceLoader, package.__spec__.loader)
|
||||
data = None
|
||||
if hasattr(package.__spec__.loader, 'get_data'):
|
||||
with suppress(OSError):
|
||||
data = loader.get_data(full_path)
|
||||
if data is not None:
|
||||
return BytesIO(data)
|
||||
|
||||
raise FileNotFoundError('{!r} resource not found in {!r}'.format(
|
||||
resource, package.__spec__.name))
|
||||
|
||||
|
||||
def open_text(package: Package,
|
||||
resource: Resource,
|
||||
encoding: str = 'utf-8',
|
||||
errors: str = 'strict') -> TextIO:
|
||||
"""Return a file-like object opened for text reading of the resource."""
|
||||
return TextIOWrapper(
|
||||
open_binary(package, resource), encoding=encoding, errors=errors)
|
||||
|
||||
|
||||
def read_binary(package: Package, resource: Resource) -> bytes:
|
||||
"""Return the binary contents of the resource."""
|
||||
with open_binary(package, resource) as fp:
|
||||
return fp.read()
|
||||
|
||||
|
||||
def read_text(package: Package,
|
||||
resource: Resource,
|
||||
encoding: str = 'utf-8',
|
||||
errors: str = 'strict') -> str:
|
||||
"""Return the decoded string of the resource.
|
||||
|
||||
The decoding-related arguments have the same semantics as those of
|
||||
bytes.decode().
|
||||
"""
|
||||
with open_text(package, resource, encoding, errors) as fp:
|
||||
return fp.read()
|
||||
|
||||
|
||||
def path(
|
||||
package: Package, resource: Resource,
|
||||
) -> 'ContextManager[Path]':
|
||||
"""A context manager providing a file path object to the resource.
|
||||
|
||||
If the resource does not already exist on its own on the file system,
|
||||
a temporary file will be created. If the file was created, the file
|
||||
will be deleted upon exiting the context manager (no exception is
|
||||
raised if the file was deleted prior to the context manager
|
||||
exiting).
|
||||
"""
|
||||
reader = _common.get_resource_reader(_common.get_package(package))
|
||||
return (
|
||||
_path_from_reader(reader, _common.normalize_path(resource))
|
||||
if reader else
|
||||
_common.as_file(
|
||||
_common.files(package).joinpath(_common.normalize_path(resource)))
|
||||
)
|
||||
|
||||
|
||||
def _path_from_reader(reader, resource):
|
||||
return _path_from_resource_path(reader, resource) or \
|
||||
_path_from_open_resource(reader, resource)
|
||||
|
||||
|
||||
def _path_from_resource_path(reader, resource):
|
||||
with suppress(FileNotFoundError):
|
||||
return Path(reader.resource_path(resource))
|
||||
|
||||
|
||||
def _path_from_open_resource(reader, resource):
|
||||
saved = io.BytesIO(reader.open_resource(resource).read())
|
||||
return _common._tempfile(saved.read, suffix=resource)
|
||||
|
||||
|
||||
def is_resource(package: Package, name: str) -> bool:
|
||||
"""True if `name` is a resource inside `package`.
|
||||
|
||||
Directories are *not* resources.
|
||||
"""
|
||||
package = _common.get_package(package)
|
||||
_common.normalize_path(name)
|
||||
reader = _common.get_resource_reader(package)
|
||||
if reader is not None:
|
||||
return reader.is_resource(name)
|
||||
package_contents = set(contents(package))
|
||||
if name not in package_contents:
|
||||
return False
|
||||
return (_common.from_package(package) / name).is_file()
|
||||
|
||||
|
||||
def contents(package: Package) -> Iterable[str]:
|
||||
"""Return an iterable of entries in `package`.
|
||||
|
||||
Note that not all entries are resources. Specifically, directories are
|
||||
not considered resources. Use `is_resource()` on each entry returned here
|
||||
to check if it is a resource or not.
|
||||
"""
|
||||
package = _common.get_package(package)
|
||||
reader = _common.get_resource_reader(package)
|
||||
if reader is not None:
|
||||
return _ensure_sequence(reader.contents())
|
||||
transversable = _common.from_package(package)
|
||||
if transversable.is_dir():
|
||||
return list(item.name for item in transversable.iterdir())
|
||||
return []
|
||||
|
||||
|
||||
@singledispatch
|
||||
def _ensure_sequence(iterable):
|
||||
return list(iterable)
|
||||
|
||||
|
||||
@_ensure_sequence.register(Sequence)
|
||||
def _(iterable):
|
||||
return iterable
|
@ -0,0 +1,142 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import abc
|
||||
|
||||
from ._compat import ABC, FileNotFoundError, runtime_checkable, Protocol
|
||||
|
||||
# Use mypy's comment syntax for Python 2 compatibility
|
||||
try:
|
||||
from typing import BinaryIO, Iterable, Text
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
class ResourceReader(ABC):
|
||||
"""Abstract base class for loaders to provide resource reading support."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def open_resource(self, resource):
|
||||
# type: (Text) -> BinaryIO
|
||||
"""Return an opened, file-like object for binary reading.
|
||||
|
||||
The 'resource' argument is expected to represent only a file name.
|
||||
If the resource cannot be found, FileNotFoundError is raised.
|
||||
"""
|
||||
# This deliberately raises FileNotFoundError instead of
|
||||
# NotImplementedError so that if this method is accidentally called,
|
||||
# it'll still do the right thing.
|
||||
raise FileNotFoundError
|
||||
|
||||
@abc.abstractmethod
|
||||
def resource_path(self, resource):
|
||||
# type: (Text) -> Text
|
||||
"""Return the file system path to the specified resource.
|
||||
|
||||
The 'resource' argument is expected to represent only a file name.
|
||||
If the resource does not exist on the file system, raise
|
||||
FileNotFoundError.
|
||||
"""
|
||||
# This deliberately raises FileNotFoundError instead of
|
||||
# NotImplementedError so that if this method is accidentally called,
|
||||
# it'll still do the right thing.
|
||||
raise FileNotFoundError
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_resource(self, path):
|
||||
# type: (Text) -> bool
|
||||
"""Return True if the named 'path' is a resource.
|
||||
|
||||
Files are resources, directories are not.
|
||||
"""
|
||||
raise FileNotFoundError
|
||||
|
||||
@abc.abstractmethod
|
||||
def contents(self):
|
||||
# type: () -> Iterable[str]
|
||||
"""Return an iterable of entries in `package`."""
|
||||
raise FileNotFoundError
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class Traversable(Protocol):
|
||||
"""
|
||||
An object with a subset of pathlib.Path methods suitable for
|
||||
traversing directories and opening files.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def iterdir(self):
|
||||
"""
|
||||
Yield Traversable objects in self
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def read_bytes(self):
|
||||
"""
|
||||
Read contents of self as bytes
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def read_text(self, encoding=None):
|
||||
"""
|
||||
Read contents of self as bytes
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_dir(self):
|
||||
"""
|
||||
Return True if self is a dir
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_file(self):
|
||||
"""
|
||||
Return True if self is a file
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def joinpath(self, child):
|
||||
"""
|
||||
Return Traversable child in self
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __truediv__(self, child):
|
||||
"""
|
||||
Return Traversable child in self
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def open(self, mode='r', *args, **kwargs):
|
||||
"""
|
||||
mode may be 'r' or 'rb' to open as text or binary. Return a handle
|
||||
suitable for reading (same as pathlib.Path.open).
|
||||
|
||||
When opening as text, accepts encoding parameters such as those
|
||||
accepted by io.TextIOWrapper.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def name(self):
|
||||
# type: () -> str
|
||||
"""
|
||||
The base name of this object without any parent references.
|
||||
"""
|
||||
|
||||
|
||||
class TraversableResources(ResourceReader):
|
||||
@abc.abstractmethod
|
||||
def files(self):
|
||||
"""Return a Traversable object for the loaded package."""
|
||||
|
||||
def open_resource(self, resource):
|
||||
return self.files().joinpath(resource).open('rb')
|
||||
|
||||
def resource_path(self, resource):
|
||||
raise FileNotFoundError(resource)
|
||||
|
||||
def is_resource(self, path):
|
||||
return self.files().joinpath(path).is_file()
|
||||
|
||||
def contents(self):
|
||||
return (item.name for item in self.files().iterdir())
|
@ -0,0 +1,123 @@
|
||||
import os.path
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from . import abc
|
||||
|
||||
from ._compat import Path, ZipPath
|
||||
from ._compat import FileNotFoundError, NotADirectoryError
|
||||
|
||||
|
||||
class FileReader(abc.TraversableResources):
|
||||
def __init__(self, loader):
|
||||
self.path = Path(loader.path).parent
|
||||
|
||||
def resource_path(self, resource):
|
||||
"""
|
||||
Return the file system path to prevent
|
||||
`resources.path()` from creating a temporary
|
||||
copy.
|
||||
"""
|
||||
return str(self.path.joinpath(resource))
|
||||
|
||||
def files(self):
|
||||
return self.path
|
||||
|
||||
|
||||
class ZipReader(abc.TraversableResources):
|
||||
def __init__(self, loader, module):
|
||||
_, _, name = module.rpartition('.')
|
||||
self.prefix = loader.prefix.replace('\\', '/') + name + '/'
|
||||
self.archive = loader.archive
|
||||
|
||||
def open_resource(self, resource):
|
||||
try:
|
||||
return super().open_resource(resource)
|
||||
except KeyError as exc:
|
||||
raise FileNotFoundError(exc.args[0])
|
||||
|
||||
def is_resource(self, path):
|
||||
# workaround for `zipfile.Path.is_file` returning true
|
||||
# for non-existent paths.
|
||||
target = self.files().joinpath(path)
|
||||
return target.is_file() and target.exists()
|
||||
|
||||
def files(self):
|
||||
return ZipPath(self.archive, self.prefix)
|
||||
|
||||
|
||||
class MultiplexedPath(abc.Traversable):
|
||||
"""
|
||||
Given a series of Traversable objects, implement a merged
|
||||
version of the interface across all objects. Useful for
|
||||
namespace packages which may be multihomed at a single
|
||||
name.
|
||||
"""
|
||||
def __init__(self, *paths):
|
||||
paths = list(OrderedDict.fromkeys(paths)) # remove duplicates
|
||||
self._paths = list(map(Path, paths))
|
||||
if not self._paths:
|
||||
message = 'MultiplexedPath must contain at least one path'
|
||||
raise FileNotFoundError(message)
|
||||
if any(not path.is_dir() for path in self._paths):
|
||||
raise NotADirectoryError(
|
||||
'MultiplexedPath only supports directories')
|
||||
|
||||
def iterdir(self):
|
||||
visited = []
|
||||
for path in self._paths:
|
||||
for file in path.iterdir():
|
||||
if file.name in visited:
|
||||
continue
|
||||
visited.append(file.name)
|
||||
yield file
|
||||
|
||||
def read_bytes(self):
|
||||
raise FileNotFoundError('{} is not a file'.format(self))
|
||||
|
||||
def read_text(self, *args, **kwargs):
|
||||
raise FileNotFoundError('{} is not a file'.format(self))
|
||||
|
||||
def is_dir(self):
|
||||
return True
|
||||
|
||||
def is_file(self):
|
||||
return False
|
||||
|
||||
def joinpath(self, child):
|
||||
# first try to find child in current paths
|
||||
for file in self.iterdir():
|
||||
if file.name == child:
|
||||
return file
|
||||
# if it does not exist, construct it with the first path
|
||||
return self._paths[0] / child
|
||||
|
||||
__truediv__ = joinpath
|
||||
|
||||
def open(self, *args, **kwargs):
|
||||
raise FileNotFoundError('{} is not a file'.format(self))
|
||||
|
||||
def name(self):
|
||||
return os.path.basename(self._paths[0])
|
||||
|
||||
def __repr__(self):
|
||||
return 'MultiplexedPath({})'.format(
|
||||
', '.join("'{}'".format(path) for path in self._paths))
|
||||
|
||||
|
||||
class NamespaceReader(abc.TraversableResources):
|
||||
def __init__(self, namespace_path):
|
||||
if 'NamespacePath' not in str(namespace_path):
|
||||
raise ValueError('Invalid path')
|
||||
self.path = MultiplexedPath(*list(namespace_path))
|
||||
|
||||
def resource_path(self, resource):
|
||||
"""
|
||||
Return the file system path to prevent
|
||||
`resources.path()` from creating a temporary
|
||||
copy.
|
||||
"""
|
||||
return str(self.path.joinpath(resource))
|
||||
|
||||
def files(self):
|
||||
return self.path
|
@ -0,0 +1,6 @@
|
||||
# for compatibility with 1.1, continue to expose as_file here.
|
||||
|
||||
from ._common import as_file
|
||||
|
||||
|
||||
__all__ = ['as_file']
|
@ -1,5 +0,0 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.34.2)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp38-cp38-macosx_10_15_x86_64
|
||||
|
@ -1,7 +1,6 @@
|
||||
_scandir.cpython-38-darwin.so,sha256=3a2UitVjb1MS0I7WSOp7jPGHsKf-ctNYTrBvDmPupOg,27780
|
||||
scandir.py,sha256=97C2AQInuKk-Phb3aXM7fJomhc-00pZMcBur23NUmrE,24827
|
||||
scandir-1.10.0.dist-info/LICENSE.txt,sha256=peL73COXREGdKUB828knk8TZwdlWwXT3y3-W-m0FjIY,1464
|
||||
scandir-1.10.0.dist-info/METADATA,sha256=cv1fZ5DeC3DJqnMByWGiprvGhLpQCkWOZiJduweakGk,9559
|
||||
scandir-1.10.0.dist-info/WHEEL,sha256=NqgkTkAaRJaCuArPZklUp2tBwn6obHN9aMIfdfLfNkU,110
|
||||
scandir-1.10.0.dist-info/WHEEL,sha256=WO4o60shExe_A5pkiO6Yb-8OHLGhlAGcs2oJ7aUuE5Q,110
|
||||
scandir-1.10.0.dist-info/top_level.txt,sha256=Ixze5mNjmis99ql7JEtAYc9-djJMbfRx-FFw3R_zZf8,17
|
||||
scandir-1.10.0.dist-info/RECORD,,
|
@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.35.1)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp39-cp39-macosx_10_15_x86_64
|
||||
|
@ -1,6 +0,0 @@
|
||||
zipp.py,sha256=o8W25XfoR5DD_krEQLbYrNMmK-x26JvaqeKuboC91YY,7121
|
||||
zipp-3.1.0.dist-info/LICENSE,sha256=2z8CRrH5J48VhFuZ_sR4uLUG63ZIeZNyL4xuJUKF-vg,1050
|
||||
zipp-3.1.0.dist-info/METADATA,sha256=EbCdCb8ZzwzYDA7RF8R830VeruipjOKnj32zpMxPsFM,1899
|
||||
zipp-3.1.0.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
|
||||
zipp-3.1.0.dist-info/top_level.txt,sha256=iAbdoSHfaGqBfVb2XuR9JqSQHCoOsOtG6y9C_LSpqFw,5
|
||||
zipp-3.1.0.dist-info/RECORD,,
|
@ -1,6 +1,6 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: zipp
|
||||
Version: 3.1.0
|
||||
Version: 3.4.0
|
||||
Summary: Backport of pathlib-compatible object wrapper for zip files
|
||||
Home-page: https://github.com/jaraco/zipp
|
||||
Author: Jason R. Coombs
|
||||
@ -18,8 +18,15 @@ Requires-Dist: sphinx ; extra == 'docs'
|
||||
Requires-Dist: jaraco.packaging (>=3.2) ; extra == 'docs'
|
||||
Requires-Dist: rst.linker (>=1.9) ; extra == 'docs'
|
||||
Provides-Extra: testing
|
||||
Requires-Dist: pytest (!=3.7.3,>=3.5) ; extra == 'testing'
|
||||
Requires-Dist: pytest-checkdocs (>=1.2.3) ; extra == 'testing'
|
||||
Requires-Dist: pytest-flake8 ; extra == 'testing'
|
||||
Requires-Dist: pytest-cov ; extra == 'testing'
|
||||
Requires-Dist: jaraco.test (>=3.2.0) ; extra == 'testing'
|
||||
Requires-Dist: jaraco.itertools ; extra == 'testing'
|
||||
Requires-Dist: func-timeout ; extra == 'testing'
|
||||
Requires-Dist: pytest-black (>=0.3.7) ; (platform_python_implementation != "PyPy") and extra == 'testing'
|
||||
Requires-Dist: pytest-mypy ; (platform_python_implementation != "PyPy") and extra == 'testing'
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/zipp.svg
|
||||
:target: `PyPI link`_
|
||||
@ -29,19 +36,14 @@ Requires-Dist: func-timeout ; extra == 'testing'
|
||||
|
||||
.. _PyPI link: https://pypi.org/project/zipp
|
||||
|
||||
.. image:: https://dev.azure.com/jaraco/zipp/_apis/build/status/jaraco.zipp?branchName=master
|
||||
:target: https://dev.azure.com/jaraco/zipp/_build/latest?definitionId=1&branchName=master
|
||||
|
||||
.. image:: https://img.shields.io/travis/jaraco/zipp/master.svg
|
||||
:target: https://travis-ci.org/jaraco/zipp
|
||||
.. image:: https://github.com/jaraco/zipp/workflows/Automated%20Tests/badge.svg
|
||||
:target: https://github.com/jaraco/zipp/actions?query=workflow%3A%22Automated+Tests%22
|
||||
:alt: Automated Tests
|
||||
|
||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||
:target: https://github.com/psf/black
|
||||
:alt: Code style: Black
|
||||
|
||||
.. image:: https://img.shields.io/appveyor/ci/jaraco/zipp/master.svg
|
||||
:target: https://ci.appveyor.com/project/jaraco/zipp/branch/master
|
||||
|
||||
.. .. image:: https://readthedocs.org/projects/zipp/badge/?version=latest
|
||||
.. :target: https://zipp.readthedocs.io/en/latest/?badge=latest
|
||||
|
@ -0,0 +1,6 @@
|
||||
zipp.py,sha256=wMSoYxAIPgYnqJAW0JcAl5sWaIcFc5xk3dNjf6ElGgU,8089
|
||||
zipp-3.4.0.dist-info/LICENSE,sha256=2z8CRrH5J48VhFuZ_sR4uLUG63ZIeZNyL4xuJUKF-vg,1050
|
||||
zipp-3.4.0.dist-info/METADATA,sha256=noSfks-ReGCmOSTxll7TELBJy0P_yAvVLa0FCFyhMeM,2134
|
||||
zipp-3.4.0.dist-info/WHEEL,sha256=EVRjI69F5qVjm_YgqcTXPnTAv3BfSUr0WVAHuSP3Xoo,92
|
||||
zipp-3.4.0.dist-info/top_level.txt,sha256=iAbdoSHfaGqBfVb2XuR9JqSQHCoOsOtG6y9C_LSpqFw,5
|
||||
zipp-3.4.0.dist-info/RECORD,,
|
@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.35.1)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
@ -4,6 +4,7 @@ import zipfile
|
||||
import itertools
|
||||
import contextlib
|
||||
import sys
|
||||
import pathlib
|
||||
|
||||
if sys.version_info < (3, 7):
|
||||
from collections import OrderedDict
|
||||
@ -105,13 +106,12 @@ class CompleteDirs(zipfile.ZipFile):
|
||||
if not isinstance(source, zipfile.ZipFile):
|
||||
return cls(_pathlib_compat(source))
|
||||
|
||||
# Only allow for FastPath when supplied zipfile is read-only
|
||||
# Only allow for FastLookup when supplied zipfile is read-only
|
||||
if 'r' not in source.mode:
|
||||
cls = CompleteDirs
|
||||
|
||||
res = cls.__new__(cls)
|
||||
vars(res).update(vars(source))
|
||||
return res
|
||||
source.__class__ = cls
|
||||
return source
|
||||
|
||||
|
||||
class FastLookup(CompleteDirs):
|
||||
@ -119,6 +119,7 @@ class FastLookup(CompleteDirs):
|
||||
ZipFile subclass to ensure implicit
|
||||
dirs exist and are resolved rapidly.
|
||||
"""
|
||||
|
||||
def namelist(self):
|
||||
with contextlib.suppress(AttributeError):
|
||||
return self.__names
|
||||
@ -161,7 +162,7 @@ class Path:
|
||||
>>> zf.writestr('a.txt', 'content of a')
|
||||
>>> zf.writestr('b/c.txt', 'content of c')
|
||||
>>> zf.writestr('b/d/e.txt', 'content of e')
|
||||
>>> zf.filename = 'abcde.zip'
|
||||
>>> zf.filename = 'mem/abcde.zip'
|
||||
|
||||
Path accepts the zipfile object itself or a filename
|
||||
|
||||
@ -173,9 +174,9 @@ class Path:
|
||||
|
||||
>>> a, b = root.iterdir()
|
||||
>>> a
|
||||
Path('abcde.zip', 'a.txt')
|
||||
Path('mem/abcde.zip', 'a.txt')
|
||||
>>> b
|
||||
Path('abcde.zip', 'b/')
|
||||
Path('mem/abcde.zip', 'b/')
|
||||
|
||||
name property:
|
||||
|
||||
@ -186,7 +187,7 @@ class Path:
|
||||
|
||||
>>> c = b / 'c.txt'
|
||||
>>> c
|
||||
Path('abcde.zip', 'b/c.txt')
|
||||
Path('mem/abcde.zip', 'b/c.txt')
|
||||
>>> c.name
|
||||
'c.txt'
|
||||
|
||||
@ -204,13 +205,35 @@ class Path:
|
||||
|
||||
Coercion to string:
|
||||
|
||||
>>> str(c)
|
||||
'abcde.zip/b/c.txt'
|
||||
>>> import os
|
||||
>>> str(c).replace(os.sep, posixpath.sep)
|
||||
'mem/abcde.zip/b/c.txt'
|
||||
|
||||
At the root, ``name``, ``filename``, and ``parent``
|
||||
resolve to the zipfile. Note these attributes are not
|
||||
valid and will raise a ``ValueError`` if the zipfile
|
||||
has no filename.
|
||||
|
||||
>>> root.name
|
||||
'abcde.zip'
|
||||
>>> str(root.filename).replace(os.sep, posixpath.sep)
|
||||
'mem/abcde.zip'
|
||||
>>> str(root.parent)
|
||||
'mem'
|
||||
"""
|
||||
|
||||
__repr = "{self.__class__.__name__}({self.root.filename!r}, {self.at!r})"
|
||||
|
||||
def __init__(self, root, at=""):
|
||||
"""
|
||||
Construct a Path from a ZipFile or filename.
|
||||
|
||||
Note: When the source is an existing ZipFile object,
|
||||
its type (__class__) will be mutated to a
|
||||
specialized type. If the caller wishes to retain the
|
||||
original type, the caller should either create a
|
||||
separate ZipFile object or pass a filename.
|
||||
"""
|
||||
self.root = FastLookup.make(root)
|
||||
self.at = at
|
||||
|
||||
@ -234,7 +257,11 @@ class Path:
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return posixpath.basename(self.at.rstrip("/"))
|
||||
return pathlib.Path(self.at).name or self.filename.name
|
||||
|
||||
@property
|
||||
def filename(self):
|
||||
return pathlib.Path(self.root.filename).joinpath(self.at)
|
||||
|
||||
def read_text(self, *args, **kwargs):
|
||||
with self.open('r', *args, **kwargs) as strm:
|
||||
@ -248,13 +275,13 @@ class Path:
|
||||
return posixpath.dirname(path.at.rstrip("/")) == self.at.rstrip("/")
|
||||
|
||||
def _next(self, at):
|
||||
return Path(self.root, at)
|
||||
return self.__class__(self.root, at)
|
||||
|
||||
def is_dir(self):
|
||||
return not self.at or self.at.endswith("/")
|
||||
|
||||
def is_file(self):
|
||||
return not self.is_dir()
|
||||
return self.exists() and not self.is_dir()
|
||||
|
||||
def exists(self):
|
||||
return self.at in self.root._name_set()
|
||||
@ -271,14 +298,16 @@ class Path:
|
||||
def __repr__(self):
|
||||
return self.__repr.format(self=self)
|
||||
|
||||
def joinpath(self, add):
|
||||
next = posixpath.join(self.at, _pathlib_compat(add))
|
||||
def joinpath(self, *other):
|
||||
next = posixpath.join(self.at, *map(_pathlib_compat, other))
|
||||
return self._next(self.root.resolve_dir(next))
|
||||
|
||||
__truediv__ = joinpath
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
if not self.at:
|
||||
return self.filename.parent
|
||||
parent_at = posixpath.dirname(self.at.rstrip('/'))
|
||||
if parent_at:
|
||||
parent_at += '/'
|
18
third_party/python/virtualenv/distributions.json
vendored
18
third_party/python/virtualenv/distributions.json
vendored
@ -21,8 +21,8 @@
|
||||
"distlib": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib-0.3.1.dist-info",
|
||||
"filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock-3.0.12.dist-info",
|
||||
"six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six-1.15.0.dist-info",
|
||||
"importlib_metadata": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata-1.7.0.dist-info",
|
||||
"zipp": "__virtualenv__/zipp-3.1.0-py3-none-any/zipp-3.1.0.dist-info"
|
||||
"importlib_metadata": "__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata-3.1.1.dist-info",
|
||||
"zipp": "__virtualenv__/zipp-3.4.0-py3-none-any/zipp-3.4.0.dist-info"
|
||||
}
|
||||
},
|
||||
"3.6": {
|
||||
@ -31,9 +31,9 @@
|
||||
"distlib": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib-0.3.1.dist-info",
|
||||
"filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock-3.0.12.dist-info",
|
||||
"six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six-1.15.0.dist-info",
|
||||
"importlib_metadata": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata-1.7.0.dist-info",
|
||||
"zipp": "__virtualenv__/zipp-3.1.0-py3-none-any/zipp-3.1.0.dist-info",
|
||||
"importlib_resources": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources-3.0.0.dist-info"
|
||||
"importlib_metadata": "__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata-3.1.1.dist-info",
|
||||
"zipp": "__virtualenv__/zipp-3.4.0-py3-none-any/zipp-3.4.0.dist-info",
|
||||
"importlib_resources": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources-3.3.0.dist-info"
|
||||
}
|
||||
},
|
||||
"3.5": {
|
||||
@ -42,9 +42,9 @@
|
||||
"distlib": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib-0.3.1.dist-info",
|
||||
"filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock-3.0.12.dist-info",
|
||||
"six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six-1.15.0.dist-info",
|
||||
"importlib_metadata": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata-1.7.0.dist-info",
|
||||
"importlib_metadata": "__virtualenv__/importlib_metadata-2.1.1-py2.py3-none-any/importlib_metadata-2.1.1.dist-info",
|
||||
"zipp": "__virtualenv__/zipp-1.2.0-py2.py3-none-any/zipp-1.2.0.dist-info",
|
||||
"importlib_resources": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources-3.0.0.dist-info"
|
||||
"importlib_resources": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources-3.2.1.dist-info"
|
||||
}
|
||||
},
|
||||
"3.4": {
|
||||
@ -58,7 +58,7 @@
|
||||
"importlib_resources": "__virtualenv__/importlib_resources-1.0.2-py2.py3-none-any/importlib_resources-1.0.2.dist-info",
|
||||
"typing": "__virtualenv__/typing-3.7.4.1-py3-none-any/typing-3.7.4.1.dist-info",
|
||||
"pathlib2": "__virtualenv__/pathlib2-2.3.5-py2.py3-none-any/pathlib2-2.3.5.dist-info",
|
||||
"scandir": "__virtualenv__/scandir-1.10.0-cp38-cp38-macosx_10_15_x86_64/scandir-1.10.0.dist-info"
|
||||
"scandir": "__virtualenv__/scandir-1.10.0-cp39-cp39-macosx_10_15_x86_64/scandir-1.10.0.dist-info"
|
||||
}
|
||||
},
|
||||
"2.7": {
|
||||
@ -72,7 +72,7 @@
|
||||
"importlib_resources": "__virtualenv__/importlib_resources-1.0.2-py2.py3-none-any/importlib_resources-1.0.2.dist-info",
|
||||
"typing": "__virtualenv__/typing-3.7.4.3-py2-none-any/typing-3.7.4.3.dist-info",
|
||||
"pathlib2": "__virtualenv__/pathlib2-2.3.5-py2.py3-none-any/pathlib2-2.3.5.dist-info",
|
||||
"scandir": "__virtualenv__/scandir-1.10.0-cp38-cp38-macosx_10_15_x86_64/scandir-1.10.0.dist-info",
|
||||
"scandir": "__virtualenv__/scandir-1.10.0-cp39-cp39-macosx_10_15_x86_64/scandir-1.10.0.dist-info",
|
||||
"contextlib2": "__virtualenv__/contextlib2-0.6.0.post1-py2.py3-none-any/contextlib2-0.6.0.post1.dist-info",
|
||||
"configparser": "__virtualenv__/configparser-4.0.2-py2.py3-none-any/configparser-4.0.2.dist-info"
|
||||
},
|
||||
|
147
third_party/python/virtualenv/modules.json
vendored
147
third_party/python/virtualenv/modules.json
vendored
@ -72,18 +72,9 @@
|
||||
"distlib._backport.tarfile": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib/_backport/tarfile.py",
|
||||
"filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock.py",
|
||||
"six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six.py",
|
||||
"importlib_metadata": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/__init__.py",
|
||||
"importlib_metadata._compat": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/_compat.py",
|
||||
"importlib_metadata.docs": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/docs/__init__.py",
|
||||
"importlib_metadata.docs.conf": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/docs/conf.py",
|
||||
"importlib_metadata.tests": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/__init__.py",
|
||||
"importlib_metadata.tests.fixtures": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/fixtures.py",
|
||||
"importlib_metadata.tests.test_api": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_api.py",
|
||||
"importlib_metadata.tests.test_integration": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_integration.py",
|
||||
"importlib_metadata.tests.test_main": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_main.py",
|
||||
"importlib_metadata.tests.test_zip": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_zip.py",
|
||||
"importlib_metadata.tests.data": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/data/__init__.py",
|
||||
"zipp": "__virtualenv__/zipp-3.1.0-py3-none-any/zipp.py"
|
||||
"importlib_metadata": "__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata/__init__.py",
|
||||
"importlib_metadata._compat": "__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata/_compat.py",
|
||||
"zipp": "__virtualenv__/zipp-3.4.0-py3-none-any/zipp.py"
|
||||
}
|
||||
},
|
||||
"3.6": {
|
||||
@ -109,43 +100,34 @@
|
||||
"distlib._backport.tarfile": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib/_backport/tarfile.py",
|
||||
"filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock.py",
|
||||
"six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six.py",
|
||||
"importlib_metadata": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/__init__.py",
|
||||
"importlib_metadata._compat": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/_compat.py",
|
||||
"importlib_metadata.docs": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/docs/__init__.py",
|
||||
"importlib_metadata.docs.conf": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/docs/conf.py",
|
||||
"importlib_metadata.tests": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/__init__.py",
|
||||
"importlib_metadata.tests.fixtures": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/fixtures.py",
|
||||
"importlib_metadata.tests.test_api": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_api.py",
|
||||
"importlib_metadata.tests.test_integration": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_integration.py",
|
||||
"importlib_metadata.tests.test_main": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_main.py",
|
||||
"importlib_metadata.tests.test_zip": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_zip.py",
|
||||
"importlib_metadata.tests.data": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/data/__init__.py",
|
||||
"zipp": "__virtualenv__/zipp-3.1.0-py3-none-any/zipp.py",
|
||||
"importlib_resources": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/__init__.py",
|
||||
"importlib_resources._common": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_common.py",
|
||||
"importlib_resources._compat": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_compat.py",
|
||||
"importlib_resources._py2": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_py2.py",
|
||||
"importlib_resources._py3": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_py3.py",
|
||||
"importlib_resources.abc": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/abc.py",
|
||||
"importlib_resources.readers": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/readers.py",
|
||||
"importlib_resources.trees": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/trees.py",
|
||||
"importlib_resources.tests": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/__init__.py",
|
||||
"importlib_resources.tests.test_files": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_files.py",
|
||||
"importlib_resources.tests.test_open": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_open.py",
|
||||
"importlib_resources.tests.test_path": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_path.py",
|
||||
"importlib_resources.tests.test_read": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_read.py",
|
||||
"importlib_resources.tests.test_resource": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_resource.py",
|
||||
"importlib_resources.tests.util": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/util.py",
|
||||
"importlib_resources.tests.data01": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data01/__init__.py",
|
||||
"importlib_resources.tests.data01.subdirectory": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data01/subdirectory/__init__.py",
|
||||
"importlib_resources.tests.data02": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data02/__init__.py",
|
||||
"importlib_resources.tests.data02.one": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data02/one/__init__.py",
|
||||
"importlib_resources.tests.data02.two": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data02/two/__init__.py",
|
||||
"importlib_resources.tests.data03": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data03/__init__.py",
|
||||
"importlib_resources.tests.data03.namespace.portion1": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data03/namespace/portion1/__init__.py",
|
||||
"importlib_resources.tests.data03.namespace.portion2": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data03/namespace/portion2/__init__.py",
|
||||
"importlib_resources.tests.zipdata01": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/zipdata01/__init__.py",
|
||||
"importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py"
|
||||
"importlib_metadata": "__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata/__init__.py",
|
||||
"importlib_metadata._compat": "__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata/_compat.py",
|
||||
"zipp": "__virtualenv__/zipp-3.4.0-py3-none-any/zipp.py",
|
||||
"importlib_resources": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/__init__.py",
|
||||
"importlib_resources._common": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/_common.py",
|
||||
"importlib_resources._compat": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/_compat.py",
|
||||
"importlib_resources._py2": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/_py2.py",
|
||||
"importlib_resources._py3": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/_py3.py",
|
||||
"importlib_resources.abc": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/abc.py",
|
||||
"importlib_resources.readers": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/readers.py",
|
||||
"importlib_resources.trees": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/trees.py",
|
||||
"importlib_resources.tests": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/__init__.py",
|
||||
"importlib_resources.tests._compat": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/_compat.py",
|
||||
"importlib_resources.tests.py27compat": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/py27compat.py",
|
||||
"importlib_resources.tests.test_files": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/test_files.py",
|
||||
"importlib_resources.tests.test_open": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/test_open.py",
|
||||
"importlib_resources.tests.test_path": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/test_path.py",
|
||||
"importlib_resources.tests.test_read": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/test_read.py",
|
||||
"importlib_resources.tests.test_reader": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/test_reader.py",
|
||||
"importlib_resources.tests.test_resource": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/test_resource.py",
|
||||
"importlib_resources.tests.util": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/util.py",
|
||||
"importlib_resources.tests.data01": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/data01/__init__.py",
|
||||
"importlib_resources.tests.data01.subdirectory": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/data01/subdirectory/__init__.py",
|
||||
"importlib_resources.tests.data02": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/data02/__init__.py",
|
||||
"importlib_resources.tests.data02.one": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/data02/one/__init__.py",
|
||||
"importlib_resources.tests.data02.two": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/data02/two/__init__.py",
|
||||
"importlib_resources.tests.zipdata01": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/zipdata01/__init__.py",
|
||||
"importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py"
|
||||
}
|
||||
},
|
||||
"3.5": {
|
||||
@ -171,43 +153,34 @@
|
||||
"distlib._backport.tarfile": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib/_backport/tarfile.py",
|
||||
"filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock.py",
|
||||
"six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six.py",
|
||||
"importlib_metadata": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/__init__.py",
|
||||
"importlib_metadata._compat": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/_compat.py",
|
||||
"importlib_metadata.docs": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/docs/__init__.py",
|
||||
"importlib_metadata.docs.conf": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/docs/conf.py",
|
||||
"importlib_metadata.tests": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/__init__.py",
|
||||
"importlib_metadata.tests.fixtures": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/fixtures.py",
|
||||
"importlib_metadata.tests.test_api": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_api.py",
|
||||
"importlib_metadata.tests.test_integration": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_integration.py",
|
||||
"importlib_metadata.tests.test_main": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_main.py",
|
||||
"importlib_metadata.tests.test_zip": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_zip.py",
|
||||
"importlib_metadata.tests.data": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/data/__init__.py",
|
||||
"importlib_metadata": "__virtualenv__/importlib_metadata-2.1.1-py2.py3-none-any/importlib_metadata/__init__.py",
|
||||
"importlib_metadata._compat": "__virtualenv__/importlib_metadata-2.1.1-py2.py3-none-any/importlib_metadata/_compat.py",
|
||||
"zipp": "__virtualenv__/zipp-1.2.0-py2.py3-none-any/zipp.py",
|
||||
"importlib_resources": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/__init__.py",
|
||||
"importlib_resources._common": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_common.py",
|
||||
"importlib_resources._compat": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_compat.py",
|
||||
"importlib_resources._py2": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_py2.py",
|
||||
"importlib_resources._py3": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_py3.py",
|
||||
"importlib_resources.abc": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/abc.py",
|
||||
"importlib_resources.readers": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/readers.py",
|
||||
"importlib_resources.trees": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/trees.py",
|
||||
"importlib_resources.tests": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/__init__.py",
|
||||
"importlib_resources.tests.test_files": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_files.py",
|
||||
"importlib_resources.tests.test_open": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_open.py",
|
||||
"importlib_resources.tests.test_path": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_path.py",
|
||||
"importlib_resources.tests.test_read": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_read.py",
|
||||
"importlib_resources.tests.test_resource": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_resource.py",
|
||||
"importlib_resources.tests.util": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/util.py",
|
||||
"importlib_resources.tests.data01": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data01/__init__.py",
|
||||
"importlib_resources.tests.data01.subdirectory": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data01/subdirectory/__init__.py",
|
||||
"importlib_resources.tests.data02": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data02/__init__.py",
|
||||
"importlib_resources.tests.data02.one": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data02/one/__init__.py",
|
||||
"importlib_resources.tests.data02.two": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data02/two/__init__.py",
|
||||
"importlib_resources.tests.data03": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data03/__init__.py",
|
||||
"importlib_resources.tests.data03.namespace.portion1": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data03/namespace/portion1/__init__.py",
|
||||
"importlib_resources.tests.data03.namespace.portion2": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data03/namespace/portion2/__init__.py",
|
||||
"importlib_resources.tests.zipdata01": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/zipdata01/__init__.py",
|
||||
"importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py"
|
||||
"importlib_resources": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/__init__.py",
|
||||
"importlib_resources._common": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/_common.py",
|
||||
"importlib_resources._compat": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/_compat.py",
|
||||
"importlib_resources._py2": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/_py2.py",
|
||||
"importlib_resources._py3": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/_py3.py",
|
||||
"importlib_resources.abc": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/abc.py",
|
||||
"importlib_resources.readers": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/readers.py",
|
||||
"importlib_resources.trees": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/trees.py",
|
||||
"importlib_resources.tests": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/__init__.py",
|
||||
"importlib_resources.tests._compat": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/_compat.py",
|
||||
"importlib_resources.tests.py27compat": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/py27compat.py",
|
||||
"importlib_resources.tests.test_files": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/test_files.py",
|
||||
"importlib_resources.tests.test_open": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/test_open.py",
|
||||
"importlib_resources.tests.test_path": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/test_path.py",
|
||||
"importlib_resources.tests.test_read": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/test_read.py",
|
||||
"importlib_resources.tests.test_reader": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/test_reader.py",
|
||||
"importlib_resources.tests.test_resource": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/test_resource.py",
|
||||
"importlib_resources.tests.util": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/util.py",
|
||||
"importlib_resources.tests.data01": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/data01/__init__.py",
|
||||
"importlib_resources.tests.data01.subdirectory": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/data01/subdirectory/__init__.py",
|
||||
"importlib_resources.tests.data02": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/data02/__init__.py",
|
||||
"importlib_resources.tests.data02.one": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/data02/one/__init__.py",
|
||||
"importlib_resources.tests.data02.two": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/data02/two/__init__.py",
|
||||
"importlib_resources.tests.zipdata01": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/zipdata01/__init__.py",
|
||||
"importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py"
|
||||
}
|
||||
},
|
||||
"3.4": {
|
||||
@ -267,7 +240,7 @@
|
||||
"importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-1.0.2-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py",
|
||||
"typing": "__virtualenv__/typing-3.7.4.1-py3-none-any/typing.py",
|
||||
"pathlib2": "__virtualenv__/pathlib2-2.3.5-py2.py3-none-any/pathlib2/__init__.py",
|
||||
"scandir": "__virtualenv__/scandir-1.10.0-cp38-cp38-macosx_10_15_x86_64/scandir.py"
|
||||
"scandir": "__virtualenv__/scandir-1.10.0-cp39-cp39-macosx_10_15_x86_64/scandir.py"
|
||||
}
|
||||
},
|
||||
"2.7": {
|
||||
@ -327,7 +300,7 @@
|
||||
"importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-1.0.2-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py",
|
||||
"typing": "__virtualenv__/typing-3.7.4.3-py2-none-any/typing.py",
|
||||
"pathlib2": "__virtualenv__/pathlib2-2.3.5-py2.py3-none-any/pathlib2/__init__.py",
|
||||
"scandir": "__virtualenv__/scandir-1.10.0-cp38-cp38-macosx_10_15_x86_64/scandir.py",
|
||||
"scandir": "__virtualenv__/scandir-1.10.0-cp39-cp39-macosx_10_15_x86_64/scandir.py",
|
||||
"contextlib2": "__virtualenv__/contextlib2-0.6.0.post1-py2.py3-none-any/contextlib2.py",
|
||||
"configparser": "__virtualenv__/configparser-4.0.2-py2.py3-none-any/configparser.py",
|
||||
"backports": "__virtualenv__/configparser-4.0.2-py2.py3-none-any/backports/__init__.py",
|
||||
|
@ -1,6 +1,6 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: virtualenv
|
||||
Version: 20.0.31
|
||||
Version: 20.2.2
|
||||
Summary: Virtual Python Environment builder
|
||||
Home-page: https://virtualenv.pypa.io/
|
||||
Author: Bernat Gabor
|
||||
@ -26,6 +26,7 @@ Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: Software Development :: Libraries
|
||||
@ -39,7 +40,7 @@ Requires-Dist: filelock (<4,>=3.0.0)
|
||||
Requires-Dist: six (<2,>=1.9.0)
|
||||
Requires-Dist: pathlib2 (<3,>=2.3.3) ; python_version < "3.4" and sys_platform != "win32"
|
||||
Requires-Dist: importlib-resources (>=1.0) ; python_version < "3.7"
|
||||
Requires-Dist: importlib-metadata (<2,>=0.12) ; python_version < "3.8"
|
||||
Requires-Dist: importlib-metadata (>=0.12) ; python_version < "3.8"
|
||||
Provides-Extra: docs
|
||||
Requires-Dist: proselint (>=0.10.2) ; extra == 'docs'
|
||||
Requires-Dist: sphinx (>=3) ; extra == 'docs'
|
||||
@ -47,7 +48,7 @@ Requires-Dist: sphinx-argparse (>=0.2.5) ; extra == 'docs'
|
||||
Requires-Dist: sphinx-rtd-theme (>=0.4.3) ; extra == 'docs'
|
||||
Requires-Dist: towncrier (>=19.9.0rc1) ; extra == 'docs'
|
||||
Provides-Extra: testing
|
||||
Requires-Dist: coverage (>=5) ; extra == 'testing'
|
||||
Requires-Dist: coverage (>=4) ; extra == 'testing'
|
||||
Requires-Dist: coverage-enable-subprocess (>=1) ; extra == 'testing'
|
||||
Requires-Dist: flaky (>=3) ; extra == 'testing'
|
||||
Requires-Dist: pytest (>=4) ; extra == 'testing'
|
||||
@ -69,8 +70,8 @@ Requires-Dist: xonsh (>=0.9.16) ; (python_version > "3.4" and python_version !=
|
||||
[![Gitter Chat](https://img.shields.io/gitter/room/pypa/virtualenv?color=FF004F&style=flat-square)](https://gitter.im/pypa/virtualenv)
|
||||
[![PyPI - Downloads](https://img.shields.io/pypi/dm/virtualenv?style=flat-square)](https://pypistats.org/packages/virtualenv)
|
||||
[![PyPI - License](https://img.shields.io/pypi/l/virtualenv?style=flat-square)](https://opensource.org/licenses/MIT)
|
||||
[![Build Status](https://github.com/pypa/virtualenv/workflows/check/badge.svg?branch=master&event=push)](https://github.com/pypa/virtualenv/actions?query=workflow%3Acheck)
|
||||
[![codecov](https://codecov.io/gh/pypa/virtualenv/branch/master/graph/badge.svg)](https://codecov.io/gh/pypa/virtualenv)
|
||||
[![Build Status](https://github.com/pypa/virtualenv/workflows/check/badge.svg?branch=main&event=push)](https://github.com/pypa/virtualenv/actions?query=workflow%3Acheck)
|
||||
[![codecov](https://codecov.io/gh/pypa/virtualenv/branch/main/graph/badge.svg)](https://codecov.io/gh/pypa/virtualenv)
|
||||
[![Code style:
|
||||
black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square)](https://github.com/psf/black)
|
||||
|
@ -2,12 +2,12 @@ virtualenv/__init__.py,sha256=SMvpjz4VJ3vJ_yfDDPzJAdi2GJOYd_UBXXuvImO07gk,205
|
||||
virtualenv/__main__.py,sha256=QMwDqrR4QbhEivl8yoRmAr6G1BY92gr4n1ConcDIxc4,2770
|
||||
virtualenv/info.py,sha256=-2pI_kyC9fNj5OR8AQWkKjlpOk4_96Lmbco3atYYBdY,1921
|
||||
virtualenv/report.py,sha256=M2OHHCWdOHZsn74tj1MYYKmaI3QRJF8VA1FZIdkQTMQ,1594
|
||||
virtualenv/version.py,sha256=3ieAw0XY11zpShwBdavzQZAO60AeVi5FVy0KWrcxwUY,66
|
||||
virtualenv/version.py,sha256=T9L0FIrWWe1IEvi_PNtZQcEIf_WbHAtFeLA1_hwZ07I,65
|
||||
virtualenv/activation/__init__.py,sha256=jLIERxJXMnHq2fH49RdWqBoaiASres4CTKMdUJOeos0,480
|
||||
virtualenv/activation/activator.py,sha256=CXomkRvhzcAeygYlDwQdDjfPyZQG85aBab5GIVQPv2M,1341
|
||||
virtualenv/activation/via_template.py,sha256=B88RGc0qoGc46DmKJmLJuzcCJU_iXWhdD93r6KLuYHQ,2204
|
||||
virtualenv/activation/via_template.py,sha256=U8LgH-lyTjXIQBUdbd0xOZpXNICpiKhsfpiZwzQg7tU,2372
|
||||
virtualenv/activation/bash/__init__.py,sha256=7aC1WfvyzgFrIQs13jOuESuAbuiAnTsKkOe0iReRoaE,312
|
||||
virtualenv/activation/bash/activate.sh,sha256=xkIDykLyI5CO3K7eeAujgPiBP2eleYDTFsqhaXsOUG4,2249
|
||||
virtualenv/activation/bash/activate.sh,sha256=aHia5vyXg2JwymkvRXCp29Aswcg88Mz5UrssXbX9Jjc,2398
|
||||
virtualenv/activation/batch/__init__.py,sha256=K0gVfwuXV7uoaMDL7moWGCq7uTDzI64giZzQQ8s2qnU,733
|
||||
virtualenv/activation/batch/activate.bat,sha256=PeQnWWsjvHT-jIWhYI7hbdzkDBZx5UOstnsCmq5PYtw,1031
|
||||
virtualenv/activation/batch/deactivate.bat,sha256=6OznnO-HC2wnWUN7YAT-bj815zeKMXEPC0keyBYwKUU,510
|
||||
@ -17,104 +17,106 @@ virtualenv/activation/cshell/activate.csh,sha256=jYwms8OTiVu9MJwXltuEm43HU09BJUq
|
||||
virtualenv/activation/fish/__init__.py,sha256=hDkJq1P1wK2qm6BXydXWA9GMkBpj-TaejbKSceFnGZU,251
|
||||
virtualenv/activation/fish/activate.fish,sha256=V7nVwSI_nsFEMlJjSQxCayNWkjubXi1KSgSw1bEakh8,3099
|
||||
virtualenv/activation/powershell/__init__.py,sha256=EA-73s5TUMkgxAhLwucFg3gsBwW5huNh7qB4I7uEU-U,256
|
||||
virtualenv/activation/powershell/activate.ps1,sha256=qXTD2IZIPXIr3HZbNahnym8l3FFwa1o_pyB8cSmxeg0,1867
|
||||
virtualenv/activation/powershell/activate.ps1,sha256=jVw_FwfVJzcByQ3Sku-wlnOo_a0-OSpAQ8R17kXVgIM,1807
|
||||
virtualenv/activation/python/__init__.py,sha256=Uv53LqOrIT_2dO1FXcUYAnwH1eypG8CJ2InhSx1GRI4,1323
|
||||
virtualenv/activation/python/activate_this.py,sha256=Xpz7exdGSjmWk0KfwHLofIpDPUtazNSNGrxT0-5ZG_s,1208
|
||||
virtualenv/activation/xonsh/__init__.py,sha256=7NUevd5EpHRMZdSyR1KgFTe9QQBO94zZOwFH6MR6zjo,355
|
||||
virtualenv/activation/xonsh/activate.xsh,sha256=qkKgWfrUjYKrgrmhf45VuBz99EMadtiNU8GMfHZZ7AU,1172
|
||||
virtualenv/app_data/__init__.py,sha256=mOgHrNxZ320NcDvl2EU9Uhaq9XSwnJwkldKAWtrMCKo,1882
|
||||
virtualenv/app_data/base.py,sha256=wtoduyV2lc020XNdOwt5gu1lkUJd0n_LMrgT8nifAwo,2054
|
||||
virtualenv/app_data/na.py,sha256=fCISMfJt3opkAqCmJBZTW9tody6ECfVPXtSrY5ZJueY,1321
|
||||
virtualenv/app_data/via_disk_folder.py,sha256=bJxZIXTAqQekwRZuoYgAE1fvwQ6w1dBR2IJFe09OIjE,5404
|
||||
virtualenv/app_data/via_tempdir.py,sha256=vt4I1wAaNouOeFSTFX5DPbA3zPZ1ikVGzXBDsNLNHRM,771
|
||||
virtualenv/app_data/__init__.py,sha256=nwgqY-Our_SYcDisLfRLmWrTSPytDkjck9-lzg-pOI8,1462
|
||||
virtualenv/app_data/base.py,sha256=dbS5Maob1-Cqs6EVqTmmbjAGeNYA1iw3pmdgYPWCJak,2129
|
||||
virtualenv/app_data/na.py,sha256=iMRVpCe4m5Q5WM5bC3ee1wYyfkfHvkcQ-8tgIw4druc,1306
|
||||
virtualenv/app_data/read_only.py,sha256=MD-4Bl2SZZiGw0g8qZy0YLBGZGCuFYXnAEvWboF1PSc,1006
|
||||
virtualenv/app_data/via_disk_folder.py,sha256=CdNXQkenyH178MtSs2Ve6uDUs30-oZpkOz_1guTtTz0,5597
|
||||
virtualenv/app_data/via_tempdir.py,sha256=Z_-PoU7qeZe-idzi3nqys4FX0rfsRgOQ9_7XwX3hxSA,770
|
||||
virtualenv/config/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57
|
||||
virtualenv/config/convert.py,sha256=msrkiG2Vq9gYQXf1C5W4n3b0ZTv6weFANV-mLUq6uMo,2091
|
||||
virtualenv/config/convert.py,sha256=WYGjMRKVriZkfTH3z1fI0sDQRZxCxAedqWbOGsaquyg,2693
|
||||
virtualenv/config/env_var.py,sha256=48XpOurSLLjMX-kXjvOpZuAoOUP-LvnbotTlmebhhFk,844
|
||||
virtualenv/config/ini.py,sha256=neMqXrA6IOkLF_M_MCQWQSeqNm4CT8tj_h3GdbJv1Cg,2783
|
||||
virtualenv/config/cli/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57
|
||||
virtualenv/config/cli/parser.py,sha256=y5IqHccLBqFpocpE75X611nVrP8v394VW94a9GAojvE,4524
|
||||
virtualenv/create/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57
|
||||
virtualenv/create/creator.py,sha256=D2YsK817anGhHxjh_ew7MlRCGjPPzW95lroRPlzblGk,8437
|
||||
virtualenv/create/creator.py,sha256=4jxxEGXCWd6tInT37QNt-13_yDtcIJdPB6EkoYzDkbM,8889
|
||||
virtualenv/create/debug.py,sha256=ETOke8w4Ib8fiufAHVeOkH3v0zrztljw3WjGvZyE0Mk,3342
|
||||
virtualenv/create/describe.py,sha256=bm0V2wpFOjdN_MkzZuJAEBSttmi5YGPVwxtwGYU5zQU,3561
|
||||
virtualenv/create/pyenv_cfg.py,sha256=VsOGfzUpaVCO3J29zrhIeip4jZ4b7llbe45iOQAIRGg,1717
|
||||
virtualenv/create/via_global_ref/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
virtualenv/create/via_global_ref/_virtualenv.py,sha256=aEuMB5MrpKhKwuWumv5J7wTpK6w9jUGR1FXPCdCT5fw,5662
|
||||
virtualenv/create/via_global_ref/api.py,sha256=uAQjwBRJ-u4d6A24QuxeB-khIrSGiP7-W_SQxNdE-Sk,4277
|
||||
virtualenv/create/via_global_ref/api.py,sha256=5MPq3XJBuUOBj53oIigeWWPm68M-J_E644WWbz37qOU,4357
|
||||
virtualenv/create/via_global_ref/store.py,sha256=cqLBEhQ979xHnlidqmxlDjsvj2Wr-mBo7shvGQSEBxU,685
|
||||
virtualenv/create/via_global_ref/venv.py,sha256=A6XrGu3oco_ZIHv0s-TybW7lErAomgLOYDMtgpdACc0,2919
|
||||
virtualenv/create/via_global_ref/venv.py,sha256=p5RkDcXhr1pmOwnl1dpS06UYHmfNVy2ld4sTwsYjYWU,2955
|
||||
virtualenv/create/via_global_ref/builtin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
virtualenv/create/via_global_ref/builtin/builtin_way.py,sha256=hO22nT-itVoYiy8wXrXXYzHw86toCp_Uq-cURR7w6ck,546
|
||||
virtualenv/create/via_global_ref/builtin/ref.py,sha256=-r9sJSW9X9rHxThk2yyJJRA5KkmJPW_axuffYBsFDIU,5501
|
||||
virtualenv/create/via_global_ref/builtin/via_global_self_do.py,sha256=9aH07lmA6SMvtynv7ZTO6Gh2aDDFdUiDQrlbtT9xze4,4057
|
||||
virtualenv/create/via_global_ref/builtin/ref.py,sha256=xCTICJhE-OiopBxl6ymo1P1NqgK3KEF8ZUOtQDtDTVA,5477
|
||||
virtualenv/create/via_global_ref/builtin/via_global_self_do.py,sha256=d569fX7fjq5vHvGGXDjo-1Xi__HhqU2xjDJOuYrmGjw,4552
|
||||
virtualenv/create/via_global_ref/builtin/cpython/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57
|
||||
virtualenv/create/via_global_ref/builtin/cpython/common.py,sha256=_ycHGl1I4Pr7RfsXlUP0otJw9VQ0L744lTpPTTxPo6w,1909
|
||||
virtualenv/create/via_global_ref/builtin/cpython/common.py,sha256=U7EvB9-2DlOQTGrTyPrEcItEbJ1sFBzo1EAOcAIjQ5Q,2392
|
||||
virtualenv/create/via_global_ref/builtin/cpython/cpython2.py,sha256=p41H2g6wAqhJzeUU48nH3u05-yWEbwCzhyj4pn8rnm4,3757
|
||||
virtualenv/create/via_global_ref/builtin/cpython/cpython3.py,sha256=9sY098at5Wp1Fhu1Aux1y06wH2ecbGj3bRucl4CGSQY,2473
|
||||
virtualenv/create/via_global_ref/builtin/cpython/mac_os.py,sha256=Hc9FVoQPuf8IV5j17LVj49lH7nyCep2nh_lWlZm49YI,12318
|
||||
virtualenv/create/via_global_ref/builtin/cpython/cpython3.py,sha256=gguQAhTQb0PH7Xg-G-mgQm5LlhyyW0V0piV3LwI-PeM,3111
|
||||
virtualenv/create/via_global_ref/builtin/cpython/mac_os.py,sha256=B0Lqgo8geZBSKSpHWUB46lDYRggW4Kg2AZUp3Z7xn9M,12382
|
||||
virtualenv/create/via_global_ref/builtin/pypy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
virtualenv/create/via_global_ref/builtin/pypy/common.py,sha256=KagqBNEuysqqO-n-VCCpuMvBK8MiZFMJQRWbWW12c6g,1696
|
||||
virtualenv/create/via_global_ref/builtin/pypy/common.py,sha256=-t-TZxCTJwpIh_oRsDyv5IilH19jKqJrZa27zWN_8Ws,1816
|
||||
virtualenv/create/via_global_ref/builtin/pypy/pypy2.py,sha256=bmMY_KJZ1iD_ifq-X9ZBOlOpJ1aN7839qigBgnWRIdA,3535
|
||||
virtualenv/create/via_global_ref/builtin/pypy/pypy3.py,sha256=ti6hmOIC4HiTBnEYKytO-d9wH-eLeMoQxQ0kZRhnNrw,1751
|
||||
virtualenv/create/via_global_ref/builtin/python2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
virtualenv/create/via_global_ref/builtin/python2/python2.py,sha256=jkJwmkeJVTzwzo95eMIptTfdBA-qmyIqZcpt48iOitU,4276
|
||||
virtualenv/create/via_global_ref/builtin/python2/site.py,sha256=mp-Y1VLSXqhIeOojQefy8ffIylWqfq20jEfc2UwMTYU,6120
|
||||
virtualenv/create/via_global_ref/builtin/python2/site.py,sha256=4uguJDuWPmB25yBmpsMYKLOnIVXkerck0UO8CP8F2c4,6078
|
||||
virtualenv/discovery/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57
|
||||
virtualenv/discovery/builtin.py,sha256=1c4Py9DnkiCLrbHp7bffvQtJI9HkxfVyFedt6IFMKEs,5079
|
||||
virtualenv/discovery/cached_py_info.py,sha256=vQiAFDoBjR13zrdmc5q97z4upBxWzUG6H6IHJZjqjeU,5007
|
||||
virtualenv/discovery/builtin.py,sha256=rB6XaQwuK1HfvJsrla3BoSQUH9QkJnwKHGWBdbK4QGM,5432
|
||||
virtualenv/discovery/cached_py_info.py,sha256=l2lELE8YkwKXCNopImY2VjmpHPTawh1d3qmdsXMtkRs,5043
|
||||
virtualenv/discovery/discover.py,sha256=evJYn4APkwjNmdolNeIBSHiOudkvN59c5oVYI2Zsjlg,1209
|
||||
virtualenv/discovery/py_info.py,sha256=PMbQIitL6ELOJpAZF3rrMxPxM8oOmTK9aDvb4YHTDEw,21783
|
||||
virtualenv/discovery/py_info.py,sha256=QtZFq0xav1tEpKI5seEJaEOkc_FXer21Gzgl_Ccqy98,21793
|
||||
virtualenv/discovery/py_spec.py,sha256=wQhLzCfXoSPsAAO9nm5-I2lNolVDux4W2vPSUfJGjlc,4790
|
||||
virtualenv/discovery/windows/__init__.py,sha256=TPbnzCtRyw47pRVHTO8ikwljNcczxmSLDdWtwasxvQU,1036
|
||||
virtualenv/discovery/windows/pep514.py,sha256=YYiaJzo-XuMtO78BMFMAudqkeJiLQkFnUTOuQZ5lJz8,5451
|
||||
virtualenv/run/__init__.py,sha256=REhXScKzirtvWjFpTZdepZCKIxcjsRHZtt3q5mDsrMQ,5771
|
||||
virtualenv/run/session.py,sha256=mzXJyVQlXXgj_kO9IJDor44Co7WKiyFGnZ0mCTIy5x0,2547
|
||||
virtualenv/run/__init__.py,sha256=lVIiIq_LoMHUGYkrTSx0tpFG_aYywy_u6GWUReHRcUA,5777
|
||||
virtualenv/run/session.py,sha256=S4NZiHzij1vp895mN9s9ZwYobJjjdP37QOHCb1o-Ufo,2563
|
||||
virtualenv/run/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
virtualenv/run/plugin/activators.py,sha256=kmHShj36eHfbnsiAJzX0U5LYvGhe0WkRYjbuKDz6gVM,2117
|
||||
virtualenv/run/plugin/base.py,sha256=-2185C01PaxOG7gnMbWWyZlo24n_FYo5J5_naeNZw8s,1934
|
||||
virtualenv/run/plugin/creators.py,sha256=5L7G5mk2GIOIaZVvDZszd2VVBSUM3jkAR4aBO0OkOXY,3517
|
||||
virtualenv/run/plugin/discovery.py,sha256=ba9szD21er0-AkuMXrdFOjFEDsIekRWljXdXkj_-8EM,994
|
||||
virtualenv/run/plugin/seeders.py,sha256=XVKaikuOC4JUO4lirHzowEJ6d0pI1pFfywCx3heE70g,1026
|
||||
virtualenv/run/plugin/creators.py,sha256=PIxJ85KmrQU7lUO-r8Znxbb4lTEzwHggc9lcDqmt2tc,3494
|
||||
virtualenv/run/plugin/discovery.py,sha256=3ykxRvPA1FJMkqsbr2TV0LBRPT5UCFeJdzEHfuEjxRM,1002
|
||||
virtualenv/run/plugin/seeders.py,sha256=c1mhzu0HNzKdif6YUV35fuAOS0XHFJz3TtccLW5fWG0,1074
|
||||
virtualenv/seed/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57
|
||||
virtualenv/seed/seeder.py,sha256=DSGE_8Ycj01vj8mkppUBA9h7JG76XsVBMt-5MWlMF6k,1178
|
||||
virtualenv/seed/embed/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
virtualenv/seed/embed/base_embed.py,sha256=j4qcALcc-ylU0bKjVxiELPqk4MJ8f0pmbe_lVYVH_5Q,4166
|
||||
virtualenv/seed/embed/base_embed.py,sha256=46mWtqWj_MjOQEqMJyosL0RWGL6HwrHAL2r1Jxc9DuI,4182
|
||||
virtualenv/seed/embed/pip_invoke.py,sha256=EMVwIeoW15SuorJ8z_-vBxPXwQJLS0ILA0Va9zNoOLI,2127
|
||||
virtualenv/seed/embed/via_app_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
virtualenv/seed/embed/via_app_data/via_app_data.py,sha256=quofMFCWc-OxvxdAJwZTWS5mOugnYB7wRqSJZxmkl-E,6053
|
||||
virtualenv/seed/embed/via_app_data/via_app_data.py,sha256=NkVhEFv4iuKG0qvEg4AAmucMwmQgNaPLB-Syepzgps0,5994
|
||||
virtualenv/seed/embed/via_app_data/pip_install/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
virtualenv/seed/embed/via_app_data/pip_install/base.py,sha256=rnR60JzM7G04cPDo2eH-aR8-iQuFXBgHJ2lQnSf0Gfs,6355
|
||||
virtualenv/seed/embed/via_app_data/pip_install/copy.py,sha256=gG2NePFHOYh-bsCf6TpsaQ_qrYhdBy67k0RWuwHSAwo,1307
|
||||
virtualenv/seed/embed/via_app_data/pip_install/symlink.py,sha256=wHCpfKobvjjaZLUSwM3FSCblZfiBFw4IQYsxwlfEEu0,2362
|
||||
virtualenv/seed/wheels/__init__.py,sha256=1J7el7lNjAwGxM4dmricrbVhSbYxs5sPzv9PTx2A6qA,226
|
||||
virtualenv/seed/wheels/acquire.py,sha256=Iq_QPJgUPCyHfrS3t2EUUj8fieymfcKNve1JbJQ5Uyc,4420
|
||||
virtualenv/seed/wheels/bundle.py,sha256=xYbhh5nQEwec2vnqNJWNVtDL3VyjGkgDWVXSuXzXB-Y,1961
|
||||
virtualenv/seed/wheels/periodic_update.py,sha256=A9l7ZpjtWzGrq2nh39y8g5OppUryHb7_W3bCR7TAnPc,12756
|
||||
virtualenv/seed/wheels/acquire.py,sha256=qchqlIynLi2VP2VtdAfVfZJHbUPcLY2Ui5r7Eh-aZz8,4426
|
||||
virtualenv/seed/wheels/bundle.py,sha256=W0uVjClv9IBa50jRvPKm0jMwWnrYTEfDny2Z6bw2W7c,1835
|
||||
virtualenv/seed/wheels/periodic_update.py,sha256=HNVEuU2OYdWHW7lVO0h3NkpLkC8bu-5R7igJRXBnGDc,12792
|
||||
virtualenv/seed/wheels/util.py,sha256=Zdo76KEDqbNmM5u9JTuyu5uzEN_fQ4oj6qHOt0h0o1M,3960
|
||||
virtualenv/seed/wheels/embed/__init__.py,sha256=qc4QGDYH6J4ikiW1GPSkgjpapQDB7TpPd6TTr21jvbU,1995
|
||||
virtualenv/seed/wheels/embed/__init__.py,sha256=CLMKoeveDRyiNAdZjEtD38cepgNXkg65xzFu5OSHEus,1995
|
||||
virtualenv/seed/wheels/embed/pip-19.1.1-py2.py3-none-any.whl,sha256=mTE08EdUcbkUUsoCnUOQ3I8pisY6cSgU8QHNG220ZnY,1360957
|
||||
virtualenv/seed/wheels/embed/pip-20.2.2-py2.py3-none-any.whl,sha256=UkTlFJT10d-7idpJLUJQywf5JGZEc20Q7WxF3rGkhQA,1503623
|
||||
virtualenv/seed/wheels/embed/pip-20.3.1-py2.py3-none-any.whl,sha256=Ql55sgk5q7_6djOpEVGogq7cd1ZNkxPjWE6wQWwoxVg,1518513
|
||||
virtualenv/seed/wheels/embed/setuptools-43.0.0-py2.py3-none-any.whl,sha256=pn-qUVGe8ozYJhr_DiIbbkw3D4-4utqKo-etiUUZmWM,583228
|
||||
virtualenv/seed/wheels/embed/setuptools-44.1.1-py2.py3-none-any.whl,sha256=J6cUwJJTE05gpvpoEw94xwN-VWLE8h-PMY8q6QDRUtU,583493
|
||||
virtualenv/seed/wheels/embed/setuptools-49.6.0-py3-none-any.whl,sha256=TdW7CgoM_3e0bKXdOoSFfuSMg-giOIa1VmE8ckmUBz8,803275
|
||||
virtualenv/seed/wheels/embed/setuptools-50.3.2-py3-none-any.whl,sha256=LCQqCFb7rX775WDfSnrdkyTzQM9I30NlHpYEkkRmeUo,785194
|
||||
virtualenv/seed/wheels/embed/setuptools-51.0.0-py3-none-any.whl,sha256=jBd5NiFZRcmjfvgJraD6s2UZGVL3oSNhhDK7-sNTxSk,785164
|
||||
virtualenv/seed/wheels/embed/wheel-0.33.6-py2.py3-none-any.whl,sha256=9NoXY9O-zy4s2SoUp8kg8PAOyjD93p6pksg2aFufryg,21556
|
||||
virtualenv/seed/wheels/embed/wheel-0.35.1-py2.py3-none-any.whl,sha256=SXrdU1JdFsFzwsHHM7j2VVEOkJ6njMDinTdCQ1RLd6I,33174
|
||||
virtualenv/seed/wheels/embed/wheel-0.36.1-py2.py3-none-any.whl,sha256=kGhk-3IsCrXy-cNbLGXjrzwAlALBCKcJwKyie8LJGHs,34788
|
||||
virtualenv/util/__init__.py,sha256=om6Hs2lH5igf5lkcSmQFiU7iMZ0Wx4dmSlMc6XW_Llg,199
|
||||
virtualenv/util/error.py,sha256=SRSZlXvMYQuJwxoUfNhlAyo3VwrAnIsZemSwPOxpjns,352
|
||||
virtualenv/util/lock.py,sha256=AyYqRMsz5YnLNDLNTrutjLqS8m0lkLqNNDpxW565b44,3550
|
||||
virtualenv/util/lock.py,sha256=oFa0FcbE_TVDHOol44Mgtfa4D3ZjnVy-HSQx-y7ERKQ,4727
|
||||
virtualenv/util/six.py,sha256=_8KWXUWi3-AaFmz4LkdyNra-uNuf70vlxwjN7oeRo8g,1463
|
||||
virtualenv/util/zipapp.py,sha256=jtf4Vn7XBnjPs_B_ObIQv_x4pFlIlPKAWHYLFV59h6U,1054
|
||||
virtualenv/util/path/__init__.py,sha256=YaBAxtzGBdMu0uUtppe0ZeCHw5HhO-5zjeb3-fzyMoI,336
|
||||
virtualenv/util/path/_permission.py,sha256=XpO2vGAk_92_biD4MEQcAQq2Zc8_rpm3M3n_hMUA1rw,745
|
||||
virtualenv/util/path/_sync.py,sha256=7oEmxJB5fc7NIsVgPJTJ4mpVPjNaNHAdhqlgIFSDfm0,2370
|
||||
virtualenv/util/path/_pathlib/__init__.py,sha256=evaey395zOuDc3FlukUeJ8SzRqLx1xWOKmg-TEPsRd4,1446
|
||||
virtualenv/util/path/_pathlib/via_os_path.py,sha256=wlnf0MIktEP01kG9z8iKOI86levXmkX7UX1LMLK7A-E,3701
|
||||
virtualenv/util/subprocess/__init__.py,sha256=2H-ZQ74OKq60eSpxfRWD-8gVUydczkrKSexl18DzOXI,753
|
||||
virtualenv/util/subprocess/_win_subprocess.py,sha256=0-eJVcxBs1Fe76OVTQnUVLaLzB4tlJxEZ-vZECQ4xL4,5576
|
||||
virtualenv-20.0.31.dist-info/LICENSE,sha256=XBWRk3jFsqqrexnOpw2M3HX3aHnjJFTkwDmfi3HRcek,1074
|
||||
virtualenv-20.0.31.dist-info/METADATA,sha256=Pwhk7KR7q09ZjMUtWXYwzvuWD1mY4hxS1e9eqpsjRs8,4923
|
||||
virtualenv-20.0.31.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110
|
||||
virtualenv-20.0.31.dist-info/entry_points.txt,sha256=1DALKzYOcffJa7Q15TQlMQu0yeFXEy5W124y0aJEfYU,1615
|
||||
virtualenv-20.0.31.dist-info/top_level.txt,sha256=JV-LVlC8YeIw1DgiYI0hEot7tgFy5IWdKVcSG7NyzaI,11
|
||||
virtualenv-20.0.31.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
||||
virtualenv-20.0.31.dist-info/RECORD,,
|
||||
virtualenv/util/path/_sync.py,sha256=rheUrGsCqmhMwNs-uc5rDthNSUlsOrBJPoK8KZj3O1o,2393
|
||||
virtualenv/util/path/_pathlib/__init__.py,sha256=FjKCi8scB5MnHg2fLX5REoE0bOPkMXqpBEILVTeJZGQ,2130
|
||||
virtualenv/util/path/_pathlib/via_os_path.py,sha256=fYDFAX483zVvC9hAOAC9FYtrGdZethS0vtYtKsL5r-s,3772
|
||||
virtualenv/util/subprocess/__init__.py,sha256=1UmFrdBv2sVeUfZbDcO2yZpe28AE0ULOu9dRKlpJaa0,801
|
||||
virtualenv/util/subprocess/_win_subprocess.py,sha256=SChkXAKVbpehyrHod1ld76RSdTIalrgME1rtz5jUfm0,5655
|
||||
virtualenv-20.2.2.dist-info/LICENSE,sha256=XBWRk3jFsqqrexnOpw2M3HX3aHnjJFTkwDmfi3HRcek,1074
|
||||
virtualenv-20.2.2.dist-info/METADATA,sha256=OWyC_GXU3AvST-YiGhmI2iE4ntdcBm-6Q1yCaU9Bx_U,4965
|
||||
virtualenv-20.2.2.dist-info/WHEEL,sha256=oh0NKYrTcu1i1-wgrI1cnhkjYIi8WJ-8qd9Jrr5_y4E,110
|
||||
virtualenv-20.2.2.dist-info/entry_points.txt,sha256=1DALKzYOcffJa7Q15TQlMQu0yeFXEy5W124y0aJEfYU,1615
|
||||
virtualenv-20.2.2.dist-info/top_level.txt,sha256=JV-LVlC8YeIw1DgiYI0hEot7tgFy5IWdKVcSG7NyzaI,11
|
||||
virtualenv-20.2.2.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
||||
virtualenv-20.2.2.dist-info/RECORD,,
|
6
third_party/python/virtualenv/virtualenv-20.2.2.dist-info/WHEEL
vendored
Normal file
6
third_party/python/virtualenv/virtualenv-20.2.2.dist-info/WHEEL
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.36.1)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
@ -47,6 +47,9 @@ deactivate () {
|
||||
deactivate nondestructive
|
||||
|
||||
VIRTUAL_ENV='__VIRTUAL_ENV__'
|
||||
if ([ "$OSTYPE" = "cygwin" ] || [ "$OSTYPE" = "msys" ]) && $(command -v cygpath &> /dev/null) ; then
|
||||
VIRTUAL_ENV=$(cygpath -u "$VIRTUAL_ENV")
|
||||
fi
|
||||
export VIRTUAL_ENV
|
||||
|
||||
_OLD_VIRTUAL_PATH="$PATH"
|
||||
|
@ -1,60 +1,60 @@
|
||||
$script:THIS_PATH = $myinvocation.mycommand.path
|
||||
$script:BASE_DIR = Split-Path (Resolve-Path "$THIS_PATH/..") -Parent
|
||||
|
||||
function global:deactivate([switch] $NonDestructive) {
|
||||
if (Test-Path variable:_OLD_VIRTUAL_PATH) {
|
||||
$env:PATH = $variable:_OLD_VIRTUAL_PATH
|
||||
Remove-Variable "_OLD_VIRTUAL_PATH" -Scope global
|
||||
}
|
||||
|
||||
if (Test-Path function:_old_virtual_prompt) {
|
||||
$function:prompt = $function:_old_virtual_prompt
|
||||
Remove-Item function:\_old_virtual_prompt
|
||||
}
|
||||
|
||||
if ($env:VIRTUAL_ENV) {
|
||||
Remove-Item env:VIRTUAL_ENV -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
if (!$NonDestructive) {
|
||||
# Self destruct!
|
||||
Remove-Item function:deactivate
|
||||
Remove-Item function:pydoc
|
||||
}
|
||||
}
|
||||
|
||||
function global:pydoc {
|
||||
python -m pydoc $args
|
||||
}
|
||||
|
||||
# unset irrelevant variables
|
||||
deactivate -nondestructive
|
||||
|
||||
$VIRTUAL_ENV = $BASE_DIR
|
||||
$env:VIRTUAL_ENV = $VIRTUAL_ENV
|
||||
|
||||
New-Variable -Scope global -Name _OLD_VIRTUAL_PATH -Value $env:PATH
|
||||
|
||||
$env:PATH = "$env:VIRTUAL_ENV/__BIN_NAME____PATH_SEP__" + $env:PATH
|
||||
if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) {
|
||||
function global:_old_virtual_prompt {
|
||||
""
|
||||
}
|
||||
$function:_old_virtual_prompt = $function:prompt
|
||||
|
||||
if ("__VIRTUAL_PROMPT__" -ne "") {
|
||||
function global:prompt {
|
||||
# Add the custom prefix to the existing prompt
|
||||
$previous_prompt_value = & $function:_old_virtual_prompt
|
||||
("__VIRTUAL_PROMPT__" + $previous_prompt_value)
|
||||
}
|
||||
}
|
||||
else {
|
||||
function global:prompt {
|
||||
# Add a prefix to the current prompt, but don't discard it.
|
||||
$previous_prompt_value = & $function:_old_virtual_prompt
|
||||
$new_prompt_value = "($( Split-Path $env:VIRTUAL_ENV -Leaf )) "
|
||||
($new_prompt_value + $previous_prompt_value)
|
||||
}
|
||||
}
|
||||
}
|
||||
$script:THIS_PATH = $myinvocation.mycommand.path
|
||||
$script:BASE_DIR = Split-Path (Resolve-Path "$THIS_PATH/..") -Parent
|
||||
|
||||
function global:deactivate([switch] $NonDestructive) {
|
||||
if (Test-Path variable:_OLD_VIRTUAL_PATH) {
|
||||
$env:PATH = $variable:_OLD_VIRTUAL_PATH
|
||||
Remove-Variable "_OLD_VIRTUAL_PATH" -Scope global
|
||||
}
|
||||
|
||||
if (Test-Path function:_old_virtual_prompt) {
|
||||
$function:prompt = $function:_old_virtual_prompt
|
||||
Remove-Item function:\_old_virtual_prompt
|
||||
}
|
||||
|
||||
if ($env:VIRTUAL_ENV) {
|
||||
Remove-Item env:VIRTUAL_ENV -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
if (!$NonDestructive) {
|
||||
# Self destruct!
|
||||
Remove-Item function:deactivate
|
||||
Remove-Item function:pydoc
|
||||
}
|
||||
}
|
||||
|
||||
function global:pydoc {
|
||||
python -m pydoc $args
|
||||
}
|
||||
|
||||
# unset irrelevant variables
|
||||
deactivate -nondestructive
|
||||
|
||||
$VIRTUAL_ENV = $BASE_DIR
|
||||
$env:VIRTUAL_ENV = $VIRTUAL_ENV
|
||||
|
||||
New-Variable -Scope global -Name _OLD_VIRTUAL_PATH -Value $env:PATH
|
||||
|
||||
$env:PATH = "$env:VIRTUAL_ENV/__BIN_NAME____PATH_SEP__" + $env:PATH
|
||||
if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) {
|
||||
function global:_old_virtual_prompt {
|
||||
""
|
||||
}
|
||||
$function:_old_virtual_prompt = $function:prompt
|
||||
|
||||
if ("__VIRTUAL_PROMPT__" -ne "") {
|
||||
function global:prompt {
|
||||
# Add the custom prefix to the existing prompt
|
||||
$previous_prompt_value = & $function:_old_virtual_prompt
|
||||
("__VIRTUAL_PROMPT__" + $previous_prompt_value)
|
||||
}
|
||||
}
|
||||
else {
|
||||
function global:prompt {
|
||||
# Add a prefix to the current prompt, but don't discard it.
|
||||
$previous_prompt_value = & $function:_old_virtual_prompt
|
||||
$new_prompt_value = "($( Split-Path $env:VIRTUAL_ENV -Leaf )) "
|
||||
($new_prompt_value + $previous_prompt_value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ from virtualenv.util.six import ensure_text
|
||||
from .activator import Activator
|
||||
|
||||
if sys.version_info >= (3, 7):
|
||||
from importlib.resources import read_text
|
||||
from importlib.resources import read_binary
|
||||
else:
|
||||
from importlib_resources import read_text
|
||||
from importlib_resources import read_binary
|
||||
|
||||
|
||||
@add_metaclass(ABCMeta)
|
||||
@ -44,7 +44,8 @@ class ViaTemplateActivator(Activator):
|
||||
for template in templates:
|
||||
text = self.instantiate_template(replacements, template, creator)
|
||||
dest = to_folder / self.as_name(template)
|
||||
dest.write_text(text, encoding="utf-8")
|
||||
# use write_bytes to avoid platform specific line normalization (\n -> \r\n)
|
||||
dest.write_bytes(text.encode("utf-8"))
|
||||
generated.append(dest)
|
||||
return generated
|
||||
|
||||
@ -52,8 +53,9 @@ class ViaTemplateActivator(Activator):
|
||||
return template.name
|
||||
|
||||
def instantiate_template(self, replacements, template, creator):
|
||||
# read text and do replacements
|
||||
text = read_text(self.__module__, str(template), encoding="utf-8", errors="strict")
|
||||
# read content as binary to avoid platform specific line normalization (\n -> \r\n)
|
||||
binary = read_binary(self.__module__, str(template))
|
||||
text = binary.decode("utf-8", errors="strict")
|
||||
for key, value in replacements.items():
|
||||
value = self._repr_unicode(creator, value)
|
||||
text = text.replace(key, value)
|
||||
|
@ -5,58 +5,53 @@ from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import logging
|
||||
import os
|
||||
from argparse import Action, ArgumentError
|
||||
|
||||
from appdirs import user_data_dir
|
||||
|
||||
from .na import AppDataDisabled
|
||||
from .read_only import ReadOnlyAppData
|
||||
from .via_disk_folder import AppDataDiskFolder
|
||||
from .via_tempdir import TempAppData
|
||||
|
||||
|
||||
class AppDataAction(Action):
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
folder = self._check_folder(values)
|
||||
if folder is None:
|
||||
raise ArgumentError("app data path {} is not valid".format(values))
|
||||
setattr(namespace, self.dest, AppDataDiskFolder(folder))
|
||||
def _default_app_data_dir(): # type: () -> str
|
||||
key = str("VIRTUALENV_OVERRIDE_APP_DATA")
|
||||
if key in os.environ:
|
||||
return os.environ[key]
|
||||
else:
|
||||
return user_data_dir(appname="virtualenv", appauthor="pypa")
|
||||
|
||||
@staticmethod
|
||||
def _check_folder(folder):
|
||||
folder = os.path.abspath(folder)
|
||||
if not os.path.exists(folder):
|
||||
try:
|
||||
os.makedirs(folder)
|
||||
logging.debug("created app data folder %s", folder)
|
||||
except OSError as exception:
|
||||
logging.info("could not create app data folder %s due to %r", folder, exception)
|
||||
return None
|
||||
write_enabled = os.access(folder, os.W_OK)
|
||||
if write_enabled:
|
||||
return folder
|
||||
|
||||
def make_app_data(folder, **kwargs):
|
||||
read_only = kwargs.pop("read_only")
|
||||
if kwargs: # py3+ kwonly
|
||||
raise TypeError("unexpected keywords: {}")
|
||||
|
||||
if folder is None:
|
||||
folder = _default_app_data_dir()
|
||||
folder = os.path.abspath(folder)
|
||||
|
||||
if read_only:
|
||||
return ReadOnlyAppData(folder)
|
||||
|
||||
if not os.path.isdir(folder):
|
||||
try:
|
||||
os.makedirs(folder)
|
||||
logging.debug("created app data folder %s", folder)
|
||||
except OSError as exception:
|
||||
logging.info("could not create app data folder %s due to %r", folder, exception)
|
||||
|
||||
if os.access(folder, os.W_OK):
|
||||
return AppDataDiskFolder(folder)
|
||||
else:
|
||||
logging.debug("app data folder %s has no write access", folder)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def default():
|
||||
for folder in AppDataAction._app_data_candidates():
|
||||
folder = AppDataAction._check_folder(folder)
|
||||
if folder is not None:
|
||||
return AppDataDiskFolder(folder)
|
||||
return AppDataDisabled()
|
||||
|
||||
@staticmethod
|
||||
def _app_data_candidates():
|
||||
key = str("VIRTUALENV_OVERRIDE_APP_DATA")
|
||||
if key in os.environ:
|
||||
yield os.environ[key]
|
||||
else:
|
||||
yield user_data_dir(appname="virtualenv", appauthor="pypa")
|
||||
return TempAppData()
|
||||
|
||||
|
||||
__all__ = (
|
||||
"AppDataDiskFolder",
|
||||
"TempAppData",
|
||||
"AppDataAction",
|
||||
"AppDataDisabled",
|
||||
"AppDataDiskFolder",
|
||||
"ReadOnlyAppData",
|
||||
"TempAppData",
|
||||
"make_app_data",
|
||||
)
|
||||
|
@ -31,6 +31,10 @@ class AppData(object):
|
||||
def py_info_clear(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def can_update(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def embed_update_log(self, distribution, for_py_version):
|
||||
raise NotImplementedError
|
||||
|
@ -8,6 +8,9 @@ from .base import AppData, ContentStore
|
||||
class AppDataDisabled(AppData):
|
||||
"""No application cache available (most likely as we don't have write permissions)"""
|
||||
|
||||
transient = True
|
||||
can_update = False
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@ -40,10 +43,6 @@ class AppDataDisabled(AppData):
|
||||
def wheel_image(self, for_py_version, name):
|
||||
raise self.error
|
||||
|
||||
@property
|
||||
def transient(self):
|
||||
return True
|
||||
|
||||
def py_info_clear(self):
|
||||
""""""
|
||||
|
||||
|
34
third_party/python/virtualenv/virtualenv/app_data/read_only.py
vendored
Normal file
34
third_party/python/virtualenv/virtualenv/app_data/read_only.py
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
import os.path
|
||||
|
||||
from virtualenv.util.lock import NoOpFileLock
|
||||
|
||||
from .via_disk_folder import AppDataDiskFolder, PyInfoStoreDisk
|
||||
|
||||
|
||||
class ReadOnlyAppData(AppDataDiskFolder):
|
||||
can_update = False
|
||||
|
||||
def __init__(self, folder): # type: (str) -> None
|
||||
if not os.path.isdir(folder):
|
||||
raise RuntimeError("read-only app data directory {} does not exist".format(folder))
|
||||
self.lock = NoOpFileLock(folder)
|
||||
|
||||
def reset(self): # type: () -> None
|
||||
raise RuntimeError("read-only app data does not support reset")
|
||||
|
||||
def py_info_clear(self): # type: () -> None
|
||||
raise NotImplementedError
|
||||
|
||||
def py_info(self, path):
|
||||
return _PyInfoStoreDiskReadOnly(self.py_info_at, path)
|
||||
|
||||
def embed_update_log(self, distribution, for_py_version):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class _PyInfoStoreDiskReadOnly(PyInfoStoreDisk):
|
||||
def write(self, content):
|
||||
raise RuntimeError("read-only app data python info cannot be updated")
|
||||
|
||||
|
||||
__all__ = ("ReadOnlyAppData",)
|
@ -46,15 +46,17 @@ class AppDataDiskFolder(AppData):
|
||||
Store the application data on the disk within a folder layout.
|
||||
"""
|
||||
|
||||
transient = False
|
||||
can_update = True
|
||||
|
||||
def __init__(self, folder):
|
||||
self.lock = ReentrantFileLock(folder)
|
||||
|
||||
def __repr__(self):
|
||||
return "{}".format(self.lock.path)
|
||||
return "{}({})".format(type(self).__name__, self.lock.path)
|
||||
|
||||
@property
|
||||
def transient(self):
|
||||
return False
|
||||
def __str__(self):
|
||||
return str(self.lock.path)
|
||||
|
||||
def reset(self):
|
||||
logging.debug("reset app data folder %s", self.lock.path)
|
||||
@ -137,7 +139,10 @@ class JSONStoreDisk(ContentStore):
|
||||
except Exception: # noqa
|
||||
pass
|
||||
if bad_format:
|
||||
self.remove()
|
||||
try:
|
||||
self.remove()
|
||||
except OSError: # reading and writing on the same file may cause race on multiple processes
|
||||
pass
|
||||
return None
|
||||
|
||||
def remove(self):
|
||||
@ -151,10 +156,7 @@ class JSONStoreDisk(ContentStore):
|
||||
|
||||
def write(self, content):
|
||||
folder = self.file.parent
|
||||
try:
|
||||
folder.mkdir(parents=True, exist_ok=True)
|
||||
except OSError:
|
||||
pass
|
||||
folder.mkdir(parents=True, exist_ok=True)
|
||||
self.file.write_text(ensure_text(json.dumps(content, sort_keys=True, indent=2)))
|
||||
logging.debug("wrote {} at %s".format(self.msg), *self.msg_args)
|
||||
|
||||
@ -168,5 +170,8 @@ class PyInfoStoreDisk(JSONStoreDisk):
|
||||
class EmbedDistributionUpdateStoreDisk(JSONStoreDisk):
|
||||
def __init__(self, in_folder, distribution):
|
||||
super(EmbedDistributionUpdateStoreDisk, self).__init__(
|
||||
in_folder, distribution, "embed update of distribution %s", (distribution,),
|
||||
in_folder,
|
||||
distribution,
|
||||
"embed update of distribution %s",
|
||||
(distribution,),
|
||||
)
|
||||
|
@ -9,6 +9,9 @@ from .via_disk_folder import AppDataDiskFolder
|
||||
|
||||
|
||||
class TempAppData(AppDataDiskFolder):
|
||||
transient = True
|
||||
can_update = False
|
||||
|
||||
def __init__(self):
|
||||
super(TempAppData, self).__init__(folder=mkdtemp())
|
||||
logging.debug("created temporary app data folder %s", self.lock.path)
|
||||
@ -21,8 +24,4 @@ class TempAppData(AppDataDiskFolder):
|
||||
safe_delete(self.lock.path)
|
||||
|
||||
def embed_update_log(self, distribution, for_py_version):
|
||||
return None
|
||||
|
||||
@property
|
||||
def transient(self):
|
||||
return True
|
||||
raise NotImplementedError
|
||||
|
@ -46,9 +46,7 @@ class ListType(TypeData):
|
||||
""""""
|
||||
|
||||
def convert(self, value, flatten=True):
|
||||
if isinstance(value, (str, bytes)):
|
||||
value = filter(None, [x.strip() for x in value.splitlines()])
|
||||
values = list(value)
|
||||
values = self.split_values(value)
|
||||
result = []
|
||||
for value in values:
|
||||
sub_values = value.split(os.pathsep)
|
||||
@ -56,6 +54,25 @@ class ListType(TypeData):
|
||||
converted = [self.as_type(i) for i in result]
|
||||
return converted
|
||||
|
||||
def split_values(self, value):
|
||||
"""Split the provided value into a list.
|
||||
|
||||
First this is done by newlines. If there were no newlines in the text,
|
||||
then we next try to split by comma.
|
||||
"""
|
||||
if isinstance(value, (str, bytes)):
|
||||
# Use `splitlines` rather than a custom check for whether there is
|
||||
# more than one line. This ensures that the full `splitlines()`
|
||||
# logic is supported here.
|
||||
values = value.splitlines()
|
||||
if len(values) <= 1:
|
||||
values = value.split(",")
|
||||
values = filter(None, [x.strip() for x in values])
|
||||
else:
|
||||
values = list(value)
|
||||
|
||||
return values
|
||||
|
||||
|
||||
def convert(value, as_type, source):
|
||||
"""Convert the value as a given type where the value comes from the given source"""
|
||||
|
@ -44,6 +44,7 @@ class Creator(object):
|
||||
self._debug = None
|
||||
self.dest = Path(options.dest)
|
||||
self.clear = options.clear
|
||||
self.no_vcs_ignore = options.no_vcs_ignore
|
||||
self.pyenv_cfg = PyEnvCfg.from_folder(self.dest)
|
||||
self.app_data = options.app_data
|
||||
|
||||
@ -57,6 +58,7 @@ class Creator(object):
|
||||
return [
|
||||
("dest", ensure_text(str(self.dest))),
|
||||
("clear", self.clear),
|
||||
("no_vcs_ignore", self.no_vcs_ignore),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
@ -79,7 +81,9 @@ class Creator(object):
|
||||
:param meta: value as returned by :meth:`can_create`
|
||||
"""
|
||||
parser.add_argument(
|
||||
"dest", help="directory to create virtualenv at", type=cls.validate_dest,
|
||||
"dest",
|
||||
help="directory to create virtualenv at",
|
||||
type=cls.validate_dest,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--clear",
|
||||
@ -88,6 +92,13 @@ class Creator(object):
|
||||
help="remove the destination directory if exist before starting (will overwrite files otherwise)",
|
||||
default=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-vcs-ignore",
|
||||
dest="no_vcs_ignore",
|
||||
action="store_true",
|
||||
help="don't create VCS ignore directive in the destination directory",
|
||||
default=False,
|
||||
)
|
||||
|
||||
@abstractmethod
|
||||
def create(self):
|
||||
@ -120,7 +131,9 @@ class Creator(object):
|
||||
if refused:
|
||||
raise ArgumentTypeError(
|
||||
"the file system codec ({}) cannot handle characters {!r} within {!r}".format(
|
||||
encoding, "".join(refused.keys()), raw_value,
|
||||
encoding,
|
||||
"".join(refused.keys()),
|
||||
raw_value,
|
||||
),
|
||||
)
|
||||
if os.pathsep in raw_value:
|
||||
@ -156,7 +169,8 @@ class Creator(object):
|
||||
safe_delete(self.dest)
|
||||
self.create()
|
||||
self.set_pyenv_cfg()
|
||||
self.setup_ignore_vcs()
|
||||
if not self.no_vcs_ignore:
|
||||
self.setup_ignore_vcs()
|
||||
|
||||
def set_pyenv_cfg(self):
|
||||
self.pyenv_cfg.content = OrderedDict()
|
||||
|
@ -8,6 +8,7 @@ from six import add_metaclass
|
||||
|
||||
from virtualenv.info import fs_supports_symlink
|
||||
from virtualenv.util.path import Path
|
||||
from virtualenv.util.six import ensure_text
|
||||
|
||||
from ..creator import Creator, CreatorMeta
|
||||
|
||||
@ -91,10 +92,10 @@ class ViaGlobalRefApi(Creator):
|
||||
text = self.env_patch_text()
|
||||
if text:
|
||||
pth = self.purelib / "_virtualenv.pth"
|
||||
logging.debug("create virtualenv import hook file %s", pth)
|
||||
logging.debug("create virtualenv import hook file %s", ensure_text(str(pth)))
|
||||
pth.write_text("import _virtualenv")
|
||||
dest_path = self.purelib / "_virtualenv.py"
|
||||
logging.debug("create %s", dest_path)
|
||||
logging.debug("create %s", ensure_text(str(dest_path)))
|
||||
dest_path.write_text(text)
|
||||
|
||||
def env_patch_text(self):
|
||||
|
@ -6,6 +6,7 @@ from collections import OrderedDict
|
||||
from six import add_metaclass
|
||||
|
||||
from virtualenv.create.describe import PosixSupports, WindowsSupports
|
||||
from virtualenv.create.via_global_ref.builtin.ref import RefMust, RefWhen
|
||||
from virtualenv.util.path import Path
|
||||
|
||||
from ..via_global_self_do import ViaGlobalRefVirtualenvBuiltin
|
||||
@ -33,19 +34,27 @@ class CPythonPosix(CPython, PosixSupports):
|
||||
targets = OrderedDict(
|
||||
(i, None) for i in ["python", "python{}".format(major), "python{}.{}".format(major, minor), host_exe.name]
|
||||
)
|
||||
yield host_exe, list(targets.keys())
|
||||
must = RefMust.COPY if interpreter.version_info.major == 2 else RefMust.NA
|
||||
yield host_exe, list(targets.keys()), must, RefWhen.ANY
|
||||
|
||||
|
||||
@add_metaclass(ABCMeta)
|
||||
class CPythonWindows(CPython, WindowsSupports):
|
||||
@classmethod
|
||||
def _executables(cls, interpreter):
|
||||
host = Path(interpreter.system_executable)
|
||||
# symlink of the python executables does not work reliably, copy always instead
|
||||
# - https://bugs.python.org/issue42013
|
||||
# - venv
|
||||
host = cls.host_python(interpreter)
|
||||
for path in (host.parent / n for n in {"python.exe", host.name}):
|
||||
yield host, [path.name]
|
||||
yield host, [path.name], RefMust.COPY, RefWhen.ANY
|
||||
# for more info on pythonw.exe see https://stackoverflow.com/a/30313091
|
||||
python_w = host.parent / "pythonw.exe"
|
||||
yield python_w, [python_w.name]
|
||||
yield python_w, [python_w.name], RefMust.COPY, RefWhen.ANY
|
||||
|
||||
@classmethod
|
||||
def host_python(cls, interpreter):
|
||||
return Path(interpreter.system_executable)
|
||||
|
||||
|
||||
def is_mac_os_framework(interpreter):
|
||||
|
@ -55,8 +55,21 @@ class CPython3Windows(CPythonWindows, CPython3):
|
||||
def sources(cls, interpreter):
|
||||
for src in super(CPython3Windows, cls).sources(interpreter):
|
||||
yield src
|
||||
for src in cls.include_dll_and_pyd(interpreter):
|
||||
yield src
|
||||
if not cls.venv_37p(interpreter):
|
||||
for src in cls.include_dll_and_pyd(interpreter):
|
||||
yield src
|
||||
|
||||
@staticmethod
|
||||
def venv_37p(interpreter):
|
||||
return interpreter.version_info.minor >= 7
|
||||
|
||||
@classmethod
|
||||
def host_python(cls, interpreter):
|
||||
if cls.venv_37p(interpreter):
|
||||
# starting with CPython 3.7 Windows ships with a venvlauncher.exe that avoids the need for dll/pyd copies
|
||||
# it also means the wrapper must be copied to avoid bugs such as https://bugs.python.org/issue42013
|
||||
return Path(interpreter.system_stdlib) / "venv" / "scripts" / "nt" / "python.exe"
|
||||
return super(CPython3Windows, cls).host_python(interpreter)
|
||||
|
||||
@classmethod
|
||||
def include_dll_and_pyd(cls, interpreter):
|
||||
|
@ -9,7 +9,7 @@ from textwrap import dedent
|
||||
|
||||
from six import add_metaclass
|
||||
|
||||
from virtualenv.create.via_global_ref.builtin.ref import ExePathRefToDest, PathRefToDest
|
||||
from virtualenv.create.via_global_ref.builtin.ref import ExePathRefToDest, PathRefToDest, RefMust
|
||||
from virtualenv.util.path import Path
|
||||
from virtualenv.util.six import ensure_text
|
||||
|
||||
@ -29,7 +29,8 @@ class CPythonmacOsFramework(CPython):
|
||||
for src in super(CPythonmacOsFramework, cls).sources(interpreter):
|
||||
yield src
|
||||
# add a symlink to the host python image
|
||||
ref = PathRefToDest(cls.image_ref(interpreter), dest=lambda self, _: self.dest / ".Python", must_symlink=True)
|
||||
exe = cls.image_ref(interpreter)
|
||||
ref = PathRefToDest(exe, dest=lambda self, _: self.dest / ".Python", must=RefMust.SYMLINK)
|
||||
yield ref
|
||||
|
||||
def create(self):
|
||||
@ -40,7 +41,7 @@ class CPythonmacOsFramework(CPython):
|
||||
current = self.current_mach_o_image_path()
|
||||
for src in self._sources:
|
||||
if isinstance(src, ExePathRefToDest):
|
||||
if src.must_copy or not self.symlinks:
|
||||
if src.must == RefMust.COPY or not self.symlinks:
|
||||
exes = [self.bin_dir / src.base]
|
||||
if not self.symlinks:
|
||||
exes.extend(self.bin_dir / a for a in src.aliases)
|
||||
@ -49,12 +50,12 @@ class CPythonmacOsFramework(CPython):
|
||||
|
||||
@classmethod
|
||||
def _executables(cls, interpreter):
|
||||
for _, targets in super(CPythonmacOsFramework, cls)._executables(interpreter):
|
||||
for _, targets, must, when in super(CPythonmacOsFramework, cls)._executables(interpreter):
|
||||
# Make sure we use the embedded interpreter inside the framework, even if sys.executable points to the
|
||||
# stub executable in ${sys.prefix}/bin.
|
||||
# See http://groups.google.com/group/python-virtualenv/browse_thread/thread/17cab2f85da75951
|
||||
fixed_host_exe = Path(interpreter.prefix) / "Resources" / "Python.app" / "Contents" / "MacOS" / "Python"
|
||||
yield fixed_host_exe, targets
|
||||
yield fixed_host_exe, targets, must, when
|
||||
|
||||
@abstractmethod
|
||||
def current_mach_o_image_path(self):
|
||||
@ -241,7 +242,7 @@ def _builtin_change_mach_o(maxint):
|
||||
|
||||
def mach_o_change(at_path, what, value):
|
||||
"""Replace a given name (what) in any LC_LOAD_DYLIB command found in the given binary with a new name (value),
|
||||
provided it's shorter."""
|
||||
provided it's shorter."""
|
||||
|
||||
def do_macho(file, bits, endian):
|
||||
# Read Mach-O header (the magic number is assumed read by the caller)
|
||||
|
@ -4,7 +4,7 @@ import abc
|
||||
|
||||
from six import add_metaclass
|
||||
|
||||
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest
|
||||
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest, RefMust, RefWhen
|
||||
from virtualenv.util.path import Path
|
||||
|
||||
from ..via_global_self_do import ViaGlobalRefVirtualenvBuiltin
|
||||
@ -20,7 +20,8 @@ class PyPy(ViaGlobalRefVirtualenvBuiltin):
|
||||
def _executables(cls, interpreter):
|
||||
host = Path(interpreter.system_executable)
|
||||
targets = sorted("{}{}".format(name, PyPy.suffix) for name in cls.exe_names(interpreter))
|
||||
yield host, targets
|
||||
must = RefMust.COPY if interpreter.version_info.major == 2 else RefMust.NA
|
||||
yield host, targets, must, RefWhen.ANY
|
||||
|
||||
@classmethod
|
||||
def exe_names(cls, interpreter):
|
||||
|
@ -52,8 +52,7 @@ def load_host_site():
|
||||
add_site_dir = sys.modules["site"].addsitedir
|
||||
for path in json.loads(site_packages):
|
||||
full_path = os.path.abspath(os.path.join(here, path.encode("utf-8")))
|
||||
if full_path not in sys.path:
|
||||
add_site_dir(full_path)
|
||||
add_site_dir(full_path)
|
||||
|
||||
|
||||
sep = "\\" if sys.platform == "win32" else "/" # no os module here yet - poor mans version
|
||||
|
@ -17,6 +17,18 @@ from virtualenv.util.path import copy, make_exe, symlink
|
||||
from virtualenv.util.six import ensure_text
|
||||
|
||||
|
||||
class RefMust(object):
|
||||
NA = "NA"
|
||||
COPY = "copy"
|
||||
SYMLINK = "symlink"
|
||||
|
||||
|
||||
class RefWhen(object):
|
||||
ANY = "ANY"
|
||||
COPY = "copy"
|
||||
SYMLINK = "symlink"
|
||||
|
||||
|
||||
@add_metaclass(ABCMeta)
|
||||
class PathRef(object):
|
||||
"""Base class that checks if a file reference can be symlink/copied"""
|
||||
@ -24,9 +36,9 @@ class PathRef(object):
|
||||
FS_SUPPORTS_SYMLINK = fs_supports_symlink()
|
||||
FS_CASE_SENSITIVE = fs_is_case_sensitive()
|
||||
|
||||
def __init__(self, src, must_symlink, must_copy):
|
||||
self.must_symlink = must_symlink
|
||||
self.must_copy = must_copy
|
||||
def __init__(self, src, must=RefMust.NA, when=RefWhen.ANY):
|
||||
self.must = must
|
||||
self.when = when
|
||||
self.src = src
|
||||
try:
|
||||
self.exists = src.exists()
|
||||
@ -35,8 +47,6 @@ class PathRef(object):
|
||||
self._can_read = None if self.exists else False
|
||||
self._can_copy = None if self.exists else False
|
||||
self._can_symlink = None if self.exists else False
|
||||
if self.must_copy is True and self.must_symlink is True:
|
||||
raise ValueError("can copy and symlink at the same time")
|
||||
|
||||
def __repr__(self):
|
||||
return "{}(src={})".format(self.__class__.__name__, self.src)
|
||||
@ -57,7 +67,7 @@ class PathRef(object):
|
||||
@property
|
||||
def can_copy(self):
|
||||
if self._can_copy is None:
|
||||
if self.must_symlink:
|
||||
if self.must == RefMust.SYMLINK:
|
||||
self._can_copy = self.can_symlink
|
||||
else:
|
||||
self._can_copy = self.can_read
|
||||
@ -66,7 +76,7 @@ class PathRef(object):
|
||||
@property
|
||||
def can_symlink(self):
|
||||
if self._can_symlink is None:
|
||||
if self.must_copy:
|
||||
if self.must == RefMust.COPY:
|
||||
self._can_symlink = self.can_copy
|
||||
else:
|
||||
self._can_symlink = self.FS_SUPPORTS_SYMLINK and self.can_read
|
||||
@ -77,9 +87,9 @@ class PathRef(object):
|
||||
raise NotImplementedError
|
||||
|
||||
def method(self, symlinks):
|
||||
if self.must_symlink:
|
||||
if self.must == RefMust.SYMLINK:
|
||||
return symlink
|
||||
if self.must_copy:
|
||||
if self.must == RefMust.COPY:
|
||||
return copy
|
||||
return symlink if symlinks else copy
|
||||
|
||||
@ -88,8 +98,8 @@ class PathRef(object):
|
||||
class ExePathRef(PathRef):
|
||||
"""Base class that checks if a executable can be references via symlink/copy"""
|
||||
|
||||
def __init__(self, src, must_symlink, must_copy):
|
||||
super(ExePathRef, self).__init__(src, must_symlink, must_copy)
|
||||
def __init__(self, src, must=RefMust.NA, when=RefWhen.ANY):
|
||||
super(ExePathRef, self).__init__(src, must, when)
|
||||
self._can_run = None
|
||||
|
||||
@property
|
||||
@ -114,8 +124,8 @@ class ExePathRef(PathRef):
|
||||
class PathRefToDest(PathRef):
|
||||
"""Link a path on the file system"""
|
||||
|
||||
def __init__(self, src, dest, must_symlink=False, must_copy=False):
|
||||
super(PathRefToDest, self).__init__(src, must_symlink, must_copy)
|
||||
def __init__(self, src, dest, must=RefMust.NA, when=RefWhen.ANY):
|
||||
super(PathRefToDest, self).__init__(src, must, when)
|
||||
self.dest = dest
|
||||
|
||||
def run(self, creator, symlinks):
|
||||
@ -131,15 +141,14 @@ class PathRefToDest(PathRef):
|
||||
class ExePathRefToDest(PathRefToDest, ExePathRef):
|
||||
"""Link a exe path on the file system"""
|
||||
|
||||
def __init__(self, src, targets, dest, must_symlink=False, must_copy=False):
|
||||
ExePathRef.__init__(self, src, must_symlink, must_copy)
|
||||
PathRefToDest.__init__(self, src, dest, must_symlink, must_copy)
|
||||
def __init__(self, src, targets, dest, must=RefMust.NA, when=RefWhen.ANY):
|
||||
ExePathRef.__init__(self, src, must, when)
|
||||
PathRefToDest.__init__(self, src, dest, must, when)
|
||||
if not self.FS_CASE_SENSITIVE:
|
||||
targets = list(OrderedDict((i.lower(), None) for i in targets).keys())
|
||||
self.base = targets[0]
|
||||
self.aliases = targets[1:]
|
||||
self.dest = dest
|
||||
self.must_copy = must_copy
|
||||
|
||||
def run(self, creator, symlinks):
|
||||
bin_dir = self.dest(creator, self.src).parent
|
||||
|
@ -4,7 +4,7 @@ from abc import ABCMeta
|
||||
|
||||
from six import add_metaclass
|
||||
|
||||
from virtualenv.create.via_global_ref.builtin.ref import ExePathRefToDest
|
||||
from virtualenv.create.via_global_ref.builtin.ref import ExePathRefToDest, RefMust, RefWhen
|
||||
from virtualenv.util.path import ensure_dir
|
||||
|
||||
from ..api import ViaGlobalRefApi, ViaGlobalRefMeta
|
||||
@ -27,26 +27,37 @@ class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
|
||||
def can_create(cls, interpreter):
|
||||
"""By default all built-in methods assume that if we can describe it we can create it"""
|
||||
# first we must be able to describe it
|
||||
if cls.can_describe(interpreter):
|
||||
meta = cls.setup_meta(interpreter)
|
||||
if meta is not None and meta:
|
||||
for src in cls.sources(interpreter):
|
||||
if src.exists:
|
||||
if meta.can_copy and not src.can_copy:
|
||||
meta.copy_error = "cannot copy {}".format(src)
|
||||
if meta.can_symlink and not src.can_symlink:
|
||||
meta.symlink_error = "cannot symlink {}".format(src)
|
||||
if not meta.can_copy and not meta.can_symlink:
|
||||
meta.error = "neither copy or symlink supported, copy: {} symlink: {}".format(
|
||||
meta.copy_error, meta.symlink_error,
|
||||
)
|
||||
else:
|
||||
meta.error = "missing required file {}".format(src)
|
||||
if meta.error:
|
||||
break
|
||||
meta.sources.append(src)
|
||||
return meta
|
||||
return None
|
||||
if not cls.can_describe(interpreter):
|
||||
return None
|
||||
meta = cls.setup_meta(interpreter)
|
||||
if meta is not None and meta:
|
||||
cls._sources_can_be_applied(interpreter, meta)
|
||||
return meta
|
||||
|
||||
@classmethod
|
||||
def _sources_can_be_applied(cls, interpreter, meta):
|
||||
for src in cls.sources(interpreter):
|
||||
if src.exists:
|
||||
if meta.can_copy and not src.can_copy:
|
||||
meta.copy_error = "cannot copy {}".format(src)
|
||||
if meta.can_symlink and not src.can_symlink:
|
||||
meta.symlink_error = "cannot symlink {}".format(src)
|
||||
else:
|
||||
msg = "missing required file {}".format(src)
|
||||
if src.when == RefMust.NA:
|
||||
meta.error = msg
|
||||
elif src.when == RefMust.COPY:
|
||||
meta.copy_error = msg
|
||||
elif src.when == RefMust.SYMLINK:
|
||||
meta.symlink_error = msg
|
||||
if not meta.can_copy and not meta.can_symlink:
|
||||
meta.error = "neither copy or symlink supported, copy: {} symlink: {}".format(
|
||||
meta.copy_error,
|
||||
meta.symlink_error,
|
||||
)
|
||||
if meta.error:
|
||||
break
|
||||
meta.sources.append(src)
|
||||
|
||||
@classmethod
|
||||
def setup_meta(cls, interpreter):
|
||||
@ -54,9 +65,8 @@ class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
|
||||
|
||||
@classmethod
|
||||
def sources(cls, interpreter):
|
||||
is_py2 = interpreter.version_info.major == 2
|
||||
for host_exe, targets in cls._executables(interpreter):
|
||||
yield ExePathRefToDest(host_exe, dest=cls.to_bin, targets=targets, must_copy=is_py2)
|
||||
for host_exe, targets, must, when in cls._executables(interpreter):
|
||||
yield ExePathRefToDest(host_exe, dest=cls.to_bin, targets=targets, must=must, when=when)
|
||||
|
||||
def to_bin(self, src):
|
||||
return self.bin_dir / src.name
|
||||
@ -79,7 +89,12 @@ class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
|
||||
try:
|
||||
self.enable_system_site_package = False
|
||||
for src in self._sources:
|
||||
src.run(self, self.symlinks)
|
||||
if (
|
||||
src.when == RefWhen.ANY
|
||||
or (src.when == RefWhen.SYMLINK and self.symlinks is True)
|
||||
or (src.when == RefWhen.COPY and self.symlinks is False)
|
||||
):
|
||||
src.run(self, self.symlinks)
|
||||
finally:
|
||||
if true_system_site != self.enable_system_site_package:
|
||||
self.enable_system_site_package = true_system_site
|
||||
@ -92,7 +107,7 @@ class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
|
||||
"""
|
||||
We directly inject the base prefix and base exec prefix to avoid site.py needing to discover these
|
||||
from home (which usually is done within the interpreter itself)
|
||||
"""
|
||||
"""
|
||||
super(ViaGlobalRefVirtualenvBuiltin, self).set_pyenv_cfg()
|
||||
self.pyenv_cfg["base-prefix"] = self.interpreter.system_prefix
|
||||
self.pyenv_cfg["base-exec-prefix"] = self.interpreter.system_exec_prefix
|
||||
|
@ -46,7 +46,10 @@ class Venv(ViaGlobalRefApi):
|
||||
from venv import EnvBuilder
|
||||
|
||||
builder = EnvBuilder(
|
||||
system_site_packages=self.enable_system_site_package, clear=False, symlinks=self.symlinks, with_pip=False,
|
||||
system_site_packages=self.enable_system_site_package,
|
||||
clear=False,
|
||||
symlinks=self.symlinks,
|
||||
with_pip=False,
|
||||
)
|
||||
builder.create(str(self.dest))
|
||||
|
||||
|
@ -15,7 +15,7 @@ from .py_spec import PythonSpec
|
||||
class Builtin(Discover):
|
||||
def __init__(self, options):
|
||||
super(Builtin, self).__init__(options)
|
||||
self.python_spec = options.python
|
||||
self.python_spec = options.python if options.python else [sys.executable]
|
||||
self.app_data = options.app_data
|
||||
|
||||
@classmethod
|
||||
@ -25,18 +25,26 @@ class Builtin(Discover):
|
||||
"--python",
|
||||
dest="python",
|
||||
metavar="py",
|
||||
help="target interpreter for which to create a virtual (either absolute path or identifier string)",
|
||||
default=sys.executable,
|
||||
type=str,
|
||||
action="append",
|
||||
default=[],
|
||||
help="interpreter based on what to create environment (path/identifier) "
|
||||
"- by default use the interpreter where the tool is installed - first found wins",
|
||||
)
|
||||
|
||||
def run(self):
|
||||
return get_interpreter(self.python_spec, self.app_data)
|
||||
for python_spec in self.python_spec:
|
||||
result = get_interpreter(python_spec, self.app_data)
|
||||
if result is not None:
|
||||
return result
|
||||
return None
|
||||
|
||||
def __repr__(self):
|
||||
return ensure_str(self.__unicode__())
|
||||
|
||||
def __unicode__(self):
|
||||
return "{} discover of python_spec={!r}".format(self.__class__.__name__, self.python_spec)
|
||||
spec = self.python_spec[0] if len(self.python_spec) == 1 else self.python_spec
|
||||
return "{} discover of python_spec={!r}".format(self.__class__.__name__, spec)
|
||||
|
||||
|
||||
def get_interpreter(key, app_data=None):
|
||||
|
@ -104,7 +104,10 @@ def _run_subprocess(cls, exe, app_data):
|
||||
result.executable = exe # keep original executable as this may contain initialization code
|
||||
else:
|
||||
msg = "failed to query {} with code {}{}{}".format(
|
||||
exe, code, " out: {!r}".format(out) if out else "", " err: {!r}".format(err) if err else "",
|
||||
exe,
|
||||
code,
|
||||
" out: {!r}".format(out) if out else "",
|
||||
" err: {!r}".format(err) if err else "",
|
||||
)
|
||||
failure = RuntimeError(msg)
|
||||
return failure, result
|
||||
|
@ -120,7 +120,7 @@ class PythonInfo(object):
|
||||
|
||||
@staticmethod
|
||||
def _distutils_install():
|
||||
# follow https://github.com/pypa/pip/blob/master/src/pip/_internal/locations.py#L95
|
||||
# follow https://github.com/pypa/pip/blob/main/src/pip/_internal/locations.py#L95
|
||||
# note here we don't import Distribution directly to allow setuptools to patch it
|
||||
d = dist.Distribution({"script_args": "--no-user-cfg"}) # conf files not parsed so they do not hijack paths
|
||||
if hasattr(sys, "_framework"):
|
||||
@ -198,7 +198,8 @@ class PythonInfo(object):
|
||||
|
||||
def __repr__(self):
|
||||
return "{}({!r})".format(
|
||||
self.__class__.__name__, {k: v for k, v in self.__dict__.items() if not k.startswith("_")},
|
||||
self.__class__.__name__,
|
||||
{k: v for k, v in self.__dict__.items() if not k.startswith("_")},
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
|
@ -1,8 +1,9 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import logging
|
||||
from functools import partial
|
||||
|
||||
from ..app_data import AppDataAction, AppDataDisabled, TempAppData
|
||||
from ..app_data import make_app_data
|
||||
from ..config.cli.parser import VirtualEnvConfigParser
|
||||
from ..report import LEVELS, setup_report
|
||||
from ..run.session import Session
|
||||
@ -88,32 +89,31 @@ def handle_extra_commands(options):
|
||||
|
||||
|
||||
def load_app_data(args, parser, options):
|
||||
parser.add_argument(
|
||||
"--read-only-app-data",
|
||||
action="store_true",
|
||||
help="use app data folder in read-only mode (write operations will fail with error)",
|
||||
)
|
||||
options, _ = parser.parse_known_args(args, namespace=options)
|
||||
|
||||
# here we need a write-able application data (e.g. the zipapp might need this for discovery cache)
|
||||
default_app_data = AppDataAction.default()
|
||||
parser.add_argument(
|
||||
"--app-data",
|
||||
dest="app_data",
|
||||
action=AppDataAction,
|
||||
default="<temp folder>" if isinstance(default_app_data, AppDataDisabled) else default_app_data,
|
||||
help="a data folder used as cache by the virtualenv",
|
||||
type=partial(make_app_data, read_only=options.read_only_app_data),
|
||||
default=make_app_data(None, read_only=options.read_only_app_data),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--reset-app-data",
|
||||
dest="reset_app_data",
|
||||
action="store_true",
|
||||
help="start with empty app data folder",
|
||||
default=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--upgrade-embed-wheels",
|
||||
dest="upgrade_embed_wheels",
|
||||
action="store_true",
|
||||
help="trigger a manual update of the embedded wheels",
|
||||
default=False,
|
||||
)
|
||||
options, _ = parser.parse_known_args(args, namespace=options)
|
||||
if options.app_data == "<temp folder>":
|
||||
options.app_data = TempAppData()
|
||||
if options.reset_app_data:
|
||||
options.app_data.reset()
|
||||
return options
|
||||
@ -134,7 +134,8 @@ def _do_report_setup(parser, args, setup_logging):
|
||||
level_map = ", ".join("{}={}".format(logging.getLevelName(l), c) for c, l in sorted(list(LEVELS.items())))
|
||||
msg = "verbosity = verbose - quiet, default {}, mapping => {}"
|
||||
verbosity_group = parser.add_argument_group(
|
||||
title="verbosity", description=msg.format(logging.getLevelName(LEVELS[3]), level_map),
|
||||
title="verbosity",
|
||||
description=msg.format(logging.getLevelName(LEVELS[3]), level_map),
|
||||
)
|
||||
verbosity = verbosity_group.add_mutually_exclusive_group()
|
||||
verbosity.add_argument("-v", "--verbose", action="count", dest="verbose", help="increase verbosity", default=2)
|
||||
|
@ -18,14 +18,14 @@ class CreatorSelector(ComponentBuilder):
|
||||
@classmethod
|
||||
def for_interpreter(cls, interpreter):
|
||||
key_to_class, key_to_meta, builtin_key, describe = OrderedDict(), {}, None, None
|
||||
errored = defaultdict(list)
|
||||
errors = defaultdict(list)
|
||||
for key, creator_class in cls.options("virtualenv.create").items():
|
||||
if key == "builtin":
|
||||
raise RuntimeError("builtin creator is a reserved name")
|
||||
meta = creator_class.can_create(interpreter)
|
||||
if meta:
|
||||
if meta.error:
|
||||
errored[meta.error].append(creator_class)
|
||||
errors[meta.error].append(creator_class)
|
||||
else:
|
||||
if "builtin" not in key_to_class and issubclass(creator_class, VirtualenvBuiltin):
|
||||
builtin_key = key
|
||||
@ -36,16 +36,16 @@ class CreatorSelector(ComponentBuilder):
|
||||
if describe is None and issubclass(creator_class, Describe) and creator_class.can_describe(interpreter):
|
||||
describe = creator_class
|
||||
if not key_to_meta:
|
||||
if errored:
|
||||
raise RuntimeError(
|
||||
"\n".join(
|
||||
"{} for creators {}".format(k, ", ".join(i.__name__ for i in v)) for k, v in errored.items()
|
||||
),
|
||||
)
|
||||
if errors:
|
||||
rows = ["{} for creators {}".format(k, ", ".join(i.__name__ for i in v)) for k, v in errors.items()]
|
||||
raise RuntimeError("\n".join(rows))
|
||||
else:
|
||||
raise RuntimeError("No virtualenv implementation for {}".format(interpreter))
|
||||
return CreatorInfo(
|
||||
key_to_class=key_to_class, key_to_meta=key_to_meta, describe=describe, builtin_key=builtin_key,
|
||||
key_to_class=key_to_class,
|
||||
key_to_meta=key_to_meta,
|
||||
describe=describe,
|
||||
builtin_key=builtin_key,
|
||||
)
|
||||
|
||||
def add_selector_arg_parse(self, name, choices):
|
||||
|
@ -10,7 +10,8 @@ class Discovery(PluginLoader):
|
||||
def get_discover(parser, args):
|
||||
discover_types = Discovery.entry_points_for("virtualenv.discovery")
|
||||
discovery_parser = parser.add_argument_group(
|
||||
title="discovery", description="discover and provide a target interpreter",
|
||||
title="discovery",
|
||||
description="discover and provide a target interpreter",
|
||||
)
|
||||
discovery_parser.add_argument(
|
||||
"--discovery",
|
||||
|
@ -17,7 +17,11 @@ class SeederSelector(ComponentBuilder):
|
||||
help="seed packages install method",
|
||||
)
|
||||
self.parser.add_argument(
|
||||
"--no-seed", "--without-pip", help="do not install seed packages", action="store_true", dest="no_seed",
|
||||
"--no-seed",
|
||||
"--without-pip",
|
||||
help="do not install seed packages",
|
||||
action="store_true",
|
||||
dest="no_seed",
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
@ -62,7 +62,8 @@ class Session(object):
|
||||
def _activate(self):
|
||||
if self.activators:
|
||||
logging.info(
|
||||
"add activators for %s", ", ".join(type(i).__name__.replace("Activator", "") for i in self.activators),
|
||||
"add activators for %s",
|
||||
", ".join(type(i).__name__.replace("Activator", "") for i in self.activators),
|
||||
)
|
||||
for activator in self.activators:
|
||||
activator.generate(self.creator)
|
||||
|
@ -109,7 +109,8 @@ class BaseEmbed(Seeder):
|
||||
if getattr(self, "no_{}".format(distribution)):
|
||||
continue
|
||||
result += " {}{},".format(
|
||||
distribution, "={}".format(getattr(self, "{}_version".format(distribution), None) or "latest"),
|
||||
distribution,
|
||||
"={}".format(getattr(self, "{}_version".format(distribution), None) or "latest"),
|
||||
)
|
||||
return result[:-1] + ")"
|
||||
|
||||
|
@ -8,14 +8,10 @@ from contextlib import contextmanager
|
||||
from subprocess import CalledProcessError
|
||||
from threading import Lock, Thread
|
||||
|
||||
import six
|
||||
|
||||
from virtualenv.info import fs_supports_symlink
|
||||
from virtualenv.seed.embed.base_embed import BaseEmbed
|
||||
from virtualenv.seed.wheels import get_wheel
|
||||
from virtualenv.util.lock import _CountedFileLock
|
||||
from virtualenv.util.path import Path
|
||||
from virtualenv.util.six import ensure_text
|
||||
|
||||
from .pip_install.copy import CopyPipInstall
|
||||
from .pip_install.symlink import SymlinkPipInstall
|
||||
@ -54,7 +50,8 @@ class FromAppData(BaseEmbed):
|
||||
key = Path(installer_class.__name__) / wheel.path.stem
|
||||
wheel_img = self.app_data.wheel_image(creator.interpreter.version_release_str, key)
|
||||
installer = installer_class(wheel.path, creator, wheel_img)
|
||||
with _CountedFileLock(ensure_text(str(wheel_img.parent / "{}.lock".format(wheel_img.name)))):
|
||||
parent = self.app_data.lock / wheel_img.parent
|
||||
with parent.non_reentrant_lock_for_key(wheel_img.name):
|
||||
if not installer.has_image():
|
||||
installer.build_image()
|
||||
installer.install(creator.interpreter.version_info)
|
||||
@ -104,7 +101,7 @@ class FromAppData(BaseEmbed):
|
||||
if version is not None:
|
||||
msg += " version {}".format(version)
|
||||
msg += ", pip download exit code {}".format(failure.returncode)
|
||||
output = failure.output if six.PY2 else (failure.output + failure.stderr)
|
||||
output = failure.output if sys.version_info < (3, 5) else (failure.output + failure.stderr)
|
||||
if output:
|
||||
msg += "\n"
|
||||
msg += output
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user