Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Please add a demo/example of each Node shape in documentation set #466

Closed
scottstirling opened this issue Feb 18, 2021 · 4 comments · Fixed by #499
Closed

Please add a demo/example of each Node shape in documentation set #466

scottstirling opened this issue Feb 18, 2021 · 4 comments · Fixed by #499

Comments

@scottstirling
Copy link

scottstirling commented Feb 18, 2021

Hi - the documentation is a great start, with the nodes well categorized, but it would be useful to have a visible example of each one along with the name in the browsable docs!

Thank you - cool project and useful tool with lots of potential.

@clayms
Copy link

clayms commented Feb 20, 2021

I'm sure there are better ways, but the following will display all of the nodes for each "resource" and each "group" in that "resource."

This runs in a Jupyter notebook.

I would advise you limit the first list of resources (diag_res) to only what you want to see, otherwise this may overwhelm your notebook. You can see I did this below by only selecting 'aws' resources, the second item in diag_res, i.e. (diag_res[1:2]).

Alternatively, you could wrap this in a function and run a separate python process to save the output as images in a folder.

import inspect
from pathlib import Path
import diagrams
from diagrams import Diagram, Node, Edge, Cluster
from IPython.core.display import display

diag_libpath = dict(inspect.getmembers(diagrams))['__path__'][0]
diag_res = sorted(
    [str(x).split("/")[-1] for x in Path(diag_libpath).iterdir() 
        if x.is_dir() if '__pycache__' not in str(x)])

print(diag_res)
['alibabacloud', 'aws', 'azure', 'base', 'custom', 'elastic', 'firebase', 'gcp', 'generic', 'k8s', 'oci', 'onprem', 'openstack', 'outscale', 'programming', 'saas']
graph_attr = {
    "margin":"-1, -1"
}

node_attr = {
    "width":"0.4",
    "height":"0.4",
    "fontsize":"8",
}

for res in diag_res[1:2]:
    diag_res_grps = sorted(
        [str(x).split("/")[-1].split(".")[0] 
            for x in Path(f"{diag_libpath}/{res}").iterdir() 
            if "__" not in str(x)])

    for grp in diag_res_grps:
        exec(f"import diagrams.{res}.{grp}")
        grp_nodes = [
            x[0] for x in eval(f"inspect.getmembers(diagrams.{res}.{grp}, inspect.isclass)")
            if "_" not in x[0]]
        if grp_nodes:
            exec(f"from diagrams.{res}.{grp} import {','.join(grp_nodes)}")

        num_nodes = len(grp_nodes)
        nodes_per_row = 5
        num_of_rows = ((num_nodes - 1) // nodes_per_row) + 1

        with Diagram(f"\n\n{res}.{grp}", graph_attr=graph_attr, show=False) as diag:
            for row in range(num_of_rows)[::-1]:
                nodes_in_row = min(
                    [nodes_per_row] + 
                    [num_nodes % x for x in [nodes_per_row] if num_nodes < ((row+1) * nodes_per_row)])
                nodes_i = row * nodes_per_row
                node_list = [''
                    f'{grp_nodes[nodes_i+item_num]}("{str(grp_nodes[nodes_i+item_num])}", **node_attr)'
                    f'- Edge(penwidth="0.0")'
                    for item_num in range(nodes_in_row)[:-1]
                ] + [''
                    f'{grp_nodes[nodes_i+nodes_in_row-1]}("{str(grp_nodes[nodes_i+nodes_in_row-1])}", **node_attr)'
                ]

                nodes_row = "-".join(node_list)

                eval(nodes_row)
        
        
        display(diag)

Only two output graphs shown to save space.
image

image

@clayms
Copy link

clayms commented Feb 20, 2021

Ideally there should be a method to list all of the resource groups, e.g. ["alibabacloud", "aws", "azure", ... , "saas"].

Then each resource group would have a method that would list all of the groups within that resource, e.g. for aws ["analytics", "ar", ..., "storage"].

Then for each resource group, a method to display all of the Nodes in that group, e.g. for aws.storage ["Backup", "CDR", "CloudendureDisasterRecovery", ..., "Storage"].

@scottstirling
Copy link
Author

scottstirling commented Feb 24, 2021

I love it, @clayms, that and all your suggestions and tips and tricks. I've been finding and liking all your posts on this library and how to do things with it and understanding the underlying Graphviz features and properties. Thank you!

@ralphtq
Copy link

ralphtq commented Feb 18, 2022

@clayms - Thanks for your code. When I ran it the labels were one top of the icons. I modified the code to place the labels on their own nodes:

from pathlib import Path
import diagrams
from diagrams import Diagram, Node, Edge, Cluster
from IPython.core.display import display

diag_libpath = dict(inspect.getmembers(diagrams))['__path__'][0]
diag_res = sorted(
    [str(x).split("/")[-1] for x in Path(diag_libpath).iterdir() 
        if x.is_dir() if '__pycache__' not in str(x)])

# print(diag_res)

graph_attr = {
      "margin":"-1, -1"
    , "fontsize":"30"
    , "compund":"True"
}


node_attr = {
    "width":"0.4",
    "height":"0.4",
    "fontsize":"8",
    "labelloc": "b"
}

nodeLabel_attr = {
     "width":"0.0"
    ,"height":"0.8"
    ,"fontsize":"10"
    ,"color": "white"
    ,"labelloc": "t"
}

for res in diag_res[1:18]:
    diag_res_grps = sorted(
        [str(x).split("/")[-1].split(".")[0] 
            for x in Path(f"{diag_libpath}/{res}").iterdir() 
            if "__" not in str(x)])


    for grp in diag_res_grps:
        exec(f"import diagrams.{res}.{grp}")
        grp_nodes = [
            x[0] for x in eval(f"inspect.getmembers(diagrams.{res}.{grp}, inspect.isclass)")
            if "_" not in x[0]]
        if grp_nodes:
            exec(f"from diagrams.{res}.{grp} import {','.join(grp_nodes)}")

        num_nodes = len(grp_nodes)
        nodes_per_row = 5
        num_of_rows = ((num_nodes - 1) // nodes_per_row) + 1

        diagram_file = f"./diagram_icons/{res}/{grp}"

        with Diagram(f"\n\n{res}.{grp}", filename=diagram_file , graph_attr=graph_attr, show=False) as diag:
            # classDef1= ("classDef 'Title:' ") # + "**classDefLabelNode_attr")
            # eval(classDef1)

            for row in range(num_of_rows)[::-1]:
                nodes_in_row = min(
                    [nodes_per_row] + 
                    [num_nodes % x for x in [nodes_per_row] if num_nodes < ((row+1) * nodes_per_row)])
                
                nodes_i = row * nodes_per_row

                node_list = [''
                    f'Node("{str(grp_nodes[nodes_i+item_num])}", **nodeLabel_attr)'
                    f'- Edge(penwidth="0.0")'
                    f'- {grp_nodes[nodes_i+item_num]}("", **node_attr)'
                    f'- Edge(penwidth="0.0")'

                    for item_num in range(nodes_in_row)[:-1]
                ] + [''
                    f'Node("{str(grp_nodes[nodes_i+nodes_in_row-1])}", **nodeLabel_attr)'
                    f'- Edge(penwidth="0.0")'
                    f'- {grp_nodes[nodes_i+nodes_in_row-1]}("", **node_attr)'
                ]

                nodes_row = "-".join(node_list)

                eval(nodes_row)
        
        
    display(diag)

Here is an example of a generated set of icons:

aws management

Still needs some improvement. Maybe there is a better way to manage the labels?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants