omlish 0.0.0.dev2__py3-none-any.whl → 0.0.0.dev4__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 (124) hide show
  1. omlish/__about__.py +1 -2
  2. omlish/__init__.py +8 -0
  3. omlish/argparse.py +4 -4
  4. omlish/asyncs/__init__.py +23 -2
  5. omlish/asyncs/anyio.py +13 -11
  6. omlish/asyncs/asyncs.py +1 -3
  7. omlish/asyncs/flavors.py +201 -0
  8. omlish/asyncs/futures.py +10 -9
  9. omlish/asyncs/trio_asyncio.py +41 -0
  10. omlish/c3.py +1 -1
  11. omlish/check.py +3 -3
  12. omlish/collections/_abc.py +2 -0
  13. omlish/collections/_io_abc.py +4 -2
  14. omlish/collections/cache/__init__.py +1 -1
  15. omlish/collections/cache/descriptor.py +8 -8
  16. omlish/collections/cache/impl.py +24 -17
  17. omlish/collections/cache/types.py +1 -1
  18. omlish/collections/coerce.py +1 -1
  19. omlish/collections/frozen.py +6 -6
  20. omlish/collections/identity.py +3 -4
  21. omlish/collections/mappings.py +2 -2
  22. omlish/collections/ordered.py +7 -7
  23. omlish/collections/skiplist.py +1 -1
  24. omlish/collections/sorted.py +1 -1
  25. omlish/collections/treap.py +25 -0
  26. omlish/collections/treapmap.py +57 -5
  27. omlish/collections/unmodifiable.py +9 -9
  28. omlish/collections/utils.py +1 -1
  29. omlish/configs/flattening.py +7 -6
  30. omlish/configs/props.py +3 -3
  31. omlish/dataclasses/__init__.py +1 -1
  32. omlish/dataclasses/impl/__init__.py +17 -1
  33. omlish/dataclasses/impl/api.py +10 -11
  34. omlish/dataclasses/impl/as_.py +4 -4
  35. omlish/dataclasses/impl/exceptions.py +1 -1
  36. omlish/dataclasses/impl/fields.py +7 -7
  37. omlish/dataclasses/impl/frozen.py +2 -2
  38. omlish/dataclasses/impl/init.py +5 -5
  39. omlish/dataclasses/impl/internals.py +1 -1
  40. omlish/dataclasses/impl/metaclass.py +1 -1
  41. omlish/dataclasses/impl/order.py +1 -1
  42. omlish/dataclasses/impl/replace.py +1 -1
  43. omlish/dataclasses/impl/repr.py +4 -4
  44. omlish/dataclasses/impl/utils.py +6 -6
  45. omlish/defs.py +13 -17
  46. omlish/{procfs.py → diag/procfs.py} +22 -24
  47. omlish/diag/ps.py +47 -0
  48. omlish/{replserver → diag/replserver}/console.py +18 -20
  49. omlish/{replserver → diag/replserver}/server.py +8 -8
  50. omlish/dispatch/dispatch.py +5 -8
  51. omlish/dispatch/functions.py +1 -1
  52. omlish/dispatch/methods.py +4 -5
  53. omlish/docker.py +1 -1
  54. omlish/dynamic.py +10 -10
  55. omlish/fnpairs.py +400 -0
  56. omlish/graphs/trees.py +13 -13
  57. omlish/inject/__init__.py +7 -7
  58. omlish/inject/elements.py +1 -1
  59. omlish/inject/exceptions.py +7 -7
  60. omlish/inject/impl/elements.py +17 -5
  61. omlish/inject/impl/injector.py +12 -10
  62. omlish/inject/impl/inspect.py +2 -2
  63. omlish/inject/impl/scopes.py +12 -11
  64. omlish/inject/proxy.py +5 -5
  65. omlish/iterators.py +19 -24
  66. omlish/json.py +143 -6
  67. omlish/lang/__init__.py +13 -4
  68. omlish/lang/cached.py +2 -5
  69. omlish/lang/classes/__init__.py +2 -2
  70. omlish/lang/classes/abstract.py +2 -2
  71. omlish/lang/classes/restrict.py +14 -14
  72. omlish/lang/classes/simple.py +1 -1
  73. omlish/lang/classes/virtual.py +5 -5
  74. omlish/lang/clsdct.py +1 -1
  75. omlish/lang/cmp.py +2 -2
  76. omlish/lang/contextmanagers.py +12 -14
  77. omlish/lang/descriptors.py +16 -4
  78. omlish/lang/exceptions.py +1 -1
  79. omlish/lang/functions.py +58 -22
  80. omlish/lang/imports.py +22 -27
  81. omlish/lang/iterables.py +2 -2
  82. omlish/lang/maybes.py +1 -0
  83. omlish/lang/objects.py +15 -9
  84. omlish/lang/resolving.py +1 -1
  85. omlish/lang/strings.py +1 -1
  86. omlish/lang/sys.py +7 -0
  87. omlish/lang/typing.py +3 -3
  88. omlish/libc.py +9 -5
  89. omlish/logs/_abc.py +5 -1
  90. omlish/logs/filters.py +2 -0
  91. omlish/logs/formatters.py +6 -2
  92. omlish/logs/utils.py +1 -1
  93. omlish/marshal/base.py +3 -3
  94. omlish/marshal/exceptions.py +1 -1
  95. omlish/marshal/global_.py +10 -4
  96. omlish/marshal/objects.py +1 -2
  97. omlish/marshal/registries.py +3 -3
  98. omlish/marshal/utils.py +2 -2
  99. omlish/marshal/values.py +1 -1
  100. omlish/math.py +9 -9
  101. omlish/reflect.py +3 -3
  102. omlish/sql/__init__.py +9 -0
  103. omlish/sql/asyncs.py +148 -0
  104. omlish/stats.py +4 -5
  105. omlish/term.py +1 -1
  106. omlish/testing/pydevd.py +28 -6
  107. omlish/testing/pytest/inject/harness.py +1 -1
  108. omlish/testing/pytest/plugins/pydevd.py +1 -1
  109. omlish/testing/pytest/plugins/switches.py +1 -1
  110. omlish/text/delimit.py +3 -6
  111. {omlish-0.0.0.dev2.dist-info → omlish-0.0.0.dev4.dist-info}/METADATA +4 -1
  112. omlish-0.0.0.dev4.dist-info/RECORD +195 -0
  113. {omlish-0.0.0.dev2.dist-info → omlish-0.0.0.dev4.dist-info}/WHEEL +1 -1
  114. omlish/lang/classes/test/test_abstract.py +0 -89
  115. omlish/lang/classes/test/test_restrict.py +0 -71
  116. omlish/lang/classes/test/test_simple.py +0 -58
  117. omlish/lang/classes/test/test_virtual.py +0 -72
  118. omlish-0.0.0.dev2.dist-info/RECORD +0 -193
  119. /omlish/{lang/classes/test → diag}/__init__.py +0 -0
  120. /omlish/{replserver → diag/replserver}/__init__.py +0 -0
  121. /omlish/{replserver → diag/replserver}/__main__.py +0 -0
  122. /omlish/sql/{_abcs.py → _abc.py} +0 -0
  123. {omlish-0.0.0.dev2.dist-info → omlish-0.0.0.dev4.dist-info}/LICENSE +0 -0
  124. {omlish-0.0.0.dev2.dist-info → omlish-0.0.0.dev4.dist-info}/top_level.txt +0 -0
