Graphinate 0.2.21__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. {graphinate-0.2.21 → graphinate-0.3.0}/.github/workflows/test.yml +1 -1
  2. {graphinate-0.2.21 → graphinate-0.3.0}/PKG-INFO +12 -13
  3. {graphinate-0.2.21 → graphinate-0.3.0}/README.md +1 -1
  4. {graphinate-0.2.21 → graphinate-0.3.0}/docs/start.md +1 -1
  5. {graphinate-0.2.21 → graphinate-0.3.0}/examples/code/python_ast.py +14 -0
  6. {graphinate-0.2.21 → graphinate-0.3.0}/examples/code/python_dependencies.py +7 -0
  7. graphinate-0.3.0/examples/github/_client.py +132 -0
  8. {graphinate-0.2.21 → graphinate-0.3.0}/examples/github/followers.py +16 -0
  9. {graphinate-0.2.21 → graphinate-0.3.0}/examples/github/repositories.py +7 -0
  10. {graphinate-0.2.21 → graphinate-0.3.0}/examples/math/graph_atlas.py +30 -0
  11. {graphinate-0.2.21 → graphinate-0.3.0}/examples/math/polygonal_graph.py +12 -2
  12. {graphinate-0.2.21 → graphinate-0.3.0}/examples/system/processes.py +7 -0
  13. {graphinate-0.2.21 → graphinate-0.3.0}/examples/web/page_links.py +10 -0
  14. {graphinate-0.2.21 → graphinate-0.3.0}/pyproject.toml +11 -12
  15. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/color.py +4 -3
  16. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/materializers/matplotlib.py +9 -7
  17. graphinate-0.3.0/src/graphinate/server/__init__.py +80 -0
  18. graphinate-0.3.0/src/graphinate/tools/mutators.py +153 -0
  19. graphinate-0.2.21/examples/github/_client.py +0 -61
  20. graphinate-0.2.21/src/graphinate/server/__init__.py +0 -110
  21. graphinate-0.2.21/src/graphinate/tools/mutators.py +0 -66
  22. {graphinate-0.2.21 → graphinate-0.3.0}/.coveragerc +0 -0
  23. {graphinate-0.2.21 → graphinate-0.3.0}/.github/dependabot.yml +0 -0
  24. {graphinate-0.2.21 → graphinate-0.3.0}/.github/workflows/codeql.yml +0 -0
  25. {graphinate-0.2.21 → graphinate-0.3.0}/.github/workflows/publish-docs.yaml +0 -0
  26. {graphinate-0.2.21 → graphinate-0.3.0}/.github/workflows/publish.yml +0 -0
  27. {graphinate-0.2.21 → graphinate-0.3.0}/.github/workflows/test-beta.yml +0 -0
  28. {graphinate-0.2.21 → graphinate-0.3.0}/.gitignore +0 -0
  29. {graphinate-0.2.21 → graphinate-0.3.0}/LICENSE +0 -0
  30. {graphinate-0.2.21 → graphinate-0.3.0}/STATS.md +0 -0
  31. {graphinate-0.2.21 → graphinate-0.3.0}/docs/acknowledge.md +0 -0
  32. {graphinate-0.2.21 → graphinate-0.3.0}/docs/assets/images/logo-128.png +0 -0
  33. {graphinate-0.2.21 → graphinate-0.3.0}/docs/assets/images/network_graph.png +0 -0
  34. {graphinate-0.2.21 → graphinate-0.3.0}/docs/assets/stylesheets/extra.css +0 -0
  35. {graphinate-0.2.21 → graphinate-0.3.0}/docs/dev.md +0 -0
  36. {graphinate-0.2.21 → graphinate-0.3.0}/docs/examples/code.md +0 -0
  37. {graphinate-0.2.21 → graphinate-0.3.0}/docs/examples/github.md +0 -0
  38. {graphinate-0.2.21 → graphinate-0.3.0}/docs/examples/math.md +0 -0
  39. {graphinate-0.2.21 → graphinate-0.3.0}/docs/examples/system.md +0 -0
  40. {graphinate-0.2.21 → graphinate-0.3.0}/docs/examples/web.md +0 -0
  41. {graphinate-0.2.21 → graphinate-0.3.0}/docs/gen_ref_pages.py +0 -0
  42. {graphinate-0.2.21 → graphinate-0.3.0}/docs/index.md +0 -0
  43. {graphinate-0.2.21 → graphinate-0.3.0}/docs/intro.md +0 -0
  44. {graphinate-0.2.21 → graphinate-0.3.0}/docs/usage/cli.md +0 -0
  45. {graphinate-0.2.21 → graphinate-0.3.0}/docs/usage/lib.md +0 -0
  46. {graphinate-0.2.21 → graphinate-0.3.0}/examples/code/requirements.txt +0 -0
  47. {graphinate-0.2.21 → graphinate-0.3.0}/examples/github/commits_visibilty_graph.py +0 -0
  48. {graphinate-0.2.21 → graphinate-0.3.0}/examples/github/followers.graphql +0 -0
  49. {graphinate-0.2.21 → graphinate-0.3.0}/examples/github/graphql.config.yml +0 -0
  50. {graphinate-0.2.21 → graphinate-0.3.0}/examples/github/repositories.graphql +0 -0
  51. {graphinate-0.2.21 → graphinate-0.3.0}/examples/github/requirements.txt +0 -0
  52. {graphinate-0.2.21 → graphinate-0.3.0}/examples/math/requirements.txt +0 -0
  53. {graphinate-0.2.21 → graphinate-0.3.0}/examples/system/requirements.txt +0 -0
  54. {graphinate-0.2.21 → graphinate-0.3.0}/examples/web/requirements.txt +0 -0
  55. {graphinate-0.2.21 → graphinate-0.3.0}/mkdocs.yml +0 -0
  56. {graphinate-0.2.21 → graphinate-0.3.0}/playground/ethernet/traceroute.py +0 -0
  57. {graphinate-0.2.21 → graphinate-0.3.0}/playground/genric_graph.graphql +0 -0
  58. {graphinate-0.2.21 → graphinate-0.3.0}/playground/graphql.config.yml +0 -0
  59. {graphinate-0.2.21 → graphinate-0.3.0}/playground/house_of_graphs.py +0 -0
  60. {graphinate-0.2.21 → graphinate-0.3.0}/playground/social/albums.json +0 -0
  61. {graphinate-0.2.21 → graphinate-0.3.0}/playground/social/musicisians.py +0 -0
  62. {graphinate-0.2.21 → graphinate-0.3.0}/playground/text/nlp_graph.py +0 -0
  63. {graphinate-0.2.21 → graphinate-0.3.0}/playground/text/requirements.txt +0 -0
  64. {graphinate-0.2.21 → graphinate-0.3.0}/playground/time_series/requirements.txt +0 -0
  65. {graphinate-0.2.21 → graphinate-0.3.0}/playground/time_series/visibility_graph.py +0 -0
  66. {graphinate-0.2.21 → graphinate-0.3.0}/sonar-project.properties +0 -0
  67. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/__init__.py +0 -0
  68. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/__main__.py +0 -0
  69. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/builders.py +0 -0
  70. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/cli.py +0 -0
  71. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/materializers/__init__.py +0 -0
  72. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/modeling.py +0 -0
  73. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/starlette/__init__.py +0 -0
  74. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/starlette/views.py +0 -0
  75. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/web/__init__.py +0 -0
  76. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/web/elements/__init__.py +0 -0
  77. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/web/elements/index.html +0 -0
  78. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/web/graphiql/__init__.py +0 -0
  79. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/web/graphiql/index.html +0 -0
  80. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/web/rapidoc/__init__.py +0 -0
  81. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/web/rapidoc/index.html +0 -0
  82. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/web/static/images/logo-128.png +0 -0
  83. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/web/static/images/network_graph.png +0 -0
  84. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/web/viewer/__init__.py +0 -0
  85. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/web/viewer/index.html +0 -0
  86. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/web/voyager/__init__.py +0 -0
  87. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/server/web/voyager/index.html +0 -0
  88. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/tools/__init__.py +0 -0
  89. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/tools/converters.py +0 -0
  90. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/tools/gui.py +0 -0
  91. {graphinate-0.2.21 → graphinate-0.3.0}/src/graphinate/typing.py +0 -0
  92. {graphinate-0.2.21 → graphinate-0.3.0}/tests/conftest.py +0 -0
  93. {graphinate-0.2.21 → graphinate-0.3.0}/tests/graphinate/test_builders.py +0 -0
  94. {graphinate-0.2.21 → graphinate-0.3.0}/tests/graphinate/test_cli.py +0 -0
  95. {graphinate-0.2.21 → graphinate-0.3.0}/tests/graphinate/test_color.py +0 -0
  96. {graphinate-0.2.21 → graphinate-0.3.0}/tests/graphinate/test_materializers.py +0 -0
  97. {graphinate-0.2.21 → graphinate-0.3.0}/tests/graphinate/test_modeling.py +0 -0
  98. {graphinate-0.2.21 → graphinate-0.3.0}/tests/graphinate/test_server.py +0 -0
  99. {graphinate-0.2.21 → graphinate-0.3.0}/tests/graphinate/test_tools.py +0 -0
