def test_attributes(): class A(Element): pass A.a = attribute("a", bytes, "default") a = A() assert a.a == "default", a.a a.a = "bar" assert a.a == "bar", a.a del a.a assert a.a == "default" try: a.a = 1 except AttributeError: pass # ok else: assert 0, "should not set integer"
def test_derivedunion_listmixins(): class A(Element): pass A.a = association("a", A) A.b = association("b", A) A.u = derivedunion(A, "u", A, 0, "*", A.a, A.b) A.name = attribute("name", str, "default") a = A() a.a = A() a.a = A() a.b = A() a.a[0].name = "foo" a.a[1].name = "bar" a.b[0].name = "baz" assert list(a.a[:].name) == ["foo", "bar"] assert sorted(list(a.u[:].name)) == ["bar", "baz", "foo"]
class ComponentItem(ElementPresentation, Classified): def __init__(self, id=None, model=None): super().__init__(id, model) self.watch("show_stereotypes", self.update_shapes) self.watch("subject[NamedElement].name") self.watch("subject.appliedStereotype", self.update_shapes) self.watch("subject.appliedStereotype.classifier.name") self.watch("subject.appliedStereotype.slot", self.update_shapes) self.watch("subject.appliedStereotype.slot.definingFeature.name") self.watch("subject.appliedStereotype.slot.value", self.update_shapes) show_stereotypes: attribute[int] = attribute("show_stereotypes", int) def update_shapes(self, event=None): self.shape = Box( Box( Text( text=lambda: UML.model.stereotypes_str(self.subject), style={ "min-width": 0, "min-height": 0 }, ), EditableText( text=lambda: self.subject.name or "", style={"font-weight": FontWeight.BOLD}, ), style={ "padding": (4, 34, 4, 4), "min-height": 44 }, draw=draw_component_icon, ), *(self.show_stereotypes and stereotype_compartments(self.subject) or []), style={ "min-width": 100, "min-height": 50, "vertical-align": VerticalAlign.TOP, }, draw=draw_border)
def test_notify(): class A(Element): notified = None def notify(self, name, pspec): self.notified = name A.assoc = association("assoc", A) A.attr = attribute("attr", bytes, "default") A.enum = enumeration("enum", ("one", "two"), "one") a = A() assert a.notified is None a.assoc = A() assert a.notified == "assoc", a.notified a.attr = "newval" assert a.notified == "attr", a.notified a.enum = "two" assert a.notified == "enum", a.notified a.notified = None a.enum = "two" # should not notify since value hasn't changed. assert a.notified is None
class NodeItem(ElementPresentation, Classified): """ Representation of node or device from UML Deployment package. """ def __init__(self, id=None, model=None): super().__init__(id, model) self.watch("show_stereotypes", self.update_shapes) self.watch("subject[NamedElement].name") self.watch("subject.appliedStereotype", self.update_shapes) self.watch("subject.appliedStereotype.classifier.name") self.watch("subject.appliedStereotype.slot", self.update_shapes) self.watch("subject.appliedStereotype.slot.definingFeature.name") self.watch("subject.appliedStereotype.slot.value", self.update_shapes) show_stereotypes: attribute[int] = attribute("show_stereotypes", int) def update_shapes(self, event=None): self.shape = Box( Box( Text( text=lambda: UML.model.stereotypes_str( self.subject, isinstance(self.subject, UML.Device) and ("device",) or (), ), style={"min-width": 0, "min-height": 0}, ), EditableText( text=lambda: self.subject.name or "", style={"font-weight": FontWeight.BOLD}, ), style={"padding": (4, 4, 4, 4)}, ), *(self.show_stereotypes and stereotype_compartments(self.subject) or []), style={"min-width": 100, "min-height": 50}, draw=draw_node )
class ClassItem(ElementPresentation[UML.Class], Classified): """This item visualizes a Class instance. A ClassItem contains two compartments: one for attributes and one for operations. """ def __init__(self, id=None, model=None): super().__init__(id, model) self.watch("show_stereotypes", self.update_shapes).watch( "show_attributes", self.update_shapes ).watch("show_operations", self.update_shapes).watch( "subject[NamedElement].name" ).watch( "subject[NamedElement].namespace.name" ).watch( "subject.appliedStereotype", self.update_shapes ).watch( "subject.appliedStereotype.classifier.name" ).watch( "subject.appliedStereotype.slot", self.update_shapes ).watch( "subject.appliedStereotype.slot.definingFeature.name" ).watch( "subject.appliedStereotype.slot.value", self.update_shapes ).watch( "subject[Classifier].isAbstract", self.update_shapes ) attribute_watches(self, "Class") operation_watches(self, "Class") show_stereotypes: attribute[int] = attribute("show_stereotypes", int) show_attributes: attribute[int] = attribute("show_attributes", int, default=True) show_operations: attribute[int] = attribute("show_operations", int, default=True) def update_shapes(self, event=None): def additional_stereotypes(): if isinstance(self.subject, UML.Stereotype): return ["stereotype"] elif UML.model.is_metaclass(self.subject): return ["metaclass"] else: return () self.shape = Box( Box( Text( text=lambda: UML.model.stereotypes_str( self.subject, additional_stereotypes() ), style={"min-width": 0, "min-height": 0}, ), EditableText( text=lambda: self.subject.name or "", style={ "font-weight": FontWeight.BOLD, "font-style": FontStyle.ITALIC if self.subject and self.subject.isAbstract else FontStyle.NORMAL, }, ), Text( text=lambda: from_package_str(self), style={"font": "sans 8", "min-width": 0, "min-height": 0}, ), style={"padding": (12, 4, 12, 4)}, ), *( self.show_attributes and self.subject and [attributes_compartment(self.subject)] or [] ), *( self.show_operations and self.subject and [operations_compartment(self.subject)] or [] ), *(self.show_stereotypes and stereotype_compartments(self.subject) or []), style={ "min-width": 100, "min-height": 50, "vertical-align": VerticalAlign.TOP, }, draw=draw_border, )
class A(Element): attr = attribute("attr", bytes, default="default")
class A(Element): attr = attribute('attr', types.StringType, default='default')
class InterfaceItem(ElementPresentation, Classified): """ Interface item supporting class box, folded notations and assembly connector icon mode. When in folded mode, provided (ball) notation is used by default. """ RADIUS_PROVIDED = 10 RADIUS_REQUIRED = 14 def __init__(self, id=None, model=None): super().__init__(id, model) self._folded = Folded.NONE self.side = Side.N handles = self.handles() h_nw = handles[NW] h_ne = handles[NE] h_sw = handles[SW] h_se = handles[SE] def is_folded(): return self._folded != Folded.NONE # edge of element define default element ports self._ports = [ InterfacePort(h_nw.pos, h_ne.pos, is_folded, Side.N), InterfacePort(h_ne.pos, h_se.pos, is_folded, Side.E), InterfacePort(h_se.pos, h_sw.pos, is_folded, Side.S), InterfacePort(h_sw.pos, h_nw.pos, is_folded, Side.W), ] self.watch("show_stereotypes", self.update_shapes).watch( "show_attributes", self.update_shapes ).watch("show_operations", self.update_shapes).watch( "subject[NamedElement].name" ).watch( "subject[NamedElement].namespace.name" ).watch( "subject.appliedStereotype", self.update_shapes ).watch( "subject.appliedStereotype.classifier.name" ).watch( "subject.appliedStereotype.slot", self.update_shapes ).watch( "subject.appliedStereotype.slot.definingFeature.name" ).watch( "subject.appliedStereotype.slot.value", self.update_shapes ).watch( "subject[Interface].supplierDependency", self.update_shapes ) attribute_watches(self, "Interface") operation_watches(self, "Interface") show_stereotypes: attribute[int] = attribute("show_stereotypes", int) show_attributes: attribute[int] = attribute("show_attributes", int, default=True) show_operations: attribute[int] = attribute("show_operations", int, default=True) def load(self, name, value): if name == "folded": self._folded = Folded(ast.literal_eval(value)) else: super().load(name, value) def save(self, save_func): super().save(save_func) save_func("folded", self._folded.value) def _set_folded(self, folded): """ Set folded notation. :param folded: Folded state, see Folded.* enum. """ if self._folded == folded: return self._folded = folded if folded == Folded.NONE: movable = True else: if self._folded == Folded.PROVIDED: icon_size = self.RADIUS_PROVIDED * 2 else: # required interface or assembly icon mode icon_size = self.RADIUS_REQUIRED * 2 self.min_width, self.min_height = icon_size, icon_size self.width, self.height = icon_size, icon_size # update only h_se handle - rest of handles should be updated by # constraints h_nw = self._handles[NW] h_se = self._handles[SE] h_se.pos.x = h_nw.pos.x + self.min_width h_se.pos.y = h_nw.pos.y + self.min_height movable = False for h in self._handles: h.movable = movable self.update_shapes() folded = property( lambda s: s._folded, _set_folded, doc="Check or set folded notation, see Folded.* enum.", ) def pre_update(self, context): assert isinstance(self.canvas, Canvas) connected_items = [c.item for c in self.canvas.get_connections(connected=self)] connectors = any( map(lambda i: isinstance(i.subject, UML.Connector), connected_items) ) if connectors or self._folded != Folded.NONE: provided = connectors or any( map( lambda i: isinstance(i.subject, UML.Implementation), connected_items ) ) required = any( map(lambda i: isinstance(i.subject, UML.Usage), connected_items) ) if required and provided: self.folded = Folded.ASSEMBLY elif required: self.folded = Folded.REQUIRED else: self.folded = Folded.PROVIDED self.update_shapes(connectors=connectors) super().pre_update(context) def update_shapes(self, event=None, connectors=None): if self._folded == Folded.NONE: self.shape = self.class_shape() else: self.shape = self.ball_and_socket_shape(connectors) def class_shape(self): return Box( Box( Text( text=lambda: UML.model.stereotypes_str( self.subject, ("interface",) ), style={"min-width": 0, "min-height": 0}, ), EditableText( text=lambda: self.subject.name or "", style={"font-weight": FontWeight.BOLD}, ), Text( text=lambda: from_package_str(self), style={"font": "sans 8", "min-width": 0, "min-height": 0}, ), style={"padding": (12, 4, 12, 4)}, ), *( self.show_attributes and self.subject and [attributes_compartment(self.subject)] or [] ), *( self.show_operations and self.subject and [operations_compartment(self.subject)] or [] ), *(self.show_stereotypes and stereotype_compartments(self.subject) or []), style={ "min-width": 100, "min-height": 50, "vertical-align": VerticalAlign.TOP, }, draw=draw_border, ) def ball_and_socket_shape(self, connectors=None): assert self.canvas if connectors is None: # distinguish between None and [] connected_items = [ c.item for c in self.canvas.get_connections(connected=self) ] connectors = any( map(lambda i: isinstance(i.subject, UML.Connector), connected_items) ) return IconBox( Box( style={"min-width": self.min_width, "min-height": self.min_height}, draw=self.draw_interface_ball_and_socket, ), Text( text=lambda: UML.model.stereotypes_str(self.subject), style={"min-width": 0, "min-height": 0}, ), EditableText( text=lambda: self.subject.name or "", style={ "font-weight": FontWeight.NORMAL if connectors else FontWeight.BOLD }, ), ) def draw_interface_ball_and_socket(self, _box, context, _bounding_box): cr = context.cairo h_nw = self._handles[NW] cx, cy = (h_nw.pos.x + self.width / 2, h_nw.pos.y + self.height / 2) if self._folded in (Folded.REQUIRED, Folded.ASSEMBLY): r = self.RADIUS_REQUIRED if self.side == Side.N: x, y = r * 2, r elif self.side == Side.E: x, y = r, r * 2 elif self.side == Side.S: x, y = 0, r elif self.side == Side.W: x, y = r, 0 cr.move_to(x, y) cr.arc_negative( cx, cy, self.RADIUS_REQUIRED, self.side.value, pi + self.side.value ) if self._folded in (Folded.PROVIDED, Folded.ASSEMBLY): cr.move_to(cx + self.RADIUS_PROVIDED, cy) cr.arc(cx, cy, self.RADIUS_PROVIDED, 0, pi * 2) cr.stroke()
class A(Element): attr = attribute('attr', bytes, default='default')
pass class ReceiveSignalEvent(MessageEvent): pass class Signal(Classifier): pass class Reception(BehavioralFeature): pass Extension.isRequired = attribute("isRequired", int) Feature.isStatic = attribute("isStatic", int, default=False) RedefinableElement.isLeaf = attribute("isLeaf", int, default=True) Generalization.isSubstitutable = attribute("isSubstitutable", int) ObjectNode.ordering = enumeration( "ordering", ("unordered", "ordered", "LIFO", "FIFO"), "FIFO" ) ObjectNode.isControlType = attribute("isControlType", int, default=False) StructuralFeature.isReadOnly = attribute("isReadOnly", int, default=False) NamedElement.visibility = enumeration( "visibility", ("public", "private", "package", "protected"), "public" ) NamedElement.name = attribute("name", str) # 33: override NamedElement.qualifiedName