scikit-base 0.12.0__tar.gz → 0.12.3__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 (75) hide show
  1. {scikit_base-0.12.0/scikit_base.egg-info → scikit_base-0.12.3}/PKG-INFO +15 -4
  2. {scikit_base-0.12.0 → scikit_base-0.12.3}/README.md +11 -1
  3. {scikit_base-0.12.0 → scikit_base-0.12.3}/pyproject.toml +2 -2
  4. {scikit_base-0.12.0 → scikit_base-0.12.3/scikit_base.egg-info}/PKG-INFO +15 -4
  5. {scikit_base-0.12.0 → scikit_base-0.12.3}/scikit_base.egg-info/SOURCES.txt +1 -0
  6. {scikit_base-0.12.0 → scikit_base-0.12.3}/scikit_base.egg-info/requires.txt +1 -1
  7. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/__init__.py +1 -1
  8. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/_nopytest_tests.py +1 -1
  9. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/base/_base.py +25 -9
  10. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/base/_meta.py +8 -3
  11. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/lookup/_lookup.py +32 -12
  12. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/testing/test_all_objects.py +1 -1
  13. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/tests/conftest.py +22 -11
  14. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/tests/test_base.py +20 -68
  15. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/deep_equals/_deep_equals.py +1 -0
  16. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/dependencies/_dependencies.py +215 -46
  17. scikit_base-0.12.3/skbase/utils/dependencies/tests/test_check_dependencies.py +172 -0
  18. scikit_base-0.12.3/skbase/utils/doctest_run.py +65 -0
  19. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/tests/test_deep_equals.py +2 -1
  20. scikit_base-0.12.0/skbase/utils/dependencies/tests/test_check_dependencies.py +0 -49
  21. {scikit_base-0.12.0 → scikit_base-0.12.3}/LICENSE +0 -0
  22. {scikit_base-0.12.0 → scikit_base-0.12.3}/docs/source/conf.py +0 -0
  23. {scikit_base-0.12.0 → scikit_base-0.12.3}/scikit_base.egg-info/dependency_links.txt +0 -0
  24. {scikit_base-0.12.0 → scikit_base-0.12.3}/scikit_base.egg-info/top_level.txt +0 -0
  25. {scikit_base-0.12.0 → scikit_base-0.12.3}/scikit_base.egg-info/zip-safe +0 -0
  26. {scikit_base-0.12.0 → scikit_base-0.12.3}/setup.cfg +0 -0
  27. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/_exceptions.py +0 -0
  28. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/base/__init__.py +0 -0
  29. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/base/_clone_base.py +0 -0
  30. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/base/_clone_plugins.py +0 -0
  31. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/base/_pretty_printing/__init__.py +0 -0
  32. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/base/_pretty_printing/_object_html_repr.py +0 -0
  33. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/base/_pretty_printing/_pprint.py +0 -0
  34. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/base/_pretty_printing/tests/__init__.py +0 -0
  35. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/base/_pretty_printing/tests/test_pprint.py +0 -0
  36. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/base/_tagmanager.py +0 -0
  37. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/lookup/__init__.py +0 -0
  38. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/lookup/tests/__init__.py +0 -0
  39. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/lookup/tests/test_lookup.py +0 -0
  40. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/testing/__init__.py +0 -0
  41. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/testing/utils/__init__.py +0 -0
  42. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/testing/utils/_conditional_fixtures.py +0 -0
  43. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/testing/utils/inspect.py +0 -0
  44. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/tests/__init__.py +0 -0
  45. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/tests/mock_package/__init__.py +0 -0
  46. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/tests/mock_package/test_mock_package.py +0 -0
  47. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/tests/test_baseestimator.py +0 -0
  48. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/tests/test_exceptions.py +0 -0
  49. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/tests/test_meta.py +0 -0
  50. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/__init__.py +0 -0
  51. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/_check.py +0 -0
  52. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/_iter.py +0 -0
  53. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/_nested_iter.py +0 -0
  54. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/_utils.py +0 -0
  55. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/deep_equals/__init__.py +0 -0
  56. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/deep_equals/_common.py +0 -0
  57. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/dependencies/__init__.py +0 -0
  58. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/dependencies/_import.py +0 -0
  59. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/dependencies/tests/__init__.py +0 -0
  60. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/random_state.py +0 -0
  61. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/stderr_mute.py +0 -0
  62. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/stdout_mute.py +0 -0
  63. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/tests/__init__.py +0 -0
  64. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/tests/test_check.py +0 -0
  65. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/tests/test_iter.py +0 -0
  66. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/tests/test_nested_iter.py +0 -0
  67. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/tests/test_random_state.py +0 -0
  68. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/tests/test_std_mute.py +0 -0
  69. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/utils/tests/test_utils.py +0 -0
  70. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/validate/__init__.py +0 -0
  71. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/validate/_named_objects.py +0 -0
  72. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/validate/_types.py +0 -0
  73. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/validate/tests/__init__.py +0 -0
  74. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/validate/tests/test_iterable_named_objects.py +0 -0
  75. {scikit_base-0.12.0 → scikit_base-0.12.3}/skbase/validate/tests/test_type_validations.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: scikit-base
