Registry / web-framework / picobox

picobox

JSON →
library4.0.0pypypi✓ verified 85d ago

Picobox is an opinionated, lightweight (around 500 LOC) dependency injection framework for Python, designed to be clean and pragmatic. It focuses on explicit demands without complex graphs, implicit injections, or XML configurations. The current version is 4.0.0, and it maintains an active development with regular major and minor releases, including support for new Python versions and deprecations of older ones.

pip install picobox
INSTALL
IMPORT
SIG · PICOBOX
P
picobox
web-frameworkpythonv4.0.0
Install
1.7s avg
Import
35ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v4.0.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.920 runs
installs and imports cleanly · install 0.0s · import 0.036s · 17.9MB
glibc
py 3.103.920 runs
installs and imports cleanly · install 1.7s · import 0.034s · 18MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

picobox
import picobox
Box
from picobox import Box
push
from picobox import push
pass_
from picobox import pass_
singleton
from picobox import singleton
threadlocal
from picobox import threadlocal
contextvars
from picobox import contextvars
from picobox.contrib import flaskscopes
In Picobox 4.0.0, the `picobox.contrib` package was renamed to `picobox.ext`. Old imports like `from picobox.contrib import flaskscopes` will break.

This quickstart demonstrates defining a `Box`, adding both value and factory dependencies with scoping, and then using the `@picobox.pass_` decorator to inject these dependencies into a function. The `picobox.push()` function is used as a context manager to activate the box for the current scope.

import picobox class MyService: def __init__(self, config_value: int): self.config_value = config_value def do_work(self) -> str: return f"Working with config: {self.config_value}" # 1. Create a Box instance box = picobox.Box() # 2. Put dependencies into the box # 'my_config' is a simple value box.put('my_config', 123) # 'my_service' is a factory, instantiated once per injection or scope box.put('my_service', factory=MyService, scope=picobox.singleton, depends=['my_config']) # 3. Use picobox.push to make the box active (often as a context manager) with picobox.push(box): # 4. Define a function that needs dependencies, using @picobox.pass_ @picobox.pass_('my_service') @picobox.pass_('my_config', as_='cfg_val') def run_application(my_service: MyService, cfg_val: int): print(f"Retrieved config value: {cfg_val}") print(my_service.do_work()) run_application()
Debug
Known issues
breakingThe `picobox.contrib` package was renamed to `picobox.ext` in version 4.0.0. Any imports or references to `picobox.contrib` will now fail.
fix
Update all imports from `picobox.contrib` to `picobox.ext` (e.g., `from picobox.contrib.flaskscopes` becomes `from picobox.ext.flaskscopes`).
affects: 4.0.0 and later
breakingPicobox 4.0.0 dropped support for Python 3.7. Picobox 3.0.0 dropped support for Python 2.7, 3.4, 3.5, and 3.6. Ensure your Python environment meets the `requires_python>=3.8` specification.
fix
Upgrade your Python interpreter to version 3.8 or newer.
affects: 3.0.0, 4.0.0
breakingIn version 2.0.0, `picobox.push()` was changed to push a box onto the stack immediately when called as a function, rather than waiting for the `__enter__()` method if used as a context manager. This can alter the timing of when a box becomes active.
fix
Review existing code using `picobox.push()` to understand if its new immediate behavior impacts dependency resolution. If relying on context manager semantics, ensure the `with` statement correctly defines the scope.
affects: 2.0.0 and later
gotchaPicobox scopes (`singleton`, `threadlocal`, `contextvars`, `factory`) determine the lifespan and sharing of injected dependencies. Misunderstanding or misapplying scopes can lead to unexpected state sharing or excessive object creation. For example, `contextvars` is critical for asyncio applications.
fix
Carefully choose the appropriate scope for each dependency based on its intended lifecycle. Use `picobox.singleton` for global instances, `picobox.threadlocal` for thread-specific instances, and `picobox.contextvars` for async task-specific instances (Python 3.7+).
affects: All versions
gotchaThe `@picobox.pass_()` decorator internally modifies the function signature. While fixed in 4.0.0 to prevent shadowing return types, on older versions or if not configured carefully, it could interfere with LSP servers or static analysis tools that rely on precise type hints.
fix
Upgrade to Picobox 4.0.0 or later to benefit from the fix. Always verify that type hints are correctly interpreted by your development tools after applying the decorator.
affects: Prior to 4.0.0 (resolved in 4.0.0)
Errors
Common errors & fixes
KeyError: '<dependency_key>'
Attempting to retrieve a dependency from a `picobox.Box` or `picobox.Stack` using `get()` or via the `@picobox.pass_()` decorator, but no dependency has been registered under the specified key.
fix
Register the dependency in the box using `box.put('<dependency_key>', value)` or `box.put('<dependency_key>', factory=some_factory_function)` before it is accessed.
ValueError: Either 'value' or 'factory' argument must be passed, not both.
When registering a dependency with `box.put()`, both the `value` argument and the `factory` argument were provided, but `picobox` requires only one of them to specify how the dependency is created.
fix
Provide either a direct `value` or a `factory` function to produce the dependency, but not both, when calling `box.put()`.
ModuleNotFoundError: No module named 'picobox.contrib'
After upgrading to picobox version 4.0.0, the `picobox.contrib` package was renamed to `picobox.ext` as a breaking change.
fix
Update import statements to use `picobox.ext` instead of `picobox.contrib`. For example, change `from picobox.contrib.some_module import SomeClass` to `from picobox.ext.some_module import SomeClass`.
Upgrade
Version history
4.0.0latest on PyPI · released Nov 20, 2023
Audit
Dependencies

No dependency data recorded yet.

Agent activity
2 hits · last 30 days
node
2
Resources
picobox — pip install picobox · libregistry