Skip to content

Commit

Permalink
Fix git installed package detection
Browse files Browse the repository at this point in the history
A package installed from git is sometimes mistaken as a standard
package since it has a `.dist-info` directory. This change ensures
that the pth file sources are also taken into consideration when
determining if a package is git sourced.

Additionally, this change ensures that a pth file is searched for in
both platlib and purelib site directories.
  • Loading branch information
abn committed Jul 24, 2020
1 parent 6106bfa commit 626bdd0
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 34 deletions.
86 changes: 53 additions & 33 deletions poetry/repositories/installed_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@
_VENDORS = Path(__file__).parent.parent.joinpath("_vendor")


try:
FileNotFoundError
except NameError:
FileNotFoundError = OSError


class InstalledRepository(Repository):
@classmethod
def get_package_paths(cls, sitedir, name): # type: (Path, str) -> Set[Path]
def get_package_paths(cls, env, name): # type: (Env, str) -> Set[Path]
"""
Process a .pth file within the site-packages directory, and return any valid
Process a .pth file within the site-packages directories, and return any valid
paths. We skip executable .pth files as there is no reliable means to do this
without side-effects to current run-time. Mo check is made that the item refers
to a directory rather than a file, however, in order to maintain backwards
Expand All @@ -24,25 +30,41 @@ def get_package_paths(cls, sitedir, name): # type: (Path, str) -> Set[Path]
Reference: https://docs.python.org/3.8/library/site.html
:param sitedir: The site-packages directory to search for .pth file.
:param env: The environment to search for the .pth file in.
:param name: The name of the package to search .pth file for.
:return: A `Set` of valid `Path` objects.
"""
paths = set()

pth_file = sitedir.joinpath("{}.pth".format(name))
if pth_file.exists():
with pth_file.open() as f:
for line in f:
line = line.strip()
if line and not line.startswith(("#", "import ", "import\t")):
path = Path(line)
if not path.is_absolute():
path = sitedir.joinpath(path)
paths.add(path)

for lib_path in [env.purelib, env.platlib]:
pth_file = lib_path.joinpath(name).with_suffix(".pth")
if pth_file.exists():
with pth_file.open() as f:
for line in f:
line = line.strip()
if line and not line.startswith(("#", "import ", "import\t")):
path = Path(line)
if not path.is_absolute():
try:
path = lib_path.joinpath(path).resolve()
except FileNotFoundError:
# this is requried to handle pathlib oddity on win32 python==3.5
path = lib_path.joinpath(path)
paths.add(path)
return paths

@classmethod
def _set_git_package_properties(cls, src, package): # type: (Path, Package) -> None
from poetry.core.vcs.git import Git

git = Git()
revision = git.rev_parse("HEAD", src).strip()
url = git.remote_url(src)

package.source_type = "git"
package.source_url = url
package.source_reference = revision

@classmethod
def load(cls, env): # type: (Env) -> InstalledRepository
"""
Expand Down Expand Up @@ -77,34 +99,32 @@ def load(cls, env): # type: (Env) -> InstalledRepository

is_standard_package = env.is_path_relative_to_lib(path)

src_path = env.path / "src"

if is_standard_package:
if path.name.endswith(".dist-info"):
paths = cls.get_package_paths(
sitedir=env.site_packages, name=package.pretty_name
)
paths = cls.get_package_paths(env=env, name=package.pretty_name)
if paths:
# TODO: handle multiple source directories?
package.source_type = "directory"
package.source_url = paths.pop().as_posix()

for src in paths:
try:
src.relative_to(src_path)
cls._set_git_package_properties(
src_path / package.name, package
)
break
except ValueError:
continue
else:
# TODO: handle multiple source directories?
package.source_type = "directory"
package.source_url = paths.pop().as_posix()
continue

src_path = env.path / "src"

# A VCS dependency should have been installed
# in the src directory. If not, it's a path dependency
try:
path.relative_to(src_path)

from poetry.core.vcs.git import Git

git = Git()
revision = git.rev_parse("HEAD", src_path / package.name).strip()
url = git.remote_url(src_path / package.name)

package.source_type = "git"
package.source_url = url
package.source_reference = revision
cls._set_git_package_properties(src_path / package.name, package)
except ValueError:
package.source_type = "directory"
package.source_url = str(path.parent)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Metadata-Version: 2.1
Name: bender
Version: 2.0.5
Summary: Python datetimes made easy
License: MIT
Keywords: cli,commands
Author: Leela
Author-email: leela@planetexpress.com
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Description-Content-Type: text/x-rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
../../../src/bender
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Metadata-Version: 2.1
Name: bender
Version: 2.0.5
Summary: Python datetimes made easy
License: MIT
Keywords: cli,commands
Author: Leela
Author-email: leela@planetexpress.com
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Description-Content-Type: text/x-rst
14 changes: 13 additions & 1 deletion tests/repositories/test_installed_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
metadata.PathDistribution(SITE_PURELIB / "editable-2.3.4.dist-info"),
metadata.PathDistribution(SITE_PURELIB / "editable-with-import-2.3.4.dist-info"),
metadata.PathDistribution(SITE_PLATLIB / "lib64-2.3.4.dist-info"),
metadata.PathDistribution(SITE_PLATLIB / "bender-2.0.5.dist-info"),
]


Expand Down Expand Up @@ -110,10 +111,21 @@ def test_load_git_package(repository):
assert pendulum.version.text == "2.0.5"
assert pendulum.description == "Python datetimes made easy"
assert pendulum.source_type == "git"
assert pendulum.source_url == "https://github.com/sdispater/pendulum.git"
assert pendulum.source_url in [
"git@github.com:sdispater/pendulum.git",
"https://github.com/sdispater/pendulum.git",
]
assert pendulum.source_reference == "bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6"


def test_load_git_package_pth(repository):
bender = get_package_from_repository("bender", repository)
assert bender is not None
assert bender.name == "bender"
assert bender.version.text == "2.0.5"
assert bender.source_type == "git"


def test_load_platlib_package(repository):
lib64 = get_package_from_repository("lib64", repository)
assert lib64 is not None
Expand Down

0 comments on commit 626bdd0

Please sign in to comment.