@@ -15,7 +15,7 @@ jobs:
15
15
  strategy:
16
16
  fail-fast: false
17
17
  matrix:
18
- python-version: [ "3.9", "3.10", "3.11", "3.12" ]
18
+ python-version: [ "3.10", "3.11", "3.12" ]
19
19
  steps:
20
20
  - uses: actions/checkout@v4
21
21
  - name: Set up Python ${{ matrix.python-version }}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: Graphinate
3
- Version: 0.2.21
3
+ Version: 0.3.0
4
4
  Summary: Graphinate. Data to Graphs.
5
5
  Project-URL: Homepage, https://erivlis.github.io/graphinate
6
6
  Project-URL: Documentation, https://erivlis.github.io/graphinate
@@ -9,7 +9,7 @@ Project-URL: Source, https://github.com/erivlis/graphinate
9
9
  Author-email: Eran Rivlis <eran@rivlis.info>
10
10
  License-File: LICENSE
11
11
  Keywords: declarative,graph
12
- Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Development Status :: 4 - Beta
13
13
  Classifier: Intended Audience :: Developers
14
14
  Classifier: Intended Audience :: Information Technology
15
15
  Classifier: Intended Audience :: Science/Research
@@ -18,7 +18,6 @@ Classifier: Natural Language :: English
18
18
  Classifier: Operating System :: OS Independent
