omlish 0.0.0.dev1__py3-none-any.whl → 0.0.0.dev2__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 (102) hide show
  1. omlish/__about__.py +2 -2
  2. omlish/argparse.py +4 -4
  3. omlish/asyncs/anyio.py +62 -1
  4. omlish/asyncs/futures.py +6 -6
  5. omlish/c3.py +4 -4
  6. omlish/check.py +6 -6
  7. omlish/collections/__init__.py +98 -63
  8. omlish/collections/cache/descriptor.py +5 -5
  9. omlish/collections/cache/impl.py +4 -4
  10. omlish/collections/coerce.py +43 -43
  11. omlish/collections/frozen.py +3 -3
  12. omlish/collections/identity.py +1 -1
  13. omlish/collections/mappings.py +3 -3
  14. omlish/collections/ordered.py +1 -1
  15. omlish/collections/skiplist.py +6 -6
  16. omlish/collections/sorted.py +3 -3
  17. omlish/collections/treap.py +17 -17
  18. omlish/collections/treapmap.py +2 -2
  19. omlish/collections/unmodifiable.py +28 -27
  20. omlish/configs/flattening.py +1 -1
  21. omlish/configs/props.py +1 -1
  22. omlish/dataclasses/impl/__init__.py +2 -0
  23. omlish/dataclasses/impl/api.py +5 -13
  24. omlish/dataclasses/impl/fields.py +1 -1
  25. omlish/dataclasses/impl/init.py +1 -1
  26. omlish/dataclasses/impl/internals.py +15 -0
  27. omlish/dataclasses/impl/main.py +4 -4
  28. omlish/dataclasses/impl/metaclass.py +1 -1
  29. omlish/dataclasses/impl/metadata.py +1 -1
  30. omlish/dataclasses/impl/order.py +1 -1
  31. omlish/dataclasses/impl/params.py +4 -38
  32. omlish/dataclasses/impl/reflect.py +1 -7
  33. omlish/dataclasses/impl/repr.py +23 -5
  34. omlish/dataclasses/impl/simple.py +2 -2
  35. omlish/dataclasses/impl/slots.py +2 -2
  36. omlish/dataclasses/impl/utils.py +4 -4
  37. omlish/dispatch/dispatch.py +9 -8
  38. omlish/dispatch/methods.py +2 -2
  39. omlish/docker.py +8 -6
  40. omlish/dynamic.py +5 -5
  41. omlish/graphs/dot/items.py +1 -1
  42. omlish/graphs/trees.py +15 -21
  43. omlish/inject/elements.py +1 -1
  44. omlish/inject/exceptions.py +1 -1
  45. omlish/inject/impl/injector.py +1 -1
  46. omlish/inject/impl/inspect.py +1 -1
  47. omlish/inject/injector.py +1 -1
  48. omlish/inject/providers.py +2 -2
  49. omlish/iterators.py +43 -2
  50. omlish/lang/__init__.py +167 -112
  51. omlish/lang/cached.py +13 -5
  52. omlish/lang/classes/__init__.py +35 -24
  53. omlish/lang/classes/abstract.py +1 -1
  54. omlish/lang/classes/simple.py +1 -1
  55. omlish/lang/clsdct.py +1 -1
  56. omlish/lang/contextmanagers.py +23 -15
  57. omlish/lang/datetimes.py +1 -1
  58. omlish/lang/descriptors.py +35 -2
  59. omlish/lang/exceptions.py +2 -0
  60. omlish/lang/functions.py +43 -13
  61. omlish/lang/imports.py +8 -8
  62. omlish/lang/iterables.py +1 -1
  63. omlish/lang/maybes.py +1 -1
  64. omlish/lang/objects.py +2 -2
  65. omlish/lang/timeouts.py +53 -0
  66. omlish/lang/typing.py +2 -2
  67. omlish/libc.py +6 -6
  68. omlish/marshal/base.py +6 -6
  69. omlish/marshal/dataclasses.py +2 -2
  70. omlish/marshal/enums.py +2 -2
  71. omlish/marshal/factories.py +10 -10
  72. omlish/marshal/iterables.py +2 -2
  73. omlish/marshal/mappings.py +2 -2
  74. omlish/marshal/optionals.py +4 -4
  75. omlish/marshal/polymorphism.py +4 -4
  76. omlish/marshal/standard.py +6 -6
  77. omlish/marshal/utils.py +1 -1
  78. omlish/os.py +13 -4
  79. omlish/procfs.py +336 -0
  80. omlish/reflect.py +2 -12
  81. omlish/replserver/console.py +9 -9
  82. omlish/replserver/server.py +4 -4
  83. omlish/sql/__init__.py +0 -0
  84. omlish/sql/_abcs.py +65 -0
  85. omlish/sql/dbs.py +90 -0
  86. omlish/stats.py +3 -3
  87. omlish/testing/pydevd.py +4 -6
  88. omlish/testing/pytest/inject/__init__.py +7 -0
  89. omlish/testing/pytest/inject/harness.py +23 -1
  90. omlish/testing/pytest/plugins/__init__.py +1 -1
  91. omlish/testing/pytest/plugins/pydevd.py +12 -0
  92. omlish/testing/pytest/plugins/switches.py +2 -2
  93. omlish/testing/testing.py +5 -5
  94. omlish/text/parts.py +3 -3
  95. omlish-0.0.0.dev2.dist-info/METADATA +31 -0
  96. omlish-0.0.0.dev2.dist-info/RECORD +193 -0
  97. {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev2.dist-info}/WHEEL +1 -1
  98. omlish/testing/pytest/plugins/pycharm.py +0 -54
  99. omlish-0.0.0.dev1.dist-info/METADATA +0 -17
  100. omlish-0.0.0.dev1.dist-info/RECORD +0 -187
  101. {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev2.dist-info}/LICENSE +0 -0
  102. {omlish-0.0.0.dev1.dist-info → omlish-0.0.0.dev2.dist-info}/top_level.txt +0 -0
omlish/lang/functions.py CHANGED
@@ -1,3 +1,4 @@
1
+ import dataclasses as dc
1
2
  import functools
2
3
  import time
3
4
  import typing as ta
@@ -6,6 +7,7 @@ from .descriptors import is_method_descriptor
6
7
 
7
8
 
8
9
  T = ta.TypeVar('T')
10
+ CallableT = ta.TypeVar('CallableT', bound=ta.Callable)
9
11
 
10
12
 
11
13
  def is_lambda(f: ta.Any) -> bool:
@@ -50,8 +52,8 @@ def raise_(o: BaseException) -> ta.NoReturn:
50
52
 
51
53
 
52
54
  def try_(
53
- exc: ta.Union[type[Exception], ta.Iterable[type[Exception]]] = Exception,
54
- default: ta.Optional[T] = None,
55
+ exc: type[Exception] | ta.Iterable[type[Exception]] = Exception,
56
+ default: T | None = None,
55
57
  ) -> ta.Callable[..., T]:
56
58
  def outer(fn):
57
59
  def inner(*args, **kwargs):
@@ -113,14 +115,42 @@ def void(*args, **kwargs) -> ta.NoReturn:
113
115
  raise VoidException
114
116
 
115
117
 
116
- def ticking_timeout(
117
- s: int | float | None,
118
- ex: type[BaseException] | BaseException = TimeoutError,
119
- ) -> ta.Callable[[], None]:
120
- if s is None:
121
- return lambda: None
122
- def tick(): # noqa
123
- if time.time() >= deadline:
124
- raise ex
125
- deadline = time.time() + s
126
- return tick
118
+ _MISSING = object()
119
+
120
+
121
+ def periodically(
122
+ fn: CallableT,
123
+ interval_s: float,
124
+ initial: ta.Any = _MISSING,
125
+ *,
126
+ include_runtime: bool = False,
127
+ ) -> CallableT:
128
+ nxt = time.time() + interval_s
129
+ ret = initial
130
+
131
+ @functools.wraps(fn)
132
+ def inner(*args, **kwargs):
133
+ nonlocal nxt, ret
134
+ if time.time() >= nxt or ret is _MISSING:
135
+ if include_runtime:
136
+ nxt = time.time() + interval_s
137
+ ret = fn(*args, **kwargs)
138
+ if not include_runtime:
139
+ nxt = time.time() + interval_s
140
+ return ret
141
+
142
+ return inner # type: ignore
143
+
144
+
145
+ @dc.dataclass(init=False)
146
+ class Args:
147
+ args: ta.Sequence[ta.Any]
148
+ kwargs: ta.Mapping[str, ta.Any]
149
+
150
+ def __init__(self, *args: ta.Any, **kwargs: ta.Any) -> None:
151
+ super().__init__()
152
+ self.args = args
153
+ self.kwargs = kwargs
154
+
155
+ def __call__(self, fn: ta.Callable[..., T]) -> T:
156
+ return fn(*self.args, **self.kwargs)
omlish/lang/imports.py CHANGED
@@ -10,11 +10,11 @@ from .cached import cached_function
10
10
  ##
