{"id":6770,"library":"picobox","title":"Picobox Dependency Injection","description":"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.","status":"active","version":"4.0.0","language":"en","source_language":"en","source_url":"https://github.com/ikalnytskyi/picobox","tags":["dependency injection","di","container","inversion of control"],"install":[{"cmd":"pip install picobox","lang":"bash","label":"Install latest version"}],"dependencies":[],"imports":[{"symbol":"picobox","correct":"import picobox"},{"symbol":"Box","correct":"from picobox import Box"},{"symbol":"push","correct":"from picobox import push"},{"symbol":"pass_","correct":"from picobox import pass_"},{"symbol":"singleton","correct":"from picobox import singleton"},{"symbol":"threadlocal","correct":"from picobox import threadlocal"},{"note":"In Picobox 4.0.0, the `picobox.contrib` package was renamed to `picobox.ext`. Old imports like `from picobox.contrib import flaskscopes` will break.","wrong":"from picobox.contrib import flaskscopes","symbol":"contextvars","correct":"from picobox import contextvars"}],"quickstart":{"code":"import picobox\n\nclass MyService:\n    def __init__(self, config_value: int):\n        self.config_value = config_value\n\n    def do_work(self) -> str:\n        return f\"Working with config: {self.config_value}\"\n\n# 1. Create a Box instance\nbox = picobox.Box()\n\n# 2. Put dependencies into the box\n# 'my_config' is a simple value\nbox.put('my_config', 123)\n\n# 'my_service' is a factory, instantiated once per injection or scope\nbox.put('my_service', factory=MyService, scope=picobox.singleton, depends=['my_config'])\n\n# 3. Use picobox.push to make the box active (often as a context manager)\nwith picobox.push(box):\n    # 4. Define a function that needs dependencies, using @picobox.pass_\n    @picobox.pass_('my_service')\n    @picobox.pass_('my_config', as_='cfg_val')\n    def run_application(my_service: MyService, cfg_val: int):\n        print(f\"Retrieved config value: {cfg_val}\")\n        print(my_service.do_work())\n\n    run_application()","lang":"python","description":"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."},"warnings":[{"fix":"Update all imports from `picobox.contrib` to `picobox.ext` (e.g., `from picobox.contrib.flaskscopes` becomes `from picobox.ext.flaskscopes`).","message":"The `picobox.contrib` package was renamed to `picobox.ext` in version 4.0.0. Any imports or references to `picobox.contrib` will now fail.","severity":"breaking","affected_versions":"4.0.0 and later"},{"fix":"Upgrade your Python interpreter to version 3.8 or newer.","message":"Picobox 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.","severity":"breaking","affected_versions":"3.0.0, 4.0.0"},{"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.","message":"In 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.","severity":"breaking","affected_versions":"2.0.0 and later"},{"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+).","message":"Picobox 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.","severity":"gotcha","affected_versions":"All versions"},{"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.","message":"The `@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.","severity":"gotcha","affected_versions":"Prior to 4.0.0 (resolved in 4.0.0)"}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z","problems":[]}