19
19
  Classifier: Programming Language :: Python :: 3
20
20
  Classifier: Programming Language :: Python :: 3 :: Only
21
- Classifier: Programming Language :: Python :: 3.9
22
21
  Classifier: Programming Language :: Python :: 3.10
23
22
  Classifier: Programming Language :: Python :: 3.11
24
23
  Classifier: Programming Language :: Python :: 3.12
@@ -26,13 +25,13 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
26
25
  Classifier: Topic :: Scientific/Engineering
27
26
  Classifier: Topic :: Software Development :: Libraries
28
27
  Classifier: Typing :: Typed
29
- Requires-Python: >=3.9
28
+ Requires-Python: >=3.10
30
29
  Requires-Dist: click>=8.1.7
31
- Requires-Dist: inflect>=7.2.1
30
+ Requires-Dist: inflect>=7.3.0
32
31
  Requires-Dist: loguru>=0.7.2
33
- Requires-Dist: matplotlib>=3.8.4
32
+ Requires-Dist: matplotlib>=3.9.0
34
33
  Requires-Dist: networkx>=3.3
35
- Requires-Dist: strawberry-graphql[asgi,opentelemetry]>=0.227.3
34
+ Requires-Dist: strawberry-graphql[asgi,opentelemetry]>=0.235.1
36
35
  Provides-Extra: dev
37
36
  Requires-Dist: pipdeptree; extra == 'dev'
38
37
  Requires-Dist: ruff; extra == 'dev'
@@ -45,17 +44,17 @@ Requires-Dist: mkdocs-material; extra == 'docs'
45
44
  Requires-Dist: mkdocs-section-index; extra == 'docs'
46
45
  Requires-Dist: mkdocstrings-python; extra == 'docs'
47
46
  Provides-Extra: plot
48
- Requires-Dist: scipy>=1.12.0; extra == 'plot'
47
+ Requires-Dist: scipy>=1.14.0; extra == 'plot'
49
48
  Provides-Extra: server
50
49
  Requires-Dist: starlette-prometheus; extra == 'server'
51
- Requires-Dist: uvicorn[standard]>=0.29.0; extra == 'server'
50
+ Requires-Dist: uvicorn[standard]>=0.30.1; extra == 'server'
52
51
  Provides-Extra: test
53
52
  Requires-Dist: faker>=23.2.1; extra == 'test'
54
- Requires-Dist: pytest-asyncio>=0.23.5; extra == 'test'
53
+ Requires-Dist: pytest-asyncio>=0.23.7; extra == 'test'
55
54
  Requires-Dist: pytest-cov>=5.0.0; extra == 'test'
56
55
  Requires-Dist: pytest-randomly>=3.15.0; extra == 'test'
