comparison env/lib/python3.9/site-packages/boltons/typeutils.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 # -*- coding: utf-8 -*-
2 """Python's built-in :mod:`functools` module builds several useful
3 utilities on top of Python's first-class function support.
4 ``typeutils`` attempts to do the same for metaprogramming with types
5 and instances.
6 """
7
8 from collections import deque
9
10 _issubclass = issubclass
11
12
13 def make_sentinel(name='_MISSING', var_name=None):
14 """Creates and returns a new **instance** of a new class, suitable for
15 usage as a "sentinel", a kind of singleton often used to indicate
16 a value is missing when ``None`` is a valid input.
17
18 Args:
19 name (str): Name of the Sentinel
20 var_name (str): Set this name to the name of the variable in
21 its respective module enable pickleability.
22
23 >>> make_sentinel(var_name='_MISSING')
24 _MISSING
25
26 The most common use cases here in boltons are as default values
27 for optional function arguments, partly because of its
28 less-confusing appearance in automatically generated
29 documentation. Sentinels also function well as placeholders in queues
30 and linked lists.
31
32 .. note::
33
34 By design, additional calls to ``make_sentinel`` with the same
35 values will not produce equivalent objects.
36
37 >>> make_sentinel('TEST') == make_sentinel('TEST')
38 False
39 >>> type(make_sentinel('TEST')) == type(make_sentinel('TEST'))
40 False
41
42 """
43 class Sentinel(object):
44 def __init__(self):
45 self.name = name
46 self.var_name = var_name
47
48 def __repr__(self):
49 if self.var_name:
50 return self.var_name
51 return '%s(%r)' % (self.__class__.__name__, self.name)
52 if var_name:
53 def __reduce__(self):
54 return self.var_name
55
56 def __nonzero__(self):
57 return False
58
59 __bool__ = __nonzero__
60
61 return Sentinel()
62
63
64 def issubclass(subclass, baseclass):
65 """Just like the built-in :func:`issubclass`, this function checks
66 whether *subclass* is inherited from *baseclass*. Unlike the
67 built-in function, this ``issubclass`` will simply return
68 ``False`` if either argument is not suitable (e.g., if *subclass*
69 is not an instance of :class:`type`), instead of raising
70 :exc:`TypeError`.
71
72 Args:
73 subclass (type): The target class to check.
74 baseclass (type): The base class *subclass* will be checked against.
75
76 >>> class MyObject(object): pass
77 ...
78 >>> issubclass(MyObject, object) # always a fun fact
79 True
80 >>> issubclass('hi', 'friend')
81 False
82 """
83 try:
84 return _issubclass(subclass, baseclass)
85 except TypeError:
86 return False
87
88
89 def get_all_subclasses(cls):
90 """Recursively finds and returns a :class:`list` of all types
91 inherited from *cls*.
92
93 >>> class A(object):
94 ... pass
95 ...
96 >>> class B(A):
97 ... pass
98 ...
99 >>> class C(B):
100 ... pass
101 ...
102 >>> class D(A):
103 ... pass
104 ...
105 >>> [t.__name__ for t in get_all_subclasses(A)]
106 ['B', 'D', 'C']
107 >>> [t.__name__ for t in get_all_subclasses(B)]
108 ['C']
109
110 """
111 try:
112 to_check = deque(cls.__subclasses__())
113 except (AttributeError, TypeError):
114 raise TypeError('expected type object, not %r' % cls)
115 seen, ret = set(), []
116 while to_check:
117 cur = to_check.popleft()
118 if cur in seen:
119 continue
120 ret.append(cur)
121 seen.add(cur)
122 to_check.extend(cur.__subclasses__())
123 return ret
124
125
126 class classproperty(object):
127 """Much like a :class:`property`, but the wrapped get function is a
128 class method. For simplicity, only read-only properties are
129 implemented.
130 """
131
132 def __init__(self, fn):
133 self.fn = fn
134
135 def __get__(self, instance, cls):
136 return self.fn(cls)