Skip to content

Commit 637ccb6

Browse files
albertsolaCopilot
andcommitted
MPT-17888: add first-level field annotations to Parameter and ParameterGroup models
Add type-annotated fields to the Parameter and ParameterGroup model classes derived from the OpenAPI spec (ParameterDefinition and ParameterGroup schemas respectively). All fields are typed as T | None since RQL select can exclude any field from the API response. Nested objects (audit, group, product, constraints, options) are typed as BaseModel | None as no dedicated sub-model classes exist for them yet. Parameter fields: name, description, scope, phase, context, type, status, external_id, display_order, group, product, constraints, audit, options. ParameterGroup fields: name, label, description, display_order, default, parameter_count, product, audit. Also extends unit tests for both models to cover field access, nested BaseModel typing, and optional field absence. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent f0bf751 commit 637ccb6

5 files changed

Lines changed: 169 additions & 3 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ cython_debug/
166166
.DS_Store
167167
.ruff_cache
168168
.idea
169-
169+
.openapi/
170170
# Makefile
171171
make/local.mk
172172

mpt_api_client/resources/catalog/products_parameter_groups.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,31 @@
66
ManagedResourceMixin,
77
)
88
from mpt_api_client.models import Model
9+
from mpt_api_client.models.model import BaseModel
910

1011

1112
class ParameterGroup(Model):
12-
"""Parameter Group resource."""
13+
"""Parameter Group resource.
14+
15+
Attributes:
16+
name: Parameter group name.
17+
label: Display label for the parameter group.
18+
description: Parameter group description.
19+
display_order: Display order of the group.
20+
default: Whether this is the default parameter group.
21+
parameter_count: Number of parameters in this group.
22+
product: Reference to the product this group belongs to.
23+
audit: Audit information (created, updated events).
24+
"""
25+
26+
name: str | None
27+
label: str | None
28+
description: str | None
29+
display_order: int | None
30+
default: bool | None
31+
parameter_count: int | None
32+
product: BaseModel | None
33+
audit: BaseModel | None
1334

1435

1536
class ParameterGroupsServiceConfig:

mpt_api_client/resources/catalog/products_parameters.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,43 @@
66
ManagedResourceMixin,
77
)
88
from mpt_api_client.models import Model
9+
from mpt_api_client.models.model import BaseModel
910

1011

1112
class Parameter(Model):
12-
"""Parameter resource."""
13+
"""Parameter resource.
14+
15+
Attributes:
16+
name: Parameter name.
17+
description: Parameter description.
18+
scope: Parameter scope (e.g. Agreement, Item, Request, Subscription, Order, Asset).
19+
phase: Parameter phase (e.g. Configuration, Order, Fulfillment).
20+
context: Parameter context (e.g. None, Purchase, Change, Configuration, Termination).
21+
type: Parameter type (e.g. SingleLineText, MultiLineText, Address, etc.).
22+
status: Parameter status.
23+
external_id: External identifier for the parameter.
24+
display_order: Display order of the parameter.
25+
group: Reference to the parameter group.
26+
product: Reference to the product this parameter belongs to.
27+
constraints: Parameter constraints (required, hidden, readonly).
28+
audit: Audit information (created, updated events).
29+
options: Type-specific parameter options.
30+
"""
31+
32+
name: str | None
33+
description: str | None
34+
scope: str | None
35+
phase: str | None
36+
context: str | None
37+
type: str | None
38+
status: str | None
39+
external_id: str | None
40+
display_order: int | None
41+
group: BaseModel | None
42+
product: BaseModel | None
43+
constraints: BaseModel | None
44+
audit: BaseModel | None
45+
options: BaseModel | None
1346

1447

1548
class ParametersServiceConfig:

tests/unit/resources/catalog/test_products_parameter_groups.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import pytest
22

3+
from mpt_api_client.models.model import BaseModel
34
from mpt_api_client.resources.catalog.products_parameter_groups import (
45
AsyncParameterGroupsService,
6+
ParameterGroup,
57
ParameterGroupsService,
68
)
79

@@ -20,6 +22,24 @@ def async_parameter_groups_service(async_http_client):
2022
)
2123

2224

25+
@pytest.fixture
26+
def parameter_group_data():
27+
return {
28+
"id": "GRP-001",
29+
"name": "General",
30+
"label": "General Settings",
31+
"description": "General configuration parameters",
32+
"displayOrder": 1,
33+
"default": True,
34+
"parameterCount": 5,
35+
"product": {"id": "PRD-001", "name": "My Product"},
36+
"audit": {
37+
"created": {"at": "2024-01-01T00:00:00Z"},
38+
"updated": {"at": "2024-01-02T00:00:00Z"},
39+
},
40+
}
41+
42+
2343
def test_endpoint(parameter_groups_service):
2444
result = parameter_groups_service.path == "/public/v1/catalog/products/PRD-001/parameter-groups"
2545

@@ -47,3 +67,33 @@ def test_async_methods_present(async_parameter_groups_service, method):
4767
result = hasattr(async_parameter_groups_service, method)
4868

4969
assert result is True
70+
71+
72+
def test_parameter_group_primitive_fields(parameter_group_data):
73+
result = ParameterGroup(parameter_group_data)
74+
75+
assert result.to_dict() == parameter_group_data
76+
77+
78+
def test_parameter_group_nested_field_types(parameter_group_data):
79+
result = ParameterGroup(parameter_group_data)
80+
81+
assert isinstance(result.product, BaseModel)
82+
assert isinstance(result.audit, BaseModel)
83+
84+
85+
def test_parameter_group_nested_field_values(parameter_group_data):
86+
result = ParameterGroup(parameter_group_data)
87+
88+
assert result.product.id == "PRD-001"
89+
assert result.product.name == "My Product"
90+
91+
92+
def test_parameter_group_optional_fields_absent():
93+
result = ParameterGroup({"id": "GRP-002"})
94+
95+
assert result.id == "GRP-002"
96+
assert not hasattr(result, "name")
97+
assert not hasattr(result, "label")
98+
assert not hasattr(result, "product")
99+
assert not hasattr(result, "audit")

tests/unit/resources/catalog/test_products_parameters.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import pytest
22

3+
from mpt_api_client.models.model import BaseModel
34
from mpt_api_client.resources.catalog.products_parameters import (
45
AsyncParametersService,
6+
Parameter,
57
ParametersService,
68
)
79

@@ -18,6 +20,30 @@ def async_parameters_service(async_http_client):
1820
)
1921

2022

23+
@pytest.fixture
24+
def parameter_data():
25+
return {
26+
"id": "PRM-001",
27+
"name": "Tenant Name",
28+
"description": "The tenant name",
29+
"scope": "Agreement",
30+
"phase": "Configuration",
31+
"context": "Purchase",
32+
"type": "SingleLineText",
33+
"status": "Active",
34+
"externalId": "ext-001",
35+
"displayOrder": 1,
36+
"group": {"id": "GRP-001", "name": "General"},
37+
"product": {"id": "PRD-001", "name": "My Product"},
38+
"constraints": {"required": True, "hidden": False, "readonly": False},
39+
"audit": {
40+
"created": {"at": "2024-01-01T00:00:00Z"},
41+
"updated": {"at": "2024-01-02T00:00:00Z"},
42+
},
43+
"options": {"placeholder": "Enter tenant name"},
44+
}
45+
46+
2147
def test_endpoint(parameters_service):
2248
result = parameters_service.path == "/public/v1/catalog/products/PRD-001/parameters"
2349

@@ -42,3 +68,39 @@ def test_async_methods_present(async_parameters_service, method):
4268
result = hasattr(async_parameters_service, method)
4369

4470
assert result is True
71+
72+
73+
def test_parameter_primitive_fields(parameter_data):
74+
result = Parameter(parameter_data)
75+
76+
assert result.to_dict() == parameter_data
77+
78+
79+
def test_parameter_nested_fields_are_base_models(parameter_data):
80+
result = Parameter(parameter_data)
81+
82+
assert isinstance(result.group, BaseModel)
83+
assert isinstance(result.product, BaseModel)
84+
assert isinstance(result.constraints, BaseModel)
85+
assert isinstance(result.audit, BaseModel)
86+
assert isinstance(result.options, BaseModel)
87+
88+
89+
def test_parameter_nested_field_values(parameter_data):
90+
result = Parameter(parameter_data)
91+
92+
assert result.group.id == "GRP-001"
93+
assert result.group.name == "General"
94+
assert result.product.id == "PRD-001"
95+
assert result.constraints.required is True
96+
assert result.constraints.hidden is False
97+
98+
99+
def test_parameter_optional_fields_absent():
100+
result = Parameter({"id": "PRM-002"})
101+
102+
assert result.id == "PRM-002"
103+
assert not hasattr(result, "name")
104+
assert not hasattr(result, "scope")
105+
assert not hasattr(result, "group")
106+
assert not hasattr(result, "options")

0 commit comments

Comments
 (0)