def check(value): value = cast_value(attrib_def.code, value) if not attrib_def.is_valid_value(value): if attrib_def.fixer: value = attrib_def.fixer(value) logger.debug(f'Fixed invalid attribute "{key}" in entity' f' {entity()} to "{str(value)}".') else: raise const.DXFValueError( f'Invalid value {str(value)} for attribute "{key}" in ' f'entity {entity()}.') return value
def __setattr__(self, key: str, value: Any) -> None: attrib_def = self.dxfattribs.get(key, None) # type: DXFAttr if attrib_def: if attrib_def.xtype == XType.callback: attrib_def.set_callback_value(self._entity, value) else: self.__dict__[key] = cast_value(attrib_def.code, value) else: raise DXFAttributeError(ERR_INVALID_DXF_ATTRIB.format(key, self.dxftype)) if key in SETTER_EVENTS: handler = getattr(self._entity, SETTER_EVENTS[key], None) if handler: handler(value)
def fast_load_dxfattribs(self, dxf: DXFNamespace, group_code_mapping: Dict[int, Union[str, List]], subclass: Union[int, str, Tags], *, recover=False, log=True) -> Tags: """ Load DXF attributes into the DXF namespace and returns the unprocessed tags without leading subclass marker(100, AcDb...). Bypasses the DXF attribute validity checks. Args: dxf: entity DXF namespace group_code_mapping: group code to DXF attribute name mapping, callback attributes have to be marked with a leading "*" subclass: subclass by index, by name or as Tags() recover: recover graphic attributes log: enable/disable logging of unprocessed tags """ if self.r12: tags = self.subclasses[0] else: if isinstance(subclass, int): tags = self.subclass_by_index(subclass) elif isinstance(subclass, str): tags = self.find_subclass(subclass) else: tags = subclass unprocessed_tags = Tags() if tags is None or len(tags) == 0: return unprocessed_tags processed_names = set() # Localize attributes: get_attrib_name = group_code_mapping.get append_unprocessed_tag = unprocessed_tags.append unprotected_set_attrib = dxf.unprotected_set mark_attrib_as_processed = processed_names.add # Ignore (100, "AcDb...") or (0, "ENTITY") tag in case of DXF R12 start = 1 if tags[0].code in (0, 100) else 0 for tag in tags[start:]: name = get_attrib_name(tag.code) if isinstance(name, list): # process group code duplicates: names = name # If all existing attrib names are used, treat this tag # like an unprocessed tag. name = None # The attribute names are processed in the order of their # definition: for name_ in names: if name_ not in processed_names: name = name_ mark_attrib_as_processed(name_) break if name: # Ignore callback attributes and group codes explicit marked # as "*IGNORE": if name[0] != '*': unprotected_set_attrib(name, cast_value(tag.code, tag.value)) else: append_unprocessed_tag(tag) if self.r12: # R12 has always unprocessed tags, because there are all tags in one # subclass and one subclass definition never covers all tags e.g. # handle is processed in DXFEntity, so it is an unprocessed tag in # AcDbEntity. return unprocessed_tags # Only DXF R13+ if recover and len(unprocessed_tags): unprocessed_tags = recover_graphic_attributes( unprocessed_tags, dxf) if len(unprocessed_tags) and log: # First tag is the subclass specifier (100, "AcDb...") name = tags[0].value self.log_unprocessed_tags(tags, subclass=name, handle=dxf.get('handle')) return unprocessed_tags