Skip to content

← Modules, Packaging and Tooling step 33 of 41

Medium Primitives

Parse an Entry-Point Reference

An entry point such as pricing = "pricing.cli:main" stores its target as a string. Before a tool imports anything, it splits that string into a module, an attribute path and optional extras. Write that parser. It checks only the spelling, and it never imports a module or looks up an attribute.

ObjectRef = tuple[str, tuple[str, ...], tuple[str, ...]]

def parse_entry_point(spec: str) -> ObjectRef: ...

Return (module, attrs, extras). The input follows this grammar, a simplified form of the real one:

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._-]*
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
pkg.mod[] ValueError

Rules

  • Allow whitespace at the start and the end, around the colon, before the opening bracket, and around each extra inside the brackets. Treat whitespace the way str.strip() does.
  • Reject whitespace inside a dotted name or an extra name.
  • Names are ASCII. Apply the character rules exactly as written, so a keyword such as class counts as a valid name.
  • Do not check whether a module or an attribute exists.
  • Keep the extras' spelling, order and duplicates.
  • Raise ValueError for any other input. That includes an empty name, an empty extra, a missing or repeated bracket, and a second colon. A colon needs an attribute path after it, and a dot needs a valid name on each side.

Extras in entry points are a legacy feature, and new metadata should not use them. They are here for parsing practice.

The driver

Complete solve(spec). On success, return ("ok", module, attrs, extras). If parse_entry_point raises ValueError, return ("invalid", "", (), ()). Keep the Literal return annotation, and return tuples, not lists, for attrs and extras.

A reference that parses can still point at nothing. A console script, for example, also needs a target that works when called with no arguments.