Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ dist/*

# Generated files
generated/
# Committed, generated schema models (write/read variants) must be version-controlled.
!infrahub_sdk/schema/generated/
!infrahub_sdk/schema/generated/*.py
sandbox/

# SpecKit internal cache
Expand Down
7 changes: 7 additions & 0 deletions changelog/+infp-234-sdk-schema-models.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
**Breaking:** The hand-maintained schema models in `infrahub_sdk.schema` are now backed by the generated write/read contract (`infrahub_sdk.schema.generated`). Public names, import paths, and behavior methods are unchanged, but a few defaults and constraints now match the server contract:

- `AttributeKind.STRING` has been removed. It was deprecated and `kind="String"` was already rejected server-side; use `AttributeKind.TEXT` instead.
- Write models now reject unknown fields (`extra="forbid"`).
- Write-model defaults now match the server contract: relationship `min_count`/`max_count` default to `0` (was `None`), node `branch` defaults to `"aware"`, `generate_profile` defaults to `True`, and `generate_template` defaults to `False`. This changes the round-trip output of programmatically-built schemas.

Constructing `AttributeSchema(name=..., kind=AttributeKind.TEXT, ...)`, `NodeSchema`, `GenericSchema`, `RelationshipSchema`, `SchemaRoot`, and the read-side `*API` models continues to work unchanged.
4 changes: 2 additions & 2 deletions infrahub_sdk/protocols_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from .context import RequestContext
from .node.metadata import NodeMetadata
from .schema import MainSchemaTypes
from .schema import MainSchemaTypesAPI


@runtime_checkable
Expand Down Expand Up @@ -173,7 +173,7 @@ class AnyAttributeOptional(Attribute):


class CoreNodeBase:
_schema: MainSchemaTypes
_schema: MainSchemaTypesAPI
_internal_id: str
id: str # NOTE this is incorrect, should be str | None
display_label: str | None
Expand Down
10 changes: 9 additions & 1 deletion infrahub_sdk/schema/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
from ..protocols_base import CoreNodeBase
from ..queries import SCHEMA_HASH_SYNC_STATUS
from .export import RESTRICTED_NAMESPACES, NamespaceExport, SchemaExport, schema_to_export_dict
from .generated.read import InfrahubSchemaRead
from .generated.write import InfrahubSchemaWrite
from .main import (
AttributeSchema,
AttributeSchemaAPI,
Expand All @@ -42,6 +44,7 @@
SchemaRootAPI,
TemplateSchemaAPI,
)
from .validate import SchemaValidationErrorDetail, SchemaValidationResult, validate_schema

if TYPE_CHECKING:
from ..client import InfrahubClient, InfrahubClientSync, SchemaType, SchemaTypeSync
Expand All @@ -56,6 +59,8 @@
"BranchSupportType",
"GenericSchema",
"GenericSchemaAPI",
"InfrahubSchemaRead",
"InfrahubSchemaWrite",
"NamespaceExport",
"NodeSchema",
"NodeSchemaAPI",
Expand All @@ -67,8 +72,11 @@
"SchemaExport",
"SchemaRoot",
"SchemaRootAPI",
"SchemaValidationErrorDetail",
"SchemaValidationResult",
"TemplateSchemaAPI",
"schema_to_export_dict",
"validate_schema",
]


Expand Down Expand Up @@ -408,7 +416,7 @@ async def check(self, schemas: list[dict], branch: str | None = None) -> tuple[b

async def _get_kind_and_attribute_schema(
self, kind: str | InfrahubNodeTypes, attribute: str, branch: str | None = None
) -> tuple[str, AttributeSchema]:
) -> tuple[str, AttributeSchemaAPI]:
node_kind: str = kind._schema.kind if not isinstance(kind, str) else kind
node_schema = await self.client.schema.get(kind=node_kind, branch=branch)
schema_attr = node_schema.get_attribute(name=attribute)
Expand Down
4 changes: 4 additions & 0 deletions infrahub_sdk/schema/generated/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Generated by "invoke backend.generate", do not edit directly
from . import enums, read, write

__all__ = ["enums", "read", "write"]
84 changes: 84 additions & 0 deletions infrahub_sdk/schema/generated/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Generated by "invoke backend.generate", do not edit directly

from __future__ import annotations

from enum import Enum


class BranchSupportType(str, Enum):
AWARE = "aware"
AGNOSTIC = "agnostic"
LOCAL = "local"


class RelationshipKind(str, Enum):
GENERIC = "Generic"
ATTRIBUTE = "Attribute"
COMPONENT = "Component"
PARENT = "Parent"
GROUP = "Group"
HIERARCHY = "Hierarchy"
PROFILE = "Profile"
TEMPLATE = "Template"


class RelationshipCardinality(str, Enum):
ONE = "one"
MANY = "many"


class RelationshipDirection(str, Enum):
BIDIR = "bidirectional"
OUTBOUND = "outbound"
INBOUND = "inbound"


class RelationshipDeleteBehavior(str, Enum):
NO_ACTION = "no-action"
CASCADE = "cascade"


class AllowOverrideType(str, Enum):
NONE = "none"
ANY = "any"


class SchemaState(str, Enum):
PRESENT = "present"
ABSENT = "absent"


class SchemaAttributeDisplay(str, Enum):
DEFAULT = "default"
EXTRA = "extra"


class ComputedAttributeKind(str, Enum):
USER = "User"
JINJA2 = "Jinja2"
TRANSFORM_PYTHON = "TransformPython"


class AttributeKind(str, Enum):
ID = "ID"
DROPDOWN = "Dropdown"
TEXT = "Text"
TEXTAREA = "TextArea"
DATETIME = "DateTime"
EMAIL = "Email"
PASSWORD = "Password"
HASHEDPASSWORD = "HashedPassword"
URL = "URL"
FILE = "File"
MAC_ADDRESS = "MacAddress"
COLOR = "Color"
NUMBER = "Number"
NUMBERPOOL = "NumberPool"
BANDWIDTH = "Bandwidth"
IPHOST = "IPHost"
IPNETWORK = "IPNetwork"
BOOLEAN = "Boolean"
CHECKBOX = "Checkbox"
LIST = "List"
JSON = "JSON"
ANY = "Any"
Loading