omdev 0.0.0.dev315__py3-none-any.whl → 0.0.0.dev316__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.
omdev/scripts/ci.py CHANGED
@@ -41,6 +41,7 @@ import gzip
41
41
  import hashlib
42
42
  import heapq
43
43
  import html
44
+ import http
44
45
  import http.client
45
46
  import http.server
46
47
  import inspect
@@ -98,6 +99,9 @@ CheckOnRaiseFn = ta.Callable[[Exception], None] # ta.TypeAlias
98
99
  CheckExceptionFactory = ta.Callable[..., Exception] # ta.TypeAlias
99
100
  CheckArgsRenderer = ta.Callable[..., ta.Optional[str]] # ta.TypeAlias
100
101
 
102
+ # ../../omlish/lite/maybes.py
103
+ U = ta.TypeVar('U')
104
+
101
105
  # ../../omlish/lite/timeouts.py
102
106
  TimeoutLike = ta.Union['Timeout', ta.Type['Timeout.DEFAULT'], ta.Iterable['TimeoutLike'], float, None] # ta.TypeAlias
103
107
 
@@ -122,7 +126,6 @@ ExitStackedT = ta.TypeVar('ExitStackedT', bound='ExitStacked')
122
126
  AsyncExitStackedT = ta.TypeVar('AsyncExitStackedT', bound='AsyncExitStacked')
123
127
 
124
128
  # ../../omlish/lite/inject.py
125
- U = ta.TypeVar('U')
126
129
  InjectorKeyCls = ta.Union[type, ta.NewType]
127
130
  InjectorProviderFn = ta.Callable[['Injector'], ta.Any]
128
131
  InjectorProviderFnMap = ta.Mapping['InjectorKey', 'InjectorProviderFn']
@@ -1145,7 +1148,13 @@ log = logging.getLogger(__name__)
1145
1148
  ##
1146
1149
 
1147
1150
 
1151
+ @functools.total_ordering
1148
1152
  class Maybe(ta.Generic[T]):
1153
+ class ValueNotPresentError(BaseException):
1154
+ pass
1155
+
1156
+ #
1157
+
1149
1158
  @property
1150
1159
  @abc.abstractmethod
1151
1160
  def present(self) -> bool:
@@ -1155,9 +1164,102 @@ class Maybe(ta.Generic[T]):
1155
1164
  def must(self) -> T:
1156
1165
  raise NotImplementedError
1157
1166
 
1167
+ #
1168
+
1169
+ @abc.abstractmethod
1170
+ def __repr__(self) -> str:
1171
+ raise NotImplementedError
1172
+
1173
+ @abc.abstractmethod
1174
+ def __hash__(self) -> int:
1175
+ raise NotImplementedError
1176
+
1177
+ @abc.abstractmethod
1178
+ def __eq__(self, other) -> bool:
1179
+ raise NotImplementedError
1180
+
1181
+ @abc.abstractmethod
1182
+ def __lt__(self, other) -> bool:
1183
+ raise NotImplementedError
1184
+
1185
+ #
1186
+
1187
+ @ta.final
1188
+ def __ne__(self, other):
1189
+ return not (self == other)
1190
+
1191
+ @ta.final
1192
+ def __iter__(self) -> ta.Iterator[T]:
1193
+ if self.present:
1194
+ yield self.must()
1195
+
1196
+ @ta.final
1197
+ def __bool__(self) -> ta.NoReturn:
1198
+ raise TypeError
1199
+
1200
+ #
1201
+
1202
+ @ta.final
1203
+ def if_present(self, consumer: ta.Callable[[T], None]) -> None:
1204
+ if self.present:
1205
+ consumer(self.must())
1206
+
1207
+ @ta.final
1208
+ def filter(self, predicate: ta.Callable[[T], bool]) -> 'Maybe[T]':
1209
+ if self.present and predicate(self.must()):
1210
+ return self
1211
+ else:
1212
+ return Maybe.empty()
1213
+
1214
+ @ta.final
1215
+ def map(self, mapper: ta.Callable[[T], U]) -> 'Maybe[U]':
1216
+ if self.present:
1217
+ return Maybe.just(mapper(self.must()))
1218
+ else:
1219
+ return Maybe.empty()
1220
+
1221
+ @ta.final
1222
+ def flat_map(self, mapper: ta.Callable[[T], 'Maybe[U]']) -> 'Maybe[U]':
1223
+ if self.present:
1224
+ if not isinstance(v := mapper(self.must()), Maybe):
1225
+ raise TypeError(v)
1226
+ return v
1227
+ else:
1228
+ return Maybe.empty()
1229
+
1230
+ @ta.final
1231
+ def or_else(self, other: ta.Union[T, U]) -> ta.Union[T, U]:
1232
+ if self.present:
1233
+ return self.must()
1234
+ else:
1235
+ return other
1236
+
1237
+ @ta.final
1238
+ def or_else_get(self, supplier: ta.Callable[[], ta.Union[T, U]]) -> ta.Union[T, U]:
1239
+ if self.present:
1240
+ return self.must()
1241
+ else:
1242
+ return supplier()
1243
+
1244
+ @ta.final
1245
+ def or_else_raise(self, exception_supplier: ta.Callable[[], Exception]) -> T:
1246
+ if self.present:
1247
+ return self.must()
1248
+ else:
1249
+ raise exception_supplier()
1250
+
1251
+ #
1252
+
1253
+ @classmethod
1254
+ def of_optional(cls, v: ta.Optional[T]) -> 'Maybe[T]':
1255
+ if v is not None:
1256
+ return cls.just(v)
1257
+ else:
1258
+ return cls.empty()
1259
+
1158
1260
  @classmethod
