ominfra 0.0.0.dev440__py3-none-any.whl → 0.0.0.dev442__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 ominfra might be problematic. Click here for more details.

@@ -1359,6 +1359,8 @@ class InstanceType(_enum.Enum):
1359
1359
  I8GE_48XLARGE = 'i8ge.48xlarge'
1360
1360
  I8GE_METAL_24XL = 'i8ge.metal-24xl'
1361
1361
  I8GE_METAL_48XL = 'i8ge.metal-48xl'
1362
+ MAC_M4_METAL = 'mac-m4.metal'
1363
+ MAC_M4PRO_METAL = 'mac-m4pro.metal'
1362
1364
 
1363
1365
 
1364
1366
  class InstanceTypeHypervisor(_enum.Enum):
@@ -1345,6 +1345,8 @@ class AttrOps(ta.Generic[T]):
1345
1345
  display: ta.Optional[str] = None,
1346
1346
 
1347
1347
  repr: bool = True, # noqa
1348
+ repr_fn: ta.Optional[ta.Callable[[ta.Any], ta.Optional[str]]] = None,
1349
+
1348
1350
  hash: bool = True, # noqa
1349
1351
  eq: bool = True,
1350
1352
  ) -> None:
@@ -1359,6 +1361,8 @@ class AttrOps(ta.Generic[T]):
1359
1361
  self._display = display
1360
1362
 
1361
1363
  self._repr = repr
1364
+ self._repr_fn = repr_fn
1365
+
1362
1366
  self._hash = hash
1363
1367
  self._eq = eq
1364
1368
 
@@ -1366,10 +1370,10 @@ class AttrOps(ta.Generic[T]):
1366
1370
  def of(
1367
1371
  cls,
1368
1372
  o: ta.Union[
1373
+ 'AttrOps.Attr',
1369
1374
  str,
1370
- ta.Tuple[str, str],
1375
+ ta.Tuple[str, ta.Union[str, ta.Mapping[str, ta.Any]]],
1371
1376
  ta.Mapping[str, ta.Any],
1372
- 'AttrOps.Attr',
1373
1377
  ],
1374
1378
  ) -> 'AttrOps.Attr':
1375
1379
  if isinstance(o, AttrOps.Attr):
@@ -1377,11 +1381,15 @@ class AttrOps(ta.Generic[T]):
1377
1381
  elif isinstance(o, str):
1378
1382
  return cls(o)
1379
1383
  elif isinstance(o, tuple):
1380
- name, disp = o
1381
- return cls(
1382
- name,
1383
- display=disp,
1384
- )
1384
+ name, x = o
1385
+ kw: ta.Mapping[str, ta.Any]
1386
+ if isinstance(x, str):
1387
+ kw = dict(display=x)
1388
+ elif isinstance(x, ta.Mapping):
1389
+ kw = x
1390
+ else:
1391
+ raise TypeError(x)
1392
+ return cls(name, **kw)
1385
1393
  elif isinstance(o, ta.Mapping):
1386
1394
  return cls(**o)
1387
1395
  else:
@@ -1403,20 +1411,34 @@ class AttrOps(ta.Generic[T]):
1403
1411
  def eq(self) -> bool:
1404
1412
  return self._eq
1405
1413
 
1414
+ @staticmethod
1415
+ def opt_repr(o: ta.Any) -> ta.Optional[str]:
1416
+ return repr(o) if o is not None else None
1417
+
1418
+ @staticmethod
1419
+ def truthy_repr(o: ta.Any) -> ta.Optional[str]:
1420
+ return repr(o) if o else None
1421
+
1422
+ #
1423
+
1406
1424
  @ta.overload
1407
1425
  def __init__(
1408
1426
  self,
1409
1427
  *attrs: ta.Sequence[ta.Union[
1410
1428
  str,
1411
- ta.Tuple[str, str],
1429
+ ta.Tuple[str, ta.Union[str, ta.Mapping[str, ta.Any]]],
1412
1430
  ta.Mapping[str, ta.Any],
1413
1431
  Attr,
1414
1432
  ]],
1433
+
1415
1434
  with_module: bool = False,
1416
1435
  use_qualname: bool = False,
1417
1436
  with_id: bool = False,
1437
+ terse: bool = False,
1418
1438
  repr_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = None,
1419
1439
  recursive: bool = False,
1440
+
1441
+ cache_hash: ta.Union[bool, str] = False,
1420
1442
  subtypes_eq: bool = False,
1421
1443
  ) -> None:
1422
1444
  ...
@@ -1426,16 +1448,20 @@ class AttrOps(ta.Generic[T]):
1426
1448
  self,
1427
1449
  attrs_fn: ta.Callable[[T], ta.Tuple[ta.Union[
1428
1450
  ta.Any,
1429
- ta.Tuple[str, ta.Any],
1451
+ ta.Tuple[ta.Any, ta.Union[str, ta.Mapping[str, ta.Any]]],
1430
1452
  Attr,
1431
1453
  ], ...]],
1432
1454
  /,
1433
1455
  *,
1456
+
1434
1457
  with_module: bool = False,
1435
1458
  use_qualname: bool = False,
1436
1459
  with_id: bool = False,
1460
+ terse: bool = False,
1437
1461
  repr_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = None,
1438
1462
  recursive: bool = False,
1463
+
1464
+ cache_hash: ta.Union[bool, str] = False,
1439
1465
  subtypes_eq: bool = False,
1440
1466
  ) -> None:
1441
1467
  ...
@@ -1443,11 +1469,15 @@ class AttrOps(ta.Generic[T]):
1443
1469
  def __init__(
1444
1470
  self,
1445
1471
  *args,
1472
+
1446
1473
  with_module=False,
1447
1474
  use_qualname=False,
1448
1475
  with_id=False,
1476
+ terse=False,
1449
1477
  repr_filter=None,
1450
1478
  recursive=False,
1479
+
1480
+ cache_hash=False,
1451
1481
  subtypes_eq=False,
1452
1482
  ) -> None:
1453
1483
  if args and len(args) == 1 and callable(args[0]):
@@ -1458,8 +1488,11 @@ class AttrOps(ta.Generic[T]):
1458
1488
  self._with_module: bool = with_module
1459
1489
  self._use_qualname: bool = use_qualname
1460
1490
  self._with_id: bool = with_id
1491
+ self._terse: bool = terse
1461
1492
  self._repr_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = repr_filter
1462
1493
  self._recursive: bool = recursive
1494
+
1495
+ self._cache_hash: ta.Union[bool, str] = cache_hash
1463
1496
  self._subtypes_eq: bool = subtypes_eq
1464
1497
 
1465
1498
  @property
@@ -1498,16 +1531,23 @@ class AttrOps(ta.Generic[T]):
1498
1531
  attrs.append(AttrOps.Attr.of(o))
1499
1532
  continue
1500
1533
 
1534
+ kw: ta.Mapping[str, ta.Any]
1501
1535
  if isinstance(o, tuple):
1502
- disp, cap, = o
1536
+ cap, x = o
1537
+ if isinstance(x, str):
1538
+ kw = dict(display=x)
1539
+ elif isinstance(x, ta.Mapping):
1540
+ kw = x
1541
+ else:
1542
+ raise TypeError(x)
1503
1543
  else:
