I am looking to add serializing-deserializing methods to a Pydantic class to communicate class attributes to a restAPI or update object with API response. I arrived up to this point, program don't crash anymore and I can call my new methods but so far the class attributes can't be modified from my method fro son Could you give me some help please ?
import uuid
from typing import Optional
from pydantic import BaseModel, Field, Extra
import json
class Panel(BaseModel):
id: str = Field(default_factory=uuid.uuid4, alias="_id")
manufacturer: str = Field(...)
model: str = Field(...)
url: str = Field(...)
documents: Optional[object]
#Electrical characteristics
power_max_stc: object = Field(...)
voltage_openCircuit: object = Field(...)
current_shunt: object = Field(...)
voltage_maxPow: object = Field(...)
current_maxPow: object = Field(...)
power_ptc: Optional[object]
power_ratioPtcStc: Optional[object]
efficiency: Optional[object]
fill_factor: Optional[object]
power_tolerance: Optional[object]
integrity_maxVoltage: Optional[object]
integrity_maxFuseCurrent: Optional[object]
#Temperature coefficients
coef_temp_shuntCurrent: Optional[object]
coef_temp_openCircuitVoltage: Optional[object]
coef_temp_maxPow: Optional[object]
#Mechanical characteristics
cells: object = Field(...)
dimensions: object = Field(...)
weight: Optional[object]
wiring: Optional[object]
bom: Optional[object]
#Operating conditions
temp_nom_cell: Optional[object]
temp_operating: Optional[object]
load_max: Optional[object]
rating_hailStorm: Optional[object]
rating_fireSafety: Optional[object]
#Waranty and certifications
certificates: Optional[object]
waranties: Optional[object]
__fields = ['manufacturer', 'model', 'url', 'documents', 'power_max_stc',
'voltage_openCircuit', 'current_shunt', 'voltage_maxPow', 'current_maxPow', 'power_ptc',
'power_ratioPtcStc', 'efficiency', 'fill_factor', 'power_tolerance', 'integrity_maxVoltage',
'integrity_maxFuseCurrent', 'coef_temp_shuntCurrent', 'coef_temp_openCircuitVoltage', 'coef_temp_maxPow', 'cells',
'dimensions', 'weight', 'wiring', 'bom', 'temp_nom_cell',
'temp_operating', 'load_max', 'rating_hailStorm', 'rating_fireSafety', 'certificates',
'waranties',
]
__fields_required = ['manufacturer', 'model', 'url', 'power_max_stc',
'voltage_openCircuit', 'current_shunt', 'voltage_maxPow', 'current_maxPow', 'cells',
'dimensions',
]
__fields_optional = ['documents', 'power_ptc',
'power_ratioPtcStc', 'efficiency', 'fill_factor', 'power_tolerance', 'integrity_maxVoltage',
'integrity_maxFuseCurrent', 'coef_temp_shuntCurrent', 'coef_temp_openCircuitVoltage', 'coef_temp_maxPow',
'weight', 'wiring', 'bom', 'temp_nom_cell',
'temp_operating', 'load_max', 'rating_hailStorm', 'rating_fireSafety', 'certificates',
'waranties',
]
@classmethod
def fromJsonInit(self, panelJson = None):
#super().__init__()
if panelJson is not None:
if self.isJsonString(panelJson):
panel = json.loads(panelJson)
hasRequiredData = True
for field in self.__fields_required:
if field not in panel: hasRequiredData = False
if hasRequiredData:
self.fromJson(jsonObject=panelJson)
else:
raise(ValueError("Insufficient Data to create object!"))
@classmethod
def fromJson(cls, jsonObject):
if cls.isJsonString(jsonObject):
panel = json.loads(jsonObject)
hasUnknownField = False
for field in panel:
if field not in cls.__fields: hasUnknownField = True
print(f"hasUnkonwnFields : ({hasUnknownField})")
if not hasUnknownField:
for field in panel:
print(f"field: {field}\nvalue: {panel[field]}")
setattr(cls,field, panel[field])
print("bam")
else:
raise(ValueError(f"Passed Invalid Data to the object!\nReminder, appropriate ifelds are:\n{self.fields}"))
@classmethod
def toJson(self):
outputJson = {}
for attr in self.__fields:
if self.isSet(attr):
outputJson[attr] = getattr(self,attr)
return outputJson
@classmethod
def isJsonString(self, jsonStr):
try:
json.loads(jsonStr)
isJson = True
except:
isJson = False
finally:
print(f"isJsonString: ({isJson})")
return isJson
@classmethod
def isSet(self, variableName):
try:
getattr(self, variableName)
#exec(f"{variableName}")
#print("sure, it was defined.")
isSetb = True
except NameError:
#print("well, it WASN'T defined after all!")
isSetb = False
finally:
return isSetb
class Config:
#extra=Extra.allow
arbitrary_types_allowed = True
allow_mutation = True
allow_population_by_field_name = True
schema_extra = {
"example": {
"_id": "066de609-b04a-4b30-b46c-32537c7f1f6e",
"manufacturer": "JA Solar",
"model": "JAM54S31/MR",
"url": "http://www.posharp.com/yl250p-32b-solar-panel-from-yingli-green-energy_p389707207d.aspx",
"documents": {"datasheet": {
"english": "http://www.posharp.com/Businesses/ca46966d-c99d-456b-9e49-5b6bc7233e14/Panel/YL255P-32b_en.pdf",
"french": "http://www.posharp.com/Businesses/ca46966d-c99d-456b-9e49-5b6bc7233e14/Panel/YL255P-32b_fr.pdf"
}},
"power_max_stc": {"value": 250.0,"unit": "W"},
"voltage_openCircuit": {"value": 40.9,"unit": "V"},
"current_shunt": {"value": 8.33,"unit": "A"},
"voltage_maxPow": {"value": 32.3,"unit": "V"},
"current_maxPow": {"value": 7.74,"unit": "A"},
"power_ptc": {"value": 220.6,"unit": "W"},
"power_ratioPtcStc": {"value": 88.2,"unit": "%"},
"efficiency": {"value": 14.0,"unit": "%"},
"fill_factor": {"value": 73.4,"unit": "%"},
"power_tolerance": {
"nominal": 0.0,
"min": -3.0,
"max": 3.0,
"interval": 6.0,
"unit": "%"
},
"integrity_maxVoltage": {"value": 1000.0,"unit": "V"},
"integrity_maxFuseCurrent": {"value": 15.0,"unit": "A"},
"coef_temp_shuntCurrent": {"value": 0.006,"unit": "%/ºC"},
"coef_temp_openCircuitVoltage": {"value": -0.37,"unit": "%/ºC"},
"coef_temp_maxPow": {"value": -0.45,"unit": "%/ºC"},
"cells": {
"type": "Monocrystalline Cell",
"size": "80x156",
"size_width": 80,
"size_height": 156,
"count_format": "8x10",
"count_format_axis1": 8,
"count_format_axis2": 10
},
"dimensions": {
"axis1": {"value": 1652.0,"unit": "mm"},
"axis2": {"value": 1306.0,"unit": "mm"},
"axis3": {"value": 55.0,"unit": "mm"},
},
"weight": {"value": 22.5,"unit": "Kg"},
"wiring": {
"junction_box": {
"rating_safety": "IP67",
"diodes": 4
},
"positive_cable": "80mm, 16mm2",
"negative_cable": "110mm, 16mm2",
"connector": "MC4",
},
"bom": {
"front_cover": "glass, 3mm",
"backsheet_cover": "PET Black 4mm",
"encapsulation": "PBT",
"frame": "aluminum",
},
"temp_nom_cell": {"value": 50.0,"unit": "ºC"},
"temp_operating": {
"nominal": 25.0,
"min": -40.0,
"max": 90.0,
"interval": 130.0,
"unit": "ºC"
},
"load_max": {"value": 50.0,"unit": "Mpa"},
"rating_hailStorm": {"value": "Grade B"},
"rating_fireSafety": {"value": "Grade Z"},
"certificates": [
{"name": "UL 1703","url": "https://www.intertek.com/building/standards/ul-1703/"},
{"name": "CEC California","url": ""},
],
"waranties": {
"defectAndWorksmanship": {"value": 5.0,"unit": "Year"},
"power_90Percent": {"value": 10.0,"unit": "Year"},
"power_80Percent": {"value": 25.0,"unit": "Year"},
"insuredByThirdParty": False
},
}
}
if __name__ == "__main__":
try:
testPanel_valid = Panel(**{
'manufacturer':"testMan",
'model':"testModel",
'url': "testUrl",
'power_max_stc': {},
'voltage_openCircuit': {},
'current_shunt': {},
'voltage_maxPow': {},
'current_maxPow': {},
'cells': {},
'dimensions': {},
})
testPanel_invalid = Panel(**{
'manufacturer':"testMan",
'model':"testModel",
'url': "testUrl",
'power_max_stc': {},
'voltage_openCircuit': {},
'current_shunt': {},
'voltage_maxPow': {},
'current_maxPow': {},
'cells': {},
'dimensions': {},
"Dmensiooooooooooooon":{}
})
except Exception as e:
print(f"Panel class error : {e}")
print(f"testPanel_valid: {testPanel_valid}\n")
print(f"testPanel_invalid: {testPanel_invalid}\n")
testPanel_valid.fromJson(json.dumps({
"manufacturer":"mySatisfactory"
}))
print(f"testPanel_valid: {testPanel_valid}\n")
I tried with the options extra = Extra.allow, arbitrary_types_allowed=True, allow_mutation=True
which I found here: text
It still does not work. If I place the extra option in the class definition line like in the url, like : cla s Model Base Model, extra Extra.forbid I get an error ambiguous configuration