anydi 0.62.0__tar.gz → 0.63.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. {anydi-0.62.0 → anydi-0.63.0}/PKG-INFO +1 -1
  2. {anydi-0.62.0 → anydi-0.63.0}/anydi/_container.py +31 -1
  3. {anydi-0.62.0 → anydi-0.63.0}/anydi/_resolver.py +9 -5
  4. {anydi-0.62.0 → anydi-0.63.0}/pyproject.toml +1 -1
  5. {anydi-0.62.0 → anydi-0.63.0}/README.md +0 -0
  6. {anydi-0.62.0 → anydi-0.63.0}/anydi/__init__.py +0 -0
  7. {anydi-0.62.0 → anydi-0.63.0}/anydi/_async_lock.py +0 -0
  8. {anydi-0.62.0 → anydi-0.63.0}/anydi/_context.py +0 -0
  9. {anydi-0.62.0 → anydi-0.63.0}/anydi/_decorators.py +0 -0
  10. {anydi-0.62.0 → anydi-0.63.0}/anydi/_injector.py +0 -0
  11. {anydi-0.62.0 → anydi-0.63.0}/anydi/_marker.py +0 -0
  12. {anydi-0.62.0 → anydi-0.63.0}/anydi/_module.py +0 -0
  13. {anydi-0.62.0 → anydi-0.63.0}/anydi/_provider.py +0 -0
  14. {anydi-0.62.0 → anydi-0.63.0}/anydi/_scanner.py +0 -0
  15. {anydi-0.62.0 → anydi-0.63.0}/anydi/_types.py +0 -0
  16. {anydi-0.62.0 → anydi-0.63.0}/anydi/ext/__init__.py +0 -0
  17. {anydi-0.62.0 → anydi-0.63.0}/anydi/ext/django/__init__.py +0 -0
  18. {anydi-0.62.0 → anydi-0.63.0}/anydi/ext/fastapi.py +0 -0
  19. {anydi-0.62.0 → anydi-0.63.0}/anydi/ext/faststream.py +0 -0
  20. {anydi-0.62.0 → anydi-0.63.0}/anydi/ext/pydantic_settings.py +0 -0
  21. {anydi-0.62.0 → anydi-0.63.0}/anydi/ext/pytest_plugin.py +0 -0
  22. {anydi-0.62.0 → anydi-0.63.0}/anydi/ext/starlette/__init__.py +0 -0
  23. {anydi-0.62.0 → anydi-0.63.0}/anydi/ext/starlette/middleware.py +0 -0
  24. {anydi-0.62.0 → anydi-0.63.0}/anydi/ext/typer.py +0 -0
  25. {anydi-0.62.0 → anydi-0.63.0}/anydi/py.typed +0 -0
  26. {anydi-0.62.0 → anydi-0.63.0}/anydi/testing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anydi
3
- Version: 0.62.0
3
+ Version: 0.63.0
4
4
  Summary: Dependency Injection library
5
5
  Keywords: dependency injection,dependencies,di,async,asyncio,application
6
6
  Author: Anton Ruhlov
@@ -431,6 +431,10 @@ class Container:
431
431
  parameters: list[ProviderParameter] = []
432
432
  scope_provider: dict[Scope, Provider] = {}
433
433
 
434
+ # Precompute constant checks
435
+ is_scoped = scope not in ("singleton", "transient")
436
+ has_defaults = defaults is not None
437
+
434
438
  for parameter in signature.parameters.values():
435
439
  if parameter.annotation is inspect.Parameter.empty:
436
440
  raise TypeError(
@@ -450,10 +454,32 @@ class Container:
450
454
  )
451
455
  has_default = default is not NOT_SET
452
456
 
457
+ # Check if provider exists before attempting to register (for scoped only)
458
+ was_auto_registered = (
459
+ is_scoped and parameter.annotation not in self._providers
460
+ )
461
+
453
462
  try:
454
463
  sub_provider = self._get_or_register_provider(parameter.annotation)
455
464
  except LookupError as exc:
456
- if parameter.name in defaults if defaults else False or has_default:
465
+ if (has_defaults and parameter.name in defaults) or has_default:
466
+ continue
467
+ # For request/custom scopes, allow unregistered dependencies
468
+ # They might be provided via context.set()
469
+ if is_scoped:
470
+ # Add to unresolved list to provide better error messages
471
+ # and prevent infinite recursion
472
+ self._resolver.add_unresolved(parameter.annotation)
473
+ parameters.append(
474
+ ProviderParameter(
475
+ name=parameter.name,
476
+ annotation=parameter.annotation,
477
+ default=default,
478
+ has_default=has_default,
479
+ provider=None, # Will check context at runtime
480
+ shared_scope=True, # Same scope, check context
481
+ )
482
+ )
457
483
  continue
458
484
  unresolved_parameter = parameter
459
485
  unresolved_exc = exc
@@ -463,6 +489,10 @@ class Container:
463
489
  if sub_provider.scope not in scope_provider:
464
490
  scope_provider[sub_provider.scope] = sub_provider
465
491
 
492
+ # If provider was auto-registered and has same scope, mark as unresolved
493
+ if was_auto_registered and sub_provider.scope == scope:
494
+ self._resolver.add_unresolved(parameter.annotation)
495
+
466
496
  parameters.append(
467
497
  ProviderParameter(
468
498
  name=parameter.name,
@@ -228,11 +228,15 @@ class Resolver:
228
228
  )
229
229
  create_lines.append(f" arg_{idx} = defaults['{name}']")
230
230
  create_lines.append(" else:")
231
- create_lines.append(" cached = NOT_SET_")
232
- create_lines.append(" if context is not None:")
233
- create_lines.append(
234
- f" cached = context.get(_param_annotations[{idx}])"
235
- )
231
+ # Direct dict access for shared scope params (avoids method call)
232
+ if param_shared_scopes[idx]:
233
+ create_lines.append(
234
+ f" cached = (context._instances.get("
235
+ f"_param_annotations[{idx}], NOT_SET_) "
236
+ f"if context is not None else NOT_SET_)"
237
+ )
238
+ else:
239
+ create_lines.append(" cached = NOT_SET_")
236
240
  create_lines.append(" if cached is NOT_SET_:")
237
241
  create_lines.append(
238
242
  f" if _param_annotations[{idx}] in "
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "anydi"
3
- version = "0.62.0"
3
+ version = "0.63.0"
4
4
  description = "Dependency Injection library"
5
5
  authors = [{ name = "Anton Ruhlov", email = "antonruhlov@gmail.com" }]
6
6
  requires-python = ">=3.10.0, <3.15"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes