Ididi

Latest version: v1.4.2

Safety actively analyzes 703125 Python packages for vulnerabilities to keep your Python projects secure.

Scan your dependencies

Page 3 of 10

1.2.4

Improvements:

- minor performance gain, 60% faster for instance resolve, should resolve 0.2 million instances in 1 second, although still 40 times slower than hard-coded factory, we tried replace recursive appraoch with iterative, no luck, only tiny improvements, so we stay at recursive appraoch

Fix:
in previous patch

py
def service_factory(
*, db: Database = use(db_fact), auth: AuthenticationService, name: str
) -> UserService:
return UserService(db=db, auth=auth)


def test_resolve():
dg = DependencyGraph()

dg.resolve(service_factory, name="aloha")


woud raise `UnsolvableDependencyError`, because `name` is a str without default values,
when when we resolve it, we will first static_resolve it, which would raise error,
now if dependencies that are provided with overrides won't be statically resolved.

1.2.3

- change `_itypes` to `interfaces`, make it public, since it is unlikely to cause breaking change

- remove `partial_resolve` from DependencyGraph

`partial_resolve` was introduced in `1.2.0`. it is not a good design,
it is like a global `try except`, which hides problems instead of solving them.


- `Ignore` Annotation


py
from ididi import Ignore

class User:
def __init__(self, name: Ignore[str]):
self.name = name


which is equivalent to


DependencyGraph().node(ignore="name")(User)



both `use` and `Ignore` are designed to be user friendly alternative to `DependencyGraph.node`

1.2.2

- `NodeConfig.ignore` & `GraphConfig.ignore` now supports `TypeAliasType`

only affect type checker

- remove `EntryConfig`, now `entry` share the same config as `NodeConfig`,
the only difference is now `dg.entry(reuse=True)` is possible, whereas it used to be always False, which does not really make sense, user can share the same dependencies across different calls to the entry function.


- `dg._reigster_node`, `dg._remove_node`, are now private, `dg.replace_node` is removed.
these three methods require user provide a `DependencyNode`, but we want to avoid user having to interact directly with `DependencyNode` to lower complexity.

1.2.1

a quick bug fix

py
from ididi import DependencyGraph


class Time:
def __init__(self, name: str):
self.name = name


def test_registered_singleton():
"""
previously
dg.should_be_scoped(dep_type) would analyze dependencies of the
dep_type, and if it contains resolvable dependencies exception would be raised

since registered_singleton is managed by user,
dg.should_be_scoped(registered_singleton) should always be False.
"""
timer = Time("1")

dg = DependencyGraph()

dg.register_singleton(timer)

assert dg.should_be_scoped(Time) is False

1.2.0

improvements

- change `Scope.register_dependent` to `Scope.register_singleton` to match the change made in 1.1.7 on `DependencyGraph`.

- positional ignore for node

py
def test_ignore():
dg = DependencyGraph()

class Item:
def __init__(self, a: int, b: str, c: int):
self.a = a
self.b = b
self.c = c

with pytest.raises(UnsolvableDependencyError):
dg.resolve(Item)

dg.node(ignore=(0, str, "c"))
with pytest.raises(TypeError):
dg.resolve(Item)

>>> TypeError: __init__() missing 3 required positional arguments: 'a', 'b', and 'c'


- partial resolve

previously, if a dependent requires a unresolvable dependency without default value, it would raise `UnsolvableDependencyError`,
this might be a problem when user wants to resolve the dependent by providing the unresolvable dependency with `dg.resolve`.

now `DependencyGraph` accepts a `partial_resolve` parameter, which would allow user to resolve a dependent with missing unsolvable-dependency.

py
def test_graph_partial_resolve_with_dep():
dg = DependencyGraph(partial_resolve=True)

class Database: ...

DATABASE = Database()

def db_factory() -> Database:
return DATABASE

class Data:
def __init__(self, name: str, db: Database = use(db_factory)):
self.name = name
self.db = db

dg.node(Data)

dg.analyze(Data)

with pytest.raises(UnsolvableDependencyError):
data = dg.resolve(Data)

data = dg.resolve(Data, name="data")
assert data.name == "data"
assert data.db is DATABASE

1.1.7

improvements

- factory have higher priority than default value

now, for a non-builtin type, ididi will try to resolve it even with default value,
this is because for classses that needs dependency injection, it does not make sense to have a default value in most cases, and in cases where it does, it most likely be like this

py
class UserRepos:
def __init__(self, db: Optional[Database] = None):
self.db = db


and it make more sense to inject `Database` than to ignore it.


- global ignore with `DependencyGraph(ignore=(type))`

py
class Timer:
def __init__(self, d: datetime):
self._d = d

dg = DependencyGraph(ignore=datetime)
with pytest.raises(TypeError):
dg.resolve(Timer)

Page 3 of 10

© 2025 Safety CLI Cybersecurity Inc. All Rights Reserved.