Skip to content

Commit

Permalink
Refactor: ExporterOptions.py (#1042)
Browse files Browse the repository at this point in the history
  • Loading branch information
HunterBarclay authored Jul 25, 2024
2 parents 0b52f29 + 75c5d10 commit bf4cdb4
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 63 deletions.
71 changes: 11 additions & 60 deletions exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import os
import platform
from dataclasses import dataclass, field, fields
from enum import Enum, EnumType
from typing import get_origin

import adsk.core
from adsk.fusion import CalculationAccuracy, TriangleMeshQualityOptions
Expand All @@ -25,6 +23,8 @@
PhysicalDepth,
PreferredUnits,
Wheel,
encodeNestedObjects,
makeObjectFromJson,
)


Expand Down Expand Up @@ -58,71 +58,22 @@ class ExporterOptions:
physicalDepth: PhysicalDepth = field(default=PhysicalDepth.AllOccurrence)
physicalCalculationLevel: CalculationAccuracy = field(default=CalculationAccuracy.LowCalculationAccuracy)

@logFailure
@timed
def readFromDesign(self) -> "ExporterOptions":
try:
designAttributes = adsk.core.Application.get().activeProduct.attributes
for field in fields(self):
attribute = designAttributes.itemByName(INTERNAL_ID, field.name)
if attribute:
setattr(
self,
field.name,
self._makeObjectFromJson(field.type, json.loads(attribute.value)),
)
designAttributes = adsk.core.Application.get().activeProduct.attributes
for field in fields(self):
attribute = designAttributes.itemByName(INTERNAL_ID, field.name)
if attribute:
attrJsonData = makeObjectFromJson(field.type, json.loads(attribute.value))
setattr(self, field.name, attrJsonData)

return self
except:
return ExporterOptions()
return self

@logFailure
@timed
def writeToDesign(self) -> None:
designAttributes = adsk.core.Application.get().activeProduct.attributes
for field in fields(self):
data = json.dumps(
getattr(self, field.name),
default=lambda obj: (
obj.value
if isinstance(obj, Enum)
else (
{
key: (lambda value: (value if not isinstance(value, Enum) else value.value))(value)
for key, value in obj.__dict__.items()
}
if hasattr(obj, "__dict__")
else obj
)
),
indent=4,
)
data = json.dumps(getattr(self, field.name), default=encodeNestedObjects, indent=4)
designAttributes.add(INTERNAL_ID, field.name, data)

# There should be a way to clean this up - Brandon
def _makeObjectFromJson(self, objectType: type, data: any) -> any:
primitives = (bool, str, int, float, type(None))
if isinstance(objectType, EnumType):
return objectType(data)
elif (
objectType in primitives or type(data) in primitives
): # Required to catch `fusion.TriangleMeshQualityOptions`
return data
elif get_origin(objectType) is list:
return [self._makeObjectFromJson(objectType.__args__[0], item) for item in data]

newObject = objectType()
attrs = [x for x in dir(newObject) if not x.startswith("__") and not callable(getattr(newObject, x))]
for attr in attrs:
currType = objectType.__annotations__.get(attr, None)
if get_origin(currType) is list:
setattr(
newObject,
attr,
[self._makeObjectFromJson(currType.__args__[0], item) for item in data[attr]],
)
elif currType in primitives:
setattr(newObject, attr, data[attr])
elif isinstance(currType, object):
setattr(newObject, attr, self._makeObjectFromJson(currType, data[attr]))

return newObject
38 changes: 35 additions & 3 deletions exporter/SynthesisFusionAddin/src/Types.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import os
import pathlib
import platform
from dataclasses import dataclass, field
from enum import Enum
from typing import Union
from dataclasses import dataclass, field, fields, is_dataclass
from enum import Enum, EnumType
from typing import Union, get_origin

# Not 100% sure what this is for - Brandon
JointParentType = Enum("JointParentType", ["ROOT", "END"])
Expand Down Expand Up @@ -88,6 +88,38 @@ def toKg(pounds: float) -> KG:
return KG(round(pounds / 2.2062, 2))


PRIMITIVES = (bool, str, int, float, type(None))


def encodeNestedObjects(obj: any) -> any:
if isinstance(obj, Enum):
return obj.value
elif hasattr(obj, "__dict__"):
return {key: encodeNestedObjects(value) for key, value in obj.__dict__.items()}
else:
assert isinstance(obj, PRIMITIVES)
return obj


def makeObjectFromJson(objType: type, data: any) -> any:
if isinstance(objType, EnumType):
return objType(data)
elif isinstance(objType, PRIMITIVES) or isinstance(data, PRIMITIVES):
return data
elif get_origin(objType) is list:
return [makeObjectFromJson(objType.__args__[0], item) for item in data]

obj = objType()
assert is_dataclass(obj) and isinstance(data, dict), "Found unsupported type to decode."
for field in fields(obj):
if field.name in data:
setattr(obj, field.name, makeObjectFromJson(field.type, data[field.name]))
else:
setattr(obj, field.name, field.default)

return obj


class OString:
def __init__(self, path: object, fileName: str):
"""Generate a string for the operating system that matches fusion requirements
Expand Down

0 comments on commit bf4cdb4

Please sign in to comment.