Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(serialize): Implement smarter loading so real exceptions are visible #296

Merged
merged 1 commit into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified dragonfly_grasshopper/icon/DF Load Objects.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions dragonfly_grasshopper/json/DF_Load_Objects.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.8.2",
"version": "1.8.3",
"nickname": "LoadObjects",
"outputs": [
[
Expand Down Expand Up @@ -29,7 +29,7 @@
}
],
"subcategory": "2 :: Serialize",
"code": "\nimport os\nimport io\nimport zipfile\nimport tempfile\nimport uuid\n\ntry: # import the core dragonfly dependencies\n import dragonfly.dictutil as df_dict_util\n from dragonfly.model import Model\n from dragonfly.config import folders\nexcept ImportError as e:\n raise ImportError('\\nFailed to import dragonfly:\\n\\t{}'.format(e))\n\ntry: # import the dragonfly_energy dependencies\n from dragonfly_energy.opendss.network import ElectricalNetwork, RoadNetwork\nexcept ImportError as e:\n raise ImportError('\\nFailed to import dragonfly_energy:\\n\\t{}'.format(e))\n\ntry: # import the core honeybee_energy dependencies\n import honeybee_energy.dictutil as energy_dict_util\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_energy:\\n\\t{}'.format(e))\n\ntry: # import the core honeybee_radiance dependencies\n import honeybee_radiance.dictutil as radiance_dict_util\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_radiance:\\n\\t{}'.format(e))\n\ntry: # import the core ladybug_{{cad}} dependencies\n from ladybug.futil import unzip_file\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, give_warning\n from ladybug_{{cad}}.config import units_system, tolerance\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\nimport json\n\n\ndef df_energy_dict_to_object(df_energy_dict, raise_exception=True):\n \"\"\"Re-serialize a dictionary of an object within dragonfly_energy.\n\n Args:\n df_energy_dict: A dictionary of a Dragonfly energy object. Note\n that this should be a non-abridged dictionary to be valid.\n raise_exception: Boolean to note whether an exception should be raised\n if the object is not identified as a part of dragonfly_energy.\n\n Returns:\n A Python object derived from the input df_energy_dict.\n \"\"\"\n try: # get the type key from the dictionary\n obj_type = df_energy_dict['type']\n except KeyError:\n raise ValueError('Dragonfly_energy dictionary lacks required \"type\" key.')\n\n if obj_type == 'ElectricalNetwork':\n return ElectricalNetwork.from_dict(df_energy_dict)\n elif obj_type == 'RoadNetwork':\n return RoadNetwork.from_dict(df_energy_dict)\n elif raise_exception:\n raise ValueError(\n '{} is not a recognized dragonfly energy object'.format(obj_type)\n )\n\n\ndef model_units_tolerance_check(model):\n \"\"\"Convert a model to the current {{Cad}} units and check the tolerance.\n\n Args:\n model: A dragonfly Model, which will have its units checked.\n \"\"\"\n # check the model units\n if model.units != units_system():\n print('Imported model units \"{}\" do not match that of the current {{Cad}} '\n 'model units \"{}\"\\nThe model is being automatically converted '\n 'to the {{Cad}} doc units.'.format(model.units, units_system()))\n model.convert_to_units(units_system())\n\n # check that the model tolerance is not too far from the {{Cad}} tolerance\n if model.tolerance / tolerance >= 100:\n msg = 'Imported Model tolerance \"{}\" is significantly coarser than the ' \\\n 'current {{Cad}} model tolerance \"{}\".\\nIt is recommended that the ' \\\n '{{Cad}} document tolerance be changed to be coarser and this ' \\\n 'component is re-reun.'.format(model.tolerance, tolerance)\n print msg\n give_warning(ghenv.Component, msg)\n\n\ndef version_check(data):\n \"\"\"Check the version of the object if it was included in the dictionary.\n\n This is most useful in cases of importing entire Models to make sure\n the Model isn't newer than the currently installed Dragonfly.\n\n Args:\n data: Dictionary of the object, which optionally has the \"version\" key.\n \"\"\"\n if 'version' in data and data['version'] is not None:\n model_ver = tuple(int(d) for d in data['version'].split('.'))\n df_ver = folders.dragonfly_schema_version\n if model_ver > df_ver:\n msg = 'Imported Model schema version \"{}\" is newer than that with the ' \\\n 'currently installed Dragonfly \"{}\".\\nThe Model may fail to import ' \\\n 'or (worse) some newer features of the Model might not be imported ' \\\n 'without detection.'.format(data['version'], folders.dragonfly_schema_version_str)\n print msg\n give_warning(ghenv.Component, msg)\n elif model_ver != df_ver:\n msg = 'Imported Model schema version \"{}\" is older than that with the ' \\\n 'currently installed Dragonfly \"{}\".\\nThe Model will be upgraded upon ' \\\n 'import.'.format(data['version'], folders.dragonfly_schema_version_str)\n print msg\n\n\nif all_required_inputs(ghenv.Component) and _load:\n # first, check whether the file is a Pollination Model Format (.POMF) file\n if zipfile.is_zipfile(_df_file):\n folder_name = str(uuid.uuid4())[:6]\n temp_dir = tempfile.gettempdir()\n folder_path = os.path.join(temp_dir, folder_name)\n os.mkdir(folder_path)\n unzip_file(_df_file, folder_path)\n _df_file = os.path.join(folder_path, 'model.json')\n\n # then\n with io.open(_df_file, encoding='utf-8') as inf:\n first_char = inf.read(1)\n second_char = inf.read(1)\n with io.open(_df_file, encoding='utf-8') as inf:\n if second_char == '{':\n inf.read(1)\n data = json.load(inf)\n\n version_check(data) # try to check the version\n try:\n df_objs = df_dict_util.dict_to_object(data, False) # re-serialize as a core object\n if df_objs is None: # try to re-serialize it as an energy object\n df_objs = df_energy_dict_to_object(data, False)\n if df_objs is None:\n df_objs = energy_dict_util.dict_to_object(data, False)\n if df_objs is None: # try to re-serialize it as a radiance object\n df_objs = radiance_dict_util.dict_to_object(data, False)\n elif isinstance(df_objs, Model):\n model_units_tolerance_check(df_objs)\n except ValueError: # no 'type' key; assume that its a group of objects\n df_objs = []\n for df_dict in data.values():\n df_obj = df_dict_util.dict_to_object(df_dict, False) # re-serialize as a core object\n if df_obj is None: # try to re-serialize it as an energy object\n df_objs = df_energy_dict_to_object(data, False)\n if df_obj is None:\n df_obj = energy_dict_util.dict_to_object(df_dict, False)\n if df_obj is None: # try to re-serialize it as a radiance object\n df_obj = radiance_dict_util.dict_to_object(df_dict, False)\n df_objs.append(df_obj)",
"code": "\nimport os\nimport io\nimport zipfile\nimport tempfile\nimport uuid\n\ntry: # import the core dragonfly dependencies\n import dragonfly.dictutil as df_dict_util\n from dragonfly.model import Model\n from dragonfly.config import folders\nexcept ImportError as e:\n raise ImportError('\\nFailed to import dragonfly:\\n\\t{}'.format(e))\n\ntry: # import the dragonfly_energy dependencies\n from dragonfly_energy.opendss.network import ElectricalNetwork, RoadNetwork\nexcept ImportError as e:\n raise ImportError('\\nFailed to import dragonfly_energy:\\n\\t{}'.format(e))\n\ntry: # import the core honeybee_energy dependencies\n import honeybee_energy.dictutil as energy_dict_util\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_energy:\\n\\t{}'.format(e))\n\ntry: # import the core honeybee_radiance dependencies\n import honeybee_radiance.dictutil as radiance_dict_util\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_radiance:\\n\\t{}'.format(e))\n\ntry: # import the core ladybug_{{cad}} dependencies\n from ladybug.futil import unzip_file\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, give_warning\n from ladybug_{{cad}}.config import units_system, tolerance\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\nimport json\n\n\ndef df_energy_dict_to_object(df_energy_dict, raise_exception=True):\n \"\"\"Re-serialize a dictionary of an object within dragonfly_energy.\n\n Args:\n df_energy_dict: A dictionary of a Dragonfly energy object. Note\n that this should be a non-abridged dictionary to be valid.\n raise_exception: Boolean to note whether an exception should be raised\n if the object is not identified as a part of dragonfly_energy.\n\n Returns:\n A Python object derived from the input df_energy_dict.\n \"\"\"\n try: # get the type key from the dictionary\n obj_type = df_energy_dict['type']\n except KeyError:\n raise ValueError('Dragonfly_energy dictionary lacks required \"type\" key.')\n\n if obj_type == 'ElectricalNetwork':\n return ElectricalNetwork.from_dict(df_energy_dict)\n elif obj_type == 'RoadNetwork':\n return RoadNetwork.from_dict(df_energy_dict)\n elif raise_exception:\n raise ValueError(\n '{} is not a recognized dragonfly energy object'.format(obj_type)\n )\n\n\ndef model_units_tolerance_check(model):\n \"\"\"Convert a model to the current {{Cad}} units and check the tolerance.\n\n Args:\n model: A dragonfly Model, which will have its units checked.\n \"\"\"\n # check the model units\n if model.units != units_system():\n print('Imported model units \"{}\" do not match that of the current {{Cad}} '\n 'model units \"{}\"\\nThe model is being automatically converted '\n 'to the {{Cad}} doc units.'.format(model.units, units_system()))\n model.convert_to_units(units_system())\n\n # check that the model tolerance is not too far from the {{Cad}} tolerance\n if model.tolerance / tolerance >= 100:\n msg = 'Imported Model tolerance \"{}\" is significantly coarser than the ' \\\n 'current {{Cad}} model tolerance \"{}\".\\nIt is recommended that the ' \\\n '{{Cad}} document tolerance be changed to be coarser and this ' \\\n 'component is re-reun.'.format(model.tolerance, tolerance)\n print msg\n give_warning(ghenv.Component, msg)\n\n\ndef version_check(data):\n \"\"\"Check the version of the object if it was included in the dictionary.\n\n This is most useful in cases of importing entire Models to make sure\n the Model isn't newer than the currently installed Dragonfly.\n\n Args:\n data: Dictionary of the object, which optionally has the \"version\" key.\n \"\"\"\n if 'version' in data and data['version'] is not None:\n model_ver = tuple(int(d) for d in data['version'].split('.'))\n df_ver = folders.dragonfly_schema_version\n if model_ver > df_ver:\n msg = 'Imported Model schema version \"{}\" is newer than that with the ' \\\n 'currently installed Dragonfly \"{}\".\\nThe Model may fail to import ' \\\n 'or (worse) some newer features of the Model might not be imported ' \\\n 'without detection.'.format(data['version'], folders.dragonfly_schema_version_str)\n print msg\n give_warning(ghenv.Component, msg)\n elif model_ver != df_ver:\n msg = 'Imported Model schema version \"{}\" is older than that with the ' \\\n 'currently installed Dragonfly \"{}\".\\nThe Model will be upgraded upon ' \\\n 'import.'.format(data['version'], folders.dragonfly_schema_version_str)\n print msg\n\n\nif all_required_inputs(ghenv.Component) and _load:\n # first, check whether the file is a Pollination Model Format (.POMF) file\n if zipfile.is_zipfile(_df_file):\n folder_name = str(uuid.uuid4())[:6]\n temp_dir = tempfile.gettempdir()\n folder_path = os.path.join(temp_dir, folder_name)\n os.mkdir(folder_path)\n unzip_file(_df_file, folder_path)\n _df_file = os.path.join(folder_path, 'model.json')\n\n # then\n with io.open(_df_file, encoding='utf-8') as inf:\n first_char = inf.read(1)\n second_char = inf.read(1)\n with io.open(_df_file, encoding='utf-8') as inf:\n if second_char == '{':\n inf.read(1)\n data = json.load(inf)\n\n version_check(data) # try to check the version\n if 'type' in data:\n df_objs = df_dict_util.dict_to_object(data, False) # re-serialize as a core object\n if df_objs is None: # try to re-serialize it as an energy object\n df_objs = df_energy_dict_to_object(data, False)\n if df_objs is None:\n df_objs = energy_dict_util.dict_to_object(data, False)\n if df_objs is None: # try to re-serialize it as a radiance object\n df_objs = radiance_dict_util.dict_to_object(data, False)\n elif isinstance(df_objs, Model):\n model_units_tolerance_check(df_objs)\n else: # no 'type' key; assume that its a group of objects\n df_objs = []\n for df_dict in data.values():\n df_obj = df_dict_util.dict_to_object(df_dict, False) # re-serialize as a core object\n if df_obj is None: # try to re-serialize it as an energy object\n df_objs = df_energy_dict_to_object(data, False)\n if df_obj is None:\n df_obj = energy_dict_util.dict_to_object(df_dict, False)\n if df_obj is None: # try to re-serialize it as a radiance object\n df_obj = radiance_dict_util.dict_to_object(df_dict, False)\n df_objs.append(df_obj)",
"category": "Dragonfly",
"name": "DF Load Objects",
"description": "Load any dragonfly object from a dragonfly JSON file\n-\nThis includes any Model, Building, Story, Room2D, WindowParameter, or ShadingParameter.\n-\nIt also includes any energy Material, Construction, ConstructionSet, Schedule, \nLoad, ProgramType, or Simulation object.\n-"
Expand Down
6 changes: 3 additions & 3 deletions dragonfly_grasshopper/src/DF Load Objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

