ovld 0.5.0__tar.gz → 0.5.1__tar.gz

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.
Files changed (68) hide show
  1. {ovld-0.5.0 → ovld-0.5.1}/PKG-INFO +1 -1
  2. {ovld-0.5.0 → ovld-0.5.1}/pyproject.toml +2 -2
  3. {ovld-0.5.0 → ovld-0.5.1}/src/ovld/codegen.py +5 -2
  4. {ovld-0.5.0 → ovld-0.5.1}/src/ovld/core.py +16 -14
  5. {ovld-0.5.0 → ovld-0.5.1}/src/ovld/medley.py +44 -36
  6. {ovld-0.5.0 → ovld-0.5.1}/src/ovld/recode.py +2 -5
  7. {ovld-0.5.0 → ovld-0.5.1}/src/ovld/utils.py +4 -0
  8. ovld-0.5.1/src/ovld/version.py +1 -0
  9. {ovld-0.5.0 → ovld-0.5.1}/tests/test_codegen.py +14 -0
  10. {ovld-0.5.0 → ovld-0.5.1}/uv.lock +12 -13
  11. ovld-0.5.0/src/ovld/version.py +0 -1
  12. {ovld-0.5.0 → ovld-0.5.1}/.github/workflows/publish.yml +0 -0
  13. {ovld-0.5.0 → ovld-0.5.1}/.github/workflows/python-package.yml +0 -0
  14. {ovld-0.5.0 → ovld-0.5.1}/.gitignore +0 -0
  15. {ovld-0.5.0 → ovld-0.5.1}/.python-version +0 -0
  16. {ovld-0.5.0 → ovld-0.5.1}/.readthedocs.yaml +0 -0
  17. {ovld-0.5.0 → ovld-0.5.1}/LICENSE +0 -0
  18. {ovld-0.5.0 → ovld-0.5.1}/README.md +0 -0
  19. {ovld-0.5.0 → ovld-0.5.1}/benchmarks/__init__.py +0 -0
  20. {ovld-0.5.0 → ovld-0.5.1}/benchmarks/common.py +0 -0
  21. {ovld-0.5.0 → ovld-0.5.1}/benchmarks/test_add.py +0 -0
  22. {ovld-0.5.0 → ovld-0.5.1}/benchmarks/test_ast.py +0 -0
  23. {ovld-0.5.0 → ovld-0.5.1}/benchmarks/test_calc.py +0 -0
  24. {ovld-0.5.0 → ovld-0.5.1}/benchmarks/test_fib.py +0 -0
  25. {ovld-0.5.0 → ovld-0.5.1}/benchmarks/test_multer.py +0 -0
  26. {ovld-0.5.0 → ovld-0.5.1}/benchmarks/test_regexp.py +0 -0
  27. {ovld-0.5.0 → ovld-0.5.1}/benchmarks/test_trivial.py +0 -0
  28. {ovld-0.5.0 → ovld-0.5.1}/benchmarks/test_tweaknum.py +0 -0
  29. {ovld-0.5.0 → ovld-0.5.1}/docs/codegen.md +0 -0
  30. {ovld-0.5.0 → ovld-0.5.1}/docs/compare.md +0 -0
  31. {ovld-0.5.0 → ovld-0.5.1}/docs/dependent.md +0 -0
  32. {ovld-0.5.0 → ovld-0.5.1}/docs/features.md +0 -0
  33. {ovld-0.5.0 → ovld-0.5.1}/docs/index.md +0 -0
  34. {ovld-0.5.0 → ovld-0.5.1}/docs/medley.md +0 -0
  35. {ovld-0.5.0 → ovld-0.5.1}/docs/types.md +0 -0
  36. {ovld-0.5.0 → ovld-0.5.1}/docs/usage.md +0 -0
  37. {ovld-0.5.0 → ovld-0.5.1}/mkdocs.yml +0 -0
  38. {ovld-0.5.0 → ovld-0.5.1}/src/ovld/__init__.py +0 -0
  39. {ovld-0.5.0 → ovld-0.5.1}/src/ovld/abc.py +0 -0
  40. {ovld-0.5.0 → ovld-0.5.1}/src/ovld/dependent.py +0 -0
  41. {ovld-0.5.0 → ovld-0.5.1}/src/ovld/mro.py +0 -0
  42. {ovld-0.5.0 → ovld-0.5.1}/src/ovld/py.typed +0 -0
  43. {ovld-0.5.0 → ovld-0.5.1}/src/ovld/signatures.py +0 -0
  44. {ovld-0.5.0 → ovld-0.5.1}/src/ovld/typemap.py +0 -0
  45. {ovld-0.5.0 → ovld-0.5.1}/src/ovld/types.py +0 -0
  46. {ovld-0.5.0 → ovld-0.5.1}/tests/__init__.py +0 -0
  47. {ovld-0.5.0 → ovld-0.5.1}/tests/modules/gingerbread.py +0 -0
  48. {ovld-0.5.0 → ovld-0.5.1}/tests/test_abc.py +0 -0
  49. {ovld-0.5.0 → ovld-0.5.1}/tests/test_codegen/test_dataclass_gen.txt +0 -0
  50. {ovld-0.5.0 → ovld-0.5.1}/tests/test_codegen/test_method.txt +0 -0
  51. {ovld-0.5.0 → ovld-0.5.1}/tests/test_codegen/test_method_metaclass.txt +0 -0
  52. {ovld-0.5.0 → ovld-0.5.1}/tests/test_codegen/test_method_per_instance.txt +0 -0
  53. {ovld-0.5.0 → ovld-0.5.1}/tests/test_codegen/test_simple.txt +0 -0
  54. {ovld-0.5.0 → ovld-0.5.1}/tests/test_codegen/test_variant_generation.txt +0 -0
  55. {ovld-0.5.0 → ovld-0.5.1}/tests/test_dependent.py +0 -0
  56. {ovld-0.5.0 → ovld-0.5.1}/tests/test_examples.py +0 -0
  57. {ovld-0.5.0 → ovld-0.5.1}/tests/test_global.py +0 -0
  58. {ovld-0.5.0 → ovld-0.5.1}/tests/test_medley.py +0 -0
  59. {ovld-0.5.0 → ovld-0.5.1}/tests/test_mro.py +0 -0
  60. {ovld-0.5.0 → ovld-0.5.1}/tests/test_ovld/test_display.txt +0 -0
  61. {ovld-0.5.0 → ovld-0.5.1}/tests/test_ovld/test_display_more.txt +0 -0
  62. {ovld-0.5.0 → ovld-0.5.1}/tests/test_ovld/test_doc.txt +0 -0
  63. {ovld-0.5.0 → ovld-0.5.1}/tests/test_ovld/test_doc2.txt +0 -0
  64. {ovld-0.5.0 → ovld-0.5.1}/tests/test_ovld/test_method_doc.txt +0 -0
  65. {ovld-0.5.0 → ovld-0.5.1}/tests/test_ovld.py +0 -0
  66. {ovld-0.5.0 → ovld-0.5.1}/tests/test_typemap.py +0 -0
  67. {ovld-0.5.0 → ovld-0.5.1}/tests/test_types.py +0 -0
  68. {ovld-0.5.0 → ovld-0.5.1}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ovld
