Source code for honeybee.checkdup

# coding=utf-8
"""Utilities to check whether there are any duplicate values in a list of ids."""

import collections


[docs] def check_duplicate_identifiers( objects_to_check, raise_exception=True, obj_name='', detailed=False, code='000000', extension='Core', error_type='Duplicate Object Identifier'): """Check whether there are duplicated identifiers across a list of objects. Args: objects_to_check: A list of honeybee objects across which duplicate identifiers will be checked. raise_exception: Boolean to note whether an exception should be raised if duplicated identifiers are found. (Default: True). obj_name: An optional name for the object to be included in the error message. Fro example, 'Room', 'Face', 'Aperture'. detailed: Boolean for whether the returned object is a detailed list of dicts with error info or a string with a message. (Default: False). code: Text for the error code. (Default: 0000). extension: Text for the name of the Honeybee extension for which duplicate identifiers are being evaluated. (Default: Core). error_type: Text for the type of error. This should be directly linked to the error code and should simply be a human-readable version of the error code. (Default: Unknown Error). Returns: A message string indicating the duplicated identifiers (if detailed is False) or a list of dictionaries with information about the duplicated identifiers (if detailed is True). This string (or list) will be empty if no duplicates were found. """ detailed = False if raise_exception else detailed obj_id_iter = (obj.identifier for obj in objects_to_check) dup = [t for t, c in collections.Counter(obj_id_iter).items() if c > 1] if len(dup) != 0: if detailed: # find the object display names dis_names = [] for obj_id in dup: dis_name = None for obj in objects_to_check: if obj.identifier == obj_id: dis_name = obj.display_name dis_names.append(dis_name) err_list = [] for dup_id, dis_name in zip(dup, dis_names): msg = 'There is a duplicated {} identifier: {}'.format(obj_name, dup_id) dup_dict = { 'type': 'ValidationError', 'code': code, 'error_type': error_type, 'extension_type': extension, 'element_type': obj_name, 'element_id': [dup_id], 'message': msg } if dis_name is not None: dup_dict['element_name'] = [dis_name] err_list.append(dup_dict) return err_list msg = 'The following duplicated {} identifiers were found:\n{}'.format( obj_name, '\n'.join(dup)) if raise_exception: raise ValueError(msg) return msg return [] if detailed else ''
[docs] def check_duplicate_identifiers_parent( objects_to_check, raise_exception=True, obj_name='', detailed=False, code='000000', extension='Core', error_type='Duplicate Object Identifier'): """Check whether there are duplicated identifiers across a list of objects. The error message will include the identifiers of top-level parents in order to make it easier to find the duplicated objects in the model. Args: objects_to_check: A list of honeybee objects across which duplicate identifiers will be checked. These objects must have the ability to have parents for this method to run correctly. raise_exception: Boolean to note whether an exception should be raised if duplicated identifiers are found. (Default: True). obj_name: An optional name for the object to be included in the error message. For example, 'Room', 'Face', 'Aperture'. detailed: Boolean for whether the returned object is a detailed list of dicts with error info or a string with a message. (Default: False). code: Text for the error code. (Default: 0000). extension: Text for the name of the Honeybee extension for which duplicate identifiers are being evaluated. (Default: Core). error_type: Text for the type of error. This should be directly linked to the error code and should simply be a human-readable version of the error code. (Default: Unknown Error). Returns: A message string indicating the duplicated identifiers (if detailed is False) or a list of dictionaries with information about the duplicated identifiers (if detailed is True). This string (or list) will be empty if no duplicates were found. """ detailed = False if raise_exception else detailed obj_id_iter = (obj.identifier for obj in objects_to_check) dup = [t for t, c in collections.Counter(obj_id_iter).items() if c > 1] if len(dup) != 0: # find the relevant top-level parents top_par, dis_names = [], [] for obj_id in dup: rel_parents, dis_name = [], None for obj in objects_to_check: if obj.identifier == obj_id: dis_name = obj.display_name if obj.has_parent: try: par_obj = obj.top_level_parent except AttributeError: par_obj = obj.parent rel_parents.append(par_obj) top_par.append(rel_parents) dis_names.append(dis_name) # if a detailed dictionary is requested, then create it if detailed: err_list = [] for dup_id, dis_name, rel_par in zip(dup, dis_names, top_par): dup_dict = { 'type': 'ValidationError', 'code': code, 'error_type': error_type, 'extension_type': extension, 'element_type': obj_name, 'element_id': [dup_id] } if dis_name is not None: dup_dict['element_name'] = [dis_name] msg = 'There is a duplicated {} identifier: {}'.format(obj_name, dup_id) if len(rel_par) != 0: dup_dict['top_parents'] = [] msg += '\n Relevant Top-Level Parents:\n' for par_o in rel_par: par_dict = { 'parent_type': par_o.__class__.__name__, 'id': par_o.identifier, 'name': par_o.display_name } dup_dict['top_parents'].append(par_dict) msg += ' {} "{}"\n'.format( par_o.__class__.__name__, par_o.full_id) dup_dict['message'] = msg err_list.append(dup_dict) return err_list # if just an error message is requested, then build it from the information msg = 'The following duplicated {} identifiers were found:\n'.format(obj_name) for obj_id, rel_par in zip(dup, top_par): obj_msg = obj_id + '\n' if len(rel_par) != 0: obj_msg += ' Relevant Top-Level Parents:\n' for par_o in rel_par: obj_msg += ' {} "{}"\n'.format( par_o.__class__.__name__, par_o.full_id) msg += obj_msg msg = msg.strip() if raise_exception: raise ValueError(msg) return msg return [] if detailed else ''
[docs] def is_equivalent(object_1, object_2): """Check if two objects are equal with an initial check for the same instance. """ if object_1 is object_2: # first see if they're the same instance return True return object_1 == object_2 # two objects that should have == operators