1504
- disp, cap = None, o
1544
+ cap, kw = o, {}
1505
1545
 
1506
1546
  path = tuple(rec(cap))
1507
1547
 
1508
1548
  attrs.append(AttrOps.Attr(
1509
1549
  '.'.join(path),
1510
- display=disp,
1550
+ **kw,
1511
1551
  ))
1512
1552
 
1513
1553
  return attrs
@@ -1524,19 +1564,27 @@ class AttrOps(ta.Generic[T]):
1524
1564
  pass
1525
1565
 
1526
1566
  def _repr(o: T) -> str:
1527
- vs = ', '.join(
1528
- f'{a._display}={v!r}' # noqa
1529
- for a in self._attrs
1530
- if a._repr # noqa
1531
- for v in [getattr(o, a._name)] # noqa
1532
- if self._repr_filter is None or self._repr_filter(v)
1533
- )
1567
+ vs: ta.List[str] = []
1568
+ for a in self._attrs:
1569
+ if not a._repr: # noqa
1570
+ continue
1571
+ v = getattr(o, a._name) # noqa
1572
+ if self._repr_filter is not None and not self._repr_filter(v):
1573
+ continue
1574
+ if (rfn := a._repr_fn) is None: # noqa
1575
+ rfn = repr
1576
+ if (vr := rfn(v)) is None:
1577
+ continue
1578
+ if self._terse:
1579
+ vs.append(vr)
1580
+ else:
1581
+ vs.append(f'{a._display}={vr}') # noqa
1534
1582
 
1535
1583
  return (
1536
1584
  f'{o.__class__.__module__ + "." if self._with_module else ""}'
1537
1585
  f'{o.__class__.__qualname__ if self._use_qualname else o.__class__.__name__}'
1538
1586
  f'{("@" + hex(id(o))[2:]) if self._with_id else ""}' # noqa
1539
- f'({vs})'
1587
+ f'({", ".join(vs)})'
1540
1588
  )
1541
1589
 
1542
1590
  if self._recursive:
@@ -1561,6 +1609,8 @@ class AttrOps(ta.Generic[T]):
1561
1609
 
1562
1610
  #
1563
1611
 
1612
+ _DEFAULT_CACHED_HASH_ATTR: ta.ClassVar[str] = '__cached_hash__'
1613
+
1564
1614
  _hash: ta.Callable[[T], int]
1565
1615
 
1566
1616
  @property
@@ -1570,13 +1620,33 @@ class AttrOps(ta.Generic[T]):
1570
1620
  except AttributeError:
1571
1621
  pass
1572
1622
 
1573
- def _hash(o: T) -> int:
1623
+ def _calc_hash(o: T) -> int:
1574
1624
  return hash(tuple(
1575
1625
  getattr(o, a._name) # noqa
1576
1626
  for a in self._attrs
1577
1627
  if a._hash # noqa
1578
1628
  ))
1579
1629
 
1630
+ if (ch := self._cache_hash) is not False:
1631
+ if ch is True:
1632
+ cha = self._DEFAULT_CACHED_HASH_ATTR
1633
+ elif isinstance(ch, str):
1634
+ cha = ch
1635
+ else:
1636
+ raise TypeError(ch)
1637
+
1638
+ def _cached_hash(o: T) -> int:
1639
+ try:
1640
+ return object.__getattribute__(o, cha)
1641
+ except AttributeError:
1642
+ object.__setattr__(o, cha, h := _calc_hash(o))
1643
+ return h
1644
+
1645
+ _hash = _cached_hash
1646
+
1647
+ else:
1648
+ _hash = _calc_hash
1649
+
1580
1650
  self._hash = _hash
1581
1651
  return _hash
1582
1652
 
@@ -1717,6 +1787,62 @@ def async_cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
1717
1787
  return _AsyncCachedNullary(fn)
1718
1788
 
1719
1789
 
1790
+ ##
1791
+
1792
+
1793
+ cached_property = functools.cached_property
1794
+
1795
+
1796
+ class _cached_property: # noqa
1797
+ """Backported to pick up https://github.com/python/cpython/commit/056dfc71dce15f81887f0bd6da09d6099d71f979 ."""
1798
+
1799
+ def __init__(self, func):
1800
+ self.func = func
1801
+ self.attrname = None # noqa
1802
+ self.__doc__ = func.__doc__
1803
+ self.__module__ = func.__module__
1804
+
1805
+ _NOT_FOUND = object()
1806
+
1807
+ def __set_name__(self, owner, name):
1808
+ if self.attrname is None:
1809
+ self.attrname = name # noqa
1810
+ elif name != self.attrname:
1811
+ raise TypeError(
1812
+ f'Cannot assign the same cached_property to two different names ({self.attrname!r} and {name!r}).',
1813
+ )
1814
+
1815
+ def __get__(self, instance, owner=None):
1816
+ if instance is None:
1817
+ return self
1818
+ if self.attrname is None:
1819
+ raise TypeError('Cannot use cached_property instance without calling __set_name__ on it.')
1820
+
1821
+ try:
1822
+ cache = instance.__dict__
1823
+ except AttributeError: # not all objects have __dict__ (e.g. class defines slots)
1824
+ raise TypeError(
1825
+ f"No '__dict__' attribute on {type(instance).__name__!r} instance to cache {self.attrname!r} property.",
1826
+ ) from None
1827
+
1828
+ val = cache.get(self.attrname, self._NOT_FOUND)
1829
+
1830
+ if val is self._NOT_FOUND:
1831
+ val = self.func(instance)
1832
+ try:
1833
+ cache[self.attrname] = val
1834
+ except TypeError:
1835
+ raise TypeError(
1836
+ f"The '__dict__' attribute on {type(instance).__name__!r} instance does not support item "
1837
+ f"assignment for caching {self.attrname!r} property.",
1838
+ ) from None
1839
+
1840
+ return val
1841
+
1842
+
1843
+ globals()['cached_property'] = _cached_property
1844
+
1845
+
1720
1846
  ########################################
1721
1847
  # ../../../../../omlish/lite/check.py
