Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

95 lignes
2.6 KiB

  1. # SPDX-License-Identifier: MIT
  2. import inspect
  3. import platform
  4. import sys
  5. import threading
  6. from collections.abc import Mapping, Sequence # noqa: F401
  7. from typing import _GenericAlias
  8. PYPY = platform.python_implementation() == "PyPy"
  9. PY_3_9_PLUS = sys.version_info[:2] >= (3, 9)
  10. PY_3_10_PLUS = sys.version_info[:2] >= (3, 10)
  11. PY_3_11_PLUS = sys.version_info[:2] >= (3, 11)
  12. PY_3_12_PLUS = sys.version_info[:2] >= (3, 12)
  13. PY_3_13_PLUS = sys.version_info[:2] >= (3, 13)
  14. PY_3_14_PLUS = sys.version_info[:2] >= (3, 14)
  15. if PY_3_14_PLUS: # pragma: no cover
  16. import annotationlib
  17. _get_annotations = annotationlib.get_annotations
  18. else:
  19. def _get_annotations(cls):
  20. """
  21. Get annotations for *cls*.
  22. """
  23. return cls.__dict__.get("__annotations__", {})
  24. class _AnnotationExtractor:
  25. """
  26. Extract type annotations from a callable, returning None whenever there
  27. is none.
  28. """
  29. __slots__ = ["sig"]
  30. def __init__(self, callable):
  31. try:
  32. self.sig = inspect.signature(callable)
  33. except (ValueError, TypeError): # inspect failed
  34. self.sig = None
  35. def get_first_param_type(self):
  36. """
  37. Return the type annotation of the first argument if it's not empty.
  38. """
  39. if not self.sig:
  40. return None
  41. params = list(self.sig.parameters.values())
  42. if params and params[0].annotation is not inspect.Parameter.empty:
  43. return params[0].annotation
  44. return None
  45. def get_return_type(self):
  46. """
  47. Return the return type if it's not empty.
  48. """
  49. if (
  50. self.sig
  51. and self.sig.return_annotation is not inspect.Signature.empty
  52. ):
  53. return self.sig.return_annotation
  54. return None
  55. # Thread-local global to track attrs instances which are already being repr'd.
  56. # This is needed because there is no other (thread-safe) way to pass info
  57. # about the instances that are already being repr'd through the call stack
  58. # in order to ensure we don't perform infinite recursion.
  59. #
  60. # For instance, if an instance contains a dict which contains that instance,
  61. # we need to know that we're already repr'ing the outside instance from within
  62. # the dict's repr() call.
  63. #
  64. # This lives here rather than in _make.py so that the functions in _make.py
  65. # don't have a direct reference to the thread-local in their globals dict.
  66. # If they have such a reference, it breaks cloudpickle.
  67. repr_context = threading.local()
  68. def get_generic_base(cl):
  69. """If this is a generic class (A[str]), return the generic base for it."""
  70. if cl.__class__ is _GenericAlias:
  71. return cl.__origin__
  72. return None