1159
1261
  def just(cls, v: T) -> 'Maybe[T]':
1160
- return tuple.__new__(_Maybe, (v,)) # noqa
1262
+ return _JustMaybe(v)
1161
1263
 
1162
1264
  _empty: ta.ClassVar['Maybe']
1163
1265
 
@@ -1166,36 +1268,79 @@ class Maybe(ta.Generic[T]):
1166
1268
  return Maybe._empty
1167
1269
 
1168
1270
 
1169
- class _Maybe(Maybe[T], tuple):
1170
- __slots__ = ()
1271
+ ##
1171
1272
 
1172
- def __init_subclass__(cls, **kwargs):
1173
- raise TypeError
1273
+
1274
+ class _Maybe(Maybe[T], abc.ABC):
1275
+ def __lt__(self, other):
1276
+ if not isinstance(other, _Maybe):
1277
+ return NotImplemented
1278
+ sp = self.present
1279
+ op = other.present
1280
+ if self.present and other.present:
1281
+ return self.must() < other.must()
1282
+ else:
1283
+ return op and not sp
1284
+
1285
+
1286
+ class _JustMaybe(_Maybe[T]):
1287
+ __slots__ = ('_v', '_hash')
1288
+
1289
+ def __init__(self, v: T) -> None:
1290
+ super().__init__()
1291
+
1292
+ self._v = v
1174
1293
 
1175
1294
  @property
1176
1295
  def present(self) -> bool:
1177
- return bool(self)
1296
+ return True
1178
1297
 
1179
1298
  def must(self) -> T:
1180
- if not self:
1181
- raise ValueError
1182
- return self[0]
1299
+ return self._v
1300
+
1301
+ #
1302
+
1303
+ def __repr__(self) -> str:
1304
+ return f'just({self._v!r})'
1305
+
1306
+ def __hash__(self) -> int:
1307
+ try:
1308
+ return self._hash # type: ignore[has-type]
1309
+ except AttributeError:
1310
+ pass
1311
+ h = self._hash = hash((_JustMaybe, self._v))
1312
+ return h
1183
1313
 
1314
+ def __eq__(self, other):
1315
+ return (
1316
+ self.__class__ is other.__class__ and
1317
+ self._v == other._v # noqa
1318
+ )
1184
1319
 
1185
- Maybe._empty = tuple.__new__(_Maybe, ()) # noqa
1186
1320
 
1321
+ class _EmptyMaybe(_Maybe[T]):
1322
+ __slots__ = ()
1187
1323
 
1188
- ##
1324
+ @property
1325
+ def present(self) -> bool:
1326
+ return False
1189
1327
 
1328
+ def must(self) -> T:
1329
+ raise Maybe.ValueNotPresentError
1190
1330
 
1191
- @functools.singledispatch
1192
- def as_maybe(obj: ta.Any) -> Maybe:
1193
- raise TypeError(obj)
1331
+ #
1194
1332
 
1333
+ def __repr__(self) -> str:
1334
+ return 'empty()'
1195
1335
 
