Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
f4079f2
Implement [Async]InjectionContext
kuyugama Nov 26, 2025
49925a9
Add injection context tests
kuyugama Nov 29, 2025
f0c1b47
Split tests into async and sync modules; add testing nested lifecycle
kuyugama Nov 29, 2025
580bf7d
Configure ty and ruff for project
kuyugama Dec 19, 2025
30c8b5d
Merge pull request #63 from KuyuCode/kh/feat/ruff-and-ty
kuyugama Dec 19, 2025
9ed2d4b
Improve `from_(...)` overloads for generators
kuyugama Dec 19, 2025
95ba688
Merge pull request #64 from KuyuCode/kh/feat/improve-from_-overloads
kuyugama Dec 19, 2025
0396e7e
Provide stub-file for InjectionContext and AsyncInjectionContext
kuyugama Dec 19, 2025
7637ecf
Fix InjectionContext and AsyncInjectionContext stubs
kuyugama Jan 3, 2026
3ea373d
Add method descriptions
kuyugama Jan 4, 2026
5c13c95
Implement basic Scope class
kuyugama Jan 9, 2026
e31f5ea
Add Scope class tests
kuyugama Jan 9, 2026
84ecdb0
Add scope merging
kuyugama Jan 9, 2026
e8bca4e
Use NewType from typing_extensions for tests
kuyugama Jan 10, 2026
b07d3e0
Add scope merge tests
kuyugama Jan 10, 2026
a6514f5
Add test for `scope.add_value` value replacement signaling
kuyugama Jan 10, 2026
9ffab7f
Add scope simplifying and copying methods and tests for them
kuyugama Jan 10, 2026
b372410
Rewrite injection value resolution using the Scope class
kuyugama Jan 10, 2026
544a59a
Add scope update method
kuyugama Jan 10, 2026
7e62129
Use `Scope.from_legacy` method to create scope from legacy dictionary…
kuyugama Jan 10, 2026
90879a4
Use `Scope.from_legacy` method to create scope from legacy dicrionary…
kuyugama Jan 10, 2026
1db2bd8
Rewrite scope merging
kuyugama Jan 12, 2026
63ca965
Optimize `Scope.from_legacy`
kuyugama Jan 12, 2026
43c93f0
Mention callable that caused 'async in sync' exception
kuyugama Jan 12, 2026
b8a4748
Add proper resolving for type factories
kuyugama Jan 12, 2026
975cd16
Improve logging messages
kuyugama Jan 12, 2026
f167438
Sort imports
kuyugama Jan 12, 2026
d361654
Upgrade dependencies
kuyugama Jan 25, 2026
81e1fb5
Update docs/requrements.txt
kuyugama Jan 25, 2026
4399b6b
Move TypeFactory and TypeInstance into Type class to keep them together
kuyugama Jan 25, 2026
2334187
Rewrite injection_impl to not use `Scope.from_legacy(...)`
kuyugama Feb 11, 2026
b6ebbca
Raise KeyError in __getitem__ if value is not found
kuyugama Feb 11, 2026
ab00036
Add Scope.__getitem__ method tests
kuyugama Feb 11, 2026
76cf2b1
Use typing_extensions.NewType for type aliases
kuyugama Feb 11, 2026
33a5788
Enforce mutual exclusivity between type instances and factories in Scope
kuyugama Feb 14, 2026
f42ff85
feat: Introduce `fundi.Scope` for explicit dependency injection
kuyugama Mar 7, 2026
b45723e
refactor(configurable): Make configurable_dependency type-safe
kuyugama Mar 12, 2026
857d194
fix(scan): Return scanned side_effects instead of raw functions
kuyugama Mar 12, 2026
ad0ee2f
Fix virtual_context() example in docstring
kuyugama Mar 12, 2026
58ddc87
feat(scope): Enhance add_factory with type inference and scan parameters
kuyugama Mar 12, 2026
dbece7f
Merge pull request #65 from KuyuCode/kh/feat/scope-as-a-class
kuyugama Mar 12, 2026
337b387
Bump version
kuyugama Mar 12, 2026
2aa8d1c
Update CITATION.cff
kuyugama Mar 12, 2026
1fcbaf0
Fix documentation
kuyugama Mar 12, 2026
5f5dd74
Merge pull request #66 from KuyuCode/kh/feat/docs
kuyugama Mar 12, 2026
c963806
Bump version
kuyugama Mar 12, 2026
91a7238
Update CITATION.cff
kuyugama Mar 12, 2026
6a3f733
Merge main onto feat/injection-context
kuyugama Mar 16, 2026
03a279a
Rewrite [Async]InjectionContext to support Scope objects
kuyugama Mar 22, 2026
9b1462b
feat: detect and raise CyclicDependencyError on circular dependencies
kuyugama Mar 22, 2026
c6477e3
Fix stubs for ainject() and from_()
kuyugama May 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ __pycache__
.python-version
docs/_build
play.py
play*.py
6 changes: 3 additions & 3 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ keywords:
- dependency injection
- fundi
license: LGPL-3.0
commit: bca6f9b886da89d52493d3ccf3142418d063ce7e
version: 1.5.0
date-released: '2025-10-10'
commit: c9638062cbb2d4c3facfa0cbaae90bde27fc1767
version: 1.6.1
date-released: '2026-03-12'
2 changes: 2 additions & 0 deletions docs/advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ but itself is not a coroutine function. In this case you will need
to override ``async_`` property of the dependency:

