param 2.1.1rc2__tar.gz → 2.2.0a1__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 (71) hide show
  1. {param-2.1.1rc2 → param-2.2.0a1}/.gitignore +5 -1
  2. {param-2.1.1rc2 → param-2.2.0a1}/PKG-INFO +3 -18
  3. {param-2.1.1rc2 → param-2.2.0a1}/numbergen/__init__.py +9 -17
  4. {param-2.1.1rc2 → param-2.2.0a1}/param/_utils.py +66 -44
  5. {param-2.1.1rc2 → param-2.2.0a1}/param/_version.py +2 -2
  6. {param-2.1.1rc2 → param-2.2.0a1}/param/depends.py +35 -3
  7. {param-2.1.1rc2 → param-2.2.0a1}/param/ipython.py +4 -9
  8. {param-2.1.1rc2 → param-2.2.0a1}/param/parameterized.py +337 -178
  9. {param-2.1.1rc2 → param-2.2.0a1}/param/parameters.py +65 -80
  10. {param-2.1.1rc2 → param-2.2.0a1}/param/reactive.py +102 -60
  11. {param-2.1.1rc2 → param-2.2.0a1}/param/serializer.py +13 -19
  12. {param-2.1.1rc2 → param-2.2.0a1}/param/version.py +26 -26
  13. param-2.2.0a1/pyproject.toml +146 -0
  14. {param-2.1.1rc2 → param-2.2.0a1}/tests/testbooleanparam.py +1 -3
  15. {param-2.1.1rc2 → param-2.2.0a1}/tests/testbytesparam.py +1 -3
  16. {param-2.1.1rc2 → param-2.2.0a1}/tests/testcalendardateparam.py +1 -3
  17. {param-2.1.1rc2 → param-2.2.0a1}/tests/testcalendardaterangeparam.py +1 -3
  18. {param-2.1.1rc2 → param-2.2.0a1}/tests/testclassselector.py +2 -4
  19. {param-2.1.1rc2 → param-2.2.0a1}/tests/testcolorparameter.py +1 -3
  20. {param-2.1.1rc2 → param-2.2.0a1}/tests/testcomparator.py +2 -2
  21. {param-2.1.1rc2 → param-2.2.0a1}/tests/testcompositeparams.py +4 -3
  22. {param-2.1.1rc2 → param-2.2.0a1}/tests/testcustomparam.py +1 -3
  23. {param-2.1.1rc2 → param-2.2.0a1}/tests/testdateparam.py +2 -4
  24. {param-2.1.1rc2 → param-2.2.0a1}/tests/testdaterangeparam.py +2 -4
  25. {param-2.1.1rc2 → param-2.2.0a1}/tests/testdefaults.py +5 -7
  26. param-2.2.0a1/tests/testdeprecations.py +205 -0
  27. {param-2.1.1rc2 → param-2.2.0a1}/tests/testdynamicparams.py +13 -11
  28. {param-2.1.1rc2 → param-2.2.0a1}/tests/testfiledeserialization.py +10 -12
  29. param-2.2.0a1/tests/testimports.py +20 -0
  30. {param-2.1.1rc2 → param-2.2.0a1}/tests/testipythonmagic.py +2 -4
  31. {param-2.1.1rc2 → param-2.2.0a1}/tests/testjsonserialization.py +5 -9
  32. {param-2.1.1rc2 → param-2.2.0a1}/tests/testlist.py +2 -2
  33. {param-2.1.1rc2 → param-2.2.0a1}/tests/testnumbergen.py +1 -3
  34. {param-2.1.1rc2 → param-2.2.0a1}/tests/testnumberparameter.py +2 -4
  35. {param-2.1.1rc2 → param-2.2.0a1}/tests/testnumpy.py +3 -5
  36. {param-2.1.1rc2 → param-2.2.0a1}/tests/testpandas.py +2 -4
  37. {param-2.1.1rc2 → param-2.2.0a1}/tests/testparamdepends.py +1 -3
  38. {param-2.1.1rc2 → param-2.2.0a1}/tests/testparameterizedobject.py +135 -13
  39. {param-2.1.1rc2 → param-2.2.0a1}/tests/testparameterizedrepr.py +1 -3
  40. {param-2.1.1rc2 → param-2.2.0a1}/tests/testparamoutput.py +1 -3
  41. {param-2.1.1rc2 → param-2.2.0a1}/tests/testparamunion.py +1 -3
  42. {param-2.1.1rc2 → param-2.2.0a1}/tests/testpickle.py +3 -3
  43. {param-2.1.1rc2 → param-2.2.0a1}/tests/testrangeparameter.py +1 -3
  44. {param-2.1.1rc2 → param-2.2.0a1}/tests/testreactive.py +13 -7
  45. {param-2.1.1rc2 → param-2.2.0a1}/tests/testsignatures.py +3 -3
  46. {param-2.1.1rc2 → param-2.2.0a1}/tests/teststringparam.py +1 -3
  47. {param-2.1.1rc2 → param-2.2.0a1}/tests/testtimedependent.py +3 -2
  48. {param-2.1.1rc2 → param-2.2.0a1}/tests/testtupleparam.py +1 -1
  49. {param-2.1.1rc2 → param-2.2.0a1}/tests/testutils.py +22 -4
  50. {param-2.1.1rc2 → param-2.2.0a1}/tests/testwatch.py +40 -35
  51. {param-2.1.1rc2 → param-2.2.0a1}/tests/utils.py +5 -3
  52. param-2.1.1rc2/pyproject.toml +0 -228
  53. param-2.1.1rc2/tests/testdeprecations.py +0 -365
  54. {param-2.1.1rc2 → param-2.2.0a1}/LICENSE.txt +0 -0
  55. {param-2.1.1rc2 → param-2.2.0a1}/README.md +0 -0
  56. {param-2.1.1rc2 → param-2.2.0a1}/param/__init__.py +0 -0
  57. {param-2.1.1rc2 → param-2.2.0a1}/param/display.py +0 -0
  58. {param-2.1.1rc2 → param-2.2.0a1}/tests/__init__.py +0 -0
  59. {param-2.1.1rc2 → param-2.2.0a1}/tests/conftest.py +0 -0
  60. {param-2.1.1rc2 → param-2.2.0a1}/tests/testaddparameter.py +0 -0
  61. {param-2.1.1rc2 → param-2.2.0a1}/tests/testbind.py +0 -0
  62. {param-2.1.1rc2 → param-2.2.0a1}/tests/testcallable.py +0 -0
  63. {param-2.1.1rc2 → param-2.2.0a1}/tests/testfileselector.py +0 -0
  64. {param-2.1.1rc2 → param-2.2.0a1}/tests/testlistselector.py +0 -0
  65. {param-2.1.1rc2 → param-2.2.0a1}/tests/testmultifileselector.py +0 -0
  66. {param-2.1.1rc2 → param-2.2.0a1}/tests/testobjectselector.py +0 -0
  67. {param-2.1.1rc2 → param-2.2.0a1}/tests/testpathparam.py +0 -0
  68. {param-2.1.1rc2 → param-2.2.0a1}/tests/testrefs.py +0 -0
  69. {param-2.1.1rc2 → param-2.2.0a1}/tests/testreprhtml.py +0 -0
  70. {param-2.1.1rc2 → param-2.2.0a1}/tests/testselector.py +0 -0
  71. {param-2.1.1rc2 → param-2.2.0a1}/tests/testversion.py +0 -0
