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
muslpy 3.10–3.920 runs
installs and imports cleanly · install 0.0s · import 0.036s · 17.9MB
glibcpy 3.10–3.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.
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.fixUpdate 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.fixUpgrade 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.fixReview 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.fixCarefully 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.fixUpgrade 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.
fixRegister 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.
fixProvide 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.
fixUpdate 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.