1196
- @as_maybe.register
1197
- def _(obj: Maybe) -> Maybe:
1198
- return obj
1336
+ def __hash__(self) -> int:
1337
+ return hash(_EmptyMaybe)
1338
+
1339
+ def __eq__(self, other):
1340
+ return self.__class__ is other.__class__
1341
+
1342
+
1343
+ Maybe._empty = _EmptyMaybe() # noqa
1199
1344
 
1200
1345
 
1201
1346
  ########################################
@@ -1587,9 +1732,16 @@ class PredicateTimeout(Timeout):
1587
1732
  # ../../../omlish/logs/filters.py
1588
1733
 
1589
1734
 
1735
+ ##
1736
+
1737
+
1590
1738
  class TidLogFilter(logging.Filter):
1591
1739
  def filter(self, record):
1592
- record.tid = threading.get_native_id()
1740
+ # FIXME: handle better - missing from wasm and cosmos
1741
+ if hasattr(threading, 'get_native_id'):
1742
+ record.tid = threading.get_native_id()
1743
+ else:
1744
+ record.tid = '?'
1593
1745
  return True
1594
1746
 
1595
1747
 
@@ -1597,6 +1749,9 @@ class TidLogFilter(logging.Filter):
1597
1749
  # ../../../omlish/logs/proxy.py
1598
1750
 
1599
1751
 
1752
+ ##
1753
+
1754
+
1600
1755
  class ProxyLogFilterer(logging.Filterer):
1601
1756
  def __init__(self, underlying: logging.Filterer) -> None: # noqa
1602
1757
  self._underlying = underlying