1722
1848
  """
ominfra/scripts/manage.py CHANGED
@@ -2524,6 +2524,8 @@ class AttrOps(ta.Generic[T]):
2524
2524
  display: ta.Optional[str] = None,
2525
2525
 
2526
2526
  repr: bool = True, # noqa
2527
+ repr_fn: ta.Optional[ta.Callable[[ta.Any], ta.Optional[str]]] = None,
2528
+
2527
2529
  hash: bool = True, # noqa
2528
2530
  eq: bool = True,
2529
2531
  ) -> None:
@@ -2538,6 +2540,8 @@ class AttrOps(ta.Generic[T]):
2538
2540
  self._display = display
2539
2541
 
2540
2542
  self._repr = repr
2543
+ self._repr_fn = repr_fn
2544
+
2541
2545
  self._hash = hash
2542
2546
  self._eq = eq
2543
2547
 
@@ -2545,10 +2549,10 @@ class AttrOps(ta.Generic[T]):
2545
2549
  def of(
2546
2550
  cls,
2547
2551
  o: ta.Union[
2552
+ 'AttrOps.Attr',
2548
2553
  str,
2549
- ta.Tuple[str, str],
2554
+ ta.Tuple[str, ta.Union[str, ta.Mapping[str, ta.Any]]],
2550
2555
  ta.Mapping[str, ta.Any],
2551
- 'AttrOps.Attr',
2552
2556
  ],
2553
2557
  ) -> 'AttrOps.Attr':
2554
2558
  if isinstance(o, AttrOps.Attr):
@@ -2556,11 +2560,15 @@ class AttrOps(ta.Generic[T]):
2556
2560
  elif isinstance(o, str):
2557
2561
  return cls(o)
2558
2562
  elif isinstance(o, tuple):
2559
- name, disp = o
2560
- return cls(
2561
- name,
2562
- display=disp,
2563
- )
2563
+ name, x = o
2564
+ kw: ta.Mapping[str, ta.Any]
2565
+ if isinstance(x, str):
2566
+ kw = dict(display=x)
2567
+ elif isinstance(x, ta.Mapping):
2568
+ kw = x
2569
+ else:
2570
+ raise TypeError(x)
2571
+ return cls(name, **kw)
2564
2572
  elif isinstance(o, ta.Mapping):
2565
2573
  return cls(**o)
2566
2574
  else:
@@ -2582,20 +2590,34 @@ class AttrOps(ta.Generic[T]):
2582
2590
  def eq(self) -> bool:
2583
2591
  return self._eq
2584
2592
 
2593
+ @staticmethod
2594
+ def opt_repr(o: ta.Any) -> ta.Optional[str]:
2595
+ return repr(o) if o is not None else None
2596
+
2597
+ @staticmethod
2598
+ def truthy_repr(o: ta.Any) -> ta.Optional[str]:
2599
+ return repr(o) if o else None
2600
+
2601
+ #
2602
+
2585
2603
  @ta.overload
2586
2604
  def __init__(
2587
2605
  self,
2588
2606
  *attrs: ta.Sequence[ta.Union[
2589
2607
  str,
2590
- ta.Tuple[str, str],
2608
+ ta.Tuple[str, ta.Union[str, ta.Mapping[str, ta.Any]]],
2591
2609
  ta.Mapping[str, ta.Any],
2592
2610
  Attr,
2593
2611
  ]],
2612
+
2594
2613
  with_module: bool = False,
2595
2614
  use_qualname: bool = False,
2596
2615
  with_id: bool = False,
2616
+ terse: bool = False,
2597
2617
  repr_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = None,
2598
2618
  recursive: bool = False,
2619
+
2620
+ cache_hash: ta.Union[bool, str] = False,
2599
2621
  subtypes_eq: bool = False,
2600
2622
  ) -> None:
2601
2623
  ...
@@ -2605,16 +2627,20 @@ class AttrOps(ta.Generic[T]):
2605
2627
  self,
2606
2628
  attrs_fn: ta.Callable[[T], ta.Tuple[ta.Union[
2607
2629
  ta.Any,
2608
- ta.Tuple[str, ta.Any],
2630
+ ta.Tuple[ta.Any, ta.Union[str, ta.Mapping[str, ta.Any]]],
2609
2631
  Attr,
2610
2632
  ], ...]],
2611
2633
  /,
2612
2634
  *,
2635
+
2613
2636
  with_module: bool = False,
2614
2637
  use_qualname: bool = False,
2615
2638
  with_id: bool = False,
2639
+ terse: bool = False,
2616
2640
  repr_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = None,
2617
2641
  recursive: bool = False,
2642
+
2643
+ cache_hash: ta.Union[bool, str] = False,
2618
2644
  subtypes_eq: bool = False,
2619
2645
  ) -> None:
2620
2646
  ...
@@ -2622,11 +2648,15 @@ class AttrOps(ta.Generic[T]):
2622
2648
  def __init__(
2623
2649
  self,
2624
2650
  *args,
2651
+
2625
2652
  with_module=False,
2626
2653
  use_qualname=False,
2627
2654
  with_id=False,
2655
+ terse=False,
2628
2656
  repr_filter=None,
2629
2657
  recursive=False,
2658
+
2659
+ cache_hash=False,
2630
2660
  subtypes_eq=False,
2631
2661
  ) -> None:
2632
2662
  if args and len(args) == 1 and callable(args[0]):
@@ -2637,8 +2667,11 @@ class AttrOps(ta.Generic[T]):
2637
2667
  self._with_module: bool = with_module
2638
2668
  self._use_qualname: bool = use_qualname
2639
2669
  self._with_id: bool = with_id
2670
+ self._terse: bool = terse
2640
2671
  self._repr_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = repr_filter
2641
2672
  self._recursive: bool = recursive
2673
+
2674
+ self._cache_hash: ta.Union[bool, str] = cache_hash
2642
2675
  self._subtypes_eq: bool = subtypes_eq
2643
2676
 
2644
2677
  @property
@@ -2677,16 +2710,23 @@ class AttrOps(ta.Generic[T]):
2677
2710
  attrs.append(AttrOps.Attr.of(o))
2678
2711
  continue
2679
2712
 
2713
+ kw: ta.Mapping[str, ta.Any]
2680
2714
  if isinstance(o, tuple):
2681
- disp, cap, = o
2715
+ cap, x = o
2716
+ if isinstance(x, str):
2717
+ kw = dict(display=x)
2718
+ elif isinstance(x, ta.Mapping):
2719
+ kw = x
2720
+ else:
2721
+ raise TypeError(x)
2682
2722
  else:
2683
- disp, cap = None, o
2723
+ cap, kw = o, {}
2684
2724
 
2685
2725
  path = tuple(rec(cap))
2686
2726
 
2687
2727
  attrs.append(AttrOps.Attr(
2688
2728
  '.'.join(path),
2689
- display=disp,
2729
+ **kw,
2690
2730
  ))
2691
2731
 
2692
2732
  return attrs
@@ -2703,19 +2743,27 @@ class AttrOps(ta.Generic[T]):
2703
2743
  pass
2704
2744
 
2705
2745
  def _repr(o: T) -> str:
2706
- vs = ', '.join(
2707
- f'{a._display}={v!r}' # noqa
2708
- for a in self._attrs
2709
- if a._repr # noqa
2710
- for v in [getattr(o, a._name)] # noqa
2711
- if self._repr_filter is None or self._repr_filter(v)
2712
- )
2746
+ vs: ta.List[str] = []
2747
+ for a in self._attrs:
2748
+ if not a._repr: # noqa
2749
+ continue
2750
+ v = getattr(o, a._name) # noqa
2751
+ if self._repr_filter is not None and not self._repr_filter(v):
2752
+ continue
2753
+ if (rfn := a._repr_fn) is None: # noqa
2754
+ rfn = repr
2755
+ if (vr := rfn(v)) is None:
2756
+ continue
2757
+ if self._terse:
2758
+ vs.append(vr)
2759
+ else:
2760
+ vs.append(f'{a._display}={vr}') # noqa
2713
2761
 
2714
2762
  return (
2715
2763
  f'{o.__class__.__module__ + "." if self._with_module else ""}'
2716
2764
  f'{o.__class__.__qualname__ if self._use_qualname else o.__class__.__name__}'
2717
2765
  f'{("@" + hex(id(o))[2:]) if self._with_id else ""}' # noqa
2718
- f'({vs})'
2766
+ f'({", ".join(vs)})'
2719
2767
  )
2720
2768
 
2721
2769
  if self._recursive:
@@ -2740,6 +2788,8 @@ class AttrOps(ta.Generic[T]):
2740
2788
 
2741
2789
  #
2742
2790
 
2791
+ _DEFAULT_CACHED_HASH_ATTR: ta.ClassVar[str] = '__cached_hash__'
2792
+
2743
2793
  _hash: ta.Callable[[T], int]
2744
2794
 
2745
2795
  @property
@@ -2749,13 +2799,33 @@ class AttrOps(ta.Generic[T]):
2749
2799
  except AttributeError:
2750
2800
  pass
2751
2801
 
2752
- def _hash(o: T) -> int:
2802
+ def _calc_hash(o: T) -> int:
2753
2803
  return hash(tuple(
2754
2804
  getattr(o, a._name) # noqa
2755
2805
  for a in self._attrs
2756
2806
  if a._hash # noqa
2757
2807
  ))
2758
2808
 
2809
+ if (ch := self._cache_hash) is not False:
2810
+ if ch is True:
2811
+ cha = self._DEFAULT_CACHED_HASH_ATTR
2812
+ elif isinstance(ch, str):
2813
+ cha = ch
2814
+ else:
2815
+ raise TypeError(ch)
2816
+
2817
+ def _cached_hash(o: T) -> int:
2818
+ try:
2819
+ return object.__getattribute__(o, cha)
2820
+ except AttributeError:
2821
+ object.__setattr__(o, cha, h := _calc_hash(o))
2822
+ return h
2823
+
2824
+ _hash = _cached_hash
2825
+
2826
+ else:
2827
+ _hash = _calc_hash
2828
+
2759
2829
  self._hash = _hash
2760
2830
  return _hash
2761
2831
 
@@ -2896,6 +2966,62 @@ def async_cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
2896
2966
  return _AsyncCachedNullary(fn)
2897
2967
 
2898
2968
 
2969
+ ##
2970
+
2971
+
2972
+ cached_property = functools.cached_property
2973
+
2974
+
2975
+ class _cached_property: # noqa
2976
+ """Backported to pick up https://github.com/python/cpython/commit/056dfc71dce15f81887f0bd6da09d6099d71f979 ."""
2977
+
2978
+ def __init__(self, func):
2979
+ self.func = func
2980
+ self.attrname = None # noqa
2981
+ self.__doc__ = func.__doc__
2982
+ self.__module__ = func.__module__
2983
+
2984
+ _NOT_FOUND = object()
2985
+
2986
+ def __set_name__(self, owner, name):
2987
+ if self.attrname is None:
2988
+ self.attrname = name # noqa
2989
+ elif name != self.attrname:
2990
+ raise TypeError(
2991
+ f'Cannot assign the same cached_property to two different names ({self.attrname!r} and {name!r}).',
2992
+ )
2993
+
2994
+ def __get__(self, instance, owner=None):
2995
+ if instance is None:
2996
+ return self
2997
+ if self.attrname is None:
2998
+ raise TypeError('Cannot use cached_property instance without calling __set_name__ on it.')
2999
+
3000
+ try:
3001
+ cache = instance.__dict__
3002
+ except AttributeError: # not all objects have __dict__ (e.g. class defines slots)
3003
+ raise TypeError(
3004
+ f"No '__dict__' attribute on {type(instance).__name__!r} instance to cache {self.attrname!r} property.",
3005
+ ) from None
3006
+
3007
+ val = cache.get(self.attrname, self._NOT_FOUND)
3008
+
3009
+ if val is self._NOT_FOUND:
3010
+ val = self.func(instance)
3011
+ try:
3012
+ cache[self.attrname] = val
3013
+ except TypeError:
3014
+ raise TypeError(
3015
+ f"The '__dict__' attribute on {type(instance).__name__!r} instance does not support item "
3016
+ f"assignment for caching {self.attrname!r} property.",
3017
+ ) from None
3018
+
3019
+ return val
3020
+
3021
+
3022
+ globals()['cached_property'] = _cached_property
3023
+
3024
+
2899
3025
  ########################################