3
- Version: 0.12.0
3
+ Version: 0.12.3
4
4
  Summary: Base classes for sklearn-like parametric objects
5
5
  Author-email: sktime developers <sktime.toolbox@gmail.com>
6
6
  Maintainer: Franz Király
@@ -90,7 +90,7 @@ Requires-Dist: nbsphinx>=0.8.6; extra == "docs"
90
90
  Requires-Dist: numpydoc; extra == "docs"
91
91
  Requires-Dist: pydata-sphinx-theme; extra == "docs"
92
92
  Requires-Dist: sphinx-issues<6.0.0; extra == "docs"
93
- Requires-Dist: sphinx-gallery<0.19.0; extra == "docs"
93
+ Requires-Dist: sphinx-gallery<0.20.0; extra == "docs"
94
94
  Requires-Dist: sphinx-panels; extra == "docs"
95
95
  Requires-Dist: sphinx-design<0.7.0; extra == "docs"
96
96
  Requires-Dist: Sphinx!=7.2.0,<9.0.0; extra == "docs"
@@ -104,6 +104,7 @@ Requires-Dist: numpy; extra == "test"
104
104
  Requires-Dist: scipy; extra == "test"
105
105
  Requires-Dist: pandas; extra == "test"
106
106
  Requires-Dist: scikit-learn>=0.24.0; extra == "test"
107
+ Dynamic: license-file
107
108
 
108
109
  <a href="https://skbase.readthedocs.io/en/latest/"><img src="https://github.com/sktime/skbase/blob/main/docs/source/images/skbase-logo-with-name.png" width="175" align="right" /></a>
109
110
 
@@ -114,7 +115,7 @@ Requires-Dist: scikit-learn>=0.24.0; extra == "test"
114
115
  `skbase` provides base classes for creating scikit-learn-like parametric objects,
115
116
  along with tools to make it easier to build your own packages that follow these design patterns.
116
117
 