@@ -5114,6 +5269,9 @@ TODO:
5114
5269
  """
5115
5270
 
5116
5271
 
5272
+ ##
5273
+
5274
+
5117
5275
  class JsonLogFormatter(logging.Formatter):
5118
5276
  KEYS: ta.Mapping[str, bool] = {
5119
5277
  'name': False,
omdev/scripts/interp.py CHANGED
@@ -71,6 +71,9 @@ CheckOnRaiseFn = ta.Callable[[Exception], None] # ta.TypeAlias
71
71
  CheckExceptionFactory = ta.Callable[..., Exception] # ta.TypeAlias
72
72
  CheckArgsRenderer = ta.Callable[..., ta.Optional[str]] # ta.TypeAlias
73
73
 
74
+ # ../../omlish/lite/maybes.py
75
+ U = ta.TypeVar('U')
76
+
74
77
  # ../../omlish/lite/timeouts.py
75
78
  TimeoutLike = ta.Union['Timeout', ta.Type['Timeout.DEFAULT'], ta.Iterable['TimeoutLike'], float, None] # ta.TypeAlias
76
79
 
@@ -86,7 +89,6 @@ ArgparseCmdFn = ta.Callable[[], ta.Optional[int]] # ta.TypeAlias
86
89
  AwaitableT = ta.TypeVar('AwaitableT', bound=ta.Awaitable)
87
90
 
88
91
  # ../../omlish/lite/inject.py
89
- U = ta.TypeVar('U')
90
92
  InjectorKeyCls = ta.Union[type, ta.NewType]
91
93
  InjectorProviderFn = ta.Callable[['Injector'], ta.Any]
92
94
  InjectorProviderFnMap = ta.Mapping['InjectorKey', 'InjectorProviderFn']
@@ -1088,7 +1090,13 @@ json_dumps_compact: ta.Callable[..., str] = functools.partial(json.dumps, **JSON
1088
1090
  ##
1089
1091
 
1090
1092
 
1093
+ @functools.total_ordering
1091
1094
  class Maybe(ta.Generic[T]):
1095
+ class ValueNotPresentError(BaseException):
1096
+ pass
1097
+
1098
+ #
1099
+
1092
1100
  @property
1093
1101
  @abc.abstractmethod
1094
1102
  def present(self) -> bool:
@@ -1098,9 +1106,102 @@ class Maybe(ta.Generic[T]):
1098
1106
  def must(self) -> T:
1099
1107
  raise NotImplementedError
1100
1108
 
1109
+ #
1110
+
1111
+ @abc.abstractmethod
1112
+ def __repr__(self) -> str:
1113
+ raise NotImplementedError
1114
+
1115
+ @abc.abstractmethod
1116
+ def __hash__(self) -> int:
1117
+ raise NotImplementedError
1118
+
1119
+ @abc.abstractmethod
1120
+ def __eq__(self, other) -> bool:
1121
+ raise NotImplementedError
1122
+
1123
+ @abc.abstractmethod
1124
+ def __lt__(self, other) -> bool:
1125
+ raise NotImplementedError
1126
+
1127
+ #
1128
+
1129
+ @ta.final
1130
+ def __ne__(self, other):
1131
+ return not (self == other)
1132
+
1133
+ @ta.final
1134
+ def __iter__(self) -> ta.Iterator[T]:
1135
+ if self.present:
1136
+ yield self.must()
1137
+
1138
+ @ta.final
1139
+ def __bool__(self) -> ta.NoReturn:
1140
+ raise TypeError
1141
+
1142
+ #
1143
+
1144
+ @ta.final
1145
+ def if_present(self, consumer: ta.Callable[[T], None]) -> None:
1146
+ if self.present:
1147
+ consumer(self.must())
1148
+
1149
+ @ta.final
1150
+ def filter(self, predicate: ta.Callable[[T], bool]) -> 'Maybe[T]':
1151
+ if self.present and predicate(self.must()):
1152
+ return self
1153
+ else:
1154
+ return Maybe.empty()
1155
+
1156
+ @ta.final
1157
+ def map(self, mapper: ta.Callable[[T], U]) -> 'Maybe[U]':
1158
+ if self.present:
1159
+ return Maybe.just(mapper(self.must()))
1160
+ else:
1161
+ return Maybe.empty()
1162
+
1163
+ @ta.final
1164
+ def flat_map(self, mapper: ta.Callable[[T], 'Maybe[U]']) -> 'Maybe[U]':
1165
+ if self.present:
1166
+ if not isinstance(v := mapper(self.must()), Maybe):
1167
+ raise TypeError(v)
1168
+ return v
1169
+ else:
1170
+ return Maybe.empty()
1171
+
1172
+ @ta.final
1173
+ def or_else(self, other: ta.Union[T, U]) -> ta.Union[T, U]:
1174
+ if self.present:
1175
+ return self.must()
1176
+ else:
1177
+ return other
1178
+
1179
+ @ta.final
1180
+ def or_else_get(self, supplier: ta.Callable[[], ta.Union[T, U]]) -> ta.Union[T, U]:
1181
+ if self.present:
1182
+ return self.must()
1183
+ else:
1184
+ return supplier()
1185
+
1186
+ @ta.final
1187
+ def or_else_raise(self, exception_supplier: ta.Callable[[], Exception]) -> T:
1188
+ if self.present:
1189
+ return self.must()
1190
+ else:
1191
+ raise exception_supplier()
1192
+
1193
+ #
1194
+
1195
+ @classmethod
1196
+ def of_optional(cls, v: ta.Optional[T]) -> 'Maybe[T]':
1197
+ if v is not None:
1198
+ return cls.just(v)
1199
+ else:
1200
+ return cls.empty()
1201
+
1101
1202
  @classmethod
1102
1203
  def just(cls, v: T) -> 'Maybe[T]':
1103
- return tuple.__new__(_Maybe, (v,)) # noqa
1204
+ return _JustMaybe(v)
1104
1205
 
1105
1206
  _empty: ta.ClassVar['Maybe']
1106
1207
 
@@ -1109,36 +1210,79 @@ class Maybe(ta.Generic[T]):
1109
1210
  return Maybe._empty
1110
1211
 
1111
1212
 
1112
- class _Maybe(Maybe[T], tuple):
1113
- __slots__ = ()
1213
+ ##
1214
+
1215
+
1216
+ class _Maybe(Maybe[T], abc.ABC):
1217
+ def __lt__(self, other):
1218
+ if not isinstance(other, _Maybe):
1219
+ return NotImplemented
1220
+ sp = self.present
1221
+ op = other.present
1222
+ if self.present and other.present:
1223
+ return self.must() < other.must()
1224
+ else:
1225
+ return op and not sp
1114
1226
 
1115
- def __init_subclass__(cls, **kwargs):
1116
- raise TypeError
1227
+
1228
+ class _JustMaybe(_Maybe[T]):
1229
+ __slots__ = ('_v', '_hash')
1230
+
1231
+ def __init__(self, v: T) -> None:
1232
+ super().__init__()
1233
+
1234
+ self._v = v
1117
1235
 
1118
1236
  @property
1119
1237
  def present(self) -> bool:
1120
- return bool(self)
1238
+ return True
1121
1239
 
1122
1240
  def must(self) -> T:
1123
- if not self:
1124
- raise ValueError
1125
- return self[0]
1241
+ return self._v
1126
1242
 
1243
+ #
1127
1244
 
1128
- Maybe._empty = tuple.__new__(_Maybe, ()) # noqa
1245
+ def __repr__(self) -> str:
1246
+ return f'just({self._v!r})'
1129
1247
 
1248
+ def __hash__(self) -> int:
1249
+ try:
1250
+ return self._hash # type: ignore[has-type]
1251
+ except AttributeError:
1252
+ pass
1253
+ h = self._hash = hash((_JustMaybe, self._v))
1254
+ return h
1130
1255
 
1131
- ##
1256
+ def __eq__(self, other):
1257
+ return (
1258
+ self.__class__ is other.__class__ and
1259
+ self._v == other._v # noqa
1260
+ )
1132
1261
 
1133
1262
 
1134
- @functools.singledispatch
1135
- def as_maybe(obj: ta.Any) -> Maybe:
1136
- raise TypeError(obj)
1263
+ class _EmptyMaybe(_Maybe[T]):
1264
+ __slots__ = ()
1137
1265
 
1266
+ @property
1267
+ def present(self) -> bool:
1268
+ return False
1269
+
1270
+ def must(self) -> T:
1271
+ raise Maybe.ValueNotPresentError
1272
+
1273
+ #
1274
+
1275
+ def __repr__(self) -> str:
1276
+ return 'empty()'
1277
+
1278
+ def __hash__(self) -> int:
1279
+ return hash(_EmptyMaybe)
1138
1280
 
1139
- @as_maybe.register
1140
- def _(obj: Maybe) -> Maybe:
1141
- return obj
1281
+ def __eq__(self, other):
1282
+ return self.__class__ is other.__class__
1283
+
1284
+
1285
+ Maybe._empty = _EmptyMaybe() # noqa
1142
1286
 
1143
1287
 
1144
1288
  ########################################
@@ -1530,9 +1674,16 @@ class PredicateTimeout(Timeout):
1530
1674
  # ../../../omlish/logs/filters.py
1531
1675
 
1532
1676
 
1677
+ ##
1678
+
1679
+
1533
1680
  class TidLogFilter(logging.Filter):
1534
1681
  def filter(self, record):
1535
- record.tid = threading.get_native_id()
1682
+ # FIXME: handle better - missing from wasm and cosmos
1683
+ if hasattr(threading, 'get_native_id'):
1684
+ record.tid = threading.get_native_id()
1685
+ else:
1686
+ record.tid = '?'
1536
1687
  return True
1537
1688
 
1538
1689
 
@@ -1540,6 +1691,9 @@ class TidLogFilter(logging.Filter):
1540
1691
  # ../../../omlish/logs/proxy.py
1541
1692
 
1542
1693
 
1694
+ ##
1695
+
1696
+
1543
1697
  class ProxyLogFilterer(logging.Filterer):
1544
1698
  def __init__(self, underlying: logging.Filterer) -> None: # noqa
1545
1699
  self._underlying = underlying
@@ -3579,6 +3733,9 @@ TODO:
3579
3733
  """
