Skip to content

Commit

Permalink
feat: remove unresolvable dependency error by default
Browse files Browse the repository at this point in the history
  • Loading branch information
raceychan committed Mar 4, 2025
1 parent e9a9de9 commit b59bd49
Show file tree
Hide file tree
Showing 17 changed files with 533 additions and 500 deletions.
44 changes: 43 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1299,4 +1299,46 @@ as well as
dg.factory(InfraBuilder().repo_maker)
```
we need to test to see if this already works
NOTE: we need to test to see if this already works
- Make sure this won't break
```python
async def create_user(name: Query[str]):
...
dg = Graph(ignore=Query)
dg.analyze(create_user)
```
```python
>>> from typing import *
>>> type Q[T] = Annotated[T, "aloha"]
>>> type(Q)
<class 'typing.TypeAliasType'>
>>> type(Q[str])
<class 'types.GenericAlias'>
assert get_origin(Q[str]) is Q
```
possible solution:
when we analyze
```python
def analyze_params(
self, ufunc: Callable[P, T], config: NodeConfig = DefaultConfig
) -> tuple[bool, list[tuple[str, IDependent[Any]]]]:
deps = Dependencies.from_signature(
signature=get_typed_signature(ufunc), function=ufunc
)
depends_on_resource: bool = False
unresolved: list[tuple[str, IDependent[Any]]] = []
for i, (name, param) in enumerate(deps.items()):
param_type = get_origin(param.param_type) or param.param_type
if param_type in config.ignore:
continue
```
4 changes: 2 additions & 2 deletions ididi/_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,10 +348,10 @@ def is_resource(self) -> bool:
return self.factory_type in ("resource", "aresource")

def analyze_unsolved_params(
self, ignore: frozenset[Any] = EmptyIgnore
self, ignore: tuple[Any] = EmptyIgnore
) -> Generator[Dependency, None, None]:
"params that needs to be statically resolved"
ignore = ignore | self.config.ignore
ignore = ignore + self.config.ignore

for i, (name, param) in enumerate(self.dependencies.items()):
if i in ignore or name in ignore:
Expand Down
18 changes: 9 additions & 9 deletions ididi/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from .interfaces import GraphIgnore, GraphIgnoreConfig, NodeIgnore, NodeIgnoreConfig

EmptyIgnore: Final[frozenset[Any]] = frozenset()
EmptyIgnore: Final[tuple[Any]] = tuple()


class FrozenSlot:
Expand Down Expand Up @@ -49,14 +49,14 @@ def __init__(
ignore: NodeIgnoreConfig = EmptyIgnore,
):

if not isinstance(ignore, frozenset):
if not isinstance(ignore, tuple):
if isinstance(ignore, Iterable):
if isinstance(ignore, str):
ignore = frozenset([ignore])
ignore = tuple((ignore,))
else:
ignore = frozenset(ignore)
ignore = tuple(ignore)
else:
ignore = frozenset([ignore])
ignore = (ignore,)

object.__setattr__(self, "ignore", ignore)
object.__setattr__(self, "reuse", reuse)
Expand All @@ -69,14 +69,14 @@ class GraphConfig(FrozenSlot):

def __init__(self, *, self_inject: bool, ignore: GraphIgnoreConfig):

if not isinstance(ignore, frozenset):
if not isinstance(ignore, tuple):
if isinstance(ignore, Iterable):
if isinstance(ignore, str):
ignore = frozenset([ignore])
ignore = tuple((ignore,))
else:
ignore = frozenset(ignore)
ignore = tuple(ignore)
else:
ignore = frozenset([ignore])
ignore = (ignore,)

object.__setattr__(self, "self_inject", self_inject)
object.__setattr__(self, "ignore", ignore)
Expand Down
38 changes: 19 additions & 19 deletions ididi/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,25 +108,25 @@ class UnsolvableParameterError(UnsolvableNodeError):
"""


class UnsolvableDependencyError(UnsolvableParameterError):
"""
Raised when a dependency parameter can't be built.
"""

def __init__(
self,
*,
dep_name: str,
factory: Union[Callable[..., Any], type],
dependent_type: Callable[..., Any],
dependency_type: Callable[..., Any],
):
type_repr = getattr(dependency_type, "__name__", str(dependency_type))
param_repr = f" * {dependent_type.__name__}({dep_name}: {type_repr}) \n value of `{dep_name}` must be provided"
self.message = (
f"Unable to resolve dependency for parameter in {factory}, \n{param_repr}"
)
super().__init__(self.message)
# class UnsolvableDependencyError(UnsolvableParameterError):
# """
# Raised when a dependency parameter can't be built.
# """

# def __init__(
# self,
# *,
# dep_name: str,
# factory: Union[Callable[..., Any], type],
# dependent_type: Callable[..., Any],
# dependency_type: Callable[..., Any],
# ):
# type_repr = getattr(dependency_type, "__name__", str(dependency_type))
# param_repr = f" * {dependent_type.__name__}({dep_name}: {type_repr}) \n value of `{dep_name}` must be provided"
# self.message = (
# f"Unable to resolve dependency for parameter in {factory}, \n{param_repr}"
# )
# super().__init__(self.message)


class ForwardReferenceNotFoundError(UnsolvableParameterError):
Expand Down
2 changes: 1 addition & 1 deletion ididi/graph.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ cdef class Resolver:
cdef readonly dict _nodes
cdef readonly dict _analyzed_nodes
cdef readonly TypeRegistry _type_registry
cdef readonly frozenset _ignore
cdef readonly tuple _ignore
cdef readonly object _workers

cdef readonly set _registered_singletons
Expand Down
21 changes: 8 additions & 13 deletions ididi/graph.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ from .errors import (
ResourceOutsideScopeError,
ReusabilityConflictError,
TopLevelBulitinTypeError,
UnsolvableDependencyError,
UnsolvableNodeError,
)
from .interfaces import (
Expand Down Expand Up @@ -449,7 +448,7 @@ cdef class Resolver:
dependent: INode[P, T],
*,
config: NodeConfig = DefaultConfig,
ignore: frozenset[str] = EmptyIgnore,
ignore: tuple[str] = EmptyIgnore,
) -> DependentNode:
if node := self._analyzed_nodes.get(dependent):
return node
Expand All @@ -463,7 +462,7 @@ cdef class Resolver:

def dfs(dep: IDependent[T]) -> DependentNode:
# when we register a concrete node we also register its bases to type_registry
cdef frozenset node_graph_ignore
cdef tuple node_graph_ignore

if dep in self._analyzed_nodes:
return self._analyzed_nodes[dep]
Expand All @@ -477,7 +476,7 @@ cdef class Resolver:
current_path.append(dep)

if ignore is not self._ignore:
node_graph_ignore = ignore | self._ignore
node_graph_ignore = ignore + self._ignore
else:
node_graph_ignore = ignore

Expand Down Expand Up @@ -506,12 +505,8 @@ cdef class Resolver:
if is_provided(param.default_):
continue
if param.unresolvable:
raise UnsolvableDependencyError(
dep_name=param.name,
dependent_type=dep,
dependency_type=param.param_type,
factory=node.factory,
)
continue

try:
fnode = dfs(param_type)
except UnsolvableNodeError as une:
Expand Down Expand Up @@ -633,7 +628,7 @@ cdef class Resolver:
if resolution := self._resolved_singletons.get(dependent):
return resolution

provided_params = frozenset(overrides)
provided_params = tuple(overrides)
node: DependentNode = self.analyze(dependent, ignore=provided_params)

return _resolve_dfs(
Expand All @@ -653,7 +648,7 @@ cdef class Resolver:
if resolution := self._resolved_singletons.get(dependent):
return resolution

provided_params = frozenset(overrides)
provided_params = tuple(overrides)
node: DependentNode = self.analyze(dependent, ignore=provided_params)
return await _aresolve_dfs(
self, self._nodes, self._resolved_singletons, node.dependent, overrides
Expand All @@ -663,7 +658,7 @@ cdef class Resolver:
self, dependent: INode[P, T], config: NodeConfig = DefaultConfig
) -> DependentNode:
merged_config = NodeConfig(
reuse=config.reuse, ignore=self._ignore | config.ignore
reuse=config.reuse, ignore=self._ignore + config.ignore
)
node = DependentNode.from_node(dependent, config=merged_config)
if node.function_dependent:
Expand Down
4 changes: 2 additions & 2 deletions ididi/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
]
INode = Union[INodeFactory[P, R], type[R]]

NodeIgnore = frozenset[Union[str, int, type, TypeAliasType]]
GraphIgnore = frozenset[Union[str, type, TypeAliasType]]
NodeIgnore = tuple[Union[str, int, type, TypeAliasType]]
GraphIgnore = tuple[Union[str, type, TypeAliasType]]

NodeConfigParam = Union[str, int, type, TypeAliasType]
GraphConfigParam = Union[str, type, TypeAliasType]
Expand Down
4 changes: 2 additions & 2 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ clean:
find ididi \( -name "*.c" -o -name "*.so" -o -name "*.html" \) -type f -exec rm -f {} \;

.PHONY: test
test:
test: compile
pixi run -e test pytest -m "not benchmark" -vx --capture=fd tests/

.PHONY: debug
Expand Down Expand Up @@ -125,7 +125,7 @@ git-push:

local-build:
@echo "Building version $(VERSION)..."
@pixi run -e publish python setup.py build_ext --inplace
@pixi run -e publish python setup.py sdist bdist_wheel

.PHONY: cibuild
cibuild:
Expand Down
Loading

0 comments on commit b59bd49

Please sign in to comment.