def value(self, value): if self._revit_object.IsReadOnly: raise RpwException('Parameter is Read Only: {}'.format( self._revit_object.Definition.Name)) # Check if value provided matches storage type if not isinstance(value, self.type): # If not, try to handle if self.type is str and value is None: value = '' if self.type is str and value is not None: value = str(value) elif self.type is DB.ElementId and value is None: value = DB.ElementId.InvalidElementId elif isinstance(value, int) and self.type is float: value = float(value) elif isinstance(value, float) and self.type is int: value = int(value) elif isinstance(value, bool) and self.type is int: value = int(value) else: raise RpwWrongStorageType(self.type, value) param = self._revit_object.Set(value) return param
def collect(cls, **kwargs): """ Collect all elements of the wrapper using the default collector. This method is defined on the main Element wrapper, but the collector parameters are defined in each wrapper. For example, :any:`WallType` uses the `_collector_params`: {'of_class': DB.WallType, 'is_type': True} These default collector parameters can be overriden by passing keyword args to the collectors call. >>> from rpw import db >>> wall_types_collector = db.WallType.collect() <rpw:Collector % FilteredElementCollector [count:4]> >>> wall_types_collector.get_elements() # All Wall Types [<rpw:WallType [name:Wall 1] [id:1557]>, ... ] >>> wall_types_collector.get_elements() [<rpw:Area % DB.Area | Rentable:30.2>] >>> rooms = db.WallInstance.collect(level="Level 1") [<rpw:WallInstance % DB.Wall symbol:Basic Wall>] """ _collector_params = getattr(cls, '_collector_params', None) if _collector_params: kwargs.update(_collector_params) return rpw.db.Collector(**kwargs) else: raise RpwException('Wrapper cannot collect by class: {}'.format(cls.__name__))
def value(self): """ Gets Parameter Value: Returns: type: parameter value in python type >>> desk.parameters['Height'].value >>> 3.0 Sets Parameter Value (must be in Transaction Context): >>> desk.parameters['Height'].value = 3 Note: `Parameter` value setter automatically handles a few type castings: * Storage is ``str`` and value is ``None``; value is converted to ``blank_string`` * Storage is ``str`` and value is ``any``; value is converted to ``string`` * Storage is ``ElementId`` and value is ``None``; value is converted to ``ElemendId.InvalidElementId`` * Storage is ``int`` and value is ``float``; value is converted to ``int`` * Storage is ``float`` and value is ``int``; value is converted to ``float`` """ if self.type is str: return self._revit_object.AsString() if self.type is float: return self._revit_object.AsDouble() if self.type is DB.ElementId: return self._revit_object.AsElementId() if self.type is int: return self._revit_object.AsInteger() raise RpwException('could not get storage type: {}'.format(self.type))
def __init__(self, **filters): """ Args: **filters (``keyword args``): Scope and filters Returns: Collector (:any:`Collector`): Collector Instance Scope Options: * ``view`` `(DB.View)`: View Scope (Optional) * ``element_ids`` `([ElementId])`: List of Element Ids to limit Collector Scope * ``elements`` `([Element])`: List of Elements to limit Collector Scope Warning: Only one scope filter should be used per query. If more then one is used, only one will be applied, in this order ``view`` > ``elements`` > ``element_ids`` Filter Options: * is_type (``bool``): Same as ``WhereElementIsElementType`` * is_not_type (``bool``): Same as ``WhereElementIsNotElementType`` * of_class (``Type``): Same as ``OfClass``. Type can be ``DB.SomeType`` or string: ``DB.Wall`` or ``'Wall'`` * of_category (``BuiltInCategory``): Same as ``OfCategory``. Can be ``DB.BuiltInCategory.OST_Wall`` or ``'Wall'`` * owner_view (``DB.ElementId, View`): ``WhereElementIsViewIndependent(True)`` * is_view_independent (``bool``): ``WhereElementIsViewIndependent(True)`` * family (``DB.ElementId``, ``DB.Element``): Element or ElementId of Family * symbol (``DB.ElementId``, ``DB.Element``): Element or ElementId of Symbol * level (``DB.Level``, ``DB.ElementId``, ``Level Name``): Level, ElementId of Level, or Level Name * not_level (``DB.Level``, ``DB.ElementId``, ``Level Name``): Level, ElementId of Level, or Level Name * parameter_filter (:any:`ParameterFilter`): Applies ``ElementParameterFilter`` * exclude (`element_references`): Element(s) or ElementId(s) to exlude from result * and_collector (``collector``): Collector to intersect with. Elements must be present in both * or_collector (``collector``): Collector to Union with. Elements must be present on of the two. * where (`function`): function to test your elements against """ # Define Filtered Element Collector Scope + Doc collector_doc = filters.pop('doc') if 'doc' in filters else revit.doc if 'view' in filters: view = filters.pop('view') view_id = view if isinstance(view, DB.ElementId) else view.Id collector = DB.FilteredElementCollector(collector_doc, view_id) elif 'elements' in filters: elements = filters.pop('elements') element_ids = to_element_ids(elements) collector = DB.FilteredElementCollector(collector_doc, List[DB.ElementId](element_ids)) elif 'element_ids' in filters: element_ids = filters.pop('element_ids') collector = DB.FilteredElementCollector(collector_doc, List[DB.ElementId](element_ids)) else: collector = DB.FilteredElementCollector(collector_doc) super(Collector, self).__init__(collector) for key in filters.keys(): if key not in [f.keyword for f in FilterClasses.get_sorted()]: raise RpwException('Filter not valid: {}'.format(key)) self._collector = self._collect(collector_doc, collector, filters)
def name(self): """ Returns: ``str``: name of the Family """ # This BIP only exist in symbols, so we retrieve a symbol first. # The Alternative is to use Element.Name.GetValue(), but I am # avoiding it due to the import bug in ironpython # https://github.com/IronLanguages/ironpython2/issues/79 try: symbol = self.symbols[0] except IndexError: raise RpwException('Family [{}] has no symbols'.format(self.name)) return Element( symbol).parameters.builtins['SYMBOL_FAMILY_NAME_PARAM'].value
def __getattr__(self, attr): """ Getter for original methods and properties or the element. This method is only called if the attribute name does not already exists. """ try: return getattr(self.__dict__['_revit_object'], attr) # except AttributeError: # This lower/snake case to be converted. # This automatically gives acess to all names in lower case format # x.name (if was not already defined, will get x.Name) # Note: will not Work for setters, unless defined by wrapper # attr_pascal_case = rpw.utils.coerce.to_pascal_case(attr) # return getattr(self.__dict__['_revit_object'], attr_pascal_case) except KeyError: raise RpwException('BaseObjectWrapper is missing _revit_object')
def __new__(cls, element, **kwargs): """ Factory Constructor will chose the best Class for the Element. This function iterates through all classes in the rpw.db module, and will find one that wraps the corresponding class. If and exact match is not found :any:`Element` is used """ defined_wrapper_classes = rpw.db.__all__ _revit_object_class = cls._revit_object_class if element is None: raise RpwTypeError('Element or Element Child', 'None') # TODO: Handle double wrapping if hasattr(element, 'unwrap'): raise RpwTypeError('revit element', 'wrapped element: {}'.format(element)) # Ensure Wrapped Element is instance of Class Wrapper or decendent if not isinstance(element, _revit_object_class): raise RpwTypeError(_revit_object_class.__name__, element.__class__.__name__) # Ensure Wrapped Element is instance of Class Wrapper or decendent if not isinstance(element, _revit_object_class): raise RpwTypeError(_revit_object_class, element.__class__) # If explicit constructor was called, use that and skip discovery if type(element) is _revit_object_class: return super(Element, cls).__new__(cls, element, **kwargs) for wrapper_class in defined_wrapper_classes: class_name = wrapper_class.__name__ if type(element) is getattr(wrapper_class, '_revit_object_class', None): # Found Mathing Class, Use Wrapper # print('Found Mathing Class, Use Wrapper: {}'.format(class_name)) return super(Element, cls).__new__(wrapper_class, element, **kwargs) else: # Could Not find a Matching Class, Use Element if related return super(Element, cls).__new__(cls, element, **kwargs) # No early return. Should not reach this point element_class_name = element.__class__.__name__ raise RpwException('Factory does not support type: {}'.format(element_class_name))
def collect(cls, **kwargs): """ Collect all elements of the wrapper, using the default collector. Collector will use default params (ie: Room ``{'of_category': 'OST_rooms'}``). These can be overriden by passing keyword args to the collectors call. >>> rooms = rpw.db.Rooms.collect() [<rpw:Room % DB.Room | Room:1>] >>> rooms = rpw.db.Area.collect() [<rpw:Area % DB.Area | Rentable:30.2>] >>> rooms = rpw.db.WallInstance.collect(level="Level 1") [<rpw:WallInstance % DB.Wall symbol:Basic Wall>] """ _collector_params = getattr(cls, '_collector_params', None) if _collector_params: kwargs.update(_collector_params) return rpw.db.Collector(**kwargs) else: raise RpwException('Wrapper cannot collect by class: {}'.format( cls.__name__))
def __new__(cls, element, **kwargs): """ Factory Constructor will chose the best Class for the Element. This function iterates through all classes in the rpw.db module, and will find one that wraps the corresponding class. If and exact match is not found :any:`Element` is used """ defined_wrapper_classes = inspect.getmembers(rpw.db, inspect.isclass) # [('Area', '<class Area>'), ... ] _revit_object_class = cls._revit_object_class if element is None: raise RpwTypeError('Element or Element Child', 'None') # Ensure Wrapped Element is instance of Class Wrapper or decendent # Must also check is element because isinstance(Element, Element) is False if not isinstance(element, _revit_object_class): # or cls is not Element: raise RpwTypeError(_revit_object_class, type(element)) # rpw.ui.forms.Console() for class_name, wrapper_class in defined_wrapper_classes: if type(element) is getattr(wrapper_class, '_revit_object_class', None): # Found Mathing Class, Use Wrapper # print('Found Mathing Class, Use Wrapper: {}'.format(class_name)) return super(Element, cls).__new__(wrapper_class, element, **kwargs) # new_obj._revit_object = element # return new_object else: # Could Not find a Matching Class, Use Element if related # print('Did not find a Matching Class, will use Element if related') if DB.Element in inspect.getmro(element.__class__): return super(Element, cls).__new__(cls, element, **kwargs) element_class_name = element.__class__.__name__ raise RpwException( 'Factory does not support type: {}'.format(element_class_name))
def __new__(cls, element, **kwargs): """ Factory Constructor will chose the best Class for the Element. This function iterates through all classes in the rpw.db module, and will find one that wraps the corresponding class. If and exact match is not found :any:`Element` is used """ defined_wrapper_classes = rpw.db.__all__ _revit_object_class = cls._revit_object_class if element is None: raise RpwTypeError('Element or Element Child', 'None') # Ensure Wrapped Element is instance of Class Wrapper or decendent # Must also check is element because isinstance(Element, Element) is False if not isinstance(element, _revit_object_class): # or cls is not Element: raise RpwTypeError('DB.Element child', element.__class__.__name__) # TODO: OPtimize so if its right type, no need to iterate: rpw.db.Wall(wall) for wrapper_class in defined_wrapper_classes: class_name = wrapper_class.__name__ if type(element) is getattr(wrapper_class, '_revit_object_class', None): # Found Mathing Class, Use Wrapper # print('Found Mathing Class, Use Wrapper: {}'.format(class_name)) return super(Element, cls).__new__(wrapper_class, element, **kwargs) else: # Could Not find a Matching Class, Use Element if related if DB.Element in inspect.getmro(element.__class__): return super(Element, cls).__new__(cls, element, **kwargs) # No early return. Should not reach this point element_class_name = element.__class__.__name__ raise RpwException( 'Factory does not support type: {}'.format(element_class_name))
def __init__(self, parameter_reference, **conditions): """ Creates Parameter Filter Rule >>> param_rule = ParameterFilter(param_id, equals=2) >>> param_rule = ParameterFilter(param_id, not_equals='a', case_sensitive=True) >>> param_rule = ParameterFilter(param_id, not_equals=3, reverse=True) Args: param_id(DB.ElementID): ElementId of parameter **conditions: Filter Rule Conditions and options. conditions: | ``begins``, ``not_begins`` | ``contains``, ``not_contains`` | ``ends``, ``not_ends`` | ``equals``, ``not_equals`` | ``less``, ``not_less`` | ``less_equal``, ``not_less_equal`` | ``greater``, ``not_greater`` | ``greater_equal``, ``not_greater_equal`` options: | ``case_sensitive``: Enforces case sensitive, String only | ``reverse``: Reverses result of Collector """ parameter_id = self.coerce_param_reference(parameter_reference) reverse = conditions.get('reverse', False) case_sensitive = conditions.get('case_sensitive', ParameterFilter.CASE_SENSITIVE) precision = conditions.get('precision', ParameterFilter.FLOAT_PRECISION) for condition in conditions.keys(): if condition not in ParameterFilter.RULES: raise RpwException('Rule not valid: {}'.format(condition)) rules = [] for condition_name, condition_value in conditions.iteritems(): # Returns on of the CreateRule factory method names above rule_factory_name = ParameterFilter.RULES.get(condition_name) filter_value_rule = getattr(DB.ParameterFilterRuleFactory, rule_factory_name) args = [condition_value] if isinstance(condition_value, str): args.append(case_sensitive) if isinstance(condition_value, float): args.append(precision) filter_rule = filter_value_rule(parameter_id, *args) if 'not_' in condition_name: filter_rule = DB.FilterInverseRule(filter_rule) logger.debug('ParamFilter Conditions: {}'.format(conditions)) logger.debug('Case sensitive: {}'.format(case_sensitive)) logger.debug('Reverse: {}'.format(reverse)) logger.debug('ARGS: {}'.format(args)) logger.debug(filter_rule) logger.debug(str(dir(filter_rule))) rules.append(filter_rule) if not rules: raise RpwException('malformed filter rule: {}'.format(conditions)) _revit_object = DB.ElementParameterFilter(List[DB.FilterRule](rules), reverse) super(ParameterFilter, self).__init__(_revit_object) self.conditions = conditions