ominfra 0.0.0.dev217__py3-none-any.whl → 0.0.0.dev218__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.
@@ -142,10 +142,6 @@ ConfigDataT = ta.TypeVar('ConfigDataT', bound='ConfigData')
142
142
  # ../../omlish/http/parsing.py
143
143
  HttpHeaders = http.client.HTTPMessage # ta.TypeAlias
144
144
 
145
- # ../../omlish/lite/contextmanagers.py
146
- ExitStackedT = ta.TypeVar('ExitStackedT', bound='ExitStacked')
147
- AsyncExitStackedT = ta.TypeVar('AsyncExitStackedT', bound='AsyncExitStacked')
148
-
149
145
  # ../../omlish/lite/inject.py
150
146
  U = ta.TypeVar('U')
151
147
  InjectorKeyCls = ta.Union[type, ta.NewType]
@@ -154,10 +150,11 @@ InjectorProviderFnMap = ta.Mapping['InjectorKey', 'InjectorProviderFn']
154
150
  InjectorBindingOrBindings = ta.Union['InjectorBinding', 'InjectorBindings']
155
151
 
156
152
  # ../../omlish/sockets/handlers.py
157
- SocketHandlerFactory = ta.Callable[[SocketAddress, ta.BinaryIO, ta.BinaryIO], 'SocketHandler']
153
+ SocketHandler = ta.Callable[[SocketAddress, 'SocketIoPair'], None] # ta.TypeAlias
158
154
 
159
155
  # ../../omlish/http/handlers.py
160
156
  HttpHandler = ta.Callable[['HttpHandlerRequest'], 'HttpHandlerResponse'] # ta.TypeAlias
157
+ HttpHandlerResponseData = ta.Union[bytes, 'HttpHandlerResponseStreamedData'] # ta.TypeAlias # noqa
161
158
 
162
159
  # ../../omlish/http/coro/server.py
163
160
  CoroHttpServerFactory = ta.Callable[[SocketAddress], 'CoroHttpServer']
@@ -2812,8 +2809,7 @@ class ProxyLogHandler(ProxyLogFilterer, logging.Handler):
2812
2809
  # ../../../omlish/sockets/addresses.py
2813
2810
  """
2814
2811
  TODO:
2815
- - SocketClientAddress family / tuple pairs
2816
- + codification of https://docs.python.org/3/library/socket.html#socket-families
2812
+ - codification of https://docs.python.org/3/library/socket.html#socket-families
2817
2813
  """
2818
2814
 
2819
2815
 
@@ -2839,11 +2835,16 @@ class SocketAddressInfo:
2839
2835
  sockaddr: SocketAddress
2840
2836
 
2841
2837
 
2838
+ class SocketFamilyAndAddress(ta.NamedTuple):
2839
+ family: socket.AddressFamily
2840
+ address: SocketAddress
2841
+
2842
+
2842
2843
  def get_best_socket_family(
2843
2844
  host: ta.Optional[str],
2844
2845
  port: ta.Union[str, int, None],
2845
2846
  family: ta.Union[int, socket.AddressFamily] = socket.AddressFamily.AF_UNSPEC,
2846
- ) -> ta.Tuple[socket.AddressFamily, SocketAddress]:
2847
+ ) -> SocketFamilyAndAddress:
2847
2848
  """https://github.com/python/cpython/commit/f289084c83190cc72db4a70c58f007ec62e75247"""
2848
2849
 
