Package: archeme
ArchemeArcheme is a tool to describe and visualize schemes and diagrams. It’s designed primarily for architectural schemes.Archeme may be used as a stand-alone command-line tool, or as a Python package.To describe schemes and diagrams, Archeme provides YAML-based DSL (domain-specific language).To draw them, Archeme usesGraphviz. The enginesdot,neato, andfdpare supported.In fact, Archeme provides some new abstraction level over Graphviz. Unlike PlantUML, Archeme almost doesn’t limit your ability to use the flexible functionality of Graphviz. However, Archeme provides more convenient means to describe elements of the same types using classes, to specify the relative positions of elements, etc. Using YAML as the base of DSL makes it possible to work with diagram descriptions as with data structures—in Archeme itself and in applications integrated with it. So, Archeme can easily combine several scheme descriptions into one.By using SVG as an output format, you may assign hyperlinks to scheme elements and thereby organize relationships between schemes—for example, in accordance with theC4 methodology.InstallationTo install Archeme, run the command:$pipinstallarchemeAfter installation, the commandarchemewill be available in your system.CLI UsageCurrently Archeme provides 2 actions (commands):generate—to generate graph description that can be drawn with Graphviz from YAML-based DSL source;merge—to merge (combine, join) multiple DSL sources into a single DSL source.ThegenerateCommand SyntaxGeneralized syntax of thegeneratecommand is the following:$archemegenerate[-c|--config<config_file>]-i|--input<input_file>-o|--output<output_file>[-d|--draw<format>]The-i/--inputand-o/--outputarguments are required, other arguments are optional.The-i/--inputparameter is used to specify YAML-based DSL source.The-o/--outputparameter points to the output file—graph description for Graphviz.You may specify an optional config file by using the-c/--configargument. Both config and scheme description files use the same YAML-based DSL. It’s recommended to use a separate config file to specify some common settings that may be reused in multiple scheme descriptions of the same style. If both config file and scheme description set the parameter of the same name, the value specified in scheme description will override the value specified in config.If the-d/--drawargument is given, Archeme will try to call Graphviz to draw an image from generated graph description, and the Graphviz calling command will be displayed. By default, Archeme doesn’t call Graphviz to visualize generated graph descriptions. The-d/--drawargument may take any output format value allowed by Graphviz (png,svg, etc.). By default, thedotengine is used. You may specify the necessary engine explicitly in DSL, see below.ThemergeCommand SyntaxGeneralized syntax of themergecommand is more simple:$archememerge-i|--input<input_file>-o|--output<output_file>The command takes 2 mandatory arguments:-i/--inputfor input YAML-based DSL file, and-o/--outputfor output YAML-based DSL file. Output files of themergecommand should be used as input files for thegeneratecommand. YAML-based DSL is described below.YAML-Based DSLSee also:Archeme DSL Quick ReferenceTo describe schemes and diagrams, YAML-based DSL is provided.DSL, same as Graphviz, operates the graph theory terms: so,graphis the whole drawing;nodeis a functional component of a scheme or a diagram;clusteris a group of nodes that is usually highlighted visually;edgeis a line that represents a relation between two nodes.DSL may be used to:specify common settings of multiple elements;define scheme structure and relations between elements;describe each separate element—node, cluster, edge;set relative positions of elements;describe how it’s needed to combine multiple scheme descriptions into a single one.Common SettingCommon settings for multiple elements usually should be specified in the config file.Graphviz EngineTheengineparameter sets the certain Graphviz engine to draw images. Archeme supports thedot,neato, andfdpengines. The default engine isdot.Code example:engine:neatoYou may read about the difference between engines in theGraphviz documentation.In relation to architectural schemes:dotis suitable for models with hierarchical relations; usingdot, you can’t strictly control relative positions of elements—the positions depend of ranks of elements;dotsupports clusters;neatoallows to set strict fixed positions to each node; it doesn’t support clusters;fdpis similar toneatobut it supports clusters; however, if clusters are used,fdpre-calculates the positions of nodes, they can’t be strictly fixed.Settings Of ElementsInelementssection, you may specify common settings of the element of different types—graph, node, cluster, edge. In the simplest case, DSL maps to Graphviz syntax. DSL code example:elements:graph:newrank:truerankdir:TBnode:shape:boxfixedsize:truewidth:4height:1style:-filled-roundededge:dir:botharrowtail:dotThis example will be converted into the following description for Graphviz:graph [newrank = "true", rankdir: "TB"]
node [shape = "box", fixedsize = "true", width = "4", height = "1", style = "filled, rounded"]
edge [dir = "both", arrowtail = "dot"]All available parameters for graphs, nodes, edges are described in theGraphviz documentation.In addition tograph,node, andedgeparameters, Archeme supports the analogousclusterparameter that allows to specify default settings for clusters. Code example:elements:cluster:labelloc:blabeljust:lshape:boxNote that you may reduce the number of lines of YAML-based DSL code. So, node settings from the example above may look like this:node {shape:box, fixedsize:true, width:4, height:1, style:[filled,rounded]}Archeme allows to specify parameters that take lists of values, in different ways. The constructionsstyle: [filled, rounded],style: filled, rounded,style: [filled],style: filledare valid.Note that if a node, cluster, or edge has some customstyleor another parameter with a list of values, it willfullyoverride the defaultstyleor whatever. This is how it works in Graphviz, and Archeme doesn’t change this behavior for compatibility reasons.For example, if the defaultstylefor nodes is[filled, rounded], and the customstyleof some node isdashed, onlydashedwill be applied to this node.To control the settings of elements more flexible, classes are provided.Classes DefinitionYou may define one or more classes for each type of elements (node,cluster,edge), and then assign any combination of defined classes to any separate element. Code example:elements:node:fixedsize:truepenwidth:3classes:generic:shape:boxwidth:4height:1style:roundeddatabase:shape:cylinderwidth:3height:3external_network:shape:circlewidth:2.5height:2.5style:filledfillcolor:'#f0f0f0'In this example, 3 classes of nodes with the namesgeneric,database, andexternal_networkare defined. Note that using of classes doesn’t disallow to use global default settings.Grid SettingsTo control the relative positions of elements, Archeme provides the ability to describe nodes arrangement as a text grid. In theelementssection of common settings you may define the horizontal and vertical intervals of the grid step. Code example:elements:grid:spacing_x:400spacing_y:250Thespacing_xparameter sets the horizontal interval and defaults to500; thespacing_yparameter sets the vertical interval and defaults to200. Grid spacing units arepoints; 1 point equals to 1/72 inch.Note thatneatoandfdpengines use different units for theposattribute: points and inches respectively. Archeme takes it into account. If you specifyengine: neato, do not try to draw the resulting graph description withfdp, and vice versa. Thedotengine doesn’t support positioning at all.Scheme DescriptionTo describe a scheme or a diagram, it’s needed to:specify scheme structure—define nodes and clusters;specify relations between nodes—define edges;control the relative positions of nodes:define a text grid, if theneatoorfdpengine is used;specify which nodes should have the same rank, if thedotengine is used.StructureTo define nodes and clusters, Archeme DSL provides thestructuresection. You may assign Graphviz attributes and Archeme classes to any node and any cluster. For nodes, theidparameter is only required. All other parameters are optional. Theidparameter is used to assign a text identifier to a certain node.Simple code example:structure:-node:id:first-node:id:secondIn this example, 2 nodes with the identifiersfirstandsecondare defined.Note that the value of thestructureparameter must be a list. If thedotengine is used, the order of nodes matters for their positioning. If theneatoorfdpengine is used, the order of nodes doesn’t matter.Clusters should be specified at the same level as nodes. Each cluster has nestedstructurethat may include nodes and nested clusters. Code example:structure:-node:id:first-node:id:second-cluster:structure:-node:id:third-node:id:fourthThe following code example shows how it’s possible to assign Graphviz attributes and Archeme classes to nodes and clusters:structure:-node:id:firstlabel:The First Nodeclass:-amazing-awesome-cluster:label:The Wonderful Clusterstyle:filledfillcolor:'#cccccc'class:wonderfulstructure:...Single class name may be specified as a string; multiple class names should be specified as a list.Archeme merges attributes of classes. Suppose 2 classes are defined as the following:classes:amazing:shape:boxwidth:4height:1style:-rounded-filledawesome:height:2style:-dashedfillcolor:'#99ccff'If both styles are assigned to some node in the order:[amazing, awesome], the resulting attributes assigned to the node will be:shape:boxwidth:4height:2style:-rounded-filled-dashedfillcolor:'#99ccff'So, thestyleattributes will be combined. Contradicting values of the attributes of the same names will be taken from the last class in the sequence (likeheightin this example).RelationsTo show relations between nodes, edges are used. To define a list of edges, use theedgessection. Simple code example:edges:-tail:firsthead:second-tail:secondhead:thirdIn this example, 2 edges are defined. These edges specify relations between 3 nodes with the identifiersfirst,second, andthird.Archeme uses directed graphs only. So each edge should have a tail (“source,” “beginning”) and a head (“target,” “ending”). For example, if an edge represents interaction between a client and a server, it will be alright if a tail will be assigned to a client, and a head—to a server. However, client requests and server responses may be shown as two different counter-directed edges.You may assign Graphviz attributes and classes to edges like in case with nodes and clusters. Example:edges:-tail:firsthead:secondlabel:HTTP APIclass:two_arrowsArcheme provides extended syntax for thelabelandxlabelattributes of edges. You may specify protocol and describe transferred data:-tail:firsthead:secondlabel:protocol:HTTPdata:Admin APIThis code will be transformed into the following construction in a graph description:"first" -> "second" [label = <<b>HTTP</b><br />Admin API>];PositioningArcheme implements a powerful concept to control relative positions of scheme elements. Positioning may be described as a multiline text grid. Suppose you have 10 nodes with the identifiers fromfirsttotenth. Feel free to set their positions in this visual way:grid:|-        -    second    sixthfirst         thirdfourth               eighthninthfifth     seventh-tenthIf the engineneatoorfdpis used, the nodes will be strictly positioned with theposattribute. Positions will be calculated using the values of theelements.grid.spacing_xandelements.grid.spacing_yparameters. A hyphen (-) means skipped step if it’s necessary not to place any nodes to the respective horizontal or vertical coordinate.Grid steps are defined by start positions of node identifiers. So, the nodessecond,third,fourth, andfifthfrom the example will be placed to the third horizontal step of the grid.Thedotengine ignores theposattribute, but it allows to place nodes with the same rank to the same hierarchy level of the resulting layout. If thedotengine is used, Archeme analyzes a grid and defines groups (subgraphs) of nodes with the same ranks. For the example above and theelements.graph.rankdirattribute set toLR(left to right), Archeme will generate the following groups:second,third,fourth,fifth;sixth,seventh;eighth,ninth,tenth.If theelements.graph.rankdirattribute is set toTB(top to bottom, default in Graphviz), for the example above Archeme will make the following groups:second,sixth;first,third;fourth,eighth;fifth,seventh.If you don’t plan to use the enginesneatoandfdpto draw a certain scheme, and use onlydot, you don’t need to describe grids. Fordot, instead of using grids, you may define groups of nodes of the same ranks explicitly. Example of code that represents the last described case:groups:--second-sixth--first-third--fourth-eighth--fifth-seventhCombining Multiple SchemesTo combine multiple schemes or diagrams into a single one, themergeArcheme command is used. Archeme merges multiple scheme descriptions using the concept of modules.A module is a scheme description that is used as a part of the structure of the resulting combined scheme description. Optionally some nodes of a certain module may be excluded from the resulting combined scheme description.Each module should have an identifier. To avoid conflicts when some nodes have the same identifiers in different modules, node identifiers are combined with module identifiers in the resulting scheme description. For example, the nodeapifrom the modulebackendwill get the identifierbackend.apiin the resulting combined scheme description.Archeme works with modules that are described in separate files. To include some module into the resulting scheme structure, you should specify module identifier and module description file. Code example:structure:-module:id:backendfile:path/to/backend.yml-module:id:frontendfile:path/to/frontend.ymlIt seems most convenient to describe modules in separate files, if Archeme is used as a stand-alone command-line tool. However, Archeme allows to specify a module description directly as a value of thedescriptionparameter that should be used instead of thefileparameter. This way may be preferred when Archeme is used as a Python package in a third-party application.In this example, 2 modules with the identifiersbackendandfrontendare added to the resulting structure.If you need not to include some module nodes into the resulting structure, use the optionalexcludeparameter:structure:-module:id:frontendfile:path/to/frontend.ymlexclude:-client_device-cdnIn this example, the nodes with the identifiersclient_deviceandcdnof the modulefrontendwill not be taken into account in the resulting combined scheme description.Feel free to add nodes, clusters, and edges to the resulting scheme description in the usual way:structure:-module:id:backendfile:path/to/backend.yml-module:id:frontendfile:path/to/frontend.yml-node:id:middlewareedges:-tail:frontend.applicationhead:middleware-tail:middlewarehead:backend.apiArcheme provides smart merging of grids. Suppose you need to combine 4 modules with the identifiersone,two,three, andfour. You may describe a grid that should be used in the resulting scheme description:grid:|one      twothree    fourArcheme will generate the resulting grid in which, for example, the leftmost nodes of the moduletwowill be placed at the same horizontal position as the leftmost nodes of the modulefour.When merging modules, Archeme deeply processes thestructure,edges,grid, andgroupsparameters of each module. Common parameters for multiple elements such asengineandelementswill be merged using the simplest algorithm. It’s best to specify them in a separate config file that will not be involved in the merge process.ExamplesArcheme repository includessome examplesof architectural schemes.Each example is located in its own folder that has the following structure:source/*—YAML-based DSL sources;target/*—generated graph descriptions for Graphviz, and resulting PNG images;draw.sh—shell script that executes the commands which create target files.PNG images drawn with Graphviz are shown below.1. Foliant Architecture, Simple, Drawn WithneatoDirectory with the example files2. Foliant Architecture, Pretty, Drawn WithneatoDirectory with the example files3. Foliant Architecture, With A Cluster, Drawn WithfdpDirectory with the example files4. Foliant Architecture, With More Clusters, Drawn WithfdpDirectory with the example files5. Foliant Architecture, With Many Nested Clusters, Drawn WithdotDirectory with the example files6. Digital Television System, Two Subsystems, Two Styles, Drawn WithdotDirectory with the example filesStyle 1Subsystem 1Subsystem 2Whole System, Reuses Subsystems DescriptionsStyle 2Subsystem 1Subsystem 2Whole System, Reuses Subsystems DescriptionsClouds and client devices icons are made byiconixar.