diff --git a/pydantic/langPack.py b/pydantic/langPack.py index d12c3ba2..a3aa8660 100644 --- a/pydantic/langPack.py +++ b/pydantic/langPack.py @@ -67,13 +67,19 @@ def _set_instances(text, render): return "" +def _lower_case_first_char(str): + return str[:1].lower() + str[1:] if str else '' + +def _set_lower_case(text, render): + return _lower_case_first_char(render(text)) + # called by chevron, text contains the label {{dataType}}, which is evaluated by the renderer (see class template) def _set_attribute(text, render): attribute = eval(render(text)) if is_required_profile(attribute["attr_origin"]): return ( - attribute["label"] + _lower_case_first_char(attribute["label"]) + ": " + _set_data_type(attribute) + _set_default(attribute) @@ -83,24 +89,29 @@ def _set_attribute(text, render): def _set_default(attribute): + multiplicity_by_name = _ends_with_s(attribute["label"]) if "range" in attribute and "isFixed" in attribute: return " = " + attribute["range"].split("#")[1] + "." + attribute["isFixed"] elif "label" in attribute and attribute["label"] == "mRID": return " = Field(default_factory=uuid.uuid4)" elif "multiplicity" in attribute: multiplicity = attribute["multiplicity"] + if multiplicity in ["M:1"] and multiplicity_by_name: + # Most probably there is a bug in the RDF that states multiplicity + # M:1 but should be M:1..N + return ' = Field(default=[], alias="'+attribute["label"]+'")' if multiplicity in ["M:1", "M:1..1"]: - return "" + return ' = Field(alias="'+attribute["label"]+'")' if multiplicity in ["M:0..1"]: - return "" + return ' = Field(default=None, alias="'+attribute["label"]+'")' elif multiplicity in ["M:0..n"] or "M:0.." in multiplicity: - return "" + return ' = Field(default=[], alias="'+attribute["label"]+'")' elif multiplicity in ["M:1..n"] or "M:1.." in multiplicity: - return "" + return ' = Field(default=[], alias="'+attribute["label"]+'")' else: - return "" + return ' = Field(default=[], alias="'+attribute["label"]+'")' else: - return "" + return ' = Field(alias="'+attribute["label"]+'")' def _is_primitive(datatype): @@ -183,9 +194,9 @@ def _set_validator(text, render): if not _is_primitive(datatype) and is_required_profile(attribute["attr_origin"]): return ( "val_" - + attribute["label"] + + _lower_case_first_char(attribute["label"]) + '_wrap = field_validator("' - + attribute["label"] + + _lower_case_first_char(attribute["label"]) + '", mode="wrap")(cyclic_references_validator)' ) elif attribute["label"] == "mRID": @@ -294,6 +305,7 @@ def run_template_schema(version_path, class_details, templates): ) class_details["setAttribute"] = _set_attribute class_details["setValidator"] = _set_validator + class_details["setLowerCase"] = _set_lower_case with open(template_path) as f: args = { "data": class_details, diff --git a/pydantic/schema_header.py b/pydantic/schema_header.py index 23f0710f..c6ea5b41 100644 --- a/pydantic/schema_header.py +++ b/pydantic/schema_header.py @@ -45,8 +45,8 @@ class PositionPoint(Base): } ) - Location: "Location" - sequenceNumber: Optional[int] + location: "Location" = Field(alias = "Location") + sequenceNumber: Optional[int] = Field(default=None) point: Point = Field( repr=False ) # we introduce this field compared to CIM definition because we want to store a proper geometry "point" in the database diff --git a/pydantic/templates/pydantic_class_template.mustache b/pydantic/templates/pydantic_class_template.mustache index 095e8363..f5f057e1 100644 --- a/pydantic/templates/pydantic_class_template.mustache +++ b/pydantic/templates/pydantic_class_template.mustache @@ -9,7 +9,7 @@ class {{class_name}}({{sub_class_of}}): ''' possibleProfileList: dict = Field(default={'class': [{{#class_origin}}CgmesProfileEnum.{{origin}}, {{/class_origin}}], - {{#attributes}}'{{label}}': [{{#attr_origin}}CgmesProfileEnum.{{origin}}, {{/attr_origin}}], + {{#attributes}}'{{#setLowerCase}}{{label}}{{/setLowerCase}}': [{{#attr_origin}}CgmesProfileEnum.{{origin}}, {{/attr_origin}}], {{/attributes}} }) {{#attributes}}