anydi 0.61.0__py3-none-any.whl → 0.62.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.
anydi/__init__.py CHANGED
@@ -2,9 +2,10 @@
2
2
 
3
3
  from ._container import Container, import_container
4
4
  from ._decorators import injectable, provided, provider, request, singleton, transient
5
+ from ._marker import Inject, Provide
5
6
  from ._module import Module
6
7
  from ._provider import ProviderDef as Provider
7
- from ._types import Inject, Provide, Scope
8
+ from ._types import Scope
8
9
 
9
10
  # Alias for dependency auto marker
10
11
  # TODO: deprecate it
anydi/_container.py CHANGED
@@ -18,11 +18,19 @@ from typing_extensions import ParamSpec, Self, type_repr
18
18
  from ._context import InstanceContext
19
19
  from ._decorators import is_provided
20
20
  from ._injector import Injector
21
+ from ._marker import Marker
21
22
  from ._module import ModuleDef, ModuleRegistrar
22
23
  from ._provider import Provider, ProviderDef, ProviderKind, ProviderParameter
23
24
  from ._resolver import Resolver
24
25
  from ._scanner import PackageOrIterable, Scanner
25
- from ._types import NOT_SET, Event, Scope, is_event_type, is_iterator_type, is_none_type
26
+ from ._types import (
27
+ NOT_SET,
28
+ Event,
29
+ Scope,
30
+ is_event_type,
31
+ is_iterator_type,
32
+ is_none_type,
33
+ )
26
34
 
27
35
  T = TypeVar("T", bound=Any)
28
36
  P = ParamSpec("P")
@@ -687,7 +695,7 @@ class Container:
687
695
 
688
696
  def validate_injected_parameter(
689
697
  self, parameter: inspect.Parameter, *, call: Callable[..., Any]
690
- ) -> tuple[Any, bool]:
698
+ ) -> tuple[Any, bool, Marker | None]:
691
699
  """Validate an injected parameter."""
692
700
  return self._injector.validate_parameter(parameter, call=call)
693
701
 
anydi/_injector.py CHANGED
@@ -17,7 +17,7 @@ from typing import (
17
17
 
18
18
  from typing_extensions import ParamSpec, type_repr
19
19
 
20
- from ._types import is_provide_marker
20
+ from ._marker import Marker, is_marker
21
21
 
22
22
  if TYPE_CHECKING:
23
23
  from ._container import Container
@@ -69,20 +69,21 @@ class Injector:
69
69
  """Get the injected parameters of a callable object."""
70
70
  injected_params: dict[str, Any] = {}
71
71
  for parameter in inspect.signature(call, eval_str=True).parameters.values():
72
- interface, should_inject = self.validate_parameter(parameter, call=call)
72
+ interface, should_inject, _ = self.validate_parameter(parameter, call=call)
73
73
  if should_inject:
74
74
  injected_params[parameter.name] = interface
75
75
  return injected_params
76
76
 
77
77
  def validate_parameter(
78
78
  self, parameter: inspect.Parameter, *, call: Callable[..., Any]
79
- ) -> tuple[Any, bool]:
79
+ ) -> tuple[Any, bool, Marker | None]:
80
80
  """Validate an injected parameter."""
81
81
  parameter = self.unwrap_parameter(parameter)
82
82
  interface = parameter.annotation
83
83
 
84
- if not is_provide_marker(parameter.default):
85
- return interface, False
84
+ marker = parameter.default
85
+ if not is_marker(marker):
86
+ return interface, False, None
86
87
 
87
88
  if interface is inspect.Parameter.empty:
88
89
  raise TypeError(
@@ -99,7 +100,7 @@ class Injector:
99
100
  f"`{type_repr(interface)}`."
100
101
  )
101
102
 
102
- return interface, True
103
+ return interface, True, marker
103
104
 
104
105
  @staticmethod
105
106
  def unwrap_parameter(parameter: inspect.Parameter) -> inspect.Parameter:
@@ -108,10 +109,10 @@ class Injector:
108
109
 
109
110
  origin, *metadata = get_args(parameter.annotation)
110
111
 
111
- if not metadata or not is_provide_marker(metadata[-1]):
112
+ if not metadata or not is_marker(metadata[-1]):
112
113
  return parameter
113
114
 
