Skip to content

Commit

Permalink
Merge pull request #119 from wimglenn/entry_points
Browse files Browse the repository at this point in the history
Entry points
  • Loading branch information
wimglenn authored May 6, 2023
2 parents 2b20984 + be2e314 commit a0d7ded
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 12 deletions.
2 changes: 1 addition & 1 deletion johnnydep/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Display dependency tree of Python distribution"""

__version__ = "1.18.0"
__version__ = "1.19.0"

from johnnydep.lib import *
1 change: 1 addition & 0 deletions johnnydep/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
("requires", "Immediate dependencies"),
("required_by", "Parent(s) in the tree"),
("import_names", "Python imports provided (top-level names only)"),
("console_scripts", "Entry points in the console_scripts group"),
("homepage", "Project URL"),
("extras_available", "Optional extensions available for the distribution"),
("extras_requested", "Optional extensions parsed from requirement specifier"),
Expand Down
10 changes: 8 additions & 2 deletions johnnydep/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ def urlretrieve(url, filename, data=None, auth=None):


try:
from importlib.metadata import distribution, PackageNotFoundError
from importlib.metadata import distribution, PackageNotFoundError, PathDistribution
except ImportError:
from importlib_metadata import distribution, PackageNotFoundError
from importlib_metadata import distribution, PackageNotFoundError, PathDistribution


try:
from zipfile import Path as zipfile_path
except ImportError:
from zipfile39 import Path as zipfile_path
38 changes: 30 additions & 8 deletions johnnydep/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
from johnnydep.compat import distribution
from johnnydep.compat import oyaml
from johnnydep.compat import PackageNotFoundError
from johnnydep.compat import PathDistribution
from johnnydep.compat import zipfile_path
from johnnydep.dot import jd2dot
from johnnydep.util import CircularMarker

Expand Down Expand Up @@ -70,6 +72,7 @@ def __init__(self, req_string, parent=None, index_url=None, env=None, extra_inde
self.req = requirements.Requirement(self.name + sep + extras + self.specifier)
self.import_names = _discover_import_names(fname)
self.metadata = _extract_metadata(fname)
self.entry_points = _discover_entry_points(fname)
self._from_fname = os.path.abspath(fname)
else:
self._from_fname = None
Expand All @@ -78,7 +81,7 @@ def __init__(self, req_string, parent=None, index_url=None, env=None, extra_inde
self.specifier = str(self.req.specifier)
log.debug("fetching best wheel")
try:
self.import_names, self.metadata = _get_info(
self.import_names, self.metadata, self.entry_points = _get_info(
dist_name=req_string,
index_url=index_url,
env=env,
Expand All @@ -89,6 +92,7 @@ def __init__(self, req_string, parent=None, index_url=None, env=None, extra_inde
raise
self.import_names = None
self.metadata = {}
self.entry_points = None
self.error = err

self.extras_requested = sorted(self.req.extras)
Expand Down Expand Up @@ -249,6 +253,11 @@ def extras_available(self):
def project_name(self):
return self.metadata.get("name", self.name)

@property
def console_scripts(self):
eps = [ep for ep in self.entry_points or [] if ep.group == "console_scripts"]
return ", ".join(["{} = {}".format(ep.name, ep.value) for ep in eps])

@property
def pinned(self):
if self.extras_requested:
Expand Down Expand Up @@ -420,9 +429,9 @@ def flatten_deps(johnnydist):

def _discover_import_names(whl_file):
log = logger.bind(whl_file=whl_file)
logger.debug("finding import names")
zipfile = ZipFile(file=whl_file)
namelist = zipfile.namelist()
log.debug("finding import names")
zf = ZipFile(file=whl_file)
namelist = zf.namelist()
try:
[top_level_fname] = [x for x in namelist if x.endswith("top_level.txt")]
except ValueError:
Expand All @@ -447,13 +456,25 @@ def _discover_import_names(whl_file):
# found a top level module
public_names.append(name)
else:
all_names = zipfile.read(top_level_fname).decode("utf-8").strip().splitlines()
all_names = zf.read(top_level_fname).decode("utf-8").strip().splitlines()
public_names = [n for n in all_names if not n.startswith("_")]
return public_names
result = [n.replace("/", ".") for n in public_names]
return result


def _discover_entry_points(whl_file):
log = logger.bind(whl_file=whl_file)
log.debug("finding entry points")
parts = os.path.basename(whl_file).split("-")
metadata_path = "-".join(parts[:2]) + ".dist-info/"
zf_path = zipfile_path(whl_file, metadata_path)
path_dist = PathDistribution(zf_path)
return path_dist.entry_points


def _extract_metadata(whl_file):
logger.debug("searching metadata", whl_file=whl_file)
log = logger.bind(whl_file=whl_file)
log.debug("searching metadata", whl_file=whl_file)
info = pkginfo.get_metadata(whl_file)
if info is None:
raise JohnnyError("failed to get metadata")
Expand Down Expand Up @@ -486,10 +507,11 @@ def _get_info(dist_name, index_url=None, env=None, extra_index_url=None):
# downloaded file can be cleaned up immediately
import_names = _discover_import_names(dist_path)
metadata = _extract_metadata(dist_path)
entry_points = _discover_entry_points(dist_path)
finally:
log.debug("removing scratch", tmpdir=tmpdir)
rmtree(tmpdir, ignore_errors=True)
return import_names, metadata
return import_names, metadata, entry_points


# TODO: multi-line progress bar?
Expand Down
2 changes: 1 addition & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ pytest-raisin
pytest-socket
coverage
wheel
whl >= 0.0.3
whl >= 0.0.4
wimpy == 0.3 # just something we can pin
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"wheel >= 0.32.0",
"pkginfo >= 1.4.2",
"importlib_metadata ; python_version < '3.7'",
"zipfile39 ; python_version < '3.9'",
],
entry_points={
"console_scripts": [
Expand Down
1 change: 1 addition & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ def test_all_fields_toml_out(mocker, capsys, make_dist):
requires = []
required_by = []
import_names = [ "that",]
console_scripts = ""
homepage = "https://www.example.org/default"
extras_available = []
extras_requested = []
Expand Down
12 changes: 12 additions & 0 deletions tests/test_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,3 +537,15 @@ def test_local_whl_json(make_dist):
assert link.startswith("file://")
assert link.endswith("loc-0.1.2-py2.py3-none-any.whl")
assert result["versions_available"] == ["0.1.1", "0.1.2", "0.1.3"]


def test_entry_points(make_dist):
# https://packaging.python.org/en/latest/specifications/entry-points/
entry_points = {"console_scripts": ["my-script = mypkg.mymod:foo"]}
make_dist(name="example", entry_points=entry_points)
dist = JohnnyDist("example")
[ep] = dist.entry_points
assert ep.name == "my-script"
assert ep.group == "console_scripts"
assert ep.value == "mypkg.mymod:foo"
assert dist.console_scripts == "my-script = mypkg.mymod:foo"

0 comments on commit a0d7ded

Please sign in to comment.