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
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ body:
attributes:
label: Environment (optional, bugs only)
description: Python version, OS, mloda version.
placeholder: Python 3.12, Linux, mloda 0.9.0
placeholder: Python 3.12, Linux, mloda 0.10.0
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ placeholder/

### Plugin discovery

mloda 0.9+ auto-discovers installed plugins via `PluginLoader.all()`, no manual import needed. Each
mloda auto-discovers installed plugins via `PluginLoader.all()`, no manual import needed. Each
`manifest.py` lists its concrete classes (`FEATURE_GROUPS`, `COMPUTE_FRAMEWORKS`, `EXTENDERS`) and
`pyproject.toml` wires them up under `[project.entry-points."mloda.*"]`. Add a plugin by appending
it to the relevant list.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Example ComputeFramework implementation."""

from typing import Optional, Set
from uuid import UUID, uuid4

from mloda.core.abstract_plugins.components.parallelization_modes import ParallelizationMode
Expand All @@ -15,8 +14,10 @@ def __init__(
self,
mode: ParallelizationMode = ParallelizationMode.SYNC,
children_if_root: frozenset[UUID] = frozenset(),
uuid: UUID = uuid4(),
function_extender: Optional[Set[Extender]] = None,
uuid: UUID | None = None,
function_extender: set[Extender] | None = None,
) -> None:
"""Initialize with default values for minimal instantiation."""
super().__init__(mode, children_if_root, uuid, function_extender)
# uuid defaults to None, not uuid4(): a default is evaluated once, so every
# instance would otherwise share one id.
super().__init__(mode, children_if_root, uuid or uuid4(), function_extender)
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Tests for MyComputeFramework."""

from uuid import uuid4

from placeholder.compute_frameworks.my_plugin import MyComputeFramework
from mloda.provider import ComputeFramework

Expand All @@ -13,3 +15,14 @@ def test_instantiation() -> None:
"""MyComputeFramework should instantiate with no arguments."""
instance = MyComputeFramework()
assert instance is not None


def test_default_uuid_is_per_instance() -> None:
"""Each instance gets its own uuid; a uuid4() default would be shared by all."""
assert MyComputeFramework().uuid != MyComputeFramework().uuid


def test_explicit_uuid_is_respected() -> None:
"""An explicitly passed uuid is not overwritten."""
given = uuid4()
assert MyComputeFramework(uuid=given).uuid == given
4 changes: 2 additions & 2 deletions placeholder/extenders/my_plugin/my_extender.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
"""Example Extender implementation."""

from typing import Any, Set
from typing import Any

from mloda.core.abstract_plugins.function_extender import Extender, ExtenderHook


class MyExtender(Extender):
"""Example Extender - rename and customize for your use case."""

def wraps(self) -> Set[ExtenderHook]:
def wraps(self) -> set[ExtenderHook]:
"""Return the set of hooks this extender wraps."""
return set()

Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ version = "0.4.0"
description = "TEMPLATE PLACEHOLDER - Do not install directly. This package reserves the name for mloda-plugin-template. See https://github.com/mloda-ai/mloda-plugin-template"
license = "Apache-2.0"
authors = [{ name = "Your Name placeholder", email = "placeholder@placeholder.com" }]
dependencies = ["mloda>=0.9.0", "mloda-testing>=0.3.2"]
dependencies = ["mloda>=0.10.0", "mloda-testing>=0.3.2"]
requires-python = ">=3.10"

# mloda 0.9 discovers installed plugins through these entry points: each resolves to a
# mloda discovers installed plugins through these entry points: each resolves to a
# manifest list of concrete classes. customize.sh rewrites the dotted paths on rename.
[project.entry-points."mloda.feature_groups"]
placeholder = "placeholder.feature_groups.manifest:FEATURE_GROUPS"
Expand Down
10 changes: 7 additions & 3 deletions tests/test_entry_points.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@ def test_entry_points_declared() -> None:
assert any(v.endswith(suffix) for v in values), f"{group}: no entry point ending in {suffix}; got {values}"


def test_plugin_loader_discovers_example_classes() -> None:
"""PluginLoader.all() registers the example classes via entry points, without importing the package."""
def test_plugin_loader_discovers_example_classes(isolated_plugin_registry: PluginRegistry) -> None:
"""PluginLoader.all() registers the example classes via entry points, without importing the package.

isolated_plugin_registry (shipped by mloda as a pytest plugin) restores the process-global
registry on teardown, so this force_reload does not leak into later tests.
"""
PluginLoader.all(force_reload=True)
registered = {cls.__name__ for cls in PluginRegistry.default().registered_classes()}
registered = {cls.__name__ for cls in isolated_plugin_registry.registered_classes()}
assert {"MyFeatureGroup", "MyComputeFramework", "MyExtender"} <= registered
6 changes: 3 additions & 3 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading