Merge branch 'mingrammer:master' into 549

pull/570/head
gabriel-tessier 3 years ago committed by GitHub
commit 97cc0ed3ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -30,9 +30,9 @@ ffmpeg -i my_big_image.jpg -vf scale=w=256:h=256:force_original_aspect_ratio=dec
Then just run the `./autogen.sh` to generate the added or updated node classes. (cf. [DEVELOPMENT][DEVELOPMENT.md]) Then just run the `./autogen.sh` to generate the added or updated node classes. (cf. [DEVELOPMENT][DEVELOPMENT.md])
> IMPORTANT NOTE: To run `autogen.sh`, you need [round][round] and > IMPORTANT NOTE: To run `autogen.sh`, you need [round][round], [black][black] and
> [inkscape][inkscape] command lines that are used for cleaning the image > [inkscape][inkscape] command lines that are used for cleaning the image
> resource filenames. > resource filenames and formatting the generated python code.
> >
> macOS users can download the inkscape via Homebrew. > macOS users can download the inkscape via Homebrew.
> >
@ -40,6 +40,7 @@ Then just run the `./autogen.sh` to generate the added or updated node classes.
[DEVELOPMENT.md]: ./DEVELOPMENT.md [DEVELOPMENT.md]: ./DEVELOPMENT.md
[round]: https://github.com/mingrammer/round [round]: https://github.com/mingrammer/round
[black]: https://pypi.org/project/black
[inkscape]: https://inkscape.org/ko/release [inkscape]: https://inkscape.org/ko/release
### Update Aliases ### Update Aliases
@ -54,7 +55,7 @@ or update the `ALIASES` map in [config.py](config.py).
Then just run the `./autogen.sh` to generate the added or updated aliases. (cf. [DEVELOPMENT][DEVELOPMENT.md]) Then just run the `./autogen.sh` to generate the added or updated aliases. (cf. [DEVELOPMENT][DEVELOPMENT.md])
> IMPORTANT NOTE: To run `autogen.sh`, you need [round][round] and > IMPORTANT NOTE: To run `autogen.sh`, you need [round][round] and
> [inkscape][inkscape] command lines that are used for clearning the image > [inkscape][inkscape] command lines that are used for cleaning the image
> resource filenames. > resource filenames.
> >
> Or you should use the docker image. > Or you should use the docker image.

@ -34,4 +34,44 @@ You should have docker installed in your system, if not click [here](https://doc
docker exec diagrams ./autogen.sh docker exec diagrams ./autogen.sh
``` ```
6. If the unit tests and the bash script `autogen.sh` is working correctly, then your system is now ready for development. 6. If the unit tests and the bash script `autogen.sh` is working correctly, then your system is now ready for development.
## Mac local development setup
To be able to develop and run diagrams locally on you Mac device, you should have [Python](https://www.python.org/downloads/), [Go](https://golang.org/doc/install) and [brew](https://brew.sh/) installed on your system.
1. Go to diagrams root directory.
2. Install poetry, the Python project management package used by diagrams.
```shell
pip install poetry
```
3. Install the project's Python dependencies.
```shell
poetry install
```
4. Install diagrams binary dependencies.
```shell
brew install imagemagick inkscape black
go get github.com/mingrammer/round
```
5. Run unit tests to confirm that it's working.
```shell
python -m unittest tests/*.py -v
```
6. Run the bash script `autogen.sh` to test.
```shell
./autogen.sh
```
7. If the unit tests and the bash script `autogen.sh` is working correctly, then your system is now ready for development.

@ -4,7 +4,7 @@
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](/LICENSE) [![license](https://img.shields.io/badge/license-MIT-blue.svg)](/LICENSE)
[![pypi version](https://badge.fury.io/py/diagrams.svg)](https://badge.fury.io/py/diagrams) [![pypi version](https://badge.fury.io/py/diagrams.svg)](https://badge.fury.io/py/diagrams)
![python version](https://img.shields.io/badge/python-3.6%2C3.7%2C3.8-blue?logo=python) ![python version](https://img.shields.io/badge/python-%3E%3D%203.6-blue?logo=python)
![Run tests](https://github.com/mingrammer/diagrams/workflows/Run%20tests/badge.svg?branch=master) ![Run tests](https://github.com/mingrammer/diagrams/workflows/Run%20tests/badge.svg?branch=master)
[![todos](https://badgen.net/https/api.tickgit.com/badgen/github.com/mingrammer/diagrams?label=todos)](https://www.tickgit.com/browse?repo=github.com/mingrammer/diagrams) [![todos](https://badgen.net/https/api.tickgit.com/badgen/github.com/mingrammer/diagrams?label=todos)](https://www.tickgit.com/browse?repo=github.com/mingrammer/diagrams)
![contributors](https://img.shields.io/github/contributors/mingrammer/diagrams) ![contributors](https://img.shields.io/github/contributors/mingrammer/diagrams)
@ -26,16 +26,18 @@ Diagrams lets you draw the cloud system architecture **in Python code**. It was
![gcp provider](https://img.shields.io/badge/GCP-orange?logo=google-cloud&color=4285f4) ![gcp provider](https://img.shields.io/badge/GCP-orange?logo=google-cloud&color=4285f4)
![ibm provider](https://img.shields.io/badge/IBM-orange?logo=ibm&color=052FAD) ![ibm provider](https://img.shields.io/badge/IBM-orange?logo=ibm&color=052FAD)
![kubernetes provider](https://img.shields.io/badge/Kubernetes-orange?logo=kubernetes&color=326ce5) ![kubernetes provider](https://img.shields.io/badge/Kubernetes-orange?logo=kubernetes&color=326ce5)
![alibaba cloud provider](https://img.shields.io/badge/AlibabaCloud-orange) ![alibaba cloud provider](https://img.shields.io/badge/AlibabaCloud-orange?logo=alibaba-cloud&color=ff6a00)
![oracle cloud provider](https://img.shields.io/badge/OracleCloud-orange?logo=oracle&color=f80000) ![oracle cloud provider](https://img.shields.io/badge/OracleCloud-orange?logo=oracle&color=f80000)
![openstack provider](https://img.shields.io/badge/OpenStack-orange?logo=openstack&color=da1a32) ![openstack provider](https://img.shields.io/badge/OpenStack-orange?logo=openstack&color=da1a32)
![firebase provider](https://img.shields.io/badge/Firebase-orange?logo=firebase&color=FFCA28) ![firebase provider](https://img.shields.io/badge/Firebase-orange?logo=firebase&color=FFCA28)
![digital ocean provider](https://img.shields.io/badge/DigitalOcean-0080ff?logo=digitalocean&color=0080ff)
![elastic provider](https://img.shields.io/badge/Elastic-orange?logo=elastic&color=005571) ![elastic provider](https://img.shields.io/badge/Elastic-orange?logo=elastic&color=005571)
![outscale provider](https://img.shields.io/badge/OutScale-orange?color=5f87bf) ![outscale provider](https://img.shields.io/badge/OutScale-orange?color=5f87bf)
![on premise provider](https://img.shields.io/badge/OnPremise-orange?color=5f87bf) ![on premise provider](https://img.shields.io/badge/OnPremise-orange?color=5f87bf)
![generic provider](https://img.shields.io/badge/Generic-orange?color=5f87bf) ![generic provider](https://img.shields.io/badge/Generic-orange?color=5f87bf)
![programming provider](https://img.shields.io/badge/Programming-orange?color=5f87bf) ![programming provider](https://img.shields.io/badge/Programming-orange?color=5f87bf)
![saas provider](https://img.shields.io/badge/SaaS-orange?color=5f87bf) ![saas provider](https://img.shields.io/badge/SaaS-orange?color=5f87bf)
![c4 provider](https://img.shields.io/badge/C4-orange?color=5f87bf)
## Getting Started ## Getting Started
@ -82,7 +84,7 @@ To contribute to diagram, check out [contribution guidelines](CONTRIBUTING.md).
## Other languages ## Other languages
- If you are familiar to Go, you can use [go-diagrams](https://github.com/blushft/go-diagrams) as well. - If you are familiar with Go, you can use [go-diagrams](https://github.com/blushft/go-diagrams) as well.
## License ## License

@ -4,7 +4,7 @@ set -e
app_root_dir="diagrams" app_root_dir="diagrams"
# NOTE: azure icon set is not latest version # NOTE: azure icon set is not latest version
providers=("onprem" "aws" "azure" "gcp" "ibm" "firebase" "k8s" "alibabacloud" "oci" "programming" "saas" "elastic" "generic" "openstack" "outscale" ) providers=("onprem" "aws" "azure" "digitalocean" "gcp" "ibm" "firebase" "k8s" "alibabacloud" "oci" "programming" "saas" "elastic" "generic" "openstack" "outscale" )
if ! [ -x "$(command -v round)" ]; then if ! [ -x "$(command -v round)" ]; then
echo 'round is not installed' echo 'round is not installed'

@ -12,8 +12,8 @@ DIR_RESOURCE = "resources"
DIR_TEMPLATE = "templates" DIR_TEMPLATE = "templates"
PROVIDERS = ( PROVIDERS = (
"base", "onprem", "aws", "azure", "gcp", "ibm", "firebase", "k8s", "alibabacloud", "oci", "programming", "saas", "elastic", "base", "onprem", "aws", "azure", "digitalocean", "gcp", "ibm", "firebase", "k8s", "alibabacloud", "oci",
"generic", "openstack", "outscale") "programming", "saas", "elastic", "generic", "openstack", "outscale")
######################### #########################
# Resource Processing # # Resource Processing #
@ -30,6 +30,7 @@ FILE_PREFIXES = {
"onprem": (), "onprem": (),
"aws": ("Amazon-", "AWS-"), "aws": ("Amazon-", "AWS-"),
"azure": ("Azure-",), "azure": ("Azure-",),
"digitalocean": (),
"gcp": ("Cloud-",), "gcp": ("Cloud-",),
"firebase": ("Cloud-",), "firebase": ("Cloud-",),
"ibm": (), "ibm": (),
@ -58,7 +59,7 @@ TMPL_MODULE = "module.tmpl"
UPPER_WORDS = { UPPER_WORDS = {
"aws": ("aws", "api", "ebs", "ec2", "efs", "emr", "rds", "ml", "mq", "nat", "vpc", "waf", "sdk"), "aws": ("aws", "api", "ebs", "ec2", "efs", "emr", "rds", "ml", "mq", "nat", "vpc", "waf", "sdk"),
"azure": ("ad", "b2c", "ai", "api", "cdn", "ddos", "dns", "fxt", "hana", "hd", "id", "sap", "sql", "vm"), "azure": ("ad", "b2c", "ai", "api", "cdn", "ddos", "dns", "fxt", "hana", "hd", "id", "sap", "sql", "vm", "vpn", "vpc"),
"gcp": ("gcp", "ai", "api", "cdn", "dns", "gke", "gpu", "iap", "ml", "nat", "os", "sdk", "sql", "tpu", "vpn"), "gcp": ("gcp", "ai", "api", "cdn", "dns", "gke", "gpu", "iap", "ml", "nat", "os", "sdk", "sql", "tpu", "vpn"),
"firebase": ("ab", "fcm", "ml"), "firebase": ("ab", "fcm", "ml"),
"k8s": ( "k8s": (
@ -84,6 +85,9 @@ TITLE_WORDS = {
"aws": { "aws": {
"cloudfront": "CloudFront" "cloudfront": "CloudFront"
}, },
"digitalocean": {
"digitalocean": "DigitalOcean"
},
"openstack": { "openstack": {
"openstack": "OpenStack" "openstack": "OpenStack"
}, },
@ -386,6 +390,7 @@ ALIASES = {
"ObjectTableStore": "OTS", "ObjectTableStore": "OTS",
} }
}, },
"digitalocean": {},
"oci": { "oci": {
"compute": { "compute": {
"VM": "VirtualMachine", "VM": "VirtualMachine",
@ -406,7 +411,8 @@ ALIASES = {
}, },
"programming": { "programming": {
"framework": { "framework": {
"Fastapi": "FastAPI" "Fastapi": "FastAPI",
"Graphql": "GraphQL"
}, },
"language": { "language": {
"Javascript": "JavaScript", "Javascript": "JavaScript",

@ -15,32 +15,32 @@ __diagram = contextvars.ContextVar("diagrams")
__cluster = contextvars.ContextVar("cluster") __cluster = contextvars.ContextVar("cluster")
def getdiagram(): def getdiagram() -> "Diagram":
try: try:
return __diagram.get() return __diagram.get()
except LookupError: except LookupError:
return None return None
def setdiagram(diagram): def setdiagram(diagram: "Diagram"):
__diagram.set(diagram) __diagram.set(diagram)
def getcluster(): def getcluster() -> "Cluster":
try: try:
return __cluster.get() return __cluster.get()
except LookupError: except LookupError:
return None return None
def setcluster(cluster): def setcluster(cluster: "Cluster"):
__cluster.set(cluster) __cluster.set(cluster)
class Diagram: class Diagram:
__directions = ("TB", "BT", "LR", "RL") __directions = ("TB", "BT", "LR", "RL")
__curvestyles = ("ortho", "curved") __curvestyles = ("ortho", "curved")
__outformats = ("png", "jpg", "svg", "pdf") __outformats = ("png", "jpg", "svg", "pdf", "dot")
# fmt: off # fmt: off
_default_graph_attrs = { _default_graph_attrs = {
@ -83,6 +83,7 @@ class Diagram:
direction: str = "LR", direction: str = "LR",
curvestyle: str = "ortho", curvestyle: str = "ortho",
outformat: str = "png", outformat: str = "png",
autolabel: bool = False,
show: bool = True, show: bool = True,
graph_attr: dict = {}, graph_attr: dict = {},
node_attr: dict = {}, node_attr: dict = {},
@ -127,8 +128,13 @@ class Diagram:
raise ValueError(f'"{curvestyle}" is not a valid curvestyle') raise ValueError(f'"{curvestyle}" is not a valid curvestyle')
self.dot.graph_attr["splines"] = curvestyle self.dot.graph_attr["splines"] = curvestyle
if not self._validate_outformat(outformat): if isinstance(outformat, list):
raise ValueError(f'"{outformat}" is not a valid output format') for one_format in outformat:
if not self._validate_outformat(one_format):
raise ValueError(f'"{one_format}" is not a valid output format')
else:
if not self._validate_outformat(outformat):
raise ValueError(f'"{outformat}" is not a valid output format')
self.outformat = outformat self.outformat = outformat
# Merge passed in attributes # Merge passed in attributes
@ -137,6 +143,7 @@ class Diagram:
self.dot.edge_attr.update(edge_attr) self.dot.edge_attr.update(edge_attr)
self.show = show self.show = show
self.autolabel = autolabel
def __str__(self) -> str: def __str__(self) -> str:
return str(self.dot) return str(self.dot)
@ -155,25 +162,13 @@ class Diagram:
return self.dot.pipe(format="png") return self.dot.pipe(format="png")
def _validate_direction(self, direction: str) -> bool: def _validate_direction(self, direction: str) -> bool:
direction = direction.upper() return direction.upper() in self.__directions
for v in self.__directions:
if v == direction:
return True
return False
def _validate_curvestyle(self, curvestyle: str) -> bool: def _validate_curvestyle(self, curvestyle: str) -> bool:
curvestyle = curvestyle.lower() return curvestyle.lower() in self.__curvestyles
for v in self.__curvestyles:
if v == curvestyle:
return True
return False
def _validate_outformat(self, outformat: str) -> bool: def _validate_outformat(self, outformat: str) -> bool:
outformat = outformat.lower() return outformat.lower() in self.__outformats
for v in self.__outformats:
if v == outformat:
return True
return False
def node(self, nodeid: str, label: str, **attrs) -> None: def node(self, nodeid: str, label: str, **attrs) -> None:
"""Create a new node.""" """Create a new node."""
@ -188,7 +183,11 @@ class Diagram:
self.dot.subgraph(dot) self.dot.subgraph(dot)
def render(self) -> None: def render(self) -> None:
self.dot.render(format=self.outformat, view=self.show, quiet=True) if isinstance(self.outformat, list):
for one_format in self.outformat:
self.dot.render(format=one_format, view=self.show, quiet=True)
else:
self.dot.render(format=self.outformat, view=self.show, quiet=True)
class Cluster: class Cluster:
@ -261,12 +260,8 @@ class Cluster:
self._diagram.subgraph(self.dot) self._diagram.subgraph(self.dot)
setcluster(self._parent) setcluster(self._parent)
def _validate_direction(self, direction: str): def _validate_direction(self, direction: str) -> bool:
direction = direction.upper() return direction.upper() in self.__directions
for v in self.__directions:
if v == direction:
return True
return False
def node(self, nodeid: str, label: str, **attrs) -> None: def node(self, nodeid: str, label: str, **attrs) -> None:
"""Create a new node in the cluster.""" """Create a new node in the cluster."""
@ -287,20 +282,32 @@ class Node:
_height = 1.9 _height = 1.9
def __init__(self, label: str = "", **attrs: Dict): def __init__(self, label: str = "", *, nodeid: str = None, **attrs: Dict):
"""Node represents a system component. """Node represents a system component.
:param label: Node label. :param label: Node label.
""" """
# Generates an ID for identifying a node. # Generates an ID for identifying a node, unless specified
self._id = self._rand_id() self._id = nodeid or self._rand_id()
self.label = label self.label = label
# Node must be belong to a diagrams.
self._diagram = getdiagram()
if self._diagram is None:
raise EnvironmentError("Global diagrams context not set up")
if self._diagram.autolabel:
prefix = self.__class__.__name__
if self.label:
self.label = prefix + "\n" + self.label
else:
self.label = prefix
# fmt: off # fmt: off
# If a node has an icon, increase the height slightly to avoid # If a node has an icon, increase the height slightly to avoid
# that label being spanned between icon image and white space. # that label being spanned between icon image and white space.
# Increase the height by the number of new lines included in the label. # Increase the height by the number of new lines included in the label.
padding = 0.4 * (label.count('\n')) padding = 0.4 * (self.label.count('\n'))
self._attrs = { self._attrs = {
"shape": "none", "shape": "none",
"height": str(self._height + padding), "height": str(self._height + padding),
@ -310,10 +317,6 @@ class Node:
# fmt: on # fmt: on
self._attrs.update(attrs) self._attrs.update(attrs)
# Node must be belong to a diagrams.
self._diagram = getdiagram()
if self._diagram is None:
raise EnvironmentError("Global diagrams context not set up")
self._cluster = getcluster() self._cluster = getcluster()
# If a node is in the cluster context, add it to cluster. # If a node is in the cluster context, add it to cluster.

@ -8,6 +8,10 @@ class _Compute(_AWS):
_icon_dir = "resources/aws/compute" _icon_dir = "resources/aws/compute"
class AppRunner(_Compute):
_icon = "app-runner.png"
class ApplicationAutoScaling(_Compute): class ApplicationAutoScaling(_Compute):
_icon = "application-auto-scaling.png" _icon = "application-auto-scaling.png"

@ -12,6 +12,10 @@ class AutoScaling(_Management):
_icon = "auto-scaling.png" _icon = "auto-scaling.png"
class Chatbot(_Management):
_icon = "chatbot.png"
class CloudformationChangeSet(_Management): class CloudformationChangeSet(_Management):
_icon = "cloudformation-change-set.png" _icon = "cloudformation-change-set.png"

@ -0,0 +1,97 @@
"""
A set of nodes and edges to visualize software architecture using the C4 model.
"""
import html
import textwrap
from diagrams import Cluster, Node, Edge
def _format_node_label(name, key, description):
"""Create a graphviz label string for a C4 node"""
title = f'<font point-size="12"><b>{html.escape(name)}</b></font><br/>'
subtitle = f'<font point-size="9">[{html.escape(key)}]<br/></font>' if key else ""
text = f'<br/><font point-size="10">{_format_description(description)}</font>' if description else ""
return f"<{title}{subtitle}{text}>"
def _format_description(description):
"""
Formats the description string so it fits into the C4 nodes.
It line-breaks the description so it fits onto exactly three lines. If there are more
than three lines, all further lines are discarded and "..." inserted on the last line to
indicate that it was shortened. This will also html-escape the description so it can
safely be included in a HTML label.
"""
wrapper = textwrap.TextWrapper(width=40, max_lines=3)
lines = [html.escape(line) for line in wrapper.wrap(description)]
lines += [""] * (3 - len(lines)) # fill up with empty lines so it is always three
return "<br/>".join(lines)
def _format_edge_label(description):
"""Create a graphviz label string for a C4 edge"""
wrapper = textwrap.TextWrapper(width=24, max_lines=3)
lines = [html.escape(line) for line in wrapper.wrap(description)]
text = "<br/>".join(lines)
return f'<<font point-size="10">{text}</font>>'
def C4Node(name, technology="", description="", type="Container", **kwargs):
key = f"{type}: {technology}" if technology else type
node_attributes = {
"label": _format_node_label(name, key, description),
"labelloc": "c",
"shape": "rect",
"width": "2.6",
"height": "1.6",
"fixedsize": "true",
"style": "filled",
"fillcolor": "dodgerblue3",
"fontcolor": "white",
}
# collapse boxes to a smaller form if they don't have a description
if not description:
node_attributes.update({"width": "2", "height": "1"})
node_attributes.update(kwargs)
return Node(**node_attributes)
def Container(name, technology="", description="", **kwargs):
return C4Node(name, technology=technology, description=description, type="Container")
def Database(name, technology="", description="", **kwargs):
return C4Node(name, technology=technology, description=description, type="Database", shape="cylinder", labelloc="b")
def System(name, description="", external=False, **kwargs):
type = "External System" if external else "System"
fillcolor = "gray60" if external else "dodgerblue4"
return C4Node(name, description=description, type=type, fillcolor=fillcolor)
def Person(name, description="", external=False, **kwargs):
type = "External Person" if external else "Person"
fillcolor = "gray60" if external else "dodgerblue4"
style = "rounded,filled"
return C4Node(name, description=description, type=type, fillcolor=fillcolor, style=style)
def SystemBoundary(name, **kwargs):
graph_attributes = {
"label": html.escape(name),
"bgcolor": "white",
"margin": "16",
"style": "dashed",
}
graph_attributes.update(kwargs)
return Cluster(name, graph_attr=graph_attributes)
def Relationship(label="", **kwargs):
edge_attribtues = {"style": "dashed", "color": "gray60"}
if label:
edge_attribtues.update({"label": _format_edge_label(label)})
edge_attribtues.update(kwargs)
return Edge(**edge_attribtues)

@ -15,6 +15,6 @@ class Custom(Node):
def _load_icon(self): def _load_icon(self):
return self._icon return self._icon
def __init__(self, label, icon_path): def __init__(self, label, icon_path, *args, **kwargs):
self._icon = icon_path self._icon = icon_path
super().__init__(label) super().__init__(label, *args, **kwargs)

@ -0,0 +1,12 @@
"""
DigitalOcean provides a set of services for DigitalOcean provider.
"""
from diagrams import Node
class _DigitalOcean(Node):
_provider = "digitalocean"
_icon_dir = "resources/digitalocean"
fontcolor = "#ffffff"

@ -0,0 +1,43 @@
# This module is automatically generated by autogen.sh. DO NOT EDIT.
from . import _DigitalOcean
class _Compute(_DigitalOcean):
_type = "compute"
_icon_dir = "resources/digitalocean/compute"
class Containers(_Compute):
_icon = "containers.png"
class Docker(_Compute):
_icon = "docker.png"
class DropletConnect(_Compute):
_icon = "droplet-connect.png"
class DropletSnapshot(_Compute):
_icon = "droplet-snapshot.png"
class Droplet(_Compute):
_icon = "droplet.png"
class K8SCluster(_Compute):
_icon = "k8s-cluster.png"
class K8SNodePool(_Compute):
_icon = "k8s-node-pool.png"
class K8SNode(_Compute):
_icon = "k8s-node.png"
# Aliases

@ -0,0 +1,27 @@
# This module is automatically generated by autogen.sh. DO NOT EDIT.
from . import _DigitalOcean
class _Database(_DigitalOcean):
_type = "database"
_icon_dir = "resources/digitalocean/database"
class DbaasPrimaryStandbyMore(_Database):
_icon = "dbaas-primary-standby-more.png"
class DbaasPrimary(_Database):
_icon = "dbaas-primary.png"
class DbaasReadOnly(_Database):
_icon = "dbaas-read-only.png"
class DbaasStandby(_Database):
_icon = "dbaas-standby.png"
# Aliases

@ -0,0 +1,47 @@
# This module is automatically generated by autogen.sh. DO NOT EDIT.
from . import _DigitalOcean
class _Network(_DigitalOcean):
_type = "network"
_icon_dir = "resources/digitalocean/network"
class Certificate(_Network):
_icon = "certificate.png"
class DomainRegistration(_Network):
_icon = "domain-registration.png"
class Domain(_Network):
_icon = "domain.png"
class Firewall(_Network):
_icon = "firewall.png"
class FloatingIp(_Network):
_icon = "floating-ip.png"
class InternetGateway(_Network):
_icon = "internet-gateway.png"
class LoadBalancer(_Network):
_icon = "load-balancer.png"
class ManagedVpn(_Network):
_icon = "managed-vpn.png"
class Vpc(_Network):
_icon = "vpc.png"
# Aliases

@ -0,0 +1,27 @@
# This module is automatically generated by autogen.sh. DO NOT EDIT.
from . import _DigitalOcean
class _Storage(_DigitalOcean):
_type = "storage"
_icon_dir = "resources/digitalocean/storage"
class Folder(_Storage):
_icon = "folder.png"
class Space(_Storage):
_icon = "space.png"
class VolumeSnapshot(_Storage):
_icon = "volume-snapshot.png"
class Volume(_Storage):
_icon = "volume.png"
# Aliases

@ -8,6 +8,10 @@ class _API(_GCP):
_icon_dir = "resources/gcp/api" _icon_dir = "resources/gcp/api"
class APIGateway(_API):
_icon = "api-gateway.png"
class Endpoints(_API): class Endpoints(_API):
_icon = "endpoints.png" _icon = "endpoints.png"

@ -28,6 +28,10 @@ class LinuxGeneral(_Os):
_icon = "linux-general.png" _icon = "linux-general.png"
class Raspbian(_Os):
_icon = "raspbian.png"
class Suse(_Os): class Suse(_Os):
_icon = "suse.png" _icon = "suse.png"

@ -20,6 +20,10 @@ class Dbt(_Analytics):
_icon = "dbt.png" _icon = "dbt.png"
class Dremio(_Analytics):
_icon = "dremio.png"
class Flink(_Analytics): class Flink(_Analytics):
_icon = "flink.png" _icon = "flink.png"

@ -28,6 +28,10 @@ class Gvisor(_Container):
_icon = "gvisor.png" _icon = "gvisor.png"
class K3S(_Container):
_icon = "k3s.png"
class Lxc(_Container): class Lxc(_Container):
_icon = "lxc.png" _icon = "lxc.png"

@ -20,6 +20,10 @@ class Awx(_Iac):
_icon = "awx.png" _icon = "awx.png"
class Puppet(_Iac):
_icon = "puppet.png"
class Terraform(_Iac): class Terraform(_Iac):
_icon = "terraform.png" _icon = "terraform.png"

@ -16,6 +16,10 @@ class Datadog(_Monitoring):
_icon = "datadog.png" _icon = "datadog.png"
class Dynatrace(_Monitoring):
_icon = "dynatrace.png"
class Grafana(_Monitoring): class Grafana(_Monitoring):
_icon = "grafana.png" _icon = "grafana.png"
@ -24,6 +28,10 @@ class Humio(_Monitoring):
_icon = "humio.png" _icon = "humio.png"
class Nagios(_Monitoring):
_icon = "nagios.png"
class Newrelic(_Monitoring): class Newrelic(_Monitoring):
_icon = "newrelic.png" _icon = "newrelic.png"

@ -108,6 +108,10 @@ class Traefik(_Network):
_icon = "traefik.png" _icon = "traefik.png"
class Tyk(_Network):
_icon = "tyk.png"
class Vyos(_Network): class Vyos(_Network):
_icon = "vyos.png" _icon = "vyos.png"

@ -24,4 +24,8 @@ class Gitlab(_Vcs):
_icon = "gitlab.png" _icon = "gitlab.png"
class Svn(_Vcs):
_icon = "svn.png"
# Aliases # Aliases

@ -36,6 +36,10 @@ class Flutter(_Framework):
_icon = "flutter.png" _icon = "flutter.png"
class Graphql(_Framework):
_icon = "graphql.png"
class Laravel(_Framework): class Laravel(_Framework):
_icon = "laravel.png" _icon = "laravel.png"
@ -56,6 +60,10 @@ class Spring(_Framework):
_icon = "spring.png" _icon = "spring.png"
class Starlette(_Framework):
_icon = "starlette.png"
class Vue(_Framework): class Vue(_Framework):
_icon = "vue.png" _icon = "vue.png"
@ -63,3 +71,4 @@ class Vue(_Framework):
# Aliases # Aliases
FastAPI = Fastapi FastAPI = Fastapi
GraphQL = Graphql

@ -52,6 +52,10 @@ class Kotlin(_Language):
_icon = "kotlin.png" _icon = "kotlin.png"
class Latex(_Language):
_icon = "latex.png"
class Matlab(_Language): class Matlab(_Language):
_icon = "matlab.png" _icon = "matlab.png"

@ -0,0 +1,15 @@
# This module is automatically generated by autogen.sh. DO NOT EDIT.
from . import _Programming
class _Runtime(_Programming):
_type = "runtime"
_icon_dir = "resources/programming/runtime"
class Dapr(_Runtime):
_icon = "dapr.png"
# Aliases

@ -20,4 +20,8 @@ class Pushover(_Alerting):
_icon = "pushover.png" _icon = "pushover.png"
class Xmatters(_Alerting):
_icon = "xmatters.png"
# Aliases # Aliases

@ -16,4 +16,8 @@ class Cloudflare(_Cdn):
_icon = "cloudflare.png" _icon = "cloudflare.png"
class Fastly(_Cdn):
_icon = "fastly.png"
# Aliases # Aliases

@ -32,4 +32,12 @@ class Telegram(_Chat):
_icon = "telegram.png" _icon = "telegram.png"
class Messenger(_Chat):
_icon = "messenger.png"
class Line(_Chat):
_icon = "line.png"
# Aliases # Aliases

@ -0,0 +1,15 @@
# This module is automatically generated by autogen.sh. DO NOT EDIT.
from . import _Saas
class _Communication(_Saas):
_type = "communication"
_icon_dir = "resources/saas/communication"
class Twilio(_Communication):
_icon = "twilio.png"
# Aliases

@ -6,7 +6,7 @@ RUN apk update && apk add --no-cache \
gcc libc-dev g++ graphviz git bash go imagemagick inkscape ttf-opensans curl fontconfig xdg-utils gcc libc-dev g++ graphviz git bash go imagemagick inkscape ttf-opensans curl fontconfig xdg-utils
# install go package. # install go package.
RUN go get github.com/mingrammer/round RUN go install github.com/mingrammer/round@latest
# install fonts # install fonts
RUN curl -O https://noto-website.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip \ RUN curl -O https://noto-website.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip \

@ -42,13 +42,13 @@ with Diagram("Clustered Web Services", show=False):
ECS("web3")] ECS("web3")]
with Cluster("DB Cluster"): with Cluster("DB Cluster"):
db_main = RDS("userdb") db_primary = RDS("userdb")
db_main - [RDS("userdb ro")] db_primary - [RDS("userdb ro")]
memcached = ElastiCache("memcached") memcached = ElastiCache("memcached")
dns >> lb >> svc_group dns >> lb >> svc_group
svc_group >> db_main svc_group >> db_primary
svc_group >> memcached svc_group >> memcached
``` ```
@ -196,14 +196,14 @@ with Diagram("Advanced Web Service with On-Premise", show=False):
Server("grpc3")] Server("grpc3")]
with Cluster("Sessions HA"): with Cluster("Sessions HA"):
main = Redis("session") primary = Redis("session")
main - Redis("replica") << metrics primary - Redis("replica") << metrics
grpcsvc >> main grpcsvc >> primary
with Cluster("Database HA"): with Cluster("Database HA"):
main = PostgreSQL("users") primary = PostgreSQL("users")
main - PostgreSQL("replica") << metrics primary - PostgreSQL("replica") << metrics
grpcsvc >> main grpcsvc >> primary
aggregator = Fluentd("logging") aggregator = Fluentd("logging")
aggregator >> Kafka("stream") >> Spark("analytics") aggregator >> Kafka("stream") >> Spark("analytics")
@ -239,14 +239,14 @@ with Diagram(name="Advanced Web Service with On-Premise (colored)", show=False):
Server("grpc3")] Server("grpc3")]
with Cluster("Sessions HA"): with Cluster("Sessions HA"):
main = Redis("session") primary = Redis("session")
main - Edge(color="brown", style="dashed") - Redis("replica") << Edge(label="collect") << metrics primary - Edge(color="brown", style="dashed") - Redis("replica") << Edge(label="collect") << metrics
grpcsvc >> Edge(color="brown") >> main grpcsvc >> Edge(color="brown") >> primary
with Cluster("Database HA"): with Cluster("Database HA"):
main = PostgreSQL("users") primary = PostgreSQL("users")
main - Edge(color="brown", style="dotted") - PostgreSQL("replica") << Edge(label="collect") << metrics primary - Edge(color="brown", style="dotted") - PostgreSQL("replica") << Edge(label="collect") << metrics
grpcsvc >> Edge(color="black") >> main grpcsvc >> Edge(color="black") >> primary
aggregator = Fluentd("logging") aggregator = Fluentd("logging")
aggregator >> Edge(label="parse") >> Kafka("stream") >> Edge(color="black", style="bold") >> Spark("analytics") aggregator >> Edge(label="parse") >> Kafka("stream") >> Edge(color="black", style="bold") >> Spark("analytics")

@ -22,11 +22,11 @@ with Diagram("Simple Web Service with DB Cluster", show=False):
web = ECS("service") web = ECS("service")
with Cluster("DB Cluster"): with Cluster("DB Cluster"):
db_main = RDS("main") db_primary = RDS("primary")
db_main - [RDS("replica1"), db_primary - [RDS("replica1"),
RDS("replica2")] RDS("replica2")]
dns >> web >> db_main dns >> web >> db_primary
``` ```
![simple web service with db cluster diagram](/img/simple_web_service_with_db_cluster_diagram.png) ![simple web service with db cluster diagram](/img/simple_web_service_with_db_cluster_diagram.png)

@ -44,7 +44,7 @@ diag
You can specify the output file format with `outformat` parameter. Default is **png**. You can specify the output file format with `outformat` parameter. Default is **png**.
> (png, jpg, svg, and pdf) are allowed. > (png, jpg, svg, pdf and dot) are allowed.
```python ```python
from diagrams import Diagram from diagrams import Diagram
@ -54,6 +54,16 @@ with Diagram("Simple Diagram", outformat="jpg"):
EC2("web") EC2("web")
``` ```
The `outformat` parameter also support list to output all the defined output in one call.
```python
from diagrams import Diagram
from diagrams.aws.compute import EC2
with Diagram("Simple Diagram Multi Output", outformat=["jpg", "png", "dot"]):
EC2("web")
```
You can specify the output filename with `filename` parameter. The extension shouldn't be included, it's determined by the `outformat` parameter. You can specify the output filename with `filename` parameter. The extension shouldn't be included, it's determined by the `outformat` parameter.
```python ```python

@ -35,22 +35,22 @@ with Diagram(name="Advanced Web Service with On-Premise (colored)", show=False):
Server("grpc3")] Server("grpc3")]
with Cluster("Sessions HA"): with Cluster("Sessions HA"):
main = Redis("session") primary = Redis("session")
main \ primary \
- Edge(color="brown", style="dashed") \ - Edge(color="brown", style="dashed") \
- Redis("replica") \ - Redis("replica") \
<< Edge(label="collect") \ << Edge(label="collect") \
<< metrics << metrics
grpcsvc >> Edge(color="brown") >> main grpcsvc >> Edge(color="brown") >> primary
with Cluster("Database HA"): with Cluster("Database HA"):
main = PostgreSQL("users") primary = PostgreSQL("users")
main \ primary \
- Edge(color="brown", style="dotted") \ - Edge(color="brown", style="dotted") \
- PostgreSQL("replica") \ - PostgreSQL("replica") \
<< Edge(label="collect") \ << Edge(label="collect") \
<< metrics << metrics
grpcsvc >> Edge(color="black") >> main grpcsvc >> Edge(color="black") >> primary
aggregator = Fluentd("logging") aggregator = Fluentd("logging")
aggregator \ aggregator \

@ -57,6 +57,7 @@ Node classes list of aws provider.
## aws.compute ## aws.compute
- **diagrams.aws.compute.AppRunner**
- **diagrams.aws.compute.ApplicationAutoScaling**, **AutoScaling** (alias) - **diagrams.aws.compute.ApplicationAutoScaling**, **AutoScaling** (alias)
- **diagrams.aws.compute.Batch** - **diagrams.aws.compute.Batch**
- **diagrams.aws.compute.ComputeOptimizer** - **diagrams.aws.compute.ComputeOptimizer**
@ -301,6 +302,7 @@ Node classes list of aws provider.
## aws.management ## aws.management
- **diagrams.aws.management.AutoScaling** - **diagrams.aws.management.AutoScaling**
- **diagrams.aws.management.Chatbot**
- **diagrams.aws.management.CloudformationChangeSet** - **diagrams.aws.management.CloudformationChangeSet**
- **diagrams.aws.management.CloudformationStack** - **diagrams.aws.management.CloudformationStack**
- **diagrams.aws.management.CloudformationTemplate** - **diagrams.aws.management.CloudformationTemplate**

@ -0,0 +1,77 @@
---
id: c4
title: C4
---
## C4 Diagrams
[C4](https://c4model.com/) is a standardized model to visualize software architecture.
You can generate C4 diagrams by using the node and edge classes from the `diagrams.c4` package:
```python
from diagrams import Diagram
from diagrams.c4 import Person, Container, Database, System, SystemBoundary, Relationship
graph_attr = {
"splines": "spline",
}
with Diagram("Container diagram for Internet Banking System", direction="TB", graph_attr=graph_attr):
customer = Person(
name="Personal Banking Customer", description="A customer of the bank, with personal bank accounts."
)
with SystemBoundary("Internet Banking System"):
webapp = Container(
name="Web Application",
technology="Java and Spring MVC",
description="Delivers the static content and the Internet banking single page application.",
)
spa = Container(
name="Single-Page Application",
technology="Javascript and Angular",
description="Provides all of the Internet banking functionality to customers via their web browser.",
)
mobileapp = Container(
name="Mobile App",
technology="Xamarin",
description="Provides a limited subset of the Internet banking functionality to customers via their mobile device.",
)
api = Container(
name="API Application",
technology="Java and Spring MVC",
description="Provides Internet banking functionality via a JSON/HTTPS API.",
)
database = Database(
name="Database",
technology="Oracle Database Schema",
description="Stores user registration information, hashed authentication credentials, access logs, etc.",
)
email = System(name="E-mail System", description="The internal Microsoft Exchange e-mail system.", external=True)
mainframe = System(
name="Mainframe Banking System",
description="Stores all of the core banking information about customers, accounts, transactions, etc.",
external=True,
)
customer >> Relationship("Visits bigbank.com/ib using [HTTPS]") >> webapp
customer >> Relationship("Views account balances, and makes payments using") >> [spa, mobileapp]
webapp >> Relationship("Delivers to the customer's web browser") >> spa
spa >> Relationship("Make API calls to [JSON/HTTPS]") >> api
mobileapp >> Relationship("Make API calls to [JSON/HTTPS]") >> api
api >> Relationship("reads from and writes to") >> database
api >> Relationship("Sends email using [SMTP]") >> email
api >> Relationship("Makes API calls to [XML/HTTPS]") >> mainframe
customer << Relationship("Sends e-mails to") << email
```
It will produce the following diagram:
![c4](/img/c4.png)

@ -0,0 +1,43 @@
---
id: digitalocean
title: DigitalOcean
---
Node classes list of digitalocean provider.
## digitalocean.compute
- **diagrams.digitalocean.compute.Containers**
- **diagrams.digitalocean.compute.Docker**
- **diagrams.digitalocean.compute.DropletConnect**
- **diagrams.digitalocean.compute.DropletSnapshot**
- **diagrams.digitalocean.compute.Droplet**
- **diagrams.digitalocean.compute.K8SCluster**
- **diagrams.digitalocean.compute.K8SNodePool**
- **diagrams.digitalocean.compute.K8SNode**
## digitalocean.database
- **diagrams.digitalocean.database.DbaasPrimaryStandbyMore**
- **diagrams.digitalocean.database.DbaasPrimary**
- **diagrams.digitalocean.database.DbaasReadOnly**
- **diagrams.digitalocean.database.DbaasStandby**
## digitalocean.network
- **diagrams.digitalocean.network.Certificate**
- **diagrams.digitalocean.network.DomainRegistration**
- **diagrams.digitalocean.network.Domain**
- **diagrams.digitalocean.network.Firewall**
- **diagrams.digitalocean.network.FloatingIp**
- **diagrams.digitalocean.network.InternetGateway**
- **diagrams.digitalocean.network.LoadBalancer**
- **diagrams.digitalocean.network.ManagedVpn**
- **diagrams.digitalocean.network.Vpc**
## digitalocean.storage
- **diagrams.digitalocean.storage.Folder**
- **diagrams.digitalocean.storage.Space**
- **diagrams.digitalocean.storage.VolumeSnapshot**
- **diagrams.digitalocean.storage.Volume**

@ -20,6 +20,7 @@ Node classes list of gcp provider.
## gcp.api ## gcp.api
- **diagrams.gcp.api.APIGateway**
- **diagrams.gcp.api.Endpoints** - **diagrams.gcp.api.Endpoints**
## gcp.compute ## gcp.compute

@ -37,6 +37,7 @@ Node classes list of generic provider.
- **diagrams.generic.os.Debian** - **diagrams.generic.os.Debian**
- **diagrams.generic.os.IOS** - **diagrams.generic.os.IOS**
- **diagrams.generic.os.LinuxGeneral** - **diagrams.generic.os.LinuxGeneral**
- **diagrams.generic.os.Raspbian**
- **diagrams.generic.os.Suse** - **diagrams.generic.os.Suse**
- **diagrams.generic.os.Ubuntu** - **diagrams.generic.os.Ubuntu**
- **diagrams.generic.os.Windows** - **diagrams.generic.os.Windows**

@ -15,6 +15,7 @@ Node classes list of onprem provider.
- **diagrams.onprem.analytics.Beam** - **diagrams.onprem.analytics.Beam**
- **diagrams.onprem.analytics.Databricks** - **diagrams.onprem.analytics.Databricks**
- **diagrams.onprem.analytics.Dbt** - **diagrams.onprem.analytics.Dbt**
- **diagrams.onprem.analytics.Dremio**
- **diagrams.onprem.analytics.Flink** - **diagrams.onprem.analytics.Flink**
- **diagrams.onprem.analytics.Hadoop** - **diagrams.onprem.analytics.Hadoop**
- **diagrams.onprem.analytics.Hive** - **diagrams.onprem.analytics.Hive**
@ -75,6 +76,7 @@ Node classes list of onprem provider.
- **diagrams.onprem.container.Docker** - **diagrams.onprem.container.Docker**
- **diagrams.onprem.container.Firecracker** - **diagrams.onprem.container.Firecracker**
- **diagrams.onprem.container.Gvisor** - **diagrams.onprem.container.Gvisor**
- **diagrams.onprem.container.K3S**
- **diagrams.onprem.container.Lxc**, **LXC** (alias) - **diagrams.onprem.container.Lxc**, **LXC** (alias)
- **diagrams.onprem.container.Rkt**, **RKT** (alias) - **diagrams.onprem.container.Rkt**, **RKT** (alias)
@ -123,6 +125,7 @@ Node classes list of onprem provider.
- **diagrams.onprem.iac.Ansible** - **diagrams.onprem.iac.Ansible**
- **diagrams.onprem.iac.Atlantis** - **diagrams.onprem.iac.Atlantis**
- **diagrams.onprem.iac.Awx** - **diagrams.onprem.iac.Awx**
- **diagrams.onprem.iac.Puppet**
- **diagrams.onprem.iac.Terraform** - **diagrams.onprem.iac.Terraform**
## onprem.identity ## onprem.identity
@ -152,8 +155,10 @@ Node classes list of onprem provider.
- **diagrams.onprem.monitoring.Cortex** - **diagrams.onprem.monitoring.Cortex**
- **diagrams.onprem.monitoring.Datadog** - **diagrams.onprem.monitoring.Datadog**
- **diagrams.onprem.monitoring.Dynatrace**
- **diagrams.onprem.monitoring.Grafana** - **diagrams.onprem.monitoring.Grafana**
- **diagrams.onprem.monitoring.Humio** - **diagrams.onprem.monitoring.Humio**
- **diagrams.onprem.monitoring.Nagios**
- **diagrams.onprem.monitoring.Newrelic** - **diagrams.onprem.monitoring.Newrelic**
- **diagrams.onprem.monitoring.PrometheusOperator** - **diagrams.onprem.monitoring.PrometheusOperator**
- **diagrams.onprem.monitoring.Prometheus** - **diagrams.onprem.monitoring.Prometheus**
@ -189,6 +194,7 @@ Node classes list of onprem provider.
- **diagrams.onprem.network.Powerdns** - **diagrams.onprem.network.Powerdns**
- **diagrams.onprem.network.Tomcat** - **diagrams.onprem.network.Tomcat**
- **diagrams.onprem.network.Traefik** - **diagrams.onprem.network.Traefik**
- **diagrams.onprem.network.Tyk**
- **diagrams.onprem.network.Vyos**, **VyOS** (alias) - **diagrams.onprem.network.Vyos**, **VyOS** (alias)
- **diagrams.onprem.network.Wildfly** - **diagrams.onprem.network.Wildfly**
- **diagrams.onprem.network.Zookeeper** - **diagrams.onprem.network.Zookeeper**
@ -232,6 +238,7 @@ Node classes list of onprem provider.
- **diagrams.onprem.vcs.Gitea** - **diagrams.onprem.vcs.Gitea**
- **diagrams.onprem.vcs.Github** - **diagrams.onprem.vcs.Github**
- **diagrams.onprem.vcs.Gitlab** - **diagrams.onprem.vcs.Gitlab**
- **diagrams.onprem.vcs.Svn**
## onprem.workflow ## onprem.workflow

@ -5,9 +5,6 @@ title: OpenStack
Node classes list of openstack provider. Node classes list of openstack provider.
## openstack.adjacentenablers
## openstack.apiproxies ## openstack.apiproxies
- **diagrams.openstack.apiproxies.EC2API** - **diagrams.openstack.apiproxies.EC2API**
@ -51,9 +48,6 @@ Node classes list of openstack provider.
- **diagrams.openstack.frontend.Horizon** - **diagrams.openstack.frontend.Horizon**
## openstack.lifecyclemanagement
## openstack.monitoring ## openstack.monitoring
- **diagrams.openstack.monitoring.Monasca** - **diagrams.openstack.monitoring.Monasca**
@ -73,9 +67,6 @@ Node classes list of openstack provider.
- **diagrams.openstack.nfv.Tacker** - **diagrams.openstack.nfv.Tacker**
## openstack.operations
## openstack.optimization ## openstack.optimization
- **diagrams.openstack.optimization.Congress** - **diagrams.openstack.optimization.Congress**

@ -41,11 +41,13 @@ Node classes list of programming provider.
- **diagrams.programming.framework.Fastapi**, **FastAPI** (alias) - **diagrams.programming.framework.Fastapi**, **FastAPI** (alias)
- **diagrams.programming.framework.Flask** - **diagrams.programming.framework.Flask**
- **diagrams.programming.framework.Flutter** - **diagrams.programming.framework.Flutter**
- **diagrams.programming.framework.Graphql**, **GraphQL** (alias)
- **diagrams.programming.framework.Laravel** - **diagrams.programming.framework.Laravel**
- **diagrams.programming.framework.Micronaut** - **diagrams.programming.framework.Micronaut**
- **diagrams.programming.framework.Rails** - **diagrams.programming.framework.Rails**
- **diagrams.programming.framework.React** - **diagrams.programming.framework.React**
- **diagrams.programming.framework.Spring** - **diagrams.programming.framework.Spring**
- **diagrams.programming.framework.Starlette**
- **diagrams.programming.framework.Vue** - **diagrams.programming.framework.Vue**
## programming.language ## programming.language
@ -61,6 +63,7 @@ Node classes list of programming provider.
- **diagrams.programming.language.Java** - **diagrams.programming.language.Java**
- **diagrams.programming.language.Javascript**, **JavaScript** (alias) - **diagrams.programming.language.Javascript**, **JavaScript** (alias)
- **diagrams.programming.language.Kotlin** - **diagrams.programming.language.Kotlin**
- **diagrams.programming.language.Latex**
- **diagrams.programming.language.Matlab** - **diagrams.programming.language.Matlab**
- **diagrams.programming.language.Nodejs**, **NodeJS** (alias) - **diagrams.programming.language.Nodejs**, **NodeJS** (alias)
- **diagrams.programming.language.Php**, **PHP** (alias) - **diagrams.programming.language.Php**, **PHP** (alias)
@ -71,3 +74,7 @@ Node classes list of programming provider.
- **diagrams.programming.language.Scala** - **diagrams.programming.language.Scala**
- **diagrams.programming.language.Swift** - **diagrams.programming.language.Swift**
- **diagrams.programming.language.Typescript**, **TypeScript** (alias) - **diagrams.programming.language.Typescript**, **TypeScript** (alias)
## programming.runtime
- **diagrams.programming.runtime.Dapr**

@ -10,6 +10,7 @@ Node classes list of saas provider.
- **diagrams.saas.alerting.Newrelic** - **diagrams.saas.alerting.Newrelic**
- **diagrams.saas.alerting.Opsgenie** - **diagrams.saas.alerting.Opsgenie**
- **diagrams.saas.alerting.Pushover** - **diagrams.saas.alerting.Pushover**
- **diagrams.saas.alerting.Xmatters**
## saas.analytics ## saas.analytics
@ -20,6 +21,7 @@ Node classes list of saas provider.
- **diagrams.saas.cdn.Akamai** - **diagrams.saas.cdn.Akamai**
- **diagrams.saas.cdn.Cloudflare** - **diagrams.saas.cdn.Cloudflare**
- **diagrams.saas.cdn.Fastly**
## saas.chat ## saas.chat
@ -29,11 +31,17 @@ Node classes list of saas provider.
- **diagrams.saas.chat.Slack** - **diagrams.saas.chat.Slack**
- **diagrams.saas.chat.Teams** - **diagrams.saas.chat.Teams**
- **diagrams.saas.chat.Telegram** - **diagrams.saas.chat.Telegram**
- **diagrams.saas.chat.Messenger**
- **diagrams.saas.chat.Line**
## saas.filesharing ## saas.filesharing
- **diagrams.saas.filesharing.Nextcloud** - **diagrams.saas.filesharing.Nextcloud**
## saas.communication
- **diagrams.saas.communication.Twilio**
## saas.identity ## saas.identity
- **diagrams.saas.identity.Auth0** - **diagrams.saas.identity.Auth0**

175
poetry.lock generated

@ -90,16 +90,16 @@ immutables = ">=0.9"
[[package]] [[package]]
name = "graphviz" name = "graphviz"
version = "0.16" version = "0.19.1"
description = "Simple Python interface for Graphviz" description = "Simple Python interface for Graphviz"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" python-versions = ">=3.6"
[package.extras] [package.extras]
dev = ["tox (>=3)", "flake8", "pep8-naming", "wheel", "twine"] dev = ["tox (>=3)", "flake8", "pep8-naming", "wheel", "twine"]
docs = ["sphinx (>=1.8)", "sphinx-rtd-theme"] docs = ["sphinx (>=1.8)", "sphinx-autodoc-typehints", "sphinx-rtd-theme"]
test = ["mock (>=3)", "pytest (>=4)", "pytest-mock (>=2)", "pytest-cov"] test = ["pytest (>=6)", "pytest-mock (>=3)", "mock (>=4)", "pytest-cov", "coverage"]
[[package]] [[package]]
name = "immutables" name = "immutables"
@ -148,17 +148,17 @@ xdg_home = ["appdirs (>=1.4.0)"]
[[package]] [[package]]
name = "jinja2" name = "jinja2"
version = "2.11.3" version = "3.0.1"
description = "A very fast and expressive template engine." description = "A very fast and expressive template engine."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" python-versions = ">=3.6"
[package.dependencies] [package.dependencies]
MarkupSafe = ">=0.23" MarkupSafe = ">=2.0"
[package.extras] [package.extras]
i18n = ["Babel (>=0.8)"] i18n = ["Babel (>=2.7)"]
[[package]] [[package]]
name = "lazy-object-proxy" name = "lazy-object-proxy"
@ -170,11 +170,11 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]] [[package]]
name = "markupsafe" name = "markupsafe"
version = "1.1.1" version = "2.0.1"
description = "Safely add untrusted strings to HTML/XML markup." description = "Safely add untrusted strings to HTML/XML markup."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" python-versions = ">=3.6"
[[package]] [[package]]
name = "mccabe" name = "mccabe"
@ -253,7 +253,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]] [[package]]
name = "pytest" name = "pytest"
version = "6.2.1" version = "7.0.1"
description = "pytest: simple powerful testing with Python" description = "pytest: simple powerful testing with Python"
category = "dev" category = "dev"
optional = false optional = false
@ -266,12 +266,12 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""}
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
iniconfig = "*" iniconfig = "*"
packaging = "*" packaging = "*"
pluggy = ">=0.12,<1.0.0a1" pluggy = ">=0.12,<2.0"
py = ">=1.8.2" py = ">=1.8.2"
toml = "*" tomli = ">=1.0.0"
[package.extras] [package.extras]
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
[[package]] [[package]]
name = "regex" name = "regex"
@ -297,6 +297,14 @@ category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
[[package]]
name = "tomli"
version = "1.2.3"
description = "A lil' TOML parser"
category = "dev"
optional = false
python-versions = ">=3.6"
[[package]] [[package]]
name = "typed-ast" name = "typed-ast"
version = "1.4.1" version = "1.4.1"
@ -328,7 +336,7 @@ testing = ["jaraco.itertools", "func-timeout"]
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.6" python-versions = "^3.6"
content-hash = "441f4ec509fbee3d303586c3abba92d71c5148600632f11c7069c709fa67774c" content-hash = "4373b4330d1af9a3f202ece28872ac4c2c95dfce54f8579efb61d00f52432ecb"
[metadata.files] [metadata.files]
appdirs = [ appdirs = [
@ -363,8 +371,8 @@ contextvars = [
{file = "contextvars-2.4.tar.gz", hash = "sha256:f38c908aaa59c14335eeea12abea5f443646216c4e29380d7bf34d2018e2c39e"}, {file = "contextvars-2.4.tar.gz", hash = "sha256:f38c908aaa59c14335eeea12abea5f443646216c4e29380d7bf34d2018e2c39e"},
] ]
graphviz = [ graphviz = [
{file = "graphviz-0.16-py2.py3-none-any.whl", hash = "sha256:3cad5517c961090dfc679df6402a57de62d97703e2880a1a46147bb0dc1639eb"}, {file = "graphviz-0.19.1-py3-none-any.whl", hash = "sha256:f34088c08be2ec16279dfa9c3b4ff3d1453c5c67597a33e2819b000e18d4c546"},
{file = "graphviz-0.16.zip", hash = "sha256:d2d25af1c199cad567ce4806f0449cb74eb30cf451fd7597251e1da099ac6e57"}, {file = "graphviz-0.19.1.zip", hash = "sha256:09ed0cde452d015fe77c4845a210eb642f28d245f5bc250d4b97808cb8f49078"},
] ]
immutables = [ immutables = [
{file = "immutables-0.11-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:bce27277a2fe91509cca69181971ab509c2ee862e8b37b09f26b64f90e8fe8fb"}, {file = "immutables-0.11-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:bce27277a2fe91509cca69181971ab509c2ee862e8b37b09f26b64f90e8fe8fb"},
@ -397,8 +405,8 @@ isort = [
{file = "isort-4.3.21.tar.gz", hash = "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1"}, {file = "isort-4.3.21.tar.gz", hash = "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1"},
] ]
jinja2 = [ jinja2 = [
{file = "Jinja2-2.11.3-py2.py3-none-any.whl", hash = "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419"}, {file = "Jinja2-3.0.1-py3-none-any.whl", hash = "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4"},
{file = "Jinja2-2.11.3.tar.gz", hash = "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6"}, {file = "Jinja2-3.0.1.tar.gz", hash = "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"},
] ]
lazy-object-proxy = [ lazy-object-proxy = [
{file = "lazy-object-proxy-1.4.3.tar.gz", hash = "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"}, {file = "lazy-object-proxy-1.4.3.tar.gz", hash = "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"},
@ -424,58 +432,75 @@ lazy-object-proxy = [
{file = "lazy_object_proxy-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239"}, {file = "lazy_object_proxy-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239"},
] ]
markupsafe = [ markupsafe = [
{file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"}, {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"},
{file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"}, {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"},
{file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183"}, {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"},
{file = "MarkupSafe-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b"}, {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"},
{file = "MarkupSafe-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e"}, {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"},
{file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f"}, {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"},
{file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1"}, {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"},
{file = "MarkupSafe-1.1.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5"}, {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"},
{file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1"}, {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"},
{file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735"}, {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"},
{file = "MarkupSafe-1.1.1-cp34-cp34m-win32.whl", hash = "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"},
{file = "MarkupSafe-1.1.1-cp34-cp34m-win_amd64.whl", hash = "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"},
{file = "MarkupSafe-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"},
{file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"},
{file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"},
{file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"},
{file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"},
{file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"},
{file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"},
{file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"},
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"},
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"},
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"},
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"},
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"},
{file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"},
{file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"},
{file = "MarkupSafe-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"},
{file = "MarkupSafe-1.1.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"},
{file = "MarkupSafe-1.1.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"},
{file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"},
{file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"},
{file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621"}, {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"},
{file = "MarkupSafe-1.1.1-cp39-cp39-win32.whl", hash = "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39"}, {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"},
{file = "MarkupSafe-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8"}, {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"},
{file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"},
{file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"},
{file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"},
{file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"},
{file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"},
{file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"},
{file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"},
{file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"},
{file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
{file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
] ]
mccabe = [ mccabe = [
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
@ -506,8 +531,8 @@ pyparsing = [
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
] ]
pytest = [ pytest = [
{file = "pytest-6.2.1-py3-none-any.whl", hash = "sha256:1969f797a1a0dbd8ccf0fecc80262312729afea9c17f1d70ebf85c5e76c6f7c8"}, {file = "pytest-7.0.1-py3-none-any.whl", hash = "sha256:9ce3ff477af913ecf6321fe337b93a2c0dcf2a0a1439c43f5452112c1e4280db"},
{file = "pytest-6.2.1.tar.gz", hash = "sha256:66e419b1899bc27346cb2c993e12c5e5e8daba9073c1fbce33b9807abc95c306"}, {file = "pytest-7.0.1.tar.gz", hash = "sha256:e30905a0c131d3d94b89624a1cc5afec3e0ba2fbdb151867d8e0ebd49850f171"},
] ]
regex = [ regex = [
{file = "regex-2020.2.20-cp27-cp27m-win32.whl", hash = "sha256:99272d6b6a68c7ae4391908fc15f6b8c9a6c345a46b632d7fdb7ef6c883a2bbb"}, {file = "regex-2020.2.20-cp27-cp27m-win32.whl", hash = "sha256:99272d6b6a68c7ae4391908fc15f6b8c9a6c345a46b632d7fdb7ef6c883a2bbb"},
@ -542,6 +567,10 @@ toml = [
{file = "toml-0.10.0-py2.py3-none-any.whl", hash = "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"}, {file = "toml-0.10.0-py2.py3-none-any.whl", hash = "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"},
{file = "toml-0.10.0.tar.gz", hash = "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"}, {file = "toml-0.10.0.tar.gz", hash = "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"},
] ]
tomli = [
{file = "tomli-1.2.3-py3-none-any.whl", hash = "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"},
{file = "tomli-1.2.3.tar.gz", hash = "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f"},
]
typed-ast = [ typed-ast = [
{file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"}, {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"},
{file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"}, {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"},

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "diagrams" name = "diagrams"
version = "0.20.0" version = "0.22.0"
description = "Diagram as Code" description = "Diagram as Code"
license = "MIT" license = "MIT"
authors = ["mingrammer <mingrammer@gmail.com>"] authors = ["mingrammer <mingrammer@gmail.com>"]
@ -11,12 +11,12 @@ include = ["resources/**/*"]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.6" python = "^3.6"
graphviz = ">=0.13.2,<0.17.0" graphviz = ">=0.13.2,<0.20.0"
jinja2 = "^2.10" jinja2 = ">=2.10,<4.0"
contextvars = { version = "^2.4", python = "~3.6" } contextvars = { version = "^2.4", python = "~3.6" }
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
pytest = "^6.2" pytest = "^7.0"
pylint = "^2.7" pylint = "^2.7"
black = {version = "^19.0", allow-prereleases = true} black = {version = "^19.0", allow-prereleases = true}
rope = "^0.14.0" rope = "^0.14.0"

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save