add types

Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2022-02-27 19:58:46 -08:00
parent 2a3cec9aac
commit 32479cfe2a
7 changed files with 514 additions and 226 deletions

View File

@ -1,2 +0,0 @@
project_name_override: kittycad
package_name_override: kittycad

View File

@ -2,6 +2,7 @@
from openapi_parser.parser.loader import OpenApiParser from openapi_parser.parser.loader import OpenApiParser
import os import os
import re
package_name = 'kittycad' package_name = 'kittycad'
@ -18,7 +19,7 @@ def main():
# Generate the types. # Generate the types.
generateTypes(cwd, parser) generateTypes(cwd, parser)
print([parser]) # Generate the paths.
def generateTypes(cwd: str, parser: OpenApiParser): def generateTypes(cwd: str, parser: OpenApiParser):
# Make sure we have the directory. # Make sure we have the directory.
@ -30,8 +31,267 @@ def generateTypes(cwd: str, parser: OpenApiParser):
schemas = data['components']['schemas'] schemas = data['components']['schemas']
for key in schemas: for key in schemas:
schema = schemas[key] schema = schemas[key]
print(key) generateType(path, key, schema)
def generateType(path: str, name: str, schema: dict):
# Generate the type.
file_name = camel_to_snake(name) + '.py'
file_path = os.path.join(path, file_name)
type_name = schema['type']
print("generating type: ", name, " at: ", file_path)
print(" schema: ", [schema])
f = open(file_path, "w")
if type_name == 'object':
has_date_time = hasDateTime(schema)
if has_date_time:
f.write("import datetime\n")
f.write("from typing import Any, Dict, List, Type, TypeVar, Union\n")
f.write("\n")
f.write("import attr\n")
if has_date_time:
f.write("from dateutil.parser import isoparse\n")
f.write("\n")
refs = getRefs(schema)
for ref in refs:
f.write("from ..models."+camel_to_snake(ref)+" import "+ref+"\n")
f.write("from ..types import UNSET, Unset\n")
f.write("\n")
f.write("T = TypeVar(\"T\", bound=\""+name+"\")\n")
f.write("\n")
f.write("@attr.s(auto_attribs=True)\n")
f.write("class "+name+":\n")
# Write the description.
f.write("\t\"\"\" \"\"\"\n")
# Iterate over the properties.
for property_name in schema['properties']:
property_schema = schema['properties'][property_name]
if 'type' in property_schema:
property_type = property_schema['type']
# Write the property.
if property_type == 'string':
if 'format' in property_schema:
if property_schema['format'] == 'date-time':
f.write("\t"+property_name+": Union[Unset, datetime.datetime] = UNSET\n")
continue
f.write("\t"+property_name+": Union[Unset, str] = UNSET\n")
elif property_type == 'integer':
f.write("\t"+property_name+": Union[Unset, int] = UNSET\n")
elif property_type == 'number':
f.write("\t"+property_name+": Union[Unset, float] = UNSET\n")
elif property_type == 'boolean':
f.write("\t"+property_name+": Union[Unset, bool] = False\n")
else:
print(" unknown type: ", property_type)
elif '$ref' in property_schema:
ref = property_schema['$ref'].replace('#/components/schemas/', '')
f.write("\t"+property_name+": Union[Unset, "+ref+"] = UNSET\n")
else:
print(" unknown schema: ", property_schema)
# Finish writing the class.
f.write("\n")
f.write("\tadditional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)\n")
# Now let's write the to_dict method.
f.write("\n")
f.write("\tdef to_dict(self) -> Dict[str, Any]:\n")
# Iternate over the properties.
for property_name in schema['properties']:
property_schema = schema['properties'][property_name]
if 'type' in property_schema:
property_type = property_schema['type']
# Write the property.
if property_type == 'string':
if 'format' in property_schema:
if property_schema['format'] == 'date-time':
f.write("\t\t"+property_name+": Union[Unset, str] = UNSET\n")
f.write("\t\tif not isinstance(self."+property_name+", Unset):\n")
f.write("\t\t\t"+property_name+" = self."+property_name+".isoformat()\n")
continue
f.write("\t"+property_name+" = self."+property_name+"\n")
elif property_type == 'integer':
f.write("\t"+property_name+" = self."+property_name+"\n")
elif property_type == 'number':
f.write("\t"+property_name+" = self."+property_name+"\n")
elif property_type == 'boolean':
f.write("\t"+property_name+" = self."+property_name+"\n")
else:
print(" unknown type: ", property_type)
elif '$ref' in property_schema:
ref = property_schema['$ref'].replace('#/components/schemas/', '')
f.write("\t\t"+property_name+": Union[Unset, str] = UNSET\n")
f.write("\t\tif not isinstance(self."+property_name+", Unset):\n")
f.write("\t\t\t"+property_name+" = self."+property_name+".value\n")
else:
print(" unknown schema: ", property_schema)
# Finish writing the to_dict method.
f.write("\n")
f.write("\t\tfield_dict: Dict[str, Any] = {}\n")
f.write("\t\tfield_dict.update(self.additional_properties)\n")
f.write("\t\tfield_dict.update({})\n")
# Iternate over the properties.
for property_name in schema['properties']:
# Write the property.
f.write("\t\tif "+property_name+" is not UNSET:\n")
f.write("\t\t\tfield_dict['"+property_name+"'] = "+property_name+"\n")
f.write("\n")
f.write("\t\treturn field_dict\n")
# Now let's write the from_dict method.
f.write("\n")
f.write("\t@classmethod\n")
f.write("\tdef from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:\n")
f.write("\t\td = src_dict.copy()\n")
# Iternate over the properties.
for property_name in schema['properties']:
property_schema = schema['properties'][property_name]
if 'type' in property_schema:
property_type = property_schema['type']
# Write the property.
if property_type == 'string':
if 'format' in property_schema:
if property_schema['format'] == 'date-time':
f.write("\t\t_"+property_name+" = d.pop(\"" +property_name+"\", UNSET)\n")
f.write("\t\t"+property_name+": Union[Unset, datetime.datetime]\n")
f.write("\t\tif not isinstance(_"+property_name+", Unset):\n")
f.write("\t\t\t"+property_name+" = UNSET\n")
f.write("\t\telse:\n")
f.write("\t\t\t"+property_name+" = isoparse(_"+property_name+")\n")
f.write("\n")
continue
f.write("\t"+property_name+" = d.pop(\"" +property_name+"\", UNSET)\n")
f.write("\n")
elif property_type == 'integer':
f.write("\t"+property_name+" = d.pop(\"" +property_name+"\", UNSET)\n")
f.write("\n")
elif property_type == 'number':
f.write("\t"+property_name+" = d.pop(\"" +property_name+"\", UNSET)\n")
f.write("\n")
elif property_type == 'boolean':
f.write("\t"+property_name+" = d.pop(\"" +property_name+"\", UNSET)\n")
f.write("\n")
else:
print(" unknown type: ", property_type)
elif '$ref' in property_schema:
ref = property_schema['$ref'].replace('#/components/schemas/', '')
f.write("\t\t_"+property_name+" = d.pop(\"" +property_name+"\", UNSET)\n")
f.write("\t\t"+property_name+": Union[Unset, "+ref+"]\n")
f.write("\t\tif not isinstance(_"+property_name+", Unset):\n")
f.write("\t\t\t"+property_name+" = UNSET\n")
f.write("\t\telse:\n")
f.write("\t\t\t"+property_name+" = "+ref+"(_"+property_name+")\n")
f.write("\n")
else:
print(" unknown schema: ", property_schema)
# Finish writing the from_dict method.
f.write("\n")
f.write("\t\t"+camel_to_snake(name)+" = cls(\n")
# Iternate over the properties.
for property_name in schema['properties']:
# Write the property.
f.write("\t\t\t"+property_name+"= "+property_name+",\n")
# Close the class.
f.write("\t\t)\n")
f.write("\n")
f.write("\t\t"+camel_to_snake(name)+".additional_properties = d\n")
f.write("return "+camel_to_snake(name)+"\n")
# write the rest of the class.
f.write("\n")
f.write("\t@property\n")
f.write("\tdef additional_keys(self) -> List[str]:\n")
f.write("\t\treturn list(self.additional_properties.keys())\n")
f.write("\n")
f.write("\tdef __getitem__(self, key: str) -> Any:\n")
f.write("\t\treturn self.additional_properties[key]\n")
f.write("\n")
f.write("\tdef __setitem__(self, key: str, value: Any) -> None:\n")
f.write("\t\tself.additional_properties[key] = value\n")
f.write("\n")
f.write("\tdef __delitem__(self, key: str) -> None:\n")
f.write("\t\tdel self.additional_properties[key]\n")
f.write("\n")
f.write("\tdef __contains__(self, key: str) -> bool:\n")
f.write("\t\treturn key in self.additional_properties\n")
elif type_name == 'string' and 'enum' in schema:
f.write("from enum import Enum\n")
f.write("\n")
f.write("class "+name+"(str, Enum):\n")
# Iterate over the properties.
for value in schema['enum']:
f.write("\t"+camel_to_screaming_snake(value)+" = '"+value+"'\n")
# close the enum.
f.write("\n")
f.write("\tdef __str__(self) -> str:\n")
f.write("\t\treturn str(self.value)\n")
else:
print(" unsupported type: ", type_name)
return
def hasDateTime(schema: dict) -> bool:
# Generate the type.
if 'type' in schema:
type_name = schema['type']
if type_name == 'object':
# Iternate over the properties.
for property_name in schema['properties']:
property_schema = schema['properties'][property_name]
has_date_time = hasDateTime(property_schema)
if has_date_time:
return True
elif type_name == 'string' and 'format' in schema:
if schema['format'] == 'date-time':
return True
return False
def getRefs(schema: dict) -> [str]:
refs = []
if '$ref' in schema:
refs.append(schema['$ref'].replace('#/components/schemas/', ''))
else:
# Generate the type.
type_name = schema['type']
if type_name == 'object':
# Iternate over the properties.
for property_name in schema['properties']:
property_schema = schema['properties'][property_name]
schema_refs = getRefs(property_schema)
for ref in schema_refs:
if ref not in refs:
refs.append(ref)
return refs
def camel_to_snake(name: str):
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()
def camel_to_screaming_snake(name: str):
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).upper()
if (__name__ == '__main__'): if (__name__ == '__main__'):
exit_code = main() exit_code = main()

View File

@ -1,2 +1,2 @@
""" A client library for accessing KittyCAD """ """ A client library for accessing KittyCAD """
from .client import AuthenticatedClient, Client from .client import Client, ClientFromEnv

View File

@ -8,27 +8,27 @@ from ..types import UNSET, Unset
T = TypeVar("T", bound="AuthSession") T = TypeVar("T", bound="AuthSession")
@attr.s(auto_attribs=True) @attr.s(auto_attribs=True)
class AuthSession: class AuthSession:
""" """ """ """
created_at: Union[Unset, datetime.datetime] = UNSET created_at: Union[Unset, datetime.datetime] = UNSET
email: Union[Unset, str] = UNSET email: Union[Unset, str] = UNSET
id: Union[Unset, str] = UNSET id: Union[Unset, str] = UNSET
image: Union[Unset, str] = UNSET
ip_address: Union[Unset, str] = UNSET ip_address: Union[Unset, str] = UNSET
is_valid: Union[Unset, bool] = False is_valid: Union[Unset, bool] = False
token: Union[Unset, str] = UNSET token: Union[Unset, str] = UNSET
user_id: Union[Unset, str] = UNSET user_id: Union[Unset, str] = UNSET
additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)
def to_dict(self) -> Dict[str, Any]: def to_dict(self) -> Dict[str, Any]:
created_at: Union[Unset, str] = UNSET created_at: Union[Unset, str] = UNSET
if not isinstance(self.created_at, Unset): if not isinstance(self.created_at, Unset):
created_at = self.created_at.isoformat() created_at = self.created_at.isoformat()
email = self.email email = self.email
id = self.id id = self.id
image = self.image
ip_address = self.ip_address ip_address = self.ip_address
is_valid = self.is_valid is_valid = self.is_valid
token = self.token token = self.token
@ -38,19 +38,21 @@ class AuthSession:
field_dict.update(self.additional_properties) field_dict.update(self.additional_properties)
field_dict.update({}) field_dict.update({})
if created_at is not UNSET: if created_at is not UNSET:
field_dict["created_at"] = created_at field_dict['created_at'] = created_at
if email is not UNSET: if email is not UNSET:
field_dict["email"] = email field_dict['email'] = email
if id is not UNSET: if id is not UNSET:
field_dict["id"] = id field_dict['id'] = id
if image is not UNSET:
field_dict['image'] = image
if ip_address is not UNSET: if ip_address is not UNSET:
field_dict["ip_address"] = ip_address field_dict['ip_address'] = ip_address
if is_valid is not UNSET: if is_valid is not UNSET:
field_dict["is_valid"] = is_valid field_dict['is_valid'] = is_valid
if token is not UNSET: if token is not UNSET:
field_dict["token"] = token field_dict['token'] = token
if user_id is not UNSET: if user_id is not UNSET:
field_dict["user_id"] = user_id field_dict['user_id'] = user_id
return field_dict return field_dict
@ -59,7 +61,7 @@ class AuthSession:
d = src_dict.copy() d = src_dict.copy()
_created_at = d.pop("created_at", UNSET) _created_at = d.pop("created_at", UNSET)
created_at: Union[Unset, datetime.datetime] created_at: Union[Unset, datetime.datetime]
if isinstance(_created_at, Unset): if not isinstance(_created_at, Unset):
created_at = UNSET created_at = UNSET
else: else:
created_at = isoparse(_created_at) created_at = isoparse(_created_at)
@ -68,6 +70,8 @@ class AuthSession:
id = d.pop("id", UNSET) id = d.pop("id", UNSET)
image = d.pop("image", UNSET)
ip_address = d.pop("ip_address", UNSET) ip_address = d.pop("ip_address", UNSET)
is_valid = d.pop("is_valid", UNSET) is_valid = d.pop("is_valid", UNSET)
@ -76,18 +80,20 @@ class AuthSession:
user_id = d.pop("user_id", UNSET) user_id = d.pop("user_id", UNSET)
auth_session = cls( auth_session = cls(
created_at=created_at, created_at= created_at,
email=email, email= email,
id=id, id= id,
ip_address=ip_address, image= image,
is_valid=is_valid, ip_address= ip_address,
token=token, is_valid= is_valid,
user_id=user_id, token= token,
user_id= user_id,
) )
auth_session.additional_properties = d auth_session.additional_properties = d
return auth_session return auth_session
@property @property
def additional_keys(self) -> List[str]: def additional_keys(self) -> List[str]:

