Skip to content

Commit 56dd0a0

Browse files
component parser typing (#561)
Category: typing JIRA issue: https://jira.ihme.washington.edu/browse/MIC-5648 Changes and notes typing Testing Ran mypy and pytest.
1 parent e1d5ae2 commit 56dd0a0

File tree

4 files changed

+24
-10
lines changed

4 files changed

+24
-10
lines changed

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
**3.2.11 - 12/23/24**
2+
3+
- Type-hinting: Fix mypy errors in vivarium/framework/components/parser.py
4+
15
**3.2.10 - 12/17/24**
26

37
- Type-hinting: Fix mypy errors in vivarium/framework/components/manager.py

docs/nitpick-exceptions

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ py:class PandasObject
4242
py:class DataFrameGroupBy
4343
py:class ResultsFormatter
4444
py:class ResultsUpdater
45+
py:class _NestedDict
4546
py:exc ResultsConfigurationError
4647
py:exc vivarium.framework.results.exceptions.ResultsConfigurationError
4748

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ exclude = [
4444
'src/vivarium/examples/disease_model/observer.py',
4545
'src/vivarium/examples/disease_model/population.py',
4646
'src/vivarium/examples/disease_model/risk.py',
47-
'src/vivarium/framework/components/parser.py',
4847
'src/vivarium/framework/engine.py',
4948
'src/vivarium/framework/population/manager.py',
5049
'src/vivarium/framework/population/population_view.py',

src/vivarium/framework/components/parser.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# mypy: ignore-errors
21
"""
32
==================================
43
The Component Configuration Parser
@@ -22,13 +21,17 @@
2221
2322
"""
2423

24+
from typing import Union
25+
2526
from layered_config_tree.main import LayeredConfigTree
2627

2728
from vivarium.framework.utilities import import_by_path
2829

2930
from ... import Component
3031
from .manager import ComponentConfigError
3132

33+
_NestedDict = dict[str, Union[str, list[str], "_NestedDict"]]
34+
3235

3336
class ParsingError(ComponentConfigError):
3437
"""Error raised when component configurations are not specified correctly."""
@@ -117,7 +120,7 @@ def parse_component_config(self, component_config: LayeredConfigTree) -> list[Co
117120
return self.process_level(component_config.to_dict(), [])
118121

119122
def process_level(
120-
self, level: str | list[str] | dict[str, dict | list], prefix: list[str]
123+
self, level: str | list[str] | _NestedDict, prefix: list[str]
121124
) -> list[Component]:
122125
"""Helper function for parsing hierarchical component configuration into a
123126
flat list of Components.
@@ -173,8 +176,8 @@ def process_level(
173176
component_list.extend(components)
174177
elif isinstance(level, list):
175178
for child in level:
176-
component = self.process_level(child, prefix)
177-
component_list.extend(component)
179+
component_from_list = self.process_level(child, prefix)
180+
component_list.extend(component_from_list)
178181
elif isinstance(level, str):
179182
component = self.create_component_from_string(".".join(prefix + [level]))
180183
component_list.append(component)
@@ -206,7 +209,7 @@ def create_component_from_string(self, component_string: str) -> Component:
206209
component = self.import_and_instantiate_component(component_path, args)
207210
return component
208211

209-
def prep_component(self, component_string: str) -> tuple[str, tuple]:
212+
def prep_component(self, component_string: str) -> tuple[str, tuple[str, ...]]:
210213
"""Transform component description string into a tuple of component paths
211214
and required arguments.
212215
@@ -224,14 +227,14 @@ def prep_component(self, component_string: str) -> tuple[str, tuple]:
224227
return path, cleaned_args
225228

226229
@staticmethod
227-
def _clean_args(args: list, path: str) -> tuple:
230+
def _clean_args(args: list[str], path: str) -> tuple[str, ...]:
228231
"""Transform component arguments into a tuple, validating that each argument
229232
is a string.
230233
231234
Parameters
232235
----------
233236
args
234-
List of arguments to the component specified at ``path``.
237+
Tuple of arguments to the component specified at ``path``.
235238
path
236239
Path representing the component for which arguments are being cleaned.
237240
@@ -255,7 +258,9 @@ def _clean_args(args: list, path: str) -> tuple:
255258
return tuple(out)
256259

257260
@staticmethod
258-
def import_and_instantiate_component(component_path: str, args: tuple[str]) -> Component:
261+
def import_and_instantiate_component(
262+
component_path: str, args: tuple[str, ...]
263+
) -> Component:
259264
"""Transform a tuple representing a Component into an actual instantiated
260265
component object.
261266
@@ -271,4 +276,9 @@ def import_and_instantiate_component(component_path: str, args: tuple[str]) -> C
271276
-------
272277
An instantiated component object.
273278
"""
274-
return import_by_path(component_path)(*args)
279+
component = import_by_path(component_path)(*args)
280+
if not isinstance(component, Component):
281+
raise ImportError(
282+
f"Attempted to import f{component_path}, which is not a component."
283+
)
284+
return component

0 commit comments

Comments
 (0)