diff --git a/doc/Changelog.md b/doc/Changelog.md index 08f1b2e3..5f4af65a 100644 --- a/doc/Changelog.md +++ b/doc/Changelog.md @@ -15,6 +15,7 @@ myst: ## Unreleased +- {gh-pr}`202` {gh-issue}`188` Explicitly prevent instantiation of abstract classes. - {gh-pr}`201` {gh-issue}`185` Add `type` attribute to the load classes and rename branches `branch_type` attribute to `type` for consistency. Please replace `branch.branch_type` by `branch.type` in your code. In addition, loads data frames gained two new columns: diff --git a/roseau/load_flow/models/branches.py b/roseau/load_flow/models/branches.py index bc34e1fe..1f5112a7 100644 --- a/roseau/load_flow/models/branches.py +++ b/roseau/load_flow/models/branches.py @@ -58,6 +58,8 @@ def __init__( geometry: The geometry of the branch. """ + if type(self) is AbstractBranch: + raise TypeError("Can't instantiate abstract class AbstractBranch") super().__init__(id, **kwargs) self._check_phases(id, phases1=phases1) self._check_phases(id, phases2=phases2) diff --git a/roseau/load_flow/models/core.py b/roseau/load_flow/models/core.py index 9d3b6a7a..1baf6cf2 100644 --- a/roseau/load_flow/models/core.py +++ b/roseau/load_flow/models/core.py @@ -38,6 +38,8 @@ def __init__(self, id: Id, **kwargs: Any) -> None: A unique ID of the element in the network. Two elements of the same type cannot have the same ID. """ + if type(self) is Element: + raise TypeError("Can't instantiate abstract class Element") super().__init__(id) self._connected_elements: list[Element] = [] self._network: ElectricalNetwork | None = None diff --git a/roseau/load_flow/models/loads/loads.py b/roseau/load_flow/models/loads/loads.py index 640a15df..9d94f027 100644 --- a/roseau/load_flow/models/loads/loads.py +++ b/roseau/load_flow/models/loads/loads.py @@ -56,6 +56,8 @@ def __init__(self, id: Id, bus: Bus, *, phases: str | None = None, **kwargs: Any :attr:`allowed_phases`. All phases of the load, except ``"n"``, must be present in the phases of the connected bus. By default, the phases of the bus are used. """ + if type(self) is AbstractLoad: + raise TypeError("Can't instantiate abstract class AbstractLoad") super().__init__(id, **kwargs) if phases is None: phases = bus.phases diff --git a/roseau/load_flow/models/tests/test_element.py b/roseau/load_flow/models/tests/test_element.py new file mode 100644 index 00000000..e7b87651 --- /dev/null +++ b/roseau/load_flow/models/tests/test_element.py @@ -0,0 +1,14 @@ +import pytest + +from roseau.load_flow.models import AbstractBranch, AbstractLoad, Bus, Element + + +def test_abstract_classes(): + with pytest.raises(TypeError, match="Can't instantiate abstract class Element"): + Element("element_id") + bus1 = Bus("bus1", phases="an") + bus2 = Bus("bus2", phases="an") + with pytest.raises(TypeError, match="Can't instantiate abstract class AbstractBranch"): + AbstractBranch("branch_id", bus1=bus1, bus2=bus2, phases1="an", phases2="an") + with pytest.raises(TypeError, match="Can't instantiate abstract class AbstractLoad"): + AbstractLoad("load_id", bus=bus1, phases="an")