Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 50 additions & 2 deletions scripts/microgenerator/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,31 @@ def process_structure(


def _should_include_class(class_name: str, class_filters: Dict[str, Any]) -> bool:
"""Checks if a class should be included based on filter criteria."""
"""Determines if a class should be included based on name filters.

Filters are defined in the configuration file and passed in the
`class_filters` dictionary.

Args:
class_name: The name of the class to check.
class_filters: A dictionary containing filter rules:
"include_suffixes": List of suffixes. If provided, the class name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for my curiosity, what happens if a class name satisfies both include_suffixes and exclude_suffixes?

MUST end with one of these suffixes.
"exclude_suffixes": List of suffixes. If provided, the class name
MUST NOT end with any of these suffixes.

Returns:
bool: True if the class should be included, False otherwise.

Example:
>>> filters = {"include_suffixes": ["Client"], "exclude_suffixes": ["BaseClient"]}
>>> _should_include_class("DatasetClient", filters)
True
>>> _should_include_class("BaseClient", filters)
False
>>> _should_include_class("SomeOtherClass", filters)
False
"""
if class_filters.get("include_suffixes"):
if not class_name.endswith(tuple(class_filters["include_suffixes"])):
return False
Expand All @@ -400,7 +424,31 @@ def _should_include_class(class_name: str, class_filters: Dict[str, Any]) -> boo


def _should_include_method(method_name: str, method_filters: Dict[str, Any]) -> bool:
"""Checks if a method should be included based on filter criteria."""
"""Determines if a method should be included based on name filters.

Filters are defined in the configuration file and passed in the
`method_filters` dictionary.

Args:
method_name: The name of the method to check.
method_filters: A dictionary containing filter rules:
"include_prefixes": List of prefixes. If provided, the method name
MUST start with one of these prefixes.
"exclude_prefixes": List of prefixes. If provided, the method name
MUST NOT start with any of these prefixes.

Returns:
bool: True if the method should be included, False otherwise.

Example:
>>> filters = {"include_prefixes": ["get_", "list_"], "exclude_prefixes": ["_internal_"]}
>>> _should_include_method("get_dataset", filters)
True
>>> _should_include_method("create_dataset", filters)
False
>>> _should_include_method("_internal_get_dataset", filters)
False
"""
if method_filters.get("include_prefixes"):
if not any(
method_name.startswith(p) for p in method_filters["include_prefixes"]
Expand Down
129 changes: 129 additions & 0 deletions scripts/microgenerator/tests/unit/test_generate_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import pytest
from scripts.microgenerator.generate import (
_should_include_class,
_should_include_method,
)


# Tests for _should_include_class
@pytest.mark.parametrize(
"class_name, filters, expected",
[
pytest.param("MyClass", {}, True, id="No filters"),
pytest.param(
"DatasetClient",
{"include_suffixes": ["Client", "Service"]},
True,
id="Include suffix match",
),
pytest.param(
"MyClass",
{"include_suffixes": ["Client", "Service"]},
False,
id="Include suffix no match",
),
pytest.param(
"MyBase",
{"exclude_suffixes": ["Base", "Util"]},
False,
id="Exclude suffix match",
),
pytest.param(
"MyClass",
{"exclude_suffixes": ["Base", "Util"]},
True,
id="Exclude suffix no match",
),
pytest.param(
"DatasetClient",
{"include_suffixes": ["Client"], "exclude_suffixes": ["BaseClient"]},
True,
id="Mix include/exclude match",
),
pytest.param(
"BaseClient",
{"include_suffixes": ["Client"], "exclude_suffixes": ["BaseClient"]},
False,
id="Mix include/exclude no match",
),
pytest.param(
"MyClass",
{"include_suffixes": [], "exclude_suffixes": []},
True,
id="Empty filters",
),
],
)
def test_should_include_class(class_name, filters, expected):
assert _should_include_class(class_name, filters) is expected


# Tests for _should_include_method
@pytest.mark.parametrize(
"method_name, filters, expected",
[
pytest.param("my_method", {}, True, id="No filters"),
pytest.param(
"get_dataset",
{"include_prefixes": ["get_", "list_"]},
True,
id="Include prefix match (get)",
),
pytest.param(
"list_jobs",
{"include_prefixes": ["get_", "list_"]},
True,
id="Include prefix match (list)",
),
pytest.param(
"create_dataset",
{"include_prefixes": ["get_", "list_"]},
False,
id="Include prefix no match",
),
pytest.param(
"_private_method",
{"exclude_prefixes": ["_", "internal_"]},
False,
id="Exclude prefix match (private)",
),
pytest.param(
"internal_helper",
{"exclude_prefixes": ["_", "internal_"]},
False,
id="Exclude prefix match (internal)",
),
pytest.param(
"get_dataset",
{"exclude_prefixes": ["_", "internal_"]},
True,
id="Exclude prefix no match",
),
pytest.param(
"get_dataset",
{"include_prefixes": ["get_"], "exclude_prefixes": ["get_internal_"]},
True,
id="Mix include/exclude match",
),
pytest.param(
"get_internal_status",
{"include_prefixes": ["get_"], "exclude_prefixes": ["get_internal_"]},
False,
id="Mix include/exclude no match (exclude wins)",
),
pytest.param(
"list_datasets",
{"include_prefixes": ["get_"], "exclude_prefixes": ["get_internal_"]},
False,
id="Mix include/exclude no match (include fails)",
),
pytest.param(
"my_method",
{"include_prefixes": [], "exclude_prefixes": []},
True,
id="Empty filters",
),
],
)
def test_should_include_method(method_name, filters, expected):
assert _should_include_method(method_name, filters) is expected
Loading