2900
3026
  # ../../../omlish/lite/check.py
2901
3027
  """
@@ -7234,8 +7360,6 @@ class _JustMaybe(_Maybe[T]):
7234
7360
  __slots__ = ('_v', '_hash')
7235
7361
 
7236
7362
  def __init__(self, v: T) -> None:
7237
- super().__init__()
7238
-
7239
7363
  self._v = v
7240
7364
 
7241
7365
  @property
@@ -1870,6 +1870,8 @@ class AttrOps(ta.Generic[T]):
1870
1870
  display: ta.Optional[str] = None,
1871
1871
 
1872
1872
  repr: bool = True, # noqa
1873
+ repr_fn: ta.Optional[ta.Callable[[ta.Any], ta.Optional[str]]] = None,
1874
+
1873
1875
  hash: bool = True, # noqa
1874
1876
  eq: bool = True,
1875
1877
  ) -> None:
@@ -1884,6 +1886,8 @@ class AttrOps(ta.Generic[T]):
1884
1886
  self._display = display
1885
1887
 
1886
1888
  self._repr = repr
1889
+ self._repr_fn = repr_fn
1890
+
1887
1891
  self._hash = hash
1888
1892
  self._eq = eq
1889
1893
 
@@ -1891,10 +1895,10 @@ class AttrOps(ta.Generic[T]):
1891
1895
  def of(
1892
1896
  cls,
1893
1897
  o: ta.Union[
1898
+ 'AttrOps.Attr',
1894
1899
  str,
1895
- ta.Tuple[str, str],
1900
+ ta.Tuple[str, ta.Union[str, ta.Mapping[str, ta.Any]]],
1896
1901
  ta.Mapping[str, ta.Any],
1897
- 'AttrOps.Attr',
1898
1902
  ],
1899
1903
  ) -> 'AttrOps.Attr':
1900
1904
  if isinstance(o, AttrOps.Attr):
@@ -1902,11 +1906,15 @@ class AttrOps(ta.Generic[T]):
1902
1906
  elif isinstance(o, str):
1903
1907
  return cls(o)
1904
1908
  elif isinstance(o, tuple):
1905
- name, disp = o
1906
- return cls(
1907
- name,
1908
- display=disp,
1909
- )
1909
+ name, x = o
1910
+ kw: ta.Mapping[str, ta.Any]
1911
+ if isinstance(x, str):
1912
+ kw = dict(display=x)
1913
+ elif isinstance(x, ta.Mapping):
1914
+ kw = x
1915
+ else:
1916
+ raise TypeError(x)
1917
+ return cls(name, **kw)
1910
1918
  elif isinstance(o, ta.Mapping):
1911
1919
  return cls(**o)
1912
1920
  else:
@@ -1928,20 +1936,34 @@ class AttrOps(ta.Generic[T]):
1928
1936
  def eq(self) -> bool:
1929
1937
  return self._eq
1930
1938
 
1939
+ @staticmethod
1940
+ def opt_repr(o: ta.Any) -> ta.Optional[str]:
1941
+ return repr(o) if o is not None else None
1942
+
1943
+ @staticmethod
1944
+ def truthy_repr(o: ta.Any) -> ta.Optional[str]:
1945
+ return repr(o) if o else None
1946
+
1947
+ #
1948
+
1931
1949
  @ta.overload
1932
1950
  def __init__(
1933
1951
  self,
1934
1952
  *attrs: ta.Sequence[ta.Union[
1935
1953
  str,
1936
- ta.Tuple[str, str],
1954
+ ta.Tuple[str, ta.Union[str, ta.Mapping[str, ta.Any]]],
1937
1955
  ta.Mapping[str, ta.Any],
1938
1956
  Attr,
1939
1957
  ]],
1958
+
1940
1959
  with_module: bool = False,
1941
1960
  use_qualname: bool = False,
1942
1961
  with_id: bool = False,
1962
+ terse: bool = False,
1943
1963
  repr_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = None,
1944
1964
  recursive: bool = False,
1965
+
1966
+ cache_hash: ta.Union[bool, str] = False,
1945
1967
  subtypes_eq: bool = False,
1946
1968
  ) -> None:
1947
1969
  ...
@@ -1951,16 +1973,20 @@ class AttrOps(ta.Generic[T]):
1951
1973
  self,
1952
1974
  attrs_fn: ta.Callable[[T], ta.Tuple[ta.Union[
1953
1975
  ta.Any,
1954
- ta.Tuple[str, ta.Any],
1976
+ ta.Tuple[ta.Any, ta.Union[str, ta.Mapping[str, ta.Any]]],
1955
1977
  Attr,
1956
1978
  ], ...]],
1957
1979
  /,
1958
1980
  *,
1981
+
1959
1982
  with_module: bool = False,
1960
1983
  use_qualname: bool = False,
1961
1984
  with_id: bool = False,
1985
+ terse: bool = False,
1962
1986
  repr_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = None,
1963
1987
  recursive: bool = False,
1988
+
1989
+ cache_hash: ta.Union[bool, str] = False,
1964
1990
  subtypes_eq: bool = False,
1965
1991
  ) -> None:
1966
1992
  ...
@@ -1968,11 +1994,15 @@ class AttrOps(ta.Generic[T]):
1968
1994
  def __init__(
1969
1995
  self,
1970
1996
  *args,
1997
+
1971
1998
  with_module=False,
1972
1999
  use_qualname=False,
1973
2000
  with_id=False,
2001
+ terse=False,
1974
2002
  repr_filter=None,
1975
2003
  recursive=False,
2004
+
2005
+ cache_hash=False,
1976
2006
  subtypes_eq=False,
1977
2007
  ) -> None:
1978
2008
  if args and len(args) == 1 and callable(args[0]):
@@ -1983,8 +2013,11 @@ class AttrOps(ta.Generic[T]):
1983
2013
  self._with_module: bool = with_module
1984
2014
  self._use_qualname: bool = use_qualname
1985
2015
  self._with_id: bool = with_id
2016
+ self._terse: bool = terse
1986
2017
  self._repr_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = repr_filter
1987
2018
  self._recursive: bool = recursive
2019
+
2020
+ self._cache_hash: ta.Union[bool, str] = cache_hash
1988
2021
  self._subtypes_eq: bool = subtypes_eq
1989
2022
 
1990
2023
  @property
@@ -2023,16 +2056,23 @@ class AttrOps(ta.Generic[T]):
2023
2056
  attrs.append(AttrOps.Attr.of(o))
2024
2057
  continue
2025
2058
 
2059
+ kw: ta.Mapping[str, ta.Any]
2026
2060
  if isinstance(o, tuple):
2027
- disp, cap, = o
2061
+ cap, x = o
2062
+ if isinstance(x, str):
2063
+ kw = dict(display=x)
2064
+ elif isinstance(x, ta.Mapping):
2065
+ kw = x
2066
+ else:
2067
+ raise TypeError(x)
2028
2068
  else:
2029
- disp, cap = None, o
2069
+ cap, kw = o, {}
2030
2070
 
2031
2071
  path = tuple(rec(cap))
2032
2072
 
2033
2073
  attrs.append(AttrOps.Attr(
2034
2074
  '.'.join(path),
2035
- display=disp,
2075
+ **kw,
2036
2076
  ))
2037
2077
 
2038
2078
  return attrs
@@ -2049,19 +2089,27 @@ class AttrOps(ta.Generic[T]):
2049
2089
  pass
2050
2090
 
2051
2091
  def _repr(o: T) -> str:
2052
- vs = ', '.join(
2053
- f'{a._display}={v!r}' # noqa
2054
- for a in self._attrs
2055
- if a._repr # noqa
2056
- for v in [getattr(o, a._name)] # noqa
2057
- if self._repr_filter is None or self._repr_filter(v)
2058
- )
2092
+ vs: ta.List[str] = []
2093
+ for a in self._attrs:
2094
+ if not a._repr: # noqa
2095
+ continue
2096
+ v = getattr(o, a._name) # noqa
2097
+ if self._repr_filter is not None and not self._repr_filter(v):
2098
+ continue
2099
+ if (rfn := a._repr_fn) is None: # noqa
2100
+ rfn = repr
2101
+ if (vr := rfn(v)) is None:
2102
+ continue
2103
+ if self._terse:
2104
+ vs.append(vr)
2105
+ else:
2106
+ vs.append(f'{a._display}={vr}') # noqa
2059
2107
 
2060
2108
  return (
2061
2109
  f'{o.__class__.__module__ + "." if self._with_module else ""}'
2062
2110
  f'{o.__class__.__qualname__ if self._use_qualname else o.__class__.__name__}'
2063
2111
  f'{("@" + hex(id(o))[2:]) if self._with_id else ""}' # noqa
2064
- f'({vs})'
2112
+ f'({", ".join(vs)})'
2065
2113
  )
2066
2114
 
2067
2115
  if self._recursive:
@@ -2086,6 +2134,8 @@ class AttrOps(ta.Generic[T]):
2086
2134
 
2087
2135
  #
2088
2136
 
2137
+ _DEFAULT_CACHED_HASH_ATTR: ta.ClassVar[str] = '__cached_hash__'
2138
+
2089
2139
  _hash: ta.Callable[[T], int]
2090
2140
 
2091
2141
  @property
@@ -2095,13 +2145,33 @@ class AttrOps(ta.Generic[T]):
2095
2145
  except AttributeError:
2096
2146
  pass
2097
2147
 
2098
- def _hash(o: T) -> int:
2148
+ def _calc_hash(o: T) -> int:
2099
2149
  return hash(tuple(
2100
2150
  getattr(o, a._name) # noqa
2101
2151
  for a in self._attrs
2102
2152
  if a._hash # noqa
2103
2153
  ))
2104
2154
 
2155
+ if (ch := self._cache_hash) is not False:
2156
+ if ch is True:
2157
+ cha = self._DEFAULT_CACHED_HASH_ATTR
2158
+ elif isinstance(ch, str):
2159
+ cha = ch
2160
+ else:
2161
+ raise TypeError(ch)
2162
+
2163
+ def _cached_hash(o: T) -> int:
2164
+ try:
2165
+ return object.__getattribute__(o, cha)
2166
+ except AttributeError:
2167
+ object.__setattr__(o, cha, h := _calc_hash(o))
2168
+ return h
2169
+
2170
+ _hash = _cached_hash
2171
+
2172
+ else:
2173
+ _hash = _calc_hash
2174
+
2105
2175
  self._hash = _hash
2106
2176
  return _hash
2107
2177
 
@@ -2242,6 +2312,62 @@ def async_cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
2242
2312
  return _AsyncCachedNullary(fn)
2243
2313
 
2244
2314
 
2315
+ ##
2316
+
2317
+
2318
+ cached_property = functools.cached_property
2319
+
2320
+
2321
+ class _cached_property: # noqa
2322
+ """Backported to pick up https://github.com/python/cpython/commit/056dfc71dce15f81887f0bd6da09d6099d71f979 ."""
2323
+
2324
+ def __init__(self, func):
2325
+ self.func = func
2326
+ self.attrname = None # noqa
2327
+ self.__doc__ = func.__doc__
2328
+ self.__module__ = func.__module__
2329
+
2330
+ _NOT_FOUND = object()
2331
+
2332
+ def __set_name__(self, owner, name):
2333
+ if self.attrname is None:
2334
+ self.attrname = name # noqa
2335
+ elif name != self.attrname:
2336
+ raise TypeError(
2337
+ f'Cannot assign the same cached_property to two different names ({self.attrname!r} and {name!r}).',
2338
+ )
2339
+
2340
+ def __get__(self, instance, owner=None):
2341
+ if instance is None:
2342
+ return self
2343
+ if self.attrname is None:
2344
+ raise TypeError('Cannot use cached_property instance without calling __set_name__ on it.')
2345
+
2346
+ try:
2347
+ cache = instance.__dict__
2348
+ except AttributeError: # not all objects have __dict__ (e.g. class defines slots)
2349
+ raise TypeError(
2350
+ f"No '__dict__' attribute on {type(instance).__name__!r} instance to cache {self.attrname!r} property.",
2351
+ ) from None
2352
+
2353
+ val = cache.get(self.attrname, self._NOT_FOUND)
2354
+
2355
+ if val is self._NOT_FOUND:
2356
+ val = self.func(instance)
2357
+ try:
2358
+ cache[self.attrname] = val
2359
+ except TypeError:
2360
+ raise TypeError(
2361
+ f"The '__dict__' attribute on {type(instance).__name__!r} instance does not support item "
2362
+ f"assignment for caching {self.attrname!r} property.",
2363
+ ) from None
2364
+
2365
+ return val
2366
+
2367
+
2368
+ globals()['cached_property'] = _cached_property
2369
+
2370
+
2245
2371
  ########################################
