def _make_sub_cmp_from_cache(parent_cmp, cached_sub_cmps): mlogger.debug('Processing cache for: %s', parent_cmp) # get allowed classes under this component allowed_sub_cmps = get_all_subclasses(parent_cmp.allowed_sub_cmps) mlogger.debug('Allowed sub components are: %s', allowed_sub_cmps) # iterate through list of cached sub components for cached_cmp in cached_sub_cmps: # type: dict for sub_class in allowed_sub_cmps: if sub_class.type_id == cached_cmp[gencomps.TYPE_ID_KEY]: mlogger.debug('Creating sub component from cache: %s, %s', cached_cmp[gencomps.NAME_KEY], sub_class) # cached_cmp might contain gencomps.SUB_CMP_KEY. This needs to be # removed since this function will make all the children # recursively. So if this component has gencomps.SUB_CMP_KEY means # it has sub components: sub_cmp_cache = None if gencomps.SUB_CMP_KEY in cached_cmp.keys(): # drop subcomponents dict from cached_cmp since we # don't want the loaded_cmp to include this sub_cmp_cache = cached_cmp.pop(gencomps.SUB_CMP_KEY) # create sub component from cleaned cached_cmp loaded_cmp = sub_class() loaded_cmp.load_cache_data(cached_cmp) # now process sub components for loaded_cmp if any if sub_cmp_cache: _make_sub_cmp_from_cache(loaded_cmp, sub_cmp_cache) parent_cmp.add_component(loaded_cmp)
def _parse_for_components(component): """Recursively parses _get_component.directory for components of type _get_component.allowed_sub_cmps This method uses get_all_subclasses() to get a list of all subclasses of _get_component.allowed_sub_cmps type. This ensures that if any new type of component_class is added later, this method does not need to be updated as the new sub-class will be listed by .__subclasses__() method of the parent class and this method will check the directory for its .type_id """ for new_cmp in _create_subcomponents( component.directory, get_all_subclasses(component.allowed_sub_cmps)): # add the successfulyl created _get_component to the parent _get_component component.add_component(new_cmp) if new_cmp.is_container: # Recursive part: parse each sub-_get_component for its allowed sub-sub-components. _parse_for_components(new_cmp)
def get_auto_filters(record_list): """ Returns a list of RecordFilter objects. This function works on the input list of usage records. This function traverses the usage records list, finds the parameters on each record object and creates a filter object for each (if a subclass of RecordFilter is available to that parameter) Any of the filter objects returned from this function, can be passed to the db.get_records() method to filter the usage record data. Example of typical use: >>> from pyrevit.usagelog import db, filters >>> all_unfiltered_records = db.get_records() >>> filter_list = filters.get_auto_filters(all_unfiltered_records) >>> chosen_filter = filter_list[0] # type: RecordFilter >>> filtered_records = db.get_records(record_filter=chosen_filter) Args: record_list (list): list of UsageRecord objects Returns: list: returns a list of RecordFilter objects, sorted; Empty list if no filters could be created. """ # lets find all subclasses of the RecordFilter class (all custom filters) filter_types = get_all_subclasses([RecordFilter]) # and make a filter dictionary based on the filter parameter names # so filters_dict['commandname'] returns a filter that filters the # records based on their 'commandname' property filters_dict = {f.filter_param: f for f in filter_types} # make a filter list and add the `None` filter to it. auto_filters = set() auto_filters.add(RecordNoneFilter()) for record in record_list: # find parameters in the record object for param, value in record.__dict__.items(): if param in filters_dict: # and if a filter is provided for that parameter, # setup the filter and add to the list. logger.debug('Adding filter: param={} value={}'.format( param, value)) auto_filters.add(filters_dict[param](value)) # return a sorted list of filters for ease of use return sorted(auto_filters)
def serialize(api_object): mlogger.debug('Attemping to serialize: %s', api_object) # wrap none in a none serializer for none values if api_object is None: return NoneSerializer() # make sure given type is a Revit API type if not api.is_api_object(api_object): raise PyRevitException("Only Revit API types are supported.") # get available serializers serializers = coreutils.get_all_subclasses( [Serializable, EnumSerializable]) # pick the compatible serializer try: compatible_serializer = \ next( x for x in serializers if x.api_types and isinstance(api_object, x.api_types) ) mlogger.debug('Serializer found for: %s', api_object) return compatible_serializer(api_object) except StopIteration: mlogger.debug('Serializer not found for: %s', api_object) # if no deserializer found, # see if given data is iterable # NOTE: commented this out since .serialize should only get api objects # if isinstance(api_object, Iterable): # mlogger.debug('Iterating over: %s', api_object) # return _serialize_items(api_object) # otherwise throw an exception raise PyRevitException( "No serializers have been implemented for \"%s\"" % repr(api_object))
def parse_comp_dir(comp_path, comp_class): return _create_subcomponents(comp_path, get_all_subclasses([comp_class]), create_from_search_dir=True)
human-readable code name. """ filter_param = 'resultcode' name_template = 'Result Code: {}' def __init__(self, filter_value): RecordFilter.__init__(self, filter_value) # overrides filter_name to convert the integer result code # to human-readable codename self.filter_name = self.name_template\ .format(RESULT_DICT[self.filter_value]) # lets find all subclasses of the RecordFilter class (all custom filters) filter_types = get_all_subclasses([RecordFilter]) # and make a filter dictionary based on the filter parameter names # so FILTERS_DICT['commandname'] returns a filter that filters the # records based on their 'commandname' property FILTERS_DICT = {f.filter_param: f for f in filter_types} def get_auto_filters(record_list): """ Returns a list of RecordFilter objects. This function works on the input list of usage records. This function traverses the usage records list, finds the parameters on each record object and creates a filter object for each (if a subclass of RecordFilter is available to that parameter) Any of the filter objects returned from this function, can be passed to the db.get_records() method to filter the usage record data.
def _get_subcomponents_classes(parent_classes): """Find available subcomponents for given parent types.""" return [x for x in get_all_subclasses(parent_classes) if x.type_id]