NORP-Core
A pure, domain-neutral meta-framework kernel.
NORP-Core is a minimal kernel for assembling software out of pluggable parts. It assumes no upper-layer implementation and no particular domain: it is the four non-replaceable components plus the registration triad and the machinery they need. Any program - a service, a CLI, a game loop, a compiler, a build tool
- can build on it and declare its own slots, hook layers, event vocabulary and component kinds.
The direction of dependency is strictly one-way:
host / application (any concrete software)
|
v
NORP-Core
|
v
Python standard library
NORP-Core never imports an upper layer.
The kernel
Exactly four non-replaceable components, plus supporting machinery:
| # | Component | Module | Responsibility |
|---|---|---|---|
| 1 | Slot connector | norp_core.layer.ArchLayer |
assemble slot values into implementations, hot-mount |
| 2 | Address resolver | norp_core.address.resolve_address |
turn an address string into an object |
| 3 | Registry | norp_core.registry.Registry |
generic kind -> name -> object store |
| 4 | Event bus | norp_core.events.EventBus |
the only decoupling point |
Supporting machinery:
norp_core.slots- the slot table (mechanism only; ships no slots);norp_core.hooks- the hook mechanism (HookSystem/HookLayer/Hook/BoundHook; ships no standard hook layers);- the registration triad
register_slot/register_layer/register_hook.
Domain neutrality
The kernel understands only generic software concepts - a slot, a hook, an event, an address, a layer, a registry. It contains no domain vocabulary and no baked-in assumption about what is being assembled:
| Guarantee | How |
|---|---|
| no fixed event vocabulary | event names are free-form strings chosen by the host |
| no pre-defined slots | SLOT_SPECS starts empty; the host calls register_slot |
| no standard hook layers | HookSystem.standard_layers() returns [] |
| no assumed component kinds | Registry is generic kind -> name -> object |
| no special slot names baked in | string passthrough is opt-in via register_passthrough_slot |
| no special dict-value handling | callables in dict values are controlled per-slot by SlotSpec.call_dict_factories |
| no host concept of its own | Registry.extras is an opaque host extension point the kernel never inspects |
An upper layer that wants any of the above simply declares it:
# a host declares its own slots (the kernel ships none)
core.register_slot(core.SlotSpec(
name="storage",
description="where data is persisted",
protocol="StorageProtocol",
string_semantics="name_or_address",
call_dict_factories=False, # this slot's dict values are callbacks
), builtin=True)
# a host declares its own hook layers
core.register_layer(name="net", order=100,
hooks={"before_request": {"mutating": True}})
# a host declares its own event topics just by emitting them
bus.emit("before_request", url="...")
Layout
core/
pyproject.toml # distribution: norpcore (import name norp_core)
README.md # this file
LICENSE # MIT
publish_pypi.ps1 # build + PyPI publish helper (PowerShell, primary)
release.ps1 # build + PyPI publish helper (PowerShell, legacy)
release.py # build + PyPI publish helper (Python, legacy)
.gitignore
norp_core/
__init__.py # the whole public surface
py.typed # PEP 561 typing marker
events.py # component 4: EventBus / Event / HookVeto
registry.py # component 3: Registry / ComponentError
address.py # component 2: resolve_address / is_address_like / AddressError
layer.py # component 1: ArchLayer / call_factory / register_passthrough_slot
slots.py # slot table mechanism (no built-in slots)
hooks.py # hook mechanism + register_layer / register_hook
tests/
test_norp_core.py # functional tests for all four components + triad
test_purity.py # import-graph purity: NORP-Core leaks no upper layer
Quick start
import norp_core as core
# 1. declare slots (NORP-Core ships none)
core.register_slot(core.SlotSpec(
name="service",
description="a pluggable service",
protocol="ServiceProtocol",
string_semantics="name_or_address",
))
# 2. register components by kind (kinds are chosen by the host)
reg = core.Registry()
reg.register("service", "mock", lambda: MyMockService())
# 3. assemble
layer = core.ArchLayer(service="mock")
layer.set_default("service", lambda ctx: reg.build("service", "mock"))
layer.connect()
svc = layer["service"]
# 4. wire the hooks / event bus
system = core.HookSystem(reg.bus)
core.register_layer(name="L1", hooks={"before_start": {"mutating": True}},
system=system)
core.register_hook("before_start", my_guard, system=system)
Testing
cd core
python tests/test_norp_core.py # functional
python tests/test_purity.py # purity (no upper-layer imports)
# or, with pytest installed:
pytest -q
test_purity.py launches a fresh interpreter, imports norp_core, and asserts
that no top-level module of an upper layer appears in sys.modules, and that
every newly imported module is either the standard library or norp_core itself.
It also statically scans the sources so a lazy import cannot sneak in.
Releasing
The distribution name is norpcore (the import name stays norp_core).
publish_pypi.ps1 is the primary one-command build-and-publish helper. It:
- checks version consistency between
pyproject.tomlandnorp_core/__init__.py; - checks the Python /
build/twineenvironment; - removes stale
dist/artifacts of the SAME version; - builds the sdist and wheel with
python -m build; - verifies the built wheel carries the declared version;
- validates the packages with
twine check; - resolves credentials, then uploads to the chosen index.
PowerShell
pip install -e ".[release]" # build + twine
.\publish_pypi.ps1 -CheckOnly # build + validate, no upload
.\publish_pypi.ps1 -DryRun # preview the upload command
.\publish_pypi.ps1 -Target testpypi -Token "pypi-xxxxxxxx"
.\publish_pypi.ps1 -Target pypi -Token "pypi-xxxxxxxx" -Force
Pass the publish token straight in with -Token to customise the credential for
a single run; if -Token is omitted the script reads PYPI_TOKEN /
TESTPYPI_TOKEN / TWINE_PASSWORD and finally falls back to ~/.pypirc, or
prompts for a masked token. The token is never written to disk or echoed.
Other flags: -SkipBuild, -SkipExisting, -Force (skip the confirmation).
If Windows blocks the script, run it with
powershell -ExecutionPolicy Bypass -File .\publish_pypi.ps1 ....
Legacy helpers
release.ps1 and release.py are the earlier equivalent helpers (test suite +
clean + build + twine check + optional upload). Credentials there are read from
PYPI_API_TOKEN / TESTPYPI_API_TOKEN or ~/.pypirc:
.\release.ps1 -BuildOnly
.\release.ps1 -Target pypi -Token "pypi-xxxxxxxx" -Yes
python release.py --build-only
python release.py --target pypi
The distribution is licensed under the MIT License — see LICENSE.
Metadata
Release files for norpcore 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| norpcore-0.1.0.tar.gz | 30.0 kB | Without provenance | Details for norpcore-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| norpcore-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for norpcore-0.1.0-py3-none-any.whl |
Total release size: 56.8 kB
Release files / norpcore-0.1.0.tar.gz
| Download URL | norpcore-0.1.0.tar.gz |
|---|---|
| Size | 30.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b635f2978dd01025e6f6636417451f0a7fabfb75bdac65ec5290be4244255cdf
|
|
BLAKE2b-256 checksum How to use checksums |
d1decb48252a4c4cdff24200f1d201d644a8ce2902f8801de211a1a23f949db7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / norpcore-0.1.0-py3-none-any.whl
| Download URL | norpcore-0.1.0-py3-none-any.whl |
|---|---|
| Size | 26.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5bc6e77919996a72828a2728bcc4aac3567f4b714664129bde6c1530a5863981
|
|
BLAKE2b-256 checksum How to use checksums |
6fcaa8db3bb6d9bfda40b2ce257296032067485f152ccaf84722b2b3d640fbc4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Security for norpcore 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.