anydi 0.67.2__py3-none-any.whl → 0.69.0__py3-none-any.whl

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.
@@ -3,34 +3,24 @@ from __future__ import annotations
3
3
  import importlib.util
4
4
  import inspect
5
5
  import logging
6
- from collections.abc import Callable, Iterator
7
- from typing import Any, cast
6
+ import warnings
7
+ from collections.abc import Generator
8
+ from typing import TYPE_CHECKING, Annotated, Any, cast, get_args, get_origin
8
9
 
9
10
  import pytest
10
11
  from anyio.pytest_plugin import extract_backend_and_options, get_runner
11
12
  from typing_extensions import get_annotations
12
13
 
13
14
  from anydi import Container, import_container
15
+ from anydi._marker import is_marker
14
16
 
15
- logger = logging.getLogger(__name__)
17
+ if TYPE_CHECKING:
18
+ from _pytest.fixtures import SubRequest
16
19
 
17
- # Storage for fixtures with inject markers
18
- _INJECTED_FIXTURES: dict[str, dict[str, Any]] = {}
20
+ logger = logging.getLogger(__name__)
19
21
 
20
22
 
21
23
  def pytest_addoption(parser: pytest.Parser) -> None:
22
- parser.addini(
23
- "anydi_autoinject",
24
- help="Automatically inject dependencies into all test functions",
25
- type="bool",
26
- default=False,
27
- )
28
- parser.addini(
29
- "anydi_inject_all",
30
- help="Deprecated: use 'anydi_autoinject' instead",
31
- type="bool",
32
- default=False,
33
- )
34
24
  parser.addini(
35
25
  "anydi_container",
36
26
  help=(
@@ -41,144 +31,30 @@ def pytest_addoption(parser: pytest.Parser) -> None:
41
31
  default=None,
42
32
  )
43
33
  parser.addini(
44
- "anydi_fixture_inject_enabled",
45
- help=(
46
- "Enable dependency injection into fixtures marked with @pytest.mark.inject"
47
- ),
34
+ "anydi_autoinject",
35
+ help="Automatically inject dependencies into all test functions",
48
36
  type="bool",
49
- default=False,
37
+ default=True,
50
38
  )
51
39
 
52
40
 
53
41
  def pytest_configure(config: pytest.Config) -> None:
54
42
  config.addinivalue_line(
55
43
  "markers",
56
- "inject: mark test as needing dependency injection",
44
+ "inject: mark test as needing dependency injection (deprecated)",
57
45
  )
58
46
 
59
- # Enable fixture injection if configured
60
- inject_fixtures_enabled = cast(bool, config.getini("anydi_fixture_inject_enabled"))
61
- if inject_fixtures_enabled:
62
- autoinject = cast(bool, config.getini("anydi_autoinject"))
63
- inject_all = cast(bool, config.getini("anydi_inject_all"))
64
- _patch_pytest_fixtures(autoinject=autoinject or inject_all)
65
- logger.debug(
66
- "Fixture injection enabled via anydi_fixture_inject_enabled config"
67
- )
68
-
69
47
 
70
48
  @pytest.hookimpl(hookwrapper=True)
71
- def pytest_fixture_setup( # noqa: C901
72
- fixturedef: pytest.FixtureDef[Any],
73
- request: pytest.FixtureRequest,
74
- ) -> Iterator[None]:
75
- """Inject dependencies into fixtures marked with @pytest.mark.inject."""
76
- # Check if this fixture has injection metadata
77
- fixture_name = fixturedef.argname
78
- if fixture_name not in _INJECTED_FIXTURES:
79
- yield
80
- return
81
-
82
- # Get the metadata
83
- fixture_info = _INJECTED_FIXTURES[fixture_name]
84
- original_func = fixture_info["func"]
85
- parameters: list[tuple[str, Any]] = fixture_info["parameters"]
86
-
87
- # Get the container
88
- try:
89
- container = cast(Container, request.getfixturevalue("container"))
90
- except pytest.FixtureLookupError:
91
- yield
92
- return
93
-
94
- resolvable_params = _select_resolvable_parameters(container, parameters)
95
-
96
- if not resolvable_params:
97
- yield
98
- return
99
-
100
- target_name = f"fixture '{fixture_name}'"
101
-
102
- def _prepare_sync_call_kwargs(kwargs: dict[str, Any]) -> dict[str, Any]:
103
- combined_kwargs = dict(kwargs)
104
- combined_kwargs.update(
105
- _resolve_dependencies_sync(container, resolvable_params, target=target_name)
106
- )
107
- return combined_kwargs
108
-
109
- async def _prepare_async_call_kwargs(kwargs: dict[str, Any]) -> dict[str, Any]:
110
- combined_kwargs = dict(kwargs)
111
- combined_kwargs.update(
112
- await _resolve_dependencies_async(
113
- container, resolvable_params, target=target_name
114
- )
115
- )
116
- return combined_kwargs
117
-
118
- def _ensure_anyio_backend() -> tuple[str, dict[str, Any]]:
119
- try:
120
- backend = request.getfixturevalue("anyio_backend")
121
- except pytest.FixtureLookupError as exc: # pragma: no cover - defensive
122
- msg = (
123
- "To run async fixtures with AnyDI, please configure the `anyio` pytest "
124
- "plugin (provide the `anyio_backend` fixture)."
125
- )
126
- pytest.fail(msg, pytrace=False)
127
- raise RuntimeError from exc # Unreachable but satisfies type checkers
128
-
129
- return extract_backend_and_options(backend)
130
-
131
- # Replace the fixture function with one that mirrors the original's type and
132
- # injects dependencies before delegating to the user-defined function.
133
- original_fixture_func = fixturedef.func
134
-
135
- if inspect.isasyncgenfunction(original_func):
136
-
137
- def asyncgen_wrapper(*args: Any, **kwargs: Any) -> Iterator[Any]:
138
- backend_name, backend_options = _ensure_anyio_backend()
139
-
140
- async def _fixture() -> Any:
141
- call_kwargs = await _prepare_async_call_kwargs(kwargs)
142
- async for value in original_func(**call_kwargs):
143
- yield value
144
-
145
- with get_runner(backend_name, backend_options) as runner:
146
- yield from runner.run_asyncgen_fixture(_fixture, {}) # type: ignore
147
-
148
- fixturedef.func = asyncgen_wrapper # type: ignore[misc]
149
- elif inspect.iscoroutinefunction(original_func):
150
-
151
- def async_wrapper(*args: Any, **kwargs: Any) -> Any:
152
- backend_name, backend_options = _ensure_anyio_backend()
153
-
154
- async def _fixture() -> Any:
155
- call_kwargs = await _prepare_async_call_kwargs(kwargs)
156
- return await original_func(**call_kwargs)
157
-
158
- with get_runner(backend_name, backend_options) as runner:
159
- return runner.run_fixture(_fixture, {})
160
-
161
- fixturedef.func = async_wrapper # type: ignore[misc]
162
- elif inspect.isgeneratorfunction(original_func):
163
-
164
- def generator_wrapper(*args: Any, **kwargs: Any) -> Iterator[Any]:
165
- call_kwargs = _prepare_sync_call_kwargs(kwargs)
166
- yield from original_func(**call_kwargs)
167
-
168
- fixturedef.func = generator_wrapper # type: ignore[misc]
169
- else:
170
-
171
- def sync_wrapper(*args: Any, **kwargs: Any) -> Any:
172
- call_kwargs = _prepare_sync_call_kwargs(kwargs)
173
- return original_func(**call_kwargs)
174
-
175
- fixturedef.func = sync_wrapper # type: ignore[misc]
176
-
177
- # Let pytest execute the modified fixture
49
+ def pytest_fixture_setup(
50
+ fixturedef: pytest.FixtureDef[Any], request: SubRequest
51
+ ) -> Generator[None]:
52
+ """Automatically enable test mode on the container fixture."""
178
53
  yield
179
-
180
- # Restore the original function
181
- fixturedef.func = original_fixture_func # type: ignore[misc]
54
+ if fixturedef.argname == "container" and fixturedef.cached_result is not None:
55
+ container = fixturedef.cached_result[0]
56
+ if isinstance(container, Container):
57
+ container.enable_test_mode()
182
58
 
183
59
 
184
60
  @pytest.fixture(scope="session")
@@ -187,118 +63,133 @@ def container(request: pytest.FixtureRequest) -> Container:
187
63
  return _find_container(request)
188
64
 
189
65
 
190
- @pytest.fixture
191
- def _anydi_should_inject(request: pytest.FixtureRequest) -> bool:
192
- marker = request.node.get_closest_marker("inject")
193
-
194
- # Check new config option first
195
- autoinject = cast(bool, request.config.getini("anydi_autoinject"))
196
-
197
- # Check deprecated option for backward compatibility
198
- inject_all = cast(bool, request.config.getini("anydi_inject_all"))
199
- if inject_all:
200
- logger.warning(
201
- "Configuration option 'anydi_inject_all' is deprecated. "
202
- "Please use 'anydi_autoinject' instead."
203
- )
204
-
205
- return marker is not None or autoinject or inject_all
206
-
207
-
208
- @pytest.fixture
209
- def _anydi_injected_parameter_iterator(
210
- request: pytest.FixtureRequest,
211
- ) -> Callable[[], Iterator[tuple[str, Any]]]:
212
- fixturenames = set(request.node._fixtureinfo.initialnames) - set(
213
- request.node._fixtureinfo.name2fixturedefs.keys()
214
- )
215
-
216
- def _iterator() -> Iterator[tuple[str, Any]]:
217
- for name, annotation in _iter_injectable_parameters(request.function):
218
- if name not in fixturenames:
219
- continue
220
- yield name, annotation
221
-
222
- return _iterator
223
-
224
-
225
66
  @pytest.fixture(autouse=True)
226
- def _anydi_inject(
227
- request: pytest.FixtureRequest,
228
- _anydi_should_inject: bool,
229
- _anydi_injected_parameter_iterator: Callable[[], Iterator[tuple[str, Any]]],
230
- ) -> None:
231
- """Inject dependencies into the test function."""
232
-
233
- if inspect.iscoroutinefunction(request.function) or not _anydi_should_inject:
67
+ def _anydi_inject(request: pytest.FixtureRequest) -> None:
68
+ """Inject dependencies into sync test functions."""
69
+ if inspect.iscoroutinefunction(request.function):
234
70
  return
235
71
 
236
- parameters = list(_anydi_injected_parameter_iterator())
72
+ parameters, uses_deprecated = _get_injectable_params(request)
237
73
  if not parameters:
238
74
  return
239
75
 
240
76
  container = cast(Container, request.getfixturevalue("container"))
241
- resolvable = _select_resolvable_parameters(container, parameters)
242
- if not resolvable:
243
- return
244
77
 
245
- resolved = _resolve_dependencies_sync(
246
- container, resolvable, target=request.node.nodeid
247
- )
248
- for argname, value in resolved.items():
249
- request.node.funcargs[argname] = value
78
+ warned = False
79
+ for name, dependency_type in parameters:
80
+ if not container.has_provider_for(dependency_type):
81
+ continue
82
+ if uses_deprecated and not warned:
83
+ _warn_deprecated_marker(request.node.name)
84
+ warned = True
85
+ try:
86
+ request.node.funcargs[name] = container.resolve(dependency_type)
87
+ except Exception: # pragma: no cover
88
+ logger.warning("Failed to resolve '%s' for %s", name, request.node.nodeid)
250
89
 
251
90
 
252
91
  @pytest.fixture(autouse=True)
253
- def _anydi_ainject(
254
- request: pytest.FixtureRequest,
255
- _anydi_should_inject: bool,
256
- _anydi_injected_parameter_iterator: Callable[[], Iterator[tuple[str, Any]]],
257
- ) -> None:
258
- """Inject dependencies into the test function."""
259
- if (
260
- not inspect.iscoroutinefunction(request.function)
261
- and not inspect.isasyncgenfunction(request.function)
262
- or not _anydi_should_inject
263
- ):
92
+ def _anydi_ainject(request: pytest.FixtureRequest) -> None:
93
+ """Inject dependencies into async test functions."""
94
+ if not inspect.iscoroutinefunction(
95
+ request.function
96
+ ) and not inspect.isasyncgenfunction(request.function):
97
+ return
98
+
99
+ parameters, uses_deprecated = _get_injectable_params(request)
100
+ if not parameters:
264
101
  return
265
102
 
266
- # Skip if the anyio backend is not available
267
103
  if "anyio_backend" not in request.fixturenames:
268
- msg = (
104
+ pytest.fail(
269
105
  "To run async test functions with `anyio`, "
270
106
  "please configure the `anyio` pytest plugin.\n"
271
- "See: https://anyio.readthedocs.io/en/stable/testing.html"
107
+ "See: https://anyio.readthedocs.io/en/stable/testing.html",
108
+ pytrace=False,
272
109
  )
273
- pytest.fail(msg, pytrace=False)
274
-
275
- parameters = list(_anydi_injected_parameter_iterator())
276
- if not parameters:
277
- return
278
110
 
279
111
  container = cast(Container, request.getfixturevalue("container"))
280
- resolvable = _select_resolvable_parameters(container, parameters)
281
- if not resolvable:
282
- return
283
112
 
284
- async def _awrapper() -> None:
285
- resolved = await _resolve_dependencies_async(
286
- container, resolvable, target=request.node.nodeid
287
- )
288
- for argname, value in resolved.items():
289
- request.node.funcargs[argname] = value
113
+ async def _resolve() -> None:
114
+ warned = False
115
+ for name, dependency_type in parameters:
116
+ if not container.has_provider_for(dependency_type):
117
+ continue
118
+ if uses_deprecated and not warned:
119
+ _warn_deprecated_marker(request.node.name)
120
+ warned = True
121
+ try:
122
+ request.node.funcargs[name] = await container.aresolve(dependency_type)
123
+ except Exception: # pragma: no cover
124
+ logger.warning(
125
+ "Failed to resolve '%s' for %s", name, request.node.nodeid
126
+ )
290
127
 
291
128
  anyio_backend = request.getfixturevalue("anyio_backend")
292
129
  backend_name, backend_options = extract_backend_and_options(anyio_backend)
293
130
 
294
131
  with get_runner(backend_name, backend_options) as runner:
295
- runner.run_fixture(_awrapper, {})
132
+ runner.run_fixture(_resolve, {})
296
133
 
297
134
 
298
- def _find_container(request: pytest.FixtureRequest) -> Container:
299
- """Find container."""
135
+ def _get_injectable_params(
136
+ request: pytest.FixtureRequest,
137
+ ) -> tuple[list[tuple[str, Any]], bool]:
138
+ """Get injectable parameters for a test function.
139
+
140
+ Returns (parameters, uses_deprecated_marker) tuple.
141
+ """
142
+ fixture_names = set(request.node._fixtureinfo.initialnames) - set(
143
+ request.node._fixtureinfo.name2fixturedefs.keys()
144
+ )
145
+
146
+ marker = request.node.get_closest_marker("inject")
147
+ autoinject = cast(bool, request.config.getini("anydi_autoinject"))
148
+
149
+ has_any_explicit = False
150
+ explicit_params: list[tuple[str, Any]] = []
151
+ all_params: list[tuple[str, Any]] = []
152
+
153
+ annotations = get_annotations(request.function, eval_str=True)
154
+
155
+ for name, annotation in annotations.items():
156
+ if name in ("request", "return"):
157
+ continue
158
+
159
+ dependency_type, is_explicit = _extract_dependency_type(annotation)
160
+
161
+ if is_explicit:
162
+ has_any_explicit = True
163
+ explicit_params.append((name, dependency_type))
164
+ elif name in fixture_names:
165
+ all_params.append((name, dependency_type))
166
+
167
+ # Priority: explicit markers > deprecated @pytest.mark.inject > autoinject
168
+ if has_any_explicit:
169
+ return explicit_params, False
170
+ if marker is not None:
171
+ return all_params, True
172
+ if autoinject:
173
+ return all_params, False
174
+ return [], False
175
+
176
+
177
+ def _extract_dependency_type(annotation: Any) -> tuple[Any, bool]:
178
+ """Extract the actual type and whether it has an explicit injection marker.
179
+
180
+ Handles Provide[T] and Annotated[T, Inject()].
181
+ Returns (unwrapped_type, is_explicit).
182
+ """
183
+ if get_origin(annotation) is Annotated:
184
+ args = get_args(annotation)
185
+ for arg in args[1:]:
186
+ if is_marker(arg):
187
+ return args[0], True
188
+ return annotation, False
300
189
 
301
- # Look for 'anydi_container' defined in pytest.ini (highest priority)
190
+
191
+ def _find_container(request: pytest.FixtureRequest) -> Container:
192
+ """Find container from config or auto-detection."""
302
193
  container_path = cast(str | None, request.config.getini("anydi_container"))
303
194
  if container_path:
304
195
  try:
@@ -309,12 +200,10 @@ def _find_container(request: pytest.FixtureRequest) -> Container:
309
200
  f"'anydi_container={container_path}': {exc}"
310
201
  ) from exc
311
202
 
312
- # Detect pytest-django + anydi_django availability
313
203
  pluginmanager = request.config.pluginmanager
314
204
  if pluginmanager.hasplugin("django") and importlib.util.find_spec("anydi_django"):
315
205
  return import_container("anydi_django.container")
316
206
 
317
- # Neither fixture nor config found
318
207
  raise pytest.FixtureLookupError(
319
208
  None,
320
209
  request,
@@ -324,154 +213,10 @@ def _find_container(request: pytest.FixtureRequest) -> Container:
324
213
  )
325
214
 
326
215
 
327
- def _patch_pytest_fixtures(*, autoinject: bool) -> None: # noqa: C901
328
- """Patch pytest.fixture decorator to intercept fixtures with inject markers."""
329
- from _pytest.fixtures import fixture as original_fixture_decorator
330
-
331
- def patched_fixture(*args: Any, **kwargs: Any) -> Any: # noqa: C901
332
- """Patched fixture decorator that handles inject markers."""
333
-
334
- def should_process(func: Callable[..., Any]) -> bool:
335
- has_inject_marker = False
336
- if hasattr(func, "pytestmark"):
337
- markers = getattr(func, "pytestmark", [])
338
- if not isinstance(markers, list):
339
- markers = [markers]
340
-
341
- has_inject_marker = any(
342
- marker.name == "inject"
343
- for marker in markers
344
- if hasattr(marker, "name")
345
- )
346
-
347
- return autoinject or has_inject_marker
348
-
349
- def register_fixture(func: Callable[..., Any]) -> Callable[..., Any] | None:
350
- if not should_process(func):
351
- return None
352
-
353
- parameters = list(_iter_injectable_parameters(func))
354
- if not parameters:
355
- return None
356
-
357
- sig = inspect.signature(func, eval_str=True)
358
- has_request_param = "request" in sig.parameters
359
-
360
- if has_request_param:
361
-
362
- def wrapper_with_request(request: Any) -> Any:
363
- return func
364
-
365
- wrapper_func = wrapper_with_request
366
- else:
367
-
368
- def wrapper_no_request() -> Any:
369
- return func
370
-
371
- wrapper_func = wrapper_no_request
372
-
373
- wrapper_func.__name__ = func.__name__
374
- wrapper_func.__annotations__ = {}
375
-
376
- fixture_name = func.__name__
377
- _INJECTED_FIXTURES[fixture_name] = {
378
- "func": func,
379
- "parameters": parameters,
380
- }
381
- logger.debug(
382
- "Registered injectable fixture '%s' with params: %s",
383
- fixture_name,
384
- [name for name, _ in parameters],
385
- )
386
-
387
- return wrapper_func
388
-
389
- # Handle both @pytest.fixture and @pytest.fixture() usage
390
- if len(args) == 1 and callable(args[0]) and not kwargs:
391
- func = args[0]
392
- wrapper_func = register_fixture(func)
393
- if wrapper_func:
394
- return original_fixture_decorator(wrapper_func)
395
-
396
- return original_fixture_decorator(func)
397
- else:
398
-
399
- def decorator(func: Callable[..., Any]) -> Any:
400
- wrapper_func = register_fixture(func)
401
- if wrapper_func:
402
- return original_fixture_decorator(*args, **kwargs)(wrapper_func)
403
-
404
- return original_fixture_decorator(*args, **kwargs)(func)
405
-
406
- return decorator
407
-
408
- # Replace pytest.fixture
409
- pytest.fixture = patched_fixture # type: ignore[assignment]
410
- # Also patch _pytest.fixtures.fixture
411
- import _pytest.fixtures
412
-
413
- _pytest.fixtures.fixture = patched_fixture # type: ignore[assignment]
414
-
415
-
416
- def _iter_injectable_parameters(
417
- func: Callable[..., Any], *, skip: tuple[str, ...] = ("request",)
418
- ) -> Iterator[tuple[str, Any]]:
419
- annotations = get_annotations(func, eval_str=True)
420
- skip_names = set(skip)
421
- for name, annotation in annotations.items():
422
- if name in skip_names or name == "return":
423
- continue
424
- yield name, annotation
425
-
426
-
427
- def _select_resolvable_parameters(
428
- container: Container,
429
- parameters: Iterator[tuple[str, Any]] | list[tuple[str, Any]],
430
- ) -> list[tuple[str, Any]]:
431
- return [
432
- (name, annotation)
433
- for name, annotation in parameters
434
- if container.has_provider_for(annotation)
435
- ]
436
-
437
-
438
- def _resolve_dependencies_sync(
439
- container: Container,
440
- parameters: list[tuple[str, Any]],
441
- *,
442
- target: str,
443
- ) -> dict[str, Any]:
444
- resolved: dict[str, Any] = {}
445
- for param_name, annotation in parameters:
446
- try:
447
- resolved[param_name] = container.resolve(annotation)
448
- logger.debug("Resolved %s=%s for %s", param_name, annotation, target)
449
- except Exception as exc: # pragma: no cover - defensive logging
450
- logger.warning(
451
- "Failed to resolve dependency for '%s' on %s.",
452
- param_name,
453
- target,
454
- exc_info=exc,
455
- )
456
- return resolved
457
-
458
-
459
- async def _resolve_dependencies_async(
460
- container: Container,
461
- parameters: list[tuple[str, Any]],
462
- *,
463
- target: str,
464
- ) -> dict[str, Any]:
465
- resolved: dict[str, Any] = {}
466
- for param_name, annotation in parameters:
467
- try:
468
- resolved[param_name] = await container.aresolve(annotation)
469
- logger.debug("Resolved %s=%s for async %s", param_name, annotation, target)
470
- except Exception as exc: # pragma: no cover - defensive logging
471
- logger.warning(
472
- "Failed to resolve async dependency for '%s' on %s.",
473
- param_name,
474
- target,
475
- exc_info=exc,
476
- )
477
- return resolved
216
+ def _warn_deprecated_marker(test_name: str) -> None:
217
+ warnings.warn(
218
+ f"Using @pytest.mark.inject on test '{test_name}' is deprecated. "
219
+ "Use Provide[T] instead.",
220
+ DeprecationWarning,
221
+ stacklevel=4,
222
+ )
anydi/ext/typer.py CHANGED
@@ -91,17 +91,17 @@ def _process_callback(callback: Callable[..., Any], container: Container) -> Any
91
91
 
92
92
  # Validate parameters and collect which ones need injection
93
93
  for parameter in sig.parameters.values():
94
- interface, should_inject, _ = container.validate_injected_parameter(
94
+ dependency_type, should_inject, _ = container.validate_injected_parameter(
95
95
  parameter, call=callback
96
96
  )
97
97
  processed_parameter = container._injector.unwrap_parameter(parameter)
98
98
  if should_inject:
99
99
  injected_param_names.add(parameter.name)
100
100
  try:
101
- scopes.add(container.providers[interface].scope)
101
+ scopes.add(container.providers[dependency_type].scope)
102
102
  except KeyError:
103
- if inspect.isclass(interface) and is_provided(interface):
104
- scopes.add(interface.__provided__["scope"])
103
+ if inspect.isclass(dependency_type) and is_provided(dependency_type):
104
+ scopes.add(dependency_type.__provided__["scope"])
105
105
  else:
106
106
  non_injected_params.append(processed_parameter)
107
107
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anydi
3
- Version: 0.67.2
3
+ Version: 0.69.0
4
4
  Summary: Dependency Injection library
5
5
  Keywords: dependency injection,dependencies,di,async,asyncio,application
6
6
  Author: Anton Ruhlov
@@ -0,0 +1,29 @@
1
+ anydi/__init__.py,sha256=KFX8OthKXwBuYDPCV61t-044DpJ88tAOzIxeUWRC5OA,633
2
+ anydi/_async_lock.py,sha256=3dwZr0KthXFYha0XKMyXf8jMmGb1lYoNC0O5w29V9ic,1104
3
+ anydi/_cli.py,sha256=0BhNvWPyuIGzUkDELIBm_nsEMWk7MtLi3oTvgXj5oko,2072
4
+ anydi/_container.py,sha256=lxUkRYU35qSiwTZYXfydElD28n2imzS81qRAAIhiHZU,46677
5
+ anydi/_context.py,sha256=ZQWxtBXWkrMsCk_L7K_A7-e09v5Mv9HApPH3LZ6ZF9k,3648
6
+ anydi/_decorators.py,sha256=7FvgmBDruv1w_iVqwloPzZwQQgyzQCklM6r9f6UVn-E,5728
7
+ anydi/_graph.py,sha256=X7AYsTMcGZtnIUJD5CVc1t8-t54fSI8CY_xh6ijODWk,7945
8
+ anydi/_injector.py,sha256=RvnPEYOgkg-WOIW1ItvVsoAZaSC9wmCnWQrfXad_86A,4507
9
+ anydi/_marker.py,sha256=yXSPbIVU-X-jMSawtCHWFMKke5VpWMiBRZlEH8PlUqE,3373
10
+ anydi/_module.py,sha256=2kN5uEXLd2Dsc58gz5IWK43wJewr_QgIVGSO3iWp798,2609
11
+ anydi/_provider.py,sha256=5pMXyiGwBo2j6OHaoOktLQfiX2rkCf5aYXFlFi65JlQ,2898
12
+ anydi/_resolver.py,sha256=CTYCjYkUXX35o2VMwvVwXyF8Kqp7h2tXituCNq6oydM,32746
13
+ anydi/_scanner.py,sha256=rCPbpW_5OV9MwYQdwTfceV_MlwSMPfpTTKuxdcMmV98,5804
14
+ anydi/_types.py,sha256=lsShY_-_CM2EFajeknAYXvLl-rHfopBT8udnK5_BtS4,1161
15
+ anydi/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ anydi/ext/django/__init__.py,sha256=Ve8lncLU9dPY_Vjt4zihPgsSxwAtFHACn0XvBM5JG8k,367
17
+ anydi/ext/fastapi.py,sha256=NowHc-z_Sw069YDv9vP98Mehum5vHsIIcqvDkRmicmc,2964
18
+ anydi/ext/faststream.py,sha256=_3FZ8vlgl1GVizVv_6ippvwSWu_Zor4qm6HaiAp24o4,2744
19
+ anydi/ext/pydantic_settings.py,sha256=y6uz0MiLtqPvRO186bIdRZVQfezLvRUfT3KvvB5fCWk,1524
20
+ anydi/ext/pytest_plugin.py,sha256=rLZ6NZUYklSg1rYx0FPdSvVmEY-faZTYqEY5qUWqZXk,7336
21
+ anydi/ext/starlette/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ anydi/ext/starlette/middleware.py,sha256=n_JJ7BcG2Mg2M5HwM_SBboxZ-mnnD6WWJn4khq7Bgbs,1860
23
+ anydi/ext/typer.py,sha256=c7HapXQfKhnLJQcHNncJAGd8jZ3crX5it6-MRCJjyPM,6268
24
+ anydi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ anydi/testing.py,sha256=cHg3mMScZbEep9smRqSNQ81BZMQOkyugHe8TvKdPnEg,1347
26
+ anydi-0.69.0.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
27
+ anydi-0.69.0.dist-info/entry_points.txt,sha256=oDl_yEX12KlWcDzsZBTg85GG1Jl1rpiYOG4C7EJvebs,87
28
+ anydi-0.69.0.dist-info/METADATA,sha256=h8I4S5WOovGNeSInAJUV_9ASebz1FClByn1Ds4DcNRg,8061
29
+ anydi-0.69.0.dist-info/RECORD,,
@@ -1,3 +1,6 @@
1
+ [console_scripts]
2
+ anydi = anydi._cli:main
3
+
1
4
  [pytest11]
2
5
  anydi = anydi.ext.pytest_plugin
3
6