3580
3734
 
3581
3735
 
3736
+ ##
3737
+
3738
+
3582
3739
  class JsonLogFormatter(logging.Formatter):
3583
3740
  KEYS: ta.Mapping[str, bool] = {
3584
3741
  'name': False,
@@ -107,6 +107,9 @@ CheckOnRaiseFn = ta.Callable[[Exception], None] # ta.TypeAlias
107
107
  CheckExceptionFactory = ta.Callable[..., Exception] # ta.TypeAlias
108
108
  CheckArgsRenderer = ta.Callable[..., ta.Optional[str]] # ta.TypeAlias
109
109
 
110
+ # ../../omlish/lite/maybes.py
111
+ U = ta.TypeVar('U')
112
+
110
113
  # ../../omlish/lite/timeouts.py
111
114
  TimeoutLike = ta.Union['Timeout', ta.Type['Timeout.DEFAULT'], ta.Iterable['TimeoutLike'], float, None] # ta.TypeAlias
112
115
 
@@ -127,7 +130,6 @@ ArgparseCmdFn = ta.Callable[[], ta.Optional[int]] # ta.TypeAlias
127
130
  AwaitableT = ta.TypeVar('AwaitableT', bound=ta.Awaitable)
128
131
 
129
132
  # ../../omlish/lite/inject.py
130
- U = ta.TypeVar('U')
131
133
  InjectorKeyCls = ta.Union[type, ta.NewType]
132
134
  InjectorProviderFn = ta.Callable[['Injector'], ta.Any]
133
135
  InjectorProviderFnMap = ta.Mapping['InjectorKey', 'InjectorProviderFn']
@@ -2504,7 +2506,13 @@ log = logging.getLogger(__name__)
2504
2506
  ##
2505
2507
 
2506
2508
 
2509
+ @functools.total_ordering
2507
2510
  class Maybe(ta.Generic[T]):
2511
+ class ValueNotPresentError(BaseException):
2512
+ pass
2513
+
2514
+ #
2515
+
2508
2516
  @property
2509
2517
  @abc.abstractmethod
2510
2518
  def present(self) -> bool:
@@ -2514,9 +2522,102 @@ class Maybe(ta.Generic[T]):
2514
2522
  def must(self) -> T:
2515
2523
  raise NotImplementedError
2516
2524
 
2525
+ #
2526
+
2527
+ @abc.abstractmethod
2528
+ def __repr__(self) -> str:
2529
+ raise NotImplementedError
2530
+
2531
+ @abc.abstractmethod
2532
+ def __hash__(self) -> int:
2533
+ raise NotImplementedError
2534
+
2535
+ @abc.abstractmethod
2536
+ def __eq__(self, other) -> bool:
2537
+ raise NotImplementedError
2538
+
2539
+ @abc.abstractmethod
2540
+ def __lt__(self, other) -> bool:
2541
+ raise NotImplementedError
2542
+
2543
+ #
2544
+
2545
+ @ta.final
2546
+ def __ne__(self, other):
2547
+ return not (self == other)
2548
+
2549
+ @ta.final
2550
+ def __iter__(self) -> ta.Iterator[T]:
2551
+ if self.present:
2552
+ yield self.must()
2553
+
2554
+ @ta.final
2555
+ def __bool__(self) -> ta.NoReturn:
2556
+ raise TypeError
2557
+
2558
+ #
2559
+
2560
+ @ta.final
2561
+ def if_present(self, consumer: ta.Callable[[T], None]) -> None:
2562
+ if self.present:
2563
+ consumer(self.must())
2564
+
2565
+ @ta.final
2566
+ def filter(self, predicate: ta.Callable[[T], bool]) -> 'Maybe[T]':
2567
+ if self.present and predicate(self.must()):
2568
+ return self
2569
+ else:
2570
+ return Maybe.empty()
2571
+
2572
+ @ta.final
2573
+ def map(self, mapper: ta.Callable[[T], U]) -> 'Maybe[U]':
2574
+ if self.present:
2575
+ return Maybe.just(mapper(self.must()))
2576
+ else:
2577
+ return Maybe.empty()
2578
+
2579
+ @ta.final
2580
+ def flat_map(self, mapper: ta.Callable[[T], 'Maybe[U]']) -> 'Maybe[U]':
2581
+ if self.present:
2582
+ if not isinstance(v := mapper(self.must()), Maybe):
2583
+ raise TypeError(v)
2584
+ return v
2585
+ else:
2586
+ return Maybe.empty()
2587
+
2588
+ @ta.final
2589
+ def or_else(self, other: ta.Union[T, U]) -> ta.Union[T, U]:
2590
+ if self.present:
2591
+ return self.must()
2592
+ else:
2593
+ return other
2594
+
2595
+ @ta.final
2596
+ def or_else_get(self, supplier: ta.Callable[[], ta.Union[T, U]]) -> ta.Union[T, U]:
2597
+ if self.present:
2598
+ return self.must()
2599
+ else:
2600
+ return supplier()
2601
+
2602
+ @ta.final
2603
+ def or_else_raise(self, exception_supplier: ta.Callable[[], Exception]) -> T:
2604
+ if self.present:
2605
+ return self.must()
2606
+ else:
2607
+ raise exception_supplier()
2608
+
2609
+ #
2610
+
2611
+ @classmethod
2612
+ def of_optional(cls, v: ta.Optional[T]) -> 'Maybe[T]':
2613
+ if v is not None:
2614
+ return cls.just(v)
2615
+ else:
2616
+ return cls.empty()
2617
+
2517
2618
  @classmethod
2518
2619
  def just(cls, v: T) -> 'Maybe[T]':
2519
- return tuple.__new__(_Maybe, (v,)) # noqa
2620
+ return _JustMaybe(v)
2520
2621
 
2521
2622
  _empty: ta.ClassVar['Maybe']
2522
2623
 
@@ -2525,36 +2626,79 @@ class Maybe(ta.Generic[T]):
2525
2626
  return Maybe._empty
2526
2627
 
2527
2628
 
2528
- class _Maybe(Maybe[T], tuple):
2529
- __slots__ = ()
2629
+ ##
2630
+
2631
+
2632
+ class _Maybe(Maybe[T], abc.ABC):
2633
+ def __lt__(self, other):
2634
+ if not isinstance(other, _Maybe):
2635
+ return NotImplemented
2636
+ sp = self.present
2637
+ op = other.present
2638
+ if self.present and other.present:
2639
+ return self.must() < other.must()
2640
+ else:
2641
+ return op and not sp
2530
2642
 
2531
- def __init_subclass__(cls, **kwargs):
2532
- raise TypeError
2643
+
2644
+ class _JustMaybe(_Maybe[T]):
2645
+ __slots__ = ('_v', '_hash')
2646
+
2647
+ def __init__(self, v: T) -> None:
2648
+ super().__init__()
2649
+
2650
+ self._v = v
2533
2651
 
2534
2652
  @property
2535
2653
  def present(self) -> bool:
2536
- return bool(self)
2654
+ return True
2537
2655
 
2538
2656
  def must(self) -> T:
2539
- if not self:
2540
- raise ValueError
2541
- return self[0]
2657
+ return self._v
2542
2658
 
2659
+ #
2543
2660
 
2544
- Maybe._empty = tuple.__new__(_Maybe, ()) # noqa
2661
+ def __repr__(self) -> str:
2662
+ return f'just({self._v!r})'
2545
2663
 
2664
+ def __hash__(self) -> int:
2665
+ try:
2666
+ return self._hash # type: ignore[has-type]
2667
+ except AttributeError:
2668
+ pass
2669
+ h = self._hash = hash((_JustMaybe, self._v))
2670
+ return h
2546
2671
 
2547
- ##
2672
+ def __eq__(self, other):
2673
+ return (
2674
+ self.__class__ is other.__class__ and
2675
+ self._v == other._v # noqa
2676
+ )
2548
2677
 
2549
2678
 
2550
- @functools.singledispatch
2551
- def as_maybe(obj: ta.Any) -> Maybe:
2552
- raise TypeError(obj)
2679
+ class _EmptyMaybe(_Maybe[T]):
2680
+ __slots__ = ()
2553
2681
 
2682
+ @property
2683
+ def present(self) -> bool:
2684
+ return False
2685
+
2686
+ def must(self) -> T:
2687
+ raise Maybe.ValueNotPresentError
2688
+
2689
+ #
2690
+
2691
+ def __repr__(self) -> str:
2692
+ return 'empty()'
2693
+
2694
+ def __hash__(self) -> int:
2695
+ return hash(_EmptyMaybe)
2554
2696
 
2555
- @as_maybe.register
2556
- def _(obj: Maybe) -> Maybe:
2557
- return obj
2697
+ def __eq__(self, other):
2698
+ return self.__class__ is other.__class__
2699
+
2700
+
2701
+ Maybe._empty = _EmptyMaybe() # noqa
2558
2702
 
2559
2703
 
2560
2704
  ########################################
@@ -2994,9 +3138,16 @@ class Func3(ta.Generic[A0, A1, A2, T]):
2994
3138
  # ../../../omlish/logs/filters.py
2995
3139
 
2996
3140
 
3141
+ ##
3142
+
3143
+
2997
3144
  class TidLogFilter(logging.Filter):
2998
3145
  def filter(self, record):
2999
- record.tid = threading.get_native_id()
3146
+ # FIXME: handle better - missing from wasm and cosmos
3147
+ if hasattr(threading, 'get_native_id'):
3148
+ record.tid = threading.get_native_id()
3149
+ else:
3150
+ record.tid = '?'
3000
3151
  return True
3001
3152
 
3002
3153
 
@@ -3004,6 +3155,9 @@ class TidLogFilter(logging.Filter):
3004
3155
  # ../../../omlish/logs/proxy.py
3005
3156
 
3006
3157
 
3158
+ ##
3159
+
3160
+
3007
3161
  class ProxyLogFilterer(logging.Filterer):
3008
3162
  def __init__(self, underlying: logging.Filterer) -> None: # noqa
3009
3163
  self._underlying = underlying
@@ -5949,6 +6103,9 @@ TODO:
5949
6103
  """
5950
6104
 
5951
6105
 
6106
+ ##
6107
+
6108
+
5952
6109
  class JsonLogFormatter(logging.Formatter):
5953
6110
  KEYS: ta.Mapping[str, bool] = {
5954
6111
  'name': False,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omdev
3
- Version: 0.0.0.dev315
3
+ Version: 0.0.0.dev316
4
4
  Summary: omdev
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
12
12
  Classifier: Operating System :: POSIX
13
13
  Requires-Python: >=3.12
14
14
  License-File: LICENSE
15
- Requires-Dist: omlish==0.0.0.dev315
15
+ Requires-Dist: omlish==0.0.0.dev316
16
16
  Provides-Extra: all
17
17
  Requires-Dist: black~=25.1; extra == "all"
18
18
  Requires-Dist: pycparser~=2.22; extra == "all"
@@ -250,9 +250,9 @@ omdev/pyproject/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
250
250
  omdev/pyproject/resources/docker-dev.sh,sha256=DHkz5D18jok_oDolfg2mqrvGRWFoCe9GQo04dR1czcc,838
251
251
  omdev/pyproject/resources/python.sh,sha256=rFaN4SiJ9hdLDXXsDTwugI6zsw6EPkgYMmtacZeTbvw,749
252
252
  omdev/scripts/__init__.py,sha256=MKCvUAEQwsIvwLixwtPlpBqmkMXLCnjjXyAXvVpDwVk,91
253
- omdev/scripts/ci.py,sha256=CagK-zEh6WFmuVvnYuBY9caZoAOC-TZtf-osDxu5aeE,353528
254
- omdev/scripts/interp.py,sha256=tU8alYhrsaMQSKCyIQZi_ETvmpUjsO-VAV1obaRsC3E,152087
255
- omdev/scripts/pyproject.py,sha256=7zCjwi0mfTLXr6B2hpexdM4mPrVdMj4c4PaC5q0kAyY,261568
253
+ omdev/scripts/ci.py,sha256=HCkgcJND22CGrB7Tw4c3EZI5RsZlHAeQQtW7rG1Fiuo,357053
254
+ omdev/scripts/interp.py,sha256=zNOZAz7DbD7vMdNhNRMt5XtkF-gjCApU5stKX0j_AOM,155600
255
+ omdev/scripts/pyproject.py,sha256=E5Xx_EhvGspwjqGecd1KCLk1I1bOkKPgjtxbT1zjYJQ,265081
256
256
  omdev/scripts/slowcat.py,sha256=lssv4yrgJHiWfOiHkUut2p8E8Tq32zB-ujXESQxFFHY,2728
257
257
  omdev/scripts/tmpexec.py,sha256=WTYcf56Tj2qjYV14AWmV8SfT0u6Y8eIU6cKgQRvEK3c,1442
258
258
  omdev/tokens/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -294,9 +294,9 @@ omdev/tools/json/rendering.py,sha256=3HhdlKSetS6iK1tjF2aILzsl8Mb3D8wW92vYwGpRdVA
294
294
  omdev/tools/pawk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
295
295
  omdev/tools/pawk/__main__.py,sha256=VCqeRVnqT1RPEoIrqHFSu4PXVMg4YEgF4qCQm90-eRI,66
296
296
  omdev/tools/pawk/pawk.py,sha256=zsEkfQX0jF5bn712uqPAyBSdJt2dno1LH2oeSMNfXQI,11424
297
- omdev-0.0.0.dev315.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
298
- omdev-0.0.0.dev315.dist-info/METADATA,sha256=E-Opc9zYrFHTsk4j2SA5cFi7vfNJbf7avfSrI2JVmfQ,1674
299
- omdev-0.0.0.dev315.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
300
- omdev-0.0.0.dev315.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
301
- omdev-0.0.0.dev315.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
302
- omdev-0.0.0.dev315.dist-info/RECORD,,
297
+ omdev-0.0.0.dev316.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
298
+ omdev-0.0.0.dev316.dist-info/METADATA,sha256=2aNPDE5Nt1HuXUTI29IIM3PZYcTNS6UQvV9QOqyc1tw,1674
299
+ omdev-0.0.0.dev316.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
300
+ omdev-0.0.0.dev316.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
301
+ omdev-0.0.0.dev316.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
302
+ omdev-0.0.0.dev316.dist-info/RECORD,,