3
- Version: 0.5.0
3
+ Version: 0.5.1
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/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ovld"
3
- version = "0.5.0"
3
+ version = "0.5.1"
4
4
  description = "Overloading Python functions"
5
5
  authors = [
6
6
  { name = "Olivier Breuleux", email = "breuleux@gmail.com" }
@@ -32,7 +32,7 @@ benchmark = [
32
32
  "multimethod>=1.12",
33
33
  "multipledispatch>=1.0.0",
34
34
  "plum-dispatch>=2.5.2",
35
- "runtype>=0.5.0",
35
+ "runtype>=0.5.1",
36
36
  ]
37
37
 
38
38
  [tool.hatch.build.targets.wheel]
@@ -6,7 +6,7 @@ from ast import _splitlines_no_ff as splitlines
6
6
  from itertools import count
7
7
  from types import FunctionType
8
8
 
9
- from .utils import MISSING, NameDatabase, sigstring
9
+ from .utils import MISSING, NameDatabase, keyword_decorator, sigstring
10
10
 
11
11
  _current = count()
12
12
 
@@ -298,6 +298,9 @@ def codegen_specializer(typemap, fn, tup):
298
298
  return func
299
299
 
300
300
 
301
- def code_generator(fn):
301
+ @keyword_decorator
302
+ def code_generator(fn, priority=0):
302
303
  fn.specializer = codegen_specializer
304
+ if priority:
305
+ fn.priority = priority
303
306
  return fn
@@ -18,6 +18,7 @@ from .signatures import ArgumentAnalyzer, LazySignature, Signature
18
18
  from .typemap import MultiTypeMap
19
19
  from .utils import (
20
20
  MISSING,
21
+ ResolutionError,
21
22
  UsageError,
22
23
  keyword_decorator,
23
24
  sigstring,
@@ -51,6 +52,7 @@ def bootstrap_dispatch(ov, name):
51
52
  dispatch.add_mixins = ov.add_mixins
52
53
  dispatch.unregister = ov.unregister
53
54
  dispatch.next = ov.next
55
+ dispatch.first_entry = first_entry
54
56
  return dispatch
55
57
 
56
58
 
@@ -95,6 +97,7 @@ class Ovld:
95
97
  self._locked = False
96
98
  self.mixins = []
97
99
  self.argument_analysis = ArgumentAnalyzer()
100
+ self.dispatch = bootstrap_dispatch(self, name=self.shortname)
98
101
  self.add_mixins(*mixins)
99
102
 
100
103
  @property
@@ -162,12 +165,12 @@ class Ovld:
162
165
  def _key_error(self, key, possibilities=None):
163
166
  typenames = sigstring(key)
164
167
  if not possibilities:
165
- return TypeError(f"No method in {self} for argument types [{typenames}]")
168
+ return ResolutionError(f"No method in {self} for argument types [{typenames}]")
166
169
  else:
167
170
  hlp = ""
168
171
  for c in possibilities:
169
172
  hlp += f"* {c.handler.__name__} (priority: {c.priority}, specificity: {list(c.specificity)})\n"
170
- return TypeError(
173
+ return ResolutionError(
171
174
  f"Ambiguous resolution in {self} for"
172
175
  f" argument types [{typenames}]\n"
173
176
  f"Candidates are:\n{hlp}"
@@ -176,10 +179,11 @@ class Ovld:
176
179
 
177
180
  def rename(self, name, shortname=None):
178
181
  """Rename this Ovld."""
179
- self.name = name
180
- self.shortname = shortname or name
181
- self.__name__ = self.shortname
182
- self.dispatch = bootstrap_dispatch(self, name=self.shortname)
182
+ if name != self.name:
183
+ self.name = name
184
+ self.shortname = shortname or name
185
+ self.__name__ = self.shortname
186
+ self.dispatch = bootstrap_dispatch(self, name=self.shortname)
183
187
 
184
188
  def __set_name__(self, inst, name):
185
189
  self.rename(name)
@@ -217,8 +221,6 @@ class Ovld:
217
221
 
218
222
  self.analyze_arguments()
219
223
  dispatch = generate_dispatch(self, self.argument_analysis)
220
- if not hasattr(self, "dispatch"):
221
- self.dispatch = bootstrap_dispatch(self, name=self.shortname)
222
224
  self.dispatch.__code__ = rename_code(dispatch.__code__, self.shortname)
223
225
  self.dispatch.__kwdefaults__ = dispatch.__kwdefaults__
224
226
  self.dispatch.__annotations__ = dispatch.__annotations__
@@ -258,6 +260,7 @@ class Ovld:
258
260
  """Register a function."""
259
261
  if fn is None:
260
262
  return partial(self._register, priority=priority)
263
+ priority = getattr(fn, "priority", priority)
261
264
  return self._register(fn, priority)
262
265
 
263
266
  def _register(self, fn, priority):
@@ -290,13 +293,16 @@ class Ovld:
290
293
  self._update()
291
294
 
292
295
  def _update(self):
293
- if self._compiled:
294
- self.compile()
296
+ self.reset()
295
297
  for child in self.children:
296
298
  child._update()
297
299
  if hasattr(self, "dispatch"):
298
300
  self.dispatch.__doc__ = self.mkdoc()
299
301
 
302
+ def reset(self):
303
+ self._compiled = False
304
+ self.dispatch.__code__ = self.dispatch.first_entry.__code__
305
+
300
306
  def copy(self, mixins=[], linkback=False):
301
307
  """Create a copy of this Ovld.
302
308
 
@@ -319,8 +325,6 @@ class Ovld:
319
325
  return ov
320
326
 
321
327
  def __get__(self, obj, cls):
322
- if not self._compiled:
323
- self.compile()
324
328
  return self.dispatch.__get__(obj, cls)
325
329
 
326
330
  def __call__(self, *args, **kwargs): # pragma: no cover
@@ -328,8 +332,6 @@ class Ovld:
328
332
 
329
333
  This should be replaced by an auto-generated function.
330
334
  """
331
- if not self._compiled:
332
- self.compile()
333
335
  return self.dispatch(*args, **kwargs)
334
336
 
335
337
  def next(self, *args):
@@ -110,7 +110,7 @@ class ChainAll(ImplList):
110
110
  class BuildOvld(Combiner):
111
111
  def __init__(self, field=None, ovld=None):
112
112
  super().__init__(field)
113
- self.ovld = ovld or Ovld(linkback=True)
113
+ self.ovld = ovld or Ovld(name=field, linkback=True)
114
114
  self.pending = []
115
115
  if field is not None:
116
116
  self.__set_name__(None, field)
@@ -125,7 +125,7 @@ class BuildOvld(Combiner):
125
125
  self.pending.clear()
126
126
  if not self.ovld.defns:
127
127
  return ABSENT
128
- self.ovld.compile()
128
+ self.ovld.reset()
129
129
  return self.ovld.dispatch
130
130
 
131
131
  def copy(self):
@@ -144,10 +144,14 @@ class BuildOvld(Combiner):
144
144
 
145
145
 
146
146
  class medley_cls_dict(dict):
147
- def __init__(self, bases):
147
+ def __init__(self, bases, default_combiner=None):
148
+ if default_combiner is None:
149
+ (default_combiner,) = {b._ovld_default_combiner for b in bases}
148
150
  super().__init__()
149
151
  self._combiners = {}
152
+ self._default_combiner = default_combiner
150
153
  self.set_direct("_ovld_combiners", self._combiners)
154
+ self.set_direct("_ovld_default_combiner", default_combiner)
151
155
  self._basic = set()
152
156
  for base in bases:
153
157
  for attr, combiner in getattr(base, "_ovld_combiners", {}).items():
@@ -175,7 +179,7 @@ class medley_cls_dict(dict):
175
179
  combiner = self._combiners.get(attr, None)
176
180
  if combiner is None:
177
181
  if inspect.isfunction(value) or isinstance(value, Ovld):
178
- combiner = BuildOvld(attr)
182
+ combiner = self._default_combiner(attr)
179
183
  else:
180
184
  combiner = KeepLast(attr)
181
185
  self._combiners[attr] = combiner
@@ -207,6 +211,19 @@ def specialize(cls, key):
207
211
  return new_t
208
212
 
209
213
 
214
+ def remap_field(dc_field, require_default=False):
215
+ if require_default:
216
+ if dc_field.default is MISSING:
217
+ # NOTE: we do not accept default_factory, because we need the default value to be set
218
+ # in the class so that existing instances of classes[0] can see it.
219
+ raise TypeError(
220
+ f"Dataclass field '{dc_field.name}' must have a default value (not a default_factory) in order to be melded in."
221
+ )
222
+ dc_field = copy(dc_field)
223
+ dc_field.kw_only = True
224
+ return dc_field
225
+
226
+
210
227
  class MedleyMC(type):
211
228
  def __subclasscheck__(cls, subclass):
212
229
  if getattr(cls, "_ovld_medleys", None):
@@ -214,10 +231,10 @@ class MedleyMC(type):
214
231
  return super().__subclasscheck__(subclass)
215
232
 
216
233
  @classmethod
217
- def __prepare__(mcls, name, bases):
218
- return medley_cls_dict(bases)
234
+ def __prepare__(mcls, name, bases, default_combiner=None):
235
+ return medley_cls_dict(bases, default_combiner=default_combiner)
219
236
 
220
- def __new__(mcls, name, bases, namespace):
237
+ def __new__(mcls, name, bases, namespace, default_combiner=None):
221
238
  result = super().__new__(mcls, name, bases, namespace)
222
239
  for attr, combiner in result._ovld_combiners.items():
223
240
  if (value := combiner.get(result)) is not ABSENT:
@@ -236,13 +253,16 @@ class MedleyMC(type):
236
253
  ]
237
254
  return dc
238
255
 
239
- def extend(cls, *others):
240
- if not others:
256
+ def extend(cls, *others, extend_subclasses=True):
257
+ if not others: # pragma: no cover
241
258
  return cls
242
- melded = meld_classes((cls, *others), require_defaults=True)
259
+ all_fields = [(f.name, f.type, f) for f in fields(cls)]
260
+ for other in others:
261
+ all_fields += [(f.name, f.type, remap_field(f, True)) for f in fields(other)]
262
+ melded = make_dataclass("_", fields=all_fields)
243
263
  for other in others:
244
264
  for k, v in vars(other).items():
245
- if k in ["__module__", "__firstlineno__"]:
265
+ if k in ["__module__", "__firstlineno__", "__static_attributes__"]:
246
266
  continue
247
267
  elif comb := cls._ovld_combiners.get(k):
248
268
  comb.juxtapose(v)
@@ -250,9 +270,10 @@ class MedleyMC(type):
250
270
  elif not k.startswith("_ovld_") and not k.startswith("__"):
251
271
  setattr(cls, k, v)
252
272
  cls.__init__ = melded.__init__
253
- for subcls in cls.__subclasses__():
254
- subothers = [o for o in others if not issubclass(subcls, o)]
255
- subcls.extend(*subothers)
273
+ if extend_subclasses:
274
+ for subcls in cls.__subclasses__():
275
+ subothers = [o for o in others if not issubclass(subcls, o)]
276
+ subcls.extend(*subothers, extend_subclasses=False)
256
277
  return cls
257
278
 
258
279
  def __add__(cls, other):
@@ -290,7 +311,7 @@ def use_combiner(combiner):
290
311
  return deco
291
312
 
292
313
 
293
- class Medley(metaclass=MedleyMC):
314
+ class Medley(metaclass=MedleyMC, default_combiner=BuildOvld):
294
315
  __post_init__ = RunAll()
295
316
  __add__ = KeepLast()
296
317
  __sub__ = KeepLast()
@@ -313,13 +334,10 @@ def unmeld_classes(main: type, exclude: type):
313
334
  _meld_classes_cache = {}
314
335
 
315
336
 
316
- def meld_classes(classes, require_defaults=False):
337
+ def meld_classes(classes):
317
338
  medleys = {}
318
- for i, cls in enumerate(classes):
319
- if require_defaults and i == 0:
320
- medleys[cls] = True
321
- else:
322
- medleys.update({x: True for x in getattr(cls, "_ovld_medleys", [cls])})
339
+ for cls in classes:
340
+ medleys.update({x: True for x in getattr(cls, "_ovld_medleys", [cls])})
323
341
  for cls in classes:
324
342
  if not hasattr(cls, "_ovld_medleys"):
325
343
  for base in cls.mro():
@@ -329,36 +347,26 @@ def meld_classes(classes, require_defaults=False):
329
347
  if len(medleys) == 1:
330
348
  return medleys[0]
331
349
 
332
- cache_key = (medleys, require_defaults)
350
+ cache_key = medleys
333
351
  if cache_key in _meld_classes_cache:
334
352
  return _meld_classes_cache[cache_key]
335
353
 
336
- def remap_field(dc_field, require_default):
337
- if require_default:
338
- if dc_field.default is MISSING:
339
- # NOTE: we do not accept default_factory, because we need the default value to be set
340
- # in the class so that existing instances of classes[0] can see it.
341
- raise TypeError(
342
- f"Dataclass field '{dc_field.name}' must have a default value (not a default_factory) in order to be melded in."
343
- )
344
- dc_field = copy(dc_field)
345
- dc_field.kw_only = True
346
- return dc_field
347
-
348
354
  cg_fields = set()
349
355
  dc_fields = []
350
356
 
351
357
  for base in medleys:
352
- rqdef = require_defaults and base is not medleys[0]
353
358
  cg_fields.update(base._ovld_codegen_fields)
354
359
  dc_fields.extend(
355
- (f.name, f.type, remap_field(f, rqdef)) for f in base.__dataclass_fields__.values()
360
+ (f.name, f.type, remap_field(f)) for f in base.__dataclass_fields__.values()
356
361
  )
357
362
 
358
363
  merged = medley_cls_dict(medleys)
359
364
  merged.set_direct("_ovld_codegen_fields", tuple(cg_fields))
360
365
  merged.set_direct("_ovld_medleys", tuple(medleys))
361
366
 
367
+ if "__qualname__" in merged._combiners:
368
+ del merged._combiners["__qualname__"]
369
+
362
370
  result = make_dataclass(
363
371
  cls_name="+".join(sorted(c.__name__ for c in medleys)),
364
372
  bases=tuple(medleys),
@@ -405,11 +405,8 @@ def _search_names(co, specials, glb, closure=None):
405
405
  if isinstance(co, CodeType):
406
406
  if closure is not None:
407
407
  for varname, cell in zip(co.co_freevars, closure):
408
- try:
409
- if any(cell.cell_contents is v for v in values):
410
- yield varname
411
- except ValueError: # cell is empty
412
- pass
408
+ if any(cell.cell_contents is v for v in values):
409
+ yield varname
413
410
  for name in co.co_names:
414
411
  if any(glb.get(name, None) is v for v in values):
415
412
  yield name
@@ -65,6 +65,10 @@ class UsageError(Exception):
65
65
  pass
66
66
 
67
67
 
68
+ class ResolutionError(TypeError):
69
+ pass
70
+
71
+
68
72
  class SpecialForm:
69
73
  def __init__(self, name, message=None):
70
74
  self.__name = name
@@ -0,0 +1 @@
1
+ version = "0.5.1"
@@ -307,3 +307,17 @@ def test_def():
307
307
  assert df.create_body(["x", "y"]).fill() == "return x + 1234"
308
308
  with pytest.raises(ValueError):
309
309
  df.create_expression(["x", "y"])
310
+
311
+
312
+ def test_codegen_priority():
313
+ @ovld
314
+ @code_generator
315
+ def f(x: int):
316
+ return Lambda(..., "'A'")
317
+
318
+ @ovld
319
+ @code_generator(priority=1)
320
+ def f(x: object):
321
+ return Lambda(..., "'B'")
322
+
323
+ assert f(2) == "B"
@@ -1,5 +1,4 @@
1
1
  version = 1
2
- revision = 1
3
2
  requires-python = ">=3.9"
4
3
 
5
4
  [[package]]
@@ -16,7 +15,7 @@ name = "click"
16
15
  version = "8.1.8"
17
16
  source = { registry = "https://pypi.org/simple" }
18
17
  dependencies = [
19
- { name = "colorama", marker = "sys_platform == 'win32'" },
18
+ { name = "colorama", marker = "platform_system == 'Windows'" },
20
19
  ]
21
20
  sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 }
22
21
  wheels = [
@@ -172,14 +171,14 @@ wheels = [
172
171
 
173
172
  [[package]]
174
173
  name = "markdown"
175
- version = "3.7"
174
+ version = "3.8"
176
175
  source = { registry = "https://pypi.org/simple" }
177
176
  dependencies = [
178
177
  { name = "importlib-metadata", marker = "python_full_version < '3.10'" },
179
178
  ]
180
- sdist = { url = "https://files.pythonhosted.org/packages/54/28/3af612670f82f4c056911fbbbb42760255801b3068c48de792d354ff4472/markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2", size = 357086 }
179
+ sdist = { url = "https://files.pythonhosted.org/packages/2f/15/222b423b0b88689c266d9eac4e61396fe2cc53464459d6a37618ac863b24/markdown-3.8.tar.gz", hash = "sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f", size = 360906 }
181
180
  wheels = [
182
- { url = "https://files.pythonhosted.org/packages/3f/08/83871f3c50fc983b88547c196d11cf8c3340e37c32d2e9d6152abe2c61f7/Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803", size = 106349 },
181
+ { url = "https://files.pythonhosted.org/packages/51/3f/afe76f8e2246ffbc867440cbcf90525264df0e658f8a5ca1f872b3f6192a/markdown-3.8-py3-none-any.whl", hash = "sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc", size = 106210 },
183
182
  ]
184
183
 
185
184
  [[package]]
@@ -286,7 +285,7 @@ version = "1.6.1"
286
285
  source = { registry = "https://pypi.org/simple" }
287
286
  dependencies = [
288
287
  { name = "click" },
289
- { name = "colorama", marker = "sys_platform == 'win32'" },
288
+ { name = "colorama", marker = "platform_system == 'Windows'" },
290
289
  { name = "ghp-import" },
291
290
  { name = "importlib-metadata", marker = "python_full_version < '3.10'" },
292
291
  { name = "jinja2" },
@@ -340,7 +339,7 @@ wheels = [
340
339
 
341
340
  [[package]]
342
341
  name = "ovld"
343
- version = "0.4.6"
342
+ version = "0.5.0"
344
343
  source = { editable = "." }
345
344
 
346
345
  [package.dev-dependencies]
@@ -477,15 +476,15 @@ wheels = [
477
476
 
478
477
  [[package]]
479
478
  name = "pytest-cov"
480
- version = "6.1.0"
479
+ version = "6.1.1"
481
480
  source = { registry = "https://pypi.org/simple" }
482
481
  dependencies = [
483
482
  { name = "coverage", extra = ["toml"] },
484
483
  { name = "pytest" },
485
484
  ]
486
- sdist = { url = "https://files.pythonhosted.org/packages/34/8c/039a7793f23f5cb666c834da9e944123f498ccc0753bed5fbfb2e2c11f87/pytest_cov-6.1.0.tar.gz", hash = "sha256:ec55e828c66755e5b74a21bd7cc03c303a9f928389c0563e50ba454a6dbe71db", size = 66651 }
485
+ sdist = { url = "https://files.pythonhosted.org/packages/25/69/5f1e57f6c5a39f81411b550027bf72842c4567ff5fd572bed1edc9e4b5d9/pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a", size = 66857 }
487
486
  wheels = [
488
- { url = "https://files.pythonhosted.org/packages/e1/c5/8d6ffe9fc8f7f57b3662156ae8a34f2b8e7a754c73b48e689ce43145e98c/pytest_cov-6.1.0-py3-none-any.whl", hash = "sha256:cd7e1d54981d5185ef2b8d64b50172ce97e6f357e6df5cb103e828c7f993e201", size = 23743 },
487
+ { url = "https://files.pythonhosted.org/packages/28/d0/def53b4a790cfb21483016430ed828f64830dd981ebe1089971cd10cab25/pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde", size = 23841 },
489
488
  ]
490
489
 
491
490
  [[package]]
@@ -664,11 +663,11 @@ wheels = [
664
663
 
665
664
  [[package]]
666
665
  name = "typing-extensions"
667
- version = "4.13.0"
666
+ version = "4.13.2"
668
667
  source = { registry = "https://pypi.org/simple" }
669
- sdist = { url = "https://files.pythonhosted.org/packages/0e/3e/b00a62db91a83fff600de219b6ea9908e6918664899a2d85db222f4fbf19/typing_extensions-4.13.0.tar.gz", hash = "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b", size = 106520 }
668
+ sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967 }
670
669
  wheels = [
671
- { url = "https://files.pythonhosted.org/packages/e0/86/39b65d676ec5732de17b7e3c476e45bb80ec64eb50737a8dce1a4178aba1/typing_extensions-4.13.0-py3-none-any.whl", hash = "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5", size = 45683 },
670
+ { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806 },
672
671
  ]
673
672
 
674
673
  [[package]]
@@ -1 +0,0 @@
1
- version = "0.5.0"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes