Modules and Packaging¶
This example creates a package whose public surface contains a type and two procedures while its parsing helper remains private.
Directory Layout¶
Package Entry Module¶
catalog/src/catalog/main.kedi:
~Product(name: str, price: float)
@_normalize_name(name: str) -> str:
= `name.strip().title()`
@make_product(name: str, price: float) -> Product:
= `Product(name=_normalize_name(name), price=price)`
@inventory_value(products: list[Product]) -> float:
= `sum(product.price for product in products)`
> export:
Product
make_product
inventory_value
Only exported names enter an importer. _normalize_name remains private even
though exported procedures can use it.
Nested Module¶
catalog/src/catalog/formatting.kedi:
@format_currency(value: float) -> str:
= `f"${value:,.2f}"`
> export:
format_currency
Manifest¶
catalog/package.kedi:
> package: catalog:
version: 1.0.0
source: src/catalog
python: python@3.11-3.14
python_dependencies:
pydantic>=2
The manifest is declarative only. It records PEP 508 dependencies but does not install them into the active Python environment.
Install and Consume¶
From catalog/:
consumer/report.kedi:
> import: catalog:
Product
make_product
inventory_value
> import: catalog/formatting:
format_currency
[products: list[Product]] = `[
make_product("keyboard", 120.0),
make_product("mouse", 45.5),
]`
[total: float] = `inventory_value(products)`
= `format_currency(total)`
Selective imports place the listed names directly in scope; they do not create
a catalog namespace object. Imports resolve at their source position, and a
module initializes at most once per root compilation.
Local Development Without Installation¶
Sibling modules resolve relative to the importing file:
> import: formatting:
format_currency
Use relative modules while developing one project. Install a package when its root import must be available to unrelated projects. Third-party packages can execute embedded Python with the importing process's permissions; package integrity is not a sandbox.