View File

@ -6,36 +6,50 @@ from ..types import UNSET, Unset
T = TypeVar("T", bound="ErrorMessage") T = TypeVar("T", bound="ErrorMessage")
@attr.s(auto_attribs=True) @attr.s(auto_attribs=True)
class ErrorMessage: class ErrorMessage:
""" """ """ """
code: Union[Unset, int] = UNSET
message: Union[Unset, str] = UNSET message: Union[Unset, str] = UNSET
status: Union[Unset, str] = UNSET
additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)
def to_dict(self) -> Dict[str, Any]: def to_dict(self) -> Dict[str, Any]:
code = self.code
message = self.message message = self.message
status = self.status
field_dict: Dict[str, Any] = {} field_dict: Dict[str, Any] = {}
field_dict.update(self.additional_properties) field_dict.update(self.additional_properties)
field_dict.update({}) field_dict.update({})
if code is not UNSET:
field_dict['code'] = code
if message is not UNSET: if message is not UNSET:
field_dict["message"] = message field_dict['message'] = message
if status is not UNSET:
field_dict['status'] = status
return field_dict return field_dict
@classmethod @classmethod
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
d = src_dict.copy() d = src_dict.copy()
code = d.pop("code", UNSET)
message = d.pop("message", UNSET) message = d.pop("message", UNSET)
status = d.pop("status", UNSET)
error_message = cls( error_message = cls(
message=message, code= code,
message= message,
status= status,
) )
error_message.additional_properties = d error_message.additional_properties = d
return error_message return error_message
@property @property
def additional_keys(self) -> List[str]: def additional_keys(self) -> List[str]:

