def _value_to_graph_object(self, key, value, _raise=True): """ Attempt to convert value to graph object. :param (str|unicode) key: Should be an object_name from GRAPH_REFERENCE :param (dict) value: This will fail if it's not a dict. :param (bool) _raise: Flag to prevent inappropriate erring. :return: (PlotlyList|PlotlyDict|None) `None` if `_raise` and failure. """ if key in graph_reference.ARRAYS: val_types = (list, ) else: val_types = (dict, ) if not isinstance(value, val_types): if _raise: path = self._get_path() + (key, ) raise exceptions.PlotlyDictValueError(self, path) else: return # this can be `None` when `_raise == False` return GraphObjectFactory.create(key, value, _raise=_raise, _parent=self, _parent_key=key)
def validate(self, caller=True): # TODO: validate values too? """Recursively check the validity of the keys in a PlotlyDict. The valid keys constitute the entries in each object dictionary in graph_objs_meta.json The validation process first requires that all nested collections be converted to the appropriate subclass of PlotlyDict/PlotlyList. Then, each of these objects call `validate` and so on, recursively, until the entire object has been validated. """ if caller: # change everything to 'checkable' objs try: self.to_graph_objs(caller=False) except exceptions.PlotlyGraphObjectError as err: err.prepare() raise obj_key = NAME_TO_KEY[self.__class__.__name__] for key, val in list(self.items()): if isinstance(val, (PlotlyDict, PlotlyList)): try: val.validate(caller=False) except exceptions.PlotlyGraphObjectError as err: err.add_to_error_path(key) err.prepare() raise else: if key in INFO[obj_key]['keymeta'].keys(): if 'key_type' not in INFO[obj_key]['keymeta'][key].keys(): continue # TODO: 'type' may not be documented yet! if INFO[obj_key]['keymeta'][key]['key_type'] == 'object': try: val_types = ( INFO[obj_key]['keymeta'][key]['val_types']) except KeyError: val_types = 'undocumented' raise exceptions.PlotlyDictValueError( obj=self, key=key, value=val, val_types=val_types ) else: matching_objects = [obj for obj in INFO if key in INFO[obj]['keymeta']] notes = '' if len(matching_objects): notes += "That key is valid only in these objects:\n\n" for obj in matching_objects: notes += "\t{0}".format(KEY_TO_NAME[obj]) try: notes += '({0}="{1}")\n'.format( repr(key), INFO[obj]['keymeta'][key]['val_types']) except KeyError: notes += '({0}="..")\n'.format(repr(key)) notes.expandtabs() else: notes += ("Couldn't find uses for key: {0}\n\n" "".format(repr(key))) raise exceptions.PlotlyDictKeyError(obj=self, key=key, notes=notes)
def to_graph_objs(self, caller=True): """Walk obj, convert dicts and lists to plotly graph objs. For each key in the object, if it corresponds to a special key that should be associated with a graph object, the ordinary dict or list will be reinitialized as a special PlotlyDict or PlotlyList of the appropriate `kind`. """ info_key = NAME_TO_KEY[self.__class__.__name__] keys = self.keys() updated_keys = graph_objs_tools.update_keys(keys) for k_old, k_new in zip(keys, updated_keys): if k_old != k_new: self[k_new] = self.pop(k_old) warnings.warn( "\n" "The key, '{old}', has been depreciated, it's been " "converted to '{new}'. You should change your code to use " "'{new}' in the future." "".format(old=k_old, new=k_new) ) for key in updated_keys: if isinstance(self[key], (PlotlyDict, PlotlyList)): try: self[key].to_graph_objs(caller=False) except exceptions.PlotlyGraphObjectError as err: err.add_to_error_path(key) err.prepare() raise elif (key in INFO[info_key]['keymeta'].keys() and 'key_type' in INFO[info_key]['keymeta'][key].keys()): if INFO[info_key]['keymeta'][key]['key_type'] == 'object': class_name = KEY_TO_NAME[key] obj = get_class_instance_by_name(class_name) if isinstance(obj, PlotlyDict): if not isinstance(self[key], dict): try: val_types = ( INFO[info_key]['keymeta'][key]['val_types'] ) except KeyError: val_types = 'undocumented' raise exceptions.PlotlyDictValueError( obj=self, key=key, value=self[key], val_types=val_types, notes="value needs to be dictionary-like" ) for k, v in list(self.pop(key).items()): obj[k] = v # finish up momentarily... else: # if not PlotlyDict, it MUST be a PlotlyList if not isinstance(self[key], list): try: val_types = ( INFO[info_key]['keymeta'][key]['val_types'] ) except KeyError: val_types = 'undocumented' raise exceptions.PlotlyDictValueError( # TODO!!! obj=self, key=key, value=self[key], val_types=val_types, notes="value needs to be list-like" ) obj += self.pop(key) try: obj.to_graph_objs(caller=False) except exceptions.PlotlyGraphObjectError as err: err.add_to_error_path(key) err.prepare() raise self[key] = obj # whew! made it!