def testMinimalInheritance(self): baseName: str = f'{TestConstants.TEST_FILE_NAME}-MinimalInheritance' fileName: str = f'{baseName}.{ImageFormat.PNG.value}' diagram: ImageDiagram = ImageDiagram(fileName=f'{fileName}') cat: ClassDefinition = ClassDefinition(name='Gato', position=Position(536, 19), size=Size(height=74, width=113)) opie: ClassDefinition = ClassDefinition(name='Opie', position=Position(495, 208), size=Size(width=216, height=87)) diagram.drawClass(classDefinition=cat) diagram.drawClass(classDefinition=opie) startPosition: Position = Position(600, 208) endPosition: Position = Position(600, 93) linePositions: LinePositions = [startPosition, endPosition] opieToCat: UmlLineDefinition = UmlLineDefinition( lineType=LineType.Inheritance, linePositions=linePositions) diagram.drawUmlLine(lineDefinition=opieToCat) diagram.write() self._assertIdenticalFiles( baseName=baseName, generatedFileName=fileName, failMessage='Minimal Inheritance image file should be identical')
def toClassDefinitions(self, oglObjects: List[OglClass]): classDefinitions: ClassDefinitions = [] for oglObject in oglObjects: umlObject: OglClass = cast(OglClass, oglObject) if not isinstance(umlObject, OglClass): continue pyutClass: PyutClass = cast(PyutClass, umlObject.pyutObject) x, y = umlObject.GetPosition() w, h = umlObject.GetSize() position: Position = Position(x=x, y=y) size: Size = Size(width=int(w), height=int(h)) classDefinition: ClassDefinition = ClassDefinition( name=pyutClass.name, position=position, size=size) if pyutClass.displayParameters is True: classDefinition.displayMethodParameters = DisplayMethodParameters.DISPLAY else: classDefinition.displayMethodParameters = DisplayMethodParameters.DO_NOT_DISPLAY classDefinition = self.__addClassDiagramDisplayPreferences( pyutClass=pyutClass, classDefinition=classDefinition) self._addMethods(classDefinition=classDefinition, pyutClass=pyutClass) self._diagram.drawClass(classDefinition=classDefinition) classDefinitions.append(classDefinition) self._classDefinitions = classDefinitions
def testBasicMethod(self): baseName: str = f'{TestConstants.TEST_FILE_NAME}-BasicMethod' fileName: str = f'{baseName}.{ImageFormat.PNG.value}' diagram: ImageDiagram = ImageDiagram(fileName=f'{fileName}') position: Position = Position(107, 30) size: Size = Size(width=266, height=100) car: ClassDefinition = ClassDefinition(name='Car', position=position, size=size) initMethodDef: MethodDefinition = MethodDefinition( name='__init__', visibility=DefinitionType.Public) initParam: ParameterDefinition = ParameterDefinition( name='make', parameterType='str', defaultValue='') initMethodDef.parameters = [initParam] car.methods = [initMethodDef] diagram.drawClass(car) diagram.write() self._assertIdenticalFiles( baseName=baseName, generatedFileName=fileName, failMessage='Basic Method image file should be identical')
def _buildCar(self) -> ClassDefinition: car: ClassDefinition = ClassDefinition(name='Car', position=Position(107, 30), size=Size(width=266, height=100)) initMethodDef: MethodDefinition = self._buildInitMethod() descMethodDef: MethodDefinition = MethodDefinition( name='getDescriptiveName', visibility=DefinitionType.Public) odometerMethodDef: MethodDefinition = MethodDefinition( name='readOdometer', visibility=DefinitionType.Public) updateOdoMethodDef: MethodDefinition = MethodDefinition( name='updateOdometer', visibility=DefinitionType.Public) incrementMethodDef: MethodDefinition = MethodDefinition( name='incrementOdometer', visibility=DefinitionType.Protected) mileageParam: ParameterDefinition = ParameterDefinition( name='mileage', defaultValue='1') updateOdoMethodDef.parameters = [mileageParam] milesParam: ParameterDefinition = ParameterDefinition( name='miles', parameterType='int') incrementMethodDef.parameters = [milesParam] car.methods = [ initMethodDef, descMethodDef, odometerMethodDef, updateOdoMethodDef, incrementMethodDef ] return car
def _buildRightClass(self) -> ClassDefinition: right: ClassDefinition = ClassDefinition(name='RightClass', position=Position( 522.0, 354.0), size=Size(height=107.0, width=167.0)) return right
def _buildLeftClass(self) -> ClassDefinition: left: ClassDefinition = ClassDefinition(name='LeftClass', position=Position( 266.0, 359.0), size=Size(height=99.0, width=127.0)) return left
def testFillPage(self): baseName: str = f'{TestConstants.TEST_FILE_NAME}-FillPage' fileName: str = f'{baseName}.{ImageFormat.PNG.value}' diagram: ImageDiagram = ImageDiagram(fileName=f'{fileName}') widthInterval: int = TestImageDiagram.CELL_WIDTH // 10 heightInterval: int = TestImageDiagram.CELL_HEIGHT // 10 for x in range(0, TestImageDiagram.TEST_LAST_X_POSITION): scrX: int = (x * TestImageDiagram.CELL_WIDTH) + (widthInterval * x) for y in range(0, TestImageDiagram.TEST_LAST_Y_POSITION): scrY: int = (y * TestImageDiagram.CELL_HEIGHT) + ( y * heightInterval) classDef: ClassDefinition = ClassDefinition( name=f'{TestImageDiagram.BASE_TEST_CLASS_NAME}{x}{y}', position=Position(scrX, scrY), size=Size(width=TestImageDiagram.CELL_WIDTH, height=TestImageDiagram.CELL_HEIGHT)) diagram.drawClass(classDef) diagram.write() self._assertIdenticalFiles( baseName=baseName, generatedFileName=fileName, failMessage='Fill Page image file should be identical')
def testBasicFields(self): baseName: str = f'{TestConstants.TEST_FILE_NAME}-BasicFields' fileName: str = f'{baseName}.{ImageFormat.PNG.value}' diagram: ImageDiagram = ImageDiagram(fileName=fileName) fieldsTestClass: ClassDefinition = ClassDefinition( name='FieldsTestClass', position=Position(226, 102), size=Size(height=156, width=230)) fieldsTestClass.fields = self._buildFields() initMethodDef: MethodDefinition = MethodDefinition( name='__init__', visibility=DefinitionType.Public) fieldsTestClass.methods = [initMethodDef] diagram.drawClass(classDefinition=fieldsTestClass) diagram.write() self._assertIdenticalFiles( baseName=baseName, generatedFileName=fileName, failMessage='Basic Fields image file should be identical')
def testBasicMethod(self): baseName: str = f'{TestConstants.TEST_FILE_NAME}-BasicMethod' fileName: str = f'{baseName}{TestConstants.TEST_SUFFIX}' diagram: PdfDiagram = PdfDiagram(fileName=f'{fileName}', dpi=TestConstants.TEST_DPI) position: Position = Position(107, 30) size: Size = Size(width=266, height=100) car: ClassDefinition = ClassDefinition(name='Car', position=position, size=size) car.displayMethodParameters = DisplayMethodParameters.DISPLAY initMethodDef: MethodDefinition = MethodDefinition(name='__init__', visibility=DefinitionType.Public) initParam: ParameterDefinition = ParameterDefinition(name='make', parameterType='str', defaultValue='') initMethodDef.parameters = [initParam] car.methods = [initMethodDef] diagram.drawClass(car) diagram.docTimeStamp = self.unitTestTimeStamp diagram.write() self._assertIdenticalFiles(baseName=baseName, generatedFileName=fileName, failMessage='Basic Method should be identical')
def __init__(self, fileName: str, docDisplayMethodParameters: DisplayMethodParameters = DisplayMethodParameters.DISPLAY, headerText: str = '', imageSize: Size = Size(width=DEFAULT_IMAGE_WIDTH, height=DEFAULT_IMAGE_HEIGHT)): """ Args: fileName: The output file name. Including the suffix docDisplayMethodParameters: The global value to consult if a class value says UNSPECIFIED headerText: The text to display as a header on the diagram imageSize: The diagram size in pixels """ super().__init__(fileName=fileName, docDisplayMethodParameters=docDisplayMethodParameters, headerText=headerText) self.logger: Logger = getLogger(__name__) self._img: Image = Image.new(mode='RGB', size=(imageSize.width, imageSize.height), color=ImageColor.getrgb(ImageDiagram.DEFAULT_BACKGROUND_COLOR)) self._imgDraw: ImageDraw = ImageDraw.Draw(self._img) self._lineDrawer: ImageLine = ImageLine(docWriter=self._imgDraw, diagramPadding=self._diagramPadding) # noinspection SpellCheckingInspection fqPath: str = self.retrieveResourcePath('MonoFonto.ttf') self._font: ImageFont = ImageFont.truetype(font=fqPath, size=BaseDiagram.DEFAULT_FONT_SIZE) self._headerFont: ImageFont = ImageFont.truetype(font=fqPath, size=BaseDiagram.HEADER_FONT_SIZE)
def generateClassDefinitions(self): graphicClassNodes: NodeList = self._documentNode.getElementsByTagName( ELEMENT_GRAPHIC_CLASS) self.logger.debug(f'{graphicClassNodes=}') for xmlGraphicClass in graphicClassNodes: xmlGraphicClass: Element = cast(Element, xmlGraphicClass) height: float = float(xmlGraphicClass.getAttribute(ATTR_HEIGHT)) width: float = float(xmlGraphicClass.getAttribute(ATTR_WIDTH)) x: float = float(xmlGraphicClass.getAttribute(ATTR_X)) y: float = float(xmlGraphicClass.getAttribute(ATTR_Y)) xmlClass: Element = xmlGraphicClass.getElementsByTagName( ELEMENT_MODEL_CLASS)[0] className: str = xmlClass.getAttribute(ATTR_NAME) displayMethods: bool = self._stringToBoolean( xmlClass.getAttribute(ATTR_SHOW_METHODS)) displayFields: bool = self._stringToBoolean( xmlClass.getAttribute(ATTR_SHOW_FIELDS)) displayStereotype: bool = self._stringToBoolean( xmlClass.getAttribute(ATTR_SHOW_STEREOTYPE)) displayParametersStr: str = xmlClass.getAttribute( ATTR_DISPLAY_PARAMETERS) displayMethodParameters: DisplayMethodParameters if displayParametersStr is None or displayParametersStr == '': displayMethodParameters: DisplayMethodParameters = DisplayMethodParameters.UNSPECIFIED else: displayMethodParameters: DisplayMethodParameters = DisplayMethodParameters( displayParametersStr) classDef: ClassDefinition = ClassDefinition(name=className) classDef.displayMethods = displayMethods classDef.displayFields = displayFields classDef.displayStereotype = displayStereotype classDef.displayMethodParameters = displayMethodParameters classSize: Size = Size(width=width, height=height) classDef.size = classSize position: Position = Position(x=x, y=y) classDef.position = position classDef.methods = self.generateMethods(xmlClass=xmlClass) self.logger.debug(f'{classDef=}') self._classDefinitions.append(classDef)
def __drawEllipseForDiagonalInheritanceLines(self, diagram: ImageDiagram): # imgDraw: ImageDraw = diagram._imgDraw eDef: EllipseDefinition = EllipseDefinition() pos: Position = Position(ELLIPSE_X, ELLIPSE_Y) size: Size = Size(width=ELLIPSE_WIDTH, height=ELLIPSE_HEIGHT) eDef.position = pos eDef.size = size diagram.drawEllipse(eDef) diagram.drawRectangle(eDef)
def _buildCat(self) -> ClassDefinition: cat: ClassDefinition = ClassDefinition(name='gato', position=Position(536, 19), size=Size(height=74, width=113)) initMethod: MethodDefinition = MethodDefinition('__init') sitMethod: MethodDefinition = MethodDefinition('sit') rollOverMethod: MethodDefinition = MethodDefinition('rollOver') cat.methods = [initMethod, sitMethod, rollOverMethod] return cat
def testBasic(self): baseName: str = f'{TestConstants.TEST_FILE_NAME}-Basic' fileName: str = f'{baseName}{TestConstants.TEST_SUFFIX}' diagram: PdfDiagram = PdfDiagram(fileName=fileName, dpi=TestConstants.TEST_DPI) classDef: ClassDefinition = ClassDefinition(name=TestDiagramParent.BASE_TEST_CLASS_NAME, size=Size(width=TestPdfDiagram.CELL_WIDTH, height=TestPdfDiagram.CELL_HEIGHT)) diagram.docTimeStamp = self.unitTestTimeStamp diagram.drawClass(classDef) diagram.write() self._assertIdenticalFiles(baseName=baseName, generatedFileName=fileName, failMessage='Basic should be identical')
def __drawEllipseForDiagonalLines(self, diagram: PdfDiagram): eDef: EllipseDefinition = EllipseDefinition() pos: Position = Position(TestPdfLine.ELLIPSE_X, TestPdfLine.ELLIPSE_Y) size: Size = Size(width=TestPdfLine.ELLIPSE_WIDTH, height=TestPdfLine.ELLIPSE_HEIGHT) eDef.position = pos eDef.size = size diagram.drawEllipse(eDef) diagram.drawRectangle(eDef) center: Position = self.__computeEllipseCenter(pos) diagram.drawText(center, text=f'({int(center.x)},{int(center.y)})')
def _buildElectricCar(self) -> ClassDefinition: electricCar: ClassDefinition = ClassDefinition(name='ElectricCar', position=Position( 52, 224), size=Size(width=173, height=64)) initMethod: MethodDefinition = MethodDefinition(name='__init__') descMethod: MethodDefinition = MethodDefinition(name='describeBattery') makeParameter: ParameterDefinition = ParameterDefinition(name='make') modelParameter: ParameterDefinition = ParameterDefinition(name='model') yearParameter: ParameterDefinition = ParameterDefinition(name='year') initMethod.parameters = [makeParameter, modelParameter, yearParameter] electricCar.methods = [initMethod, descMethod] return electricCar
def testBasic(self): baseName: str = f'{TestConstants.TEST_FILE_NAME}-Basic' fileName: str = f'{baseName}.{ImageFormat.PNG.value}' diagram: ImageDiagram = ImageDiagram(fileName=f'{fileName}') classDef: ClassDefinition = ClassDefinition( name=TestDiagramParent.BASE_TEST_CLASS_NAME, size=Size(width=266, height=100), position=Position(x=107, y=30)) diagram.drawClass(classDef) diagram.write() self._assertIdenticalFiles( baseName=baseName, generatedFileName=fileName, failMessage='Basic image file should be identical')
def _buildNameTestCase(self) -> ClassDefinition: namesTest: ClassDefinition = ClassDefinition(name='NamesTestCase', position=Position( 409, 362), size=Size(height=65, width=184)) testFirst: MethodDefinition = MethodDefinition(name='testFirstLasName') formattedName: MethodDefinition = MethodDefinition( name='getFormattedName') firstParam: ParameterDefinition = ParameterDefinition(name='first') lastParam: ParameterDefinition = ParameterDefinition(name='last') formattedName.parameters = [firstParam, lastParam] namesTest.methods = [testFirst, formattedName] return namesTest
def _buildOpie(self) -> ClassDefinition: opie: ClassDefinition = ClassDefinition(name='Opie', position=Position(495, 208), size=Size(width=216, height=87)) publicMethod: MethodDefinition = MethodDefinition( name='publicMethod', visibility=DefinitionType.Public, returnType='bool') paramDef: ParameterDefinition = ParameterDefinition( name='param', parameterType='float', defaultValue='23.0') publicMethod.parameters = [paramDef] opie.methods = [publicMethod] return opie
def testMethodReprRegression(self): baseName: str = f'{TestConstants.TEST_FILE_NAME}-MethodReprRegression' fileName: str = f'{baseName}{TestConstants.TEST_SUFFIX}' diagram: PdfDiagram = PdfDiagram(fileName=fileName, dpi=TestConstants.TEST_DPI) position: Position = Position(107, 30) size: Size = Size(width=266, height=100) car: ClassDefinition = ClassDefinition(name='Car', position=position, size=size) initMethodDef: MethodDefinition = MethodDefinition(name='__init__', visibility=cast(DefinitionType, None)) car.methods = [initMethodDef] diagram.drawClass(car) diagram.docTimeStamp = self.unitTestTimeStamp diagram.write() self._assertIdenticalFiles(baseName=baseName, generatedFileName=fileName, failMessage='MethodReprRegression should be identical')
def toClassDefinitions(self, oglObjects: List[OglClass]): classDefinitions: ClassDefinitions = [] for umlObject in oglObjects: umlObject: OglClass = cast(OglClass, umlObject) if not isinstance(umlObject, OglClass): continue pyutClass: PyutClass = umlObject.getPyutObject() x, y = umlObject.GetPosition() w, h = umlObject.GetSize() position: Position = Position(x=x, y=y) size: Size = Size(width=int(w), height=int(h)) classDefinition: ClassDefinition = ClassDefinition(name=pyutClass.name, position=position, size=size) self._addMethods(classDefinition=classDefinition, pyutClass=pyutClass) self._diagram.drawClass(classDefinition=classDefinition) classDefinitions.append(classDefinition) self._classDefinitions = classDefinitions
def _drawClassSymbol(self, classDefinition: ClassDefinition, rectX: int, rectY: int) -> int: """ Draws the UML Class symbol. Args: classDefinition: The class definition rectX: x position rectY: y position Returns: The computed UML symbol width """ symbolWidth: int = classDefinition.size.width symbolHeight: int = classDefinition.size.height size: Size = Size(width=symbolWidth, height=symbolHeight) dimensions: Dimensions = self.__convertSize(size=size) convertedWidth: int = dimensions.width convertedHeight: int = dimensions.height # # The docs for rect are incorrect; style is string # noinspection PyTypeChecker self._pdf.rect(x=rectX, y=rectY, w=convertedWidth, h=convertedHeight, style=PdfDiagram.FPDF_DRAW) nameWidth: int = self._pdf.get_string_width(classDefinition.name) textX: int = rectX + ((symbolWidth // 2) - (nameWidth // 2)) textY: int = rectY + self._fontSize self._pdf.text(x=textX, y=textY, txt=classDefinition.name) return convertedWidth
def _buildTopClass(self) -> ClassDefinition: top: ClassDefinition = ClassDefinition(name='TopClass', position=Position(409.0, 159.0), size=Size(height=100, width=113)) return top
def testMinimalInheritance(self): baseName: str = f'{TestConstants.TEST_FILE_NAME}-MinimalInheritance' fileName: str = f'{baseName}{TestConstants.TEST_SUFFIX}' diagram: PdfDiagram = PdfDiagram(fileName=f'{fileName}', dpi=75) cat: ClassDefinition = ClassDefinition(name='Gato', position=Position(536, 19), size=Size(height=74, width=113)) opie: ClassDefinition = ClassDefinition(name='Opie', position=Position(495, 208), size=Size(width=216, height=87)) diagram.drawClass(classDefinition=cat) diagram.drawClass(classDefinition=opie) linePositions: LinePositions = [Position(600, 208), Position(600, 93)] opieToCat: UmlLineDefinition = UmlLineDefinition(lineType=LineType.Inheritance, linePositions=linePositions) diagram.drawUmlLine(lineDefinition=opieToCat) diagram.docTimeStamp = self.unitTestTimeStamp diagram.write() self._assertIdenticalFiles(baseName=baseName, generatedFileName=fileName, failMessage='SophisticatedLayout should be identical')
def testBasicFields(self): baseName: str = f'{TestConstants.TEST_FILE_NAME}-BasicFields' fileName: str = f'{baseName}{TestConstants.TEST_SUFFIX}' diagram: PdfDiagram = PdfDiagram(fileName=fileName, dpi=TestConstants.TEST_DPI) fieldsTestClass: ClassDefinition = ClassDefinition(name='FieldsTestClass', position=Position(226, 102), size=Size(height=156, width=230)) fieldsTestClass.fields = self._buildFields() initMethodDef: MethodDefinition = MethodDefinition(name='__init__', visibility=DefinitionType.Public) fieldsTestClass.methods = [initMethodDef] diagram.drawClass(classDefinition=fieldsTestClass) diagram.docTimeStamp = self.unitTestTimeStamp diagram.write() self._assertIdenticalFiles(baseName=baseName, generatedFileName=fileName, failMessage='Basic Fields should be identical')