api lockfile (api.lock)¶
by generate-api-file produces a deterministic, line-oriented summary of
the public type-level surface of a project. the file is meant to be
committed alongside the source and reviewed as a diff: any change to the
public api shows up as a line-level change in the lockfile
by generate-api-file # writes ./api.lock
by generate-api-file --stdout # writes to stdout
by generate-api-file -o public.lock
workflow¶
- commit
api.lockto version control next topyproject.toml - in CI, regenerate the lockfile and fail if
git diff --exit-code api.lockis non-empty - during code review, the diff is the api change. a reviewer who approves the diff has approved the api change
record grammar¶
each non-header line is one record. fields are colon-separated. the first
line is the format-version header (#api-lock:v=1); the remaining lines
are sorted lexicographically
<qualified>:c[<bases>] # class
<qualified>:c<tv>[<bases>] # generic class
<qualified>:c[<bases>]{<flags>} # class with flags
<qualified>:d(<params>)-><ret> # def / method
<qualified>:d{<deco>}<tv>(<params>)-><ret> # def with decorators / typevars
<qualified>:v=<type> # variable / class attribute
<qualified>:v[<quals>]=<type> # qualified variable
<qualified>:i=<type> # instance attribute (via self.x)
<qualified>:t=<type> # type alias
<qualified>:t<tv>=<type> # generic type alias
<qualified>:p=getter|setter|deleter,... # property accessors
<qualified>:r=<target> # re-export of class/function/alias
<qualified>:m=<module> # module re-export
<qualified> is the dotted path from the project root: pkg.mod.ClassName.method
<tv> is <variance? name, ...> — +T covariant, -T contravariant,
*Ts typevar-tuple, plain T invariant
<flags> joins on ,: dataclass, enum, final, named_tuple,
protocol, typed_dict
<deco> joins on ,: abstractmethod, async, classmethod,
deprecated, final, no_type_check, overload, override, property,
staticmethod, type_check_only
<quals> joins on ,: classvar, final, initvar, notrequired,
readonly, required
what's included¶
- module-level functions, classes, type aliases, variables, and re-exports
whose name does not start with
_ - instance attributes assigned via
self.x = ...inside__init__ - dunders conventionally part of the public surface (
__all__,__author__,__doc__,__version__)
what's excluded¶
- any symbol whose simple name starts with
_(unless it's one of the conventional public dunders above) - stdlib, site-packages, and other non-first-party modules
- output from
by build— theout/directory is not considered first-party source for lockfile purposes
determinism and stability¶
lockfile lines are sorted lexicographically and union members are written in a canonical order, so two runs against the same source produce byte-identical output
python-version sensitivity¶
by generate-api-file --python-version 3.10 and --python-version 3.13
can produce materially different lockfiles for the same source, because
many typing constructs (Self, Required, NotRequired, LiteralString,
…) are only resolvable on newer targets. for libraries that support a
range of python versions, pick the lowest supported version as the
canonical lockfile target