omlish 0.0.0.dev1__py3-none-any.whl → 0.0.0.dev3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of omlish might be problematic. Click here for more details.

Files changed (147) hide show
  1. omlish/__about__.py +2 -3
  2. omlish/argparse.py +8 -8
  3. omlish/asyncs/__init__.py +2 -2
  4. omlish/asyncs/anyio.py +64 -1
  5. omlish/asyncs/asyncs.py +1 -3
  6. omlish/asyncs/futures.py +16 -15
  7. omlish/c3.py +5 -5
  8. omlish/check.py +8 -8
  9. omlish/collections/__init__.py +98 -63
  10. omlish/collections/_abc.py +2 -0
  11. omlish/collections/_io_abc.py +4 -2
  12. omlish/collections/cache/__init__.py +1 -1
  13. omlish/collections/cache/descriptor.py +12 -12
  14. omlish/collections/cache/impl.py +27 -20
  15. omlish/collections/cache/types.py +1 -1
  16. omlish/collections/coerce.py +44 -44
  17. omlish/collections/frozen.py +9 -9
  18. omlish/collections/identity.py +4 -5
  19. omlish/collections/mappings.py +5 -5
  20. omlish/collections/ordered.py +8 -8
  21. omlish/collections/skiplist.py +7 -7
  22. omlish/collections/sorted.py +4 -4
  23. omlish/collections/treap.py +42 -17
  24. omlish/collections/treapmap.py +59 -7
  25. omlish/collections/unmodifiable.py +25 -24
  26. omlish/collections/utils.py +1 -1
  27. omlish/configs/flattening.py +8 -7
  28. omlish/configs/props.py +3 -3
  29. omlish/dataclasses/__init__.py +1 -1
  30. omlish/dataclasses/impl/__init__.py +18 -0
  31. omlish/dataclasses/impl/api.py +15 -24
  32. omlish/dataclasses/impl/as_.py +4 -4
  33. omlish/dataclasses/impl/exceptions.py +1 -1
  34. omlish/dataclasses/impl/fields.py +8 -8
  35. omlish/dataclasses/impl/frozen.py +2 -2
  36. omlish/dataclasses/impl/init.py +6 -6
  37. omlish/dataclasses/impl/internals.py +16 -1
  38. omlish/dataclasses/impl/main.py +4 -4
  39. omlish/dataclasses/impl/metaclass.py +2 -2
  40. omlish/dataclasses/impl/metadata.py +1 -1
  41. omlish/dataclasses/impl/order.py +2 -2
  42. omlish/dataclasses/impl/params.py +4 -38
  43. omlish/dataclasses/impl/reflect.py +1 -7
  44. omlish/dataclasses/impl/replace.py +1 -1
  45. omlish/dataclasses/impl/repr.py +24 -6
  46. omlish/dataclasses/impl/simple.py +2 -2
  47. omlish/dataclasses/impl/slots.py +2 -2
  48. omlish/dataclasses/impl/utils.py +7 -7
  49. omlish/defs.py +13 -17
  50. omlish/diag/procfs.py +334 -0
  51. omlish/diag/ps.py +47 -0
  52. omlish/{replserver → diag/replserver}/console.py +26 -28
  53. omlish/{replserver → diag/replserver}/server.py +12 -12
  54. omlish/dispatch/dispatch.py +14 -16
  55. omlish/dispatch/functions.py +1 -1
  56. omlish/dispatch/methods.py +6 -7
  57. omlish/docker.py +8 -6
  58. omlish/dynamic.py +13 -13
  59. omlish/fnpairs.py +311 -0
  60. omlish/graphs/dot/items.py +1 -1
  61. omlish/graphs/trees.py +25 -31
  62. omlish/inject/__init__.py +7 -7
  63. omlish/inject/elements.py +2 -2
  64. omlish/inject/exceptions.py +8 -8
  65. omlish/inject/impl/elements.py +4 -4
  66. omlish/inject/impl/injector.py +6 -6
  67. omlish/inject/impl/inspect.py +3 -3
  68. omlish/inject/impl/scopes.py +9 -9
  69. omlish/inject/injector.py +1 -1
  70. omlish/inject/providers.py +2 -2
  71. omlish/inject/proxy.py +5 -5
  72. omlish/iterators.py +62 -26
  73. omlish/json.py +7 -6
  74. omlish/lang/__init__.py +172 -112
  75. omlish/lang/cached.py +15 -10
  76. omlish/lang/classes/__init__.py +35 -24
  77. omlish/lang/classes/abstract.py +3 -3
  78. omlish/lang/classes/restrict.py +14 -14
  79. omlish/lang/classes/simple.py +2 -2
  80. omlish/lang/classes/virtual.py +5 -5
  81. omlish/lang/clsdct.py +2 -2
  82. omlish/lang/cmp.py +2 -2
  83. omlish/lang/contextmanagers.py +31 -25
  84. omlish/lang/datetimes.py +1 -1
  85. omlish/lang/descriptors.py +51 -6
  86. omlish/lang/exceptions.py +2 -0
  87. omlish/lang/functions.py +101 -35
  88. omlish/lang/imports.py +25 -30
  89. omlish/lang/iterables.py +2 -2
  90. omlish/lang/maybes.py +2 -1
  91. omlish/lang/objects.py +17 -11
  92. omlish/lang/resolving.py +1 -1
  93. omlish/lang/strings.py +1 -1
  94. omlish/lang/timeouts.py +53 -0
  95. omlish/lang/typing.py +5 -5
  96. omlish/libc.py +15 -11
  97. omlish/logs/_abc.py +5 -1
  98. omlish/logs/filters.py +2 -0
  99. omlish/logs/formatters.py +6 -2
  100. omlish/logs/utils.py +1 -1
  101. omlish/marshal/base.py +9 -9
  102. omlish/marshal/dataclasses.py +2 -2
  103. omlish/marshal/enums.py +2 -2
  104. omlish/marshal/exceptions.py +1 -1
  105. omlish/marshal/factories.py +10 -10
  106. omlish/marshal/global_.py +10 -4
  107. omlish/marshal/iterables.py +2 -2
  108. omlish/marshal/mappings.py +2 -2
  109. omlish/marshal/objects.py +1 -2
  110. omlish/marshal/optionals.py +4 -4
  111. omlish/marshal/polymorphism.py +4 -4
  112. omlish/marshal/registries.py +3 -3
  113. omlish/marshal/standard.py +6 -6
  114. omlish/marshal/utils.py +3 -3
  115. omlish/marshal/values.py +1 -1
  116. omlish/math.py +9 -9
  117. omlish/os.py +13 -4
  118. omlish/reflect.py +5 -15
  119. omlish/sql/__init__.py +0 -0
  120. omlish/sql/_abc.py +65 -0
  121. omlish/sql/dbs.py +90 -0
  122. omlish/stats.py +7 -8
  123. omlish/term.py +1 -1
  124. omlish/testing/pydevd.py +30 -12
  125. omlish/testing/pytest/inject/__init__.py +7 -0
  126. omlish/testing/pytest/inject/harness.py +24 -2
  127. omlish/testing/pytest/plugins/__init__.py +1 -1
  128. omlish/testing/pytest/plugins/pydevd.py +12 -0
  129. omlish/testing/pytest/plugins/switches.py +3 -3
  130. omlish/testing/testing.py +5 -5
  131. omlish/text/delimit.py +3 -6
  132. omlish/text/parts.py +3 -3
  133. omlish-0.0.0.dev3.dist-info/METADATA +31 -0
  134. omlish-0.0.0.dev3.dist-info/RECORD +191 -0
  135. {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev3.dist-info}/WHEEL +1 -1
  136. omlish/lang/classes/test/test_abstract.py +0 -89
  137. omlish/lang/classes/test/test_restrict.py +0 -71
  138. omlish/lang/classes/test/test_simple.py +0 -58
  139. omlish/lang/classes/test/test_virtual.py +0 -72
  140. omlish/testing/pytest/plugins/pycharm.py +0 -54
  141. omlish-0.0.0.dev1.dist-info/METADATA +0 -17
  142. omlish-0.0.0.dev1.dist-info/RECORD +0 -187
  143. /omlish/{lang/classes/test → diag}/__init__.py +0 -0
  144. /omlish/{replserver → diag/replserver}/__init__.py +0 -0
  145. /omlish/{replserver → diag/replserver}/__main__.py +0 -0
  146. {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev3.dist-info}/LICENSE +0 -0
  147. {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev3.dist-info}/top_level.txt +0 -0
