Skip to content

Commit

Permalink
[MNT] 0.9.0 deprecations and change actions (#355)
Browse files Browse the repository at this point in the history
Carries out deprecations and change actions scheduled for 0.9.0:

* change of `all_objects` `filter_tags` argument behaviour for `str` and
iterable of `str` to mean tags with value `True`
  • Loading branch information
fkiraly authored Aug 23, 2024
1 parent d81a395 commit 699a301
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 39 deletions.
40 changes: 5 additions & 35 deletions skbase/lookup/_lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,46 +203,16 @@ def _filter_by_tags(obj, tag_filter=None, as_dataframe=True):
if not hasattr(obj, "get_class_tag"):
return False

klass_tags = obj.get_class_tags().keys()

# todo 0.9.0: remove the warning message
# i.e., this message and all warnings referring to it
warn_msg = (
"The meaning of filter_tags arguments in all_objects of type str "
"and iterable of str will change from scikit-base 0.9.0. "
"Currently, str or iterable of str arguments select objects that possess the "
"tag(s) with the specified name, of any value. "
"From 0.9.0 onwards, str or iterable of str "
"will select objects that possess the tag with the specified name, "
"with the value True (boolean). See scikit-base issue #326 for the rationale "
"behind this change. "
"To retain previous behaviour, that is, "
"to select objects that possess the tag with the specified name, of any value, "
"use a dict with the tag name as key, and re.Pattern('*?') as value. "
"That is, from re import Pattern, and pass {tag_name: Pattern('*?')} "
"as filter_tags, and similarly with multiple tag names. "
)

# case: tag_filter is string
if isinstance(tag_filter, str):
# todo 0.9.0: reomove this warning
warnings.warn(warn_msg, DeprecationWarning, stacklevel=2)
# todo 0.9.0: replace this line
return tag_filter in klass_tags
# by this line
# tag_filter = {tag_filter: True}
tag_filter = {tag_filter: True}

# case: tag_filter is iterable of str but not dict
# If a iterable of strings is provided, check that all are in the returned tag_dict
if isinstance(tag_filter, Iterable) and not isinstance(tag_filter, dict):
if not all(isinstance(t, str) for t in tag_filter):
raise ValueError(f"{type_msg} {tag_filter}")
# todo 0.9.0: reomove this warning
warnings.warn(warn_msg, DeprecationWarning, stacklevel=2)
# todo 0.9.0: replace this line
return all(tag in klass_tags for tag in tag_filter)
# by this line
# tag_filter = {tag: True for tag in tag_filter}
tag_filter = dict.fromkeys(tag_filter, True)

# case: tag_filter is dict
# check that all keys are str
Expand Down Expand Up @@ -712,8 +682,6 @@ def get_package_metadata(
return module_info


# todo 0.9.0: change docstring to reflect handling of filter_tags
# in case of str or iterable of str
def all_objects(
object_types=None,
filter_tags=None,
Expand Down Expand Up @@ -760,7 +728,9 @@ def all_objects(
Filter used to determine if ``klass`` has tag or expected tag values.
- If a str or list of strings is provided, the return will be filtered
to keep classes that have all the tag(s) specified by the strings.
to keep classes that have all the tag(s) specified by the strings,
with the tag value being True.
- If a dict is provided, the return will be filtered to keep exactly the classes
where tags satisfy all the filter conditions specified by ``filter_tags``.
Filter conditions are as follows, for ``tag_name: search_value`` pairs in
Expand Down
9 changes: 5 additions & 4 deletions skbase/lookup/tests/test_lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
SKBASE_PUBLIC_CLASSES_BY_MODULE,
SKBASE_PUBLIC_FUNCTIONS_BY_MODULE,
SKBASE_PUBLIC_MODULES,
ClassWithABTrue,
Parent,
)
from skbase.tests.mock_package.test_mock_package import (
Expand Down Expand Up @@ -374,18 +375,18 @@ def test_filter_by_tags():
assert _filter_by_tags(NotABaseObject) is True

# Check when tag_filter is a str and present in the class
assert _filter_by_tags(Parent, tag_filter="A") is True
assert _filter_by_tags(ClassWithABTrue, tag_filter="A") is True
# Check when tag_filter is str and not present in the class
assert _filter_by_tags(BaseObject, tag_filter="A") is False
assert _filter_by_tags(Parent, tag_filter="A") is False

# Test functionality when tag present and object doesn't have tag interface
assert _filter_by_tags(NotABaseObject, tag_filter="A") is False

# Test functionality where tag_filter is Iterable of str
# all tags in iterable are in the class
assert _filter_by_tags(Parent, ("A", "B", "C")) is True
assert _filter_by_tags(ClassWithABTrue, ("A", "B")) is True
# Some tags in iterable are in class and others aren't
assert _filter_by_tags(Parent, ("A", "B", "C", "D", "E")) is False
assert _filter_by_tags(ClassWithABTrue, ("A", "B", "C", "D", "E")) is False

# Test functionality where tag_filter is Dict[str, Any]
# All keys in dict are in tag_filter and values all match
Expand Down
16 changes: 16 additions & 0 deletions skbase/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,19 @@ def some_method(self):
def some_other_method(self):
"""To be implemented in the child class."""
pass


# Fixture class for testing tag system, child overrides tags
class ClassWithABTrue(Parent):
"""Child class that sets A, B tags to True."""

_tags = {"A": True, "B": True}
__author__ = ["fkiraly", "RNKuhns"]

def some_method(self):
"""Child class' implementation."""
pass

def some_other_method(self):
"""To be implemented in the child class."""
pass

0 comments on commit 699a301

Please sign in to comment.