main commit
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-10-16 16:30:25 +09:00
parent 91c7e04474
commit 537e7b363f
1146 changed files with 45926 additions and 77196 deletions

View File

@@ -1,5 +1,5 @@
# util/langhelpers.py
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
# Copyright (C) 2005-2023 the SQLAlchemy authors and contributors
# <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
@@ -60,85 +60,7 @@ _HP = TypeVar("_HP", bound="hybridproperty[Any]")
_HM = TypeVar("_HM", bound="hybridmethod[Any]")
if compat.py314:
# vendor a minimal form of get_annotations per
# https://github.com/python/cpython/issues/133684#issuecomment-2863841891
from annotationlib import call_annotate_function # type: ignore
from annotationlib import Format
def _get_and_call_annotate(obj, format): # noqa: A002
annotate = getattr(obj, "__annotate__", None)
if annotate is not None:
ann = call_annotate_function(annotate, format, owner=obj)
if not isinstance(ann, dict):
raise ValueError(f"{obj!r}.__annotate__ returned a non-dict")
return ann
return None
# this is ported from py3.13.0a7
_BASE_GET_ANNOTATIONS = type.__dict__["__annotations__"].__get__ # type: ignore # noqa: E501
def _get_dunder_annotations(obj):
if isinstance(obj, type):
try:
ann = _BASE_GET_ANNOTATIONS(obj)
except AttributeError:
# For static types, the descriptor raises AttributeError.
return {}
else:
ann = getattr(obj, "__annotations__", None)
if ann is None:
return {}
if not isinstance(ann, dict):
raise ValueError(
f"{obj!r}.__annotations__ is neither a dict nor None"
)
return dict(ann)
def _vendored_get_annotations(
obj: Any, *, format: Format # noqa: A002
) -> Mapping[str, Any]:
"""A sparse implementation of annotationlib.get_annotations()"""
try:
ann = _get_dunder_annotations(obj)
except Exception:
pass
else:
if ann is not None:
return dict(ann)
# But if __annotations__ threw a NameError, we try calling __annotate__
ann = _get_and_call_annotate(obj, format)
if ann is None:
# If that didn't work either, we have a very weird object:
# evaluating
# __annotations__ threw NameError and there is no __annotate__.
# In that case,
# we fall back to trying __annotations__ again.
ann = _get_dunder_annotations(obj)
if ann is None:
if isinstance(obj, type) or callable(obj):
return {}
raise TypeError(f"{obj!r} does not have annotations")
if not ann:
return {}
return dict(ann)
def get_annotations(obj: Any) -> Mapping[str, Any]:
# FORWARDREF has the effect of giving us ForwardRefs and not
# actually trying to evaluate the annotations. We need this so
# that the annotations act as much like
# "from __future__ import annotations" as possible, which is going
# away in future python as a separate mode
return _vendored_get_annotations(obj, format=Format.FORWARDREF)
elif compat.py310:
if compat.py310:
def get_annotations(obj: Any) -> Mapping[str, Any]:
return inspect.get_annotations(obj)
@@ -252,11 +174,10 @@ def string_or_unprintable(element: Any) -> str:
return "unprintable element %r" % element
def clsname_as_plain_name(
cls: Type[Any], use_name: Optional[str] = None
) -> str:
name = use_name or cls.__name__
return " ".join(n.lower() for n in re.findall(r"([A-Z][a-z]+|SQL)", name))
def clsname_as_plain_name(cls: Type[Any]) -> str:
return " ".join(
n.lower() for n in re.findall(r"([A-Z][a-z]+|SQL)", cls.__name__)
)
def method_is_overridden(
@@ -328,30 +249,10 @@ def decorator(target: Callable[..., Any]) -> Callable[[_Fn], _Fn]:
if not inspect.isfunction(fn) and not inspect.ismethod(fn):
raise Exception("not a decoratable function")
# Python 3.14 defer creating __annotations__ until its used.
# We do not want to create __annotations__ now.
annofunc = getattr(fn, "__annotate__", None)
if annofunc is not None:
fn.__annotate__ = None # type: ignore[union-attr]
try:
spec = compat.inspect_getfullargspec(fn)
finally:
fn.__annotate__ = annofunc # type: ignore[union-attr]
else:
spec = compat.inspect_getfullargspec(fn)
spec = compat.inspect_getfullargspec(fn)
env: Dict[str, Any] = {}
# Do not generate code for annotations.
# update_wrapper() copies the annotation from fn to decorated.
# We use dummy defaults for code generation to avoid having
# copy of large globals for compiling.
# We copy __defaults__ and __kwdefaults__ from fn to decorated.
empty_defaults = (None,) * len(spec.defaults or ())
empty_kwdefaults = dict.fromkeys(spec.kwonlydefaults or ())
spec = spec._replace(
annotations={},
defaults=empty_defaults,
kwonlydefaults=empty_kwdefaults,
)
spec = _update_argspec_defaults_into_env(spec, env)
names = (
tuple(cast("Tuple[str, ...]", spec[0]))
@@ -396,21 +297,41 @@ def decorator(target: Callable[..., Any]) -> Callable[[_Fn], _Fn]:
% metadata
)
env: Dict[str, Any] = {
targ_name: target,
fn_name: fn,
"__name__": fn.__module__,
}
mod = sys.modules[fn.__module__]
env.update(vars(mod))
env.update({targ_name: target, fn_name: fn, "__name__": fn.__module__})
decorated = cast(
types.FunctionType,
_exec_code_in_env(code, env, fn.__name__),
)
decorated.__defaults__ = fn.__defaults__
decorated.__kwdefaults__ = fn.__kwdefaults__ # type: ignore
return update_wrapper(decorated, fn) # type: ignore[return-value]
decorated.__defaults__ = getattr(fn, "__func__", fn).__defaults__
return update_wrapper(decorate, target) # type: ignore[return-value]
decorated.__wrapped__ = fn # type: ignore
return cast(_Fn, update_wrapper(decorated, fn))
return update_wrapper(decorate, target)
def _update_argspec_defaults_into_env(spec, env):
"""given a FullArgSpec, convert defaults to be symbol names in an env."""
if spec.defaults:
new_defaults = []
i = 0
for arg in spec.defaults:
if type(arg).__module__ not in ("builtins", "__builtin__"):
name = "x%d" % i
env[name] = arg
new_defaults.append(name)
i += 1
else:
new_defaults.append(arg)
elem = list(spec)
elem[3] = tuple(new_defaults)
return compat.FullArgSpec(*elem)
else:
return spec
def _exec_code_in_env(
@@ -463,9 +384,6 @@ class PluginLoader:
self.impls[name] = load
def deregister(self, name: str) -> None:
del self.impls[name]
def _inspect_func_args(fn):
try:
@@ -493,13 +411,15 @@ def get_cls_kwargs(
*,
_set: Optional[Set[str]] = None,
raiseerr: Literal[True] = ...,
) -> Set[str]: ...
) -> Set[str]:
...
@overload
def get_cls_kwargs(
cls: type, *, _set: Optional[Set[str]] = None, raiseerr: bool = False
) -> Optional[Set[str]]: ...
) -> Optional[Set[str]]:
...
def get_cls_kwargs(
@@ -743,9 +663,7 @@ def format_argspec_init(method, grouped=True):
"""format_argspec_plus with considerations for typical __init__ methods
Wraps format_argspec_plus with error handling strategies for typical
__init__ cases:
.. sourcecode:: text
__init__ cases::
object.__init__ -> (self)
other unreflectable (usually C) -> (self, *args, **kwargs)
@@ -800,9 +718,7 @@ def create_proxy_methods(
def getargspec_init(method):
"""inspect.getargspec with considerations for typical __init__ methods
Wraps inspect.getargspec with error handling for typical __init__ cases:
.. sourcecode:: text
Wraps inspect.getargspec with error handling for typical __init__ cases::
object.__init__ -> (self)
other unreflectable (usually C) -> (self, *args, **kwargs)
@@ -1176,19 +1092,23 @@ class generic_fn_descriptor(Generic[_T_co]):
self.__name__ = fget.__name__
@overload
def __get__(self: _GFD, obj: None, cls: Any) -> _GFD: ...
def __get__(self: _GFD, obj: None, cls: Any) -> _GFD:
...
@overload
def __get__(self, obj: object, cls: Any) -> _T_co: ...
def __get__(self, obj: object, cls: Any) -> _T_co:
...
def __get__(self: _GFD, obj: Any, cls: Any) -> Union[_GFD, _T_co]:
raise NotImplementedError()
if TYPE_CHECKING:
def __set__(self, instance: Any, value: Any) -> None: ...
def __set__(self, instance: Any, value: Any) -> None:
...
def __delete__(self, instance: Any) -> None: ...
def __delete__(self, instance: Any) -> None:
...
def _reset(self, obj: Any) -> None:
raise NotImplementedError()
@@ -1327,10 +1247,12 @@ class HasMemoized:
self.__name__ = fget.__name__
@overload
def __get__(self: _MA, obj: None, cls: Any) -> _MA: ...
def __get__(self: _MA, obj: None, cls: Any) -> _MA:
...
@overload
def __get__(self, obj: Any, cls: Any) -> _T: ...
def __get__(self, obj: Any, cls: Any) -> _T:
...
def __get__(self, obj, cls):
if obj is None:
@@ -1676,9 +1598,9 @@ class hybridmethod(Generic[_T]):
class symbol(int):
"""A constant symbol.
>>> symbol("foo") is symbol("foo")
>>> symbol('foo') is symbol('foo')
True
>>> symbol("foo")
>>> symbol('foo')
<symbol 'foo>
A slight refinement of the MAGICCOOKIE=object() pattern. The primary
@@ -1744,8 +1666,6 @@ class _IntFlagMeta(type):
items: List[symbol]
cls._items = items = []
for k, v in dict_.items():
if re.match(r"^__.*__$", k):
continue
if isinstance(v, int):
sym = symbol(k, canonical=v)
elif not k.startswith("_"):
@@ -2039,15 +1959,12 @@ NoneType = type(None)
def attrsetter(attrname):
code = "def set(obj, value): obj.%s = value" % attrname
code = "def set(obj, value):" " obj.%s = value" % attrname
env = locals().copy()
exec(code, env)
return env["set"]
_dunders = re.compile("^__.+__$")
class TypingOnly:
"""A mixin class that marks a class as 'typing only', meaning it has
absolutely no methods, attributes, or runtime functionality whatsoever.
@@ -2058,9 +1975,15 @@ class TypingOnly:
def __init_subclass__(cls) -> None:
if TypingOnly in cls.__bases__:
remaining = {
name for name in cls.__dict__ if not _dunders.match(name)
}
remaining = set(cls.__dict__).difference(
{
"__module__",
"__doc__",
"__slots__",
"__orig_bases__",
"__annotations__",
}
)
if remaining:
raise AssertionError(
f"Class {cls} directly inherits TypingOnly but has "
@@ -2293,11 +2216,3 @@ def has_compiled_ext(raise_=False):
)
else:
return False
class _Missing(enum.Enum):
Missing = enum.auto()
Missing = _Missing.Missing
MissingOr = Union[_T, Literal[_Missing.Missing]]