We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Seams, Modules, Packaging and Tooling step 27 of 36
Parsing an entry-point object reference
Implement the parser an installer runs over every [project.scripts] line
before it can generate a wrapper.
ObjectRef = tuple[str, tuple[str, ...], tuple[str, ...]]
def parse_entry_point(spec: str) -> ObjectRef:
Return (module, attrs, extras). The grammar, which you should implement
exactly as written here:
entry-point = module [ ":" attrs ] [ extras ]
module = identifier ("." identifier)*
attrs = identifier ("." identifier)*
extras = "[" extra ("," extra)* "]"
identifier = [A-Za-z_][A-Za-z0-9_]*
extra = [A-Za-z0-9_][A-Za-z0-9._-]*
Whitespace is permitted around the whole reference, around the :, and
inside the brackets. Anything that does not match — an empty module, an empty
attribute path, a segment that is not an identifier, an unbalanced bracket,
an empty extras list — raises ValueError.
Examples:
| Input | Result |
|---|---|
"pkg.mod" |
("pkg.mod", (), ()) |
"pkg.mod:Class.method" |
("pkg.mod", ("Class", "method"), ()) |
"pkg.mod:main [extra1,extra2]" |
("pkg.mod", ("main",), ("extra1", "extra2")) |
":main" |
ValueError |
"pkg.mod:" |
ValueError |
Because the harness compares return values rather than exceptions, the graded entrypoint is a driver:
def solve(spec: str) -> tuple[Literal["ok", "invalid"], str, tuple[str, ...], tuple[str, ...]]:
("ok", module, attrs, extras) on success, and ("invalid", "", (), ()) when
parse_entry_point raises. Write the real function properly and let the
driver catch — the point is that the parser has one job and reports failure by
raising, not by returning a sentinel that every caller must remember to check.
Why validation, and not just split(":"). This string ends up inside a
generated wrapper script that an installer writes into someone’s bin/
directory. A malformed reference that is accepted here becomes an executable
that fails at invocation with an import error, on a user’s machine, long
after anything can be done about it. Rejecting "pkg-mod:main" at build time
costs nothing; accepting it costs a bug report.
Returns a 4-tuple containing two tuples, not lists. The harness compares
container types exactly, which is the point: a caller doing
getattr down attrs needs a fixed-length sequence, not something it can
accidentally mutate.
Your submission must pass mypy --strict, including the Literal tag on the
driver’s return type.
Stuck?
Python reference solution
Sign in to attempt this problem and reveal the reference solution.