ovld 0.5.9__py3-none-any.whl → 0.5.10__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.
- ovld/core.py +82 -60
- ovld/medley.py +10 -5
- ovld/mro.py +2 -2
- ovld/signatures.py +4 -5
- ovld/typemap.py +4 -2
- ovld/types.py +3 -3
- ovld/version.py +1 -1
- {ovld-0.5.9.dist-info → ovld-0.5.10.dist-info}/METADATA +1 -1
- ovld-0.5.10.dist-info/RECORD +18 -0
- ovld-0.5.9.dist-info/RECORD +0 -18
- {ovld-0.5.9.dist-info → ovld-0.5.10.dist-info}/WHEEL +0 -0
- {ovld-0.5.9.dist-info → ovld-0.5.10.dist-info}/licenses/LICENSE +0 -0
ovld/core.py
CHANGED
@@ -25,6 +25,21 @@ from .utils import (
|
|
25
25
|
subtler_type,
|
26
26
|
)
|
27
27
|
|
28
|
+
_orig_getdoc = inspect.getdoc
|
29
|
+
|
30
|
+
|
31
|
+
def _getdoc(fn):
|
32
|
+
if hasattr(fn, "__calculate_doc__"):
|
33
|
+
if inspect.ismethod(fn):
|
34
|
+
fn = fn.__func__
|
35
|
+
fn.__doc__ = fn.__calculate_doc__()
|
36
|
+
del fn.__calculate_doc__
|
37
|
+
return _orig_getdoc(fn)
|
38
|
+
|
39
|
+
|
40
|
+
inspect.getdoc = _getdoc
|
41
|
+
|
42
|
+
|
28
43
|
_current_id = itertools.count()
|
29
44
|
|
30
45
|
|
@@ -72,8 +87,6 @@ class Ovld:
|
|
72
87
|
dispatch.
|
73
88
|
linkback: Whether to keep a pointer in the parent mixins to this
|
74
89
|
ovld so that updates can be propagated. (default: False)
|
75
|
-
allow_replacement: Allow replacing a method by another with the
|
76
|
-
same signature. (default: True)
|
77
90
|
"""
|
78
91
|
|
79
92
|
def __init__(
|
@@ -82,50 +95,43 @@ class Ovld:
|
|
82
95
|
mixins=[],
|
83
96
|
name=None,
|
84
97
|
linkback=False,
|
85
|
-
allow_replacement=True,
|
86
98
|
):
|
87
99
|
"""Initialize an Ovld."""
|
88
100
|
self.id = next(_current_id)
|
89
101
|
self.specialization_self = MISSING
|
90
102
|
self._compiled = False
|
103
|
+
self._signatures = None
|
104
|
+
self._argument_analysis = None
|
91
105
|
self.linkback = linkback
|
92
106
|
self.children = []
|
93
|
-
self.allow_replacement = allow_replacement
|
94
107
|
self.name = name
|
95
108
|
self.shortname = name or f"__OVLD{self.id}"
|
96
109
|
self.__name__ = name
|
97
|
-
self.
|
110
|
+
self._regs = {}
|
98
111
|
self._locked = False
|
99
112
|
self.mixins = []
|
100
|
-
self.argument_analysis = ArgumentAnalyzer()
|
101
113
|
self.dispatch = bootstrap_dispatch(self, name=self.shortname)
|
102
114
|
self.add_mixins(*mixins)
|
103
115
|
|
104
|
-
|
105
|
-
def defns(self):
|
106
|
-
defns = {}
|
116
|
+
def regs(self):
|
107
117
|
for mixin in self.mixins:
|
108
|
-
|
109
|
-
|
110
|
-
return defns
|
118
|
+
yield from mixin.regs()
|
119
|
+
yield from self._regs.items()
|
111
120
|
|
112
|
-
def
|
113
|
-
self.
|
114
|
-
for key, fn in list(self.defns.items()):
|
115
|
-
self.argument_analysis.add(fn)
|
116
|
-
self.argument_analysis.compile()
|
117
|
-
return self.argument_analysis
|
121
|
+
def empty(self):
|
122
|
+
return not self._regs and all(m.empty() for m in self.mixins)
|
118
123
|
|
119
124
|
def mkdoc(self):
|
125
|
+
fns = [f for f, _ in self.regs()]
|
120
126
|
try:
|
121
|
-
docs = [fn.__doc__ for fn in
|
127
|
+
docs = [fn.__doc__ for fn in fns if fn.__doc__]
|
122
128
|
if len(docs) == 1:
|
123
129
|
maindoc = docs[0]
|
124
130
|
else:
|
125
|
-
maindoc = f"Ovld with {len(
|
131
|
+
maindoc = f"Ovld with {len(fns)} methods."
|
126
132
|
|
127
133
|
doc = f"{maindoc}\n\n"
|
128
|
-
for fn in
|
134
|
+
for fn in fns:
|
129
135
|
fndef = inspect.signature(fn)
|
130
136
|
fdoc = fn.__doc__
|
131
137
|
if not fdoc or fdoc == maindoc:
|
@@ -192,17 +198,41 @@ class Ovld:
|
|
192
198
|
def __set_name__(self, inst, name):
|
193
199
|
self.rename(name)
|
194
200
|
|
195
|
-
def _set_attrs_from(self, fn):
|
196
|
-
"""Inherit relevant attributes from the function."""
|
197
|
-
if self.name is None:
|
198
|
-
self.__qualname__ = fn.__qualname__
|
199
|
-
self.__module__ = fn.__module__
|
200
|
-
self.rename(f"{fn.__module__}.{fn.__qualname__}", fn.__name__)
|
201
|
-
|
202
201
|
def ensure_compiled(self):
|
203
202
|
if not self._compiled:
|
204
203
|
self.compile()
|
205
204
|
|
205
|
+
@property
|
206
|
+
def signatures(self):
|
207
|
+
if self._signatures is None:
|
208
|
+
regs = {}
|
209
|
+
for fn, priority in self.regs():
|
210
|
+
ss = self.specialization_self
|
211
|
+
cgf = getattr(ss, "_ovld_codegen_fields", ())
|
212
|
+
lcl = {f: getattr(ss, f) for f in cgf}
|
213
|
+
sig = replace(Signature.extract(fn, lcl), priority=priority)
|
214
|
+
|
215
|
+
def _set(sig, fn):
|
216
|
+
if sig in regs:
|
217
|
+
# Push down the existing handler with a lower tiebreak
|
218
|
+
msig = replace(sig, tiebreak=sig.tiebreak - 1)
|
219
|
+
_set(msig, regs[sig])
|
220
|
+
regs[sig] = fn
|
221
|
+
|
222
|
+
_set(sig, fn)
|
223
|
+
self._signatures = regs
|
224
|
+
return self._signatures
|
225
|
+
|
226
|
+
@property
|
227
|
+
def argument_analysis(self):
|
228
|
+
if self._argument_analysis is None:
|
229
|
+
aa = ArgumentAnalyzer()
|
230
|
+
for sig in self.signatures:
|
231
|
+
aa.add(sig)
|
232
|
+
aa.compile()
|
233
|
+
self._argument_analysis = aa
|
234
|
+
return self._argument_analysis
|
235
|
+
|
206
236
|
def compile(self):
|
207
237
|
"""Finalize this overload.
|
208
238
|
|
@@ -223,7 +253,9 @@ class Ovld:
|
|
223
253
|
name = self.__name__
|
224
254
|
self.map = MultiTypeMap(name=name, key_error=self._key_error, ovld=self)
|
225
255
|
|
226
|
-
self.
|
256
|
+
for sig, fn in list(self.signatures.items()):
|
257
|
+
self.register_signature(sig, fn)
|
258
|
+
|
227
259
|
dispatch = generate_dispatch(self, self.argument_analysis)
|
228
260
|
self.dispatch.__code__ = rename_code(dispatch.__code__, self.shortname)
|
229
261
|
self.dispatch.__kwdefaults__ = dispatch.__kwdefaults__
|
@@ -231,10 +263,7 @@ class Ovld:
|
|
231
263
|
self.dispatch.__defaults__ = dispatch.__defaults__
|
232
264
|
self.dispatch.__globals__.update(dispatch.__globals__)
|
233
265
|
self.dispatch.map = self.map
|
234
|
-
self.dispatch.
|
235
|
-
|
236
|
-
for key, fn in list(self.defns.items()):
|
237
|
-
self.register_signature(key, fn)
|
266
|
+
self.dispatch.__generate_doc__ = self.mkdoc
|
238
267
|
|
239
268
|
self._compiled = True
|
240
269
|
|
@@ -275,42 +304,35 @@ class Ovld:
|
|
275
304
|
def _register(self, fn, priority):
|
276
305
|
"""Register a function."""
|
277
306
|
|
278
|
-
|
279
|
-
|
280
|
-
self._set_attrs_from(fn)
|
281
|
-
|
282
|
-
sig = replace(Signature.extract(fn), priority=priority)
|
283
|
-
if not self.allow_replacement and sig in self._defns:
|
284
|
-
raise TypeError(f"There is already a method for {sigstring(sig.types)}")
|
307
|
+
if not isinstance(priority, tuple):
|
308
|
+
priority = (priority,)
|
285
309
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
_set(sig, fn)
|
310
|
+
self._attempt_modify()
|
311
|
+
if self.name is None:
|
312
|
+
self.__qualname__ = fn.__qualname__
|
313
|
+
self.__module__ = fn.__module__
|
314
|
+
self.rename(f"{fn.__module__}.{fn.__qualname__}", fn.__name__)
|
315
|
+
self._regs[fn] = priority
|
294
316
|
|
295
|
-
self.
|
317
|
+
self.invalidate()
|
296
318
|
return self
|
297
319
|
|
298
320
|
def unregister(self, fn):
|
299
321
|
"""Unregister a function."""
|
300
322
|
self._attempt_modify()
|
301
|
-
|
302
|
-
self.
|
303
|
-
|
304
|
-
def
|
305
|
-
self.
|
323
|
+
del self._regs[fn]
|
324
|
+
self.invalidate()
|
325
|
+
|
326
|
+
def invalidate(self):
|
327
|
+
self._signatures = None
|
328
|
+
self._argument_analysis = None
|
329
|
+
if self._compiled:
|
330
|
+
self._compiled = False
|
331
|
+
self.dispatch.__code__ = self.dispatch.first_entry.__code__
|
306
332
|
for child in self.children:
|
307
|
-
child.
|
333
|
+
child.invalidate()
|
308
334
|
if hasattr(self, "dispatch"):
|
309
|
-
self.dispatch.
|
310
|
-
|
311
|
-
def reset(self):
|
312
|
-
self._compiled = False
|
313
|
-
self.dispatch.__code__ = self.dispatch.first_entry.__code__
|
335
|
+
self.dispatch.__calculate_doc__ = self.mkdoc
|
314
336
|
|
315
337
|
def copy(self, mixins=[], linkback=False):
|
316
338
|
"""Create a copy of this Ovld.
|
ovld/medley.py
CHANGED
@@ -123,9 +123,9 @@ class BuildOvld(Combiner):
|
|
123
123
|
for f, arg in self.pending:
|
124
124
|
f(arg)
|
125
125
|
self.pending.clear()
|
126
|
-
if
|
126
|
+
if self.ovld.empty():
|
127
127
|
return ABSENT
|
128
|
-
self.ovld.
|
128
|
+
self.ovld.invalidate()
|
129
129
|
return self.ovld.dispatch
|
130
130
|
|
131
131
|
def copy(self):
|
@@ -337,15 +337,20 @@ _meld_classes_cache = {}
|
|
337
337
|
|
338
338
|
|
339
339
|
def meld_classes(classes):
|
340
|
+
def key(cls):
|
341
|
+
return getattr(cls, "_ovld_specialization_parent", None) or cls
|
342
|
+
|
340
343
|
medleys = {}
|
341
344
|
for cls in classes:
|
342
|
-
medleys.update({x:
|
345
|
+
medleys.update({key(x): x for x in getattr(cls, "_ovld_medleys", [cls])})
|
343
346
|
for cls in classes:
|
347
|
+
cls = key(cls)
|
344
348
|
if not hasattr(cls, "_ovld_medleys"):
|
345
349
|
for base in cls.mro():
|
346
350
|
if base is not cls and base in medleys:
|
347
351
|
del medleys[base]
|
348
|
-
|
352
|
+
|
353
|
+
medleys = tuple(medleys.values())
|
349
354
|
if len(medleys) == 1:
|
350
355
|
return medleys[0]
|
351
356
|
|
@@ -372,7 +377,7 @@ def meld_classes(classes):
|
|
372
377
|
|
373
378
|
result = make_dataclass(
|
374
379
|
cls_name="+".join(sorted(c.__name__ for c in medleys)),
|
375
|
-
bases=
|
380
|
+
bases=medleys,
|
376
381
|
fields=dc_fields,
|
377
382
|
kw_only=True,
|
378
383
|
namespace=merged,
|
ovld/mro.py
CHANGED
@@ -118,8 +118,8 @@ def typeorder(t1, t2):
|
|
118
118
|
ords = [typeorder(a1, a2) for a1, a2 in zip(args1, args2)]
|
119
119
|
return Order.merge(ords)
|
120
120
|
|
121
|
-
if not isinstance(t1, type) or not isinstance(t2, type):
|
122
|
-
return Order.
|
121
|
+
if not isinstance(t1, type) or not isinstance(t2, type):
|
122
|
+
return Order.NONE
|
123
123
|
|
124
124
|
sx = issubclass(t1, t2)
|
125
125
|
sy = issubclass(t2, t1)
|
ovld/signatures.py
CHANGED
@@ -30,7 +30,7 @@ class LazySignature(inspect.Signature):
|
|
30
30
|
|
31
31
|
@property
|
32
32
|
def parameters(self):
|
33
|
-
anal = self.ovld.
|
33
|
+
anal = self.ovld.argument_analysis
|
34
34
|
parameters = []
|
35
35
|
if anal.is_method:
|
36
36
|
parameters.append(
|
@@ -117,7 +117,7 @@ class Signature:
|
|
117
117
|
arginfo: list[Arginfo] = field(default_factory=list, hash=False, compare=False)
|
118
118
|
|
119
119
|
@classmethod
|
120
|
-
def extract(cls, fn):
|
120
|
+
def extract(cls, fn, lcl={}):
|
121
121
|
typelist = []
|
122
122
|
sig = inspect.signature(fn)
|
123
123
|
max_pos = 0
|
@@ -135,7 +135,7 @@ class Signature:
|
|
135
135
|
is_method = True
|
136
136
|
continue
|
137
137
|
pos = nm = None
|
138
|
-
ann = normalize_type(param.annotation, fn)
|
138
|
+
ann = normalize_type(param.annotation, fn, lcl)
|
139
139
|
if param.kind is inspect._POSITIONAL_ONLY:
|
140
140
|
pos = i - is_method
|
141
141
|
typelist.append(ann)
|
@@ -188,9 +188,8 @@ class ArgumentAnalyzer:
|
|
188
188
|
self.is_method = None
|
189
189
|
self.done = False
|
190
190
|
|
191
|
-
def add(self,
|
191
|
+
def add(self, sig):
|
192
192
|
self.done = False
|
193
|
-
sig = Signature.extract(fn)
|
194
193
|
self.complex_transforms.update(arg.canonical for arg in sig.arginfo if arg.is_complex)
|
195
194
|
for arg in sig.arginfo:
|
196
195
|
if arg.position is not None:
|
ovld/typemap.py
CHANGED
@@ -242,7 +242,8 @@ class MultiTypeMap(dict):
|
|
242
242
|
self.maps[-1].register(object, entry)
|
243
243
|
|
244
244
|
def display_methods(self):
|
245
|
-
for h, prio in sorted(self.priorities.items(), key=lambda kv:
|
245
|
+
for h, prio in sorted(self.priorities.items(), key=lambda kv: kv[1], reverse=True):
|
246
|
+
prio = ":".join(map(str, prio))
|
246
247
|
prio = f"[{prio}]"
|
247
248
|
width = 6
|
248
249
|
print(f"{prio:{width}} \033[1m{h.__name__}\033[0m")
|
@@ -306,7 +307,8 @@ class MultiTypeMap(dict):
|
|
306
307
|
color = "\033[1;32m"
|
307
308
|
rank += 1
|
308
309
|
spec = ".".join(map(str, c.specificity))
|
309
|
-
|
310
|
+
prios = ":".join(map(str, c.priority))
|
311
|
+
lvl = f"[{prios}:{spec}]"
|
310
312
|
width = 2 * len(args) + 6
|
311
313
|
print(f"{color}{bullet} {lvl:{width}} {handler.__name__}")
|
312
314
|
co = handler.__code__
|
ovld/types.py
CHANGED
@@ -25,7 +25,7 @@ def eval_annotation(t, ctx, locals, catch=False):
|
|
25
25
|
else: # pragma: no cover
|
26
26
|
glb = {}
|
27
27
|
return eval(t, glb, locals)
|
28
|
-
else:
|
28
|
+
else: # pragma: no cover
|
29
29
|
return t
|
30
30
|
except Exception: # pragma: no cover
|
31
31
|
if catch:
|
@@ -43,11 +43,11 @@ class TypeNormalizer:
|
|
43
43
|
else:
|
44
44
|
self.generic_handlers.register(generic, handler)
|
45
45
|
|
46
|
-
def __call__(self, t, fn):
|
46
|
+
def __call__(self, t, fn, lcl={}):
|
47
47
|
from .dependent import DependentType
|
48
48
|
|
49
49
|
if isinstance(t, str):
|
50
|
-
t = eval_annotation(t, fn,
|
50
|
+
t = eval_annotation(t, fn, lcl)
|
51
51
|
|
52
52
|
if t is type:
|
53
53
|
t = type[object]
|
ovld/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
version = "0.5.
|
1
|
+
version = "0.5.10"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
ovld/__init__.py,sha256=JuCM8Sj65gobV0KYyLr95cSI23Pi6RYZ7X3_F3fdsSw,1821
|
2
|
+
ovld/abc.py,sha256=4qpZyYwI8dWgY1Oiv5FhdKg2uzNcyWxIpGmGJVcjXrs,1177
|
3
|
+
ovld/codegen.py,sha256=27tmamlanuTPDT-x31ISyqP0wGKW9BCFZJGVyq9qLg8,9728
|
4
|
+
ovld/core.py,sha256=vVvaQppGZcccgRuxMkdQCr9jXrG9_xJn3ohyT0bIkEA,18251
|
5
|
+
ovld/dependent.py,sha256=JIgsc_5ddPH51_2IrZ6JW6bWE5RyrrrOwR2e9UvDhZ4,8922
|
6
|
+
ovld/medley.py,sha256=qiYUtMbYR-fzvmqfr7BDY2Ht3SbNOEJ9VaR7s-BNGRo,12962
|
7
|
+
ovld/mro.py,sha256=RxHoOpf5nIOD4yU-Bb0Zt5tFyral9zljaPDVGebnnJo,6218
|
8
|
+
ovld/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
ovld/recode.py,sha256=vXg9XLExp_9LdAHO0JWR4wvwHhpOLu2Xcrg9ZYg1nms,16407
|
10
|
+
ovld/signatures.py,sha256=EXE5Jik8m-3UtkS1lgr3rl5QS7NRcJfuI3VRaU6v1bg,8960
|
11
|
+
ovld/typemap.py,sha256=jcYiIPt8wVng0u7qdceEMt7i0gmlo7BMFbvHLkf6zD8,14092
|
12
|
+
ovld/types.py,sha256=sP4xqx5jZ-gYnQ4LlvT5v7N8I1npNdKKZf72rBelvEA,13402
|
13
|
+
ovld/utils.py,sha256=8nvycMWpTmwGq7ojjDA7yi2NdkU78NBdUlvRk_vDECY,5086
|
14
|
+
ovld/version.py,sha256=H2w8gxble-MJwdr4ywy0-MXcLJNCr6buKONQqjAMUuQ,19
|
15
|
+
ovld-0.5.10.dist-info/METADATA,sha256=TQnXuZ-NjT_wv8OGFY6zz33x7_4QGOcN6f3bNhNmBZw,10459
|
16
|
+
ovld-0.5.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
17
|
+
ovld-0.5.10.dist-info/licenses/LICENSE,sha256=cSwNTIzd1cbI89xt3PeZZYJP2y3j8Zus4bXgo4svpX8,1066
|
18
|
+
ovld-0.5.10.dist-info/RECORD,,
|
ovld-0.5.9.dist-info/RECORD
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
ovld/__init__.py,sha256=JuCM8Sj65gobV0KYyLr95cSI23Pi6RYZ7X3_F3fdsSw,1821
|
2
|
-
ovld/abc.py,sha256=4qpZyYwI8dWgY1Oiv5FhdKg2uzNcyWxIpGmGJVcjXrs,1177
|
3
|
-
ovld/codegen.py,sha256=27tmamlanuTPDT-x31ISyqP0wGKW9BCFZJGVyq9qLg8,9728
|
4
|
-
ovld/core.py,sha256=WqZ1lvcAGSri02XZeY73Bj5AKB9RYBCAvHLbyns8u68,17792
|
5
|
-
ovld/dependent.py,sha256=JIgsc_5ddPH51_2IrZ6JW6bWE5RyrrrOwR2e9UvDhZ4,8922
|
6
|
-
ovld/medley.py,sha256=Pq6j4qPl8osyQ4Xp-ktnt2uJXytC9Jo70toS5LYHRf8,12840
|
7
|
-
ovld/mro.py,sha256=-M-BFtmSSEZ39eMPpZ4c2xTAwE43zuJu_jtlxAEfuPo,6238
|
8
|
-
ovld/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
ovld/recode.py,sha256=vXg9XLExp_9LdAHO0JWR4wvwHhpOLu2Xcrg9ZYg1nms,16407
|
10
|
-
ovld/signatures.py,sha256=Q8JucSOun0ESGx14aWtHtBzLEiM6FxY5HP3imyqXoDo,8984
|
11
|
-
ovld/typemap.py,sha256=wkLuCc6xa2VZJOMaAhuYYgnNrywhovkQwbkBnoRfCsY,13985
|
12
|
-
ovld/types.py,sha256=CRL6Vuzg5moXgAAhIj2698GvZoyF4HWbUDYz2hKt6us,13373
|
13
|
-
ovld/utils.py,sha256=8nvycMWpTmwGq7ojjDA7yi2NdkU78NBdUlvRk_vDECY,5086
|
14
|
-
ovld/version.py,sha256=fa8mYJ1rRpnvSWOBQjwJEtqO9AqOw8j-QGkxIJqUaM0,18
|
15
|
-
ovld-0.5.9.dist-info/METADATA,sha256=7TIVCS1fVm0Oq7GcG5KR9JRNWQa6JkM-c6euVUu3e6g,10458
|
16
|
-
ovld-0.5.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
17
|
-
ovld-0.5.9.dist-info/licenses/LICENSE,sha256=cSwNTIzd1cbI89xt3PeZZYJP2y3j8Zus4bXgo4svpX8,1066
|
18
|
-
ovld-0.5.9.dist-info/RECORD,,
|
File without changes
|
File without changes
|