Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/attr/_compat.py: 76%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

38 statements  

1# SPDX-License-Identifier: MIT 

2 

3import inspect 

4import platform 

5import sys 

6import threading 

7 

8from collections.abc import Mapping, Sequence # noqa: F401 

9from typing import _GenericAlias 

10 

11 

12PYPY = platform.python_implementation() == "PyPy" 

13PY_3_8_PLUS = sys.version_info[:2] >= (3, 8) 

14PY_3_9_PLUS = sys.version_info[:2] >= (3, 9) 

15PY310 = sys.version_info[:2] >= (3, 10) 

16PY_3_12_PLUS = sys.version_info[:2] >= (3, 12) 

17 

18 

19if sys.version_info < (3, 8): 

20 try: 

21 from typing_extensions import Protocol 

22 except ImportError: # pragma: no cover 

23 Protocol = object 

24else: 

25 from typing import Protocol # noqa: F401 

26 

27 

28class _AnnotationExtractor: 

29 """ 

30 Extract type annotations from a callable, returning None whenever there 

31 is none. 

32 """ 

33 

34 __slots__ = ["sig"] 

35 

36 def __init__(self, callable): 

37 try: 

38 self.sig = inspect.signature(callable) 

39 except (ValueError, TypeError): # inspect failed 

40 self.sig = None 

41 

42 def get_first_param_type(self): 

43 """ 

44 Return the type annotation of the first argument if it's not empty. 

45 """ 

46 if not self.sig: 

47 return None 

48 

49 params = list(self.sig.parameters.values()) 

50 if params and params[0].annotation is not inspect.Parameter.empty: 

51 return params[0].annotation 

52 

53 return None 

54 

55 def get_return_type(self): 

56 """ 

57 Return the return type if it's not empty. 

58 """ 

59 if ( 

60 self.sig 

61 and self.sig.return_annotation is not inspect.Signature.empty 

62 ): 

63 return self.sig.return_annotation 

64 

65 return None 

66 

67 

68# Thread-local global to track attrs instances which are already being repr'd. 

69# This is needed because there is no other (thread-safe) way to pass info 

70# about the instances that are already being repr'd through the call stack 

71# in order to ensure we don't perform infinite recursion. 

72# 

73# For instance, if an instance contains a dict which contains that instance, 

74# we need to know that we're already repr'ing the outside instance from within 

75# the dict's repr() call. 

76# 

77# This lives here rather than in _make.py so that the functions in _make.py 

78# don't have a direct reference to the thread-local in their globals dict. 

79# If they have such a reference, it breaks cloudpickle. 

80repr_context = threading.local() 

81 

82 

83def get_generic_base(cl): 

84 """If this is a generic class (A[str]), return the generic base for it.""" 

85 if cl.__class__ is _GenericAlias: 

86 return cl.__origin__ 

87 return None