omlish/lang/cached.py CHANGED
@@ -207,7 +207,7 @@ class _CachedFunctionDescriptor(_CachedFunction[T]):
207
207
  return bound
208
208
 
209
209
 
210
- def cached_function(fn=None, **kwargs):
210
+ def cached_function(fn=None, **kwargs): # noqa
211
211
  if fn is None:
212
212
  return functools.partial(cached_function, **kwargs)
213
213
  opts = _CachedFunction.Opts(**kwargs)
@@ -217,9 +217,6 @@ def cached_function(fn=None, **kwargs):
217
217
  return _CachedFunctionDescriptor(fn, scope, opts=opts)
218
218
 
219
219
 
220
- cached_function = cached_function
221
-
222
-
223
220
  ##
224
221
 
225
222
 
@@ -269,7 +266,7 @@ class _CachedProperty:
269
266
  raise TypeError(self._name)
270
267
 
271
268
 
272
- def cached_property(fn=None, **kwargs):
269
+ def cached_property(fn=None, **kwargs): # noqa
273
270
  if fn is None:
274
271
  return functools.partial(cached_property, **kwargs)
275
272
  return _CachedProperty(fn, **kwargs)
@@ -8,13 +8,13 @@ from .abstract import ( # noqa
8
8
 
9
9
  from .restrict import ( # noqa
10
10
  Final,
11
- FinalException,
11
+ FinalError,
12
12
  NoBool,
13
13
  NotInstantiable,
14
14
  NotPicklable,
15
15
  PackageSealed,
16
16
  Sealed,
17
- SealedException,
17
+ SealedError,
18
18
  no_bool,
19
19
  )
20
20
 
@@ -23,7 +23,7 @@ def make_abstract(obj: T) -> T:
23
23
  return obj
24
24
 
25
25
 
26
- class Abstract(abc.ABC):
26
+ class Abstract(abc.ABC): # noqa
27
27
  __slots__ = ()
28
28
 
29
29
  def __forceabstract__(self):
@@ -31,7 +31,7 @@ class Abstract(abc.ABC):
31
31
 
32
32
  setattr(__forceabstract__, '__isabstractmethod__', True)
33
33
 
34
- def __init_subclass__(cls, **kwargs) -> None:
34
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
35
35
  if Abstract in cls.__bases__:
36
36
  cls.__forceabstract__ = Abstract.__forceabstract__ # type: ignore
37
37
  else:
@@ -8,9 +8,9 @@ from .abstract import is_abstract
8
8
  ##
9
9
 
10
10
 
11
- class FinalException(TypeError):
11
+ class FinalError(TypeError):
12
12
 
13
- def __init__(self, _type: ta.Type) -> None:
13
+ def __init__(self, _type: type) -> None:
14
14
  super().__init__()
15
15
 
16
16
  self._type = _type
@@ -22,17 +22,17 @@ class FinalException(TypeError):
22
22
  class Final(Abstract):
23
23
  __slots__ = ()
24
24
 
25
- def __init_subclass__(cls, **kwargs) -> None:
25
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
26
26
  super().__init_subclass__(**kwargs)
27
27
 
28
28
  abstracts: set[ta.Any] = set()
29
29
  for base in cls.__bases__:
30
30
  if base is Abstract:
31
- raise FinalException(base)
31
+ raise FinalError(base)
32
32
  elif base is Final:
33
33
  continue
34
34
  elif Final in base.__mro__:
35
- raise FinalException(base)
35
+ raise FinalError(base)
36
36
  else:
37
37
  abstracts.update(getattr(base, '__abstractmethods__', []))
38
38
 
@@ -40,15 +40,15 @@ class Final(Abstract):
40
40
  try:
41
41
  v = cls.__dict__[a]
42
42
  except KeyError:
43
- raise FinalException(a)
43
+ raise FinalError(a) from None
44
44
  if is_abstract(v):
45
- raise FinalException(a)
45
+ raise FinalError(a)
46
46
 
47
47
 
48
48
  ##
49
49
 
50
50
 
51
- class SealedException(TypeError):
51
+ class SealedError(TypeError):
52
52
 
53
53
  def __init__(self, _type) -> None:
54
54
  super().__init__()
@@ -62,24 +62,24 @@ class SealedException(TypeError):
62
62
  class Sealed:
63
63
  __slots__ = ()
64
64
 
65
- def __init_subclass__(cls, **kwargs) -> None:
65
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
66
66
  for base in cls.__bases__:
67
67
  if base is not Abstract:
68
68
  if Sealed in base.__bases__:
69
69
  if cls.__module__ != base.__module__:
70
- raise SealedException(base)
70
+ raise SealedError(base)
71
71
  super().__init_subclass__(**kwargs)
72
72
 
73
73
 
74
74
  class PackageSealed:
75
75
  __slots__ = ()
76
76
 
77
- def __init_subclass__(cls, **kwargs) -> None:
77
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
78
78
  for base in cls.__bases__:
79
79
  if base is not Abstract:
80
80
  if PackageSealed in base.__bases__:
81
81
  if cls.__module__.split('.')[:-1] != base.__module__.split('.')[:-1]:
82
- raise SealedException(base)
82
+ raise SealedError(base)
83
83
  super().__init_subclass__(**kwargs)
84
84
 
85
85
 
@@ -89,7 +89,7 @@ class PackageSealed:
89
89
  class NotInstantiable(Abstract):
90
90
  __slots__ = ()
91
91
 
92
- def __new__(cls, *args, **kwargs) -> ta.NoReturn:
92
+ def __new__(cls, *args, **kwargs):
93
93
  raise TypeError
94
94
 
95
95
 
@@ -133,5 +133,5 @@ class _NoBoolDescriptor:
133
133
  return self._fn(*args, **kwargs)
134
134
 
135
135
 
136
- def no_bool(fn):
136
+ def no_bool(fn): # noqa
137
137
  return _NoBoolDescriptor(fn)
@@ -100,7 +100,7 @@ class Singleton:
100
100
  def __new__(cls):
101
101
  return cls.__dict__[_SINGLETON_INSTANCE_ATTR]
102
102
 
103
- def __init_subclass__(cls, **kwargs):
103
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
104
104
  super().__init_subclass__(**kwargs)
105
105
  _set_singleton_instance(super().__new__(cls)) # noqa
106
106
 
@@ -15,10 +15,10 @@ Ty = ta.TypeVar('Ty', bound=type)
15
15
 
16
16
 
17
17
  def _make_not_instantiable():
18
- def __new__(cls, *args, **kwargs):
18
+ def __new__(cls, *args, **kwargs): # noqa
19
19
  raise TypeError(cls)
20
20
 
21
- def __init__(self, *args, **kwargs):
21
+ def __init__(self, *args, **kwargs): # noqa
22
22
  raise TypeError(self)
23
23
 
24
24
  return {
@@ -49,7 +49,7 @@ class _VirtualMeta(abc.ABCMeta):
49
49
  reqset -= set(mro_cls.__dict__)
50
50
  return reqset
51
51
 
52
- def __subclasshook__(cls, subclass):
52
+ def __subclasshook__(cls, subclass): # noqa
53
53
  if cls is not kls:
54
54
  return super(kls, cls).__subclasshook__(subclass) # type: ignore
55
55
  if get_missing_reqs(subclass):
@@ -117,11 +117,11 @@ class Callable(NotInstantiable, Final, ta.Generic[T]):
117
117
  raise TypeError
118
118
 
119
119
  @classmethod
120
- def __instancecheck__(cls, instance):
120
+ def __instancecheck__(cls, instance: object) -> bool:
121
121
  return callable(instance)
122
122
 
123
123
  @classmethod
124
- def __subclasscheck__(cls, subclass):
124
+ def __subclasscheck__(cls, subclass: type) -> bool:
125
125
  if not hasattr(subclass, '__call__'):
126
126
  return False
127
127
  call = subclass.__call__
omlish/lang/clsdct.py CHANGED
@@ -60,7 +60,7 @@ class ClassDctFn:
60
60
  return self._fn(cls_dct, *args, **kwargs)
61
61
 
62
62
 
63
- def cls_dct_fn(offset=1, *, wrap=True):
63
+ def cls_dct_fn(offset=1, *, wrap=True): # noqa
64
64
  def outer(fn):
65
65
  return ClassDctFn(fn, offset, wrap=wrap)
66
66
 
omlish/lang/cmp.py CHANGED
@@ -18,7 +18,7 @@ class InfinityType:
18
18
  def __le__(self, other: ta.Any) -> bool:
19
19
  return False
20
20
 
21
- def __eq__(self, other: ta.Any) -> bool:
21
+ def __eq__(self, other: object) -> bool:
22
22
  return isinstance(other, self.__class__)
23
23
 
24
24
  def __gt__(self, other: ta.Any) -> bool:
@@ -47,7 +47,7 @@ class NegativeInfinityType:
47
47
  def __le__(self, other: ta.Any) -> bool:
48
48
  return True
49
49
 
50
- def __eq__(self, other: ta.Any) -> bool:
50
+ def __eq__(self, other: object) -> bool:
51
51
  return isinstance(other, self.__class__)
52
52
 
53
53
  def __gt__(self, other: ta.Any) -> bool:
@@ -19,8 +19,8 @@ class ContextManaged:
19
19
 
20
20
  def __exit__(
21
21
  self,
22
- exc_type: ta.Type[Exception] | None,
23
- exc_val: Exception | None,
22
+ exc_type: type[BaseException] | None,
23
+ exc_val: BaseException | None,
24
24
  exc_tb: types.TracebackType | None,
25
25
  ) -> bool | None:
26
26
  return None
@@ -28,7 +28,7 @@ class ContextManaged:
28
28
 
29
29
  class NopContextManaged(ContextManaged):
30
30
 
31
- def __init_subclass__(cls, **kwargs):
31
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
32
32
  raise TypeError
33
33
 
34
34
 
@@ -37,7 +37,7 @@ NOP_CONTEXT_MANAGED = NopContextManaged()
37
37
 
38
38
  class NopContextManager:
39
39
 
40
- def __init_subclass__(cls, **kwargs):
40
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
41
41
  raise TypeError
42
42
 
43
43
  def __call__(self, *args, **kwargs):
@@ -84,11 +84,11 @@ def disposing(obj: T, attr: str = 'dispose') -> ta.Iterator[T]:
84
84
 
85
85
 
86
86
  @contextlib.contextmanager
87
- def breakpoint_on_exception():
87
+ def breakpoint_on_exception(): # noqa
88
88
  try:
89
89
  yield
90
90
  except Exception as e: # noqa
91
- breakpoint()
91
+ breakpoint() # noqa
92
92
  raise
93
93
 
94
94
 
@@ -102,7 +102,7 @@ def context_var_setting(var: contextvars.ContextVar[T], val: T) -> ta.Iterator[T
102
102
 
103
103
 
104
104
  @contextlib.contextmanager
105
- def attr_setting(obj, attr, val, *, default=None):
105
+ def attr_setting(obj, attr, val, *, default=None): # noqa
106
106
  not_set = object()
107
107
  orig = getattr(obj, attr, not_set)
108
108
  try:
@@ -146,8 +146,8 @@ class ExitStacked:
146
146
 
147
147
  def __exit__(
148
148
  self,
149
- exc_type: ta.Type[Exception] | None,
150
- exc_val: Exception | None,
149
+ exc_type: type[BaseException] | None,
150
+ exc_val: BaseException | None,
151
151
  exc_tb: types.TracebackType | None,
152
152
  ) -> bool | None:
153
153
  self._exit_stack.__exit__(exc_type, exc_val, exc_tb)
@@ -212,10 +212,8 @@ class ContextWrapped:
212
212
  raise TypeError(cm)
213
213
  ret = type(self)(fn, cm)
214
214
  if self._name is not None:
215
- try:
215
+ with contextlib.suppress(TypeError):
216
216
  instance.__dict__[self._name] = ret
217
- except TypeError:
218
- pass
219
217
  return ret
220
218
 
221
219
  def __call__(self, *args, **kwargs):
@@ -228,7 +226,7 @@ class ContextWrapped:
228
226
  return self._fn[0](*args, **kwargs)
229
227
 
230
228
 
231
- def context_wrapped(cm): # ContextWrappable -> ta.Callable[[CallableT], CallableT]:
229
+ def context_wrapped(cm): # ContextWrappable -> ta.Callable[[CallableT], CallableT]: # noqa
232
230
  def inner(fn):
233
231
  return ContextWrapped(fn, cm)
234
232
  return inner
@@ -238,7 +236,7 @@ def context_wrapped(cm): # ContextWrappable -> ta.Callable[[CallableT], Callabl
238
236
 
239
237
 
240
238
  Lockable = ta.Callable[[], ta.ContextManager]
241
- DefaultLockable = ta.Union[None, bool, Lockable, ta.ContextManager]
239
+ DefaultLockable = bool | Lockable | ta.ContextManager | None
242
240
 
243
241
 
244
242
  def default_lock(value: DefaultLockable, default: DefaultLockable) -> Lockable:
@@ -1,4 +1,5 @@
1
1
  import functools
2
+ import operator
2
3
  import typing as ta
3
4
 
4
5
 
@@ -8,6 +9,17 @@ T = ta.TypeVar('T')
8
9
  ##
9
10
 
10
11
 
12
+ def attr_property(n: str):
13
+ return property(operator.attrgetter(n))
14
+
15
+
16
+ def item_property(n: str):
17
+ return property(operator.itemgetter(n))
18
+
19
+
20
+ ##
21
+
22
+
11
23
  BUILTIN_METHOD_DESCRIPTORS = (classmethod, staticmethod)
12
24
 
13
25
 
@@ -28,7 +40,7 @@ def unwrap_method_descriptors(fn: ta.Callable) -> ta.Callable:
28
40
  ##
29
41
 
30
42
 
31
- class AccessForbiddenException(Exception):
43
+ class AccessForbiddenError(Exception):
32
44
 
33
45
  def __init__(self, name: str | None = None, *args: ta.Any, **kwargs: ta.Any) -> None:
34
46
  super().__init__(*((name,) if name is not None else ()), *args, **kwargs) # noqa
@@ -42,17 +54,17 @@ class AccessForbiddenDescriptor:
42
54
 
43
55
  self._name = name
44
56
 
45
- def __set_name__(self, owner: ta.Type, name: str) -> None:
57
+ def __set_name__(self, owner: type, name: str) -> None:
46
58
  if self._name is None:
47
59
  self._name = name
48
60
  elif name != self._name:
49
61
  raise NameError(name)
50
62
 
51
63
  def __get__(self, instance, owner=None):
52
- raise AccessForbiddenException(self._name)
64
+ raise AccessForbiddenError(self._name)
53
65
 
54
66
 
55
- def access_forbidden():
67
+ def access_forbidden(): # noqa
56
68
  return AccessForbiddenDescriptor()
57
69
 
58
70
 
omlish/lang/exceptions.py CHANGED
@@ -1,2 +1,2 @@
1
- class Unreachable(Exception):
1
+ class Unreachable(Exception): # noqa
2
2
  pass
omlish/lang/functions.py CHANGED
@@ -7,14 +7,21 @@ from .descriptors import is_method_descriptor
7
7
 
8
8
 
9
9
  T = ta.TypeVar('T')
10
+ P = ta.ParamSpec('P')
10
11
  CallableT = ta.TypeVar('CallableT', bound=ta.Callable)
11
12
 
12
13
 
14
+ ##
15
+
16
+
13
17
  def is_lambda(f: ta.Any) -> bool:
14
18
  l = lambda: 0
15
19
  return isinstance(f, type(l)) and f.__name__ == l.__name__
16
20
 
17
21
 
22
+ ##
23
+
24
+
18
25
  def maybe_call(obj: ta.Any, att: str, *args, default: ta.Any = None, **kwargs) -> ta.Any:
19
26
  try:
20
27
  fn = getattr(obj, att)
@@ -24,6 +31,16 @@ def maybe_call(obj: ta.Any, att: str, *args, default: ta.Any = None, **kwargs) -
24
31
  return fn(*args, **kwargs)
25
32
 
26
33
 
34
+ def recurse(fn: ta.Callable[..., T], *args, **kwargs) -> T:
35
+ def rec(*args, **kwargs) -> T:
36
+ return fn(rec, *args, **kwargs)
37
+
38
+ return rec(*args, **kwargs)
39
+
40
+
41
+ ##
42
+
43
+
27
44
  def unwrap_func(fn: ta.Callable) -> ta.Callable:
28
45
  fn, _ = unwrap_func_with_partials(fn)
29
46
  return fn
@@ -41,38 +58,51 @@ def unwrap_func_with_partials(fn: ta.Callable) -> tuple[ta.Callable, list[functo
41
58
  nxt = getattr(fn, '__wrapped__', None)
42
59
  if not callable(nxt):
43
60
  break
44
- elif nxt is fn:
61
+ if nxt is fn:
45
62
  raise TypeError(fn)
46
63
  fn = nxt
47
64
  return fn, ps
48
65
 
49
66
 
67
+ ##
68
+
69
+
50
70
  def raise_(o: BaseException) -> ta.NoReturn:
51
71
  raise o
52
72
 
53
73
 
74
+ def raising(o: BaseException) -> ta.Callable[..., ta.NoReturn]:
75
+ def inner(*args, **kwargs):
76
+ raise o
77
+ return inner
78
+
79
+
54
80
  def try_(
81
+ fn: ta.Callable[P, T],
55
82
  exc: type[Exception] | ta.Iterable[type[Exception]] = Exception,
56
83
  default: T | None = None,
57
- ) -> ta.Callable[..., T]:
58
- def outer(fn):
59
- def inner(*args, **kwargs):
60
- try:
61
- return fn(*args, **kwargs)
62
- except exct:
63
- return default
64
-
65
- return inner
84
+ ) -> ta.Callable[P, T]:
85
+ def inner(*args, **kwargs):
86
+ try:
87
+ return fn(*args, **kwargs)
88
+ except exct:
89
+ return default
66
90
 
67
91
  exct = (exc,) if isinstance(exc, type) else tuple(exc)
68
- return outer
92
+ return inner
69
93
 
70
94
 
71
- def recurse(fn: ta.Callable[..., T], *args, **kwargs) -> T:
72
- def rec(*args, **kwargs) -> T:
73
- return fn(rec, *args, **kwargs)
95
+ def finally_(fn: ta.Callable[P, T], fin: ta.Callable) -> ta.Callable[P, T]:
96
+ def inner(*args, **kwargs):
97
+ try:
98
+ return fn(*args, **kwargs)
99
+ finally:
100
+ fin()
101
+
102
+ return inner
74
103
 
75
- return rec(*args, **kwargs)
104
+
105
+ ##
76
106
 
77
107
 
78
108
  def identity(obj: T) -> T:
@@ -98,21 +128,24 @@ def is_not_none(o: ta.Any) -> bool:
98
128
  return o is not None
99
129
 
100
130
 
101
- class VoidException(Exception):
131
+ class VoidError(Exception):
102
132
  pass
103
133
 
104
134
 
105
135
  class Void:
106
136
 
107
- def __new__(cls, *args, **kwargs):
108
- raise VoidException
137
+ def __new__(cls, *args: ta.Any, **kwargs: ta.Any) -> None: # type: ignore # noqa
138
+ raise VoidError
139
+
140
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
141
+ raise VoidError
109
142
 
110
- def __init_subclass__(cls, **kwargs):
111
- raise VoidException
112
143
 
144
+ def void(*args: ta.Any, **kwargs: ta.Any) -> ta.NoReturn:
145
+ raise VoidError
113
146
 
114
- def void(*args, **kwargs) -> ta.NoReturn:
115
- raise VoidException
147
+
148
+ ##
116
149
 
117
150
 
118
151
  _MISSING = object()
@@ -142,6 +175,9 @@ def periodically(
142
175
  return inner # type: ignore
143
176
 
144
177
 
178
+ ##
179
+
180
+
145
181
  @dc.dataclass(init=False)
146
182
  class Args:
147
183
  args: ta.Sequence[ta.Any]
omlish/lang/imports.py CHANGED
@@ -1,5 +1,6 @@
1
+ import contextlib
1
2
  import functools
2
- import importlib
3
+ import importlib.resources
3
4
  import sys
4
5
  import types
5
6
  import typing as ta
@@ -17,7 +18,7 @@ def lazy_import(name: str, package: str | None = None) -> ta.Callable[[], ta.Any
17
18
  def proxy_import(name: str, package: str | None = None) -> types.ModuleType:
18
19
  omod = None
19
20
 
20
- def __getattr__(att):
21
+ def __getattr__(att): # noqa
21
22
  nonlocal omod
22
23
  if omod is None:
23
24
  omod = importlib.import_module(name, package=package)
@@ -31,9 +32,6 @@ def proxy_import(name: str, package: str | None = None) -> types.ModuleType:
31
32
  ##
32
33
 
33
34
 
34
- _pkg_resources = lazy_import('pkg_resources')
35
-
36
-
37
35
  def import_module(dotted_path: str) -> types.ModuleType:
38
36
  if not dotted_path:
39
37
  raise ImportError(dotted_path)
@@ -42,7 +40,7 @@ def import_module(dotted_path: str) -> types.ModuleType:
42
40
  try:
43
41
  mod = getattr(mod, name)
44
42
  except AttributeError:
45
- raise AttributeError('Module %r has no attribute %r' % (mod, name))
43
+ raise AttributeError(f'Module {mod!r} has no attribute {name!r}') from None
46
44
  return mod
47
45
 
48
46
 
@@ -52,7 +50,7 @@ def import_module_attr(dotted_path: str) -> ta.Any:
52
50
  try:
53
51
  return getattr(mod, class_name)
54
52
  except AttributeError:
55
- raise AttributeError('Module %r has no attr %r' % (module_name, class_name))
53
+ raise AttributeError(f'Module {module_name!r} has no attr {class_name!r}') from None
56
54
 
57
55
 
58
56
  SPECIAL_IMPORTABLE: ta.AbstractSet[str] = frozenset([
@@ -65,46 +63,43 @@ def yield_importable(
65
63
  package_root: str,
66
64
  *,
67
65
  recursive: bool = False,
68
- filter: ta.Callable[[str], bool] | None = None,
66
+ filter: ta.Callable[[str], bool] | None = None, # noqa
69
67
  include_special: bool = False,
70
68
  ) -> ta.Iterator[str]:
71
- def rec(dir):
72
- if dir.split('.')[-1] == '__pycache__':
69
+ def rec(cur):
70
+ if cur.split('.')[-1] == '__pycache__':
73
71
  return
74
72
 
75
73
  try:
76
- module = sys.modules[dir]
74
+ module = sys.modules[cur]
77
75
  except KeyError:
78
76
  try:
79
- __import__(dir)
77
+ __import__(cur)
80
78
  except ImportError:
81
79
  return
82
- module = sys.modules[dir]
80
+ module = sys.modules[cur]
83
81
 
84
82
  # FIXME: pyox
85
83
  if getattr(module, '__file__', None) is None:
86
84
  return
87
85
 
88
- for file in _pkg_resources().resource_listdir(dir, '.'):
89
- if file.endswith('.py'):
90
- if not (include_special or file not in SPECIAL_IMPORTABLE):
86
+ for file in importlib.resources.files(cur).iterdir():
87
+ if file.is_file() and file.name.endswith('.py'):
88
+ if not (include_special or file.name not in SPECIAL_IMPORTABLE):
91
89
  continue
92
90
 
93
- name = dir + '.' + file[:-3]
91
+ name = cur + '.' + file.name[:-3]
94
92
  if filter is not None and not filter(name):
95
93
  continue
96
94
 
97
95
  yield name
98
96
 
99
- elif recursive and '.' not in file:
100
- name = dir + '.' + file
97
+ elif recursive and file.is_dir():
98
+ name = cur + '.' + file.name
101
99
  if filter is not None and not filter(name):
102
100
  continue
103
-
104
- try:
101
+ with contextlib.suppress(ImportError, NotImplementedError):
105
102
  yield from rec(name)
106
- except (ImportError, NotImplementedError):
107
- pass
108
103
 
109
104
  yield from rec(package_root)
110
105
 
@@ -112,10 +107,10 @@ def yield_importable(
112
107
  def yield_import_all(
113
108
  package_root: str,
114
109
  *,
115
- globals: dict[str, ta.Any] | None = None,
116
- locals: dict[str, ta.Any] | None = None,
110
+ globals: dict[str, ta.Any] | None = None, # noqa
111
+ locals: dict[str, ta.Any] | None = None, # noqa
117
112
  recursive: bool = False,
118
- filter: ta.Callable[[str], bool] | None = None,
113
+ filter: ta.Callable[[str], bool] | None = None, # noqa
119
114
  include_special: bool = False,
120
115
  ) -> ta.Iterator[str]:
121
116
  for import_path in yield_importable(
@@ -132,7 +127,7 @@ def import_all(
132
127
  package_root: str,
133
128
  *,
134
129
  recursive: bool = False,
135
- filter: ta.Callable[[str], bool] | None = None,
130
+ filter: ta.Callable[[str], bool] | None = None, # noqa
136
131
  include_special: bool = False,
137
132
  ) -> None:
138
133
  for _ in yield_import_all(
omlish/lang/iterables.py CHANGED
@@ -28,13 +28,13 @@ def exhaust(it: ta.Iterable[ta.Any]) -> None:
28
28
  pass
29
29
 
30
30
 
31
- def peek(vs: ta.Iterable[T]) -> ta.Tuple[T, ta.Iterator[T]]:
31
+ def peek(vs: ta.Iterable[T]) -> tuple[T, ta.Iterator[T]]:
32
32
  it = iter(vs)
33
33
  v = next(it)
34
34
  return v, itertools.chain(iter((v,)), it)
35
35
 
36
36
 
37
- Rangeable: ta.TypeAlias = int | ta.Tuple[int] | ta.Tuple[int, int] | ta.Iterable[int]
37
+ Rangeable: ta.TypeAlias = int | tuple[int] | tuple[int, int] | ta.Iterable[int]
38
38
 
39
39
 
40
40
  def asrange(i: Rangeable) -> ta.Iterable[int]:
omlish/lang/maybes.py CHANGED
@@ -63,6 +63,7 @@ class Maybe(abc.ABC, ta.Generic[T]):
63
63
 
64
64
 
65
65
  class _Maybe(Maybe[T], tuple):
66
+ __slots__ = ()
66
67
 
67
68
  @property
68
69
  def present(self) -> bool: