|
2 | 2 |
|
3 | 3 | from __future__ import annotations |
4 | 4 |
|
5 | | -from typing import Any, Literal |
| 5 | +from typing import Annotated, Any, Literal |
6 | 6 |
|
7 | 7 | from pydantic import BaseModel, ConfigDict, Field |
8 | 8 |
|
9 | 9 |
|
10 | | -class ComputedAttributeWrite(BaseModel): |
| 10 | +class AttributeParametersWrite(BaseModel): |
11 | 11 | model_config = ConfigDict(extra="forbid") |
12 | | - kind: Literal["User", "Jinja2", "TransformPython"] = Field( |
| 12 | + |
| 13 | + |
| 14 | +class ListAttributeParametersWrite(AttributeParametersWrite): |
| 15 | + model_config = ConfigDict(extra="forbid") |
| 16 | + regex: str | None = Field( |
| 17 | + default=None, |
| 18 | + description="Regular expression that each list item value must match if defined", |
| 19 | + ) |
| 20 | + |
| 21 | + |
| 22 | +class TextAttributeParametersWrite(AttributeParametersWrite): |
| 23 | + model_config = ConfigDict(extra="forbid") |
| 24 | + regex: str | None = Field( |
| 25 | + default=None, |
| 26 | + description="Regular expression that attribute value must match if defined", |
| 27 | + ) |
| 28 | + min_length: int | None = Field( |
| 29 | + default=None, |
| 30 | + description="Set a minimum number of characters allowed.", |
| 31 | + ) |
| 32 | + max_length: int | None = Field( |
| 33 | + default=None, |
| 34 | + description="Set a maximum number of characters allowed.", |
| 35 | + ) |
| 36 | + |
| 37 | + |
| 38 | +class NumberAttributeParametersWrite(AttributeParametersWrite): |
| 39 | + model_config = ConfigDict(extra="forbid") |
| 40 | + min_value: int | None = Field( |
| 41 | + default=None, |
| 42 | + description="Set a minimum value allowed.", |
| 43 | + ) |
| 44 | + max_value: int | None = Field( |
| 45 | + default=None, |
| 46 | + description="Set a maximum value allowed.", |
| 47 | + ) |
| 48 | + excluded_values: str | None = Field( |
| 49 | + default=None, |
| 50 | + description="List of values or range of values not allowed for the attribute, format is: '100,150-200,280,300-400'", |
| 51 | + pattern=r"^(\d+(?:-\d+)?)(?:,\d+(?:-\d+)?)*$", |
| 52 | + ) |
| 53 | + |
| 54 | + |
| 55 | +class NumberPoolParametersWrite(AttributeParametersWrite): |
| 56 | + model_config = ConfigDict(extra="forbid") |
| 57 | + end_range: int = Field( |
| 58 | + default=9223372036854775807, |
| 59 | + description="End range for numbers for the associated NumberPool", |
| 60 | + ) |
| 61 | + start_range: int = Field( |
| 62 | + default=1, |
| 63 | + description="Start range for numbers for the associated NumberPool", |
| 64 | + ) |
| 65 | + number_pool_id: str | None = Field( |
| 66 | + default=None, |
| 67 | + description="The ID of the numberpool associated with this attribute. Only set after the number pool has been provisioned.", |
| 68 | + ) |
| 69 | + |
| 70 | + |
| 71 | +class DropdownChoiceWrite(BaseModel): |
| 72 | + model_config = ConfigDict(extra="forbid") |
| 73 | + name: str = Field( |
13 | 74 | ..., |
14 | | - description="Defines how the value of the attribute is computed.", |
| 75 | + description="Name of the choice, must be unique within the dropdown.", |
15 | 76 | ) |
16 | | - jinja2_template: str | None = Field( |
| 77 | + description: str | None = Field( |
17 | 78 | default=None, |
18 | | - description="Jinja2 template used to compute the value, required when kind is Jinja2.", |
| 79 | + description="Description of the choice.", |
| 80 | + ) |
| 81 | + color: str | None = Field( |
| 82 | + default=None, |
| 83 | + description="Color of the choice, must be a valid HTML color code.", |
| 84 | + pattern=r"#[0-9a-fA-F]{6}\b", |
19 | 85 | ) |
20 | | - transform: str | None = Field( |
| 86 | + label: str | None = Field( |
21 | 87 | default=None, |
| 88 | + description="Human friendly representation of the choice.", |
| 89 | + ) |
| 90 | + |
| 91 | + |
| 92 | +class ComputedAttributeUserWrite(BaseModel): |
| 93 | + model_config = ConfigDict(extra="forbid") |
| 94 | + kind: Literal["User"] = Field( |
| 95 | + ..., |
| 96 | + description="Defines how the value of the attribute is computed.", |
| 97 | + ) |
| 98 | + |
| 99 | + |
| 100 | +class ComputedAttributeJinja2Write(BaseModel): |
| 101 | + model_config = ConfigDict(extra="forbid") |
| 102 | + kind: Literal["Jinja2"] = Field( |
| 103 | + ..., |
| 104 | + description="Defines how the value of the attribute is computed.", |
| 105 | + ) |
| 106 | + jinja2_template: str = Field( |
| 107 | + ..., |
| 108 | + description="Jinja2 template used to compute the value, required when kind is Jinja2.", |
| 109 | + ) |
| 110 | + |
| 111 | + |
| 112 | +class ComputedAttributeTransformPythonWrite(BaseModel): |
| 113 | + model_config = ConfigDict(extra="forbid") |
| 114 | + kind: Literal["TransformPython"] = Field( |
| 115 | + ..., |
| 116 | + description="Defines how the value of the attribute is computed.", |
| 117 | + ) |
| 118 | + transform: str = Field( |
| 119 | + ..., |
22 | 120 | description="Python transform name or ID, required when kind is TransformPython.", |
23 | 121 | ) |
24 | 122 |
|
25 | 123 |
|
| 124 | +AttributeParametersUnionWrite = ( |
| 125 | + NumberPoolParametersWrite |
| 126 | + | NumberAttributeParametersWrite |
| 127 | + | TextAttributeParametersWrite |
| 128 | + | ListAttributeParametersWrite |
| 129 | + | AttributeParametersWrite |
| 130 | +) |
| 131 | + |
| 132 | +ComputedAttributeWrite = Annotated[ |
| 133 | + ComputedAttributeUserWrite | ComputedAttributeJinja2Write | ComputedAttributeTransformPythonWrite, |
| 134 | + Field(discriminator="kind"), |
| 135 | +] |
| 136 | + |
| 137 | + |
26 | 138 | class AttributeSchemaWrite(BaseModel): |
27 | 139 | model_config = ConfigDict(extra="forbid") |
28 | 140 | id: str | None = Field( |
@@ -71,7 +183,7 @@ class AttributeSchemaWrite(BaseModel): |
71 | 183 | default=None, |
72 | 184 | description="Defines how the value of this attribute will be populated.", |
73 | 185 | ) |
74 | | - choices: list[dict[str, Any]] | None = Field( |
| 186 | + choices: list[DropdownChoiceWrite] | None = Field( |
75 | 187 | default=None, |
76 | 188 | description="Define a list of valid choices for a dropdown attribute.", |
77 | 189 | ) |
@@ -129,7 +241,7 @@ class AttributeSchemaWrite(BaseModel): |
129 | 241 | default="any", |
130 | 242 | description="Type of allowed override for the attribute.", |
131 | 243 | ) |
132 | | - parameters: dict[str, Any] | None = Field( |
| 244 | + parameters: AttributeParametersUnionWrite | None = Field( |
133 | 245 | default=None, |
134 | 246 | description="Extra parameters specific to this kind of attribute", |
135 | 247 | ) |
@@ -160,7 +272,7 @@ class RelationshipSchemaWrite(BaseModel): |
160 | 272 | peer: str = Field( |
161 | 273 | ..., |
162 | 274 | description="Type (kind) of objects supported on the other end of the relationship.", |
163 | | - pattern="^[A-Z][a-zA-Z0-9]+$", |
| 275 | + pattern=r"^[A-Z][a-zA-Z0-9]+$", |
164 | 276 | ) |
165 | 277 | kind: Literal["Generic", "Attribute", "Component", "Parent", "Group", "Hierarchy", "Profile", "Template"] = Field( |
166 | 278 | default="Generic", |
@@ -254,14 +366,14 @@ class BaseNodeSchemaWrite(BaseModel): |
254 | 366 | name: str = Field( |
255 | 367 | ..., |
256 | 368 | description="Node name, must be unique within a namespace and must start with an uppercase letter.", |
257 | | - pattern="^[A-Z][a-zA-Z0-9]+$", |
| 369 | + pattern=r"^[A-Z][a-zA-Z0-9]+$", |
258 | 370 | min_length=2, |
259 | 371 | max_length=32, |
260 | 372 | ) |
261 | 373 | namespace: str = Field( |
262 | 374 | ..., |
263 | 375 | description="Node Namespace, Namespaces are used to organize models into logical groups and to prevent name collisions.", |
264 | | - pattern="^[A-Z][a-z0-9]+$", |
| 376 | + pattern=r"^[A-Z][a-z0-9]+$", |
265 | 377 | min_length=3, |
266 | 378 | max_length=64, |
267 | 379 | ) |
|
0 commit comments