Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve exception/traceback when invalid entry-points are specified #3684

Merged
merged 2 commits into from Nov 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 9 additions & 1 deletion setuptools/_entry_points.py
Expand Up @@ -2,6 +2,7 @@
import operator
import itertools

from .errors import OptionError
from .extern.jaraco.text import yield_lines
from .extern.jaraco.functools import pass_none
from ._importlib import metadata
Expand All @@ -14,7 +15,14 @@ def ensure_valid(ep):
Exercise one of the dynamic properties to trigger
the pattern match.
"""
ep.extras
try:
ep.extras
except AttributeError as ex:
msg = (
f"Problems to parse {ep}.\nPlease ensure entry-point follows the spec: "
"https://packaging.python.org/en/latest/specifications/entry-points/"
)
raise OptionError(msg) from ex


def load_group(value, group):
Expand Down
75 changes: 53 additions & 22 deletions setuptools/tests/test_egg_info.py
Expand Up @@ -6,12 +6,18 @@
import stat
import time
from typing import List, Tuple
from pathlib import Path

import pytest
from jaraco import path

from setuptools import errors
from setuptools.command.egg_info import (
egg_info, manifest_maker, EggInfoDeprecationWarning, get_pkg_info_revision,
EggInfoDeprecationWarning,
egg_info,
get_pkg_info_revision,
manifest_maker,
write_entries,
)
from setuptools.dist import Distribution

Expand All @@ -24,6 +30,28 @@ class Environment(str):
pass


@pytest.fixture
def env():
with contexts.tempdir(prefix='setuptools-test.') as env_dir:
env = Environment(env_dir)
os.chmod(env_dir, stat.S_IRWXU)
subs = 'home', 'lib', 'scripts', 'data', 'egg-base'
env.paths = dict(
(dirname, os.path.join(env_dir, dirname))
for dirname in subs
)
list(map(os.mkdir, env.paths.values()))
path.build({
env.paths['home']: {
'.pydistutils.cfg': DALS("""
[egg_info]
egg-base = %(egg-base)s
""" % env.paths)
}
})
yield env


class TestEggInfo:

setup_script = DALS("""
Expand Down Expand Up @@ -51,27 +79,6 @@ def _extract_mv_version(pkg_info_lines: List[str]) -> Tuple[int, int]:
version_str = pkg_info_lines[0].split(' ')[1]
return tuple(map(int, version_str.split('.')[:2]))

@pytest.fixture
def env(self):
with contexts.tempdir(prefix='setuptools-test.') as env_dir:
env = Environment(env_dir)
os.chmod(env_dir, stat.S_IRWXU)
subs = 'home', 'lib', 'scripts', 'data', 'egg-base'
env.paths = dict(
(dirname, os.path.join(env_dir, dirname))
for dirname in subs
)
list(map(os.mkdir, env.paths.values()))
path.build({
env.paths['home']: {
'.pydistutils.cfg': DALS("""
[egg_info]
egg-base = %(egg-base)s
""" % env.paths)
}
})
yield env

def test_egg_info_save_version_info_setup_empty(self, tmpdir_cwd, env):
"""
When the egg_info section is empty or not present, running
Expand Down Expand Up @@ -1084,3 +1091,27 @@ def test_egg_info_tag_only_once(self, tmpdir_cwd, env):

def test_get_pkg_info_revision_deprecated(self):
pytest.warns(EggInfoDeprecationWarning, get_pkg_info_revision)


class TestWriteEntries:

def test_invalid_entry_point(self, tmpdir_cwd, env):
dist = Distribution({"name": "foo", "version": "0.0.1"})
dist.entry_points = {"foo": "foo = invalid-identifier:foo"}
cmd = dist.get_command_obj("egg_info")
expected_msg = r"Problems to parse .*invalid-identifier.*"
with pytest.raises(errors.OptionError, match=expected_msg) as ex:
write_entries(cmd, "entry_points", "entry_points.txt")
assert "ensure entry-point follows the spec" in ex.value.args[0]

def test_valid_entry_point(self, tmpdir_cwd, env):
dist = Distribution({"name": "foo", "version": "0.0.1"})
dist.entry_points = {
"abc": "foo = bar:baz",
"def": ["faa = bor:boz"],
}
cmd = dist.get_command_obj("egg_info")
write_entries(cmd, "entry_points", "entry_points.txt")
content = Path("entry_points.txt").read_text(encoding="utf-8")
assert "[abc]\nfoo = bar:baz\n" in content
assert "[def]\nfaa = bor:boz\n" in content