ghenv.Component.Name = 'DF Load Objects'
ghenv.Component.NickName = 'LoadObjects'
ghenv.Component.Message = '1.8.2'
ghenv.Component.Message = '1.8.3'
ghenv.Component.Category = 'Dragonfly'
ghenv.Component.SubCategory = '2 :: Serialize'
ghenv.Component.AdditionalHelpFromDocStrings = '2'
Expand Down Expand Up @@ -172,7 +172,7 @@ def version_check(data):
data = json.load(inf)

version_check(data) # try to check the version
try:
if 'type' in data:
df_objs = df_dict_util.dict_to_object(data, False) # re-serialize as a core object
if df_objs is None: # try to re-serialize it as an energy object
df_objs = df_energy_dict_to_object(data, False)
Expand All @@ -182,7 +182,7 @@ def version_check(data):
df_objs = radiance_dict_util.dict_to_object(data, False)
elif isinstance(df_objs, Model):
model_units_tolerance_check(df_objs)
except ValueError: # no 'type' key; assume that its a group of objects
else: # no 'type' key; assume that its a group of objects
df_objs = []
for df_dict in data.values():
df_obj = df_dict_util.dict_to_object(df_dict, False) # re-serialize as a core object
Expand Down
Binary file modified dragonfly_grasshopper/user_objects/DF Load Objects.ghuser
Binary file not shown.