@@ -19,7 +19,7 @@ builtdocs/
19
19
  jupyter_execute/
20
20
  doc/Reference_Manual/
21
21
  doc/user_guide/data.pickle
22
- doc/user_guide/output.csv
22
+ doc/user_guide/output.*
23
23
  doc/reference/generated
24
24
 
25
25
  # Unit test / Coverage report
@@ -32,3 +32,7 @@ param/_version.py
32
32
  # asv benchmark
33
33
  benchmarks/.asv
34
34
  benchmarks/param
35
+
36
+ # pixi
37
+ .pixi
38
+ pixi.lock
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: param
3
- Version: 2.1.1rc2
3
+ Version: 2.2.0a1
4
4
  Summary: Make your Python code clearer and more reliable by declaring Parameters.
5
5
  Project-URL: Homepage, https://param.holoviz.org/
6
6
  Project-URL: Tracker, https://github.com/holoviz/param/issues
@@ -23,18 +23,16 @@ Classifier: Programming Language :: Python :: 3.9
23
23
  Classifier: Programming Language :: Python :: 3.10
24
24
  Classifier: Programming Language :: Python :: 3.11
25
25
  Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Programming Language :: Python :: 3.13
26
27
  Classifier: Topic :: Scientific/Engineering
27
28
  Classifier: Topic :: Software Development :: Libraries
28
29
  Requires-Python: >=3.8
29
30
  Provides-Extra: all
30
31
  Requires-Dist: aiohttp; extra == 'all'
31
32
  Requires-Dist: cloudpickle; extra == 'all'
32
- Requires-Dist: coverage[toml]; extra == 'all'
33
- Requires-Dist: flake8; extra == 'all'
34
33
  Requires-Dist: gmpy; extra == 'all'
35
34
  Requires-Dist: ipython; extra == 'all'
36
35
  Requires-Dist: jsonschema; extra == 'all'
37
- Requires-Dist: nbsite==0.8.4; extra == 'all'
38
36
  Requires-Dist: nbval; extra == 'all'
39
37
  Requires-Dist: nest-asyncio; extra == 'all'
40
38
  Requires-Dist: numpy; extra == 'all'
@@ -42,29 +40,17 @@ Requires-Dist: odfpy; extra == 'all'
42
40
  Requires-Dist: openpyxl; extra == 'all'
43
41
  Requires-Dist: pandas; extra == 'all'
44
42
  Requires-Dist: panel; extra == 'all'
45
- Requires-Dist: pre-commit; extra == 'all'
46
43
  Requires-Dist: pyarrow; extra == 'all'
47
44
  Requires-Dist: pytest; extra == 'all'
48
45
  Requires-Dist: pytest-asyncio; extra == 'all'
49
46
  Requires-Dist: pytest-xdist; extra == 'all'
50
- Requires-Dist: sphinx-remove-toctrees; extra == 'all'
51
47
  Requires-Dist: tables; extra == 'all'
52
48
  Requires-Dist: xlrd; extra == 'all'
53
- Provides-Extra: doc
54
- Requires-Dist: aiohttp; extra == 'doc'
55
- Requires-Dist: nbsite==0.8.4; extra == 'doc'
56
- Requires-Dist: pandas; extra == 'doc'
57
- Requires-Dist: panel; extra == 'doc'
58
- Requires-Dist: sphinx-remove-toctrees; extra == 'doc'
59
49
  Provides-Extra: examples
60
50
  Requires-Dist: aiohttp; extra == 'examples'
61
51
  Requires-Dist: pandas; extra == 'examples'
62
52
  Requires-Dist: panel; extra == 'examples'
63
- Provides-Extra: lint
64
- Requires-Dist: flake8; extra == 'lint'
65
- Requires-Dist: pre-commit; extra == 'lint'
66
53
  Provides-Extra: tests
67
- Requires-Dist: coverage[toml]; extra == 'tests'
68
54
  Requires-Dist: pytest; extra == 'tests'
69
55
  Requires-Dist: pytest-asyncio; extra == 'tests'
70
56
  Provides-Extra: tests-deser
@@ -84,7 +70,6 @@ Requires-Dist: pytest-xdist; extra == 'tests-examples'
84
70
  Provides-Extra: tests-full
85
71
  Requires-Dist: aiohttp; extra == 'tests-full'
86
72
  Requires-Dist: cloudpickle; extra == 'tests-full'
87
- Requires-Dist: coverage[toml]; extra == 'tests-full'
88
73
  Requires-Dist: gmpy; extra == 'tests-full'
89
74
  Requires-Dist: ipython; extra == 'tests-full'
90
75
  Requires-Dist: jsonschema; extra == 'tests-full'
