scikit-base 1.0.0__tar.gz → 1.0.2__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 (81) hide show
  1. {scikit_base-1.0.0/scikit_base.egg-info → scikit_base-1.0.2}/PKG-INFO +3 -3
  2. {scikit_base-1.0.0 → scikit_base-1.0.2}/README.md +1 -1
  3. {scikit_base-1.0.0 → scikit_base-1.0.2}/pyproject.toml +2 -2
  4. {scikit_base-1.0.0 → scikit_base-1.0.2/scikit_base.egg-info}/PKG-INFO +3 -3
  5. {scikit_base-1.0.0 → scikit_base-1.0.2}/scikit_base.egg-info/SOURCES.txt +1 -0
  6. {scikit_base-1.0.0 → scikit_base-1.0.2}/scikit_base.egg-info/requires.txt +1 -1
  7. {scikit_base-1.0.0 → scikit_base-1.0.2}/scikit_base.egg-info/top_level.txt +0 -1
  8. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/__init__.py +1 -1
  9. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/base/_base.py +23 -7
  10. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/base/_pretty_printing/_object_html_repr.py +4 -3
  11. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/base/_pretty_printing/tests/test_object_html_repr.py +19 -0
  12. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/tests/test_base.py +48 -0
  13. scikit_base-1.0.2/skbase/tests/test_deep_equals.py +35 -0
  14. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/_iter.py +1 -1
  15. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/deep_equals/_deep_equals.py +4 -1
  16. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/tests/test_iter.py +17 -0
  17. {scikit_base-1.0.0 → scikit_base-1.0.2}/LICENSE +0 -0
  18. {scikit_base-1.0.0 → scikit_base-1.0.2}/docs/source/conf.py +0 -0
  19. {scikit_base-1.0.0 → scikit_base-1.0.2}/scikit_base.egg-info/dependency_links.txt +0 -0
  20. {scikit_base-1.0.0 → scikit_base-1.0.2}/scikit_base.egg-info/zip-safe +0 -0
  21. {scikit_base-1.0.0 → scikit_base-1.0.2}/setup.cfg +0 -0
  22. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/_exceptions.py +0 -0
  23. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/_nopytest_tests.py +0 -0
  24. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/base/__init__.py +0 -0
  25. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/base/_clone_base.py +0 -0
  26. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/base/_clone_plugins.py +0 -0
  27. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/base/_meta.py +0 -0
  28. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/base/_pretty_printing/__init__.py +0 -0
  29. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/base/_pretty_printing/_pprint.py +0 -0
  30. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/base/_pretty_printing/tests/__init__.py +0 -0
  31. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/base/_pretty_printing/tests/test_pprint.py +0 -0
  32. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/base/_tagmanager.py +0 -0
  33. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/lookup/__init__.py +0 -0
  34. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/lookup/_lookup.py +0 -0
  35. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/lookup/tests/__init__.py +0 -0
  36. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/lookup/tests/test_lookup.py +0 -0
  37. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/testing/__init__.py +0 -0
  38. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/testing/test_all_objects.py +0 -0
  39. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/testing/utils/__init__.py +0 -0
  40. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/testing/utils/_conditional_fixtures.py +0 -0
  41. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/testing/utils/inspect.py +0 -0
  42. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/tests/__init__.py +0 -0
  43. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/tests/conftest.py +0 -0
  44. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/tests/mock_package/__init__.py +0 -0
  45. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/tests/mock_package/test_mock_package.py +0 -0
  46. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/tests/test_baseestimator.py +0 -0
  47. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/tests/test_exceptions.py +0 -0
  48. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/tests/test_lookup.py +0 -0
  49. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/tests/test_lookup_metaclasses.py +0 -0
  50. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/tests/test_meta.py +0 -0
  51. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/tests/test_tagaliaser.py +0 -0
  52. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/__init__.py +0 -0
  53. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/_check.py +0 -0
  54. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/_nested_iter.py +0 -0
  55. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/_utils.py +0 -0
  56. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/deep_equals/__init__.py +0 -0
  57. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/deep_equals/_common.py +0 -0
  58. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/dependencies/__init__.py +0 -0
  59. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/dependencies/_dependencies.py +0 -0
  60. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/dependencies/_import.py +0 -0
  61. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/dependencies/tests/__init__.py +0 -0
  62. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/dependencies/tests/test_check_dependencies.py +0 -0
  63. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/dependencies/tests/test_safe_import.py +0 -0
  64. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/doctest_run.py +0 -0
  65. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/git_diff.py +0 -0
  66. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/random_state.py +0 -0
  67. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/stderr_mute.py +0 -0
  68. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/stdout_mute.py +0 -0
  69. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/tests/__init__.py +0 -0
  70. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/tests/test_check.py +0 -0
  71. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/tests/test_deep_equals.py +0 -0
  72. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/tests/test_nested_iter.py +0 -0
  73. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/tests/test_random_state.py +0 -0
  74. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/tests/test_std_mute.py +0 -0
  75. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/utils/tests/test_utils.py +0 -0
  76. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/validate/__init__.py +0 -0
  77. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/validate/_named_objects.py +0 -0
  78. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/validate/_type_checks.py +0 -0
  79. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/validate/tests/__init__.py +0 -0
  80. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/validate/tests/test_iterable_named_objects.py +0 -0
  81. {scikit_base-1.0.0 → scikit_base-1.0.2}/skbase/validate/tests/test_type_validations.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scikit-base
