omlish 0.0.0.dev144__py3-none-any.whl → 0.0.0.dev146__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.
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev144'
2
- __revision__ = '4d901652b9972fb965683ca3ac965147536a9dd4'
1
+ __version__ = '0.0.0.dev146'
2
+ __revision__ = '3e5441b65738d0b3c80a43abb47b62f9ef5a6bee'
3
3
 
4
4
 
5
5
  #
@@ -51,63 +51,56 @@ class CacheImpl(Cache[K, V]):
51
51
  https://google.github.io/guava/releases/16.0/api/docs/com/google/common/cache/CacheBuilder.html
52
52
  """
53
53
 
54
- try:
55
- if not ta.TYPE_CHECKING:
56
- from ..._ext.cy.collections.cache import CacheLink as Link
57
- else:
58
- raise ImportError # noqa
59
-
60
- except ImportError:
61
- class Link:
62
- __slots__ = [
63
- 'seq',
64
- 'ins_prev',
65
- 'ins_next',
66
- 'lru_prev',
67
- 'lru_next',
68
- 'lfu_prev',
69
- 'lfu_next',
70
- 'key',
71
- 'value',
72
- 'weight',
73
- 'written',
74
- 'accessed',
75
- 'hits',
76
- 'unlinked',
77
- ]
78
-
79
- seq: int
80
- ins_prev: 'CacheImpl.Link'
81
- ins_next: 'CacheImpl.Link'
82
- lru_prev: 'CacheImpl.Link'
83
- lru_next: 'CacheImpl.Link'
84
- lfu_prev: 'CacheImpl.Link'
85
- lfu_next: 'CacheImpl.Link'
86
- key: ta.Any | weakref.ref
87
- value: ta.Any | weakref.ref
88
- weight: float
89
- written: float
90
- accessed: float
91
- hits: int
92
- unlinked: bool
93
-
94
- def __repr__(self) -> str:
95
- return (
96
- f'Link@{self.seq!s}('
97
- f'ins_prev={("@" + str(self.ins_prev.seq)) if self.ins_prev is not None else None}, '
98
- f'ins_next={("@" + str(self.ins_next.seq)) if self.ins_next is not None else None}, '
99
- f'lru_prev={("@" + str(self.lru_prev.seq)) if self.lru_prev is not None else None}, '
100
- f'lru_next={("@" + str(self.lru_next.seq)) if self.lru_next is not None else None}, '
101
- f'lfu_prev={("@" + str(self.lfu_prev.seq)) if self.lfu_prev is not None else None}, '
102
- f'lfu_next={("@" + str(self.lfu_next.seq)) if self.lfu_next is not None else None}, '
103
- f'key={self.key!r}, '
104
- f'value={self.value!r}, '
105
- f'weight={self.weight}, '
106
- f'written={self.written}, '
107
- f'accessed={self.accessed}, '
108
- f'hits={self.hits}, '
109
- f'unlinked={self.unlinked})'
110
- )
54
+ class Link:
55
+ __slots__ = [
56
+ 'seq',
57
+ 'ins_prev',
58
+ 'ins_next',
59
+ 'lru_prev',
60
+ 'lru_next',
61
+ 'lfu_prev',
62
+ 'lfu_next',
63
+ 'key',
64
+ 'value',
65
+ 'weight',
66
+ 'written',
67
+ 'accessed',
68
+ 'hits',
69
+ 'unlinked',
70
+ ]
71
+
72
+ seq: int
73
+ ins_prev: 'CacheImpl.Link'
74
+ ins_next: 'CacheImpl.Link'
75
+ lru_prev: 'CacheImpl.Link'
76
+ lru_next: 'CacheImpl.Link'
77
+ lfu_prev: 'CacheImpl.Link'
78
+ lfu_next: 'CacheImpl.Link'
79
+ key: ta.Any | weakref.ref
80
+ value: ta.Any | weakref.ref
81
+ weight: float
82
+ written: float
83
+ accessed: float
84
+ hits: int
85
+ unlinked: bool
86
+
87
+ def __repr__(self) -> str:
88
+ return (
89
+ f'Link@{self.seq!s}('
90
+ f'ins_prev={("@" + str(self.ins_prev.seq)) if self.ins_prev is not None else None}, '
91
+ f'ins_next={("@" + str(self.ins_next.seq)) if self.ins_next is not None else None}, '
92
+ f'lru_prev={("@" + str(self.lru_prev.seq)) if self.lru_prev is not None else None}, '
93
+ f'lru_next={("@" + str(self.lru_next.seq)) if self.lru_next is not None else None}, '
94
+ f'lfu_prev={("@" + str(self.lfu_prev.seq)) if self.lfu_prev is not None else None}, '
95
+ f'lfu_next={("@" + str(self.lfu_next.seq)) if self.lfu_next is not None else None}, '
96
+ f'key={self.key!r}, '
97
+ f'value={self.value!r}, '
98
+ f'weight={self.weight}, '
99
+ f'written={self.written}, '
100
+ f'accessed={self.accessed}, '
101
+ f'hits={self.hits}, '
102
+ f'unlinked={self.unlinked})'
103
+ )
111
104
 
112
105
  _cache: ta.MutableMapping[ta.Any, Link]
113
106
 
omlish/defs.py CHANGED
@@ -199,7 +199,7 @@ def abstract_method(cls_dct, *names):
199
199
 
200
200
  @lang.cls_dct_fn()
201
201
  def abstract_property(cls_dct, *names):
202
- return not_implemented(cls_dct, *names, wrapper=abc.abstractmethod)
202
+ return not_implemented(cls_dct, *names, wrapper=lambda o: property(abc.abstractmethod(o)))
203
203
 
204
204
 
205
205
  @lang.cls_dct_fn()
@@ -11,10 +11,10 @@ from ..http.handlers import HttpHandler
11
11
  from ..io import IncrementalWriteBuffer
12
12
  from ..io import ReadableListBuffer
13
13
  from ..socket import SocketAddress
14
- from .handlers import SocketFdIoHandler
14
+ from .handlers import SocketFdioHandler
15
15
 
16
16
 
17
- class CoroHttpServerConnectionFdIoHandler(SocketFdIoHandler):
17
+ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
18
18
  def __init__(
19
19
  self,
20
20
  addr: SocketAddress,
@@ -7,7 +7,7 @@ from ..check import check_not_none
7
7
  from ..socket import SocketAddress
8
8
 
9
9
 
10
- class FdIoHandler(abc.ABC):
10
+ class FdioHandler(abc.ABC):
11
11
  @abc.abstractmethod
12
12
  def fd(self) -> int:
13
13
  raise NotImplementedError
@@ -43,7 +43,7 @@ class FdIoHandler(abc.ABC):
43
43
  pass
44
44
 
45
45
 
46
- class SocketFdIoHandler(FdIoHandler, abc.ABC):
46
+ class SocketFdioHandler(FdioHandler, abc.ABC):
47
47
  def __init__(
48
48
  self,
49
49
  addr: SocketAddress,
@@ -4,13 +4,13 @@ import select
4
4
  import sys
5
5
  import typing as ta
6
6
 
7
- from .pollers import FdIoPoller
7
+ from .pollers import FdioPoller
8
8
 
9
9
 
10
- KqueueFdIoPoller: ta.Optional[ta.Type[FdIoPoller]]
10
+ KqueueFdioPoller: ta.Optional[ta.Type[FdioPoller]]
11
11
  if sys.platform == 'darwin' or sys.platform.startswith('freebsd'):
12
12
 
13
- class _KqueueFdIoPoller(FdIoPoller):
13
+ class _KqueueFdioPoller(FdioPoller):
14
14
  DEFAULT_MAX_EVENTS = 1000
15
15
 
16
16
  def __init__(
@@ -98,14 +98,14 @@ if sys.platform == 'darwin' or sys.platform.startswith('freebsd'):
98
98
 
99
99
  #
100
100
 
101
- def poll(self, timeout: ta.Optional[float]) -> FdIoPoller.PollResult:
101
+ def poll(self, timeout: ta.Optional[float]) -> FdioPoller.PollResult:
102
102
  kq = self._get_kqueue()
103
103
  try:
104
104
  kes = kq.control(None, self._max_events, timeout)
105
105
 
106
106
  except OSError as exc:
107
107
  if exc.errno == errno.EINTR:
108
- return FdIoPoller.PollResult(msg='EINTR encountered in poll', exc=exc)
108
+ return FdioPoller.PollResult(msg='EINTR encountered in poll', exc=exc)
109
109
  else:
110
110
  raise
111
111
 
@@ -117,8 +117,8 @@ if sys.platform == 'darwin' or sys.platform.startswith('freebsd'):
117
117
  if ke.filter == select.KQ_FILTER_WRITE:
118
118
  w.append(ke.ident)
119
119
 
120
- return FdIoPoller.PollResult(r, w)
120
+ return FdioPoller.PollResult(r, w)
121
121
 
122
- KqueueFdIoPoller = _KqueueFdIoPoller
122
+ KqueueFdioPoller = _KqueueFdioPoller
123
123
  else:
124
- KqueueFdIoPoller = None
124
+ KqueueFdioPoller = None
@@ -1,27 +1,27 @@
1
1
  # ruff: noqa: UP006 UP007
2
2
  import typing as ta
3
3
 
4
- from .handlers import FdIoHandler
5
- from .pollers import FdIoPoller
4
+ from .handlers import FdioHandler
5
+ from .pollers import FdioPoller
6
6
 
7
7
 
8
- class FdIoManager:
8
+ class FdioManager:
9
9
  def __init__(
10
10
  self,
11
- poller: FdIoPoller,
11
+ poller: FdioPoller,
12
12
  ) -> None:
13
13
  super().__init__()
14
14
 
15
15
  self._poller = poller
16
16
 
17
- self._handlers: ta.Dict[int, FdIoHandler] = {} # Preserves insertion order
17
+ self._handlers: ta.Dict[int, FdioHandler] = {} # Preserves insertion order
18
18
 
19
- def register(self, h: FdIoHandler) -> None:
19
+ def register(self, h: FdioHandler) -> None:
20
20
  if (hid := id(h)) in self._handlers:
21
21
  raise KeyError(h)
22
22
  self._handlers[hid] = h
23
23
 
24
- def unregister(self, h: FdIoHandler) -> None:
24
+ def unregister(self, h: FdioHandler) -> None:
25
25
  del self._handlers[id(h)]
26
26
 
27
27
  def poll(self, *, timeout: float = 1.) -> None:
@@ -9,7 +9,7 @@ import typing as ta
9
9
  ##
10
10
 
11
11
 
12
- class FdIoPoller(abc.ABC):
12
+ class FdioPoller(abc.ABC):
13
13
  def __init__(self) -> None:
14
14
  super().__init__()
15
15
 
@@ -120,8 +120,8 @@ class FdIoPoller(abc.ABC):
120
120
  ##
121
121
 
122
122
 
123
- class SelectFdIoPoller(FdIoPoller):
124
- def poll(self, timeout: ta.Optional[float]) -> FdIoPoller.PollResult:
123
+ class SelectFdioPoller(FdioPoller):
124
+ def poll(self, timeout: ta.Optional[float]) -> FdioPoller.PollResult:
125
125
  try:
126
126
  r, w, x = select.select(
127
127
  self._readable,
@@ -132,22 +132,22 @@ class SelectFdIoPoller(FdIoPoller):
132
132
 
133
133
  except OSError as exc:
134
134
  if exc.errno == errno.EINTR:
135
- return FdIoPoller.PollResult(msg='EINTR encountered in poll', exc=exc)
135
+ return FdioPoller.PollResult(msg='EINTR encountered in poll', exc=exc)
136
136
  elif exc.errno == errno.EBADF:
137
- return FdIoPoller.PollResult(msg='EBADF encountered in poll', exc=exc)
137
+ return FdioPoller.PollResult(msg='EBADF encountered in poll', exc=exc)
138
138
  else:
139
139
  raise
140
140
 
141
- return FdIoPoller.PollResult(r, w)
141
+ return FdioPoller.PollResult(r, w)
142
142
 
143
143
 
144
144
  ##
145
145
 
146
146
 
147
- PollFdIoPoller: ta.Optional[ta.Type[FdIoPoller]]
147
+ PollFdioPoller: ta.Optional[ta.Type[FdioPoller]]
148
148
  if hasattr(select, 'poll'):
149
149
 
150
- class _PollFdIoPoller(FdIoPoller):
150
+ class _PollFdioPoller(FdioPoller):
151
151
  def __init__(self) -> None:
152
152
  super().__init__()
153
153
 
@@ -180,14 +180,14 @@ if hasattr(select, 'poll'):
180
180
 
181
181
  #
182
182
 
183
- def poll(self, timeout: ta.Optional[float]) -> FdIoPoller.PollResult:
183
+ def poll(self, timeout: ta.Optional[float]) -> FdioPoller.PollResult:
184
184
  polled: ta.List[ta.Tuple[int, int]]
185
185
  try:
186
186
  polled = self._poller.poll(timeout * 1000 if timeout is not None else None)
187
187
 
188
188
  except OSError as exc:
189
189
  if exc.errno == errno.EINTR:
190
- return FdIoPoller.PollResult(msg='EINTR encountered in poll', exc=exc)
190
+ return FdioPoller.PollResult(msg='EINTR encountered in poll', exc=exc)
191
191
  else:
192
192
  raise
193
193
 
@@ -205,8 +205,8 @@ if hasattr(select, 'poll'):
205
205
  r.append(fd)
206
206
  if mask & self._WRITE:
207
207
  w.append(fd)
208
- return FdIoPoller.PollResult(r, w, inv=inv)
208
+ return FdioPoller.PollResult(r, w, inv=inv)
209
209
 
210
- PollFdIoPoller = _PollFdIoPoller
210
+ PollFdioPoller = _PollFdioPoller
211
211
  else:
212
- PollFdIoPoller = None
212
+ PollFdioPoller = None
omlish/lite/marshal.py CHANGED
@@ -35,23 +35,24 @@ T = ta.TypeVar('T')
35
35
  @dc.dataclass(frozen=True)
36
36
  class ObjMarshalOptions:
37
37
  raw_bytes: bool = False
38
+ nonstrict_dataclasses: bool = False
38
39
 
39
40
 
40
41
  class ObjMarshaler(abc.ABC):
41
42
  @abc.abstractmethod
42
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
43
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
43
44
  raise NotImplementedError
44
45
 
45
46
  @abc.abstractmethod
46
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
47
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
47
48
  raise NotImplementedError
48
49
 
49
50
 
50
51
  class NopObjMarshaler(ObjMarshaler):
51
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
52
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
52
53
  return o
53
54
 
54
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
55
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
55
56
  return o
56
57
 
57
58
 
@@ -59,29 +60,29 @@ class NopObjMarshaler(ObjMarshaler):
59
60
  class ProxyObjMarshaler(ObjMarshaler):
60
61
  m: ta.Optional[ObjMarshaler] = None
61
62
 
62
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
63
- return check_not_none(self.m).marshal(o, opts)
63
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
64
+ return check_not_none(self.m).marshal(o, ctx)
64
65
 
65
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
66
- return check_not_none(self.m).unmarshal(o, opts)
66
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
67
+ return check_not_none(self.m).unmarshal(o, ctx)
67
68
 
68
69
 
69
70
  @dc.dataclass(frozen=True)
70
71
  class CastObjMarshaler(ObjMarshaler):
71
72
  ty: type
72
73
 
73
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
74
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
74
75
  return o
75
76
 
76
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
77
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
77
78
  return self.ty(o)
78
79
 
79
80
 
80
81
  class DynamicObjMarshaler(ObjMarshaler):
81
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
82
- return marshal_obj(o)
82
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
83
+ return ctx.manager.marshal_obj(o, opts=ctx.options)
83
84
 
84
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
85
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
85
86
  return o
86
87
 
87
88
 
@@ -89,10 +90,10 @@ class DynamicObjMarshaler(ObjMarshaler):
89
90
  class Base64ObjMarshaler(ObjMarshaler):
90
91
  ty: type
91
92
 
92
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
93
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
93
94
  return base64.b64encode(o).decode('ascii')
94
95
 
95
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
96
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
96
97
  return self.ty(base64.b64decode(o))
97
98
 
98
99
 
@@ -100,25 +101,25 @@ class Base64ObjMarshaler(ObjMarshaler):
100
101
  class BytesSwitchedObjMarshaler(ObjMarshaler):
101
102
  m: ObjMarshaler
102
103
 
103
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
104
- if opts.raw_bytes:
104
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
105
+ if ctx.options.raw_bytes:
105
106
  return o
106
- return self.m.marshal(o, opts)
107
+ return self.m.marshal(o, ctx)
107
108
 
108
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
109
- if opts.raw_bytes:
109
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
110
+ if ctx.options.raw_bytes:
110
111
  return o
111
- return self.m.unmarshal(o, opts)
112
+ return self.m.unmarshal(o, ctx)
112
113
 
113
114
 
114
115
  @dc.dataclass(frozen=True)
115
116
  class EnumObjMarshaler(ObjMarshaler):
116
117
  ty: type
117
118
 
118
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
119
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
119
120
  return o.name
120
121
 
121
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
122
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
122
123
  return self.ty.__members__[o] # type: ignore
123
124
 
124
125
 
@@ -126,15 +127,15 @@ class EnumObjMarshaler(ObjMarshaler):
126
127
  class OptionalObjMarshaler(ObjMarshaler):
127
128
  item: ObjMarshaler
128
129
 
129
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
130
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
130
131
  if o is None:
131
132
  return None
132
- return self.item.marshal(o, opts)
133
+ return self.item.marshal(o, ctx)
133
134
 
134
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
135
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
135
136
  if o is None:
136
137
  return None
137
- return self.item.unmarshal(o, opts)
138
+ return self.item.unmarshal(o, ctx)
138
139
 
139
140
 
140
141
  @dc.dataclass(frozen=True)
@@ -143,11 +144,11 @@ class MappingObjMarshaler(ObjMarshaler):
143
144
  km: ObjMarshaler
144
145
  vm: ObjMarshaler
145
146
 
146
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
147
- return {self.km.marshal(k, opts): self.vm.marshal(v, opts) for k, v in o.items()}
147
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
148
+ return {self.km.marshal(k, ctx): self.vm.marshal(v, ctx) for k, v in o.items()}
148
149
 
149
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
150
- return self.ty((self.km.unmarshal(k, opts), self.vm.unmarshal(v, opts)) for k, v in o.items())
150
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
151
+ return self.ty((self.km.unmarshal(k, ctx), self.vm.unmarshal(v, ctx)) for k, v in o.items())
151
152
 
152
153
 
153
154
  @dc.dataclass(frozen=True)
@@ -155,11 +156,11 @@ class IterableObjMarshaler(ObjMarshaler):
155
156
  ty: type
156
157
  item: ObjMarshaler
157
158
 
158
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
159
- return [self.item.marshal(e, opts) for e in o]
159
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
160
+ return [self.item.marshal(e, ctx) for e in o]
160
161
 
161
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
162
- return self.ty(self.item.unmarshal(e, opts) for e in o)
162
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
163
+ return self.ty(self.item.unmarshal(e, ctx) for e in o)
163
164
 
164
165
 
165
166
  @dc.dataclass(frozen=True)
@@ -168,11 +169,18 @@ class DataclassObjMarshaler(ObjMarshaler):
168
169
  fs: ta.Mapping[str, ObjMarshaler]
169
170
  nonstrict: bool = False
170
171
 
171
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
172
- return {k: m.marshal(getattr(o, k), opts) for k, m in self.fs.items()}
172
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
173
+ return {
174
+ k: m.marshal(getattr(o, k), ctx)
175
+ for k, m in self.fs.items()
176
+ }
173
177
 
174
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
175
- return self.ty(**{k: self.fs[k].unmarshal(v, opts) for k, v in o.items() if not self.nonstrict or k in self.fs})
178
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
179
+ return self.ty(**{
180
+ k: self.fs[k].unmarshal(v, ctx)
181
+ for k, v in o.items()
182
+ if not (self.nonstrict or ctx.options.nonstrict_dataclasses) or k in self.fs
183
+ })
176
184
 
177
185
 
178
186
  @dc.dataclass(frozen=True)
@@ -192,50 +200,50 @@ class PolymorphicObjMarshaler(ObjMarshaler):
192
200
  {i.tag: i for i in impls},
193
201
  )
194
202
 
195
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
203
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
196
204
  impl = self.impls_by_ty[type(o)]
197
- return {impl.tag: impl.m.marshal(o, opts)}
205
+ return {impl.tag: impl.m.marshal(o, ctx)}
198
206
 
199
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
207
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
200
208
  [(t, v)] = o.items()
201
209
  impl = self.impls_by_tag[t]
202
- return impl.m.unmarshal(v, opts)
210
+ return impl.m.unmarshal(v, ctx)
203
211
 
204
212
 
205
213
  @dc.dataclass(frozen=True)
206
214
  class DatetimeObjMarshaler(ObjMarshaler):
207
215
  ty: type
208
216
 
209
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
217
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
210
218
  return o.isoformat()
211
219
 
212
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
220
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
213
221
  return self.ty.fromisoformat(o) # type: ignore
214
222
 
215
223
 
216
224
  class DecimalObjMarshaler(ObjMarshaler):
217
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
225
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
218
226
  return str(check_isinstance(o, decimal.Decimal))
219
227
 
220
- def unmarshal(self, v: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
228
+ def unmarshal(self, v: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
221
229
  return decimal.Decimal(check_isinstance(v, str))
222
230
 
223
231
 
224
232
  class FractionObjMarshaler(ObjMarshaler):
225
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
233
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
226
234
  fr = check_isinstance(o, fractions.Fraction)
227
235
  return [fr.numerator, fr.denominator]
228
236
 
229
- def unmarshal(self, v: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
237
+ def unmarshal(self, v: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
230
238
  num, denom = check_isinstance(v, list)
231
239
  return fractions.Fraction(num, denom)
232
240
 
233
241
 
234
242
  class UuidObjMarshaler(ObjMarshaler):
235
- def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
243
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
236
244
  return str(o)
237
245
 
238
- def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
246
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
239
247
  return uuid.UUID(o)
240
248
 
241
249
 
@@ -396,6 +404,12 @@ class ObjMarshalerManager:
396
404
 
397
405
  #
398
406
 
407
+ def _make_context(self, opts: ta.Optional[ObjMarshalOptions]) -> 'ObjMarshalContext':
408
+ return ObjMarshalContext(
409
+ options=opts or self._default_options,
410
+ manager=self,
411
+ )
412
+
399
413
  def marshal_obj(
400
414
  self,
401
415
  o: ta.Any,
@@ -403,7 +417,7 @@ class ObjMarshalerManager:
403
417
  opts: ta.Optional[ObjMarshalOptions] = None,
404
418
  ) -> ta.Any:
405
419
  m = self.get_obj_marshaler(ty if ty is not None else type(o))
406
- return m.marshal(o, opts or self._default_options)
420
+ return m.marshal(o, self._make_context(opts))
407
421
 
408
422
  def unmarshal_obj(
409
423
  self,
@@ -412,7 +426,7 @@ class ObjMarshalerManager:
412
426
  opts: ta.Optional[ObjMarshalOptions] = None,
413
427
  ) -> T:
414
428
  m = self.get_obj_marshaler(ty)
415
- return m.unmarshal(o, opts or self._default_options)
429
+ return m.unmarshal(o, self._make_context(opts))
416
430
 
417
431
  def roundtrip_obj(
418
432
  self,
@@ -427,6 +441,12 @@ class ObjMarshalerManager:
427
441
  return u
428
442
 
429
443
 
444
+ @dc.dataclass(frozen=True)
445
+ class ObjMarshalContext:
446
+ options: ObjMarshalOptions
447
+ manager: ObjMarshalerManager
448
+
449
+
430
450
  ##
431
451
 
432
452
 
@@ -0,0 +1,8 @@
1
+ def read_package_resource_binary(package: str, resource: str) -> bytes:
2
+ import importlib.resources
3
+ return importlib.resources.read_binary(package, resource)
4
+
5
+
6
+ def read_package_resource_text(package: str, resource: str) -> str:
7
+ import importlib.resources
8
+ return importlib.resources.read_text(package, resource)
@@ -0,0 +1,2 @@
1
+ # @omlish-lite
2
+ from .types import Manifest # noqa
@@ -0,0 +1,165 @@
1
+ # ruff: noqa: UP006 UP007
2
+ """
3
+ Should be kept somewhat lightweight - used in cli entrypoints.
4
+
5
+ TODO:
6
+ - persisted caching support - {pkg_name: manifests}
7
+ """
8
+ import dataclasses as dc
9
+ import importlib.machinery
10
+ import importlib.resources
11
+ import json
12
+ import typing as ta
13
+
14
+ from .types import Manifest
15
+
16
+
17
+ ##
18
+
19
+
20
+ class ManifestLoader:
21
+ def __init__(
22
+ self,
23
+ *,
24
+ module_remap: ta.Optional[ta.Mapping[str, str]] = None,
25
+ ) -> None:
26
+ super().__init__()
27
+
28
+ self._module_remap = module_remap or {}
29
+ self._module_reverse_remap = {v: k for k, v in self._module_remap.items()}
30
+
31
+ self._cls_cache: ta.Dict[str, type] = {}
32
+ self._raw_cache: ta.Dict[str, ta.Optional[ta.Sequence[Manifest]]] = {}
33
+
34
+ @classmethod
35
+ def from_entry_point(
36
+ cls,
37
+ globals: ta.Mapping[str, ta.Any], # noqa
38
+ *,
39
+ module_remap: ta.Optional[ta.Mapping[str, str]] = None,
40
+ **kwargs: ta.Any,
41
+ ) -> 'ManifestLoader':
42
+ rm: ta.Dict[str, str] = {}
43
+
44
+ if module_remap:
45
+ rm.update(module_remap)
46
+
47
+ if '__name__' in globals and '__spec__' in globals:
48
+ name: str = globals['__name__']
49
+ spec: importlib.machinery.ModuleSpec = globals['__spec__']
50
+ if '__main__' not in rm and name == '__main__':
51
+ rm[spec.name] = '__main__'
52
+
53
+ return cls(module_remap=rm, **kwargs)
54
+
55
+ def load_cls(self, key: str) -> type:
56
+ try:
57
+ return self._cls_cache[key]
58
+ except KeyError:
59
+ pass
60
+
61
+ if not key.startswith('$'):
62
+ raise Exception(f'Bad key: {key}')
63
+
64
+ parts = key[1:].split('.')
65
+ pos = next(i for i, p in enumerate(parts) if p[0].isupper())
66
+
67
+ mod_name = '.'.join(parts[:pos])
68
+ mod_name = self._module_remap.get(mod_name, mod_name)
69
+ mod = importlib.import_module(mod_name)
70
+
71
+ obj: ta.Any = mod
72
+ for ca in parts[pos:]:
73
+ obj = getattr(obj, ca)
74
+
75
+ cls = obj
76
+ if not isinstance(cls, type):
77
+ raise TypeError(cls)
78
+
79
+ self._cls_cache[key] = cls
80
+ return cls
81
+
82
+ def load_contents(self, obj: ta.Any, pkg_name: str) -> ta.Sequence[Manifest]:
83
+ if not isinstance(obj, (list, tuple)):
84
+ raise TypeError(obj)
85
+
86
+ lst: ta.List[Manifest] = []
87
+ for e in obj:
88
+ m = Manifest(**e)
89
+
90
+ m = dc.replace(m, module=pkg_name + m.module)
91
+
92
+ [(key, value_dct)] = m.value.items()
93
+ if not key.startswith('$'):
94
+ raise Exception(f'Bad key: {key}')
95
+ if key.startswith('$.'):
96
+ key = f'${pkg_name}{key[1:]}'
97
+ m = dc.replace(m, value={key: value_dct})
98
+
99
+ lst.append(m)
100
+
101
+ return lst
102
+
103
+ def load_raw(self, pkg_name: str) -> ta.Optional[ta.Sequence[Manifest]]:
104
+ try:
105
+ return self._raw_cache[pkg_name]
106
+ except KeyError:
107
+ pass
108
+
109
+ t = importlib.resources.files(pkg_name).joinpath('.manifests.json')
110
+ if not t.is_file():
111
+ self._raw_cache[pkg_name] = None
112
+ return None
113
+
114
+ src = t.read_text('utf-8')
115
+ obj = json.loads(src)
116
+ if not isinstance(obj, (list, tuple)):
117
+ raise TypeError(obj)
118
+
119
+ lst = self.load_contents(obj, pkg_name)
120
+
121
+ self._raw_cache[pkg_name] = lst
122
+ return lst
123
+
124
+ def load(
125
+ self,
126
+ *pkg_names: str,
127
+ only: ta.Optional[ta.Iterable[type]] = None,
128
+ ) -> ta.Sequence[Manifest]:
129
+ only_keys: ta.Optional[ta.Set]
130
+ if only is not None:
131
+ only_keys = set()
132
+ for cls in only:
133
+ if not (isinstance(cls, type) and dc.is_dataclass(cls)):
134
+ raise TypeError(cls)
135
+ mod_name = cls.__module__
136
+ mod_name = self._module_reverse_remap.get(mod_name, mod_name)
137
+ only_keys.add(f'${mod_name}.{cls.__qualname__}')
138
+ else:
139
+ only_keys = None
140
+
141
+ lst: ta.List[Manifest] = []
142
+ for pn in pkg_names:
143
+ for manifest in (self.load_raw(pn) or []):
144
+ [(key, value_dct)] = manifest.value.items()
145
+ if only_keys is not None and key not in only_keys:
146
+ continue
147
+
148
+ cls = self.load_cls(key)
149
+ value = cls(**value_dct)
150
+
151
+ manifest = dc.replace(manifest, value=value)
152
+ lst.append(manifest)
153
+
154
+ return lst
155
+
156
+ ENTRY_POINT_GROUP = 'omlish.manifests'
157
+
158
+ def discover(self) -> ta.Sequence[str]:
159
+ # This is a fat dep so do it late.
160
+ import importlib.metadata
161
+
162
+ return [
163
+ ep.value
164
+ for ep in importlib.metadata.entry_points(group=self.ENTRY_POINT_GROUP)
165
+ ]
@@ -0,0 +1,17 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import dataclasses as dc
3
+ import typing as ta
4
+
5
+
6
+ @dc.dataclass(frozen=True)
7
+ class ManifestOrigin:
8
+ module: str
9
+ attr: str
10
+
11
+ file: str
12
+ line: int
13
+
14
+
15
+ @dc.dataclass(frozen=True)
16
+ class Manifest(ManifestOrigin):
17
+ value: ta.Any
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omlish
3
- Version: 0.0.0.dev144
3
+ Version: 0.0.0.dev146
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,12 +1,12 @@
1
1
  omlish/.manifests.json,sha256=RX24SRc6DCEg77PUVnaXOKCWa5TF_c9RQJdGIf7gl9c,1135
2
- omlish/__about__.py,sha256=MT0BTpx7mPru-9X9bEnyKHLlujaF7_MenPp4KN78i3c,3409
2
+ omlish/__about__.py,sha256=G3zss6e134zxU5xmjngBc8mskjSdZxwZFcH8cUO87Sc,3409
3
3
  omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
4
4
  omlish/argparse.py,sha256=cqKGAqcxuxv_s62z0gq29L9KAvg_3-_rFvXKjVpRJjo,8126
5
5
  omlish/c3.py,sha256=ubu7lHwss5V4UznbejAI0qXhXahrU01MysuHOZI9C4U,8116
6
6
  omlish/cached.py,sha256=UI-XTFBwA6YXWJJJeBn-WkwBkfzDjLBBaZf4nIJA9y0,510
7
7
  omlish/check.py,sha256=CBOCfl6ANZ7CKke2bGfQfUew9m22_ke0GvfEDO4Sjug,10595
8
8
  omlish/datetimes.py,sha256=HajeM1kBvwlTa-uR1TTZHmZ3zTPnnUr1uGGQhiO1XQ0,2152
9
- omlish/defs.py,sha256=T3bq_7h_tO3nDB5RAFBn7DkdeQgqheXzkFColbOHZko,4890
9
+ omlish/defs.py,sha256=9uUjJuVIbCBL3g14fyzAp-9gH935MFofvlfOGwcBIaM,4913
10
10
  omlish/dynamic.py,sha256=35C_cCX_Vq2HrHzGk5T-zbrMvmUdiIiwDzDNixczoDo,6541
11
11
  omlish/iterators.py,sha256=GGLC7RIT86uXMjhIIIqnff_Iu5SI_b9rXYywYGFyzmo,7292
12
12
  omlish/libc.py,sha256=8r7Ejyhttk9ruCfBkxNTrlzir5WPbDE2vmY7VPlceMA,15362
@@ -110,7 +110,7 @@ omlish/collections/unmodifiable.py,sha256=QmUEi9IBXqiM_KGgH2rqg15VmkHJo1MZ6kwq2t
110
110
  omlish/collections/utils.py,sha256=9o9STwzAn5YjZRZ9ns1kuo7NgLXLaoVPFu6AJd-3JT8,4336
111
111
  omlish/collections/cache/__init__.py,sha256=D1gO71VcwxFTZP9gAc9isHfg_TEdalwhsJcgGLvS9hg,233
112
112
  omlish/collections/cache/descriptor.py,sha256=t-1Gh4DTABDuNmeDJlpoW4LV3gi_uSlBd9ZfBINfYCM,5023
113
- omlish/collections/cache/impl.py,sha256=nQox5kChhns9h2a5gnX-ayQGBQJ5-B1aZkLQ2Aej19g,15137
113
+ omlish/collections/cache/impl.py,sha256=ySRU9UJG7jH9VPvuXdwZQ_rSqrleY-1mtie5Ml738wY,14755
114
114
  omlish/collections/cache/types.py,sha256=yNjwd6CGyTJQdxN2CQxFqqBAlcs1Z7vvNV-aU1K7p8E,685
115
115
  omlish/concurrent/__init__.py,sha256=9p-s8MvBEYDqHIoYU3OYoe-Nni22QdkW7nhZGEukJTM,197
116
116
  omlish/concurrent/executors.py,sha256=FYKCDYYuj-OgMa8quLsA47SfFNX3KDJvRENVk8NDsrA,1292
@@ -320,11 +320,12 @@ omlish/lite/io.py,sha256=3ECgUXdRnXyS6pGTSoVr6oB4moI38EpWxTq08zaTM-U,5339
320
320
  omlish/lite/journald.py,sha256=f5Y2Q6-6O3iK_7MoGiwZwoQEOcP7LfkxxQNUR9tMjJM,3882
321
321
  omlish/lite/json.py,sha256=7-02Ny4fq-6YAu5ynvqoijhuYXWpLmfCI19GUeZnb1c,740
322
322
  omlish/lite/logs.py,sha256=1pcGu0ekhVCcLUckLSP16VccnAoprjtl5Vkdfm7y1Wg,6184
323
- omlish/lite/marshal.py,sha256=a3_wuMjiCXHYngzgLhJU2C2BFznVC_VlrzRJ5_hpuRI,12989
323
+ omlish/lite/marshal.py,sha256=1wqZWKapZ5rFgDxSkb447Xv2ce2SFEpiB1EMg1nh2BI,13530
324
324
  omlish/lite/maybes.py,sha256=7OlHJ8Q2r4wQ-aRbZSlJY7x0e8gDvufFdlohGEIJ3P4,833
325
325
  omlish/lite/pidfile.py,sha256=PRSDOAXmNkNwxh-Vwif0Nrs8RAmWroiNhLKIbdjwzBc,1723
326
326
  omlish/lite/pycharm.py,sha256=CUArgzaG8ZZ0evN7tdrML5WXyF-G_BvF_s3Z4SI2LA0,1164
327
327
  omlish/lite/reflect.py,sha256=ad_ya_zZJOQB8HoNjs9yc66R54zgflwJVPJqiBXMzqA,1681
328
+ omlish/lite/resources.py,sha256=YNSmX1Ohck1aoWRs55a-o5ChVbFJIQhtbqE-XwF55Oc,326
328
329
  omlish/lite/runtime.py,sha256=lVw5_yuQNHXZLwGf_l59u8IrAtBLZWPTml6owQ55uro,439
329
330
  omlish/lite/secrets.py,sha256=3Mz3V2jf__XU9qNHcH56sBSw95L3U2UPL24bjvobG0c,816
330
331
  omlish/lite/socket.py,sha256=7OYgkXTcQv0wq7TQuLnl9y6dJA1ZT6Vbc1JH59QlxgY,1792
@@ -333,11 +334,11 @@ omlish/lite/strings.py,sha256=QURcE4-1pKVW8eT_5VCJpXaHDWR2dW2pYOChTJnZDiQ,1504
333
334
  omlish/lite/subprocesses.py,sha256=1we1S-YQ9kbH36hPWLoh6zKZUARRnq2__ewtX_dVdWU,3633
334
335
  omlish/lite/typing.py,sha256=U3-JaEnkDSYxK4tsu_MzUn3RP6qALBe5FXQXpD-licE,1090
335
336
  omlish/lite/fdio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
336
- omlish/lite/fdio/corohttp.py,sha256=VuS4IaAluMPgtl9iQnMnKQsEMlqruN6B1BKkTV0WWKk,4080
337
- omlish/lite/fdio/handlers.py,sha256=ukUiwF8-UCr4mzTTfOaTipC0k3k7THiHnohVdYfH69o,1341
338
- omlish/lite/fdio/kqueue.py,sha256=lIWvvRpRyak0dmzE6FPtCdS02HGo0EEI0D1g8cWyLYk,3832
339
- omlish/lite/fdio/manager.py,sha256=-gMVzk4B1YTZS-d2TdM12woUme37pcNVUxNTiLe91lA,1250
340
- omlish/lite/fdio/pollers.py,sha256=d73P2ynzFdQZhmxhMKghzO6zvLwzTMSaIgBi7wQ5IQs,5507
337
+ omlish/lite/fdio/corohttp.py,sha256=FHdakDTGI2UYbCihahuwleyailclxQMUGhpkz3suww4,4080
338
+ omlish/lite/fdio/handlers.py,sha256=Wr0O2cvIC8NuLs3yoDHj9ZG4n1g_oVEeT87B0WDsg0Y,1341
339
+ omlish/lite/fdio/kqueue.py,sha256=YgGBQibkAUYODYDiGl7Enjtx1oQsJXuDsBLBXgqlLQw,3832
340
+ omlish/lite/fdio/manager.py,sha256=q4wWf7nKrNtjx6yPEvrVnFt4UtK_BTvVlquEGw7poEo,1250
341
+ omlish/lite/fdio/pollers.py,sha256=yNadAt3W5wd90PFmd3vD77bq5QwoVb2A6SM2JjZpKRs,5507
341
342
  omlish/lite/http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
342
343
  omlish/lite/http/coroserver.py,sha256=aBaYjP80yQHQxPxwi7PTYHub-fdRDKsMnB-tM8lBc2o,18095
343
344
  omlish/lite/http/handlers.py,sha256=Yu0P3nqz-frklwCM2PbiWvoJNE-NqeTFLBvpNpqcdtA,753
@@ -350,6 +351,9 @@ omlish/logs/formatters.py,sha256=q79nMnR2mRIStPyGrydQHpYTXgC5HHptt8lH3W2Wwbs,671
350
351
  omlish/logs/handlers.py,sha256=UpzUf3kWBBzWOnrtljoZsLjISw3Ix-ePz3Nsmp6lRgE,255
351
352
  omlish/logs/noisy.py,sha256=Ubc-eTH6ZbGYsLfUUi69JAotwuUwzb-SJBeGo_0dIZI,348
352
353
  omlish/logs/utils.py,sha256=MgGovbP0zUrZ3FGD3qYNQWn-l0jy0Y0bStcQvv5BOmQ,391
354
+ omlish/manifests/__init__.py,sha256=P2B0dpT8D7l5lJwRGPA92IcQj6oeXfd90X5-q9BJrKg,51
355
+ omlish/manifests/load.py,sha256=Wn0Orrs65rLdXneT7tlixX5Q5OXW460-zzw6IkAye7k,4788
356
+ omlish/manifests/types.py,sha256=d8bv5tknCJqclRfxCpao_8XxHo2yofhLpVHQTB-MfNw,260
353
357
  omlish/marshal/__init__.py,sha256=iVA7n31L08Bdub6HKPvYOXVvDhk2CMA6rPeKDL_u1to,2298
354
358
  omlish/marshal/any.py,sha256=e82OyYK3Emm1P1ClnsnxP7fIWC2iNVyW0H5nK4mLmWM,779
355
359
  omlish/marshal/base.py,sha256=HEzfby-PgGzIhiRpBkFrkw5-hKacRSC5W_jwLjT8aYw,6740
@@ -500,9 +504,9 @@ omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,329
500
504
  omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
501
505
  omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
502
506
  omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
503
- omlish-0.0.0.dev144.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
504
- omlish-0.0.0.dev144.dist-info/METADATA,sha256=iSpb58aExr5aGcD3lhNq7BsAewClNKVvMdnbWH4u3sU,4264
505
- omlish-0.0.0.dev144.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
506
- omlish-0.0.0.dev144.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
507
- omlish-0.0.0.dev144.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
508
- omlish-0.0.0.dev144.dist-info/RECORD,,
507
+ omlish-0.0.0.dev146.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
508
+ omlish-0.0.0.dev146.dist-info/METADATA,sha256=V8cPQmzScS8Lnw8b-HzO9Pg_uvOnOaPZxPJ_yrzxTc8,4264
509
+ omlish-0.0.0.dev146.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
510
+ omlish-0.0.0.dev146.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
511
+ omlish-0.0.0.dev146.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
512
+ omlish-0.0.0.dev146.dist-info/RECORD,,