def _drawVerticalBoundaries(self, diagram: ImageDiagram): imgDraw: ImageDraw = diagram._imgDraw topStart: InternalPosition = self.__toInternal(Position( x=TOP_LINE_LEFT_X, y=TOP_LINE_Y), diagram=diagram) topEnd: InternalPosition = self.__toInternal(Position( x=TOP_LINE_RIGHT_X, y=TOP_LINE_Y), diagram=diagram) bottomStart: InternalPosition = self.__toInternal(Position( x=BOTTOM_LINE_LEFT_X, y=BOTTOM_LINE_Y), diagram=diagram) bottomEnd: InternalPosition = self.__toInternal(Position( x=BOTTOM_LINE_RIGHT_X, y=BOTTOM_LINE_Y), diagram=diagram) xy = [topStart.x, topStart.y, topEnd.x, topEnd.y] imgDraw.line(xy=xy, fill=ImageDiagram.DEFAULT_LINE_COLOR, width=BOUNDARY_LINE_WIDTH) xy = [bottomStart.x, bottomStart.y, bottomEnd.x, bottomEnd.y] imgDraw.line(xy=xy, fill=ImageDiagram.DEFAULT_LINE_COLOR, width=BOUNDARY_LINE_WIDTH)
def _toPyUmlPositions(self, oglLink, pyutLinkType: LinkType) -> LinePositions: if pyutLinkType == LinkType.INHERITANCE: srcAnchor: AnchorPoint = oglLink.sourceAnchor destAnchor: AnchorPoint = oglLink.destinationAnchor else: srcAnchor = oglLink.destinationAnchor destAnchor = oglLink.sourceAnchor srcX, srcY = srcAnchor.GetPosition() destX, destY = destAnchor.GetPosition() sourcePosition: Position = Position(x=srcX, y=srcY) destinationPosition: Position = Position(x=destX, y=destY) bends: List[ControlPoint] = oglLink.GetControlPoints() if bends is None or len(bends) == 0: linePositions: LinePositions = [ sourcePosition, destinationPosition ] else: linePositions = [sourcePosition] for cp in bends: bend: ControlPoint = cast(ControlPoint, cp) self.logger.debug(f'{bend:}') bendX, bendY = bend.GetPosition() bendPosition: Position = Position(x=bendX, y=bendY) linePositions.append(bendPosition) linePositions.append(destinationPosition) return linePositions
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 _drawHorizontalBoundaries(self, diagram: ImageDiagram): imgDraw: ImageDraw = diagram._imgDraw startLeftTop: InternalPosition = self.__toInternal(Position(x=V_LEFT_X, y=V_TOP_Y), diagram=diagram) endLLeftBottom: InternalPosition = self.__toInternal(Position( x=V_LEFT_X, y=V_BOTTOM_Y), diagram=diagram) startRightTop: InternalPosition = self.__toInternal(Position( x=V_RIGHT_X, y=V_TOP_Y), diagram=diagram) endRightBottom: InternalPosition = self.__toInternal(Position( x=V_RIGHT_X, y=V_BOTTOM_Y), diagram=diagram) xy = [ startLeftTop.x, startLeftTop.y, endLLeftBottom.x, endLLeftBottom.y ] imgDraw.line(xy=xy, fill=ImageDiagram.DEFAULT_LINE_COLOR, width=BOUNDARY_LINE_WIDTH) xy = [ startRightTop.x, startRightTop.y, endRightBottom.x, endRightBottom.y ] imgDraw.line(xy=xy, fill=ImageDiagram.DEFAULT_LINE_COLOR, width=BOUNDARY_LINE_WIDTH)
def _toPyUmlPositions(self, oglLink): srcAnchor: AnchorPoint = oglLink.sourceAnchor destAnchor: AnchorPoint = oglLink.destinationAnchor srcX, srcY = srcAnchor.GetPosition() destX, destY = destAnchor.GetPosition() sourcePosition: Position = Position(x=srcX, y=srcY) destinationPosition: Position = Position(x=destX, y=destY) return destinationPosition, sourcePosition
def _createOrthogonalLines( self, lineType: LineType ) -> Tuple[UmlLineDefinition, UmlLineDefinition, UmlLineDefinition, UmlLineDefinition]: northLinePositions: LinePositions = [ Position(BOTTOM_LINE_LEFT_X + X_INC, TOP_LINE_Y), Position(BOTTOM_LINE_LEFT_X + X_INC, BOTTOM_LINE_Y) ] north: UmlLineDefinition = UmlLineDefinition( lineType=lineType, linePositions=northLinePositions) northLinePositions: LinePositions = [ Position(BOTTOM_LINE_RIGHT_X + X_DEC, TOP_LINE_Y), Position(BOTTOM_LINE_RIGHT_X + X_DEC, BOTTOM_LINE_Y) ] south: UmlLineDefinition = UmlLineDefinition( lineType=lineType, linePositions=northLinePositions) eastLinePositions: LinePositions = [ Position(V_LEFT_X, V_TOP_Y + Y_INC), Position(V_RIGHT_X, V_TOP_Y + Y_INC) ] east: UmlLineDefinition = UmlLineDefinition( lineType=lineType, linePositions=eastLinePositions) westLinePositions: LinePositions = [ Position(V_RIGHT_X, V_BOTTOM_Y + Y_DEC), Position(V_LEFT_X, V_BOTTOM_Y + Y_DEC) ] west: UmlLineDefinition = UmlLineDefinition( lineType=lineType, linePositions=westLinePositions) return north, south, east, west
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 __createDiagonalLines( self, lineType: LineType ) -> Tuple[UmlLineDefinition, UmlLineDefinition, UmlLineDefinition, UmlLineDefinition]: pos: Position = Position(ELLIPSE_X, ELLIPSE_Y) arrowSize: float = ELLIPSE_WIDTH / 2 center: Position = self.__computeEllipseCenter(pos) neDst: Position = self.__computeNorthEastDestination( center=center, arrowSize=arrowSize) nwDst: Position = self.__computeNorthWestDestination( center=center, arrowSize=arrowSize) seDst: Position = self.__computeSouthEastDestination( center=center, arrowSize=arrowSize) swDst: Position = self.__computeSouthWestDestination( center=center, arrowSize=arrowSize) nePositions: LinePositions = [center, neDst] northEast: UmlLineDefinition = UmlLineDefinition( lineType=lineType, linePositions=nePositions) nwPositions: LinePositions = [center, nwDst] northWest: UmlLineDefinition = UmlLineDefinition( lineType=lineType, linePositions=nwPositions) swPositions: LinePositions = [center, swDst] southWest: UmlLineDefinition = UmlLineDefinition( lineType=lineType, linePositions=swPositions) sePositions: LinePositions = [center, seDst] southEast: UmlLineDefinition = UmlLineDefinition( lineType=lineType, linePositions=sePositions) return northEast, northWest, southEast, southWest
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 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 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 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 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 generateUmlLineDefinitions(self): graphicLinkNodes: NodeList = self._documentNode.getElementsByTagName( ELEMENT_GRAPHIC_LINK) for xmlGraphicLink in graphicLinkNodes: xmlGraphicLink: Element = cast(Element, xmlGraphicLink) xmlLink: Element = xmlGraphicLink.getElementsByTagName( ELEMENT_MODEL_LINK)[0] controlPoints: NodeList = xmlGraphicLink.getElementsByTagName( ELEMENT_CONTROL_POINT) srcX: float = float( xmlGraphicLink.getAttribute(ATTR_LINK_SOURCE_ANCHOR_X)) srcY: float = float( xmlGraphicLink.getAttribute(ATTR_LINK_SOURCE_ANCHOR_Y)) strType: str = xmlLink.getAttribute(ATTR_TYPE) lineType: LineType = LineType.toEnum(strType) srcPosition: Position = Position(x=srcX, y=srcY) linePositions: LinePositions = [srcPosition] umlLineDefinition: UmlLineDefinition = UmlLineDefinition( linePositions=linePositions, lineType=lineType) for controlPoint in controlPoints: controlPoint: Element = cast(Element, controlPoint) self.logger.debug(f'{controlPoint=}') x: float = float(controlPoint.getAttribute(ATTR_X)) y: float = float(controlPoint.getAttribute(ATTR_Y)) bendPosition: Position = Position(x=x, y=y) linePositions.append(bendPosition) destX: float = float( xmlGraphicLink.getAttribute(ATTR_LINK_DESTINATION_ANCHOR_X)) destY: float = float( xmlGraphicLink.getAttribute(ATTR_LINK_DESTINATION_ANCHOR_Y)) destPosition: Position = Position(x=destX, y=destY) linePositions.append(destPosition) self.logger.debug(f'{umlLineDefinition=}') self._umlLineDefinitions.append(umlLineDefinition)
def __computeEllipseCenter(self, ellipsePos: Position) -> Position: x: int = ellipsePos.x y: int = ellipsePos.y centerX: int = x + (ELLIPSE_WIDTH // 2) centerY: int = y + (ELLIPSE_HEIGHT // 2) return Position(centerX, centerY)
def _buildSophisticatedLineDefinitions(self) -> UmlLineDefinitions: startPosition: Position = Position(600, 208) endPosition: Position = Position(600, 93) opieToCatLinePositions: LinePositions = [startPosition, endPosition] opieToCat: UmlLineDefinition = UmlLineDefinition( lineType=LineType.Inheritance, linePositions=opieToCatLinePositions) startPosition2: Position = Position(190, 224) endPosition2: Position = Position(190, 130) eCarToCarLinePositions: LinePositions = [startPosition2, endPosition2] eCarToCar: UmlLineDefinition = UmlLineDefinition( lineType=LineType.Inheritance, linePositions=eCarToCarLinePositions) lineDefinitions: UmlLineDefinitions = [opieToCat, eCarToCar] return lineDefinitions
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 __computeDestination( self, center: Position, arrowSize: float, radians: float, ) -> Position: from math import cos from math import sin return Position(center.x + round(arrowSize * cos(radians)), center.y + round(arrowSize * sin(radians)))
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 __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 __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 __toInternalCoordinates(self, definition: ShapeDefinition) -> Tuple[int, int, int, int]: pos: Position = definition.position size: Size = definition.size internalStart: InternalPosition = self.__toInternal(position=pos) internalEnd: InternalPosition = self.__toInternal(position=Position(x=pos.x + size.width, y=pos.y + size.height)) x1 = internalStart.x y1 = internalStart.y x2 = internalEnd.x y2 = internalEnd.y xy = (x1, y1, x2, y2) return xy
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 __createOrthogonalLines( self, lineType: LineType ) -> Tuple[UmlLineDefinition, UmlLineDefinition, UmlLineDefinition, UmlLineDefinition]: northLinePositions: LinePositions = [ Position(TestPdfLine.V_RIGHT_X, TestPdfLine.V_TOP_Y), Position(TestPdfLine.V_RIGHT_X, TestPdfLine.V_BOTTOM_Y) ] north: UmlLineDefinition = UmlLineDefinition( lineType=lineType, linePositions=northLinePositions) southLinePositions: LinePositions = [ Position(TestPdfLine.V_LEFT_X, TestPdfLine.V_BOTTOM_Y), Position(TestPdfLine.V_LEFT_X, TestPdfLine.V_TOP_Y) ] south: UmlLineDefinition = UmlLineDefinition( lineType=lineType, linePositions=southLinePositions) eastLinePositions: LinePositions = [ Position(TestPdfLine.H_LEFT_X, TestPdfLine.H_LEFT_TOP_Y + TestPdfLine.Y_INC), Position(TestPdfLine.H_RIGHT_X, TestPdfLine.H_LEFT_TOP_Y + TestPdfLine.Y_INC) ] east: UmlLineDefinition = UmlLineDefinition( lineType=lineType, linePositions=eastLinePositions) westLinePositions: LinePositions = [ Position(TestPdfLine.H_RIGHT_X, TestPdfLine.H_RIGHT_BOTTOM_Y), Position(TestPdfLine.H_LEFT_X, TestPdfLine.H_LEFT_BOTTOM_Y) ] west: UmlLineDefinition = UmlLineDefinition( lineType=lineType, linePositions=westLinePositions) return north, south, east, west