3
- Version: 1.0.0
3
+ Version: 1.0.2
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<7.0.0; extra == "docs"
93
- Requires-Dist: sphinx-gallery<0.21.0; extra == "docs"
93
+ Requires-Dist: sphinx-gallery<0.22.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,<10.0.0; extra == "docs"
@@ -115,7 +115,7 @@ Dynamic: license-file
115
115
  `skbase` provides base classes for creating scikit-learn-like parametric objects,
116
116
  along with tools to make it easier to build your own packages that follow these design patterns.
117
117
 
118
- :rocket: Version 1.0.0 is now available. Check out our
118
+ :rocket: Version 1.0.2 is now available. Check out our
119
119
  [release notes](https://skbase.readthedocs.io/en/latest/changelog.html).
120
120
 
121
121
  | Overview | |
@@ -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 1.0.0 is now available. Check out our
10
+ :rocket: Version 1.0.2 is now available. Check out our
11
11
  [release notes](https://skbase.readthedocs.io/en/latest/changelog.html).
12
12
 
13
13
  | Overview | |
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "scikit-base"
3
- version = "1.0.0"
3
+ version = "1.0.2"
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<7.0.0",
74
- "sphinx-gallery<0.21.0",
74
+ "sphinx-gallery<0.22.0",
75
75
  "sphinx-panels",
76
76
  "sphinx-design<0.7.0",
77
77
  "Sphinx!=7.2.0,<10.0.0",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scikit-base
3
- Version: 1.0.0
3
+ Version: 1.0.2
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<7.0.0; extra == "docs"
93
- Requires-Dist: sphinx-gallery<0.21.0; extra == "docs"
93
+ Requires-Dist: sphinx-gallery<0.22.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,<10.0.0; extra == "docs"
@@ -115,7 +115,7 @@ Dynamic: license-file
115
115
  `skbase` provides base classes for creating scikit-learn-like parametric objects,
116
116
  along with tools to make it easier to build your own packages that follow these design patterns.
117
117
 
118
- :rocket: Version 1.0.0 is now available. Check out our
118
+ :rocket: Version 1.0.2 is now available. Check out our
119
119
  [release notes](https://skbase.readthedocs.io/en/latest/changelog.html).
120
120
 
121
121
  | Overview | |
@@ -37,6 +37,7 @@ skbase/tests/__init__.py
37
37
  skbase/tests/conftest.py
38
38
  skbase/tests/test_base.py
39
39
  skbase/tests/test_baseestimator.py
40
+ skbase/tests/test_deep_equals.py
40
41
  skbase/tests/test_exceptions.py
41
42
  skbase/tests/test_lookup.py
42
43
  skbase/tests/test_lookup_metaclasses.py
@@ -19,7 +19,7 @@ nbsphinx>=0.8.6
19
19
  numpydoc
20
20
  pydata-sphinx-theme
21
21
  sphinx-issues<7.0.0
22
- sphinx-gallery<0.21.0
22
+ sphinx-gallery<0.22.0
23
23
  sphinx-panels
24
24
  sphinx-design<0.7.0
25
25
  Sphinx!=7.2.0,<10.0.0
@@ -1,4 +1,3 @@
1
- build
2
1
  build_tools
3
2
  docs
4
3
  enhancement_proposals
@@ -7,4 +7,4 @@ The included functionality makes it easy to reuse scikit-learn and
7
7
  sktime design principles in your project.
8
8
  """
9
9
 
10
- __version__: str = "1.0.0"
10
+ __version__: str = "1.0.2"
@@ -58,6 +58,7 @@ import re
58
58
  import warnings
59
59
  from collections import defaultdict
60
60
  from copy import deepcopy
61
+ from inspect import isclass
61
62
  from typing import List
62
63
 
63
64
  from skbase._exceptions import NotFittedError
@@ -330,13 +331,28 @@ class BaseObject(_FlagManager):
330
331
  """
331
332
  params = {key: getattr(self, key) for key in self.get_param_names()}
332
333
 
333
- if deep:
334
- deep_params = {}
335
- for key, value in params.items():
336
- if hasattr(value, "get_params"):
337
- deep_items = value.get_params().items()
338
- deep_params.update({f"{key}__{k}": val for k, val in deep_items})
339
- params.update(deep_params)
334
+ if not deep:
335
+ return params
336
+
337
+ # we know deep=True, so recurse
338
+ deep_params = {}
339
+ for key, value in params.items():
340
+ # Skip class objects (e.g. BaseObject subclasses stored as params);
341
+ # only recurse into instances with a valid get_params method.
342
+ if isclass(value):
343
+ continue
344
+
345
+ get_params = getattr(value, "get_params", None)
346
+ if not callable(get_params):
347
+ continue
348
+
349
+ sub_params = get_params()
350
+ if not isinstance(sub_params, dict):
351
+ continue
352
+
353
+ deep_params.update({f"{key}__{k}": v for k, v in sub_params.items()})
354
+
355
+ params.update(deep_params)
340
356
 
341
357
  return params
342
358
 
@@ -8,6 +8,7 @@
8
8
  import html
9
9
  import uuid
10
10
  from contextlib import closing
11
+ from inspect import isclass
11
12
  from io import StringIO
12
13
  from string import Template
13
14
 
@@ -103,12 +104,12 @@ def _get_visual_block(base_object):
103
104
  elif base_object is None:
104
105
  return _VisualBlock("single", base_object, names="None", name_details="None")
105
106
 
106
- # check if base_object looks like a meta base_object wraps base_object
107
+ # collect BaseObject instances in the first layer to display in parallel
107
108
  if hasattr(base_object, "get_params"):
108
109
  base_objects = []
109
110
  for key, value in base_object.get_params().items():
110
- # Only look at the BaseObjects in the first layer
111
- if "__" not in key and hasattr(value, "get_params"):
111
+ # Recurse to nested BaseObject instances in the first layer (not classes)
112
+ if "__" not in key and hasattr(value, "get_params") and not isclass(value):
112
113
  base_objects.append(value)
113
114
  if len(base_objects):
114
115
  return _VisualBlock("parallel", base_objects, names=None)
@@ -32,6 +32,25 @@ class MetaObjectForHtml(BaseMetaObject):
32
32
  super().__init__()
33
33
 
34
34
 
35
+ class ParentWithClassParam(BaseObject):
36
+ """BaseObject whose parameter holds a BaseObject subclass, not an instance."""
37
+
38
+ def __init__(self, nested_cls):
39
+ self.nested_cls = nested_cls
40
+ super().__init__()
41
+
42
+
43
+ def test_html_repr_with_baseobject_class_param():
44
+ """HTML diagram repr must not call get_params on a BaseObject class param.
45
+
46
+ Regression test for https://github.com/sktime/skbase/issues/558
47
+ """
48
+ parent = ParentWithClassParam(nested_cls=ComponentDummy)
49
+ html_repr = _object_html_repr(parent)
50
+ assert isinstance(html_repr, str)
51
+ assert parent.__class__.__name__ in html_repr
52
+
53
+
35
54
  def test_meta_object_html_repr_does_not_raise():
36
55
  """Ensure HTML repr for a meta-object does not raise (regression test).
37
56
 
@@ -42,6 +42,7 @@ __all__ = [
42
42
  "test_get_param_names",
43
43
  "test_get_params",
44
44
  "test_get_params_invariance",
45
+ "test_get_params_deep_with_baseobject_class_param",
45
46
  "test_get_params_after_set_params",
46
47
  "test_set_params",
47
48
  "test_set_params_raises_error_non_existent_param",
@@ -761,6 +762,25 @@ def test_get_params_invariance(
761
762
  assert all(item in deep_params.items() for item in shallow_params.items())
762
763
 
763
764
 
765
+ class ParentWithClassParam(BaseObject):
766
+ """BaseObject whose parameter holds a BaseObject subclass, not an instance."""
767
+
768
+ def __init__(self, nested_cls):
769
+ self.nested_cls = nested_cls
770
+ super().__init__()
771
+
772
+
773
+ def test_get_params_deep_with_baseobject_class_param():
774
+ """get_params(deep=True) must not recurse into BaseObject class parameters.
775
+
776
+ Regression test for https://github.com/sktime/skbase/issues/558
777
+ """
778
+ parent = ParentWithClassParam(nested_cls=Child)
779
+ params = parent.get_params(deep=True)
780
+ assert params["nested_cls"] is Child
781
+ assert not any(key.startswith("nested_cls__") for key in params)
782
+
783
+
764
784
  def test_get_params_after_set_params(fixture_class_parent: Type[Parent]):
765
785
  """Test that get_params returns the same thing before and after set_params.
766
786
 
@@ -1498,3 +1518,31 @@ def test_get_class_tags_diamond_inheritance():
1498
1518
  obj = Diamond()
1499
1519
  assert obj.get_tag("A", raise_error=False) == 42
1500
1520
  assert obj.get_tag("B", raise_error=False) == 2
1521
+
1522
+
1523
+ class BadGetParamsClass:
1524
+
1525
+ get_params = "This is not a method in order to test get_params nesting handling."
1526
+
1527
+
1528
+ class NestedBadGetParamsTester(BaseObject):
1529
+ """Class for testing get_params functionality."""
1530
+
1531
+ clsvar = 210
1532
+
1533
+ def __init__(self, a, b):
1534
+ self.a = a
1535
+ self.b = b
1536
+ super().__init__()
1537
+
1538
+
1539
+ def test_get_params_with_nested_bad_get_params():
1540
+ """Test that get_params works when nested get_params is not method."""
1541
+ nested_bad_get_params = BadGetParamsClass()
1542
+ obj = NestedBadGetParamsTester(a=7, b=nested_bad_get_params)
1543
+
1544
+ # this should not raise an error
1545
+ # error mode is attenpting to call get_params of nested_bad_get_params,
1546
+ # which is a string, instead of the get_params of the parent object
1547
+ # instead, get_params should recognize the string type and not call it
1548
+ obj.get_params(deep=True)
@@ -0,0 +1,35 @@
1
+ from skbase.utils.deep_equals import deep_equals
2
+
3
+
4
+ def test_deep_equals_numpy_string_array():
5
+ """Test that deep_equals works on string-dtype numpy arrays. GitHub issue #517."""
6
+ import numpy as np
7
+
8
+ s = np.array(["1", "2", "1"])
9
+ # Same arrays should be equal
10
+ assert deep_equals(s, s) is True
11
+
12
+ # Different arrays should not be equal
13
+ t = np.array(["1", "2", "3"])
14
+ assert deep_equals(s, t) is False
15
+
16
+
17
+ def test_deep_equals_equal_object():
18
+ class DummyComposite:
19
+ def __init__(self, func1, func2, neq_called):
20
+ self.func1 = func1
21
+ self.func2 = func2
22
+ self.neq_called = neq_called
23
+
24
+ class Dummy:
25
+ def __init__(self, func):
26
+ self.func = func
27
+
28
+ def __eq__(self, other) -> DummyComposite:
29
+ return DummyComposite(self.func, other.func, False)
30
+
31
+ def __ne__(self, other) -> DummyComposite:
32
+ return DummyComposite(self.func, other.func, True)
33
+
34
+ a = Dummy(lambda x: x)
35
+ assert deep_equals(a, a)
@@ -210,7 +210,7 @@ def make_strings_unique(str_list):
210
210
  str_count = collections.Counter(str_list)
211
211
  # if any duplicates, we append _integer of occurrence to non-uniques
212
212
  now_count: collections.Counter = collections.Counter()
213
- unique_strs = str_list
213
+ unique_strs = list(str_list)
214
214
  for i, x in enumerate(unique_strs):
215
215
  if str_count[x] > 1:
216
216
  now_count.update([x])
@@ -142,7 +142,7 @@ def _numpy_equals_plugin(x, y, return_msg=False, deep_equals=None):
142
142
  return ret(False, f".shape, x.shape = {x.shape} != y.shape = {y.shape}")
143
143
  if x.dtype != y.dtype:
144
144
  return ret(False, f".dtype, x.dtype = {x.dtype} != y.dtype = {y.dtype}")
145
- if x.dtype == "str":
145
+ if x.dtype == "str" or np.issubdtype(x.dtype, np.character):
146
146
  return ret(np.array_equal(x, y), ".values")
147
147
  elif x.dtype == "object":
148
148
  x_flat = x.flatten()
@@ -508,6 +508,9 @@ def deep_equals_custom(x, y, return_msg=False, plugins=None):
508
508
  """
509
509
  ret = _make_ret(return_msg)
510
510
 
511
+ if x is y:
512
+ return ret(True, "")
513
+
511
514
  if type(x) is not type(y):
512
515
  return ret(False, f".type, x.type = {type(x)} != y.type = {type(y)}")
513
516
 
@@ -126,3 +126,20 @@ def test_make_strings_unique_output():
126
126
  # Case when input is not flat
127
127
  some_strs = ["abc_1", ("abc_2", "bcd")]
128
128
  assert make_strings_unique(some_strs) == ["abc_1", ("abc_2", "bcd")]
129
+
130
+
131
+ def test_make_strings_unique_immutable_input():
132
+ """Test that make_strings_unique does not mutate its input in-place."""
133
+ # Test with a flat list containing duplicates
134
+ input_list = ["abc", "abc", "bcd"]
135
+ input_copy = list(input_list)
136
+ make_strings_unique(input_list)
137
+ assert input_list == input_copy, "make_strings_unique mutated its input flat list!"
138
+
139
+ # Test with a nested list structure
140
+ nested_list = [["abc", "abc"], "bcd"]
141
+ nested_copy = [["abc", "abc"], "bcd"]
142
+ make_strings_unique(nested_list)
143
+ assert (
144
+ nested_list == nested_copy
145
+ ), "make_strings_unique mutated its input nested list!"
File without changes
File without changes