@@ -1,6 +1,4 @@
1
- """
2
- Callable objects that generate numbers according to different distributions.
3
- """
1
+ """Callable objects that generate numbers according to different distributions."""
4
2
 
5
3
  import random
6
4
  import operator
@@ -14,7 +12,7 @@ from math import e,pi
14
12
  import param
15
13
 
16
14
 
17
- from param import __version__ # noqa: API import
15
+ from param import __version__
18
16
 
19
17
  class TimeAware(param.Parameterized):
20
18
  """
@@ -135,7 +133,7 @@ operator_symbols = {
135
133
  }
136
134
 
137
135
  def pprint(x, *args, **kwargs):
138
- "Pretty-print the provided item, translating operators to their symbols"
136
+ """Pretty-print the provided item, translating operators to their symbols"""
139
137
  return x.pprint(*args, **kwargs) if hasattr(x,'pprint') else operator_symbols.get(x, repr(x))
140
138
 
141
139
 
@@ -214,6 +212,7 @@ class Hash:
214
212
  for __call__ must be specified in the constructor and must stay
215
213
  constant across calls.
216
214
  """
215
+
217
216
  def __init__(self, name, input_count):
218
217
  self.name = name
219
218
  self.input_count = input_count
@@ -224,7 +223,6 @@ class Hash:
224
223
 
225
224
  def _rational(self, val):
226
225
  """Convert the given value to a rational, if necessary."""
227
-
228
226
  I32 = 4294967296 # Maximum 32 bit unsigned int (i.e. 'I') value
229
227
  if isinstance(val, int):
230
228
  numer, denom = val, 1
@@ -241,9 +239,7 @@ class Hash:
241
239
 
242
240
 
243
241
  def __getstate__(self):
244
- """
245
- Avoid Hashlib.md5 TypeError in deepcopy (hashlib issue)
246
- """
242
+ """Avoid Hashlib.md5 TypeError in deepcopy (hashlib issue)"""
247
243
  d = self.__dict__.copy()
248
244
  d.pop('_digest')
249
245
  d.pop('_hash_struct')
@@ -374,9 +370,7 @@ class TimeAwareRandomState(TimeAware):
374
370
 
375
371
 
376
372
  def _verify_constrained_hash(self):
377
- """
378
- Warn if the object name is not explicitly set.
379
- """
373
+ """Warn if the object name is not explicitly set."""
380
374
  changed_params = self.param.values(onlychanged=True)
381
375
  if self.time_dependent and ('name' not in changed_params):
