diff --git a/news/4944.bugfix.mdB b/news/4944.bugfix.rst similarity index 100% rename from news/4944.bugfix.mdB rename to news/4944.bugfix.rst diff --git a/news/4976.vendor.rst b/news/4976.vendor.rst new file mode 100644 index 00000000..47d9199f --- /dev/null +++ b/news/4976.vendor.rst @@ -0,0 +1,2 @@ +Updated vendor version of `pythonfinder` from `1.2.9` to `1.2.10` which fixes a bug with WSL +(Windows Subsystem for Linux) when a path can not be read and Permission Denied error is encountered. diff --git a/pipenv/vendor/pythonfinder/__init__.py b/pipenv/vendor/pythonfinder/__init__.py index 7ff28b14..6bca7239 100644 --- a/pipenv/vendor/pythonfinder/__init__.py +++ b/pipenv/vendor/pythonfinder/__init__.py @@ -10,7 +10,7 @@ from .exceptions import InvalidPythonVersion from .models import SystemPath, WindowsFinder from .pythonfinder import Finder -__version__ = "1.2.9" +__version__ = "1.2.10" logger = logging.getLogger(__name__) diff --git a/pipenv/vendor/pythonfinder/__main__.py b/pipenv/vendor/pythonfinder/__main__.py index e6d7c950..b2af108f 100644 --- a/pipenv/vendor/pythonfinder/__main__.py +++ b/pipenv/vendor/pythonfinder/__main__.py @@ -8,7 +8,6 @@ import sys from pipenv.vendor.pythonfinder.cli import cli - PYTHONFINDER_MAIN = os.path.dirname(os.path.abspath(__file__)) PYTHONFINDER_PACKAGE = os.path.dirname(PYTHONFINDER_MAIN) diff --git a/pipenv/vendor/pythonfinder/cli.py b/pipenv/vendor/pythonfinder/cli.py index ea34ffab..c8d7753b 100644 --- a/pipenv/vendor/pythonfinder/cli.py +++ b/pipenv/vendor/pythonfinder/cli.py @@ -30,7 +30,7 @@ def cli( click.echo( "{0} version {1}".format( click.style("PythonFinder", fg="white", bold=True), - click.style(str(__version__), fg="yellow") + click.style(str(__version__), fg="yellow"), ) ) ctx.exit() diff --git a/pipenv/vendor/pythonfinder/compat.py b/pipenv/vendor/pythonfinder/compat.py index 71c4b6a2..1cded958 100644 --- a/pipenv/vendor/pythonfinder/compat.py +++ b/pipenv/vendor/pythonfinder/compat.py @@ -9,8 +9,8 @@ else: from pathlib import Path if six.PY3: - from functools import lru_cache from builtins import TimeoutError + from functools import lru_cache else: from backports.functools_lru_cache import lru_cache # type: ignore # noqa @@ -20,6 +20,7 @@ else: def getpreferredencoding(): import locale + # Borrowed from Invoke # (see https://github.com/pyinvoke/invoke/blob/93af29d/invoke/runners.py#L881) _encoding = locale.getpreferredencoding(False) diff --git a/pipenv/vendor/pythonfinder/environment.py b/pipenv/vendor/pythonfinder/environment.py index 6b22fb08..0a7d5de8 100644 --- a/pipenv/vendor/pythonfinder/environment.py +++ b/pipenv/vendor/pythonfinder/environment.py @@ -27,7 +27,7 @@ ASDF_DATA_DIR = os.path.expanduser( IS_64BIT_OS = None SYSTEM_ARCH = platform.architecture()[0] -if sys.maxsize > 2 ** 32: +if sys.maxsize > 2**32: IS_64BIT_OS = platform.machine() == "AMD64" else: IS_64BIT_OS = False diff --git a/pipenv/vendor/pythonfinder/models/__init__.py b/pipenv/vendor/pythonfinder/models/__init__.py index 3d05af63..e7e03a70 100644 --- a/pipenv/vendor/pythonfinder/models/__init__.py +++ b/pipenv/vendor/pythonfinder/models/__init__.py @@ -3,7 +3,6 @@ from __future__ import absolute_import, print_function import abc import operator - from itertools import chain import pipenv.vendor.six as six diff --git a/pipenv/vendor/pythonfinder/models/mixins.py b/pipenv/vendor/pythonfinder/models/mixins.py index 001b7017..1e31efd3 100644 --- a/pipenv/vendor/pythonfinder/models/mixins.py +++ b/pipenv/vendor/pythonfinder/models/mixins.py @@ -20,22 +20,23 @@ from ..utils import ( ) if MYPY_RUNNING: - from .path import PathEntry - from .python import PythonVersion from typing import ( - Optional, - Union, Any, + DefaultDict, Dict, + Generator, Iterator, List, - DefaultDict, - Generator, + Optional, Tuple, - TypeVar, Type, + TypeVar, + Union, ) + from ..compat import Path # noqa + from .path import PathEntry + from .python import PythonVersion BaseFinderType = TypeVar("BaseFinderType") diff --git a/pipenv/vendor/pythonfinder/models/path.py b/pipenv/vendor/pythonfinder/models/path.py index 269496d6..76bb50ab 100644 --- a/pipenv/vendor/pythonfinder/models/path.py +++ b/pipenv/vendor/pythonfinder/models/path.py @@ -3,15 +3,17 @@ from __future__ import absolute_import, print_function import operator import os +import stat import sys +import errno from collections import defaultdict from itertools import chain import pipenv.vendor.attr as attr import pipenv.vendor.six as six from pipenv.vendor.cached_property import cached_property -from ..compat import Path, fs_str +from ..compat import Path, fs_str from ..environment import ( ASDF_DATA_DIR, ASDF_INSTALLED, @@ -41,19 +43,20 @@ from .mixins import BaseFinder, BasePath if MYPY_RUNNING: from typing import ( - Optional, - Dict, + Any, + Callable, DefaultDict, + Dict, + Generator, Iterator, List, - Union, + Optional, Tuple, - Generator, - Callable, Type, - Any, TypeVar, + Union, ) + from .python import PythonFinder, PythonVersion from .windows import WindowsFinder @@ -61,6 +64,14 @@ if MYPY_RUNNING: ChildType = Union[PythonFinder, "PathEntry"] PathType = Union[PythonFinder, "PathEntry"] +def exists_and_is_accessible(path): + try: + return path.exists() + except PermissionError as pe: + if pe.errno == errno.EACCES: # Permission denied + return False + else: + raise @attr.s class SystemPath(object): @@ -168,7 +179,7 @@ class SystemPath(object): for child in self.paths.values(): if child.pythons: python_executables.update(dict(child.pythons)) - for finder_name, finder in self.__finders.items(): + for _, finder in self.__finders.items(): if finder.pythons: python_executables.update(dict(finder.pythons)) self._python_executables = python_executables @@ -188,7 +199,7 @@ class SystemPath(object): continue if entry not in self._version_dict[version] and entry.is_python: self._version_dict[version].append(entry) - for p, entry in self.python_executables.items(): + for _, entry in self.python_executables.items(): version = entry.as_python # type: PythonVersion if not version: continue @@ -222,7 +233,7 @@ class SystemPath(object): path=p.absolute(), is_root=True, only_python=self.only_python ) for p in path_instances - if p.exists() + if exists_and_is_accessible(p) } ) new_instance = attr.evolve( @@ -669,7 +680,7 @@ class SystemPath(object): path=p.absolute(), is_root=True, only_python=only_python ) for p in _path_objects - if p.exists() + if exists_and_is_accessible(p) } ) instance = cls( @@ -705,12 +716,14 @@ class PathEntry(BasePath): return self.path.as_posix() >= other.path.as_posix() def __del__(self): - if getattr(self, "_children"): + if hasattr(self, "_children"): del self._children BasePath.__del__(self) def _filter_children(self): # type: () -> Iterator[Path] + if not os.access(str(self.path), os.R_OK): + return iter([]) if self.only_python: children = filter_pythons(self.path) else: diff --git a/pipenv/vendor/pythonfinder/models/python.py b/pipenv/vendor/pythonfinder/models/python.py index f1351c6f..3ab900ee 100644 --- a/pipenv/vendor/pythonfinder/models/python.py +++ b/pipenv/vendor/pythonfinder/models/python.py @@ -35,22 +35,23 @@ from .mixins import BaseFinder, BasePath if MYPY_RUNNING: from typing import ( - DefaultDict, - Optional, - Callable, - Generator, Any, - Union, - Tuple, - List, + Callable, + DefaultDict, Dict, + Generator, + Iterator, + List, + Optional, + Tuple, Type, TypeVar, - Iterator, + Union, overload, ) - from .path import PathEntry + from .._vendor.pep514tools.environment import Environment + from .path import PathEntry else: def overload(f): @@ -197,7 +198,7 @@ class PythonFinder(BaseFinder, BasePath): def versions(self): # type: () -> DefaultDict[Tuple, PathEntry] if not self._versions: - for base_path, entry, version_tuple in self._iter_versions(): + for _, entry, version_tuple in self._iter_versions(): self._versions[version_tuple] = entry return self._versions diff --git a/pipenv/vendor/pythonfinder/models/windows.py b/pipenv/vendor/pythonfinder/models/windows.py index 5a4d9136..4c288ae4 100644 --- a/pipenv/vendor/pythonfinder/models/windows.py +++ b/pipenv/vendor/pythonfinder/models/windows.py @@ -14,7 +14,7 @@ from .path import PathEntry from .python import PythonVersion, VersionMap if MYPY_RUNNING: - from typing import DefaultDict, Tuple, List, Optional, Union, TypeVar, Type, Any + from typing import Any, DefaultDict, List, Optional, Tuple, Type, TypeVar, Union FinderType = TypeVar("FinderType") @@ -43,7 +43,8 @@ class WindowsFinder(BaseFinder): pythons = [py for py in self.version_list if version_matcher(py)] version_sort = operator.attrgetter("version_sort") return [ - c.comes_from for c in sorted(pythons, key=version_sort, reverse=True) + c.comes_from + for c in sorted(pythons, key=version_sort, reverse=True) if c.comes_from ] diff --git a/pipenv/vendor/pythonfinder/pythonfinder.py b/pipenv/vendor/pythonfinder/pythonfinder.py index e7d9c217..a80f91df 100644 --- a/pipenv/vendor/pythonfinder/pythonfinder.py +++ b/pipenv/vendor/pythonfinder/pythonfinder.py @@ -14,10 +14,10 @@ from .exceptions import InvalidPythonVersion from .utils import Iterable, filter_pythons, version_re if environment.MYPY_RUNNING: - from typing import Optional, Dict, Any, Union, List, Iterator, Text - from .models.path import Path, PathEntry + from typing import Any, Dict, Iterator, List, Optional, Text, Union + + from .models.path import Path, PathEntry, SystemPath from .models.windows import WindowsFinder - from .models.path import SystemPath STRING_TYPE = Union[str, Text, bytes] diff --git a/pipenv/vendor/pythonfinder/utils.py b/pipenv/vendor/pythonfinder/utils.py index ee5502c5..a0eeda1a 100644 --- a/pipenv/vendor/pythonfinder/utils.py +++ b/pipenv/vendor/pythonfinder/utils.py @@ -14,7 +14,7 @@ import pipenv.vendor.attr as attr import pipenv.vendor.six as six from pipenv.vendor.packaging.version import LegacyVersion, Version -from .compat import Path, lru_cache, TimeoutError # noqa +from .compat import Path, TimeoutError, lru_cache # noqa from .environment import MYPY_RUNNING, PYENV_ROOT, SUBPROCESS_TIMEOUT from .exceptions import InvalidPythonVersion @@ -30,8 +30,10 @@ from pipenv.vendor.six.moves import Sequence # type: ignore # noqa # isort:sk # fmt: on if MYPY_RUNNING: - from typing import Any, Union, List, Callable, Set, Tuple, Dict, Optional, Iterator + from typing import Any, Callable, Dict, Iterator, List, Optional, Set, Tuple, Union + from pipenv.vendor.attr.validators import _OptionalValidator # type: ignore + from .models.path import PathEntry @@ -62,8 +64,10 @@ else: KNOWN_EXTS = KNOWN_EXTS | set( filter(None, os.environ.get("PATHEXT", "").split(os.pathsep)) ) -PY_MATCH_STR = r"((?P{0})(?:\d?(?:\.\d[cpm]{{0,3}}))?(?:-?[\d\.]+)*(?!w))".format( - "|".join(PYTHON_IMPLEMENTATIONS) +PY_MATCH_STR = ( + r"((?P{0})(?:\d?(?:\.\d[cpm]{{0,3}}))?(?:-?[\d\.]+)*(?!w))".format( + "|".join(PYTHON_IMPLEMENTATIONS) + ) ) EXE_MATCH_STR = r"{0}(?:\.(?P{1}))?".format(PY_MATCH_STR, "|".join(KNOWN_EXTS)) RE_MATCHER = re.compile(r"({0}|{1})".format(version_re_str, PY_MATCH_STR)) diff --git a/pipenv/vendor/vendor.txt b/pipenv/vendor/vendor.txt index 3d7b39ea..95aa65eb 100644 --- a/pipenv/vendor/vendor.txt +++ b/pipenv/vendor/vendor.txt @@ -31,7 +31,7 @@ ptyprocess==0.7.0 pyparsing==2.4.7 python-dateutil==2.8.2 python-dotenv==0.19.0 -pythonfinder==1.2.9 +pythonfinder==1.2.10 requests==2.26.0 requirementslib==1.6.1 shellingham==1.4.0