.. code-block:: python

from fundi import from_

def require_event_data(event: RemoteEvent):
Expand All @@ -177,6 +178,7 @@ For example, if there is function that returns context-manager and type-hint is
to contextlib.AbstractContextManager FunDI will correctly infer it as lifespan dependency.

.. code-block:: python

from fundi import from_

from contextlib import AbstractContextManager
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
project = "FunDI"
copyright = "2025, Kuyugama"
author = "Kuyugama"
release = "1.5.0"
release = "1.6.1"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand Down
12 changes: 6 additions & 6 deletions docs/howtos/debugging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ FunDI provides useful functions to help you debug and optimize your dependency i

.. code-block:: python

from fundi import tree, scan
from fundi import Scope, tree, scan

print(tree({"username": "user"}, scan(application)))
print(tree(Scope({"username": "user"}), scan(application)))

Outputs::

Expand All @@ -27,9 +27,9 @@ FunDI provides useful functions to help you debug and optimize your dependency i

.. code-block:: python

from fundi import order, scan
from fundi import Scope, order, scan

print(order({"username": "user"}, scan(application)))
print(order(Scope({"username": "user"}), scan(application)))

Outputs::

Expand Down Expand Up @@ -57,7 +57,7 @@ library adds its injection trace to exception.

from contextlib import ExitStack

from fundi import from_, scan, inject, injection_trace
from fundi import Scope, from_, scan, inject, injection_trace


def require_random_animal() -> str:
Expand All @@ -72,7 +72,7 @@ library adds its injection trace to exception.


try:
inject({}, scan(application))
inject(Scope(), scan(application))
except Exception as e:
print(injection_trace(e))

Expand Down
12 changes: 6 additions & 6 deletions docs/howtos/injection.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Example of synchronous injection:
import secrets
from contextlib import ExitStack

from fundi import from_, scan, inject
from fundi import Scope, from_, scan, inject


def require_unique_id() -> str:
Expand All @@ -36,7 +36,7 @@ Example of synchronous injection:
print(f"Application started with {user_id = } and {username = }")


inject({"username": "Kuyugama"}, scan(application))
inject(Scope({"username": "Kuyugama"}), scan(application))


Example of asynchronous injection:
Expand All @@ -47,7 +47,7 @@ Example of asynchronous injection:
import asyncio
from contextlib import AsyncExitStack

from fundi import from_, scan, ainject
from fundi import Scope, from_, scan, ainject


async def require_user(username: str) -> str:
Expand All @@ -60,7 +60,7 @@ Example of asynchronous injection:


async def main():
ainject({"username": "Kuyugama"}, scan(application))
await ainject(Scope({"username": "Kuyugama"}), scan(application))

if __name__ == "__main__":
asyncio.run(main())
Expand All @@ -72,14 +72,14 @@ Example of injection that produces value:
import secrets
from contextlib import ExitStack

from fundi import scan, inject
from fundi import Scope, scan, inject


def require_unique_id() -> str:
return secrets.token_hex(12)


user_id = inject({}, scan(require_user_id))
user_id = inject(Scope(), scan(require_unique_id))
print("Generated user id is", user_id)

..
Expand Down
12 changes: 8 additions & 4 deletions docs/howtos/overriding.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Example of overriding dependency result:

.. code-block:: python

from fundi import scan, inject
from fundi import Scope, scan, inject

from src import application
from src.models import User
Expand All @@ -35,7 +35,7 @@ Example of overriding dependency result:
username="test_user",
)

inject({"username": test_user.username}, scan(application), override={require_user: test_user})
inject(Scope({"username": test_user.username}), scan(application), override={require_user: test_user})


Example of overriding dependency callable:
Expand All @@ -44,7 +44,7 @@ Example of overriding dependency callable:

from contextlib import ExitStack

from fundi import scan, inject
from fundi import Scope, scan, inject

from src import application
from src.models import User
Expand All @@ -61,5 +61,9 @@ Example of overriding dependency callable:
return test_user


inject({"username": test_user.username}, scan(application), override={require_user: scan(test_require_user)})
inject(
Scope({"username": test_user.username}),
scan(application),
override={require_user: scan(test_require_user)}
)

Loading
Loading