2849
2850
  infos = socket.getaddrinfo(
@@ -2854,7 +2855,80 @@ def get_best_socket_family(
2854
2855
  flags=socket.AI_PASSIVE,
2855
2856
  )
2856
2857
  ai = SocketAddressInfo(*next(iter(infos)))
2857
- return ai.family, ai.sockaddr
2858
+ return SocketFamilyAndAddress(ai.family, ai.sockaddr)
2859
+
2860
+
2861
+ class SocketAndAddress(ta.NamedTuple):
2862
+ socket: socket.socket
2863
+ address: SocketAddress
2864
+
2865
+
2866
+ ########################################
2867
+ # ../../../omlish/sockets/io.py
2868
+
2869
+
2870
+ ##
2871
+
2872
+
2873
+ class SocketWriter(io.BufferedIOBase):
2874
+ """
2875
+ Simple writable BufferedIOBase implementation for a socket
2876
+
2877
+ Does not hold data in a buffer, avoiding any need to call flush().
2878
+ """
2879
+
2880
+ def __init__(self, sock):
2881
+ super().__init__()
2882
+
2883
+ self._sock = sock
2884
+
2885
+ def writable(self):
2886
+ return True
2887
+
2888
+ def write(self, b):
2889
+ self._sock.sendall(b)
2890
+ with memoryview(b) as view:
2891
+ return view.nbytes
2892
+
2893
+ def fileno(self):
2894
+ return self._sock.fileno()
2895
+
2896
+
2897
+ class SocketIoPair(ta.NamedTuple):
2898
+ r: ta.BinaryIO
2899
+ w: ta.BinaryIO
2900
+
2901
+ @classmethod
2902
+ def from_socket(
2903
+ cls,
2904
+ sock: socket.socket,
2905
+ *,
2906
+ r_buf_size: int = -1,
2907
+ w_buf_size: int = 0,
2908
+ ) -> 'SocketIoPair':
2909
+ rf: ta.Any = sock.makefile('rb', r_buf_size)
2910
+
2911
+ if w_buf_size:
2912
+ wf: ta.Any = SocketWriter(sock)
2913
+ else:
2914
+ wf = sock.makefile('wb', w_buf_size)
2915
+
2916
+ return cls(rf, wf)
2917
+
2918
+
2919
+ ##
2920
+
2921
+
2922
+ def close_socket_immediately(sock: socket.socket) -> None:
2923
+ try:
2924
+ # Explicitly shutdown. socket.close() merely releases the socket and waits for GC to perform the actual close.
2925
+ sock.shutdown(socket.SHUT_WR)
2926
+
2927
+ except OSError:
2928
+ # Some platforms may raise ENOTCONN here
2929
+ pass
2930
+
2931
+ sock.close()
2858
2932
 
2859
2933
 
2860
2934
  ########################################
@@ -4426,116 +4500,6 @@ else:
4426
4500
  KqueueFdioPoller = None
4427
4501
 
4428
4502
 
4429
- ########################################
4430
- # ../../../omlish/lite/contextmanagers.py
4431
-
4432
-
4433
- ##
4434
-
4435
-
4436
- class ExitStacked:
4437
- _exit_stack: ta.Optional[contextlib.ExitStack] = None
4438
-
4439
- def __enter__(self: ExitStackedT) -> ExitStackedT:
4440
- check.state(self._exit_stack is None)
4441
- es = self._exit_stack = contextlib.ExitStack()
4442
- es.__enter__()
4443
- return self
4444
-
4445
- def __exit__(self, exc_type, exc_val, exc_tb):
4446
- if (es := self._exit_stack) is None:
4447
- return None
4448
- self._exit_contexts()
4449
- return es.__exit__(exc_type, exc_val, exc_tb)
4450
-
4451
- def _exit_contexts(self) -> None:
4452
- pass
4453
-
4454
- def _enter_context(self, cm: ta.ContextManager[T]) -> T:
4455
- es = check.not_none(self._exit_stack)
4456
- return es.enter_context(cm)
4457
-
4458
-
4459
- class AsyncExitStacked:
4460
- _exit_stack: ta.Optional[contextlib.AsyncExitStack] = None
4461
-
4462
- async def __aenter__(self: AsyncExitStackedT) -> AsyncExitStackedT:
4463
- check.state(self._exit_stack is None)
4464
- es = self._exit_stack = contextlib.AsyncExitStack()
4465
- await es.__aenter__()
4466
- return self
4467
-
4468
- async def __aexit__(self, exc_type, exc_val, exc_tb):
4469
- if (es := self._exit_stack) is None:
4470
- return None
4471
- await self._async_exit_contexts()
4472
- return await es.__aexit__(exc_type, exc_val, exc_tb)
4473
-
4474
- async def _async_exit_contexts(self) -> None:
4475
- pass
4476
-
4477
- def _enter_context(self, cm: ta.ContextManager[T]) -> T:
4478
- es = check.not_none(self._exit_stack)
4479
- return es.enter_context(cm)
4480
-
4481
- async def _enter_async_context(self, cm: ta.AsyncContextManager[T]) -> T:
4482
- es = check.not_none(self._exit_stack)
4483
- return await es.enter_async_context(cm)
4484
-
4485
-
4486
- ##
4487
-
4488
-
4489
- @contextlib.contextmanager
4490
- def defer(fn: ta.Callable) -> ta.Generator[ta.Callable, None, None]:
4491
- try:
4492
- yield fn
4493
- finally:
4494
- fn()
4495
-
4496
-
4497
- @contextlib.asynccontextmanager
4498
- async def adefer(fn: ta.Callable) -> ta.AsyncGenerator[ta.Callable, None]:
4499
- try:
4500
- yield fn
4501
- finally:
4502
- await fn()
4503
-
4504
-
4505
- ##
4506
-
4507
-
4508
- @contextlib.contextmanager
4509
- def attr_setting(obj, attr, val, *, default=None): # noqa
4510
- not_set = object()
4511
- orig = getattr(obj, attr, not_set)
4512
- try:
4513
- setattr(obj, attr, val)
4514
- if orig is not not_set:
4515
- yield orig
4516
- else:
4517
- yield default
4518
- finally:
4519
- if orig is not_set:
4520
- delattr(obj, attr)
4521
- else:
4522
- setattr(obj, attr, orig)
4523
-
4524
-
4525
- ##
4526
-
4527
-
4528
- class aclosing(contextlib.AbstractAsyncContextManager): # noqa
4529
- def __init__(self, thing):
4530
- self.thing = thing
4531
-
4532
- async def __aenter__(self):
4533
- return self.thing
4534
-
4535
- async def __aexit__(self, *exc_info):
4536
- await self.thing.aclose()
4537
-
4538
-
4539
4503
  ########################################
4540
4504
  # ../../../omlish/lite/inject.py
4541
4505
 
@@ -6427,24 +6391,6 @@ def journald_log_handler_factory(
6427
6391
  ##
6428
6392
 
6429
6393
 
6430
- class SocketHandler(abc.ABC):
6431
- def __init__(
6432
- self,
6433
- client_address: SocketAddress,
6434
- rfile: ta.BinaryIO,
6435
- wfile: ta.BinaryIO,
6436
- ) -> None:
6437
- super().__init__()
6438
-
6439
- self._client_address = client_address
6440
- self._rfile = rfile
6441
- self._wfile = wfile
6442
-
6443
- @abc.abstractmethod
6444
- def handle(self) -> None:
6445
- raise NotImplementedError
6446
-
6447
-
6448
6394
  ########################################
6449
6395
  # ../configs.py
6450
6396
 
@@ -6865,6 +6811,9 @@ class SupervisorSetup(abc.ABC):
6865
6811
  # ../../../omlish/http/handlers.py
6866
6812
 
6867
6813
 
6814
+ ##
6815
+
6816
+
6868
6817
  @dc.dataclass(frozen=True)
6869
6818
  class HttpHandlerRequest:
6870
6819
  client_address: SocketAddress
@@ -6879,10 +6828,16 @@ class HttpHandlerResponse:
6879
6828
  status: ta.Union[http.HTTPStatus, int]
6880
6829
 
6881
6830
  headers: ta.Optional[ta.Mapping[str, str]] = None
6882
- data: ta.Optional[bytes] = None
6831
+ data: ta.Optional[HttpHandlerResponseData] = None
6883
6832
  close_connection: ta.Optional[bool] = None
6884
6833
 
6885
6834
 
6835
+ @dc.dataclass(frozen=True)
6836
+ class HttpHandlerResponseStreamedData:
6837
+ iter: ta.Iterable[bytes]
6838
+ length: ta.Optional[int] = None
6839
+
6840
+
6886
6841
  class HttpHandlerError(Exception):
6887
6842
  pass
6888
6843
 
@@ -7394,7 +7349,7 @@ class CoroHttpServer:
7394
7349
 
7395
7350
  message: ta.Optional[str] = None
7396
7351
  headers: ta.Optional[ta.Sequence['CoroHttpServer._Header']] = None
7397
- data: ta.Optional[bytes] = None
7352
+ data: ta.Optional[HttpHandlerResponseData] = None
7398
7353
  close_connection: ta.Optional[bool] = False
7399
7354
 
7400
7355
  def get_header(self, key: str) -> ta.Optional['CoroHttpServer._Header']:
@@ -7405,7 +7360,7 @@ class CoroHttpServer:
7405
7360
 
7406
7361
  #
7407
7362
 
7408
- def _build_response_bytes(self, a: _Response) -> bytes:
7363
+ def _build_response_head_bytes(self, a: _Response) -> bytes:
7409
7364
  out = io.BytesIO()
7410
7365
 
7411
7366
  if a.version >= HttpProtocolVersions.HTTP_1_0:
@@ -7420,11 +7375,22 @@ class CoroHttpServer:
7420
7375
 
7421
7376
  out.write(b'\r\n')
7422
7377
 
7423
- if a.data is not None:
7424
- out.write(a.data)
7425
-
7426
7378
  return out.getvalue()
7427
7379
 
7380
+ def _yield_response_data(self, a: _Response) -> ta.Iterator[bytes]:
7381
+ if a.data is None:
7382
+ return
7383
+
7384
+ elif isinstance(a.data, bytes):
7385
+ yield a.data
7386
+ return
7387
+
7388
+ elif isinstance(a.data, HttpHandlerResponseStreamedData):
7389
+ yield from a.data.iter
7390
+
7391
+ else:
7392
+ raise TypeError(a.data)
7393
+
7428
7394
  #
7429
7395
 
7430
7396
  DEFAULT_CONTENT_TYPE = 'text/plain'
@@ -7435,8 +7401,17 @@ class CoroHttpServer:
7435
7401
 
7436
7402
  if resp.get_header('Content-Type') is None:
7437
7403
  nh.append(self._Header('Content-Type', self._default_content_type))
7404
+
7438
7405
  if resp.data is not None and resp.get_header('Content-Length') is None:
7439
- nh.append(self._Header('Content-Length', str(len(resp.data))))
7406
+ cl: ta.Optional[int]
7407
+ if isinstance(resp.data, bytes):
7408
+ cl = len(resp.data)
7409
+ elif isinstance(resp.data, HttpHandlerResponseStreamedData):
7410
+ cl = resp.data.length
7411
+ else:
7412
+ raise TypeError(resp.data)
7413
+ if cl is not None:
7414
+ nh.append(self._Header('Content-Length', str(cl)))
7440
7415
 
7441
7416
  if nh:
7442
7417
  kw.update(headers=[*(resp.headers or []), *nh])
@@ -7610,9 +7585,13 @@ class CoroHttpServer:
7610
7585
 
7611
7586
  elif isinstance(o, self._Response):
7612
7587
  i = None
7588
+
7613
7589
  r = self._preprocess_response(o)
7614
- b = self._build_response_bytes(r)
7615
- check.none((yield self.WriteIo(b)))
7590
+ hb = self._build_response_head_bytes(r)
7591
+ check.none((yield self.WriteIo(hb)))
7592
+
7593
+ for b in self._yield_response_data(r):
7594
+ yield self.WriteIo(b)
7616
7595
 
7617
7596
  else:
7618
7597
  raise TypeError(o)
@@ -7731,27 +7710,20 @@ class CoroHttpServer:
7731
7710
  ##
7732
7711
 
7733
7712
 
7734
- class CoroHttpServerSocketHandler(SocketHandler):
7713
+ class CoroHttpServerSocketHandler: # SocketHandler
7735
7714
  def __init__(
7736
7715
  self,
7737
- client_address: SocketAddress,
7738
- rfile: ta.BinaryIO,
7739
- wfile: ta.BinaryIO,
7740
- *,
7741
7716
  server_factory: CoroHttpServerFactory,
7717
+ *,
7742
7718
  log_handler: ta.Optional[ta.Callable[[CoroHttpServer, CoroHttpServer.AnyLogIo], None]] = None,
7743
7719
  ) -> None:
7744
- super().__init__(
7745
- client_address,
7746
- rfile,
7747
- wfile,
7748
- )
7720
+ super().__init__()
7749
7721
 
7750
7722
  self._server_factory = server_factory
7751
7723
  self._log_handler = log_handler
7752
7724
 
7753
- def handle(self) -> None:
7754
- server = self._server_factory(self._client_address)
7725
+ def __call__(self, client_address: SocketAddress, fp: SocketIoPair) -> None:
7726
+ server = self._server_factory(client_address)
7755
7727
 
7756
7728
  gen = server.coro_handle()
7757
7729
 
@@ -7763,15 +7735,15 @@ class CoroHttpServerSocketHandler(SocketHandler):
7763
7735
  self._log_handler(server, o)
7764
7736
 
7765
7737
  elif isinstance(o, CoroHttpServer.ReadIo):
7766
- i = self._rfile.read(o.sz)
7738
+ i = fp.r.read(o.sz)
7767
7739
 
7768
7740
  elif isinstance(o, CoroHttpServer.ReadLineIo):
7769
- i = self._rfile.readline(o.sz)
7741
+ i = fp.r.readline(o.sz)
7770
7742
 
7771
7743
  elif isinstance(o, CoroHttpServer.WriteIo):
7772
7744
  i = None
7773
- self._wfile.write(o.data)
7774
- self._wfile.flush()
7745
+ fp.w.write(o.data)
7746
+ fp.w.flush()
7775
7747
 
7776
7748
  else:
7777
7749
  raise TypeError(o)
@@ -8877,7 +8849,7 @@ class HttpServer(HasDispatchers):
8877
8849
 
8878
8850
  self._conns: ta.List[CoroHttpServerConnectionFdioHandler] = []
8879
8851
 
8880
- exit_stack.enter_context(defer(self._server.close)) # noqa
8852
+ exit_stack.callback(self._server.close)
8881
8853
 
8882
8854
  def get_dispatchers(self) -> Dispatchers:
8883
8855
  l = []
@@ -10,7 +10,6 @@ from omlish.http.handlers import HttpHandlerRequest
10
10
  from omlish.http.handlers import HttpHandlerResponse
11
11
  from omlish.io.fdio.handlers import SocketFdioHandler
12
12
  from omlish.lite.check import check
13
- from omlish.lite.contextmanagers import defer
14
13
  from omlish.lite.json import JSON_PRETTY_KWARGS
15
14
  from omlish.sockets.addresses import SocketAddress
16
15
 
@@ -73,7 +72,7 @@ class HttpServer(HasDispatchers):
73
72
 
74
73
  self._conns: ta.List[CoroHttpServerConnectionFdioHandler] = []
75
74
 
76
- exit_stack.enter_context(defer(self._server.close)) # noqa
75
+ exit_stack.callback(self._server.close)
77
76
 
78
77
  def get_dispatchers(self) -> Dispatchers:
79
78
  l = []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ominfra
3
- Version: 0.0.0.dev217
3
+ Version: 0.0.0.dev218
4
4
  Summary: ominfra
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,8 +12,8 @@ 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: omdev==0.0.0.dev217
16
- Requires-Dist: omlish==0.0.0.dev217
15
+ Requires-Dist: omdev==0.0.0.dev218
16
+ Requires-Dist: omlish==0.0.0.dev218
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -114,7 +114,7 @@ ominfra/manage/targets/targets.py,sha256=7GP6UAZyJFEhpkJN6UQdpr_WN3p7C76v-s445y-
114
114
  ominfra/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
115
115
  ominfra/scripts/journald2aws.py,sha256=CM1nZMpecXJpcg7icJUCJ-_DX-7CduQurxZQ7EmhQmA,171450
116
116
  ominfra/scripts/manage.py,sha256=MaUur1_dDdMHt5YnE6Waxa_v70kydHzKCBHXAuTmKd0,362827
117
- ominfra/scripts/supervisor.py,sha256=Laa7EM9tsLzjzb2Pkg2DVeUJX7OpsWLHuwlA9WP0cNM,295534
117
+ ominfra/scripts/supervisor.py,sha256=ejPO7r3Ta0RQbP28MyL8MJNS1jop6g8d9qdv-vJ0OYA,294602
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
@@ -125,7 +125,7 @@ ominfra/supervisor/events.py,sha256=XGrtzHr1xm0dwjz329fn9eR0_Ap-LQL6Sk8LJ8eVDEo,
125
125
  ominfra/supervisor/exceptions.py,sha256=Qbu211H3CLlSmi9LsSikOwrcL5HgJP9ugvcKWlGTAoI,750
126
126
  ominfra/supervisor/groups.py,sha256=MBbsbt8Zh_WEYkGOr1KXa82gnPVw9wPB2lAnqhugXSc,2457
127
127
  ominfra/supervisor/groupsimpl.py,sha256=PCDyc_Wc-pnvIj56_aEyiA5exCpK6n9iErqnJzO2rZk,2281
128
- ominfra/supervisor/http.py,sha256=Tl5eT6dyf4KuQXKbhGo1B6CFEzUDtPl_DZAuUFVD9zI,3453
128
+ ominfra/supervisor/http.py,sha256=P7afN223jeR_g36bPK-cWulnJo1wAeFUBWAaMKPycmw,3387
129
129
  ominfra/supervisor/inject.py,sha256=IeR-WKvK1sGNxMe6G2OBT5kSP7EUP5ipkDgcUFmDPCA,4838
130
130
  ominfra/supervisor/io.py,sha256=moaGNaPuYXEAUzLg8Qjo05DEIcOUNYUj8SSr8eT0d24,3198
131
131
  ominfra/supervisor/main.py,sha256=zCVuHZG2kGIPHwTLH4EUr5xpN4vJYessmKO2P0NE5RU,4381
@@ -156,9 +156,9 @@ ominfra/tailscale/api.py,sha256=C5-t_b6jZXUWcy5k8bXm7CFnk73pSdrlMOgGDeGVrpw,1370
156
156
  ominfra/tailscale/cli.py,sha256=3FnJbgpLw6gInTfhERd1mDy9ijjMUGxkdYVo43Tnxx4,3555
157
157
  ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
158
158
  ominfra/tools/listresources.py,sha256=4qVg5txsb10EHhvqXXeM6gJ2jx9LbroEnPydDv1uXs0,6176
159
- ominfra-0.0.0.dev217.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
160
- ominfra-0.0.0.dev217.dist-info/METADATA,sha256=iTe6sIvgKblZxtFkb4vMZGGDzVFpVoV0l2bXB-3Jf5k,731
161
- ominfra-0.0.0.dev217.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
162
- ominfra-0.0.0.dev217.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
163
- ominfra-0.0.0.dev217.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
164
- ominfra-0.0.0.dev217.dist-info/RECORD,,
159
+ ominfra-0.0.0.dev218.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
160
+ ominfra-0.0.0.dev218.dist-info/METADATA,sha256=CIoVjeFWhR47YXXqQ65hW7lHeJK6XpLd0jTGOcP6RA4,731
161
+ ominfra-0.0.0.dev218.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
162
+ ominfra-0.0.0.dev218.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
163
+ ominfra-0.0.0.dev218.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
164
+ ominfra-0.0.0.dev218.dist-info/RECORD,,