2246
2372
  # ../../../omlish/lite/check.py
2247
2373
  """
@@ -4120,6 +4246,70 @@ def build_config_named_children(
4120
4246
  return lst
4121
4247
 
4122
4248
 
4249
+ ########################################
4250
+ # ../../../omlish/http/coro/io.py
4251
+
4252
+
4253
+ ##
4254
+
4255
+
4256
+ class CoroHttpIo:
4257
+ def __new__(cls, *args, **kwargs): # noqa
4258
+ raise TypeError
4259
+
4260
+ def __init_subclass__(cls, **kwargs): # noqa
4261
+ raise TypeError
4262
+
4263
+ #
4264
+
4265
+ MAX_LINE: ta.ClassVar[int] = 65536
4266
+
4267
+ #
4268
+
4269
+ class Io(Abstract):
4270
+ pass
4271
+
4272
+ #
4273
+
4274
+ class AnyLogIo(Io, Abstract):
4275
+ pass
4276
+
4277
+ #
4278
+
4279
+ @dc.dataclass(frozen=True)
4280
+ class ConnectIo(Io):
4281
+ args: ta.Tuple[ta.Any, ...]
4282
+ kwargs: ta.Optional[ta.Dict[str, ta.Any]] = None
4283
+
4284
+ #
4285
+
4286
+ class CloseIo(Io):
4287
+ pass
4288
+
4289
+ #
4290
+
4291
+ class AnyReadIo(Io): # noqa
4292
+ pass
4293
+
4294
+ @dc.dataclass(frozen=True)
4295
+ class ReadIo(AnyReadIo):
4296
+ sz: ta.Optional[int]
4297
+
4298
+ @dc.dataclass(frozen=True)
4299
+ class ReadLineIo(AnyReadIo):
4300
+ sz: int
4301
+
4302
+ @dc.dataclass(frozen=True)
4303
+ class PeekIo(AnyReadIo):
4304
+ sz: int
4305
+
4306
+ #
4307
+
4308
+ @dc.dataclass(frozen=True)
4309
+ class WriteIo(Io):
4310
+ data: bytes
4311
+
4312
+
4123
4313
  ########################################
4124
4314
  # ../../../omlish/http/parsing.py
4125
4315
  # PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -6020,8 +6210,6 @@ class _JustMaybe(_Maybe[T]):
6020
6210
  __slots__ = ('_v', '_hash')
6021
6211
 
6022
6212
  def __init__(self, v: T) -> None:
6023
- super().__init__()
6024
-
6025
6213
  self._v = v
6026
6214
 
6027
6215
  @property
@@ -9398,48 +9586,21 @@ class CoroHttpServer:
9398
9586
 
9399
9587
  #
9400
9588
 
9401
- class Io(Abstract):
9402
- pass
9403
-
9404
- #
9405
-
9406
- class AnyLogIo(Io):
9407
- pass
9408
-
9409
9589
  @dc.dataclass(frozen=True)
9410
- class ParsedRequestLogIo(AnyLogIo):
9590
+ class ParsedRequestLogIo(CoroHttpIo.AnyLogIo):
9411
9591
  request: ParsedHttpRequest
9412
9592
 
9413
9593
  @dc.dataclass(frozen=True)
9414
- class ErrorLogIo(AnyLogIo):
9594
+ class ErrorLogIo(CoroHttpIo.AnyLogIo):
9415
9595
  error: 'CoroHttpServer.Error'
9416
9596
 
9417
9597
  #
9418
9598
 
9419
- class AnyReadIo(Io): # noqa
9420
- pass
9421
-
9422
- @dc.dataclass(frozen=True)
9423
- class ReadIo(AnyReadIo):
9424
- sz: int
9425
-
9426
- @dc.dataclass(frozen=True)
9427
- class ReadLineIo(AnyReadIo):
9428
- sz: int
9429
-
9430
- #
9431
-
9432
- @dc.dataclass(frozen=True)
9433
- class WriteIo(Io):
9434
- data: bytes
9435
-
9436
- #
9437
-
9438
9599
  @dc.dataclass(frozen=True)
9439
9600
  class CoroHandleResult:
9440
9601
  close_reason: ta.Literal['response', 'internal', None] = None
9441
9602
 
9442
- def coro_handle(self) -> ta.Generator[Io, ta.Optional[bytes], CoroHandleResult]:
9603
+ def coro_handle(self) -> ta.Generator[CoroHttpIo.Io, ta.Optional[bytes], CoroHandleResult]:
9443
9604
  return self._coro_run_handler(self._coro_handle_one())
9444
9605
 
9445
9606
  class Close(Exception): # noqa
@@ -9448,20 +9609,20 @@ class CoroHttpServer:
9448
9609
  def _coro_run_handler(
9449
9610
  self,
9450
9611
  gen: ta.Generator[
9451
- ta.Union[AnyLogIo, AnyReadIo, _Response],
9612
+ ta.Union[CoroHttpIo.AnyLogIo, CoroHttpIo.AnyReadIo, _Response],
9452
9613
  ta.Optional[bytes],
9453
9614
  None,
9454
9615
  ],
9455
- ) -> ta.Generator[Io, ta.Optional[bytes], CoroHandleResult]:
9616
+ ) -> ta.Generator[CoroHttpIo.Io, ta.Optional[bytes], CoroHandleResult]:
9456
9617
  i: ta.Optional[bytes]
9457
9618
  o: ta.Any = next(gen)
9458
9619
  while True:
9459
9620
  try:
9460
- if isinstance(o, self.AnyLogIo):
9621
+ if isinstance(o, CoroHttpIo.AnyLogIo):
9461
9622
  i = None
9462
9623
  yield o
9463
9624
 
9464
- elif isinstance(o, self.AnyReadIo):
9625
+ elif isinstance(o, CoroHttpIo.AnyReadIo):
9465
9626
  i = check.isinstance((yield o), bytes)
9466
9627
 
9467
9628
  elif isinstance(o, self._Response):
@@ -9469,10 +9630,10 @@ class CoroHttpServer:
9469
9630
 
9470
9631
  r = self._preprocess_response(o)
9471
9632
  hb = self._build_response_head_bytes(r)
9472
- check.none((yield self.WriteIo(hb)))
9633
+ check.none((yield CoroHttpIo.WriteIo(hb)))
9473
9634
 
9474
9635
  for b in self._yield_response_data(r):
9475
- yield self.WriteIo(b)
9636
+ yield CoroHttpIo.WriteIo(b)
9476
9637
 
9477
9638
  o.close()
9478
9639
  if o.close_connection:
@@ -9500,7 +9661,7 @@ class CoroHttpServer:
9500
9661
  raise
9501
9662
 
9502
9663
  def _coro_handle_one(self) -> ta.Generator[
9503
- ta.Union[AnyLogIo, AnyReadIo, _Response],
9664
+ ta.Union[CoroHttpIo.AnyLogIo, CoroHttpIo.AnyReadIo, _Response],
9504
9665
  ta.Optional[bytes],
9505
9666
  None,
9506
9667
  ]:
@@ -9510,7 +9671,7 @@ class CoroHttpServer:
9510
9671
  sz = next(gen)
9511
9672
  while True:
9512
9673
  try:
9513
- line = check.isinstance((yield self.ReadLineIo(sz)), bytes)
9674
+ line = check.isinstance((yield CoroHttpIo.ReadLineIo(sz)), bytes)
9514
9675
  sz = gen.send(line)
9515
9676
  except StopIteration as e:
9516
9677
  parsed = e.value
@@ -9549,7 +9710,7 @@ class CoroHttpServer:
9549
9710
 
9550
9711
  request_data: ta.Optional[bytes]
9551
9712
  if (cl := parsed.headers.get('Content-Length')) is not None:
9552
- request_data = check.isinstance((yield self.ReadIo(int(cl))), bytes)
9713
+ request_data = check.isinstance((yield CoroHttpIo.ReadIo(int(cl))), bytes)
9553
9714
  else:
9554
9715
  request_data = None
9555
9716
 
@@ -10609,7 +10770,7 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
10609
10770
  *,
10610
10771
  read_size: int = 0x10000,
10611
10772
  write_size: int = 0x10000,
10612
- log_handler: ta.Optional[ta.Callable[[CoroHttpServer, CoroHttpServer.AnyLogIo], None]] = None,
10773
+ log_handler: ta.Optional[ta.Callable[[CoroHttpServer, CoroHttpIo.AnyLogIo], None]] = None,
10613
10774
  ) -> None:
10614
10775
  check.state(not sock.getblocking())
10615
10776
 
@@ -10629,13 +10790,13 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
10629
10790
  )
10630
10791
  self._srv_coro: ta.Optional[
10631
10792
  ta.Generator[
10632
- CoroHttpServer.Io,
10793
+ CoroHttpIo.Io,
10633
10794
  ta.Optional[bytes],
10634
10795
  CoroHttpServer.CoroHandleResult,
10635
10796
  ],
10636
10797
  ] = self._coro_srv.coro_handle()
10637
10798
 
10638
- self._cur_io: ta.Optional[CoroHttpServer.Io] = None
10799
+ self._cur_io: ta.Optional[CoroHttpIo.Io] = None
10639
10800
  self._next_io()
10640
10801
 
10641
10802
  #
@@ -10658,22 +10819,22 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
10658
10819
  o = None
10659
10820
  break
10660
10821
 
10661
- if isinstance(o, CoroHttpServer.AnyLogIo):
10822
+ if isinstance(o, CoroHttpIo.AnyLogIo):
10662
10823
  if self._log_handler is not None:
10663
10824
  self._log_handler(self._coro_srv, o)
10664
10825
  o = None
10665
10826
 
10666
- elif isinstance(o, CoroHttpServer.ReadIo):
10827
+ elif isinstance(o, CoroHttpIo.ReadIo):
10667
10828
  if (d := self._read_buf.read(o.sz)) is None:
10668
10829
  break
10669
10830
  o = None
10670
10831
 
10671
- elif isinstance(o, CoroHttpServer.ReadLineIo):
10832
+ elif isinstance(o, CoroHttpIo.ReadLineIo):
10672
10833
  if (d := self._read_buf.read_until(b'\n')) is None:
10673
10834
  break
10674
10835
  o = None
10675
10836
 
10676
- elif isinstance(o, CoroHttpServer.WriteIo):
10837
+ elif isinstance(o, CoroHttpIo.WriteIo):
10677
10838
  check.none(self._write_buf)
10678
10839
  self._write_buf = IncrementalWriteBuffer(o.data, write_size=self._write_size)
10679
10840
  break
@@ -10707,11 +10868,11 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
10707
10868
 
10708
10869
  self._read_buf.feed(buf)
10709
10870
 
10710
- if isinstance(self._cur_io, CoroHttpServer.AnyReadIo):
10871
+ if isinstance(self._cur_io, CoroHttpIo.AnyReadIo):
10711
10872
  self._next_io()
10712
10873
 
10713
10874
  def on_writable(self) -> None:
10714
- check.isinstance(self._cur_io, CoroHttpServer.WriteIo)
10875
+ check.isinstance(self._cur_io, CoroHttpIo.WriteIo)
10715
10876
  wb = check.not_none(self._write_buf)
10716
10877
  while wb.rem > 0:
10717
10878
  def send(d: bytes) -> int:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ominfra
3
- Version: 0.0.0.dev440
3
+ Version: 0.0.0.dev442
4
4
  Summary: ominfra
5
5
  Author: wrmsr
6
6
  License-Expression: BSD-3-Clause
@@ -14,8 +14,8 @@ Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Python: >=3.13
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
- Requires-Dist: omdev==0.0.0.dev440
18
- Requires-Dist: omlish==0.0.0.dev440
17
+ Requires-Dist: omdev==0.0.0.dev442
18
+ Requires-Dist: omlish==0.0.0.dev442
19
19
  Provides-Extra: all
20
20
  Requires-Dist: paramiko~=4.0; extra == "all"
21
21
  Requires-Dist: asyncssh~=2.21; extra == "all"
@@ -14,7 +14,7 @@ ominfra/clouds/aws/logs.py,sha256=SW8ebBJrUTDG0dnYIld4zbWNVCkAHzFZq4kpn76yWTo,54
14
14
  ominfra/clouds/aws/metadata.py,sha256=71LtmJxjdlp_HN19zXQTX4ZLO4KI5LLiQ6fHuF8vUis,2772
15
15
  ominfra/clouds/aws/instancetypes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  ominfra/clouds/aws/instancetypes/__main__.py,sha256=Jsrv3P7LX2Cg08W7ByZfZ1JQT4lgLDPW1qNAmShFuMk,75
17
- ominfra/clouds/aws/instancetypes/cache.json.gz,sha256=bvkYajX5OAdbGtrx5fJ-oQ8sCKm0X8Rk9_4rZuYBcps,31494
17
+ ominfra/clouds/aws/instancetypes/cache.json.gz,sha256=DSlV4qQgnsPBLPVAsuk67BhbagwELfQ5ZJ3ocGdppSQ,33174
18
18
  ominfra/clouds/aws/instancetypes/cache.py,sha256=tEH7bH6kTTqgXcwsNk5Rf7eCf14vsnEHMV6q-PbZc4M,338
19
19
  ominfra/clouds/aws/instancetypes/cli.py,sha256=yNxUZjbud5M9tBZZbfiswa8jGQaKJ3YVwxFIMQTo2sA,2207
20
20
  ominfra/clouds/aws/journald2aws/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
@@ -30,7 +30,7 @@ ominfra/clouds/aws/models/gen/__main__.py,sha256=Jsrv3P7LX2Cg08W7ByZfZ1JQT4lgLDP
30
30
  ominfra/clouds/aws/models/gen/cli.py,sha256=vcI8_-BOv4f-s_TFAqvnyzvBexZ_9y5akiUEGfioCqA,3857
31
31
  ominfra/clouds/aws/models/gen/gen.py,sha256=4pftOlyEIxDDoe73c5Z7NaJ1uhFsTBnMwmS1nlDiLOE,15903
32
32
  ominfra/clouds/aws/models/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
- ominfra/clouds/aws/models/services/ec2.py,sha256=xZx6gSu9rvwVjyjMHtvv4DHubZ2XpBnVAD3YI9SHLQE,281209
33
+ ominfra/clouds/aws/models/services/ec2.py,sha256=oKa2jk-6BRrgFnTZNvDG15b6K5wbn6sq5evVG6f7N6U,281283
34
34
  ominfra/clouds/aws/models/services/lambda_.py,sha256=dp2I4ZVDb6Dci15XcjPPURUElyzH8cwhM911J_HM7Qo,25823
35
35
  ominfra/clouds/aws/models/services/rds.py,sha256=ziHgTwFZwl2FnyOyZMg3yJT_29-e0Z4RXBtWUaFfRr4,60108
36
36
  ominfra/clouds/aws/models/services/s3.py,sha256=aWbl4YtAiQyBfcNgerNxfWBIHZsbpFlT66JdRBYnQ9c,51426
@@ -112,9 +112,9 @@ ominfra/manage/targets/connection.py,sha256=mOHCsDVG-DZBhl3Mb7TTr1vhPb0gxDOOMW1x
112
112
  ominfra/manage/targets/inject.py,sha256=3M4wBkxtvymq_yhiotHlTN8iydELMjVCndyp9Bq-4eo,1572
113
113
  ominfra/manage/targets/targets.py,sha256=LjSQrDsHEjEQMDHcxtNKmLjy0YGLXJRGPFdUjazzFIM,1918
114
114
  ominfra/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
115
- ominfra/scripts/journald2aws.py,sha256=9DWt-aBq8D247C80cgp6xzDPujHAi4iRtpC0Sj2_5xs,242632
116
- ominfra/scripts/manage.py,sha256=xYZht72US3brB1xJI6XonccohRFIfflNR1OjlMvZh4I,466569
117
- ominfra/scripts/supervisor.py,sha256=KodoaDPmIqOLXGoVdh0t-lqA3dKSUVIXqPgirA4yn38,376188
115
+ ominfra/scripts/journald2aws.py,sha256=qLfqpuWE7xU7lyfctgU5Wbz3HmhXWjqlEpxDr3ZQkx4,246638
116
+ ominfra/scripts/manage.py,sha256=3mhCCk_aC2xn0je6MdYiS3ybnFnk3CYWGxkjo_be3ck,470547
117
+ ominfra/scripts/supervisor.py,sha256=52lSprHBuOgRZ2Z2pWued2k6nEMDzRMrogHbrh3ZDEA,380857
118
118
  ominfra/supervisor/LICENSE.txt,sha256=ZrHY15PVR98y26Yg6iQfa-SXnUaYTDhrUsPVcEO5OKM,1874
119
119
  ominfra/supervisor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
120
120
  ominfra/supervisor/__main__.py,sha256=I0yFw-C08OOiZ3BF6lF1Oiv789EQXu-_j6whDhQUTEA,66
@@ -156,9 +156,9 @@ ominfra/tailscale/api.py,sha256=XASv9C_CWI-u-yX5jVzhJrkJhlwQRkYQWQQG1uJwAd8,1375
156
156
  ominfra/tailscale/cli.py,sha256=zRV7-tKB7kBah1oTVZlol-vwx1FBlnfzYAPGkeU5jX4,3543
157
157
  ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
158
158
  ominfra/tools/listresources.py,sha256=ePmo7cUAiBZARkM_3K4GKYZXxV73An_aioS1m-AAJis,6181
159
- ominfra-0.0.0.dev440.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
160
- ominfra-0.0.0.dev440.dist-info/METADATA,sha256=gA2kUkRYpjv71ka0JLc_GgMy6b5ADK8gcbTrsmHi-k4,2377
161
- ominfra-0.0.0.dev440.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
162
- ominfra-0.0.0.dev440.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
163
- ominfra-0.0.0.dev440.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
164
- ominfra-0.0.0.dev440.dist-info/RECORD,,
159
+ ominfra-0.0.0.dev442.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
160
+ ominfra-0.0.0.dev442.dist-info/METADATA,sha256=gLYd-7PEZ3fwaodczxQ9kzdd-DHRtDSaO5jdW2f7Eqo,2377
161
+ ominfra-0.0.0.dev442.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
162
+ ominfra-0.0.0.dev442.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
163
+ ominfra-0.0.0.dev442.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
164
+ ominfra-0.0.0.dev442.dist-info/RECORD,,