project.yaml¶
Project identity¶
project.yaml opens with the same descriptive metadata that
pyproject.toml's [project] table carries: a name, a version, a short
description, and a pointer to the readme file.
name: acme-inference
version: "2.3.0"
description: Inference serving for Acme models
readme: README.rst
project.yaml and listed under dynamic
instead, when its value is computed rather than written by hand, for example a
version stamped in from a version-control tag:
Lucid version¶
lucid is the required-requires-python: a version specifier for the
Lucid toolchain the project needs.
lucid names the toolchain that both runs and builds a project,
project.yaml has no counterpart to pyproject.toml's [build-system]
table. There is no separate build backend to select or pin; the lucid
version specifier already pins the one toolchain that builds and runs the
project.
License¶
license is an SPDX license expression, and license-files is a list of
glob patterns for the license text to distribute, following the same model as
the modern pyproject.toml license fields:
People and links¶
authors and maintainers are lists of name/email pairs. keywords
and classifiers describe the project for a package index. urls is a
mapping of labels to links:
authors:
- name: Ada Lovelace
email: ada@example.com
maintainers:
- name: Grace Hopper
email: grace@example.com
keywords:
- inference
- serving
classifiers:
- "Intended Audience :: Developers"
urls:
Homepage: https://example.com/acme-inference
Documentation: https://example.com/acme-inference/docs
Repository: https://example.com/acme-inference.git
Issues: https://example.com/acme-inference/issues
Dependencies¶
dependencies is a mapping from a required project's name to a version
specifier, in place of pyproject.toml's flat list of requirement strings:
library.initialize walks to topologically sort library initialization (see
Library initialization below), so a project's dependency list and its
initialization order come from one declaration instead of two.
optional-dependencies declares installable extras the same way
pyproject.toml does: named groups of additional dependencies that a
consumer can opt into.
development.yaml's
Development dependencies.
Public API¶
export is a tree mapping the paths a project makes public to where
they actually live — the one place a project's externally visible
surface is declared, full stop:
export promotes something the project
already exposes to itself into something the outside world can reach
too, but it cannot reach past a leading underscore to expose what the
project keeps to itself.
No __module__ or __qualname__¶
Python spreads a symbol's location across two attributes: __module__
(the dotted module it was defined in) and __qualname__ (its lexical
nesting within that module, for anything declared inside a class or
function). Two attributes for one concept is two chances for them to
disagree, and both encode wherever a symbol happens to be defined —
exactly the internal layout Public API already keeps out of everything
else a project exposes.
Lucid folds both into one, __path__: !DottedPath. DottedPath is a
Sequence[str] of the location's segments — indexing and slicing it
work exactly like any other sequence of strings — and its __str__
joins them with dots, so printing a path and inspecting its segments are
just two views of the same value. It is frozen (!, see
Mutable, read-only, and immutable views) because a
symbol's location does not change after it is computed. __name__
stays exactly as it already is, the bare identifier, always equal to
path[-1]:
str(slow_query.__path__) # "acme_inference.queries.slow_query"
slow_query.__path__[-1] # "slow_query"
slow_query.__name__ # "slow_query"
__path__. By
default it holds the symbol's own defining location — project name, then
module path, then lexical nesting — exactly what __module__ and
__qualname__ used to spell out between them. Flattening the two into
one sequence does mean the boundary between them is gone: for a method
nested inside a class, __path__ no longer says which prefix was the
module and which was the class nesting, the way __module__ and
__qualname__ separately did. Nothing in Lucid needs that boundary —
the segments as a whole, or just the trailing name, cover every actual
use — and the rare code that wants "which module is this in" asks the
containing module directly rather than parsing a path apart. A symbol
named in export: gets its __path__
overridden instead, to the path the tree actually declares for it, so a
symbol's visible identity matches how the outside world reaches it rather
than wherever it happens to live inside the project:
str(User.__path__) # "acme_inference.models.User" -- the export path,
# not wherever .models.User actually lives
export: tree is already a trie: one path segment per
level, an internal dotted location at every leaf. Walking it once builds
the reverse of it too — a hash table from each leaf's internal location to
the segment list leading there — and that table is exactly the set of
overrides applied to produce every exported symbol's __path__.
Local aliases¶
local-alias declares a tree of aliases that remap paths for local use
inside the project. Aliases can flatten an internal source layout, for example
mapping an internal ._src package back onto the project root, or promote a
deeply nested definition to a short local path:
export and local-alias, a project has no remaining need for
__init__.py-style re-exporting or flattening modules.
Library initialization¶
library-context names a context manager (see
Context managers), holding the setup work that
Python would otherwise run as side effects in __init__.py, such as
configuring an underlying native library:
library.initialize enters it:
with library.initialize({"numpy": numpy_params, "acme-inference": project_params}):
run_entry_point()
library-context is entered in dependency
order: library.initialize topologically sorts the libraries being
initialized using the dependencies declared in each project's
project.yaml, so a library is initialized after every library it depends
on.
Entry points¶
entry-points is a mapping of names to paths: the runnable commands a
project exposes, for example to the command line, in place of
pyproject.toml's [project.scripts] table:
library.initialize; see
Library initialization.