添加注册登录功能
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
from collections import defaultdict as defaultdict
|
||||
from functools import partial as partial
|
||||
from functools import update_wrapper as update_wrapper
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from . import preloaded as preloaded
|
||||
from ._collections import coerce_generator_arg as coerce_generator_arg
|
||||
@@ -66,6 +65,7 @@ from .compat import py310 as py310
|
||||
from .compat import py311 as py311
|
||||
from .compat import py312 as py312
|
||||
from .compat import py313 as py313
|
||||
from .compat import py314 as py314
|
||||
from .compat import py38 as py38
|
||||
from .compat import py39 as py39
|
||||
from .compat import pypy as pypy
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -454,7 +454,9 @@ def to_column_set(x: Any) -> Set[Any]:
|
||||
return x
|
||||
|
||||
|
||||
def update_copy(d, _new=None, **kw):
|
||||
def update_copy(
|
||||
d: Dict[Any, Any], _new: Optional[Dict[Any, Any]] = None, **kw: Any
|
||||
) -> Dict[Any, Any]:
|
||||
"""Copy the given dict and update with the given values."""
|
||||
|
||||
d = d.copy()
|
||||
|
||||
@@ -104,7 +104,7 @@ class immutabledict(ImmutableDictBase[_KT, _VT]):
|
||||
|
||||
new = ImmutableDictBase.__new__(self.__class__)
|
||||
dict.__init__(new, self)
|
||||
dict.update(new, __d) # type: ignore
|
||||
dict.update(new, __d)
|
||||
return new
|
||||
|
||||
def _union_w_kw(
|
||||
@@ -117,8 +117,8 @@ class immutabledict(ImmutableDictBase[_KT, _VT]):
|
||||
new = ImmutableDictBase.__new__(self.__class__)
|
||||
dict.__init__(new, self)
|
||||
if __d:
|
||||
dict.update(new, __d) # type: ignore
|
||||
dict.update(new, kw) # type: ignore
|
||||
dict.update(new, __d)
|
||||
dict.update(new, kw)
|
||||
return new
|
||||
|
||||
def merge_with(
|
||||
@@ -130,7 +130,7 @@ class immutabledict(ImmutableDictBase[_KT, _VT]):
|
||||
if new is None:
|
||||
new = ImmutableDictBase.__new__(self.__class__)
|
||||
dict.__init__(new, self)
|
||||
dict.update(new, d) # type: ignore
|
||||
dict.update(new, d)
|
||||
if new is None:
|
||||
return self
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ from typing import Type
|
||||
from typing import TypeVar
|
||||
|
||||
|
||||
py314b1 = sys.version_info >= (3, 14, 0, "beta", 1)
|
||||
py314 = sys.version_info >= (3, 14)
|
||||
py313 = sys.version_info >= (3, 13)
|
||||
py312 = sys.version_info >= (3, 12)
|
||||
py311 = sys.version_info >= (3, 11)
|
||||
|
||||
@@ -60,7 +60,85 @@ _HP = TypeVar("_HP", bound="hybridproperty[Any]")
|
||||
_HM = TypeVar("_HM", bound="hybridmethod[Any]")
|
||||
|
||||
|
||||
if compat.py310:
|
||||
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:
|
||||
|
||||
def get_annotations(obj: Any) -> Mapping[str, Any]:
|
||||
return inspect.get_annotations(obj)
|
||||
@@ -250,10 +328,30 @@ def decorator(target: Callable[..., Any]) -> Callable[[_Fn], _Fn]:
|
||||
if not inspect.isfunction(fn) and not inspect.ismethod(fn):
|
||||
raise Exception("not a decoratable function")
|
||||
|
||||
spec = compat.inspect_getfullargspec(fn)
|
||||
env: Dict[str, Any] = {}
|
||||
# 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 = _update_argspec_defaults_into_env(spec, env)
|
||||
# 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,
|
||||
)
|
||||
|
||||
names = (
|
||||
tuple(cast("Tuple[str, ...]", spec[0]))
|
||||
@@ -298,43 +396,23 @@ def decorator(target: Callable[..., Any]) -> Callable[[_Fn], _Fn]:
|
||||
% metadata
|
||||
)
|
||||
|
||||
mod = sys.modules[fn.__module__]
|
||||
env.update(vars(mod))
|
||||
env.update({targ_name: target, fn_name: fn, "__name__": fn.__module__})
|
||||
env: Dict[str, Any] = {
|
||||
targ_name: target,
|
||||
fn_name: fn,
|
||||
"__name__": fn.__module__,
|
||||
}
|
||||
|
||||
decorated = cast(
|
||||
types.FunctionType,
|
||||
_exec_code_in_env(code, env, fn.__name__),
|
||||
)
|
||||
decorated.__defaults__ = getattr(fn, "__func__", fn).__defaults__
|
||||
|
||||
decorated.__wrapped__ = fn # type: ignore[attr-defined]
|
||||
decorated.__defaults__ = fn.__defaults__
|
||||
decorated.__kwdefaults__ = fn.__kwdefaults__ # type: ignore
|
||||
return update_wrapper(decorated, fn) # type: ignore[return-value]
|
||||
|
||||
return update_wrapper(decorate, target) # type: ignore[return-value]
|
||||
|
||||
|
||||
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(
|
||||
code: Union[str, types.CodeType], env: Dict[str, Any], fn_name: str
|
||||
) -> Callable[..., Any]:
|
||||
@@ -385,6 +463,9 @@ class PluginLoader:
|
||||
|
||||
self.impls[name] = load
|
||||
|
||||
def deregister(self, name: str) -> None:
|
||||
del self.impls[name]
|
||||
|
||||
|
||||
def _inspect_func_args(fn):
|
||||
try:
|
||||
|
||||
@@ -112,7 +112,7 @@ def find_cycles(
|
||||
todo.remove(node)
|
||||
break
|
||||
else:
|
||||
node = stack.pop()
|
||||
stack.pop()
|
||||
return output
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ import sys
|
||||
import typing
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import cast
|
||||
from typing import Dict
|
||||
from typing import ForwardRef
|
||||
from typing import Generic
|
||||
@@ -33,6 +32,8 @@ from typing import TYPE_CHECKING
|
||||
from typing import TypeVar
|
||||
from typing import Union
|
||||
|
||||
import typing_extensions
|
||||
|
||||
from . import compat
|
||||
|
||||
if True: # zimports removes the tailing comments
|
||||
@@ -56,6 +57,7 @@ if True: # zimports removes the tailing comments
|
||||
from typing_extensions import Self as Self # 3.11
|
||||
from typing_extensions import TypeAliasType as TypeAliasType # 3.12
|
||||
from typing_extensions import Never as Never # 3.11
|
||||
from typing_extensions import LiteralString as LiteralString # 3.11
|
||||
|
||||
_T = TypeVar("_T", bound=Any)
|
||||
_KT = TypeVar("_KT")
|
||||
@@ -64,14 +66,6 @@ _KT_contra = TypeVar("_KT_contra", contravariant=True)
|
||||
_VT = TypeVar("_VT")
|
||||
_VT_co = TypeVar("_VT_co", covariant=True)
|
||||
|
||||
if compat.py38:
|
||||
# typing_extensions.Literal is different from typing.Literal until
|
||||
# Python 3.10.1
|
||||
LITERAL_TYPES = frozenset([typing.Literal, Literal])
|
||||
else:
|
||||
LITERAL_TYPES = frozenset([Literal])
|
||||
|
||||
|
||||
if compat.py310:
|
||||
# why they took until py310 to put this in stdlib is beyond me,
|
||||
# I've been wanting it since py27
|
||||
@@ -79,7 +73,9 @@ if compat.py310:
|
||||
else:
|
||||
NoneType = type(None) # type: ignore
|
||||
|
||||
NoneFwd = ForwardRef("None")
|
||||
|
||||
def is_fwd_none(typ: Any) -> bool:
|
||||
return isinstance(typ, ForwardRef) and typ.__forward_arg__ == "None"
|
||||
|
||||
|
||||
_AnnotationScanType = Union[
|
||||
@@ -330,7 +326,7 @@ def resolve_name_to_real_class_name(name: str, module_name: str) -> str:
|
||||
|
||||
|
||||
def is_pep593(type_: Optional[Any]) -> bool:
|
||||
return type_ is not None and get_origin(type_) is Annotated
|
||||
return type_ is not None and get_origin(type_) in _type_tuples.Annotated
|
||||
|
||||
|
||||
def is_non_string_iterable(obj: Any) -> TypeGuard[Iterable[Any]]:
|
||||
@@ -340,7 +336,7 @@ def is_non_string_iterable(obj: Any) -> TypeGuard[Iterable[Any]]:
|
||||
|
||||
|
||||
def is_literal(type_: Any) -> bool:
|
||||
return get_origin(type_) in LITERAL_TYPES
|
||||
return get_origin(type_) in _type_tuples.Literal
|
||||
|
||||
|
||||
def is_newtype(type_: Optional[_AnnotationScanType]) -> TypeGuard[NewType]:
|
||||
@@ -348,7 +344,7 @@ def is_newtype(type_: Optional[_AnnotationScanType]) -> TypeGuard[NewType]:
|
||||
|
||||
# doesn't work in 3.8, 3.7 as it passes a closure, not an
|
||||
# object instance
|
||||
# return isinstance(type_, NewType)
|
||||
# isinstance(type, type_instances.NewType)
|
||||
|
||||
|
||||
def is_generic(type_: _AnnotationScanType) -> TypeGuard[GenericProtocol[Any]]:
|
||||
@@ -356,7 +352,13 @@ def is_generic(type_: _AnnotationScanType) -> TypeGuard[GenericProtocol[Any]]:
|
||||
|
||||
|
||||
def is_pep695(type_: _AnnotationScanType) -> TypeGuard[TypeAliasType]:
|
||||
return isinstance(type_, TypeAliasType)
|
||||
# NOTE: a generic TAT does not instance check as TypeAliasType outside of
|
||||
# python 3.10. For sqlalchemy use cases it's fine to consider it a TAT
|
||||
# though.
|
||||
# NOTE: things seems to work also without this additional check
|
||||
if is_generic(type_):
|
||||
return is_pep695(type_.__origin__)
|
||||
return isinstance(type_, _type_instances.TypeAliasType)
|
||||
|
||||
|
||||
def flatten_newtype(type_: NewType) -> Type[Any]:
|
||||
@@ -375,15 +377,15 @@ def pep695_values(type_: _AnnotationScanType) -> Set[Any]:
|
||||
"""
|
||||
_seen = set()
|
||||
|
||||
def recursive_value(type_):
|
||||
if type_ in _seen:
|
||||
def recursive_value(inner_type):
|
||||
if inner_type in _seen:
|
||||
# recursion are not supported (at least it's flagged as
|
||||
# an error by pyright). Just avoid infinite loop
|
||||
return type_
|
||||
_seen.add(type_)
|
||||
if not is_pep695(type_):
|
||||
return type_
|
||||
value = type_.__value__
|
||||
return inner_type
|
||||
_seen.add(inner_type)
|
||||
if not is_pep695(inner_type):
|
||||
return inner_type
|
||||
value = inner_type.__value__
|
||||
if not is_union(value):
|
||||
return value
|
||||
return [recursive_value(t) for t in value.__args__]
|
||||
@@ -397,7 +399,7 @@ def pep695_values(type_: _AnnotationScanType) -> Set[Any]:
|
||||
if isinstance(t, list):
|
||||
stack.extend(t)
|
||||
else:
|
||||
types.add(None if t in {NoneType, NoneFwd} else t)
|
||||
types.add(None if t is NoneType or is_fwd_none(t) else t)
|
||||
return types
|
||||
else:
|
||||
return {res}
|
||||
@@ -410,7 +412,7 @@ def is_fwd_ref(
|
||||
) -> TypeGuard[ForwardRef]:
|
||||
if check_for_plain_string and isinstance(type_, str):
|
||||
return True
|
||||
elif isinstance(type_, ForwardRef):
|
||||
elif isinstance(type_, _type_instances.ForwardRef):
|
||||
return True
|
||||
elif check_generic and is_generic(type_):
|
||||
return any(
|
||||
@@ -469,8 +471,7 @@ def de_optionalize_union_types(
|
||||
|
||||
typ.discard(None) # type: ignore
|
||||
|
||||
typ.discard(NoneType)
|
||||
typ.discard(NoneFwd)
|
||||
typ = {t for t in typ if t is not NoneType and not is_fwd_none(t)}
|
||||
|
||||
return make_union_type(*typ)
|
||||
|
||||
@@ -546,7 +547,8 @@ def _de_optionalize_fwd_ref_union_types(
|
||||
|
||||
def make_union_type(*types: _AnnotationScanType) -> Type[Any]:
|
||||
"""Make a Union type."""
|
||||
return Union.__getitem__(types) # type: ignore
|
||||
|
||||
return Union[types] # type: ignore
|
||||
|
||||
|
||||
def includes_none(type_: Any) -> bool:
|
||||
@@ -571,7 +573,22 @@ def includes_none(type_: Any) -> bool:
|
||||
return any(includes_none(t) for t in pep695_values(type_))
|
||||
if is_newtype(type_):
|
||||
return includes_none(type_.__supertype__)
|
||||
return type_ in (NoneFwd, NoneType, None)
|
||||
try:
|
||||
return type_ in (NoneType, None) or is_fwd_none(type_)
|
||||
except TypeError:
|
||||
# if type_ is Column, mapped_column(), etc. the use of "in"
|
||||
# resolves to ``__eq__()`` which then gives us an expression object
|
||||
# that can't resolve to boolean. just catch it all via exception
|
||||
return False
|
||||
|
||||
|
||||
def is_a_type(type_: Any) -> bool:
|
||||
return (
|
||||
isinstance(type_, type)
|
||||
or hasattr(type_, "__origin__")
|
||||
or type_.__module__ in ("typing", "typing_extensions")
|
||||
or type(type_).__mro__[0].__module__ in ("typing", "typing_extensions")
|
||||
)
|
||||
|
||||
|
||||
def is_union(type_: Any) -> TypeGuard[ArgsTypeProtocol]:
|
||||
@@ -687,3 +704,30 @@ class CallableReference(Generic[_FN]):
|
||||
def __set__(self, instance: Any, value: _FN) -> None: ...
|
||||
|
||||
def __delete__(self, instance: Any) -> None: ...
|
||||
|
||||
|
||||
class _TypingInstances:
|
||||
def __getattr__(self, key: str) -> tuple[type, ...]:
|
||||
types = tuple(
|
||||
{
|
||||
t
|
||||
for t in [
|
||||
getattr(typing, key, None),
|
||||
getattr(typing_extensions, key, None),
|
||||
]
|
||||
if t is not None
|
||||
}
|
||||
)
|
||||
if not types:
|
||||
raise AttributeError(key)
|
||||
self.__dict__[key] = types
|
||||
return types
|
||||
|
||||
|
||||
_type_tuples = _TypingInstances()
|
||||
if TYPE_CHECKING:
|
||||
_type_instances = typing_extensions
|
||||
else:
|
||||
_type_instances = _type_tuples
|
||||
|
||||
LITERAL_TYPES = _type_tuples.Literal
|
||||
|
||||
Reference in New Issue
Block a user