117
- :rocket: Version 0.12.0 is now available. Check out our
118
+ :rocket: Version 0.12.3 is now available. Check out our
118
119
  [release notes](https://skbase.readthedocs.io/en/latest/changelog.html).
119
120
 
120
121
  | Overview | |
@@ -160,3 +161,13 @@ or, if you want to install with the maximum set of dependencies, use:
160
161
  ```bash
161
162
  pip install scikit-base[all_extras]
162
163
  ```
164
+
165
+ ## Contributors ✨
166
+
167
+ This project follows the
168
+ [all-contributors](https://github.com/all-contributors/all-contributors) specification.
169
+ Contributions of any kind welcome!
170
+
171
+ Thanks go to these wonderful people:
172
+
173
+ [skbase contributors](https://github.com/sktime/skbase/graphs/contributors)
@@ -7,7 +7,7 @@
7
7
  `skbase` provides base classes for creating scikit-learn-like parametric objects,
8
8
  along with tools to make it easier to build your own packages that follow these design patterns.
9
9
 
10
- :rocket: Version 0.12.0 is now available. Check out our
10
+ :rocket: Version 0.12.3 is now available. Check out our
11
11
  [release notes](https://skbase.readthedocs.io/en/latest/changelog.html).
12
12
 
13
13
  | Overview | |
@@ -53,3 +53,13 @@ or, if you want to install with the maximum set of dependencies, use:
53
53
  ```bash
54
54
  pip install scikit-base[all_extras]
55
55
  ```
56
+
57
+ ## Contributors ✨
58
+
59
+ This project follows the
60
+ [all-contributors](https://github.com/all-contributors/all-contributors) specification.
61
+ Contributions of any kind welcome!
62
+
63
+ Thanks go to these wonderful people:
64
+
65
+ [skbase contributors](https://github.com/sktime/skbase/graphs/contributors)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "scikit-base"
3
- version = "0.12.0"
3
+ version = "0.12.3"
4
4
  description = "Base classes for sklearn-like parametric objects"
5
5
  authors = [
6
6
  {name = "sktime developers", email = "sktime.toolbox@gmail.com"},
@@ -71,7 +71,7 @@ docs = [
71
71
  "numpydoc",
72
72
  "pydata-sphinx-theme",
73
73
  "sphinx-issues<6.0.0",
74
- "sphinx-gallery<0.19.0",
74
+ "sphinx-gallery<0.20.0",
75
75
  "sphinx-panels",
76
76
  "sphinx-design<0.7.0",
77
77
  "Sphinx!=7.2.0,<9.0.0",
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: scikit-base
3
- Version: 0.12.0
3
+ Version: 0.12.3
4
4
  Summary: Base classes for sklearn-like parametric objects
5
5
  Author-email: sktime developers <sktime.toolbox@gmail.com>
6
6
  Maintainer: Franz Király
@@ -90,7 +90,7 @@ Requires-Dist: nbsphinx>=0.8.6; extra == "docs"
90
90
  Requires-Dist: numpydoc; extra == "docs"
91
91
  Requires-Dist: pydata-sphinx-theme; extra == "docs"
92
92
  Requires-Dist: sphinx-issues<6.0.0; extra == "docs"
93
- Requires-Dist: sphinx-gallery<0.19.0; extra == "docs"
93
+ Requires-Dist: sphinx-gallery<0.20.0; extra == "docs"
94
94
  Requires-Dist: sphinx-panels; extra == "docs"
95
95
  Requires-Dist: sphinx-design<0.7.0; extra == "docs"
96
96
  Requires-Dist: Sphinx!=7.2.0,<9.0.0; extra == "docs"
@@ -104,6 +104,7 @@ Requires-Dist: numpy; extra == "test"
104
104
  Requires-Dist: scipy; extra == "test"
105
105
  Requires-Dist: pandas; extra == "test"
106
106
  Requires-Dist: scikit-learn>=0.24.0; extra == "test"
107
+ Dynamic: license-file
107
108
 
108
109
  <a href="https://skbase.readthedocs.io/en/latest/"><img src="https://github.com/sktime/skbase/blob/main/docs/source/images/skbase-logo-with-name.png" width="175" align="right" /></a>
109
110
 
@@ -114,7 +115,7 @@ Requires-Dist: scikit-learn>=0.24.0; extra == "test"
114
115
  `skbase` provides base classes for creating scikit-learn-like parametric objects,
115
116
  along with tools to make it easier to build your own packages that follow these design patterns.
116
117
 
117
- :rocket: Version 0.12.0 is now available. Check out our
118
+ :rocket: Version 0.12.3 is now available. Check out our
118
119
  [release notes](https://skbase.readthedocs.io/en/latest/changelog.html).
119
120
 
120
121
  | Overview | |
@@ -160,3 +161,13 @@ or, if you want to install with the maximum set of dependencies, use:
160
161
  ```bash
161
162
  pip install scikit-base[all_extras]
162
163
  ```
164
+
165
+ ## Contributors ✨
166
+
167
+ This project follows the
168
+ [all-contributors](https://github.com/all-contributors/all-contributors) specification.
169
+ Contributions of any kind welcome!
170
+
171
+ Thanks go to these wonderful people:
172
+
173
+ [skbase contributors](https://github.com/sktime/skbase/graphs/contributors)
@@ -45,6 +45,7 @@ skbase/utils/_check.py
45
45
  skbase/utils/_iter.py
46
46
  skbase/utils/_nested_iter.py
47
47
  skbase/utils/_utils.py
48
+ skbase/utils/doctest_run.py
48
49
  skbase/utils/random_state.py
49
50
  skbase/utils/stderr_mute.py
50
51
  skbase/utils/stdout_mute.py
@@ -19,7 +19,7 @@ nbsphinx>=0.8.6
19
19
  numpydoc
20
20
  pydata-sphinx-theme
21
21
  sphinx-issues<6.0.0
22
- sphinx-gallery<0.19.0
22
+ sphinx-gallery<0.20.0
23
23
  sphinx-panels
24
24
  sphinx-design<0.7.0
25
25
  Sphinx!=7.2.0,<9.0.0
@@ -6,4 +6,4 @@
6
6
  The included functionality makes it easy to reuse scikit-learn and
7
7
  sktime design principles in your project.
8
8
  """
9
- __version__: str = "0.12.0"
9
+ __version__: str = "0.12.3"
@@ -7,7 +7,7 @@ from skbase.lookup import all_objects
7
7
 
8
8
  MODULES_TO_IGNORE = ("tests", "testing", "dependencies", "all")
9
9
 
10
- # all_objectscrawls all modules excepting pytest test files
10
+ # all_objects crawls all modules excepting pytest test files
11
11
  # if it encounters an unisolated import, it will throw an exception
12
12
  results = all_objects(modules_to_ignore=MODULES_TO_IGNORE)
13
13
 
@@ -1169,13 +1169,19 @@ class BaseObject(_FlagManager):
1169
1169
  class TagAliaserMixin:
1170
1170
  """Mixin class for tag aliasing and deprecation of old tags.
1171
1171
 
1172
- To deprecate tags, add the TagAliaserMixin to BaseObject or BaseEstimator.
1173
- alias_dict contains the deprecated tags, and supports removal and renaming.
1174
- For removal, add an entry "old_tag_name": ""
1175
- For renaming, add an entry "old_tag_name": "new_tag_name"
1176
- deprecate_dict contains the version number of renaming or removal.
1177
- the keys in deprecate_dict should be the same as in alias_dict.
1178
- values in deprecate_dict should be strings, the version of removal/renaming.
1172
+ To deprecate tags, add the ``TagAliaserMixin`` to ``BaseObject``
1173
+ or ``BaseEstimator``.
1174
+
1175
+ ``alias_dict`` contains the deprecated tags, and supports removal and renaming.
1176
+
1177
+ * For removal, add an entry ``"old_tag_name": ""``
1178
+ * For renaming, add an entry ``"old_tag_name": "new_tag_name"``
1179
+
1180
+ ``deprecate_dict`` contains the version number of renaming or removal.
1181
+
1182
+ * The keys in ``deprecate_dict`` should be the same as in alias_dict.
1183
+ * Values in ``deprecate_dict`` should be strings, the version of
1184
+ removal/renaming, in PEP 440 format, e.g., ``"1.0.0"``.
1179
1185
 
1180
1186
  The class will ensure that new tags alias old tags and vice versa, during
1181
1187
  the deprecation period. Informative warnings will be raised whenever the
@@ -1195,6 +1201,9 @@ class TagAliaserMixin:
1195
1201
  # key = old tag; value = version in which tag will be removed, as string
1196
1202
  deprecate_dict = {"old_tag": "0.12.0", "tag_to_remove": "99.99.99"}
1197
1203
 
1204
+ # package name used for deprecation warnings
1205
+ _package_name = ""
1206
+
1198
1207
  def __init__(self):
1199
1208
  """Construct TagAliaserMixin."""
1200
1209
  super(TagAliaserMixin, self).__init__()
@@ -1242,6 +1251,7 @@ class TagAliaserMixin:
1242
1251
  tags set by ``set_tags`` or ``clone_tags``.
1243
1252
  """
1244
1253
  collected_tags = super(TagAliaserMixin, cls).get_class_tags()
1254
+ cls._deprecate_tag_warn(collected_tags)
1245
1255
  collected_tags = cls._complete_dict(collected_tags)
1246
1256
  return collected_tags
1247
1257
 
@@ -1322,6 +1332,7 @@ class TagAliaserMixin:
1322
1332
  and new tags from ``_tags_dynamic`` object attribute.
1323
1333
  """
1324
1334
  collected_tags = super(TagAliaserMixin, self).get_tags()
1335
+ self._deprecate_tag_warn(collected_tags)
1325
1336
  collected_tags = self._complete_dict(collected_tags)
1326
1337
  return collected_tags
1327
1338
 
@@ -1452,14 +1463,19 @@ class TagAliaserMixin:
1452
1463
  if tag_name in cls.alias_dict.keys():
1453
1464
  version = cls.deprecate_dict[tag_name]
1454
1465
  new_tag = cls.alias_dict[tag_name]
1455
- msg = f"tag {tag_name!r} will be removed in sktime version {version}"
1466
+ pkg_name = cls._package_name
1467
+ if pkg_name != "":
1468
+ pkg_name = f"{pkg_name} "
1469
+ msg = (
1470
+ f"tag {tag_name!r} will be removed in {pkg_name} version {version}"
1471
+ )
1456
1472
  if new_tag != "":
1457
1473
  msg += (
1458
1474
  f" and replaced by {new_tag!r}, please use {new_tag!r} instead"
1459
1475
  )
1460
1476
  else:
1461
1477
  msg += ", please remove code that access or sets {tag_name!r}"
1462
- warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
1478
+ warnings.warn(msg, category=FutureWarning, stacklevel=2)
1463
1479
 
1464
1480
 
1465
1481
  class BaseEstimator(BaseObject):
@@ -360,6 +360,7 @@ class _MetaObjectMixin:
360
360
  cls_type=None,
361
361
  allow_dict=False,
362
362
  allow_mix=True,
363
+ allow_empty=False,
363
364
  clone=True,
364
365
  ):
365
366
  """Check that objects is a list of objects or sequence of named objects.
@@ -373,10 +374,14 @@ class _MetaObjectMixin:
373
374
  Name of checked attribute in error messages.
374
375
  cls_type : class or tuple of classes, default=BaseEstimator.
375
376
  class(es) that all objects are checked to be an instance of.
377
+ allow_dict : bool, default=False
378
+ Whether ``objs`` can be a dictionary mapping str names to objects.
376
379
  allow_mix : bool, default=True
377
- Whether mix of objects and (str, objects) is allowed in `objs.`
380
+ Whether mix of objects and (str, objects) is allowed in ``objs``.
381
+ allow_empty : bool, default=False
382
+ Whether ``objs`` can be empty.
378
383
  clone : bool, default=True
379
- Whether objects or named objects in `objs` are returned as clones
384
+ Whether objects or named objects in ``objs`` are returned as clones
380
385
  (True) or references (False).
381
386
 
382
387
  Returns
@@ -421,7 +426,7 @@ class _MetaObjectMixin:
421
426
 
422
427
  if (
423
428
  objs is None
424
- or len(objs) == 0
429
+ or (not allow_empty and len(objs) == 0)
425
430
  or not (isinstance(objs, list) or (allow_dict and isinstance(objs, dict)))
426
431
  ):
427
432
  raise TypeError(msg)
@@ -430,7 +430,7 @@ def _get_module_info(
430
430
  authors = ", ".join(authors)
431
431
  # Compile information on classes in the module
432
432
  module_classes: MutableMapping = {} # of ClassInfo type
433
- for name, klass in inspect.getmembers(module, inspect.isclass):
433
+ for name, klass in _get_members_uw(module, inspect.isclass):
434
434
  # Skip a class if non-public items should be excluded and it starts with "_"
435
435
  if (
436
436
  (exclude_non_public_items and klass.__name__.startswith("_"))
@@ -440,7 +440,9 @@ def _get_module_info(
440
440
  ):
441
441
  continue
442
442
  # Otherwise, store info about the class
443
- if klass.__module__ == module.__name__ or name in designed_imports:
443
+ uw_klass = inspect.unwrap(klass) # unwrap any decorators
444
+ klassname = uw_klass.__name__
445
+ if uw_klass.__module__ == module.__name__ or name in designed_imports:
444
446
  klass_authors = getattr(klass, "__author__", authors)
445
447
  if isinstance(klass_authors, (list, tuple)):
446
448
  klass_authors = ", ".join(klass_authors)
@@ -453,9 +455,9 @@ def _get_module_info(
453
455
  )
454
456
  module_classes[name] = {
455
457
  "klass": klass,
456
- "name": klass.__name__,
458
+ "name": klassname,
457
459
  "description": (
458
- "" if klass.__doc__ is None else klass.__doc__.split("\n")[0]
460
+ "" if uw_klass.__doc__ is None else uw_klass.__doc__.split("\n")[0]
459
461
  ),
460
462
  "tags": (
461
463
  klass.get_class_tags() if hasattr(klass, "get_class_tags") else None
@@ -464,23 +466,25 @@ def _get_module_info(
464
466
  "is_base_class": klass in package_base_classes,
465
467
  "is_base_object": issubclass(klass, BaseObject),
466
468
  "authors": klass_authors,
467
- "module_name": module.__name__,
469
+ "module_name": uw_klass.__module__,
468
470
  }
469
471
 
470
472
  module_functions: MutableMapping = {} # of FunctionInfo type
471
- for name, func in inspect.getmembers(module, inspect.isfunction):
472
- if func.__module__ == module.__name__ or name in designed_imports:
473
+ for name, func in _get_members_uw(module, inspect.isfunction):
474
+ uw_func = inspect.unwrap(func) # unwrap any decorators
475
+ funcname = uw_func.__name__
476
+ if uw_func.__module__ == module.__name__ or name in designed_imports:
473
477
  # Skip a class if non-public items should be excluded and it starts with "_"
474
- if exclude_non_public_items and func.__name__.startswith("_"):
478
+ if exclude_non_public_items and funcname.startswith("_"):
475
479
  continue
476
480
  # Otherwise, store info about the class
477
481
  module_functions[name] = {
478
482
  "func": func,
479
- "name": func.__name__,
483
+ "name": funcname,
480
484
  "description": (
481
- "" if func.__doc__ is None else func.__doc__.split("\n")[0]
485
+ "" if uw_func.__doc__ is None else uw_func.__doc__.split("\n")[0]
482
486
  ),
483
- "module_name": module.__name__,
487
+ "module_name": uw_func.__module__,
484
488
  }
485
489
 
486
490
  # Combine all the information on the module together
@@ -505,6 +509,22 @@ def _get_module_info(
505
509
  return module_info
506
510
 
507
511
 
512
+ def _get_members_uw(module, predicate=None):
513
+ """Get members of a module. Same as inspect.getmembers, but robust to decorators."""
514
+ for name, obj in vars(module).items():
515
+ if not callable(obj):
516
+ continue
517
+
518
+ try:
519
+ unwrapped = inspect.unwrap(obj)
520
+ except ValueError:
521
+ continue # skip circular wrappers or broken decorators
522
+
523
+ if predicate is not None and not predicate(unwrapped):
524
+ continue
525
+ yield name, obj
526
+
527
+
508
528
  def get_package_metadata(
509
529
  package_name: str,
510
530
  path: Optional[str] = None,
@@ -876,7 +896,7 @@ def all_objects(
876
896
 
877
897
  # remove names if return_names=False
878
898
  if not return_names:
879
- all_estimators = [estimator for (name, estimator) in all_estimators]
899
+ all_estimators = [estimator for (_, estimator) in all_estimators]
880
900
  columns = ["object"]
881
901
  else:
882
902
  columns = ["name", "object"]
@@ -226,7 +226,7 @@ class BaseFixtureGenerator:
226
226
  @pytest.fixture(scope="function")
227
227
  def object_instance(self, request):
228
228
  """object_instance fixture definition for indirect use."""
229
- # esetimator_instance is cloned at the start of every test
229
+ # estimator_instance is cloned at the start of every test
230
230
  return request.param.clone()
231
231
 
232
232
 
@@ -56,6 +56,7 @@ SKBASE_MODULES = (
56
56
  "skbase.utils.dependencies",
57
57
  "skbase.utils.dependencies._dependencies",
58
58
  "skbase.utils.dependencies._import",
59
+ "skbase.utils.doctest_run",
59
60
  "skbase.utils.random_state",
60
61
  "skbase.utils.stderr_mute",
61
62
  "skbase.utils.stdout_mute",
@@ -83,6 +84,7 @@ SKBASE_PUBLIC_MODULES = (
83
84
  "skbase.utils",
84
85
  "skbase.utils.deep_equals",
85
86
  "skbase.utils.dependencies",
87
+ "skbase.utils.doctest_run",
86
88
  "skbase.utils.random_state",
87
89
  "skbase.utils.stderr_mute",
88
90
  "skbase.utils.stdout_mute",
@@ -188,6 +190,7 @@ SKBASE_PUBLIC_FUNCTIONS_BY_MODULE = {
188
190
  "skbase.utils._utils": ("subset_dict_keys",),
189
191
  "skbase.utils.deep_equals": ("deep_equals",),
190
192
  "skbase.utils.deep_equals._deep_equals": ("deep_equals", "deep_equals_custom"),
193
+ "skbase.utils.doctest_run": ("run_doctest",),
191
194
  "skbase.utils.random_state": (
192
195
  "check_random_state",
193
196
  "sample_dependent_seed",
@@ -199,7 +202,11 @@ SKBASE_FUNCTIONS_BY_MODULE = SKBASE_PUBLIC_FUNCTIONS_BY_MODULE.copy()
199
202
  SKBASE_FUNCTIONS_BY_MODULE.update(
200
203
  {
201
204
  "skbase.base._clone_base": {"_check_clone", "_clone"},
202
- "skbase.base._clone_plugins": ("_default_clone",),
205
+ "skbase.base._clone_plugins": (
206
+ "_default_clone",
207
+ "_get_sklearn_clone",
208
+ "_is_sklearn_present",
209
+ ),
203
210
  "skbase.base._pretty_printing._object_html_repr": (
204
211
  "_get_visual_block",
205
212
  "_object_html_repr",
@@ -208,20 +215,22 @@ SKBASE_FUNCTIONS_BY_MODULE.update(
208
215
  ),
209
216
  "skbase.base._pretty_printing._pprint": ("_changed_params", "_safe_repr"),
210
217
  "skbase.lookup._lookup": (
218
+ "all_objects",
219
+ "get_package_metadata",
220
+ "_check_object_types",
221
+ "_coerce_to_tuple",
211
222
  "_determine_module_path",
223
+ "_filter_by_tags",
224
+ "_filter_by_class",
225
+ "_get_members_uw",
226
+ "_get_module_info",
212
227
  "_get_return_tags",
228
+ "_import_module",
213
229
  "_is_ignored_module",
214
- "all_objects",
215
230
  "_is_non_public_module",
216
- "get_package_metadata",
217
231
  "_make_dataframe",
218
232
  "_walk",
219
- "_filter_by_tags",
220
- "_filter_by_class",
221
- "_import_module",
222
- "_check_object_types",
223
- "_get_module_info",
224
- "_coerce_to_tuple",
233
+ "_walk_and_retrieve_all_objs",
225
234
  ),
226
235
  "skbase.testing.utils.inspect": ("_get_args",),
227
236
  "skbase.utils._check": ("_is_scalar_nan",),
@@ -265,13 +274,15 @@ SKBASE_FUNCTIONS_BY_MODULE.update(
265
274
  "deep_equals_custom",
266
275
  ),
267
276
  "skbase.utils.dependencies._dependencies": (
268
- "_check_soft_dependencies",
269
- "_check_python_version",
270
277
  "_check_env_marker",
271
278
  "_check_estimator_deps",
279
+ "_check_python_version",
280
+ "_check_soft_dependencies",
272
281
  "_get_pkg_version",
273
282
  "_get_installed_packages",
283
+ "_get_installed_packages_private",
274
284
  "_normalize_requirement",
285
+ "_normalize_version",
275
286
  "_raise_at_severity",
276
287
  ),
277
288
  "skbase.utils.random_state": (
@@ -51,10 +51,7 @@ __all__ = [
51
51
  "test_clone",
52
52
  "test_clone_2",
53
53
  "test_clone_raises_error_for_nonconforming_objects",
54
- "test_clone_param_is_none",
55
- "test_clone_empty_array",
56
- "test_clone_sparse_matrix",
57
- "test_clone_nan",
54
+ "test_clone_none_and_empty_array_nan_sparse_matrix",
58
55
  "test_clone_estimator_types",
59
56
  "test_clone_class_rather_than_instance_raises_error",
60
57
  "test_clone_sklearn_composite",
@@ -1025,75 +1022,30 @@ def test_nested_config_after_clone_tags(clone_config):
1025
1022
  not _check_soft_dependencies("scikit-learn", severity="none"),
1026
1023
  reason="skip test if sklearn is not available",
1027
1024
  ) # sklearn is part of the dev dependency set, test should be executed with that
1028
- def test_clone_param_is_none(fixture_class_parent: Type[Parent]):
1029
- """Test clone with keyword parameter set to None."""
1030
- from sklearn.base import clone
1031
-
1032
- base_obj = fixture_class_parent(c=None)
1033
- new_base_obj = clone(base_obj)
1034
- new_base_obj2 = base_obj.clone()
1035
- assert base_obj.c is new_base_obj.c
1036
- assert base_obj.c is new_base_obj2.c
1037
-
1038
-
1039
- @pytest.mark.skipif(
1040
- not _check_soft_dependencies("scikit-learn", severity="none"),
1041
- reason="skip test if sklearn is not available",
1042
- ) # sklearn is part of the dev dependency set, test should be executed with that
1043
- def test_clone_empty_array(fixture_class_parent: Type[Parent]):
1044
- """Test clone with keyword parameter is scipy sparse matrix.
1045
-
1046
- This test is based on scikit-learn regression test to make sure clone
1047
- works with default parameter set to scipy sparse matrix.
1048
- """
1049
- from sklearn.base import clone
1050
-
1051
- # Regression test for cloning estimators with empty arrays
1052
- base_obj = fixture_class_parent(c=np.array([]))
1053
- new_base_obj = clone(base_obj)
1054
- new_base_obj2 = base_obj.clone()
1055
- np.testing.assert_array_equal(base_obj.c, new_base_obj.c)
1056
- np.testing.assert_array_equal(base_obj.c, new_base_obj2.c)
1057
-
1058
-
1059
- @pytest.mark.skipif(
1060
- not _check_soft_dependencies("scikit-learn", severity="none"),
1061
- reason="skip test if sklearn is not available",
1062
- ) # sklearn is part of the dev dependency set, test should be executed with that
1063
- def test_clone_sparse_matrix(fixture_class_parent: Type[Parent]):
1064
- """Test clone with keyword parameter is scipy sparse matrix.
1065
-
1066
- This test is based on scikit-learn regression test to make sure clone
1067
- works with default parameter set to scipy sparse matrix.
1068
- """
1069
- from sklearn.base import clone
1070
-
1071
- base_obj = fixture_class_parent(c=sp.csr_matrix(np.array([[0]])))
1072
- new_base_obj = clone(base_obj)
1073
- new_base_obj2 = base_obj.clone()
1074
- np.testing.assert_array_equal(base_obj.c, new_base_obj.c)
1075
- np.testing.assert_array_equal(base_obj.c, new_base_obj2.c)
1076
-
1077
-
1078
- @pytest.mark.skipif(
1079
- not _check_soft_dependencies("scikit-learn", severity="none"),
1080
- reason="skip test if sklearn is not available",
1081
- ) # sklearn is part of the dev dependency set, test should be executed with that
1082
- def test_clone_nan(fixture_class_parent: Type[Parent]):
1083
- """Test clone with keyword parameter is np.nan.
1084
-
1085
- This test is based on scikit-learn regression test to make sure clone
1086
- works with default parameter set to np.nan.
1087
- """
1025
+ @pytest.mark.parametrize(
1026
+ "c_value",
1027
+ [
1028
+ None,
1029
+ np.array([]),
1030
+ sp.csr_matrix(np.array([[0]])),
1031
+ np.nan,
1032
+ ],
1033
+ )
1034
+ def test_clone_none_and_empty_array_nan_sparse_matrix(
1035
+ fixture_class_parent: Type[Parent], c_value
1036
+ ):
1088
1037
  from sklearn.base import clone
1089
1038
 
1090
- # Regression test for cloning estimators with default parameter as np.nan
1091
- base_obj = fixture_class_parent(c=np.nan)
1039
+ base_obj = fixture_class_parent(c=c_value)
1092
1040
  new_base_obj = clone(base_obj)
1093
1041
  new_base_obj2 = base_obj.clone()
1094
1042
 
1095
- assert base_obj.c is new_base_obj.c
1096
- assert base_obj.c is new_base_obj2.c
1043
+ if isinstance(base_obj.c, (np.ndarray, type(sp.csr_matrix(np.array([[0]]))))):
1044
+ np.testing.assert_array_equal(base_obj.c, new_base_obj.c)
1045
+ np.testing.assert_array_equal(base_obj.c, new_base_obj2.c)
1046
+ else:
1047
+ assert base_obj.c is new_base_obj.c
1048
+ assert base_obj.c is new_base_obj2.c
1097
1049
 
1098
1050
 
1099
1051
  def test_clone_estimator_types(fixture_class_parent: Type[Parent]):
@@ -267,6 +267,7 @@ def _pandas_equals(x, y, return_msg=False, deep_equals=None):
267
267
  return ret(
268
268
  False, f".dtypes, x.dtypes = {x.dtypes} != y.dtypes = {y.dtypes}"
269
269
  )
270
+ return ret(x.equals(y), "index.equals, x = {} != y = {}", [x, y])
270
271
  else:
271
272
  raise RuntimeError(
272
273
  f"Unexpected type of pandas object in _pandas_equals: type(x)={type(x)},"