예제 #1
0
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)
예제 #2
0
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)
예제 #3
0
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)
예제 #4
0
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))
예제 #5
0
def parse_comp_dir(comp_path, comp_class):
    return _create_subcomponents(comp_path,
                                 get_all_subclasses([comp_class]),
                                 create_from_search_dir=True)
예제 #6
0
    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.
예제 #7
0
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]