@@ -8,6 +8,7 @@ TODO:
8
8
  - further cythonize hot path?
9
9
  """
10
10
  import collections
11
+ import contextlib
11
12
  import functools
12
13
  import logging
13
14
  import time
@@ -17,7 +18,7 @@ import weakref
17
18
  from ... import lang
18
19
  from .types import Cache
19
20
  from .types import Eviction
20
- from .types import OverweightException
21
+ from .types import OverweightError
21
22
 
22
23
 
23
24
  K = ta.TypeVar('K')
@@ -33,15 +34,15 @@ class SKIP(lang.Marker):
33
34
  pass
34
35
 
35
36
 
36
- def LRU(cache: 'Cache') -> None:
37
+ def LRU(cache: 'Cache') -> None: # noqa
37
38
  cache._kill(cache._root.lru_next) # type: ignore # noqa
38
39
 
39
40
 
40
- def LRI(cache: 'Cache') -> None:
41
+ def LRI(cache: 'Cache') -> None: # noqa
41
42
  cache._kill(cache._root.ins_next) # type: ignore # noqa
42
43
 
43
44
 
44
- def LFU(cache: 'Cache') -> None:
45
+ def LFU(cache: 'Cache') -> None: # noqa
45
46
  cache._kill(cache._root.lfu_prev) # type: ignore # noqa
46
47
 
47
48
 
@@ -82,8 +83,8 @@ class CacheImpl(Cache[K, V]):
82
83
  lru_next: 'CacheImpl.Link'
83
84
  lfu_prev: 'CacheImpl.Link'
84
85
  lfu_next: 'CacheImpl.Link'
85
- key: ta.Union[ta.Any, weakref.ref]
86
- value: ta.Union[ta.Any, weakref.ref]
86
+ key: ta.Any | weakref.ref
87
+ value: ta.Any | weakref.ref
87
88
  weight: float
88
89
  written: float
89
90
  accessed: float
@@ -92,7 +93,7 @@ class CacheImpl(Cache[K, V]):
92
93
 
93
94
  def __repr__(self) -> str:
94
95
  return (
95
- f'Link@{str(self.seq)}('
96
+ f'Link@{self.seq!s}('
96
97
  f'ins_prev={("@" + str(self.ins_prev.seq)) if self.ins_prev is not None else None}, '
97
98
  f'ins_next={("@" + str(self.ins_next.seq)) if self.ins_next is not None else None}, '
98
99
  f'lru_prev={("@" + str(self.lru_prev.seq)) if self.lru_prev is not None else None}, '
@@ -120,7 +121,7 @@ class CacheImpl(Cache[K, V]):
120
121
  identity_keys: bool = False,
121
122
  expire_after_access: float | None = None,
122
123
  expire_after_write: float | None = None,
123
- removal_listener: ta.Callable[[ta.Union[K, weakref.ref], ta.Union[V, weakref.ref]], None] | None = None,
124
+ removal_listener: ta.Callable[[K | weakref.ref, V | weakref.ref], None] | None = None,
124
125
  clock: ta.Callable[[], float] | None = None,
125
126
  weak_keys: bool = False,
126
127
  weak_values: bool = False,
@@ -165,7 +166,7 @@ class CacheImpl(Cache[K, V]):
165
166
  if self._track_frequency:
166
167
  self._root.lfu_next = self._root.lfu_prev = self._root
167
168
 
168
- weak_dead: ta.Optional[ta.Deque[CacheImpl.Link]]
169
+ weak_dead: collections.deque[CacheImpl.Link] | None
169
170
  if weak_keys or weak_values:
170
171
  weak_dead = collections.deque()
171
172
  weak_dead_ref = weakref.ref(weak_dead)
@@ -276,10 +277,8 @@ class CacheImpl(Cache[K, V]):
276
277
  raise Exception
277
278
 
278
279
  def fail():
279
- try:
280
+ with contextlib.suppress(KeyError):
280
281
  del self._cache[cache_key]
281
- except KeyError:
282
- pass
283
282
  self._unlink(link)
284
283
  raise KeyError(key)
285
284
 
@@ -309,7 +308,7 @@ class CacheImpl(Cache[K, V]):
309
308
  link, value = self._get_link(key)
310
309
  except KeyError:
311
310
  self._misses += 1
312
- raise KeyError(key)
311
+ raise KeyError(key) from None
313
312
 
314
313
  if link.lru_next is not self._root:
315
314
  link.lru_prev.lru_next = link.lru_next
@@ -340,7 +339,7 @@ class CacheImpl(Cache[K, V]):
340
339
  return value
341
340
 
342
341
  @staticmethod
343
- def _weak_die(dead_ref: weakref.ref, link: Link, key_ref: weakref.ref) -> None:
342
+ def _weak_die(dead_ref: weakref.ref, link: Link, key_ref: weakref.ref) -> None: # noqa
344
343
  dead = dead_ref()
345
344
  if dead is not None:
346
345
  dead.append(link)
@@ -372,7 +371,7 @@ class CacheImpl(Cache[K, V]):
372
371
 
373
372
  if self._max_weight is not None and weight > self._max_weight:
374
373
  if self._raise_overweight:
375
- raise OverweightException
374
+ raise OverweightError
376
375
  else:
377
376
  return
378
377
 
@@ -387,10 +386,18 @@ class CacheImpl(Cache[K, V]):
387
386
  self._eviction(self)
388
387
 
389
388
  link = CacheImpl.Link()
389
+
390
390
  self._seq += 1
391
391
  link.seq = self._seq
392
- link.key = weakref.ref(key, functools.partial(CacheImpl._weak_die, self._weak_dead_ref, link)) if self._weak_keys else key # noqa
393
- link.value = weakref.ref(value, functools.partial(CacheImpl._weak_die, self._weak_dead_ref, link)) if self._weak_values else value # noqa
392
+
393
+ def make_ref(o, b):
394
+ if not b:
395
+ return o
396
+ return weakref.ref(o, functools.partial(CacheImpl._weak_die, self._weak_dead_ref, link)) # type: ignore # noqa
397
+
398
+ link.key = make_ref(key, self._weak_keys)
399
+ link.value = make_ref(value, self._weak_values)
400
+
394
401
  link.weight = weight
395
402
  link.written = link.accessed = self._clock()
396
403
  link.hits = 0
@@ -463,10 +470,10 @@ class CacheImpl(Cache[K, V]):
463
470
  else:
464
471
  yield key # type: ignore
465
472
 
466
- next = link.ins_prev
467
- if next is link:
473
+ nxt = link.ins_prev
474
+ if nxt is link:
468
475
  raise ValueError
469
- link = next
476
+ link = nxt
470
477
 
471
478
  @property
472
479
  def stats(self) -> Cache.Stats:
@@ -6,7 +6,7 @@ K = ta.TypeVar('K')
6
6
  V = ta.TypeVar('V')
7
7
 
8
8
 
9
- class OverweightException(Exception):
9
+ class OverweightError(Exception):
10
10
  pass
11
11
 
12
12
 
@@ -39,8 +39,8 @@ def seq(
39
39
 
40
40
 
41
41
  def opt_seq(
42
- it: ta.Optional[ta.Iterable[T]],
43
- ) -> ta.Optional[ta.Sequence[T]]:
42
+ it: ta.Iterable[T] | None,
43
+ ) -> ta.Sequence[T] | None:
44
44
  if it is None:
45
45
  return None
46
46
  else:
@@ -48,8 +48,8 @@ def opt_seq(
48
48
 
49
49
 
50
50
  def seq_or_none(
51
- it: ta.Optional[ta.Iterable[T]],
52
- ) -> ta.Optional[ta.Sequence[T]]:
51
+ it: ta.Iterable[T] | None,
52
+ ) -> ta.Sequence[T] | None:
53
53
  ret = opt_seq(it)
54
54
  if ret:
55
55
  return ret
@@ -58,7 +58,7 @@ def seq_or_none(
58
58
 
59
59
 
60
60
  def seq_of(
61
- fn: ta.Union[ta.Callable[[T], T2], tuple],
61
+ fn: ta.Callable[[T], T2] | tuple,
62
62
  ) -> ta.Callable[[ta.Iterable[T]], ta.Sequence[T2]]:
63
63
  def inner(it):
64
64
  return seq(fn(e) for e in it) # type: ignore
@@ -68,8 +68,8 @@ def seq_of(
68
68
 
69
69
 
70
70
  def opt_seq_of(
71
- fn: ta.Union[ta.Callable[[T], T2], tuple],
72
- ) -> ta.Callable[[ta.Optional[ta.Iterable[T]]], ta.Optional[ta.Sequence[T2]]]:
71
+ fn: ta.Callable[[T], T2] | tuple,
72
+ ) -> ta.Callable[[ta.Iterable[T] | None], ta.Sequence[T2] | None]:
73
73
  def inner(it):
74
74
  if it is None:
75
75
  return None
@@ -81,8 +81,8 @@ def opt_seq_of(
81
81
 
82
82
 
83
83
  def seq_of_or_none(
84
- fn: ta.Union[ta.Callable[[T], T2], tuple],
85
- ) -> ta.Callable[[ta.Optional[ta.Iterable[T]]], ta.Optional[ta.Sequence[T2]]]:
84
+ fn: ta.Callable[[T], T2] | tuple,
85
+ ) -> ta.Callable[[ta.Iterable[T] | None], ta.Sequence[T2] | None]:
86
86
  def inner(it):
87
87
  if it is None:
88
88
  return None
@@ -115,8 +115,8 @@ def abs_set(
115
115
 
116
116
 
117
117
  def opt_abs_set(
118
- it: ta.Optional[ta.Iterable[T]],
119
- ) -> ta.Optional[ta.AbstractSet[T]]:
118
+ it: ta.Iterable[T] | None,
119
+ ) -> ta.AbstractSet[T] | None:
120
120
  if it is None:
121
121
  return None
122
122
  else:
@@ -124,8 +124,8 @@ def opt_abs_set(
124
124
 
125
125
 
126
126
  def abs_set_or_none(
127
- it: ta.Optional[ta.Iterable[T]],
128
- ) -> ta.Optional[ta.AbstractSet[T]]:
127
+ it: ta.Iterable[T] | None,
128
+ ) -> ta.AbstractSet[T] | None:
129
129
  ret = opt_abs_set(it)
130
130
  if ret:
131
131
  return ret
@@ -134,7 +134,7 @@ def abs_set_or_none(
134
134
 
135
135
 
136
136
  def abs_set_of(
137
- fn: ta.Union[ta.Callable[[T], T2], tuple],
137
+ fn: ta.Callable[[T], T2] | tuple,
138
138
  ) -> ta.Callable[[ta.Iterable[T]], ta.AbstractSet[T2]]:
139
139
  def inner(it):
140
140
  return abs_set(fn(e) for e in it) # type: ignore
@@ -144,8 +144,8 @@ def abs_set_of(
144
144
 
145
145
 
146
146
  def opt_abs_set_of(
147
- fn: ta.Union[ta.Callable[[T], T2], tuple],
148
- ) -> ta.Callable[[ta.Optional[ta.Iterable[T]]], ta.Optional[ta.AbstractSet[T2]]]:
147
+ fn: ta.Callable[[T], T2] | tuple,
148
+ ) -> ta.Callable[[ta.Iterable[T] | None], ta.AbstractSet[T2] | None]:
149
149
  def inner(it):
150
150
  if it is None:
151
151
  return None
@@ -157,8 +157,8 @@ def opt_abs_set_of(
157
157
 
158
158
 
159
159
  def abs_set_of_or_none(
160
- fn: ta.Union[ta.Callable[[T], T2], tuple],
161
- ) -> ta.Callable[[ta.Optional[ta.Iterable[T]]], ta.Optional[ta.AbstractSet[T2]]]:
160
+ fn: ta.Callable[[T], T2] | tuple,
161
+ ) -> ta.Callable[[ta.Iterable[T] | None], ta.AbstractSet[T2] | None]:
162
162
  def inner(it):
163
163
  if it is None:
164
164
  return None
@@ -191,8 +191,8 @@ def frozenset_(
191
191
 
192
192
 
193
193
  def opt_frozenset(
194
- it: ta.Optional[ta.Iterable[T]],
195
- ) -> ta.Optional[frozenset[T]]:
194
+ it: ta.Iterable[T] | None,
195
+ ) -> frozenset[T] | None:
196
196
  if it is None:
197
197
  return None
198
198
  else:
@@ -200,8 +200,8 @@ def opt_frozenset(
200
200
 
201
201
 
202
202
  def frozenset_or_none(
203
- it: ta.Optional[ta.Iterable[T]],
204
- ) -> ta.Optional[frozenset[T]]:
203
+ it: ta.Iterable[T] | None,
204
+ ) -> frozenset[T] | None:
205
205
  ret = opt_frozenset(it)
206
206
  if ret:
207
207
  return ret
@@ -210,7 +210,7 @@ def frozenset_or_none(
210
210
 
211
211
 
212
212
  def frozenset_of(
213
- fn: ta.Union[ta.Callable[[T], T2], tuple],
213
+ fn: ta.Callable[[T], T2] | tuple,
214
214
  ) -> ta.Callable[[ta.Iterable[T]], frozenset[T2]]:
215
215
  def inner(it):
216
216
  return frozenset_(fn(e) for e in it) # type: ignore
@@ -220,8 +220,8 @@ def frozenset_of(
220
220
 
221
221
 
222
222
  def opt_frozenset_of(
223
- fn: ta.Union[ta.Callable[[T], T2], tuple],
224
- ) -> ta.Callable[[ta.Optional[ta.Iterable[T]]], ta.Optional[frozenset[T2]]]:
223
+ fn: ta.Callable[[T], T2] | tuple,
224
+ ) -> ta.Callable[[ta.Iterable[T] | None], frozenset[T2] | None]:
225
225
  def inner(it):
226
226
  if it is None:
227
227
  return None
@@ -233,8 +233,8 @@ def opt_frozenset_of(
233
233
 
234
234
 
235
235
  def frozenset_of_or_none(
236
- fn: ta.Union[ta.Callable[[T], T2], tuple],
237
- ) -> ta.Callable[[ta.Optional[ta.Iterable[T]]], ta.Optional[frozenset[T2]]]:
236
+ fn: ta.Callable[[T], T2] | tuple,
237
+ ) -> ta.Callable[[ta.Iterable[T] | None], frozenset[T2] | None]:
238
238
  def inner(it):
239
239
  if it is None:
240
240
  return None
@@ -255,15 +255,15 @@ def frozenset_of_or_none(
255
255
  # region map
256
256
 
257
257
 
258
- def map(
259
- src: ta.Union[ta.Mapping[K, V], ta.Iterable[tuple[K, V]]],
258
+ def map( # noqa
259
+ src: ta.Mapping[K, V] | ta.Iterable[tuple[K, V]],
260
260
  ) -> ta.Mapping[K, V]:
261
261
  return FrozenDict(src)
262
262
 
263
263
 
264
264
  def opt_map(
265
- src: ta.Optional[ta.Union[ta.Mapping[K, V], ta.Iterable[tuple[K, V]]]],
266
- ) -> ta.Optional[ta.Mapping[K, V]]:
265
+ src: ta.Mapping[K, V] | ta.Iterable[tuple[K, V]] | None,
266
+ ) -> ta.Mapping[K, V] | None:
267
267
  if src is None:
268
268
  return None
269
269
  else:
@@ -271,8 +271,8 @@ def opt_map(
271
271
 
272
272
 
273
273
  def map_or_none(
274
- src: ta.Optional[ta.Union[ta.Mapping[K, V], ta.Iterable[tuple[K, V]]]],
275
- ) -> ta.Optional[ta.Mapping[K, V]]:
274
+ src: ta.Mapping[K, V] | ta.Iterable[tuple[K, V]] | None,
275
+ ) -> ta.Mapping[K, V] | None:
276
276
  ret = opt_map(src)
277
277
  if ret:
278
278
  return ret
@@ -281,10 +281,10 @@ def map_or_none(
281
281
 
282
282
 
283
283
  def map_of(
284
- key_fn: ta.Union[ta.Callable[[K], K2], tuple],
285
- value_fn: ta.Union[ta.Callable[[V], V2], tuple],
284
+ key_fn: ta.Callable[[K], K2] | tuple,
285
+ value_fn: ta.Callable[[V], V2] | tuple,
286
286
  ) -> ta.Callable[
287
- [ta.Union[ta.Mapping[K, V], ta.Iterable[tuple[K, V]]]],
287
+ [ta.Mapping[K, V] | ta.Iterable[tuple[K, V]]],
288
288
  ta.Mapping[K2, V2],
289
289
  ]:
290
290
  def inner(src):
@@ -296,11 +296,11 @@ def map_of(
296
296
 
297
297
 
298
298
  def opt_map_of(
299
- key_fn: ta.Union[ta.Callable[[K], K2], tuple],
300
- value_fn: ta.Union[ta.Callable[[V], V2], tuple],
299
+ key_fn: ta.Callable[[K], K2] | tuple,
300
+ value_fn: ta.Callable[[V], V2] | tuple,
301
301
  ) -> ta.Callable[
302
- [ta.Optional[ta.Union[ta.Mapping[K, V], ta.Iterable[tuple[K, V]]]]],
303
- ta.Optional[ta.Mapping[K2, V2]],
302
+ [ta.Mapping[K, V] | ta.Iterable[tuple[K, V]] | None],
303
+ ta.Mapping[K2, V2] | None,
304
304
  ]:
305
305
  def inner(src):
306
306
  if src is None:
@@ -314,11 +314,11 @@ def opt_map_of(
314
314
 
315
315
 
316
316
  def map_of_or_none(
317
- key_fn: ta.Union[ta.Callable[[K], K2], tuple],
318
- value_fn: ta.Union[ta.Callable[[V], V2], tuple],
317
+ key_fn: ta.Callable[[K], K2] | tuple,
318
+ value_fn: ta.Callable[[V], V2] | tuple,
319
319
  ) -> ta.Callable[
320
- [ta.Optional[ta.Union[ta.Mapping[K, V], ta.Iterable[tuple[K, V]]]]],
321
- ta.Optional[ta.Mapping[K2, V2]],
320
+ [ta.Mapping[K, V] | ta.Iterable[tuple[K, V]] | None],
321
+ ta.Mapping[K2, V2] | None,
322
322
  ]:
323
323
  def inner(src):
324
324
  if src is None:
@@ -17,7 +17,7 @@ class Frozen(ta.Hashable, abc.ABC):
17
17
 
18
18
  class FrozenDict(ta.Mapping[K, V], Frozen):
19
19
 
20
- def __new__(cls, *args, **kwargs) -> 'FrozenDict[K, V]':
20
+ def __new__(cls, *args: ta.Any, **kwargs: ta.Any) -> 'FrozenDict[K, V]': # noqa
21
21
  if len(args) == 1 and Frozen in type(args[0]).__bases__:
22
22
  return args[0]
23
23
  return super().__new__(cls)
@@ -35,10 +35,10 @@ class FrozenDict(ta.Mapping[K, V], Frozen):
35
35
  return dict(self._dct)
36
36
 
37
37
  def __repr__(self) -> str:
38
- return '(%r)' % (self._dct,)
38
+ return f'({self._dct!r})'
39
39
 
40
40
  def __eq__(self, other) -> bool:
41
- return type(self) == type(other) and self._dct == other._dct
41
+ return type(self) is type(other) and self._dct == other._dct
42
42
 
43
43
  def __getitem__(self, key: K) -> V:
44
44
  return self._dct[key]
@@ -63,29 +63,29 @@ class FrozenDict(ta.Mapping[K, V], Frozen):
63
63
  def __setstate__(self, t):
64
64
  self.__init__(t) # type: ignore
65
65
 
66
- def drop(self, *keys):
66
+ def drop(self, *keys: T) -> 'FrozenDict[K, V]':
67
67
  ks = frozenset(keys)
68
68
  return type(self)((k, self[k]) for k in self if k not in ks)
69
69
 
70
- def set(self, *args, **kwargs):
70
+ def set(self, *args: ta.Any, **kwargs: ta.Any) -> 'FrozenDict[K, V]':
71
71
  new = type(self)(*args, **kwargs)
72
72
  return type(self)(itertools.chain(self.items(), new.items()))
73
73
 
74
74
 
75
75
  class FrozenList(ta.Sequence[T], Frozen):
76
76
 
77
- def __init__(self, it: ta.Optional[ta.Iterable[T]] = None) -> None:
77
+ def __init__(self, it: ta.Iterable[T] | None = None) -> None:
78
78
  super().__init__()
79
79
 
80
80
  self._tup: tuple = tuple(it) if it is not None else ()
81
- self._hash: ta.Optional[int] = None
81
+ self._hash: int | None = None
82
82
 
83
83
  @property
84
84
  def debug(self) -> ta.Sequence[T]:
85
85
  return list(self)
86
86
 
87
87
  def __repr__(self) -> str:
88
- return '([%s])' % (', '.join(map(repr, self._tup)),)
88
+ return f'([{", ".join(map(repr, self._tup))}])'
89
89
 
90
90
  def __add__(self, o) -> 'FrozenList[T]':
91
91
  if isinstance(o, FrozenList):
@@ -111,7 +111,7 @@ class FrozenList(ta.Sequence[T], Frozen):
111
111
  self._hash = hash(self._tup)
112
112
  return self._hash
113
113
 
114
- def __getitem__(self, idx: ta.Union[int, slice]) -> 'FrozenList[T]': # type: ignore
114
+ def __getitem__(self, idx: int | slice) -> 'FrozenList[T]': # type: ignore
115
115
  if isinstance(idx, int):
116
116
  return self._tup[idx]
117
117
  else:
@@ -1,3 +1,4 @@
1
+ import contextlib
1
2
  import operator as op
2
3
  import typing as ta
3
4
 
@@ -63,13 +64,13 @@ class IdentityKeyDict(ta.MutableMapping[K, V]):
63
64
  def __iter__(self) -> ta.Iterator[K]:
64
65
  return iter(map(op.itemgetter(0), self._dict.values()))
65
66
 
66
- def clear(self):
67
+ def clear(self) -> None:
67
68
  self._dict.clear()
68
69
 
69
70
 
70
71
  class IdentitySet(ta.MutableSet[T]):
71
72
 
72
- def __init__(self, init: ta.Optional[ta.Iterable[T]] = None) -> None:
73
+ def __init__(self, init: ta.Iterable[T] | None = None) -> None:
73
74
  super().__init__()
74
75
  self._dict: dict[int, T] = {}
75
76
  if init is not None:
@@ -87,10 +88,8 @@ class IdentitySet(ta.MutableSet[T]):
87
88
  self._dict[id(item)] = item
88
89
 
89
90
  def discard(self, item: T) -> None:
90
- try:
91
+ with contextlib.suppress(KeyError):
91
92
  del self._dict[id(item)]
92
- except KeyError:
93
- pass
94
93
 
95
94
  def update(self, items: ta.Iterable[T]) -> None:
96
95
  for item in items:
@@ -8,7 +8,7 @@ K = ta.TypeVar('K')
8
8
  V = ta.TypeVar('V')
9
9
 
10
10
 
11
- def multikey_dict(dct: ta.Mapping[ta.Union[ta.Iterable[K], K], V], *, deep: bool = False) -> dict[K, V]:
11
+ def multikey_dict(dct: ta.Mapping[ta.Iterable[K] | K, V], *, deep: bool = False) -> dict[K, V]:
12
12
  ret = {}
13
13
  for k, v in dct.items():
14
14
  if deep and isinstance(v, dict):
@@ -23,7 +23,7 @@ def multikey_dict(dct: ta.Mapping[ta.Union[ta.Iterable[K], K], V], *, deep: bool
23
23
 
24
24
  def guarded_map_update(
25
25
  dst: ta.MutableMapping[ta.Any, ta.Any],
26
- *srcs: ta.Mapping[ta.Any, ta.Any]
26
+ *srcs: ta.Mapping[ta.Any, ta.Any],
27
27
  ) -> ta.MutableMapping[ta.Any, ta.Any]:
28
28
  for src in srcs:
29
29
  for k, v in src.items():
@@ -68,10 +68,10 @@ class TypeMap(ta.Generic[T]):
68
68
  def __len__(self) -> int:
69
69
  return len(self._items)
70
70
 
71
- def __iter__(self) -> ta.Iterable[T]:
71
+ def __iter__(self) -> ta.Iterator[T]:
72
72
  return iter(self._items)
73
73
 
74
- def get(self, ty: type[T]) -> ta.Optional[T]:
74
+ def get(self, ty: type[T]) -> T | None:
75
75
  return self._dct.get(ty)
76
76
 
77
77
  def __getitem__(self, ty: type[T]) -> ta.Sequence[T]:
@@ -99,7 +99,7 @@ class TypeMultiMap(ta.Generic[V]):
99
99
  def __len__(self) -> int:
100
100
  return len(self._items)
101
101
 
102
- def __iter__(self) -> ta.Iterable[V]:
102
+ def __iter__(self) -> ta.Iterator[V]:
103
103
  return iter(self._items)
104
104
 
105
105
  def __getitem__(self, ty: type[T]) -> ta.Sequence[T]:
@@ -6,7 +6,7 @@ T = ta.TypeVar('T')
6
6
 
7
7
  class OrderedSet(ta.MutableSet[T]):
8
8
 
9
- def __init__(self, iterable: ta.Optional[ta.Iterable[T]] = None) -> None:
9
+ def __init__(self, iterable: ta.Iterable[T] | None = None) -> None:
10
10
  super().__init__()
11
11
  self._dct: dict[T, ta.Any] = {}
12
12
  if iterable is not None:
@@ -37,17 +37,17 @@ class OrderedSet(ta.MutableSet[T]):
37
37
  def __reversed__(self):
38
38
  return reversed(self._dct.keys())
39
39
 
40
- def pop(self, last=True):
40
+ def pop(self, last: bool = True) -> T:
41
41
  if not self:
42
42
  raise KeyError('set is empty')
43
43
  item = next(reversed(self._dct.keys()))
44
44
  self.discard(item)
45
45
  return item
46
46
 
47
- def __repr__(self):
47
+ def __repr__(self) -> str:
48
48
  if not self:
49
- return '%s()' % (self.__class__.__name__,)
50
- return '%s(%r)' % (self.__class__.__name__, list(self))
49
+ return f'{self.__class__.__name__}()'
50
+ return f'{self.__class__.__name__}({list(self)!r})'
51
51
 
52
52
  def __eq__(self, other) -> bool:
53
53
  if isinstance(other, OrderedSet):
@@ -55,11 +55,11 @@ class OrderedSet(ta.MutableSet[T]):
55
55
  return set(self) == set(other)
56
56
 
57
57
 
58
- class OrderedFrozenSet(ta.FrozenSet[T]):
58
+ class OrderedFrozenSet(ta.FrozenSet[T]): # noqa
59
59
 
60
60
  _list: ta.Sequence[T]
61
61
 
62
- def __new__(cls, items: ta.Iterable[T]) -> ta.FrozenSet[T]: # type: ignore
62
+ def __new__(cls, items: ta.Iterable[T]) -> frozenset[T]: # type: ignore
63
63
  item_set = set()
64
64
  item_list = []
65
65
  for item in items:
@@ -76,6 +76,6 @@ class OrderedFrozenSet(ta.FrozenSet[T]):
76
76
  def __iter__(self) -> ta.Iterator[T]:
77
77
  return iter(self._list)
78
78
 
79
- def __sub__(self, other: ta.Iterable[T]) -> ta.FrozenSet[T]:
79
+ def __sub__(self, other: ta.Iterable[T]) -> frozenset[T]:
80
80
  s = set(other)
81
81
  return type(self)(i for i in self if i not in s)
@@ -27,7 +27,7 @@ class SkipList(SortedCollection[T]):
27
27
  def __init__(
28
28
  self,
29
29
  value: T,
30
- level: int
30
+ level: int,
31
31
  ) -> None:
32
32
  super().__init__()
33
33
 
@@ -46,7 +46,7 @@ class SkipList(SortedCollection[T]):
46
46
  self,
47
47
  *,
48
48
  max_height: int = 16,
49
- comparator: ta.Optional[SortedCollection.Comparator[T]] = None,
49
+ comparator: SortedCollection.Comparator[T] | None = None,
50
50
  ) -> None:
51
51
  super().__init__()
52
52
 
@@ -108,7 +108,7 @@ class SkipList(SortedCollection[T]):
108
108
  self._length += 1
109
109
  return True
110
110
 
111
- def _find(self, value: T) -> ta.Optional[_Node]:
111
+ def _find(self, value: T) -> _Node | None:
112
112
  if value is None:
113
113
  raise TypeError(value)
114
114
 
@@ -120,7 +120,7 @@ class SkipList(SortedCollection[T]):
120
120
 
121
121
  return cur.next[0]
122
122
 
123
- def find(self, value: T) -> ta.Optional[T]:
123
+ def find(self, value: T) -> T | None:
124
124
  node = self._find(value)
125
125
  if node is None:
126
126
  return None
@@ -157,7 +157,7 @@ class SkipList(SortedCollection[T]):
157
157
  self._length -= 1
158
158
  return True
159
159
 
160
- def iter(self, base: ta.Optional[T] = None) -> ta.Iterable[T]:
160
+ def iter(self, base: T | None = None) -> ta.Iterable[T]:
161
161
  if base is not None:
162
162
  cur = self._find(base)
163
163
  while cur is not None and self._compare(base, cur.value) > 0: # type: ignore
@@ -169,7 +169,7 @@ class SkipList(SortedCollection[T]):
169
169
  yield cur.value # type: ignore
170
170
  cur = cur.next[0]
171
171
 
172
- def riter(self, base: ta.Optional[T] = None) -> ta.Iterable[T]:
172
+ def riter(self, base: T | None = None) -> ta.Iterable[T]:
173
173
  if base is not None:
174
174
  cur = self._find(base)
175
175
  while cur is not self._head and self._compare(base, cur.value) < 0: # type: ignore
@@ -190,4 +190,4 @@ class SkipList(SortedCollection[T]):
190
190
  class SkipListDict(SortedListDict[K, V]):
191
191
 
192
192
  def __init__(self, *args, **kwargs) -> None:
193
- super().__init__(SkipList(comparator=SortedListDict._item_comparator), *args, **kwargs)
193
+ super().__init__(SkipList(comparator=SortedListDict._item_comparator), *args, **kwargs) # noqa
@@ -38,7 +38,7 @@ class SortedCollection(lang.Abstract, ta.Collection[T]):
38
38
  raise NotImplementedError
39
39
 
40
40
  @abc.abstractmethod
41
- def find(self, value: T) -> ta.Optional[T]:
41
+ def find(self, value: T) -> T | None:
42
42
  raise NotImplementedError
43
43
 
44
44
  @abc.abstractmethod
@@ -46,11 +46,11 @@ class SortedCollection(lang.Abstract, ta.Collection[T]):
46
46
  raise NotImplementedError
47
47
 
48
48
  @abc.abstractmethod
49
- def iter(self, base: ta.Optional[T] = None) -> ta.Iterable[T]:
49
+ def iter(self, base: T | None = None) -> ta.Iterable[T]:
50
50
  raise NotImplementedError
51
51
 
52
52
  @abc.abstractmethod
53
- def riter(self, base: ta.Optional[T] = None) -> ta.Iterable[T]:
53
+ def riter(self, base: T | None = None) -> ta.Iterable[T]:
54
54
  raise NotImplementedError
55
55
 
56
56
 
@@ -110,7 +110,7 @@ class SortedListDict(SortedMutableMapping[K, V]):
110
110
  return len(self._impl)
111
111
 
112
112
  def __iter__(self) -> ta.Iterator[K]:
113
- for k, v in self._impl:
113
+ for k, _ in self._impl:
114
114
  yield k
115
115
 
116
116
  def items(self) -> ta.Iterator[tuple[K, V]]: # type: ignore