382
376
  self.param.log(param.WARNING, "Default object name used to set the seed: "
@@ -575,9 +569,7 @@ class VonMisesRandom(RandomDistribution):
575
569
 
576
570
 
577
571
  class ScaledTime(NumberGenerator, TimeDependent):
578
- """
579
- The current time multiplied by some conversion factor.
580
- """
572
+ """The current time multiplied by some conversion factor."""
581
573
 
582
574
  factor = param.Number(default=1.0, doc="""
583
575
  The factor to be multiplied by the current time value.""")
@@ -763,5 +755,5 @@ class BoundedNumber(NumberGenerator):
763
755
  else: return val
764
756
 
765
757
 
766
- _public = list({_k for _k,_v in locals().items() if isinstance(_v,type) and issubclass(_v,NumberGenerator)})
767
- __all__ = _public
758
+ _public = {_k for _k,_v in locals().items() if isinstance(_v,type) and issubclass(_v,NumberGenerator)}
759
+ __all__ = ["__version__", *_public]
@@ -1,22 +1,30 @@
1
+ from __future__ import annotations
2
+
1
3
  import asyncio
2
4
  import collections
3
5
  import contextvars
4
6
  import datetime as dt
5
- import inspect
6
7
  import functools
8
+ import inspect
7
9
  import numbers
8
10
  import os
9
11
  import re
10
12
  import sys
11
13
  import traceback
12
14
  import warnings
13
-
14
- from collections import defaultdict, OrderedDict
15
+ from collections import OrderedDict, abc, defaultdict
15
16
  from contextlib import contextmanager
16
17
  from numbers import Real
17
18
  from textwrap import dedent
18
19
  from threading import get_ident
19
- from collections import abc
20
+ from typing import TYPE_CHECKING, Callable, TypeVar
21
+
22
+ if TYPE_CHECKING:
23
+ from typing_extensions import Concatenate, ParamSpec
24
+
25
+ P = ParamSpec("P")
26
+ R = TypeVar("R")
27
+ CallableT = TypeVar("CallableT", bound=Callable)
20
28
 
21
29
  DEFAULT_SIGNATURE = inspect.Signature([
22
30
  inspect.Parameter('self', inspect.Parameter.POSITIONAL_OR_KEYWORD),
@@ -29,7 +37,8 @@ class ParamWarning(Warning):
29
37
  """Base Param Warning"""
30
38
 
31
39
  class ParamPendingDeprecationWarning(ParamWarning, PendingDeprecationWarning):
32
- """Param PendingDeprecationWarning
40
+ """
41
+ Param PendingDeprecationWarning
33
42
 
34
43
  This warning type is useful when the warning is not meant to be displayed
35
44
  to REPL/notebooks users, as DeprecationWarning are displayed when triggered
@@ -38,22 +47,22 @@ class ParamPendingDeprecationWarning(ParamWarning, PendingDeprecationWarning):
38
47
 
39
48
 
40
49
  class ParamDeprecationWarning(ParamWarning, DeprecationWarning):
41
- """Param DeprecationWarning
50
+ """
51
+ Param DeprecationWarning
42
52
 
43
53
  Ignored by default except when triggered by code in __main__
44
54
  """
45
55
 
46
56
 
47
57
  class ParamFutureWarning(ParamWarning, FutureWarning):
48
- """Param FutureWarning
58
+ """
59
+ Param FutureWarning
49
60
 
50
61
  Always displayed.
51
62
  """
52
63
 
53
64
  class Skip(Exception):
54
- """
55
- Exception that allows skipping an update when resolving a reference.
56
- """
65
+ """Exception that allows skipping an update when resolving a reference."""
57
66
 
58
67
  def _deprecated(extra_msg="", warning_cat=ParamDeprecationWarning):
59
68
  def decorator(func):
@@ -72,7 +81,8 @@ def _deprecated(extra_msg="", warning_cat=ParamDeprecationWarning):
72
81
 
73
82
 
74
83
  def _deprecate_positional_args(func):
75
- """Internal decorator for methods that issues warnings for positional arguments
84
+ """
85
+ Internal decorator for methods that issues warnings for positional arguments
76
86
  Using the keyword-only argument syntax in pep 3102, arguments after the
77
87
  ``*`` will issue a warning when passed as a positional argument.
78
88
  Adapted from scikit-learn
@@ -98,7 +108,7 @@ def _deprecate_positional_args(func):
98
108
  f"Passing '{extra_args}' as positional argument(s) to 'param.{name}' "
99
109
  "has been deprecated since Param 2.0.0 and will raise an error in a future version, "
100
110
  "please pass them as keyword arguments.",
101
- ParamDeprecationWarning,
111
+ ParamFutureWarning,
102
112
  stacklevel=2,
103
113
  )
104
114
 
@@ -114,7 +124,7 @@ def _deprecate_positional_args(func):
114
124
 
115
125
  # Copy of Python 3.2 reprlib's recursive_repr but allowing extra arguments
116
126
  def _recursive_repr(fillvalue='...'):
117
- 'Decorator to make a repr function return fillvalue for a recursive call'
127
+ """Decorator to make a repr function return fillvalue for a recursive call"""
118
128
 
119
129
  def decorating_function(user_function):
120
130
  repr_running = set()
@@ -192,22 +202,11 @@ def _validate_error_prefix(parameter, attribute=None):
192
202
 
193
203
  def _is_mutable_container(value):
194
204
  """True for mutable containers, which typically need special handling when being copied"""
195
- return issubclass(type(value), MUTABLE_TYPES)
196
-
197
-
198
- def _dict_update(dictionary, **kwargs):
199
- """
200
- Small utility to update a copy of a dict with the provided keyword args.
201
- """
202
- d = dictionary.copy()
203
- d.update(kwargs)
204
- return d
205
+ return isinstance(value, MUTABLE_TYPES)
205
206
 
206
207
 
207
208
  def full_groupby(l, key=lambda x: x):
208
- """
209
- Groupby implementation which does not require a prior sort
210
- """
209
+ """Groupby implementation which does not require a prior sort"""
211
210
  d = defaultdict(list)
212
211
  for item in l:
213
212
  d[key(item)].append(item)
@@ -215,9 +214,7 @@ def full_groupby(l, key=lambda x: x):
215
214
 
216
215
 
217
216
  def iscoroutinefunction(function):
218
- """
219
- Whether the function is an asynchronous generator or a coroutine.
220
- """
217
+ """Whether the function is an asynchronous generator or a coroutine."""
221
218
  # Partial unwrapping not required starting from Python 3.11.0
222
219
  # See https://github.com/holoviz/param/pull/894#issuecomment-1867084447
223
220
  while isinstance(function, functools.partial):
@@ -228,9 +225,7 @@ def iscoroutinefunction(function):
228
225
  )
229
226
 
230
227
  async def _to_thread(func, /, *args, **kwargs):
231
- """
232
- Polyfill for asyncio.to_thread in Python < 3.9
233
- """
228
+ """Polyfill for asyncio.to_thread in Python < 3.9"""
234
229
  loop = asyncio.get_running_loop()
235
230
  ctx = contextvars.copy_context()
236
231
  func_call = functools.partial(ctx.run, func, *args, **kwargs)
@@ -274,6 +269,7 @@ def flatten(line):
274
269
  Returns
275
270
  -------
276
271
  flattened : generator
272
+
277
273
  """
278
274
  for element in line:
279
275
  if any(isinstance(element, tp) for tp in (list, tuple, dict)):
@@ -282,12 +278,12 @@ def flatten(line):
282
278
  yield element
283
279
 
284
280
 
285
- def accept_arguments(f):
286
- """
287
- Decorator for decorators that accept arguments
288
- """
281
+ def accept_arguments(
282
+ f: Callable[Concatenate[CallableT, P], R]
283
+ ) -> Callable[P, Callable[[CallableT], R]]:
284
+ """Decorator for decorators that accept arguments"""
289
285
  @functools.wraps(f)
290
- def _f(*args, **kwargs):
286
+ def _f(*args: P.args, **kwargs: P.kwargs) -> Callable[[CallableT], R]:
291
287
  return lambda actual_f: f(actual_f, *args, **kwargs)
292
288
  return _f
293
289
 
@@ -305,7 +301,7 @@ def _produce_value(value_obj):
305
301
 
306
302
 
307
303
  # PARAM3_DEPRECATION
308
- @_deprecated()
304
+ @_deprecated(warning_cat=ParamFutureWarning)
309
305
  def produce_value(value_obj):
310
306
  """
311
307
  A helper function that produces an actual parameter from a stored
@@ -318,7 +314,7 @@ def produce_value(value_obj):
318
314
 
319
315
 
320
316
  # PARAM3_DEPRECATION
321
- @_deprecated()
317
+ @_deprecated(warning_cat=ParamFutureWarning)
322
318
  def as_unicode(obj):
323
319
  """
324
320
  Safely casts any object to unicode including regular string
@@ -330,7 +326,7 @@ def as_unicode(obj):
330
326
 
331
327
 
332
328
  # PARAM3_DEPRECATION
333
- @_deprecated()
329
+ @_deprecated(warning_cat=ParamFutureWarning)
334
330
  def is_ordered_dict(d):
335
331
  """
336
332
  Predicate checking for ordered dictionaries. OrderedDict is always
@@ -361,7 +357,7 @@ def _hashable(x):
361
357
 
362
358
 
363
359
  # PARAM3_DEPRECATION
364
- @_deprecated()
360
+ @_deprecated(warning_cat=ParamFutureWarning)
365
361
  def hashable(x):
366
362
  """
367
363
  Return a hashable version of the given object x, with lists and
@@ -410,7 +406,7 @@ def _named_objs(objlist, namesdict=None):
410
406
 
411
407
 
412
408
  # PARAM3_DEPRECATION
413
- @_deprecated()
409
+ @_deprecated(warning_cat=ParamFutureWarning)
414
410
  def named_objs(objlist, namesdict=None):
415
411
  """
416
412
  Given a list of objects, returns a dictionary mapping from
@@ -548,7 +544,7 @@ def _abbreviate_paths(pathspec,named_paths):
548
544
 
549
545
 
550
546
  # PARAM3_DEPRECATION
551
- @_deprecated()
547
+ @_deprecated(warning_cat=ParamFutureWarning)
552
548
  def abbreviate_paths(pathspec,named_paths):
553
549
  """
554
550
  Given a dict of (pathname,path) pairs, removes any prefix shared by all pathnames.
@@ -571,7 +567,8 @@ def _to_datetime(x):
571
567
 
572
568
  @contextmanager
573
569
  def exceptions_summarized():
574
- """Useful utility for writing docs that need to show expected errors.
570
+ """
571
+ Useful utility for writing docs that need to show expected errors.
575
572
  Shows exception only, concisely, without a traceback.
576
573
  """
577
574
  try:
@@ -602,3 +599,28 @@ def async_executor(func):
602
599
  task.add_done_callback(_running_tasks.discard)
603
600
  else:
604
601
  event_loop.run_until_complete(func())
602
+
603
+ class _GeneratorIsMeta(type):
604
+ def __instancecheck__(cls, inst):
605
+ return isinstance(inst, tuple(cls.types()))
606
+
607
+ def __subclasscheck__(cls, sub):
608
+ return issubclass(sub, tuple(cls.types()))
609
+
610
+ def __iter__(cls):
611
+ yield from cls.types()
612
+
613
+ class _GeneratorIs(metaclass=_GeneratorIsMeta):
614
+ @classmethod
615
+ def __iter__(cls):
616
+ yield from cls.types()
617
+
618
+ def gen_types(gen_func):
619
+ """
620
+ Decorator which takes a generator function which yields difference types
621
+ make it so it can be called with isinstance and issubclass.
622
+ """
623
+ if not inspect.isgeneratorfunction(gen_func):
624
+ msg = "gen_types decorator can only be applied to generator"
625
+ raise TypeError(msg)
626
+ return type(gen_func.__name__, (_GeneratorIs,), {"types": staticmethod(gen_func)})
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '2.1.1rc2'
16
- __version_tuple__ = version_tuple = (2, 1, 1)
15
+ __version__ = version = '2.2.0a1'
16
+ __version_tuple__ = version_tuple = (2, 2, 0)
@@ -1,17 +1,48 @@
1
+ from __future__ import annotations
2
+
1
3
  import inspect
2
4
 
3
5
  from collections import defaultdict
4
6
  from functools import wraps
7
+ from typing import TYPE_CHECKING, TypeVar, Callable, Protocol, TypedDict, overload
5
8
 
6
9
  from .parameterized import (
7
10
  Parameter, Parameterized, ParameterizedMetaclass, transform_reference,
8
11
  )
9
12
  from ._utils import accept_arguments, iscoroutinefunction
10
13
 
14
+ if TYPE_CHECKING:
15
+ CallableT = TypeVar("CallableT", bound=Callable)
16
+ Dependency = Parameter | str
17
+
18
+ class DependencyInfo(TypedDict):
19
+ dependencies: tuple[Dependency, ...]
20
+ kw: dict[str, Dependency]
21
+ watch: bool
22
+ on_init: bool
23
+
24
+ class DependsFunc(Protocol[CallableT]):
25
+ _dinfo: DependencyInfo
26
+ __call__: CallableT
27
+
28
+ @overload
29
+ def depends(
30
+ *dependencies: str, watch: bool = ..., on_init: bool = ...
31
+ ) -> Callable[[CallableT], DependsFunc[CallableT]]:
32
+ ...
33
+
34
+ @overload
35
+ def depends(
36
+ *dependencies: Parameter, watch: bool = ..., on_init: bool = ..., **kw: Parameter
37
+ ) -> Callable[[CallableT], DependsFunc[CallableT]]:
38
+ ...
11
39
 
12
40
  @accept_arguments
13
- def depends(func, *dependencies, watch=False, on_init=False, **kw):
14
- """Annotates a function or Parameterized method to express its dependencies.
41
+ def depends(
42
+ func: CallableT, /, *dependencies: Dependency, watch: bool = False, on_init: bool = False, **kw: Parameter
43
+ ) -> Callable[[CallableT], DependsFunc[CallableT]]:
44
+ """
45
+ Annotates a function or Parameterized method to express its dependencies.
15
46
 
16
47
  The specified dependencies can be either be Parameter instances or if a
17
48
  method is supplied they can be defined as strings referring to Parameters
@@ -27,6 +58,7 @@ def depends(func, *dependencies, watch=False, on_init=False, **kw):
27
58
  on_init : bool, optional
28
59
  Whether to invoke the function/method when the instance is created,
29
60
  by default False
61
+
30
62
  """
31
63
  dependencies, kw = (
32
64
  tuple(transform_reference(arg) for arg in dependencies),
@@ -117,6 +149,6 @@ def depends(func, *dependencies, watch=False, on_init=False, **kw):
117
149
  _dinfo.update({'dependencies': dependencies,
118
150
  'kw': kw, 'watch': watch, 'on_init': on_init})
119
151
 
120
- _depends._dinfo = _dinfo
152
+ _depends._dinfo = _dinfo # type: ignore[attr-defined]
121
153
 
122
154
  return _depends
@@ -61,7 +61,6 @@ class ParamPager:
61
61
  and the dictionary of parameter values. If include_super is
62
62
  True, parameters are also collected from the super classes.
63
63
  """
64
-
65
64
  params = dict(obj.param.objects('existing'))
66
65
  if isinstance(obj,type):
67
66
  changed = []
@@ -86,12 +85,11 @@ class ParamPager:
86
85
  docstrings in a clean format (alternating red and blue for
87
86
  readability).
88
87
  """
89
-
90
88
  (params, val_dict, changed) = info
91
89
  contents = []
92
90
  displayed_params = []
93
91
  for name in self.sort_by_precedence(params):
94
- if only_changed and not (name in changed):
92
+ if only_changed and name not in changed:
95
93
  continue
96
94
  displayed_params.append((name, params[name]))
97
95
 
@@ -147,7 +145,6 @@ class ParamPager:
147
145
  Collect the information about parameters needed to build a
148
146
  properly formatted table and then tabulate it.
149
147
  """
150
-
151
148
  info_list, bounds_dict = [], {}
152
149
  (params, val_dict, changed) = info
153
150
  col_widths = {k:0 for k in order}
@@ -155,7 +152,7 @@ class ParamPager:
155
152
  ordering = self.sort_by_precedence(params)
156
153
  for name in ordering:
157
154
  p = params[name]
158
- if only_changed and not (name in changed):
155
+ if only_changed and name not in changed:
159
156
  continue
160
157
 
161
158
  constant = 'C' if p.constant else 'V'
@@ -209,7 +206,6 @@ class ParamPager:
209
206
  order: The order of the table columns
210
207
  bound_dict: Dictionary of appropriately formatted bounds
211
208
  """
212
-
213
209
  contents, tail = [], []
214
210
  column_set = {k for _, row in info_list for k in row}
215
211
  columns = [col for col in order if col in column_set]
@@ -316,6 +312,7 @@ def load_ipython_extension(ip, verbose=True):
316
312
  Implements the %params line magic used to inspect the parameters
317
313
  of a parameterized class or object.
318
314
  """
315
+
319
316
  def __init__(self, *args, **kwargs):
320
317
  super().__init__(*args, **kwargs)
321
318
  self.param_pager = ParamPager()
@@ -353,9 +350,7 @@ def load_ipython_extension(ip, verbose=True):
353
350
 
354
351
 
355
352
  class IPythonDisplay:
356
- """
357
- Reactive display handler that updates the output.
358
- """
353
+ """Reactive display handler that updates the output."""
359
354
 
360
355
  enabled = True
361
356