Skip to content

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

catalog/
  package.kedi
  src/
    catalog/
      main.kedi
      formatting.kedi
consumer/
  report.kedi

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/:

kedi install

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.