Mercurial > repos > shellac > sam_consensus_v3
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) |