mode-streaming 0.5.0__tar.gz → 0.5.1__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.
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/PKG-INFO +1 -1
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/objects.py +62 -37
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode_streaming.egg-info/PKG-INFO +1 -1
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode_streaming.egg-info/scm_version.json +2 -2
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/utils/test_objects.py +24 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/.editorconfig +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/.github/ISSUE_TEMPLATE.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/.github/workflows/deploy-docs.yml +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/.github/workflows/publish.yml +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/.github/workflows/tests.yml +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/.gitignore +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/.pre-commit-config.yaml +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/AUTHORS +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/CHANGELOG.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/CODE_OF_CONDUCT.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/CONTRIBUTING.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/LICENSE +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/README.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/changelog.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/contributing.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/creating-service.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/example-service.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/example-webapp.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/index.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.debug.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.exceptions.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.locals.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.loop.eventlet.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.loop.gevent.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.loop.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.loop.uvloop.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.proxy.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.services.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.signals.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.supervisors.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.threads.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.timers.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.types.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.types.services.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.types.signals.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.types.supervisors.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.aiter.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.collections.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.compat.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.contexts.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.cron.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.futures.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.graphs.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.imports.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.locals.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.locks.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.logging.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.loops.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.mocks.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.objects.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.queues.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.text.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.times.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.tracebacks.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.trees.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.types.graphs.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.utils.types.trees.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/docs/references/mode.worker.md +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/examples/service.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/examples/webapp.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mkdocs.yml +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/__init__.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/debug.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/exceptions.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/locals.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/loop/__init__.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/loop/_gevent_loop.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/loop/eventlet.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/loop/gevent.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/loop/uvloop.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/proxy.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/py.typed +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/services.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/signals.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/supervisors.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/threads.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/timers.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/types/__init__.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/types/services.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/types/signals.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/types/supervisors.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/__init__.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/aiter.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/collections.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/compat.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/contexts.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/cron.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/futures.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/graphs/__init__.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/graphs/formatter.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/graphs/graph.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/imports.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/locals.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/locks.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/logging.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/loops.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/mocks.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/queues.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/text.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/times.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/tracebacks.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/trees.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/types/__init__.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/types/graphs.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/utils/types/trees.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode/worker.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode_streaming.egg-info/SOURCES.txt +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode_streaming.egg-info/dependency_links.txt +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode_streaming.egg-info/requires.txt +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode_streaming.egg-info/scm_file_list.json +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/mode_streaming.egg-info/top_level.txt +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/pyproject.toml +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/requirements-docs.txt +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/requirements-tests.txt +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/requirements.txt +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/scripts/build-docs.sh +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/scripts/build.sh +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/scripts/bump.sh +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/scripts/clean.sh +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/scripts/format.sh +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/scripts/lint.sh +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/scripts/tests.sh +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/setup.cfg +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/__init__.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/conftest.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/__init__.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/test_mode.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/test_proxy.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/test_service.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/test_signals.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/test_supervisors.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/test_timers.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/utils/__init__.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/utils/test_aiter.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/utils/test_collections.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/utils/test_compat.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/utils/test_contexts.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/utils/test_futures.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/utils/test_locals.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/utils/test_queues.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/utils/test_text.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/utils/test_times.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/utils/test_tracebacks.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/functional/utils/test_trees.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/__init__.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/test_debug.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/test_locals.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/test_services.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/test_supervisors.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/test_threads.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/test_worker.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/utils/__init__.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/utils/test_cron.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/utils/test_imports.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/utils/test_locks.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/utils/test_logging.py +0 -0
- {mode_streaming-0.5.0 → mode_streaming-0.5.1}/tests/unit/utils/test_loops.py +0 -0
|
@@ -28,7 +28,6 @@ from typing import (
|
|
|
28
28
|
cast,
|
|
29
29
|
get_args,
|
|
30
30
|
get_origin,
|
|
31
|
-
get_type_hints,
|
|
32
31
|
)
|
|
33
32
|
|
|
34
33
|
try:
|
|
@@ -39,20 +38,39 @@ except ImportError:
|
|
|
39
38
|
return t
|
|
40
39
|
|
|
41
40
|
|
|
42
|
-
try:
|
|
43
|
-
from typing import _type_check # type: ignore
|
|
44
|
-
except ImportError:
|
|
45
|
-
|
|
46
|
-
def _type_check(arg, msg, is_argument=True, module=None): # type: ignore
|
|
47
|
-
return arg
|
|
48
|
-
|
|
49
|
-
|
|
50
41
|
def _is_class_var(typ):
|
|
51
42
|
# Works for typing.ClassVar and types.GenericAlias (Python 3.9+)
|
|
52
43
|
origin = getattr(typ, "__origin__", None)
|
|
53
44
|
return origin is ClassVar
|
|
54
45
|
|
|
55
46
|
|
|
47
|
+
if sys.version_info >= (3, 10):
|
|
48
|
+
from inspect import get_annotations as _own_annotations
|
|
49
|
+
else:
|
|
50
|
+
|
|
51
|
+
def _own_annotations(
|
|
52
|
+
cls: type,
|
|
53
|
+
*,
|
|
54
|
+
globals: Optional[dict] = None,
|
|
55
|
+
locals: Optional[dict] = None,
|
|
56
|
+
eval_str: bool = False,
|
|
57
|
+
) -> dict:
|
|
58
|
+
"""Backport of :func:`inspect.get_annotations` for Python 3.9.
|
|
59
|
+
|
|
60
|
+
Returns only the annotations declared directly in ``cls.__dict__``,
|
|
61
|
+
never inherited ones -- matching the 3.10+ stdlib function this
|
|
62
|
+
shadows, which is what makes it safe to use per-class inside a
|
|
63
|
+
bounded MRO walk (see ``local_annotations`` below).
|
|
64
|
+
"""
|
|
65
|
+
ann = cls.__dict__.get("__annotations__", {})
|
|
66
|
+
if eval_str:
|
|
67
|
+
ann = {
|
|
68
|
+
k: (eval(v, globals, locals) if isinstance(v, str) else v) # noqa: S307
|
|
69
|
+
for k, v in ann.items()
|
|
70
|
+
}
|
|
71
|
+
return dict(ann)
|
|
72
|
+
|
|
73
|
+
|
|
56
74
|
def _get_globalns(cls):
|
|
57
75
|
# Get the global namespace for a class
|
|
58
76
|
module = sys.modules.get(cls.__module__)
|
|
@@ -364,9 +382,31 @@ def local_annotations(
|
|
|
364
382
|
globalns: Optional[dict[str, Any]] = None,
|
|
365
383
|
localns: Optional[dict[str, Any]] = None,
|
|
366
384
|
) -> Iterable[tuple[str, type]]:
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
)
|
|
385
|
+
# NOTE: Must only consider annotations defined directly on `cls`, not
|
|
386
|
+
# inherited ones. `annotations()` (the caller) already walks the MRO
|
|
387
|
+
# itself via `iter_mro_reversed(cls, stop=stop)` and calls
|
|
388
|
+
# `local_annotations` once per class in that bounded range, so callers
|
|
389
|
+
# can exclude base classes at/above `stop` (e.g. faust.Record excludes
|
|
390
|
+
# its internal ModelT/Model bases this way). Using
|
|
391
|
+
# `typing.get_type_hints(cls, ...)` here defeats that: it always merges
|
|
392
|
+
# annotations from the *entire* real MRO regardless of `stop`, so a
|
|
393
|
+
# non-ClassVar annotation on an excluded base (e.g.
|
|
394
|
+
# `ModelT.__evaluated_fields__`) would leak back in as if it were a
|
|
395
|
+
# field of every subclass.
|
|
396
|
+
#
|
|
397
|
+
# Plain `cls.__annotations__` attribute access is *not* safe for this
|
|
398
|
+
# either: on Python < 3.10 it falls back to an inherited base's
|
|
399
|
+
# `__annotations__` via normal MRO lookup when `cls` itself has none of
|
|
400
|
+
# its own (re-introducing the same kind of leak), and on Python 3.14+
|
|
401
|
+
# (PEP 649, deferred evaluation of annotations) direct `__annotations__`
|
|
402
|
+
# access on a class can behave unreliably -- the stdlib explicitly
|
|
403
|
+
# recommends `inspect.get_annotations()` instead, which reads only
|
|
404
|
+
# `cls.__dict__["__annotations__"]` (own annotations, no MRO fallback)
|
|
405
|
+
# and is written to handle PEP 649 correctly. `_own_annotations` here is
|
|
406
|
+
# that function, with a same-behavior backport for 3.9. String/ForwardRef
|
|
407
|
+
# annotations are still resolved below, per value, via
|
|
408
|
+
# `_resolve_refs`/`eval_type`.
|
|
409
|
+
d = _own_annotations(cls)
|
|
370
410
|
return _resolve_refs(
|
|
371
411
|
d,
|
|
372
412
|
globalns if globalns is not None else _get_globalns(cls),
|
|
@@ -415,37 +455,22 @@ def eval_type(
|
|
|
415
455
|
alias_types = alias_types or {}
|
|
416
456
|
if isinstance(typ, str):
|
|
417
457
|
typ = ForwardRef(typ)
|
|
418
|
-
|
|
419
|
-
|
|
458
|
+
# `typing._eval_type` (imported above as `_eval_type`) already resolves
|
|
459
|
+
# ForwardRef instances directly -- it is the same stdlib function
|
|
460
|
+
# `typing.get_type_hints()` itself relies on, so it always matches
|
|
461
|
+
# whatever internal ForwardRef implementation the running interpreter
|
|
462
|
+
# has (this previously went through a hand-rolled evaluator here that
|
|
463
|
+
# poked at ForwardRef's private __forward_evaluated__/__forward_code__/
|
|
464
|
+
# __forward_value__ attributes as a workaround for Python 3.6/3.7; those
|
|
465
|
+
# attributes are not part of any stable API and are no longer present at
|
|
466
|
+
# all on Python 3.14's ForwardRef, which raised AttributeError. mode's
|
|
467
|
+
# floor is Python 3.9, well past the versions that workaround targeted).
|
|
420
468
|
typ = _eval_type(typ, globalns, localns)
|
|
421
469
|
if typ in invalid_types:
|
|
422
470
|
raise InvalidAnnotation(typ)
|
|
423
471
|
return alias_types.get(typ, typ)
|
|
424
472
|
|
|
425
473
|
|
|
426
|
-
def _ForwardRef_safe_eval(
|
|
427
|
-
ref: ForwardRef,
|
|
428
|
-
globalns: Optional[dict[str, Any]] = None,
|
|
429
|
-
localns: Optional[dict[str, Any]] = None,
|
|
430
|
-
) -> type:
|
|
431
|
-
# On 3.6/3.7 ForwardRef._evaluate crashes if str references ClassVar
|
|
432
|
-
if not ref.__forward_evaluated__:
|
|
433
|
-
if globalns is None and localns is None:
|
|
434
|
-
globalns = localns = {}
|
|
435
|
-
elif globalns is None:
|
|
436
|
-
globalns = localns
|
|
437
|
-
elif localns is None:
|
|
438
|
-
localns = globalns
|
|
439
|
-
val = eval(ref.__forward_code__, globalns, localns) # noqa: S307
|
|
440
|
-
if not _is_class_var(val):
|
|
441
|
-
val = _type_check(
|
|
442
|
-
val, "Forward references must evaluate to types."
|
|
443
|
-
)
|
|
444
|
-
ref.__forward_value__ = val
|
|
445
|
-
ref.__forward_evaluated__ = True
|
|
446
|
-
return ref.__forward_value__
|
|
447
|
-
|
|
448
|
-
|
|
449
474
|
def iter_mro_reversed(cls: type, stop: type) -> Iterable[type]:
|
|
450
475
|
"""Iterate over superclasses, in reverse Method Resolution Order.
|
|
451
476
|
|
|
@@ -251,6 +251,30 @@ def test_annotations__no_local_ns_raises():
|
|
|
251
251
|
annotations(X, globalns=None, localns=None)
|
|
252
252
|
|
|
253
253
|
|
|
254
|
+
def test_annotations__stop_excludes_base_above_stop():
|
|
255
|
+
# Regression test: a non-ClassVar annotation on a base class *above*
|
|
256
|
+
# `stop` must not leak into the fields of a subclass, even though
|
|
257
|
+
# Python's typing.get_type_hints() (which local_annotations() must NOT
|
|
258
|
+
# use directly) would normally merge annotations across the whole real
|
|
259
|
+
# MRO regardless of any `stop` boundary.
|
|
260
|
+
class Base:
|
|
261
|
+
# Deliberately not ClassVar, mirroring faust ModelT.__evaluated_fields__.
|
|
262
|
+
internal: int = 0
|
|
263
|
+
|
|
264
|
+
class Middle(Base):
|
|
265
|
+
pass
|
|
266
|
+
|
|
267
|
+
class Leaf(Middle):
|
|
268
|
+
foo: int
|
|
269
|
+
|
|
270
|
+
fields, _ = annotations(
|
|
271
|
+
Leaf, stop=Middle, globalns=globals(), localns=locals()
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
assert "internal" not in fields
|
|
275
|
+
assert fields == {"foo": int}
|
|
276
|
+
|
|
277
|
+
|
|
254
278
|
@pytest.mark.parametrize(
|
|
255
279
|
"input,expected",
|
|
256
280
|
[
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|