View File

@ -4,45 +4,45 @@ from typing import Any, Dict, List, Type, TypeVar, Union
import attr import attr
from dateutil.parser import isoparse from dateutil.parser import isoparse
from ..models.valid_output_file_format import ValidOutputFileFormat
from ..models.valid_source_file_format import ValidSourceFileFormat
from ..models.file_conversion_status import FileConversionStatus from ..models.file_conversion_status import FileConversionStatus
from ..models.valid_file_type import ValidFileType
from ..types import UNSET, Unset from ..types import UNSET, Unset
T = TypeVar("T", bound="FileConversion") T = TypeVar("T", bound="FileConversion")
@attr.s(auto_attribs=True) @attr.s(auto_attribs=True)
class FileConversion: class FileConversion:
""" """ """ """
completed_at: Union[Unset, datetime.datetime] = UNSET completed_at: Union[Unset, datetime.datetime] = UNSET
created_at: Union[Unset, datetime.datetime] = UNSET created_at: Union[Unset, datetime.datetime] = UNSET
id: Union[Unset, str] = UNSET id: Union[Unset, str] = UNSET
output: Union[Unset, str] = UNSET output: Union[Unset, str] = UNSET
output_format: Union[Unset, ValidFileType] = UNSET output_format: Union[Unset, ValidOutputFileFormat] = UNSET
src_format: Union[Unset, ValidFileType] = UNSET src_format: Union[Unset, ValidSourceFileFormat] = UNSET
started_at: Union[Unset, datetime.datetime] = UNSET
status: Union[Unset, FileConversionStatus] = UNSET status: Union[Unset, FileConversionStatus] = UNSET
additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)
def to_dict(self) -> Dict[str, Any]: def to_dict(self) -> Dict[str, Any]:
completed_at: Union[Unset, str] = UNSET completed_at: Union[Unset, str] = UNSET
if not isinstance(self.completed_at, Unset): if not isinstance(self.completed_at, Unset):
completed_at = self.completed_at.isoformat() completed_at = self.completed_at.isoformat()
created_at: Union[Unset, str] = UNSET created_at: Union[Unset, str] = UNSET
if not isinstance(self.created_at, Unset): if not isinstance(self.created_at, Unset):
created_at = self.created_at.isoformat() created_at = self.created_at.isoformat()
id = self.id id = self.id
output = self.output output = self.output
output_format: Union[Unset, str] = UNSET output_format: Union[Unset, str] = UNSET
if not isinstance(self.output_format, Unset): if not isinstance(self.output_format, Unset):
output_format = self.output_format.value output_format = self.output_format.value
src_format: Union[Unset, str] = UNSET src_format: Union[Unset, str] = UNSET
if not isinstance(self.src_format, Unset): if not isinstance(self.src_format, Unset):
src_format = self.src_format.value src_format = self.src_format.value
started_at: Union[Unset, str] = UNSET
if not isinstance(self.started_at, Unset):
started_at = self.started_at.isoformat()
status: Union[Unset, str] = UNSET status: Union[Unset, str] = UNSET
if not isinstance(self.status, Unset): if not isinstance(self.status, Unset):
status = self.status.value status = self.status.value
@ -51,19 +51,21 @@ class FileConversion:
field_dict.update(self.additional_properties) field_dict.update(self.additional_properties)
field_dict.update({}) field_dict.update({})
if completed_at is not UNSET: if completed_at is not UNSET:
field_dict["completed_at"] = completed_at field_dict['completed_at'] = completed_at
if created_at is not UNSET: if created_at is not UNSET:
field_dict["created_at"] = created_at field_dict['created_at'] = created_at
if id is not UNSET: if id is not UNSET:
field_dict["id"] = id field_dict['id'] = id
if output is not UNSET: if output is not UNSET:
field_dict["output"] = output field_dict['output'] = output
if output_format is not UNSET: if output_format is not UNSET:
field_dict["output_format"] = output_format field_dict['output_format'] = output_format
if src_format is not UNSET: if src_format is not UNSET:
field_dict["src_format"] = src_format field_dict['src_format'] = src_format
if started_at is not UNSET:
field_dict['started_at'] = started_at
if status is not UNSET: if status is not UNSET:
field_dict["status"] = status field_dict['status'] = status
return field_dict return field_dict
@ -72,14 +74,14 @@ class FileConversion:
d = src_dict.copy() d = src_dict.copy()
_completed_at = d.pop("completed_at", UNSET) _completed_at = d.pop("completed_at", UNSET)
completed_at: Union[Unset, datetime.datetime] completed_at: Union[Unset, datetime.datetime]
if isinstance(_completed_at, Unset): if not isinstance(_completed_at, Unset):
completed_at = UNSET completed_at = UNSET
else: else:
completed_at = isoparse(_completed_at) completed_at = isoparse(_completed_at)
_created_at = d.pop("created_at", UNSET) _created_at = d.pop("created_at", UNSET)
created_at: Union[Unset, datetime.datetime] created_at: Union[Unset, datetime.datetime]
if isinstance(_created_at, Unset): if not isinstance(_created_at, Unset):
created_at = UNSET created_at = UNSET
else: else:
created_at = isoparse(_created_at) created_at = isoparse(_created_at)
@ -89,38 +91,47 @@ class FileConversion:
output = d.pop("output", UNSET) output = d.pop("output", UNSET)
_output_format = d.pop("output_format", UNSET) _output_format = d.pop("output_format", UNSET)
output_format: Union[Unset, ValidFileType] output_format: Union[Unset, ValidOutputFileFormat]
if isinstance(_output_format, Unset): if not isinstance(_output_format, Unset):
output_format = UNSET output_format = UNSET
else: else:
output_format = ValidFileType(_output_format) output_format = ValidOutputFileFormat(_output_format)
_src_format = d.pop("src_format", UNSET) _src_format = d.pop("src_format", UNSET)
src_format: Union[Unset, ValidFileType] src_format: Union[Unset, ValidSourceFileFormat]
if isinstance(_src_format, Unset): if not isinstance(_src_format, Unset):
src_format = UNSET src_format = UNSET
else: else:
src_format = ValidFileType(_src_format) src_format = ValidSourceFileFormat(_src_format)
_started_at = d.pop("started_at", UNSET)
started_at: Union[Unset, datetime.datetime]
if not isinstance(_started_at, Unset):
started_at = UNSET
else:
started_at = isoparse(_started_at)
_status = d.pop("status", UNSET) _status = d.pop("status", UNSET)
status: Union[Unset, FileConversionStatus] status: Union[Unset, FileConversionStatus]
if isinstance(_status, Unset): if not isinstance(_status, Unset):
status = UNSET status = UNSET
else: else:
status = FileConversionStatus(_status) status = FileConversionStatus(_status)
file_conversion = cls( file_conversion = cls(
completed_at=completed_at, completed_at= completed_at,
created_at=created_at, created_at= created_at,
id=id, id= id,
output=output, output= output,
output_format=output_format, output_format= output_format,
src_format=src_format, src_format= src_format,
status=status, started_at= started_at,
status= status,
) )
file_conversion.additional_properties = d file_conversion.additional_properties = d
return file_conversion return file_conversion
@property @property
def additional_keys(self) -> List[str]: def additional_keys(self) -> List[str]:

View File

@ -1,12 +1,11 @@
from enum import Enum from enum import Enum
class FileConversionStatus(str, Enum): class FileConversionStatus(str, Enum):
QUEUED = "Queued" QUEUED = 'Queued'
UPLOADED = "Uploaded" UPLOADED = 'Uploaded'
IN_PROGRESS = "In Progress" IN _PROGRESS = 'In Progress'
COMPLETED = "Completed" COMPLETED = 'Completed'
FAILED = "Failed" FAILED = 'Failed'
def __str__(self) -> str: def __str__(self) -> str:
return str(self.value) return str(self.value)