57
- Requires-Dist: pytest-xdist>=3.5.0; extra == 'test'
58
- Requires-Dist: pytest>=8.1.1; extra == 'test'
56
+ Requires-Dist: pytest-xdist>=3.6.1; extra == 'test'
57
+ Requires-Dist: pytest>=8.2.2; extra == 'test'
59
58
  Description-Content-Type: text/markdown
60
59
 
61
60
  # [Graphinate. Data to Graphs.](https://erivlis.github.io/graphinate/)
@@ -153,7 +152,7 @@ To install with server support
153
152
  pip install graphinate[server]
154
153
  ```
155
154
 
156
- **Graphinate** officially supports Python >= 3.9.
155
+ **Graphinate** officially supports Python >= 3.10.
157
156
 
158
157
  ### Example
159
158
 
@@ -93,7 +93,7 @@ To install with server support
93
93
  pip install graphinate[server]
94
94
  ```
95
95
 
96
- **Graphinate** officially supports Python >= 3.9.
96
+ **Graphinate** officially supports Python >= 3.10.
97
97
 
98
98
  ### Example
99
99
 
@@ -17,7 +17,7 @@ To install with server support
17
17
  pip install graphinate[server]
18
18
  ```
19
19
 
20
- **Graphinate** officially supports Python 3.9+.
20
+ **Graphinate** officially supports Python >= 3.10.
21
21
 
22
22
  ## Demo
23
23
 
@@ -1,3 +1,10 @@
1
+ """
2
+ Define functions to create an abstract syntax tree (AST) graph model using the 'graphinate' library.
3
+ The 'ast_graph_model' function parses the AST of a specified class and creates nodes and edges for the graph model.
4
+ The nodes represent AST nodes with their type and label, while the edges represent relationships between AST nodes.
5
+ """
6
+
7
+
1
8
  import ast
2
9
  import hashlib
3
10
  import inspect
@@ -35,6 +42,13 @@ def _ast_edge(parsed_ast: AST):
35
42
 
36
43
 
37
44
  def ast_graph_model():
45
+ """
46
+ Create an abstract syntax tree (AST) graph model.
47
+
48
+ Returns:
49
+ GraphModel: A graph model representing the AST nodes and their relationships.
50
+ """
51
+
38
52
  graph_model = graphinate.model(name='AST Graph')
39
53
 
40
54
  root_ast_node = ast.parse(inspect.getsource(graphinate.builders.D3Builder))
@@ -6,6 +6,13 @@ from pipdeptree._non_host import handle_non_host_target
6
6
 
7
7
 
8
8
  def dependency_graph_model():
9
+ """
10
+ Generate a dependency graph model.
11
+
12
+ Returns:
13
+ GraphModel: A graph model representing the dependency graph.
14
+ """
15
+
9
16
  options = get_options(args=None)
10
17
  handle_non_host_target(options)
11
18
 
@@ -0,0 +1,132 @@
1
+ import functools
2
+ import os
3
+ from collections.abc import Iterable
4
+ from typing import Optional, Union
5
+
6
+ # see requirements.txt
7
+ from github import Auth, Github
8
+ from github.AuthenticatedUser import AuthenticatedUser
9
+ from github.Commit import Commit
10
+ from github.File import File
11
+ from github.NamedUser import NamedUser
12
+ from github.Repository import Repository
13
+
14
+ # define a 'GITHUB_TOKEN' Env Var.
15
+ token = os.getenv('GITHUB_TOKEN')
16
+
17
+ # using an access token
18
+ auth = Auth.Token(token)
19
+
20
+ # Public Web GitHub
21
+ client = Github(auth=auth)
22
+
23
+
24
+ # or GitHub Enterprise with custom hostname
25
+ # g = Github(auth=auth, base_url='https://{hostname}/api/v3')
26
+
27
+
28
+ @functools.lru_cache
29
+ def github_user(user_id: Optional[str] = None) -> Union[NamedUser, AuthenticatedUser]:
30
+ """
31
+ Get the GitHub user object for the specified user ID or the authenticated user.
32
+
33
+ Parameters:
34
+ user_id (Optional[str]): The ID of the user to retrieve.
35
+ If not provided, retrieve the authenticated user.
36
+
37
+ Returns:
38
+ Union[NamedUser, AuthenticatedUser]: The GitHub user object corresponding to the user ID provided,
39
+ or the authenticated user if no user ID is specified.
40
+ Note:
41
+ This function requires authentication with a valid GitHub token.
42
+ """
43
+ user = client.get_user(user_id) if user_id else client.get_user()
44
+ return user
45
+
46
+
47
+ @functools.lru_cache
48
+ def github_repositories(
49
+ user_id: Optional[str] = None,
50
+ repo_id: Optional[str] = None) -> Iterable[Repository]:
51
+ """
52
+ Get the GitHub repositories for the specified user ID or the authenticated user.
53
+
54
+ Parameters:
55
+ user_id (Optional[str]): The ID of the user whose repositories to retrieve.
56
+ If not provided, retrieve repositories of the authenticated user.
57
+ repo_id (Optional[str]): The ID of the repository to retrieve.
58
+ If provided, only that repository will be returned.
59
+
60
+ Returns:
61
+ Iterable[Repository]:
62
+ A list of GitHub repository objects corresponding to the user ID and/or repository ID provided.
63
+
64
+ Note:
65
+ This function requires authentication with a valid GitHub token.
66
+ """
67
+
68
+ user = github_user(user_id)
69
+ if repo_id and (repo := user.get_repo(name=repo_id)):
70
+ return [repo]
71
+ else:
72
+ return user.get_repos()
73
+
74
+
75
+ def github_commits(
76
+ repo: Repository,
77
+ commit_id: Optional[str] = None) -> Iterable[Commit]:
78
+ """
79
+ Retrieve commits from a GitHub repository.
80
+
81
+ Parameters:
82
+ repo (Repository): The GitHub repository object from which to retrieve commits.
83
+ commit_id (str, optional): The ID of the commit to retrieve.
84
+ If provided, only that commit will be returned.
85
+ Defaults to None.
86
+
87
+ Returns:
88
+ Iterable[Commit]: An Iterable of Commit objects representing the commits in the repository.
89
+
90
+ Example:
91
+ To retrieve all commits from a repository:
92
+ ```
93
+ for commit in github_commits(repo):
94
+ print(commit)
95
+ ```
96
+
97
+ To retrieve a specific commit by ID:
98
+ ```
99
+ for commit in github_commits(repo, commit_id='abcdef123456'):
100
+ print(commit)
101
+ ```
102
+
103
+ Note:
104
+ This function requires authentication with a valid GitHub token.
105
+ """
106
+ if commit_id and (commit := repo.get_commit(sha=commit_id)):
107
+ yield commit
108
+ else:
109
+ yield from repo.get_commits()
110
+
111
+
112
+ def github_files(
113
+ commit: Commit,
114
+ file_id: Optional[str] = None) -> Iterable[File]:
115
+ """
116
+ Retrieves Files from a GitHub Commit
117
+
118
+ Parameters:
119
+ commit (Commit): A Commit object from the GitHub API.
120
+ file_id (Optional[str]): An optional parameter specifying the filename to filter the files. Default is None.
121
+
122
+ Returns:
123
+ Iterable[File]: An Iterable of File objects based on the filtering criteria.
124
+
125
+ Note:
126
+ This function requires authentication with a valid GitHub token.
127
+ """
128
+ files: list[File] = commit.files
129
+ if file_id:
130
+ yield from [file for file in files if file.filename == file_id]
131
+ else:
132
+ yield from files
@@ -1,3 +1,9 @@
1
+ """
2
+ Defines a function `followers_graph_model` that creates a graph model representing GitHub followers.
3
+ It recursively fetches followers of a given user up to a specified maximum depth.
4
+ The function yields edges between users in the graph.
5
+ """
6
+
1
7
  from typing import Optional
2
8
 
3
9
  import graphinate
@@ -7,6 +13,16 @@ DEPTH = 0
7
13
 
8
14
 
9
15
  def followers_graph_model(max_depth: int = DEPTH):
16
+ """
17
+ Create a graph model representing GitHub followers.
18
+
19
+ Args:
20
+ max_depth (int): The maximum depth to fetch followers recursively (default is 0).
21
+
22
+ Returns:
23
+ GraphModel: A graph model representing GitHub followers.
24
+ """
25
+
10
26
  graph_model = graphinate.model(name='Github Followers Graph')
11
27
 
12
28
  def _followers(user_id: Optional[str] = None, depth: int = 0, **kwargs):
@@ -8,6 +8,13 @@ from _client import github_commits, github_files, github_repositories, github_us
8
8
 
9
9
 
10
10
  def repo_graph_model(): # noqa: C901
11
+ """
12
+ Create a graph model for GitHub repositories.
13
+
14
+ Returns:
15
+ GraphModel: A graph model representing GitHub repositories with nodes and edges.
16
+ """
17
+
11
18
  graph_model = graphinate.model(name='GitHub Repository Graph')
12
19
 
13
20
  @graph_model.edge
@@ -35,6 +35,21 @@ def spiral_torus_edges(n, k):
35
35
 
36
36
 
37
37
  def atlas():
38
+ """
39
+ Generate a dictionary of various graph structures and models based on the provided atlas.
40
+ The function creates different types of graphs and models using NetworkX library.
41
+ The generated graphs include Tetrahedron, Cube, Octahedron, Dodecahedron, Icosahedron, Tesseract, Truncated Cube,
42
+ Truncated Tetrahedron, Ladder, Ring, Möbius, Cylinder, Spiral, Spiral Torus, and Circulant[10,[2]].
43
+ Additionally, the function includes adjacency mappings for specific named graphs like
44
+ Buckyball - Truncated Icosahedral Graph, D30 - Rhombic Triacontahedral Graph, Small Rhombicosidodecahedral Graph,
45
+ Small Rhombicuboctahedral Graph, Great Rhombicosidodecahedral Graph, Disdyakis Dodecahedral Graph,
46
+ Deltoidal Icositetrahedral Graph, Icosidodecahedral Graph, Deltoidal Hexecontahedral Graph, Kocohl74,
47
+ Utility Graph, Errara Graph, and Dragon Curve Blob 6.
48
+ The adjacency mappings define the connections between nodes in each named graph.
49
+ The function returns a dictionary
50
+ containing the named graphs as keys and their corresponding NetworkX graph objects as values.
51
+ """
52
+
38
53
  ladder_size = 16
39
54
  ladder = nx.ladder_graph(ladder_size)
40
55
 
@@ -775,6 +790,21 @@ def atlas():
775
790
 
776
791
 
777
792
  def models(iterable):
793
+ """
794
+ Generate a graph model based on the provided iterable of graphs.
795
+ The function creates a graph model named 'Graph Atlas' using the 'graphinate' library.
796
+ It then combines all the graphs from the input iterable into a single disjoint union graph using NetworkX library.
797
+ The function defines edges for the combined graph by iterating over all edges in the disjoint union graph and
798
+ yielding dictionaries with 'source' and 'target' keys representing the edge connections.
799
+ Finally, the function yields the created graph model containing the combined graph with defined edges.
800
+
801
+ Args:
802
+ iterable: An iterable containing graphs to be combined into a single graph model.
803
+
804
+ Yields:
805
+ GraphModel: A graph model containing the combined graph with defined edges.
806
+ """
807
+
778
808
  graph_model = graphinate.model('Graph Atlas')
779
809
 
780
810
  graph_atlas = nx.disjoint_union_all(g for _, g in iterable)
@@ -5,7 +5,17 @@ import networkx as nx
5
5
  N: int = 8
6
6
 
7
7
 
8
- def get_graph_model(number_of_sides: int = N):
8
+ def polygonal_graph_model(number_of_sides: int = N):
9
+ """
10
+ Create a polygonal graph model.
11
+
12
+ Args:
13
+ number_of_sides (int): Number of sides in the polygon. Defaults to N.
14
+
15
+ Returns:
16
+ GraphModel: A graph model representing a polygonal graph.
17
+ """
18
+
9
19
  # Define GraphModel
10
20
  graph_model = graphinate.model(name="Octagonal Graph")
11
21
 
@@ -19,7 +29,7 @@ def get_graph_model(number_of_sides: int = N):
19
29
  return graph_model
20
30
 
21
31
 
22
- model = get_graph_model()
32
+ model = polygonal_graph_model()
23
33
 
24
34
  if __name__ == '__main__':
25
35
  use_materialize = True
@@ -7,6 +7,13 @@ import psutil
7
7
 
8
8
 
9
9
  def processes_graph_model():
10
+ """
11
+ Create a graph model representing processes and their parent-child relationships.
12
+
13
+ Returns:
14
+ GraphModel: A graph model representing processes and their parent-child relationships.
15
+ """
16
+
10
17
  graph_model = graphinate.model("Processes Graph")
11
18
 
12
19
  def processes() -> Iterable[psutil.Process]:
@@ -9,6 +9,16 @@ DEFAULT_MAX_DEPTH = 0
9
9
 
10
10
 
11
11
  def page_links_graph_model(max_depth: int = DEFAULT_MAX_DEPTH):
12
+ """
13
+ Create a graph model based on page links.
14
+
15
+ Args:
16
+ max_depth (int, optional): The maximum depth to crawl for page links. Defaults to DEFAULT_MAX_DEPTH.
17
+
18
+ Returns:
19
+ GraphModel: A graph model representing the page links.
20
+ """
21
+
12
22
  def _links(url: str, depth=0, **kwargs):
13
23
  reqs = requests.get(url)
14
24
  logger.debug('Analyzing Page: {url}')
@@ -1,19 +1,18 @@
1
1
  [project]
2
2
  name = "Graphinate"
3
- version = "0.2.21"
3
+ version = "0.3.0"
4
4
  authors = [
5
5
  { name = "Eran Rivlis", email = "eran@rivlis.info" },
6
6
  ]
7
7
  description = "Graphinate. Data to Graphs."
8
8
  readme = "README.md"
9
- requires-python = ">=3.9"
9
+ requires-python = ">=3.10"
10
10
  classifiers = [
11
- "Development Status :: 3 - Alpha",
11
+ "Development Status :: 4 - Beta",
12
12
  "Intended Audience :: Developers",
13
13
  "Intended Audience :: Information Technology",
14
14
  "Intended Audience :: Science/Research",
15
15
  "Programming Language :: Python :: 3",
16
- "Programming Language :: Python :: 3.9",
17
16
  "Programming Language :: Python :: 3.10",
18
17
  "Programming Language :: Python :: 3.11",
19
18
  "Programming Language :: Python :: 3.12",
@@ -29,11 +28,11 @@ classifiers = [
29
28
  keywords = ['graph', 'declarative']
30
29
  dependencies = [
31
30
  "click>=8.1.7",
32
- "inflect>=7.2.1",
31
+ "inflect>=7.3.0",
33
32
  "loguru>=0.7.2",
34
- "matplotlib>=3.8.4",
33
+ "matplotlib>=3.9.0",
35
34
  "networkx>=3.3",
36
- "strawberry-graphql[asgi,opentelemetry]>=0.227.3"
35
+ "strawberry-graphql[asgi,opentelemetry]>=0.235.1"
37
36
  ]
38
37
 
39
38
 
@@ -60,18 +59,18 @@ docs = [
60
59
  ]
61
60
  test = [
62
61
  "faker>=23.2.1",
63
- "pytest>=8.1.1",
64
- "pytest-asyncio>=0.23.5",
62
+ "pytest>=8.2.2",
63
+ "pytest-asyncio>=0.23.7",
65
64
  "pytest-cov>=5.0.0",
66
65
  "pytest-randomly>=3.15.0",
67
- "pytest-xdist>=3.5.0"
66
+ "pytest-xdist>=3.6.1"
68
67
  ]
69
68
  plot = [
70
- "scipy>=1.12.0"
69
+ "scipy>=1.14.0"
71
70
  ]
72
71
  server = [
73
72
  "starlette-prometheus",
74
- "uvicorn[standard]>=0.29.0"
73
+ "uvicorn[standard]>=0.30.1"
75
74
  ]
76
75
 
77
76
 
@@ -10,10 +10,11 @@ import networkx as nx
10
10
  def node_color_mapping(graph: nx.Graph, cmap: Union[str, mpl.colors.Colormap] = "tab20") -> Mapping:
11
11
  """
12
12
  Parameters:
13
- graph: graph_id
14
- cmap : str or `~matplotlib.colors.Colormap` - The colormap used to map values to RGBA colors.
13
+ graph: nx.Graph - The input graph for which node colors need to be mapped.
14
+ cmap: Union[str, mpl.colors.Colormap], optional - The colormap used to map values to RGBA colors.
15
+ Default is "tab20".
15
16
  Returns:
16
- Nodes RGBA Color list.
17
+ Mapping - A dictionary mapping nodes to their corresponding RGBA colors based on the colormap.
17
18
  """
18
19
  type_lookup = {t: i for i, t in enumerate(graph.graph['node_types'].keys())}
19
20
  color_lookup = {node: type_lookup.get(data.get('type'), 0) for node, data in graph.nodes.data()}
@@ -8,11 +8,12 @@ def draw(graph: nx.Graph,
8
8
  with_node_labels: bool = True,
9
9
  with_edge_labels: bool = False):
10
10
  """
11
+ Draws the given networkx graph with optional node and edge labels.
11
12
 
12
- Args:
13
- graph:
14
- with_node_labels:
15
- with_edge_labels:
13
+ Parameters:
14
+ graph (nx.Graph): The input graph to be drawn.
15
+ with_node_labels (bool): Whether to display node labels. Default is True.
16
+ with_edge_labels (bool): Whether to display edge labels. Default is False.
16
17
 
17
18
  Returns:
18
19
  None
@@ -54,11 +55,12 @@ def plot(graph: nx.Graph,
54
55
  with_node_labels: bool = True,
55
56
  with_edge_labels: bool = False):
56
57
  """
58
+ Plots the given networkx graph with optional node and edge labels.
57
59
 
58
60
  Args:
59
- graph:
60
- with_node_labels:
61
- with_edge_labels:
61
+ graph (nx.Graph): The input graph to be plotted.
62
+ with_node_labels (bool): Whether to display node labels. Default is True.
63
+ with_edge_labels (bool): Whether to display edge labels. Default is False.
62
64
 
63
65
  Returns:
64
66
  None
@@ -0,0 +1,80 @@
1
+ import contextlib
2
+ import webbrowser
3
+
4
+ import strawberry
5
+ from starlette.applications import Starlette
6
+ from starlette.requests import Request
7
+ from starlette.schemas import SchemaGenerator
8
+ from starlette.types import ASGIApp
9
+ from strawberry.asgi import GraphQL
10
+ from strawberry.extensions.tracing import OpenTelemetryExtension
11
+
12
+ from .starlette import routes
13
+
14
+ DEFAULT_PORT: int = 8072
15
+
16
+ GRAPHQL_ROUTE_PATH = "/graphql"
17
+
18
+
19
+ def openapi_schema(request: Request) -> ASGIApp:
20
+ """
21
+ Generates an OpenAPI schema for the GraphQL API and other routes.
22
+
23
+ Args:
24
+ request (Request): The HTTP request object.
25
+
26
+ Returns:
27
+ ASGIApp: An OpenAPI response containing the schema for the specified routes.
28
+ """
29
+ schema_data = {
30
+ 'openapi': '3.0.0',
31
+ 'info': {'title': 'Graphinate API', 'version': '1.0'},
32
+ 'paths': {
33
+ '/graphql': {'get': {'responses': {200: {'description': 'GraphQL'}}}},
34
+ '/graphiql': {'get': {'responses': {200: {'description': 'GraphiQL UI.'}}}},
35
+ '/metrics': {'get': {'responses': {200: {'description': 'Prometheus metrics.'}}}},
36
+ '/viewer': {'get': {'responses': {200: {'description': '3D Force-Directed Graph Viewer'}}}},
37
+ '/voyager': {'get': {'responses': {200: {'description': 'Voyager GraphQL Schema Viewer'}}}}
38
+ }
39
+ }
40
+
41
+ schema = SchemaGenerator(schema_data)
42
+ return schema.OpenAPIResponse(request=request)
43
+
44
+
45
+ def graphql(graphql_schema: strawberry.Schema, port: int = DEFAULT_PORT):
46
+ """
47
+
48
+ Args:
49
+ graphql_schema:
50
+ port:
51
+
52
+ Returns:
53
+
54
+ """
55
+ graphql_schema.extensions.append(OpenTelemetryExtension)
56
+
57
+ @contextlib.asynccontextmanager
58
+ async def lifespan(app: Starlette): # pragma: no cover
59
+ def open_url():
60
+ for app_name in ('voyager', 'graphiql', 'viewer'):
61
+ webbrowser.open(f'http://localhost:{port}/{app_name}')
62
+
63
+ open_url()
64
+ yield
65
+
66
+ graphql_app: GraphQL = GraphQL(graphql_schema)
67
+ app = Starlette(
68
+ lifespan=lifespan,
69
+ routes=routes()
70
+ )
71
+ app.add_route(GRAPHQL_ROUTE_PATH, graphql_app)
72
+ app.add_websocket_route(GRAPHQL_ROUTE_PATH, graphql_app)
73
+
74
+ from starlette_prometheus import PrometheusMiddleware, metrics
75
+ app.add_middleware(PrometheusMiddleware)
76
+ app.add_route("/metrics", metrics)
77
+ app.add_route("/schema", route=openapi_schema, include_in_schema=False)
78
+
79
+ import uvicorn
80
+ uvicorn.run(app, host='0.0.0.0', port=port)