11
11
 
12
12
 
13
- def lazy_import(name: str, package: ta.Optional[str] = None) -> ta.Callable[[], ta.Any]:
13
+ def lazy_import(name: str, package: str | None = None) -> ta.Callable[[], ta.Any]:
14
14
  return cached_function(functools.partial(importlib.import_module, name, package=package))
15
15
 
16
16
 
17
- def proxy_import(name: str, package: ta.Optional[str] = None) -> types.ModuleType:
17
+ def proxy_import(name: str, package: str | None = None) -> types.ModuleType:
18
18
  omod = None
19
19
 
20
20
  def __getattr__(att):
@@ -65,7 +65,7 @@ def yield_importable(
65
65
  package_root: str,
66
66
  *,
67
67
  recursive: bool = False,
68
- filter: ta.Optional[ta.Callable[[str], bool]] = None,
68
+ filter: ta.Callable[[str], bool] | None = None,
69
69
  include_special: bool = False,
70
70
  ) -> ta.Iterator[str]:
71
71
  def rec(dir):
@@ -112,10 +112,10 @@ def yield_importable(
112
112
  def yield_import_all(
113
113
  package_root: str,
114
114
  *,
115
- globals: ta.Optional[dict[str, ta.Any]] = None,
116
- locals: ta.Optional[dict[str, ta.Any]] = None,
115
+ globals: dict[str, ta.Any] | None = None,
116
+ locals: dict[str, ta.Any] | None = None,
117
117
  recursive: bool = False,
118
- filter: ta.Optional[ta.Callable[[str], bool]] = None,
118
+ filter: ta.Callable[[str], bool] | None = None,
119
119
  include_special: bool = False,
120
120
  ) -> ta.Iterator[str]:
121
121
  for import_path in yield_importable(
@@ -132,7 +132,7 @@ def import_all(
132
132
  package_root: str,
133
133
  *,
134
134
  recursive: bool = False,
135
- filter: ta.Optional[ta.Callable[[str], bool]] = None,
135
+ filter: ta.Callable[[str], bool] | None = None,
136
136
  include_special: bool = False,
137
137
  ) -> None:
138
138
  for _ in yield_import_all(
@@ -144,7 +144,7 @@ def import_all(
144
144
  pass
145
145
 
146
146
 
147
- def try_import(spec: str) -> ta.Optional[types.ModuleType]:
147
+ def try_import(spec: str) -> types.ModuleType | None:
148
148
  s = spec.lstrip('.')
149
149
  l = len(spec) - len(s)
150
150
  try:
omlish/lang/iterables.py CHANGED
@@ -34,7 +34,7 @@ def peek(vs: ta.Iterable[T]) -> ta.Tuple[T, ta.Iterator[T]]:
34
34
  return v, itertools.chain(iter((v,)), it)
35
35
 
36
36
 
37
- Rangeable: ta.TypeAlias = ta.Union[int, ta.Tuple[int], ta.Tuple[int, int], ta.Iterable[int]]
37
+ Rangeable: ta.TypeAlias = int | ta.Tuple[int] | ta.Tuple[int, int] | ta.Iterable[int]
38
38
 
39
39
 
40
40
  def asrange(i: Rangeable) -> ta.Iterable[int]:
omlish/lang/maybes.py CHANGED
@@ -130,7 +130,7 @@ def empty() -> Maybe[T]:
130
130
  return _empty # noqa
131
131
 
132
132
 
133
- def maybe(o: ta.Optional[T]) -> Maybe[T]:
133
+ def maybe(o: T | None) -> Maybe[T]:
134
134
  if o is None:
135
135
  return _empty # noqa
136
136
  return just(o)
omlish/lang/objects.py CHANGED
@@ -28,7 +28,7 @@ def new_type(
28
28
  name: str,
29
29
  bases: ta.Sequence[ta.Any],
30
30
  namespace: ta.Mapping[str, ta.Any],
31
- **kwargs
31
+ **kwargs,
32
32
  ) -> ta.Type:
33
33
  return types.new_class(
34
34
  name,
@@ -44,7 +44,7 @@ def super_meta(
44
44
  name: str,
45
45
  bases: ta.Sequence[ta.Any],
46
46
  namespace: ta.MutableMapping[str, ta.Any],
47
- **kwargs
47
+ **kwargs,
48
48
  ) -> ta.Type:
49
49
  """Per types.new_class"""
50
50
  resolved_bases = types.resolve_bases(bases)
@@ -0,0 +1,53 @@
1
+ import abc
2
+ import time
3
+ import typing as ta
4
+
5
+
6
+ TimeoutLike: ta.TypeAlias = ta.Union['Timeout', float]
7
+
8
+
9
+ class Timeout(abc.ABC):
10
+ @abc.abstractmethod
11
+ def __call__(self) -> float:
12
+ raise NotImplementedError
13
+
14
+ @abc.abstractmethod
15
+ def or_(self, o: ta.Any) -> ta.Any:
16
+ raise NotImplementedError
17
+
18
+
19
+ class DeadlineTimeout(Timeout):
20
+ def __init__(
21
+ self,
22
+ deadline: float,
23
+ exc: type[BaseException] | BaseException = TimeoutError,
24
+ ) -> None:
25
+ super().__init__()
26
+ self.deadline = deadline
27
+ self.exc = exc
28
+
29
+ def __call__(self) -> float:
30
+ if (rem := self.deadline - time.time()) > 0:
31
+ return rem
32
+ raise self.exc
33
+
34
+ def or_(self, o: ta.Any) -> ta.Any:
35
+ return self()
36
+
37
+
38
+ class InfiniteTimeout(Timeout):
39
+ def __call__(self) -> float:
40
+ return float('inf')
41
+
42
+ def or_(self, o: ta.Any) -> ta.Any:
43
+ return o
44
+
45
+
46
+ def timeout(t: TimeoutLike | None) -> Timeout:
47
+ if t is None:
48
+ return InfiniteTimeout()
49
+ if isinstance(t, Timeout):
50
+ return t
51
+ if isinstance(t, (float, int)):
52
+ return DeadlineTimeout(time.time() + t)
53
+ raise TypeError(t)
omlish/lang/typing.py CHANGED
@@ -12,7 +12,7 @@ import typing as ta
12
12
  Ty = ta.TypeVar('Ty', bound=type)
13
13
 
14
14
 
15
- BytesLike: ta.TypeAlias = ta.Union[bytes, bytearray]
15
+ BytesLike: ta.TypeAlias = bytes | bytearray
16
16
 
17
17
 
18
18
  ##
@@ -87,6 +87,6 @@ def typed_partial(obj, **kw):
87
87
  for n, p in sig.parameters.items()
88
88
  if n not in kw
89
89
  and p.annotation is not inspect.Signature.empty
90
- }
90
+ },
91
91
  )(inner)
92
92
  return _update_wrapper_no_anns(lam, obj)
omlish/libc.py CHANGED
@@ -94,7 +94,7 @@ libc.mmap.argtypes = [
94
94
  ct.c_int,
95
95
  ct.c_int,
96
96
  ct.c_int,
97
- ct.c_size_t
97
+ ct.c_size_t,
98
98
  ]
99
99
  mmap = libc.mmap
100
100
 
@@ -138,7 +138,7 @@ elif DARWIN:
138
138
  libc.munmap.restype = ct.c_int
139
139
  libc.munmap.argtypes = [
140
140
  ct.c_void_p,
141
- ct.c_size_t
141
+ ct.c_size_t,
142
142
  ]
143
143
  munmap = libc.munmap
144
144
 
@@ -148,7 +148,7 @@ libc.mprotect.restype = ct.c_int
148
148
  libc.mprotect.argtypes = [
149
149
  ct.c_void_p,
150
150
  ct.c_size_t,
151
- ct.c_int
151
+ ct.c_int,
152
152
  ]
153
153
  mprotect = libc.mprotect
154
154
 
@@ -164,7 +164,7 @@ if LINUX:
164
164
  ct.c_void_p,
165
165
  ct.c_size_t,
166
166
  ct.c_size_t,
167
- ct.c_int
167
+ ct.c_int,
168
168
  ]
169
169
  mremap = libc.mremap
170
170
 
@@ -179,7 +179,7 @@ class Mmap:
179
179
  length: int,
180
180
  *,
181
181
  prot: int = PROT_READ | PROT_WRITE,
182
- flags: ta.Optional[int] = None,
182
+ flags: int | None = None,
183
183
  fd: int = -1,
184
184
  offset: int = 0,
185
185
  desired_base: int = 0,
@@ -205,7 +205,7 @@ class Mmap:
205
205
  self._is_mapped = False
206
206
 
207
207
  @property
208
- def base(self) -> ta.Optional[int]:
208
+ def base(self) -> int | None:
209
209
  return self._base
210
210
 
211
211
  def __enter__(self) -> 'Mmap':
omlish/marshal/base.py CHANGED
@@ -146,7 +146,7 @@ class BaseContext(lang.Abstract):
146
146
 
147
147
  @dc.dataclass(frozen=True)
148
148
  class MarshalContext(BaseContext, lang.Final):
149
- factory: ta.Optional[MarshalerFactory] = None
149
+ factory: MarshalerFactory | None = None
150
150
 
151
151
  def make(self, o: ta.Any) -> Marshaler:
152
152
  rty = rfl.type_(o)
@@ -157,7 +157,7 @@ class MarshalContext(BaseContext, lang.Final):
157
157
 
158
158
  @dc.dataclass(frozen=True)
159
159
  class UnmarshalContext(BaseContext, lang.Final):
160
- factory: ta.Optional[UnmarshalerFactory] = None
160
+ factory: UnmarshalerFactory | None = None
161
161
 
162
162
  def make(self, o: ta.Any) -> Unmarshaler:
163
163
  rty = rfl.type_(o)
@@ -194,8 +194,8 @@ class RecursiveUnmarshalerFactory(RecursiveTypeFactory[Unmarshaler, UnmarshalCon
194
194
 
195
195
  @dc.dataclass(frozen=True)
196
196
  class SetType(RegistryItem, lang.Final):
197
- marshaler: ta.Optional[Marshaler] = None
198
- marshaler_factory: ta.Optional[MarshalerFactory] = None
197
+ marshaler: Marshaler | None = None
198
+ marshaler_factory: MarshalerFactory | None = None
199
199
 
200
- unmarshaler: ta.Optional[Unmarshaler] = None
201
- unmarshaler_factory: ta.Optional[UnmarshalerFactory] = None
200
+ unmarshaler: Unmarshaler | None = None
201
+ unmarshaler_factory: UnmarshalerFactory | None = None
@@ -79,7 +79,7 @@ def _make_field_obj(ctx, ty, obj, fac):
79
79
 
80
80
 
81
81
  class DataclassMarshalerFactory(MarshalerFactory):
82
- def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Optional[Marshaler]:
82
+ def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler | None:
83
83
  if isinstance(rty, type) and dc.is_dataclass(rty):
84
84
  dc_md = get_dataclass_metadata(rty)
85
85
  fields = [
@@ -97,7 +97,7 @@ class DataclassMarshalerFactory(MarshalerFactory):
97
97
 
98
98
 
99
99
  class DataclassUnmarshalerFactory(UnmarshalerFactory):
100
- def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Optional[Unmarshaler]:
100
+ def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler | None:
101
101
  if isinstance(rty, type) and dc.is_dataclass(rty):
102
102
  dc_md = get_dataclass_metadata(rty)
103
103
  d: dict[str, tuple[FieldInfo, Unmarshaler]] = {}
omlish/marshal/enums.py CHANGED
@@ -22,7 +22,7 @@ class EnumMarshaler(Marshaler):
22
22
 
23
23
 
24
24
  class EnumMarshalerFactory(MarshalerFactory):
25
- def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Optional[Marshaler]:
25
+ def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler | None:
26
26
  if isinstance(rty, type) and issubclass(rty, enum.Enum):
27
27
  return EnumMarshaler(rty)
28
28
  return None
@@ -37,7 +37,7 @@ class EnumUnmarshaler(Unmarshaler):
37
37
 
38
38
 
39
39
  class EnumUnmarshalerFactory(UnmarshalerFactory):
40
- def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Optional[Unmarshaler]:
40
+ def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler | None:
41
41
  if isinstance(rty, type) and issubclass(rty, enum.Enum):
42
42
  return EnumUnmarshaler(rty)
43
43
  return None
@@ -17,7 +17,7 @@ A = ta.TypeVar('A')
17
17
 
18
18
  class Factory(abc.ABC, ta.Generic[R, C, A]):
19
19
  @abc.abstractmethod
20
- def __call__(self, ctx: C, arg: A) -> ta.Optional[R]:
20
+ def __call__(self, ctx: C, arg: A) -> R | None:
21
21
  raise NotImplementedError
22
22
 
23
23
 
@@ -26,9 +26,9 @@ class Factory(abc.ABC, ta.Generic[R, C, A]):
26
26
 
27
27
  @dc.dataclass(frozen=True)
28
28
  class FuncFactory(ta.Generic[R, C, A]):
29
- fn: ta.Callable[[C, A], ta.Optional[R]]
29
+ fn: ta.Callable[[C, A], R | None]
30
30
 
31
- def __call__(self, ctx: C, arg: A) -> ta.Optional[R]:
31
+ def __call__(self, ctx: C, arg: A) -> R | None:
32
32
  return self.fn(ctx, arg)
33
33
 
34
34
 
@@ -39,7 +39,7 @@ class FuncFactory(ta.Generic[R, C, A]):
39
39
  class TypeMapFactory(Factory[R, C, rfl.Type]):
40
40
  m: ta.Mapping[rfl.Type, R] = dc.field(default_factory=dict)
41
41
 
42
- def __call__(self, ctx: C, rty: rfl.Type) -> ta.Optional[R]:
42
+ def __call__(self, ctx: C, rty: rfl.Type) -> R | None:
43
43
  return self.m.get(rty)
44
44
 
45
45
 
@@ -50,10 +50,10 @@ class TypeCacheFactory(Factory[R, C, rfl.Type]):
50
50
  def __init__(self, f: Factory[R, C, rfl.Type]) -> None:
51
51
  super().__init__()
52
52
  self._f = f
53
- self._dct: dict[rfl.Type, ta.Optional[R]] = {}
53
+ self._dct: dict[rfl.Type, R | None] = {}
54
54
  self._mtx = threading.RLock()
55
55
 
56
- def __call__(self, ctx: C, rty: rfl.Type) -> ta.Optional[R]:
56
+ def __call__(self, ctx: C, rty: rfl.Type) -> R | None:
57
57
  try:
58
58
  return self._dct[rty]
59
59
  except KeyError:
@@ -73,14 +73,14 @@ class RecursiveTypeFactory(Factory[R, C, rfl.Type]):
73
73
  def __init__(
74
74
  self,
75
75
  f: Factory[R, C, rfl.Type],
76
- prx: ta.Callable[[], tuple[ta.Optional[R], ta.Callable[[ta.Optional[R]], None]]],
76
+ prx: ta.Callable[[], tuple[R | None, ta.Callable[[R | None], None]]],
77
77
  ) -> None:
78
78
  super().__init__()
79
79
  self._f = f
80
80
  self._prx = prx
81
- self._dct: dict[rfl.Type, ta.Optional[R]] = {}
81
+ self._dct: dict[rfl.Type, R | None] = {}
82
82
 
83
- def __call__(self, ctx: C, rty: rfl.Type) -> ta.Optional[R]:
83
+ def __call__(self, ctx: C, rty: rfl.Type) -> R | None:
84
84
  try:
85
85
  return self._dct[rty]
86
86
  except KeyError:
@@ -108,7 +108,7 @@ class CompositeFactory(Factory[R, C, A]):
108
108
  self._fs = fs
109
109
  self._st = strategy
110
110
 
111
- def __call__(self, ctx: C, arg: A) -> ta.Optional[R]:
111
+ def __call__(self, ctx: C, arg: A) -> R | None:
112
112
  w: list[R] = []
113
113
  for c in self._fs:
114
114
  if (r := c(ctx, arg)) is None:
@@ -23,7 +23,7 @@ class IterableMarshaler(Marshaler):
23
23
 
24
24
 
25
25
  class IterableMarshalerFactory(MarshalerFactory):
26
- def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Optional[Marshaler]:
26
+ def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler | None:
27
27
  if isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Iterable):
28
28
  if (e := ctx.make(check.single(rty.args))) is None:
29
29
  return None # type: ignore
@@ -45,7 +45,7 @@ class IterableUnmarshaler(Unmarshaler):
45
45
 
46
46
 
47
47
  class IterableUnmarshalerFactory(UnmarshalerFactory):
48
- def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Optional[Unmarshaler]:
48
+ def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler | None:
49
49
  if isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Iterable):
50
50
  if (e := ctx.make(check.single(rty.args))) is None:
51
51
  return None # type: ignore
@@ -26,7 +26,7 @@ class MappingMarshaler(Marshaler):
26
26
 
27
27
 
28
28
  class MappingMarshalerFactory(MarshalerFactory):
29
- def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Optional[Marshaler]:
29
+ def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler | None:
30
30
  if isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Mapping):
31
31
  kt, vt = rty.args
32
32
  if (ke := ctx.make(kt)) is None or (ve := ctx.make(vt)) is None:
@@ -53,7 +53,7 @@ class MappingUnmarshaler(Unmarshaler):
53
53
 
54
54
 
55
55
  class MappingUnmarshalerFactory(UnmarshalerFactory):
56
- def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Optional[Unmarshaler]:
56
+ def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler | None:
57
57
  if isinstance(rty, rfl.Generic) and issubclass(rty.cls, collections.abc.Mapping):
58
58
  kt, vt = rty.args
59
59
  if (ke := ctx.make(kt)) is None or (ve := ctx.make(vt)) is None:
@@ -15,14 +15,14 @@ from .values import Value
15
15
  class OptionalMarshaler(Marshaler):
16
16
  e: Marshaler
17
17
 
18
- def marshal(self, ctx: MarshalContext, o: ta.Optional[ta.Any]) -> Value:
18
+ def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
19
19
  if o is None:
20
20
  return None
21
21
  return self.e.marshal(ctx, o)
22
22
 
23
23
 
24
24
  class OptionalMarshalerFactory(MarshalerFactory):
25
- def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Optional[Marshaler]:
25
+ def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler | None:
26
26
  if isinstance(rty, rfl.Union) and rty.is_optional:
27
27
  if (e := ctx.make(rty.without_none())) is None:
28
28
  return None # type: ignore
@@ -34,14 +34,14 @@ class OptionalMarshalerFactory(MarshalerFactory):
34
34
  class OptionalUnmarshaler(Unmarshaler):
35
35
  e: Unmarshaler
36
36
 
37
- def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Optional[ta.Any]:
37
+ def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
38
38
  if v is None:
39
39
  return None
40
40
  return self.e.unmarshal(ctx, v)
41
41
 
42
42
 
43
43
  class OptionalUnmarshalerFactory(UnmarshalerFactory):
44
- def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Optional[Unmarshaler]:
44
+ def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler | None:
45
45
  if isinstance(rty, rfl.Union) and rty.is_optional:
46
46
  if (e := ctx.make(rty.without_none())) is None:
47
47
  return None # type: ignore
@@ -100,7 +100,7 @@ def polymorphism_from_subclasses(ty: type, *, naming: Naming | None = None) -> P
100
100
  class PolymorphismMarshaler(Marshaler):
101
101
  m: ta.Mapping[type, tuple[str, Marshaler]]
102
102
 
103
- def marshal(self, ctx: MarshalContext, o: ta.Optional[ta.Any]) -> Value:
103
+ def marshal(self, ctx: MarshalContext, o: ta.Any | None) -> Value:
104
104
  tag, m = self.m[type(o)]
105
105
  return {tag: m.marshal(ctx, o)}
106
106
 
@@ -109,7 +109,7 @@ class PolymorphismMarshaler(Marshaler):
109
109
  class PolymorphismMarshalerFactory(MarshalerFactory):
110
110
  p: Polymorphism
111
111
 
112
- def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> ta.Optional[Marshaler]:
112
+ def __call__(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler | None:
113
113
  if rty is self.p.ty:
114
114
  return PolymorphismMarshaler({
115
115
  i.ty: (i.tag, ctx.make(i.ty))
@@ -125,7 +125,7 @@ class PolymorphismMarshalerFactory(MarshalerFactory):
125
125
  class PolymorphismUnmarshaler(Unmarshaler):
126
126
  m: ta.Mapping[str, Unmarshaler]
127
127
 
128
- def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Optional[ta.Any]:
128
+ def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
129
129
  ma = check.isinstance(v, collections.abc.Mapping)
130
130
  [(tag, iv)] = ma.items()
131
131
  u = self.m[tag] # type: ignore
@@ -136,7 +136,7 @@ class PolymorphismUnmarshaler(Unmarshaler):
136
136
  class PolymorphismUnmarshalerFactory(UnmarshalerFactory):
137
137
  p: Polymorphism
138
138
 
139
- def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> ta.Optional[Unmarshaler]:
139
+ def __call__(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler | None:
140
140
  if rty is self.p.ty:
141
141
  return PolymorphismUnmarshaler({
142
142
  t: u
@@ -47,9 +47,9 @@ def new_standard_marshaler_factory() -> MarshalerFactory:
47
47
  return TypeCacheFactory( # noqa
48
48
  RecursiveMarshalerFactory(
49
49
  CompositeFactory(
50
- *STANDARD_MARSHALER_FACTORIES
51
- )
52
- )
50
+ *STANDARD_MARSHALER_FACTORIES,
51
+ ),
52
+ ),
53
53
  )
54
54
 
55
55
 
@@ -74,7 +74,7 @@ def new_standard_unmarshaler_factory() -> UnmarshalerFactory:
74
74
  return TypeCacheFactory( # noqa
75
75
  RecursiveUnmarshalerFactory(
76
76
  CompositeFactory(
77
- *STANDARD_UNMARSHALER_FACTORIES
78
- )
79
- )
77
+ *STANDARD_UNMARSHALER_FACTORIES,
78
+ ),
79
+ ),
80
80
  )
omlish/marshal/utils.py CHANGED
@@ -5,7 +5,7 @@ T = ta.TypeVar('T')
5
5
 
6
6
 
7
7
  class _Proxy(ta.Generic[T]):
8
- __obj: ta.Optional[T] = None
8
+ __obj: T | None = None
9
9
 
10
10
  @property
11
11
  def _obj(self) -> T:
omlish/os.py CHANGED
@@ -1,14 +1,23 @@
1
1
  import contextlib
2
+ import resource
2
3
  import shutil
3
4
  import tempfile
4
5
  import typing as ta
5
6
 
6
7
 
8
+ PAGE_SIZE = resource.getpagesize()
9
+
10
+
11
+ def round_to_page_size(sz: int) -> int:
12
+ sz += PAGE_SIZE - 1
13
+ return sz - (sz % PAGE_SIZE)
14
+
15
+
7
16
  @contextlib.contextmanager
8
17
  def tmp_dir(
9
- root_dir: ta.Optional[str] = None,
18
+ root_dir: str | None = None,
10
19
  cleanup: bool = True,
11
- **kwargs: ta.Any
20
+ **kwargs: ta.Any,
12
21
  ) -> ta.Iterator[str]:
13
22
  path = tempfile.mkdtemp(dir=root_dir, **kwargs)
14
23
  try:
@@ -20,9 +29,9 @@ def tmp_dir(
20
29
 
21
30
  @contextlib.contextmanager
22
31
  def tmp_file(
23
- root_dir: ta.Optional[str] = None,
32
+ root_dir: str | None = None,
24
33
  cleanup: bool = True,
25
- **kwargs: ta.Any
34
+ **kwargs: ta.Any,
26
35
  ) -> ta.Iterator[tempfile._TemporaryFileWrapper]: # noqa
27
36
  with tempfile.NamedTemporaryFile(dir=root_dir, delete=False, **kwargs) as f:
28
37
  try: