ovld 0.4.6__py3-none-any.whl → 0.5.0__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/typemap.py CHANGED
@@ -6,7 +6,7 @@ from types import CodeType
6
6
 
7
7
  from .mro import sort_types
8
8
  from .recode import generate_dependent_dispatch
9
- from .utils import MISSING, subtler_type
9
+ from .utils import MISSING, CodegenInProgress, subtler_type
10
10
 
11
11
 
12
12
  class TypeMap(dict):
@@ -58,6 +58,7 @@ class TypeMap(dict):
58
58
  @dataclass
59
59
  class Candidate:
60
60
  handler: object
61
+ base_handler: object
61
62
  priority: float
62
63
  specificity: tuple
63
64
  tiebreak: int
@@ -69,9 +70,7 @@ class Candidate:
69
70
  if self.priority > other.priority:
70
71
  return True
71
72
  elif self.specificity != other.specificity:
72
- return all(
73
- s1 >= s2 for s1, s2 in zip(self.specificity, other.specificity)
74
- )
73
+ return all(s1 >= s2 for s1, s2 in zip(self.specificity, other.specificity))
75
74
  else:
76
75
  return self.tiebreak > other.tiebreak
77
76
 
@@ -95,7 +94,7 @@ class MultiTypeMap(dict):
95
94
  specific than [object, int] (which means there is an ambiguity).
