Skip to main content

SPOC

title-image

License: MIT Language GitHub PyPI Downloads

Build a framework in 30 lines

Say what kinds of things your app has:

import spoc

framework = spoc.Framework("models", "commands", "views")

model = framework.kind("models")
command = framework.kind("commands")
view = framework.kind("views")

Tag your code with them, anywhere in the project:

from framework import model


@model
class Post:
    """Registers as models:blog.post."""
from framework import command


@command
def publish(title: str = "Hello, SPOC") -> str:
    """Registers as commands:blog.publish."""
    return f"published {title!r}"
from framework import view


@view
def posts_api() -> list[str]:
    """Registers as views:blog.posts_api."""
    return []
[spoc.apps]
development = ["apps.blog"]
from pathlib import Path

from framework import framework

framework.start(Path(__file__).resolve().parent)

That's it — no registry to wire up, no list to keep in sync. Ask SPOC what it found:

spoc check
spoc list
spoc stubs
OK: /path/to/blog checks out clean
commands:blog.publish
models:blog.post
views:blog.posts_api
wrote framework.pyi (3 identifiers)

SPOC turns your application's declarations into one typed, inspectable registry.

check dry-boots your project and reports what's wrong before anything runs. list reads the shelf. stubs writes real autocomplete for every name you just typed — so framework.objects.models.blog.post completes in your editor before you've written a single test. Add a fourth decorated function tomorrow; all three commands see it with no edit to any of these files.

See it work without writing a file

pip install spoc
spoc init myproject --template starter
cd myproject && python main.py --help
usage: myproject [-h] {core.add,core.items} ...

positional arguments:
  {core.add,core.items}
    core.add            Add an item to the store.
    core.items          List the items in the store.

options:
  -h, --help            show this help message and exit

Nobody wrote that command list. It was derived from what the generated app registered — the same trick as above, scaffolded for you. uvx spoc init myproject works with nothing installed at all.

What you get

  • One name per component, always. Class names derive their own. Ask for a name that isn't there and the error says which segment was wrong and what would have matched — never a silent None.
  • Autocomplete, with no code changes. spoc stubs writes a type stub beside your entry point: names complete as you type, components come back as their real types, typos become editor errors. spoc projection emits the same registry as JSON for tools in any language.
  • A lifecycle you can reason about. Modules start in dependency order and stop in reverse, sync or async.
  • Problems found before runtime. spoc check dry-boots and reports config errors, cycles, collisions, and sync/async mismatches. spoc list and spoc explain read the registry from your terminal.
  • Tests in the box. spoc.testing gives isolated framework scopes and an app-tree builder, arriving as ready-made pytest fixtures.
  • Zero dependencies. dependencies = [], enforced. Optional data-format codecs live behind extras (pip install "spoc[full]").

SPOC never runs your components. FastAPI still serves your HTTP, Typer still parses your argv, Celery still runs your jobs. SPOC only answers what does this app contain, and under what name — how architecture, names, and lifecycle work underneath is in the docs.

Should you use it?

Yes, if…

  • one codebase feeds several surfaces — HTTP and CLI and workers — and each re-discovers the same components its own way.
  • you are shipping a framework other people write apps against.
  • things must start in dependency order and stop in reverse.
  • a mistyped component name should be an editor error, not a None at 3am.

No, if…

  • it's one app, one surface, a handful of modules. Imports are cheaper. SPOC pays off above a complexity threshold, not below it.
  • you are already on Django. Its app registry is a structural model.
  • you want something that runs your components. SPOC only names and orders them.

Weighing it against imports, entry points, pluggy, or a DI container specifically? Why not just…? has the one-line answer for each.

Install

Python 3.12+

pip install spoc

The generated project imports spoc at runtime, so install it where you run the project from — installation guide.

Documentation

Read the docs — tutorials, how-to guides, and the full API reference.

A good path in: your first project → names & the registry → build a framework.

Stability

SPOC is 1.0. A public name changes incompatibly only in a major release, and only after a completed deprecation cycle — so spoc>=1.0,<2 is the pin that matters. Every name, command, and extra carries a tier (public, provisional, internal), and both the tiers and every change to them are checked on each CI run.

Stability & Versioning — the tiers, the deprecation lifecycle, and the criteria 1.0 was cut against.

Links

Metadata

Release files for spoc 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for spoc 0.9.0
File Size Uploaded Provenance
spoc-0.9.0.tar.gz 275.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for spoc 0.9.0
File Interpreter ABI Platform
spoc-0.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 432.2 kB

Release files / spoc-0.9.0.tar.gz

Download URL spoc-0.9.0.tar.gz
Size 275.2 kB
Tags Source
SHA-256 checksum
How to use checksums
f24ac1e513182c3c77aaef6adc096658b4903e344bf56306c8e9ad8c2ec4dbd1
BLAKE2b-256 checksum
How to use checksums
b01519741fd56732a4e0a6700051272d98f5ec17a81eeeb9f76c3d212ff747cf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / spoc-0.9.0-py3-none-any.whl

Download URL spoc-0.9.0-py3-none-any.whl
Size 157.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fed26f53a78b6a634803074a75673007d58d398c99a86fa2e1c03dc531f3b1a0
BLAKE2b-256 checksum
How to use checksums
978515147d96fb35cf12562382c93f49cf0203b23719e0f0d3362b7288719ce9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for spoc 0.9.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.

Release history Release notifications | RSS feed

This release

0.9.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page