Skip to content

Commit dc7bb9a

Browse files
authored
Release 0.4.0 for 25.8.1 (#5)
* use ruff out of band and copy venv * generated models * added table * added replace for - in version * generated from 25.8.1 GA
1 parent 6bc9958 commit dc7bb9a

File tree

32 files changed

+19835
-912
lines changed

32 files changed

+19835
-912
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ Pydantic models for EDA OpenAPI spec. Models are generated for the EDA Core API
88

99
Install dev dependencies:
1010

11-
```
11+
```bash
1212
uv sync --all-groups
1313
```
1414

1515
Generate models for a specific version of the openapi repo (git ref):
1616

17-
```
17+
```bash
1818
python gen_models.py --version v25.4.1
1919
```
2020

@@ -31,3 +31,4 @@ The following table matches the project version with the version of the EDA deli
3131
| pydantic_eda | EDA release |
3232
| ------------ | ----------- |
3333
| 0.3.2 | 25.4.1 |
34+
| 0.4.0 | 25.8.1 |

gen_models.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import argparse
44
import json
55
import logging
6+
import os
67
import shutil
78
import subprocess
89
import sys
@@ -95,7 +96,7 @@ def process_specs(self):
9596
api_name = "core"
9697
# core api has a v0.0.1 in the spec but that will change
9798
# for now use the version provided by a user from the cmd
98-
api_version = self.version.replace(".", "_")
99+
api_version = self.version.replace(".", "_").replace("-", "_")
99100
logger.debug(f"API name: {api_name}, API version: {api_version}")
100101
self.sanitize_schema_objects(spec_file, api_name, api_version)
101102
self.generate_classes_for_spec(spec_file, api_name, api_version)
@@ -135,8 +136,9 @@ def generate_classes_for_spec(
135136
"schemas",
136137
"--output-model-type",
137138
"pydantic_v2.BaseModel",
138-
"--formatters",
139-
"ruff-format",
139+
# we will format manually using ruff in the venv
140+
# "--formatters",
141+
# "ruff-format",
140142
"--use-annotated",
141143
"--parent-scoped-naming",
142144
"--collapse-root-models",
@@ -159,7 +161,23 @@ def generate_classes_for_spec(
159161

160162
try:
161163
logger.info(f"Generating models for {spec_file}...")
162-
subprocess.run(cmd, check=True)
164+
165+
# Create environment with explicit path to virtual env binaries
166+
env = os.environ.copy()
167+
venv_path = os.environ.get("VIRTUAL_ENV", ".venv")
168+
venv_bin = Path(venv_path) / "bin"
169+
170+
# Prepend venv bin directory to PATH
171+
current_path = env.get("PATH", "")
172+
env["PATH"] = f"{venv_bin}:{current_path}"
173+
174+
subprocess.run(cmd, check=True, env=env)
175+
176+
# Format the generated file with ruff
177+
logger.debug(f"Formatting {dest_file} with ruff...")
178+
ruff_cmd = ["ruff", "format", str(dest_file)]
179+
subprocess.run(ruff_cmd, check=True, env=env)
180+
163181
except subprocess.CalledProcessError as e:
164182
logger.error(f"Error generating models for {spec_file}: {e}")
165183

pydantic_eda/apps/aaa/v1alpha1/models.py

Lines changed: 125 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
# filename: aaa.json
33

44
from __future__ import annotations
5+
56
from typing import Annotated, Any, Dict, List, Literal, Optional
6-
from pydantic import BaseModel, Field, RootModel
7+
8+
from pydantic import AwareDatetime, BaseModel, Field, RootModel
79

810

911
class AppGroupVersion(BaseModel):
@@ -37,6 +39,12 @@ class ErrorResponse(BaseModel):
3739
description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.'
3840
),
3941
] = None
42+
domain: Annotated[
43+
Optional[str],
44+
Field(
45+
description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.'
46+
),
47+
] = None
4048
errors: Annotated[
4149
Optional[List[ErrorItem]],
4250
Field(
@@ -91,7 +99,7 @@ class Resource(BaseModel):
9199
class ResourceHistoryEntry(BaseModel):
92100
author: Optional[str] = None
93101
changeType: Optional[str] = None
94-
commitTime: Optional[str] = None
102+
commitTime: Optional[AwareDatetime] = None
95103
hash: Optional[str] = None
96104
message: Optional[str] = None
97105
transactionId: Optional[int] = None
@@ -110,6 +118,43 @@ class StatusDetails(BaseModel):
110118
name: Optional[str] = None
111119

112120

121+
class TopoAttrMetadata(BaseModel):
122+
type: Optional[str] = None
123+
ui_description: Optional[str] = None
124+
ui_description_key: Optional[str] = None
125+
ui_name: Optional[str] = None
126+
ui_name_key: Optional[str] = None
127+
128+
129+
class TopoLinkEndpoint(BaseModel):
130+
endpoint: Optional[str] = None
131+
node: Optional[str] = None
132+
node_key: Optional[str] = None
133+
134+
135+
class TopoNodeGrouping(BaseModel):
136+
group: Optional[str] = None
137+
tier: Optional[int] = None
138+
139+
140+
class TopoOverlayEndpointState(BaseModel):
141+
state: Optional[int] = None
142+
143+
144+
TopoOverlayLinkState = TopoOverlayEndpointState
145+
146+
147+
class TopoOverlayNodeState(BaseModel):
148+
badges: Optional[List[int]] = None
149+
state: Optional[int] = None
150+
151+
152+
class TopoSchema(BaseModel):
153+
group: Optional[str] = None
154+
kind: Optional[str] = None
155+
version: Optional[str] = None
156+
157+
113158
class UIResult(RootModel[str]):
114159
root: str
115160

@@ -208,7 +253,7 @@ class NodeGroupStatus(BaseModel):
208253

209254

210255
class NodeGroupDeletedResourceEntry(BaseModel):
211-
commitTime: Optional[str] = None
256+
commitTime: Optional[AwareDatetime] = None
212257
hash: Optional[str] = None
213258
name: Optional[str] = None
214259
namespace: Optional[str] = None
@@ -251,13 +296,78 @@ class Status(BaseModel):
251296
string: Optional[str] = None
252297

253298

299+
class TopoElemMetadata(BaseModel):
300+
attributes: Optional[Dict[str, TopoAttrMetadata]] = None
301+
schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None
302+
subtitle: Optional[str] = None
303+
subtitle_key: Optional[str] = None
304+
305+
306+
class TopoOverlayEndpoint(BaseModel):
307+
attributes: Optional[Dict[str, Dict[str, Any]]] = None
308+
cr_name: Optional[str] = None
309+
labels: Optional[Dict[str, str]] = None
310+
name: Optional[str] = None
311+
namespace: Optional[str] = None
312+
overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None
313+
schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None
314+
state: Optional[int] = None
315+
ui_name: Optional[str] = None
316+
317+
318+
class TopoOverlayLink(BaseModel):
319+
attributes: Optional[Dict[str, Dict[str, Any]]] = None
320+
cr_name: Optional[str] = None
321+
endpoint_a: Optional[TopoLinkEndpoint] = None
322+
endpoint_a_details: Optional[TopoOverlayEndpoint] = None
323+
endpoint_b: Optional[TopoLinkEndpoint] = None
324+
endpoint_b_details: Optional[TopoOverlayEndpoint] = None
325+
key: Optional[str] = None
326+
labels: Optional[Dict[str, str]] = None
327+
name: Optional[str] = None
328+
namespace: Optional[str] = None
329+
overlays: Optional[Dict[str, TopoOverlayLinkState]] = None
330+
schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None
331+
state: Optional[int] = None
332+
ui_name: Optional[str] = None
333+
334+
335+
class TopoOverlayNode(BaseModel):
336+
attributes: Optional[Dict[str, Dict[str, Any]]] = None
337+
badges: Optional[List[int]] = None
338+
cr_name: Optional[str] = None
339+
grouping: Optional[TopoNodeGrouping] = None
340+
key: Optional[str] = None
341+
labels: Optional[Dict[str, str]] = None
342+
name: Optional[str] = None
343+
namespace: Optional[str] = None
344+
overlays: Optional[Dict[str, TopoOverlayNodeState]] = None
345+
schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None
346+
state: Optional[int] = None
347+
ui_name: Optional[str] = None
348+
349+
350+
class Topology(BaseModel):
351+
endpoints: Optional[TopoElemMetadata] = None
352+
group: Optional[str] = None
353+
grouping: Optional[TopoSchema] = None
354+
links: Optional[TopoElemMetadata] = None
355+
name: Optional[str] = None
356+
nodes: Optional[TopoElemMetadata] = None
357+
ui_description: Optional[str] = None
358+
ui_description_key: Optional[str] = None
359+
ui_name: Optional[str] = None
360+
ui_name_key: Optional[str] = None
361+
version: Optional[str] = None
362+
363+
254364
class NodeGroup(BaseModel):
255365
"""
256366
NodeGroup is the Schema for the nodegroups API
257367
"""
258368

259-
apiVersion: str
260-
kind: str
369+
apiVersion: Annotated[str, Field(pattern="^aaa\\.eda\\.nokia\\.com/v1alpha1$")]
370+
kind: Annotated[str, Field(pattern="^NodeGroup$")]
261371
metadata: NodeGroupMetadata
262372
spec: Annotated[
263373
NodeGroupSpec,
@@ -280,3 +390,13 @@ class NodeGroupList(BaseModel):
280390
apiVersion: str
281391
items: Optional[List[NodeGroup]] = None
282392
kind: str
393+
394+
395+
class OverlayState(BaseModel):
396+
links: Optional[Dict[str, TopoOverlayLink]] = None
397+
nodes: Optional[Dict[str, TopoOverlayNode]] = None
398+
399+
400+
class ResourceTopology(BaseModel):
401+
topology: Optional[OverlayState] = None
402+
topologyMetadata: Optional[Topology] = None

0 commit comments

Comments
 (0)