-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3983ad6
commit e6507ae
Showing
7 changed files
with
425 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,329 @@ | ||
"""NXDL models""" | ||
|
||
from typing import Optional, Union, List | ||
|
||
import pydantic | ||
|
||
|
||
class Item(pydantic.BaseModel): | ||
|
||
class Config: | ||
extra = "forbid" | ||
|
||
|
||
class EnumerationItem(Item): | ||
value: str | ||
doc: Optional[str] = None | ||
|
||
|
||
class Enumeration(Item): | ||
item: List[EnumerationItem] | ||
|
||
|
||
class DimensionItem(Item): | ||
index: int | ||
required: bool | ||
value: Optional[str] = None | ||
ref: Optional[str] = None | ||
|
||
|
||
class DocDimensionItem(Item): | ||
index: str | ||
value: str | ||
|
||
|
||
class DocDimensions(Item): | ||
dim: List[DocDimensionItem] | ||
|
||
|
||
class Dimensions(Item): | ||
rank: Optional[Union[int, str]] = None | ||
dim: Optional[List[DimensionItem]] = None | ||
doc: Optional[Union[DocDimensions, str]] = None | ||
|
||
|
||
class Attribute(Item): | ||
name: str | ||
type: str | ||
doc: Optional[str] = None | ||
recommended: Optional[bool] = None | ||
optional: Optional[bool] = None | ||
dimensions: Optional[Dimensions] = None | ||
enumeration: Optional[Enumeration] = None | ||
deprecated: Optional[str] = None | ||
|
||
|
||
class Field(Item): | ||
name: str | ||
type: str | ||
nameType: Optional[str] = None | ||
units: Optional[str] = None | ||
signal: Optional[int] = None | ||
axis: Optional[int] = None | ||
primary: Optional[int] = None | ||
axes: Optional[str] = None | ||
doc: Optional[str] = None | ||
recommended: Optional[bool] = None | ||
optional: Optional[bool] = None | ||
minOccurs: Optional[int] = None | ||
maxOccurs: Optional[Union[int, str]] = None | ||
stride: Optional[bool] = None | ||
data_offset: Optional[bool] = None | ||
dimensions: Optional[Dimensions] = None | ||
enumeration: Optional[Enumeration] = None | ||
attribute: Optional[List[Attribute]] = None | ||
deprecated: Optional[str] = None | ||
|
||
class Config: | ||
extra = "forbid" | ||
|
||
|
||
class Group(Item): | ||
type: str | ||
name: Optional[str] = None # type[2:].upper() | ||
doc: Optional[List[Optional[str]]] = None # NXmirror returns [None] | ||
recommended: Optional[bool] = None | ||
optional: Optional[bool] = None | ||
minOccurs: Optional[int] = None | ||
maxOccurs: Optional[Union[int, str]] = None | ||
attribute: Optional[List[Attribute]] = None | ||
field: Optional[List[Field]] = None | ||
group: Optional[List["Group"]] = None | ||
link: Optional[List["Link"]] = None | ||
deprecated: Optional[str] = None | ||
|
||
@pydantic.model_validator(mode="after") | ||
def name_from_type(self) -> "Group": | ||
if self.name is None: | ||
self.name = self.type[2:].upper() | ||
return self | ||
|
||
|
||
class Link(Item): | ||
name: str | ||
target: str | ||
doc: Optional[str] = None | ||
|
||
class Config: | ||
extra = "forbid" | ||
|
||
|
||
class Choice(Item): | ||
name: str | ||
group: List[Group] | ||
|
||
class Config: | ||
extra = "forbid" | ||
|
||
|
||
class Symbol(Item): | ||
name: str | ||
doc: str | ||
|
||
|
||
class Symbols(Item): | ||
symbol: Optional[List[Symbol]] = None | ||
doc: Optional[str] = None | ||
|
||
|
||
class Definition(Item): | ||
xmlns: str | ||
xmlns_xsi: str | ||
name: str | ||
type: str | ||
category: str | ||
xsi_schemaLocation: str | ||
ignoreExtraGroups: bool | ||
ignoreExtraFields: bool | ||
ignoreExtraAttributes: bool | ||
xmlns_xs: Optional[str] = None | ||
xmlns_ns: Optional[str] = None | ||
extends: Optional[str] = None | ||
deprecated: Optional[str] = None | ||
doc: Optional[str] = None | ||
symbols: Optional[Symbols] = None | ||
attribute: Optional[List[Attribute]] = None | ||
field: Optional[List[Field]] = None | ||
group: Optional[List[Group]] = None | ||
link: Optional[List[Link]] = None | ||
choice: Optional[List[Choice]] = None | ||
|
||
class Config: | ||
extra = "forbid" | ||
|
||
|
||
def load_enumeration_item(enum_item: dict) -> dict: | ||
data = dict() | ||
for key, value in enum_item.items(): | ||
if key.startswith("@"): | ||
key = key[1:] | ||
data[key] = value | ||
return data | ||
|
||
|
||
def load_enumeration(enumeration: dict) -> dict: | ||
data = dict() | ||
for key, value in enumeration.items(): | ||
data[key] = [load_enumeration_item(item) for item in value] | ||
return data | ||
|
||
|
||
def load_doc_dimension_item(dim_item: dict) -> dict: | ||
data = dict() | ||
for key, value in dim_item.items(): | ||
if key.startswith("@"): | ||
key = key[1:] | ||
data[key] = value | ||
return data | ||
|
||
|
||
def load_dimension_item(dim_item: dict) -> dict: | ||
data = dict() | ||
for key, value in dim_item.items(): | ||
if key.startswith("@"): | ||
key = key[1:] | ||
data[key] = value | ||
return data | ||
|
||
|
||
def load_doc_dimensions(dimensions: dict) -> dict: | ||
data = dict() | ||
for key, value in dimensions.items(): | ||
if key.startswith("@"): | ||
key = key[1:] | ||
elif key == "dim": | ||
value = [load_doc_dimension_item(item) for item in value] | ||
data[key] = value | ||
return data | ||
|
||
|
||
def load_dimensions(dimensions: dict) -> dict: | ||
data = dict() | ||
for key, value in dimensions.items(): | ||
if key.startswith("@"): | ||
key = key[1:] | ||
elif key == "dim": | ||
value = [load_dimension_item(item) for item in value] | ||
elif key == "doc" and isinstance(value, dict): | ||
value = load_doc_dimensions(value) | ||
data[key] = value | ||
return data | ||
|
||
|
||
def load_link(link: dict) -> dict: | ||
data = dict() | ||
for key, value in link.items(): | ||
if key.startswith("@"): | ||
key = key[1:] | ||
data[key] = value | ||
return data | ||
|
||
|
||
def load_choice(choice: dict) -> dict: | ||
data = dict() | ||
for key, value in choice.items(): | ||
if key.startswith("@"): | ||
key = key[1:] | ||
elif key == "group": | ||
value = [load_group(group) for group in value] | ||
data[key] = value | ||
return data | ||
|
||
|
||
def load_attribute(attr: dict) -> dict: | ||
data = dict() | ||
for key, value in attr.items(): | ||
if key.startswith("@"): | ||
key = key[1:] | ||
elif key == "enumeration": | ||
value = load_enumeration(value) | ||
elif key == "dimensions": | ||
value = load_dimensions(value) | ||
data[key] = value | ||
return data | ||
|
||
|
||
def load_field(field: dict) -> dict: | ||
data = dict() | ||
for key, value in field.items(): | ||
if key.startswith("@"): | ||
key = key[1:] | ||
elif key == "attribute": | ||
value = [load_attribute(attr) for attr in value] | ||
elif key == "enumeration": | ||
value = load_enumeration(value) | ||
elif key == "dimensions": | ||
value = load_dimensions(value) | ||
data[key] = value | ||
return data | ||
|
||
|
||
def load_group(group: dict) -> dict: | ||
data = dict() | ||
for key, value in group.items(): | ||
if key.startswith("@"): | ||
key = key[1:] | ||
elif key == "attribute": | ||
value = [load_attribute(attr) for attr in value] | ||
elif key == "field": | ||
value = [load_field(field) for field in value] | ||
elif key == "group": | ||
value = [load_group(group) for group in value] | ||
elif key == "link": | ||
value = [load_link(attr) for attr in value] | ||
data[key] = value | ||
return data | ||
|
||
|
||
def load_symbol(symbol: dict) -> dict: | ||
data = dict() | ||
for key, value in symbol.items(): | ||
if key.startswith("@"): | ||
key = key[1:] | ||
data[key] = value | ||
return data | ||
|
||
|
||
def load_symbols(symbols: dict) -> dict: | ||
data = dict() | ||
for key, value in symbols.items(): | ||
if key.startswith("@"): | ||
key = key[1:] | ||
elif key == "symbol": | ||
value = [load_symbol(attr) for attr in value] | ||
data[key] = value | ||
return data | ||
|
||
|
||
def load_definition(definition: str) -> Definition: | ||
data = dict() | ||
|
||
for key, value in definition.items(): | ||
if key.startswith("@"): | ||
key = key[1:].replace(":", "_") | ||
elif key == "attribute": | ||
value = [load_attribute(attr) for attr in value] | ||
elif key == "field": | ||
value = [load_field(attr) for attr in value] | ||
elif key == "group": | ||
value = [load_group(attr) for attr in value] | ||
elif key == "link": | ||
value = [load_link(attr) for attr in value] | ||
elif key == "choice": | ||
value = [load_choice(attr) for attr in value] | ||
elif key == "symbols": | ||
value = load_symbols(value) | ||
data[key] = value | ||
|
||
return Definition(**data) | ||
|
||
|
||
if __name__ == "__main__": | ||
from . import repo | ||
|
||
names = repo.get_nxdl_class_names( | ||
url="https://github.com/XraySpectroscopy/nexus_definitions.git" | ||
) | ||
|
||
for name in names: | ||
load_definition(repo.get_nxdl_class(name)) |
Oops, something went wrong.