114
- if is_provide_marker(parameter.default):
115
+ if is_marker(parameter.default):
115
116
  raise TypeError(
116
117
  "Cannot specify `Inject` in `Annotated` and "
117
118
  f"default value together for '{parameter.name}'"
anydi/_marker.py ADDED
@@ -0,0 +1,116 @@
1
+ """Provide marker implementation and utilities."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Annotated, Any, TypeVar
6
+
7
+ from ._types import NOT_SET
8
+
9
+ T = TypeVar("T")
10
+
11
+
12
+ class Marker:
13
+ """Marker stored in annotations or defaults to request injection."""
14
+
15
+ __slots__ = ("_interface", "_attrs", "_preferred_owner", "_current_owner")
16
+
17
+ _FRAMEWORK_ATTRS = frozenset({"dependency", "use_cache", "cast", "cast_result"})
18
+
19
+ def __init__(self, interface: Any = NOT_SET) -> None:
20
+ # Avoid reinitializing attributes when mixins call __init__ multiple times
21
+ if not hasattr(self, "_attrs"):
22
+ super().__init__()
23
+ self._attrs: dict[str, dict[str, Any]] = {}
24
+ self._preferred_owner = "fastapi"
25
+ self._current_owner: str | None = None
26
+ self._interface = interface
27
+
28
+ def set_owner(self, owner: str) -> None:
29
+ self._preferred_owner = owner
30
+
31
+ def _store_attr(self, name: str, value: Any) -> None:
32
+ owner = self._current_owner or self._preferred_owner
33
+ self._attrs.setdefault(owner, {})[name] = value
34
+
35
+ def _get_attr(self, name: str) -> Any:
36
+ owner = self._preferred_owner
37
+ if owner in self._attrs and name in self._attrs[owner]:
38
+ return self._attrs[owner][name]
39
+ for attrs in self._attrs.values():
40
+ if name in attrs:
41
+ return attrs[name]
42
+ raise AttributeError(name)
43
+
44
+ def __setattr__(self, name: str, value: Any) -> None:
45
+ if name in self._FRAMEWORK_ATTRS and hasattr(self, "_attrs"):
46
+ self._store_attr(name, value)
47
+ else:
48
+ super().__setattr__(name, value)
49
+
50
+ def __getattr__(self, name: str) -> Any:
51
+ if name in self._FRAMEWORK_ATTRS and hasattr(self, "_attrs"):
52
+ return self._get_attr(name)
53
+ raise AttributeError(name)
54
+
55
+ @property
56
+ def interface(self) -> Any:
57
+ if self._interface is NOT_SET:
58
+ raise TypeError("Interface is not set.")
59
+ return self._interface
60
+
61
+ @interface.setter
62
+ def interface(self, interface: Any) -> None:
63
+ self._interface = interface
64
+
65
+ def __class_getitem__(cls, item: Any) -> Any:
66
+ return Annotated[item, cls()]
67
+
68
+
69
+ _marker_cls: type[Marker] = Marker
70
+
71
+
72
+ def extend_marker(marker_cls: type[Marker]) -> None:
73
+ """Register an additional framework-specific provide marker."""
74
+
75
+ global _marker_cls
76
+ previous = _marker_cls
77
+
78
+ if previous is Marker:
79
+ _marker_cls = marker_cls
80
+ else:
81
+ name = f"Marker_{marker_cls.__name__}_{previous.__name__}"
82
+
83
+ def __init__(self: Marker) -> None:
84
+ marker_cls.__init__(self)
85
+ previous.__init__(self)
86
+
87
+ combined: type[Marker] = type(
88
+ name, (marker_cls, previous), {"__init__": __init__}
89
+ )
90
+ _marker_cls = combined
91
+
92
+
93
+ def is_marker(obj: Any) -> bool:
94
+ return isinstance(obj, Marker)
95
+
96
+
97
+ class _ProvideMeta(type):
98
+ """Metaclass for Provide that delegates __class_getitem__ to the active marker."""
99
+
100
+ def __getitem__(cls, item: Any) -> Any:
101
+ if hasattr(_marker_cls, "__class_getitem__"):
102
+ return _marker_cls.__class_getitem__(item) # type: ignore
103
+ return Annotated[item, _marker_cls()]
104
+
105
+
106
+ if TYPE_CHECKING:
107
+ Provide = Annotated[T, Marker()]
108
+
109
+ else:
110
+
111
+ class Provide(metaclass=_ProvideMeta):
112
+ pass
113
+
114
+
115
+ def Inject() -> Any:
116
+ return _marker_cls()
anydi/_types.py CHANGED
@@ -3,85 +3,17 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import inspect
6
- from collections.abc import AsyncIterator, Callable, Iterator
6
+ from collections.abc import AsyncIterator, Iterator
7
7
  from types import NoneType
8
- from typing import TYPE_CHECKING, Annotated, Any, Literal, TypeVar
8
+ from typing import Any, Literal
9
9
 
10
10
  from typing_extensions import Sentinel
11
11
 
12
- T = TypeVar("T")
13
-
14
12
  Scope = Literal["transient", "singleton", "request"] | str
15
13
 
16
14
  NOT_SET = Sentinel("NOT_SET")
17
15
 
18
16
 
19
- class ProvideMarker:
20
- """A marker object for declaring dependency."""
21
-
22
- __slots__ = ("_interface",)
23
-
24
- def __init__(self, interface: Any = NOT_SET) -> None:
25
- self._interface = interface
26
-
27
- @property
28
- def interface(self) -> Any:
29
- if self._interface is NOT_SET:
30
- raise TypeError("Interface is not set.")
31
- return self._interface
32
-
33
- @interface.setter
34
- def interface(self, interface: Any) -> None:
35
- self._interface = interface
36
-
37
- def __class_getitem__(cls, item: Any) -> Any:
38
- return Annotated[item, cls()]
39
-
40
-
41
- _provide_factory: Callable[[], Any] = ProvideMarker
42
-
43
-
44
- def set_provide_factory(factory: Callable[[], Any]) -> Callable[[], Any]:
45
- """Set the global factory used by Inject() and Provide."""
46
- global _provide_factory
47
- previous = _provide_factory
48
- _provide_factory = factory
49
- return previous
50
-
51
-
52
- def is_provide_marker(obj: Any) -> bool:
53
- return isinstance(obj, ProvideMarker)
54
-
55
-
56
- class _ProvideMeta(type):
57
- """Metaclass for Provide that delegates __class_getitem__ to the current factory."""
58
-
59
- def __getitem__(cls, item: Any) -> Any:
60
- # Use the current factory's __class_getitem__ if available
61
- factory = _provide_factory
62
- if hasattr(factory, "__class_getitem__"):
63
- return factory.__class_getitem__(item) # type: ignore[attr-defined]
64
- # Fallback to creating Annotated with factory instance
65
- return Annotated[item, factory()]
66
-
67
-
68
- if TYPE_CHECKING:
69
- Provide = Annotated[T, ProvideMarker()]
70
-
71
- else:
72
-
73
- class Provide(metaclass=_ProvideMeta):
74
- pass
75
-
76
-
77
- def Inject() -> Any:
78
- return _provide_factory()
79
-
80
-
81
- # Alias from backward compatibility
82
- is_inject_marker = is_provide_marker
83
-
84
-
85
17
  class Event:
86
18
  """Represents an event object."""
87
19
 
anydi/ext/fastapi.py CHANGED
@@ -12,7 +12,7 @@ from fastapi.routing import APIRoute
12
12
  from starlette.requests import Request
13
13
 
14
14
  from anydi import Container, Inject
15
- from anydi._types import ProvideMarker, set_provide_factory
15
+ from anydi._marker import Marker, extend_marker
16
16
 
17
17
  from .starlette.middleware import RequestScopedMiddleware
18
18
 
@@ -24,19 +24,23 @@ def get_container(request: Request) -> Container:
24
24
  return cast(Container, request.app.state.container)
25
25
 
26
26
 
27
- class _ProvideMarker(params.Depends, ProvideMarker):
27
+ class FastAPIMarker(params.Depends, Marker):
28
28
  def __init__(self) -> None:
29
- super().__init__(dependency=self._dependency, use_cache=True)
30
- ProvideMarker.__init__(self)
31
-
32
- async def _dependency(
29
+ Marker.__init__(self)
30
+ self._current_owner = "fastapi"
31
+ params.Depends.__init__(
32
+ self, dependency=self._fastapi_dependency, use_cache=True
33
+ )
34
+ self._current_owner = None
35
+
36
+ async def _fastapi_dependency(
33
37
  self, container: Annotated[Container, Depends(get_container)]
34
38
  ) -> Any:
35
39
  return await container.aresolve(self.interface)
36
40
 
37
41
 
38
42
  # Configure Inject() and Provide[T] to use FastAPI-specific marker
39
- set_provide_factory(_ProvideMarker)
43
+ extend_marker(FastAPIMarker)
40
44
 
41
45
 
42
46
  def _iter_dependencies(dependant: Dependant) -> Iterator[Dependant]:
@@ -57,7 +61,11 @@ def _validate_route_dependencies(
57
61
  if not call:
58
62
  continue # pragma: no cover
59
63
  for parameter in inspect.signature(call, eval_str=True).parameters.values():
60
- container.validate_injected_parameter(parameter, call=call)
64
+ _, should_inject, marker = container.validate_injected_parameter(
65
+ parameter, call=call
66
+ )
67
+ if should_inject and marker:
68
+ marker.set_owner("fastapi")
61
69
 
62
70
 
63
71
  def install(app: FastAPI, container: Container) -> None:
anydi/ext/faststream.py CHANGED
@@ -10,7 +10,7 @@ from fast_depends.dependencies import Dependant
10
10
  from faststream import BaseMiddleware, ContextRepo, StreamMessage
11
11
 
12
12
  from anydi import Container
13
- from anydi._types import Inject, ProvideMarker, set_provide_factory
13
+ from anydi._marker import Inject, Marker, extend_marker
14
14
 
15
15
  if TYPE_CHECKING:
16
16
  from faststream._internal.basic_types import AsyncFuncAny
@@ -47,18 +47,26 @@ class RequestScopedMiddleware(BaseMiddleware):
47
47
  return await call_next(msg)
48
48
 
49
49
 
50
- class _ProvideMarker(Dependant, ProvideMarker):
50
+ class FastStreamMarker(Dependant, Marker):
51
51
  def __init__(self) -> None:
52
- super().__init__(self._dependency, use_cache=True, cast=True, cast_result=True)
53
- ProvideMarker.__init__(self)
54
-
55
- async def _dependency(self, context: ContextRepo) -> Any:
52
+ Marker.__init__(self)
53
+ self._current_owner = "faststream"
54
+ Dependant.__init__(
55
+ self,
56
+ self._faststream_dependency,
57
+ use_cache=True,
58
+ cast=True,
59
+ cast_result=True,
60
+ )
61
+ self._current_owner = None
62
+
63
+ async def _faststream_dependency(self, context: ContextRepo) -> Any:
56
64
  container = get_container_from_context(context)
57
65
  return await container.aresolve(self.interface)
58
66
 
59
67
 
60
68
  # Configure Inject() and Provide[T] to use FastStream-specific marker
61
- set_provide_factory(_ProvideMarker)
69
+ extend_marker(FastStreamMarker)
62
70
 
63
71
 
64
72
  def _get_broker_handlers(broker: BrokerUsecase[Any, Any]) -> list[Any]:
@@ -71,4 +79,8 @@ def install(broker: BrokerUsecase[Any, Any], container: Container) -> None:
71
79
  for handler in _get_broker_handlers(broker):
72
80
  call = handler._original_call # noqa
73
81
  for parameter in inspect.signature(call, eval_str=True).parameters.values():
74
- container.validate_injected_parameter(parameter, call=call)
82
+ _, should_inject, marker = container.validate_injected_parameter(
83
+ parameter, call=call
84
+ )
85
+ if should_inject and marker:
86
+ marker.set_owner("faststream")
anydi/ext/typer.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import concurrent.futures
5
6
  import contextlib
6
7
  import functools
7
8
  import inspect
@@ -9,6 +10,7 @@ from collections.abc import Awaitable, Callable
9
10
  from typing import Any
10
11
 
11
12
  import anyio
13
+ import sniffio
12
14
  from typer import Typer
13
15
 
14
16
  from anydi import Container, Scope
@@ -22,7 +24,16 @@ def _wrap_async_callback_no_injection(callback: Callable[..., Any]) -> Any:
22
24
 
23
25
  @functools.wraps(callback)
24
26
  def async_no_injection_wrapper(*args: Any, **kwargs: Any) -> Any:
25
- return anyio.run(callback, *args, **kwargs)
27
+ # Check if we're already in an async context
28
+ try:
29
+ sniffio.current_async_library()
30
+ # We're in an async context, run anyio.run() in a separate thread
31
+ with concurrent.futures.ThreadPoolExecutor() as executor:
32
+ future = executor.submit(anyio.run, callback, *args, **kwargs)
33
+ return future.result()
34
+ except sniffio.AsyncLibraryNotFoundError:
35
+ # Not in an async context, can use anyio.run directly
36
+ return anyio.run(callback, *args, **kwargs)
26
37
 
27
38
  return async_no_injection_wrapper
28
39
 
@@ -54,7 +65,16 @@ def _wrap_async_callback_with_injection(
54
65
 
55
66
  return await container.run(callback, *args, **kwargs)
56
67
 
57
- return anyio.run(_run)
68
+ # Check if we're already in an async context
69
+ try:
70
+ sniffio.current_async_library()
71
+ # We're in an async context, run anyio.run() in a separate thread
72
+ with concurrent.futures.ThreadPoolExecutor() as executor:
73
+ future = executor.submit(anyio.run, _run)
74
+ return future.result()
75
+ except sniffio.AsyncLibraryNotFoundError:
76
+ # Not in an async context, can use anyio.run directly
77
+ return anyio.run(_run)
58
78
 
59
79
  # Update the wrapper's signature to only show non-injected parameters to Typer
60
80
  async_wrapper.__signature__ = sig.replace(parameters=non_injected_params) # type: ignore
@@ -71,9 +91,10 @@ def _process_callback(callback: Callable[..., Any], container: Container) -> Any
71
91
 
72
92
  # Validate parameters and collect which ones need injection
73
93
  for parameter in sig.parameters.values():
74
- interface, should_inject = container.validate_injected_parameter(
94
+ interface, should_inject, _ = container.validate_injected_parameter(
75
95
  parameter, call=callback
76
96
  )
97
+ processed_parameter = container._injector.unwrap_parameter(parameter)
77
98
  if should_inject:
78
99
  injected_param_names.add(parameter.name)
79
100
  try:
@@ -82,7 +103,7 @@ def _process_callback(callback: Callable[..., Any], container: Container) -> Any
82
103
  if inspect.isclass(interface) and is_provided(interface):
83
104
  scopes.add(interface.__provided__["scope"])
84
105
  else:
85
- non_injected_params.add(parameter)
106
+ non_injected_params.add(processed_parameter)
86
107
 
87
108
  # If no parameters need injection and callback is not async, return original
88
109
  if not injected_param_names and not inspect.iscoroutinefunction(callback):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anydi
3
- Version: 0.61.0
3
+ Version: 0.62.0
4
4
  Summary: Dependency Injection library
5
5
  Keywords: dependency injection,dependencies,di,async,asyncio,application
6
6
  Author: Anton Ruhlov
@@ -1,26 +1,27 @@
1
- anydi/__init__.py,sha256=bQKzn9qfNnIMi1m3J-DdSknSDwNg8j08fdQg_-Edkto,613
1
+ anydi/__init__.py,sha256=KFX8OthKXwBuYDPCV61t-044DpJ88tAOzIxeUWRC5OA,633
2
2
  anydi/_async_lock.py,sha256=3dwZr0KthXFYha0XKMyXf8jMmGb1lYoNC0O5w29V9ic,1104
3
- anydi/_container.py,sha256=oJ1EQnQ1tvi3Y0XNJvhmjVKVd-KzzRbNVaazIRuG3w4,27900
3
+ anydi/_container.py,sha256=fXRJGMprZ5heLsVBEy0Ma_tCTciiK2_Qdsb1HW36tj8,27972
4
4
  anydi/_context.py,sha256=-9QqeMWo9OpZVXZxZCQgIsswggl3Ch7lgx1KiFX_ezc,3752
5
5
  anydi/_decorators.py,sha256=J3W261ZAG7q4XKm4tbAv1wsWr9ysx9_5MUbUvSJB_MQ,2809
6
- anydi/_injector.py,sha256=IxKTh2rzMHrsW554tbiJl33Hb5sRGKYY_NU1rC4UvxE,4378
6
+ anydi/_injector.py,sha256=1Ux71DhGxu3dLwPJP8gU73olI0pcZ3_tVaVzwKH7100,4411
7
+ anydi/_marker.py,sha256=xVydjGdkxd_DqqwttnJZRkQbhpCTE9OnrhFmFJMlgvI,3415
7
8
  anydi/_module.py,sha256=2kN5uEXLd2Dsc58gz5IWK43wJewr_QgIVGSO3iWp798,2609
8
9
  anydi/_provider.py,sha256=OV1WFHTYv7W2U0XDk_Kql1r551Vhq8o-pUV5ep1HQcU,1574
9
10
  anydi/_resolver.py,sha256=dMtWU4OHWMYP7J2Rks0sdwyjLHF1uKo77lnvTGhhtBo,30222
10
11
  anydi/_scanner.py,sha256=rbRkHzyd2zMu7AFLffN6_tZJcMaW9gy7E-lVdHLHYrs,4294
11
- anydi/_types.py,sha256=tLJS27j0lWJFd4fIIGlGbbfKBVTPTnWgPYqZlenktis,2939
12
+ anydi/_types.py,sha256=lsShY_-_CM2EFajeknAYXvLl-rHfopBT8udnK5_BtS4,1161
12
13
  anydi/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
14
  anydi/ext/django/__init__.py,sha256=Ve8lncLU9dPY_Vjt4zihPgsSxwAtFHACn0XvBM5JG8k,367
14
- anydi/ext/fastapi.py,sha256=TQoS1Vh9chV0Tj0qyxjgqoGTYEMC3jp0il9CDZCZLcc,2326
15
- anydi/ext/faststream.py,sha256=i6uXE21UawmTYDBqRv7yqDMc-lRiYSYf45sD87O2wX4,2442
15
+ anydi/ext/fastapi.py,sha256=ExDuCLtKB4DBk0GUe70JSzAfyKJs-BcPvHINsXoNVos,2560
16
+ anydi/ext/faststream.py,sha256=yszUfSbo3vJ2tr9PNC2GR-uX1XgRSXGH2lvLNoAXkc4,2738
16
17
  anydi/ext/pydantic_settings.py,sha256=jVJZ1wPaPpsxdNPlJj9yq282ebqLZ9tckWpZ0eIwWLg,1533
17
18
  anydi/ext/pytest_plugin.py,sha256=M54DkA-KxD9GqLnXdoCyn-Qur2c44MB6d0AgJuYCZ5w,16171
18
19
  anydi/ext/starlette/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
20
  anydi/ext/starlette/middleware.py,sha256=9CQtGg5ZzUz2gFSzJr8U4BWzwNjK8XMctm3n52M77Z0,792
20
- anydi/ext/typer.py,sha256=Jw3DspLeCD_yF_GSk4eDlC3bZJWMNYpJ3H6zs5PTVAc,5133
21
+ anydi/ext/typer.py,sha256=z-sDd3jZMPTE2CyEuJ0f9uIJB43FjoLWbjpnkOvqSKA,6236
21
22
  anydi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
23
  anydi/testing.py,sha256=cHg3mMScZbEep9smRqSNQ81BZMQOkyugHe8TvKdPnEg,1347
23
- anydi-0.61.0.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
24
- anydi-0.61.0.dist-info/entry_points.txt,sha256=AgOcQYM5KyS4D37QcYb00tiid0QA-pD1VrjHHq4QAps,44
25
- anydi-0.61.0.dist-info/METADATA,sha256=s2qDGW7f-s4bAkHDjl_QNl1AJY8VHHkXNwDJK1_VEQ8,8007
26
- anydi-0.61.0.dist-info/RECORD,,
24
+ anydi-0.62.0.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
25
+ anydi-0.62.0.dist-info/entry_points.txt,sha256=AgOcQYM5KyS4D37QcYb00tiid0QA-pD1VrjHHq4QAps,44
26
+ anydi-0.62.0.dist-info/METADATA,sha256=eWtDMEmZnfsaNCmqZ2CN1AS5DzE5gk4swTQCHcDg0WM,8007
27
+ anydi-0.62.0.dist-info/RECORD,,
File without changes