96
95
  """
97
96
 
98
- def __init__(self, name="_ovld", key_error=KeyError):
97
+ def __init__(self, name="_ovld", key_error=KeyError, ovld=None):
99
98
  self.maps = {}
100
99
  self.priorities = {}
101
100
  self.tiebreaks = {}
@@ -107,8 +106,10 @@ class MultiTypeMap(dict):
107
106
  self.dispatch_id = count()
108
107
  self.all = {}
109
108
  self.errors = {}
109
+ self.ovld = ovld
110
+ self.in_progress = set()
110
111
 
111
- def mro(self, obj_t_tup):
112
+ def mro(self, obj_t_tup, specialize=True):
112
113
  specificities = {}
113
114
  candidates = None
114
115
  nargs = len([t for t in obj_t_tup if not isinstance(t, tuple)])
@@ -126,9 +127,7 @@ class MultiTypeMap(dict):
126
127
  results = {
127
128
  handler: spc
128
129
  for (handler, sig), spc in results.items()
129
- if sig.req_pos
130
- <= nargs
131
- <= (math.inf if sig.vararg else sig.max_pos)
130
+ if sig.req_pos <= nargs <= (math.inf if sig.vararg else sig.max_pos)
132
131
  and not (sig.req_names - names)
133
132
  }
134
133
 
@@ -152,14 +151,26 @@ class MultiTypeMap(dict):
152
151
  for c in candidates:
153
152
  specificities.setdefault(c, []).append(results[c])
154
153
 
154
+ def get_handler(func):
155
+ if specialize and (specializer := getattr(func, "specializer", False)):
156
+ key = (func, obj_t_tup)
157
+ if key in self.in_progress:
158
+ raise CodegenInProgress()
159
+ self.in_progress.add(key)
160
+ return specializer(self, func, obj_t_tup)
161
+ else:
162
+ return func
163
+
155
164
  candidates = [
156
165
  Candidate(
157
- handler=c,
166
+ handler=h,
167
+ base_handler=c,
158
168
  priority=self.priorities.get(c, 0),
159
169
  specificity=tuple(specificities[c]),
160
170
  tiebreak=self.tiebreaks.get(c, 0),
161
171
  )
162
172
  for c in candidates
173
+ if (h := get_handler(c))
163
174
  ]
164
175
 
165
176
  # The sort ensures that if candidate A dominates candidate B, A will
@@ -170,9 +181,7 @@ class MultiTypeMap(dict):
170
181
 
171
182
  candidates.sort(key=Candidate.sort_key, reverse=True)
172
183
 
173
- self.all[obj_t_tup] = {
174
- getattr(c.handler, "__code__", None) for c in candidates
175
- }
184
+ self.all[obj_t_tup] = {getattr(c.handler, "__code__", None) for c in candidates}
176
185
 
177
186
  processed = set()
178
187
 
@@ -239,7 +248,7 @@ class MultiTypeMap(dict):
239
248
  width = 6
240
249
  print(f"{prio:{width}} \033[1m{h.__name__}\033[0m")
241
250
  co = h.__code__
242
- print(f"{'':{width-2}} @ {co.co_filename}:{co.co_firstlineno}")
251
+ print(f"{'':{width - 2}} @ {co.co_filename}:{co.co_firstlineno}")
243
252
 
244
253
  def display_resolution(self, *args, **kwargs):
245
254
  from .dependent import is_dependent
@@ -263,9 +272,7 @@ class MultiTypeMap(dict):
263
272
  for grp in self.mro(tuple(argt)):
264
273
  grp.sort(key=lambda x: x.handler.__name__)
265
274
  match = [
266
- dependent_match(
267
- self.type_tuples[c.handler], [*args, *kwargs.items()]
268
- )
275
+ dependent_match(self.type_tuples[c.base_handler], [*args, *kwargs.items()])
269
276
  for c in grp
270
277
  ]
271
278
  ambiguous = len([m for m in match if m]) > 1
@@ -292,22 +299,17 @@ class MultiTypeMap(dict):
292
299
  width = 2 * len(args) + 6
293
300
  print(f"{color}{bullet} {lvl:{width}} {handler.__name__}")
294
301
  co = handler.__code__
295
- print(
296
- f" {'':{width-1}}@ {co.co_filename}:{co.co_firstlineno}\033[0m"
297
- )
302
+ print(f" {'':{width - 1}}@ {co.co_filename}:{co.co_firstlineno}\033[0m")
298
303
  if ambiguous:
299
- message += " There is ambiguity between multiple matching methods, marked '=='."
304
+ message += (
305
+ " There is ambiguity between multiple matching methods, marked '=='."
306
+ )
300
307
  finished = True
301
308
  print("Resolution:", message)
302
309
 
303
- def wrap_dependent(self, tup, handlers, group, next_call):
304
- handlers = list(handlers)
305
- htup = [(h, self.type_tuples[h]) for h in handlers]
306
- slf = (
307
- "self, "
308
- if inspect.getfullargspec(handlers[0]).args[0] == "self"
309
- else ""
310
- )
310
+ def wrap_dependent(self, tup, group, next_call):
311
+ htup = [(c.handler, self.type_tuples[c.base_handler]) for c in group]
312
+ slf = "self, " if inspect.getfullargspec(group[0].handler).args[0] == "self" else ""
311
313
  return generate_dependent_dispatch(
312
314
  tup,
313
315
  htup,
@@ -326,11 +328,9 @@ class MultiTypeMap(dict):
326
328
  funcs = []
327
329
  for group in reversed(results):
328
330
  handlers = [c.handler for c in group]
329
- dependent = any(self.dependent[c.handler] for c in group)
331
+ dependent = any(self.dependent[c.base_handler] for c in group)
330
332
  if dependent:
331
- nxt = self.wrap_dependent(
332
- obj_t_tup, handlers, group, funcs[-1] if funcs else None
333
- )
333
+ nxt = self.wrap_dependent(obj_t_tup, group, funcs[-1] if funcs else None)
334
334
  elif len(group) != 1:
335
335
  nxt = None
336
336
  else:
@@ -342,11 +342,7 @@ class MultiTypeMap(dict):
342
342
 
343
343
  parents = []
344
344
  for group, (func, codes) in zip(results, funcs):
345
- tups = (
346
- [obj_t_tup]
347
- if not parents
348
- else [(parent, *obj_t_tup) for parent in parents]
349
- )
345
+ tups = [obj_t_tup] if not parents else [(parent, *obj_t_tup) for parent in parents]
350
346
  if func is None:
351
347
  for tup in tups:
352
348
  self.errors[tup] = self.key_error(obj_t_tup, group)
@@ -386,3 +382,9 @@ class MultiTypeMap(dict):
386
382
  raise self.errors[obj_t_tup]
387
383
  else:
388
384
  return self[obj_t_tup]
385
+
386
+ def __call__(self, *obj_t_tup, after=None):
387
+ if after:
388
+ return self[(after, *obj_t_tup)]
389
+ else:
390
+ return self[obj_t_tup]
ovld/types.py CHANGED
@@ -1,3 +1,4 @@
1
+ import importlib
1
2
  import inspect
2
3
  import sys
3
4
  import typing
@@ -5,7 +6,9 @@ from dataclasses import dataclass
5
6
  from functools import partial
6
7
  from typing import Protocol, get_args, runtime_checkable
7
8
 
9
+ from .codegen import Code
8
10
  from .mro import Order, TypeRelationship, subclasscheck, typeorder
11
+ from .recode import generate_checking_code
9
12
  from .typemap import TypeMap
10
13
  from .utils import UnionType, UnionTypes, UsageError, clsstring
11
14
 
@@ -17,6 +20,24 @@ def get_args(tp):
17
20
  return args
18
21
 
19
22
 
23
+ def eval_annotation(t, ctx, locals, catch=False):
24
+ try:
25
+ if isinstance(t, str):
26
+ if hasattr(ctx, "__globals__"):
27
+ glb = ctx.__globals__
28
+ elif hasattr(ctx, "__module__"): # pragma: no cover
29
+ glb = vars(importlib.import_module(ctx.__module__))
30
+ else: # pragma: no cover
31
+ glb = {}
32
+ return eval(t, glb, locals)
33
+ else:
34
+ return t
35
+ except Exception: # pragma: no cover
36
+ if catch:
37
+ return None
38
+ raise
39
+
40
+
20
41
  class TypeNormalizer:
21
42
  def __init__(self, generic_handlers=None):
22
43
  self.generic_handlers = generic_handlers or TypeMap()
@@ -31,7 +52,7 @@ class TypeNormalizer:
31
52
  from .dependent import DependentType
32
53
 
33
54
  if isinstance(t, str):
34
- t = eval(t, getattr(fn, "__globals__", {}))
55
+ t = eval_annotation(t, fn, {})
35
56
 
36
57
  if t is type:
37
58
  t = type[object]
@@ -216,11 +237,15 @@ def _getcls(ref):
216
237
 
217
238
 
218
239
  class AllMC(type):
240
+ __bound__ = False
241
+
219
242
  def __type_order__(self, other):
220
243
  return Order.MORE
221
244
 
222
245
  def __is_subtype__(self, other):
223
- return True
246
+ if not self.__bound__:
247
+ return True
248
+ return subclasscheck(self.__bound__, other) or subclasscheck(other, self.__bound__)
224
249
 
225
250
  def __is_supertype__(self, other):
226
251
  return False
@@ -231,6 +256,10 @@ class AllMC(type):
231
256
  def __isinstance__(self, other): # pragma: no cover
232
257
  return False
233
258
 
259
+ def __getitem__(self, item):
260
+ name = getattr(item, "__name__", str(item))
261
+ return type(f"All[{name}]", (self,), {"__bound__": item})
262
+
234
263
 
235
264
  class All(metaclass=AllMC):
236
265
  """All is the empty/void/bottom type -- it acts as a subtype of all types.
@@ -308,11 +337,7 @@ def Exactly(cls, base_cls):
308
337
  @parametrized_class_check
309
338
  def StrictSubclass(cls, base_cls):
310
339
  """Match subclasses but not the base class."""
311
- return (
312
- isinstance(cls, type)
313
- and issubclass(cls, base_cls)
314
- and cls is not base_cls
315
- )
340
+ return isinstance(cls, type) and issubclass(cls, base_cls) and cls is not base_cls
316
341
 
317
342
 
318
343
  @parametrized_class_check
@@ -321,20 +346,13 @@ class Union:
321
346
  self.__args__ = self.types = types
322
347
 
323
348
  def codegen(self):
324
- from .dependent import combine, generate_checking_code
325
-
326
- template = " or ".join("{}" for t in self.types)
327
- return combine(
328
- template, [generate_checking_code(t) for t in self.types]
329
- )
349
+ return Code("($[ or ]checks)", checks=[generate_checking_code(t) for t in self.types])
330
350
 
331
351
  def __type_order__(self, other):
332
352
  if other is Union:
333
353
  return Order.LESS
334
354
  classes = self.types
335
- compare = [
336
- x for t in classes if (x := typeorder(t, other)) is not Order.NONE
337
- ]
355
+ compare = [x for t in classes if (x := typeorder(t, other)) is not Order.NONE]
338
356
  if not compare:
339
357
  return Order.NONE
340
358
  elif any(x is Order.MORE or x is Order.SAME for x in compare):
@@ -372,20 +390,13 @@ class Intersection:
372
390
  self.__args__ = self.types = types
373
391
 
374
392
  def codegen(self):
375
- from .dependent import combine, generate_checking_code
376
-
377
- template = " and ".join("{}" for t in self.types)
378
- return combine(
379
- template, [generate_checking_code(t) for t in self.types]
380
- )
393
+ return Code("($[ and ]checks)", checks=[generate_checking_code(t) for t in self.types])
381
394
 
382
395
  def __type_order__(self, other):
383
396
  if other is Intersection:
384
397
  return Order.LESS
385
398
  classes = self.types
386
- compare = [
387
- x for t in classes if (x := typeorder(t, other)) is not Order.NONE
388
- ]
399
+ compare = [x for t in classes if (x := typeorder(t, other)) is not Order.NONE]
389
400
  if not compare:
390
401
  return Order.NONE
391
402
  elif any(x is Order.LESS or x is Order.SAME for x in compare):
@@ -431,15 +442,3 @@ class Dataclass(Protocol):
431
442
  return hasattr(subclass, "__dataclass_fields__") and hasattr(
432
443
  subclass, "__dataclass_params__"
433
444
  )
434
-
435
-
436
- __all__ = [
437
- "Dataclass",
438
- "Deferred",
439
- "Exactly",
440
- "HasMethod",
441
- "Intersection",
442
- "StrictSubclass",
443
- "class_check",
444
- "parametrized_class_check",
445
- ]
ovld/utils.py CHANGED
@@ -57,13 +57,20 @@ def keyword_decorator(deco):
57
57
  return new_deco
58
58
 
59
59
 
60
+ class CodegenInProgress(Exception):
61
+ pass
62
+
63
+
60
64
  class UsageError(Exception):
61
65
  pass
62
66
 
63
67
 
64
- class Unusable:
65
- def __init__(self, message):
66
- self.__message = message
68
+ class SpecialForm:
69
+ def __init__(self, name, message=None):
70
+ self.__name = name
71
+ self.__message = (
72
+ message or f"{name}() can only be used from inside an @ovld-registered function."
73
+ )
67
74
 
68
75
  def __call__(self, *args, **kwargs):
69
76
  raise UsageError(self.__message)
@@ -71,6 +78,11 @@ class Unusable:
71
78
  def __getattr__(self, attr):
72
79
  raise UsageError(self.__message)
73
80
 
81
+ def __str__(self):
82
+ return f"<SpecialForm {self.__name}>"
83
+
84
+ __repr__ = __str__
85
+
74
86
 
75
87
  class GenericAliasMC(type):
76
88
  def __instancecheck__(cls, obj):
@@ -96,6 +108,18 @@ def clsstring(cls):
96
108
  return r
97
109
 
98
110
 
111
+ def typemap_entry_string(cls):
112
+ if isinstance(cls, tuple):
113
+ key, typ = cls
114
+ return f"{key}: {clsstring(typ)}"
115
+ else:
116
+ return clsstring(cls)
117
+
118
+
119
+ def sigstring(types):
120
+ return ", ".join(map(typemap_entry_string, types))
121
+
122
+
99
123
  def subtler_type(obj):
100
124
  if isinstance(obj, GenericAlias):
101
125
  return type[obj]
@@ -110,7 +134,7 @@ def subtler_type(obj):
110
134
 
111
135
 
112
136
  class NameDatabase:
113
- def __init__(self, default_name):
137
+ def __init__(self, default_name="TMP"):
114
138
  self.default_name = default_name
115
139
  self.count = count()
116
140
  self.variables = {}
@@ -120,32 +144,34 @@ class NameDatabase:
120
144
  def register(self, name):
121
145
  self.registered.add(name)
122
146
 
123
- def gensym(self, desired_name):
147
+ def gensym(self, desired_name, value=None):
124
148
  i = 1
125
149
  name = desired_name
126
- while name in self.registered:
150
+ while name in self.registered or (
151
+ name in __builtins__ and __builtins__[name] != value
152
+ ):
127
153
  name = f"{desired_name}{i}"
128
154
  i += 1
129
155
  self.registered.add(name)
130
156
  return name
131
157
 
132
- def __getitem__(self, value):
158
+ def get(self, value, suggested_name=None):
133
159
  if isinstance(value, (int, float, str)):
134
160
  return repr(value)
135
161
  if id(value) in self.names:
136
162
  return self.names[id(value)]
137
- name = getattr(value, "__name__", self.default_name)
138
- if not re.match(string=name, pattern=r"[a-zA-Z_][a-zA-Z0-9_]+"):
139
- name = self.default_name
140
- name = self.gensym(name)
163
+ dflt = suggested_name or self.default_name
164
+ if (
165
+ isinstance(value, GenericAlias) and typing.get_origin(value) is type
166
+ ): # pragma: no cover
167
+ name = "t_" + getattr(typing.get_args(value)[0], "__name__", dflt)
168
+ else:
169
+ name = getattr(value, "__name__", dflt)
170
+ if not re.match(string=name, pattern=r"^[a-zA-Z_][a-zA-Z0-9_]*$"):
171
+ name = dflt
172
+ name = self.gensym(name, value)
141
173
  self.variables[name] = value
142
174
  self.names[id(value)] = name
143
175
  return name
144
176
 
145
-
146
- __all__ = [
147
- "BOOTSTRAP",
148
- "MISSING",
149
- "Named",
150
- "keyword_decorator",
151
- ]
177
+ __getitem__ = get
ovld/version.py CHANGED
@@ -1 +1 @@
1
- version = "0.4.6"
1
+ version = "0.5.0"
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: ovld
3
- Version: 0.4.6
3
+ Version: 0.5.0
4
4
  Summary: Overloading Python functions
5
5
  Project-URL: Homepage, https://ovld.readthedocs.io/en/latest/
6
6
  Project-URL: Documentation, https://ovld.readthedocs.io/en/latest/
@@ -20,10 +20,11 @@ Fast multiple dispatch in Python, with many extra features.
20
20
 
21
21
  With ovld, you can write a version of the same function for every type signature using annotations instead of writing an awkward sequence of `isinstance` statements. Unlike Python's `singledispatch`, it works for multiple arguments.
22
22
 
23
- * ⚡️ **[Fast](https://ovld.readthedocs.io/en/latest/compare/#results):** `ovld` is the fastest multiple dispatch library around, by some margin.
24
- * 🚀 [**Variants**](https://ovld.readthedocs.io/en/latest/usage/#variants) and [**mixins**](https://ovld.readthedocs.io/en/latest/usage/#mixins) of functions and methods.
23
+ * ⚡️ **[Fast](https://ovld.readthedocs.io/en/latest/compare/#results):** ovld is the fastest multiple dispatch library around, by some margin.
24
+ * 🚀 [**Variants**](https://ovld.readthedocs.io/en/latest/usage/#variants), [**mixins**](https://ovld.readthedocs.io/en/latest/usage/#mixins) and [**medleys**](https://ovld.readthedocs.io/en/latest/medley) of functions and methods.
25
25
  * 🦄 **[Dependent types](https://ovld.readthedocs.io/en/latest/dependent/):** Overloaded functions can depend on more than argument types: they can depend on actual values.
26
- * 🔑 **Extensive:** Dispatch on functions, methods, positional arguments and even [keyword arguments](https://ovld.readthedocs.io/en/latest/usage/#keyword-arguments) (with some restrictions).
26
+ * 🔑 **[Extensive](https://ovld.readthedocs.io/en/latest/usage/#keyword-arguments):** Dispatch on functions, methods, positional arguments and even keyword arguments (with some restrictions).
27
+ * ⚙️ **[Codegen](https://ovld.readthedocs.io/en/latest/codegen/):** (Experimental) For advanced use cases, you can generate custom code for overloads.
27
28
 
28
29
  ## Example
29
30
 
@@ -62,7 +63,7 @@ A *variant* of an `ovld` is a copy of the `ovld`, with some methods added or cha
62
63
 
63
64
  ```python
64
65
  @add.variant
65
- def mul(self, x: object, y: object):
66
+ def mul(x: object, y: object):
66
67
  return x * y
67
68
 
68
69
  assert mul([1, 2], [3, 4]) == [3, 8]
@@ -199,19 +200,64 @@ assert Two().f(1) == "an integer"
199
200
  assert Two().f("s") == "a string"
200
201
  ```
201
202
 
203
+ ## Medleys
204
+
205
+ Inheriting from [`ovld.Medley`](https://ovld.readthedocs.io/en/latest/medley/) lets you combine functionality in a new way. Classes created that way are free-form medleys that you can (almost) arbitrarily combine together.
206
+
207
+ All medleys are dataclasses and you must define their data fields as you would for a normal dataclass (using `dataclass.field` if needed).
208
+
209
+ ```python
210
+ from ovld import Medley
211
+
212
+ class Punctuator(Medley):
213
+ punctuation: str = "."
214
+
215
+ def __call__(self, x: str):
216
+ return f"{x}{self.punctuation}"
217
+
218
+ class Multiplier(Medley):
219
+ factor: int = 3
220
+
221
+ def __call__(self, x: int):
222
+ return x * self.factor
223
+
224
+ # You can add the classes together to merge their methods and fields using ovld
225
+ PuMu = Punctuator + Multiplier
226
+ f = PuMu(punctuation="!", factor=3)
227
+
228
+ # You can also combine existing instances!
229
+ f2 = Punctuator("!") + Multiplier(3)
230
+
231
+ assert f("hello") == f2("hello") == "hello!"
232
+ assert f(10) == f2(10) == 30
233
+
234
+ # You can also meld medleys inplace, but only if all new fields have defaults
235
+ class Total(Medley):
236
+ pass
237
+
238
+ Total.extend(Punctuator, Multiplier)
239
+ f3 = Total(punctuation="!", factor=3)
240
+ ```
241
+
242
+
243
+ # Code generation
244
+
245
+ (Experimental) For advanced use cases, you can generate custom code for type checkers or overloads. [See here](https://ovld.readthedocs.io/en/latest/codegen/).
246
+
247
+
202
248
  # Benchmarks
203
249
 
204
250
  `ovld` is pretty fast: the overhead is comparable to `isinstance` or `match`, and only 2-3x slower when dispatching on `Literal` types. Compared to other multiple dispatch libraries, it has 1.5x to 100x less overhead.
205
251
 
206
252
  Time relative to the fastest implementation (1.00) (lower is better).
207
253
 
208
- | Benchmark | custom | [ovld](https://github.com/breuleux/ovld) | [plum](https://github.com/beartype/plum) | [multim](https://github.com/coady/multimethod) | [multid](https://github.com/mrocklin/multipledispatch/) | [runtype](https://github.com/erezsh/runtype) | [fastcore](https://github.com/fastai/fastcore) | [sd](https://docs.python.org/3/library/functools.html#functools.singledispatch) |
209
- | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
210
- |[trivial](https://github.com/breuleux/ovld/tree/master/benchmarks/test_trivial.py)|1.45|1.00|3.32|4.63|2.04|2.41|51.93|1.91|
211
- |[multer](https://github.com/breuleux/ovld/tree/master/benchmarks/test_multer.py)|1.13|1.00|11.05|4.53|8.31|2.19|46.74|7.32|
212
- |[add](https://github.com/breuleux/ovld/tree/master/benchmarks/test_add.py)|1.08|1.00|3.73|5.21|2.37|2.79|59.31|x|
213
- |[ast](https://github.com/breuleux/ovld/tree/master/benchmarks/test_ast.py)|1.00|1.08|23.14|3.09|1.68|1.91|28.39|1.66|
214
- |[calc](https://github.com/breuleux/ovld/tree/master/benchmarks/test_calc.py)|1.00|1.23|54.61|29.32|x|x|x|x|
215
- |[regexp](https://github.com/breuleux/ovld/tree/master/benchmarks/test_regexp.py)|1.00|1.87|19.18|x|x|x|x|x|
216
- |[fib](https://github.com/breuleux/ovld/tree/master/benchmarks/test_fib.py)|1.00|3.30|444.31|125.77|x|x|x|x|
217
- |[tweaknum](https://github.com/breuleux/ovld/tree/master/benchmarks/test_tweaknum.py)|1.00|2.09|x|x|x|x|x|x|
254
+ | Benchmark | custom | [ovld](https://github.com/breuleux/ovld) | [plum](https://github.com/beartype/plum) | [multim](https://github.com/coady/multimethod) | [multid](https://github.com/mrocklin/multipledispatch) | [runtype](https://github.com/erezsh/runtype) | [sd](https://docs.python.org/3/library/functools.html#functools.singledispatch) |
255
+ | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
256
+ |[trivial](https://github.com/breuleux/ovld/tree/master/benchmarks/test_trivial.py)|1.45|1.00|3.32|4.63|2.04|2.41|1.91|
257
+ |[multer](https://github.com/breuleux/ovld/tree/master/benchmarks/test_multer.py)|1.13|1.00|11.05|4.53|8.31|2.19|7.32|
258
+ |[add](https://github.com/breuleux/ovld/tree/master/benchmarks/test_add.py)|1.08|1.00|3.73|5.21|2.37|2.79|x|
259
+ |[ast](https://github.com/breuleux/ovld/tree/master/benchmarks/test_ast.py)|1.00|1.08|23.14|3.09|1.68|1.91|1.66|
260
+ |[calc](https://github.com/breuleux/ovld/tree/master/benchmarks/test_calc.py)|1.00|1.23|54.61|29.32|x|x|x|
261
+ |[regexp](https://github.com/breuleux/ovld/tree/master/benchmarks/test_regexp.py)|1.00|1.87|19.18|x|x|x|x|
262
+ |[fib](https://github.com/breuleux/ovld/tree/master/benchmarks/test_fib.py)|1.00|3.30|444.31|125.77|x|x|x|
263
+ |[tweaknum](https://github.com/breuleux/ovld/tree/master/benchmarks/test_tweaknum.py)|1.00|2.09|x|x|x|x|x|
@@ -0,0 +1,18 @@
1
+ ovld/__init__.py,sha256=JuCM8Sj65gobV0KYyLr95cSI23Pi6RYZ7X3_F3fdsSw,1821
2
+ ovld/abc.py,sha256=4qpZyYwI8dWgY1Oiv5FhdKg2uzNcyWxIpGmGJVcjXrs,1177
3
+ ovld/codegen.py,sha256=0ZZdXw-nn9t52BX93GX6zwTeBB_wCmc5OxSk37sBrVU,9112
4
+ ovld/core.py,sha256=uAnzuxa3hZjZSbCs3FW_0uR9qQlY-HZhgKpDTyvp59Y,17346
5
+ ovld/dependent.py,sha256=h3j4oQYTQfGqMzggWlLV6TpojX_GtYRFWAO0GcMB0Zs,9085
6
+ ovld/medley.py,sha256=Gin0EYeuQ7qZdDKNFFIwBY4o8W-VT5pl2bP8GCSopU4,12136
7
+ ovld/mro.py,sha256=nqe9jHvsaLu-CfXoP2f7tHg5_8IkcESWMnBmvr4XGIo,4605
8
+ ovld/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ ovld/recode.py,sha256=AoNgJw75RAlfSBeFL5-UeB_T7wN_Xqzuahr9VhqC_yI,16126
10
+ ovld/signatures.py,sha256=Q8JucSOun0ESGx14aWtHtBzLEiM6FxY5HP3imyqXoDo,8984
11
+ ovld/typemap.py,sha256=5Pro1Ee60fH4L7NW7k5nbN5EfDygA0LFHcI6o3mCagI,13596
12
+ ovld/types.py,sha256=0hkhAR5_5793NABdrM-fP1dSJBhYof85FILKqVP2YMg,13392
13
+ ovld/utils.py,sha256=q2zFrK3OifhDu4SsVyLP4WKIp8FDDcJmLwMEUoWHS6c,4227
14
+ ovld/version.py,sha256=-beU6vQRolzltfD0fQR6KSzR5yUgbfwYBlKbvzktqbg,18
15
+ ovld-0.5.0.dist-info/METADATA,sha256=HzSeUKkJrJRUbPJZqw1XZpkW58EKhgl6GOi32CaPPcw,9276
16
+ ovld-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
+ ovld-0.5.0.dist-info/licenses/LICENSE,sha256=cSwNTIzd1cbI89xt3PeZZYJP2y3j8Zus4bXgo4svpX8,1066
18
+ ovld-0.5.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.25.0
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,15 +0,0 @@
1
- ovld/__init__.py,sha256=IVzs4_9skMa_UGZsGT7Ra_dIxj7KKNlV77XxlqcS6ow,1446
2
- ovld/abc.py,sha256=4qpZyYwI8dWgY1Oiv5FhdKg2uzNcyWxIpGmGJVcjXrs,1177
3
- ovld/core.py,sha256=MtRcJNhMwsix2Y7zP1fQS-taCy_t0bqkjHQdLF8WE8E,25719
4
- ovld/dependent.py,sha256=M85EJPRGNnEpmsr3tEX1U-1di1cxQb5-0oQtLgvfRoA,10183
5
- ovld/mro.py,sha256=D9KY3KEFnWL_SXZqHsVKNgRM1E0d8TPPILVZ3SxdUb4,4643
6
- ovld/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- ovld/recode.py,sha256=bwsdM-TPpSQEmJhv8G30yDLrF8_I5wyTXpITMCC1W9k,17961
8
- ovld/typemap.py,sha256=PH5dy8ddVCcqj2TkQbgsM7fmCdHsJT9WGXFPn4JZsCA,13131
9
- ovld/types.py,sha256=lvOl1fldIqCJM-TvvdM2nMvAYDgcA45awfpkUB6kKpo,12984
10
- ovld/utils.py,sha256=k-cVMbJigtdeuD5_JEYtq1a6fXhmUGqLfBu8YxYd5VY,3395
11
- ovld/version.py,sha256=DWNNbWBv-hyqVy76bKbnHWaDUbqL0BOtdkPSV_88dx0,18
12
- ovld-0.4.6.dist-info/METADATA,sha256=mXEwvqopBdpksDEKETVZkp-airCb48yt4AWZIQ2r2wU,7833
13
- ovld-0.4.6.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
14
- ovld-0.4.6.dist-info/licenses/LICENSE,sha256=cSwNTIzd1cbI89xt3PeZZYJP2y3j8Zus4bXgo4svpX8,1066
15
- ovld-0.4.6.dist-info/RECORD,,