Skip to content

Commit ca598bd

Browse files
committed
added utests
1 parent 46fb227 commit ca598bd

File tree

7 files changed

+158
-16
lines changed

7 files changed

+158
-16
lines changed

nodescraper/cli/helper.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,33 @@ def extract_analyzer_args_from_model(
313313
return None
314314

315315

316+
def extract_collector_args_from_model(
317+
plugin_cls: type, data_model: BaseModel, logger: logging.Logger
318+
) -> Optional[BaseModel]:
319+
"""Extract collector args from a plugin and a data model.
320+
321+
Args:
322+
plugin_cls (type): The plugin class from registry.
323+
data_model (BaseModel): System data model.
324+
logger (logging.Logger): logger.
325+
326+
Returns:
327+
Optional[BaseModel]: Instance of collector args model or None if unavailable.
328+
"""
329+
if not hasattr(plugin_cls, "COLLECTOR_ARGS") or not plugin_cls.COLLECTOR_ARGS:
330+
logger.warning(
331+
"Plugin: %s does not support reference config creation. No collector args defined.",
332+
getattr(plugin_cls, "__name__", str(plugin_cls)),
333+
)
334+
return None
335+
336+
try:
337+
return plugin_cls.COLLECTOR_ARGS.build_from_model(data_model)
338+
except NotImplementedError as e:
339+
logger.info("%s: %s", plugin_cls.__name__, str(e))
340+
return None
341+
342+
316343
def generate_reference_config(
317344
results: list[PluginResult], plugin_reg: PluginRegistry, logger: logging.Logger
318345
) -> PluginConfig:
@@ -344,11 +371,16 @@ def generate_reference_config(
344371

345372
plugin = plugin_reg.plugins.get(obj.source)
346373

347-
args = extract_analyzer_args_from_model(plugin, data_model, logger)
348-
if not args:
349-
continue
350-
plugins[obj.source] = {"analysis_args": {}}
351-
plugins[obj.source]["analysis_args"] = args.model_dump(exclude_none=True)
374+
if obj.source not in plugins:
375+
plugins[obj.source] = {}
376+
377+
a_args = extract_analyzer_args_from_model(plugin, data_model, logger)
378+
if a_args:
379+
plugins[obj.source]["analysis_args"] = a_args.model_dump(exclude_none=True)
380+
381+
c_args = extract_collector_args_from_model(plugin, data_model, logger)
382+
if c_args:
383+
plugins[obj.source]["collector_args"] = c_args.model_dump(exclude_none=True)
352384
plugin_config.plugins = plugins
353385

354386
return plugin_config

nodescraper/models/analyzerargs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class AnalyzerArgs(BaseModel):
3131

3232
@classmethod
3333
def build_from_model(cls, datamodel):
34-
"""Build analyzer args instance from data model object
34+
"""Build collector args instance from data model object
3535
3636
Args:
3737
datamodel (TDataModel): data model to use for creating analyzer args
@@ -40,5 +40,5 @@ def build_from_model(cls, datamodel):
4040
NotImplementedError: Not implemented error
4141
"""
4242
raise NotImplementedError(
43-
"Setting analyzer args from datamodel is not implemented for class: %s", cls.__name__
43+
"Setting collector args from datamodel is not implemented for class: %s", cls.__name__
4444
)

nodescraper/models/collectorargs.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,22 @@
2323
# SOFTWARE.
2424
#
2525
###############################################################################
26-
from abc import ABC
27-
2826
from pydantic import BaseModel
2927

3028

31-
class CollectorArgs(BaseModel, ABC):
29+
class CollectorArgs(BaseModel):
3230
model_config = {"extra": "forbid", "exclude_none": True}
31+
32+
@classmethod
33+
def build_from_model(cls, datamodel):
34+
"""Build analyzer args instance from data model object
35+
36+
Args:
37+
datamodel (TDataModel): data model to use for creating analyzer args
38+
39+
Raises:
40+
NotImplementedError: Not implemented error
41+
"""
42+
raise NotImplementedError(
43+
"Setting analyzer args from datamodel is not implemented for class: %s", cls.__name__
44+
)

nodescraper/plugins/inband/process/collector_args.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,20 @@
2525
###############################################################################
2626

2727
from nodescraper.models import CollectorArgs
28+
from nodescraper.plugins.inband.process.processdata import ProcessDataModel
2829

2930

3031
class ProcessCollectorArgs(CollectorArgs):
3132
top_n_process: int = 10
3233

33-
model_config = {"extra": "forbid"}
34+
@classmethod
35+
def build_from_model(cls, datamodel: ProcessDataModel) -> "ProcessCollectorArgs":
36+
"""build analyzer args from data model
37+
38+
Args:
39+
datamodel (BiosDataModel): data model for plugin
40+
41+
Returns:
42+
ProcessCollectorArgs: instance of analyzer args class
43+
"""
44+
return cls(top_n_process=datamodel.kfd_process)

test/unit/framework/common/shared_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ class TestModelArg(AnalyzerArgs):
7272

7373
@classmethod
7474
def build_from_model(cls, model):
75-
return cls(model_attr=int(model.some_version))
75+
return cls(model_attr=int(model.foo))
7676

7777

7878
class DummyDataModel(DataModel):
79-
some_version: str = None
79+
foo: str = None
8080

8181

8282
class TestPluginA(PluginInterface[MockConnectionManager, None]):

test/unit/framework/test_cli_helper.py

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,17 @@
3131
from types import SimpleNamespace
3232

3333
import pytest
34-
from common.shared_utils import DummyDataModel
34+
35+
# from common.shared_utils import DummyDataModel
36+
from conftest import DummyDataModel
3537
from pydantic import BaseModel
3638

3739
from nodescraper.cli import cli
38-
from nodescraper.cli.helper import build_config, find_datamodel_and_result
40+
from nodescraper.cli.helper import (
41+
build_config,
42+
extract_collector_args_from_model,
43+
find_datamodel_and_result,
44+
)
3945
from nodescraper.configregistry import ConfigRegistry
4046
from nodescraper.enums import ExecutionStatus, SystemInteractionLevel
4147
from nodescraper.models import PluginConfig, TaskResult
@@ -50,7 +56,7 @@ def test_generate_reference_config(plugin_registry):
5056
source="TestPluginA",
5157
message="Plugin tasks completed successfully",
5258
result_data=DataPluginResult(
53-
system_data=DummyDataModel(some_version="17"),
59+
system_data=DummyDataModel(foo="17"),
5460
collection_result=TaskResult(
5561
status=ExecutionStatus.OK,
5662
message="BIOS: 17",
@@ -176,3 +182,59 @@ def build_from_model(cls, datamodel):
176182
assert isinstance(cfg, PluginConfig)
177183
assert set(cfg.plugins) == {parent}
178184
assert cfg.plugins[parent]["analysis_args"] == {}
185+
186+
187+
def test_no_collector_args_defined(caplog):
188+
class NoArgsPlugin:
189+
pass
190+
191+
caplog.set_level(logging.WARNING)
192+
res = extract_collector_args_from_model(
193+
NoArgsPlugin, DummyDataModel(foo=1), logging.getLogger()
194+
)
195+
assert res is None
196+
assert "does not support reference config creation" in caplog.text
197+
198+
199+
def test_collector_args_none(caplog):
200+
class NoneArgsPlugin:
201+
COLLECTOR_ARGS = None
202+
203+
caplog.set_level(logging.WARNING)
204+
res = extract_collector_args_from_model(
205+
NoneArgsPlugin, DummyDataModel(foo=1), logging.getLogger()
206+
)
207+
assert res is None
208+
assert "does not support reference config creation" in caplog.text
209+
210+
211+
def test_successful_build_from_model():
212+
class MyArgs(BaseModel):
213+
a: int
214+
215+
@classmethod
216+
def build_from_model(cls, dm):
217+
return cls(a=dm.foo)
218+
219+
class GoodPlugin:
220+
COLLECTOR_ARGS = MyArgs
221+
222+
dm = DummyDataModel(foo=42)
223+
args = extract_collector_args_from_model(GoodPlugin, dm, logging.getLogger())
224+
assert isinstance(args, MyArgs)
225+
assert args.a == 42
226+
227+
228+
def test_build_from_model_not_implemented(caplog):
229+
class BadArgs(BaseModel):
230+
@classmethod
231+
def build_from_model(cls, dm):
232+
raise NotImplementedError("not implemented")
233+
234+
class BadPlugin:
235+
COLLECTOR_ARGS = BadArgs
236+
237+
caplog.set_level(logging.INFO)
238+
res = extract_collector_args_from_model(BadPlugin, DummyDataModel(foo=7), logging.getLogger())
239+
assert res is None
240+
assert "not implemented" in caplog.text
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import pytest
2+
3+
from nodescraper.models import CollectorArgs
4+
5+
6+
class MyArgs(CollectorArgs):
7+
args_foo: int
8+
9+
@classmethod
10+
def build_from_model(cls, datamodel):
11+
return cls(args_foo=datamodel.foo)
12+
13+
14+
def test_build_from_model(dummy_data_model):
15+
dummy = dummy_data_model(foo=1)
16+
args = MyArgs.build_from_model(dummy)
17+
assert isinstance(args, MyArgs)
18+
assert args.args_foo == dummy.foo
19+
dump = args.model_dump(mode="json", exclude_none=True)
20+
assert dump == {"args_foo": 1}
21+
22+
23+
def test_base_build_from_model_not_implemented():
24+
with pytest.raises(NotImplementedError):
25+
CollectorArgs.build_from_model("anything")

0 commit comments

Comments
 (0)