Graphinate 0.5.1__tar.gz → 0.6.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 (101) hide show
  1. {graphinate-0.5.1 → graphinate-0.6.0}/.github/workflows/publish.yml +1 -1
  2. {graphinate-0.5.1 → graphinate-0.6.0}/.github/workflows/test.yml +1 -1
  3. {graphinate-0.5.1 → graphinate-0.6.0}/PKG-INFO +3 -1
  4. {graphinate-0.5.1 → graphinate-0.6.0}/README.md +2 -0
  5. {graphinate-0.5.1 → graphinate-0.6.0}/docs/intro.md +14 -10
  6. {graphinate-0.5.1 → graphinate-0.6.0}/docs/usage/cli.md +8 -0
  7. {graphinate-0.5.1 → graphinate-0.6.0}/examples/math/graph_atlas.py +2 -6
  8. {graphinate-0.5.1 → graphinate-0.6.0}/mkdocs.yml +6 -2
  9. {graphinate-0.5.1 → graphinate-0.6.0}/pyproject.toml +9 -9
  10. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/builders.py +4 -3
  11. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/__init__.py +12 -4
  12. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/rapidoc/index.html +3 -2
  13. graphinate-0.6.0/src/graphinate/server/web/viewer/index.html +542 -0
  14. {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_builders.py +2 -2
  15. graphinate-0.5.1/src/graphinate/server/web/viewer/index.html +0 -162
  16. {graphinate-0.5.1 → graphinate-0.6.0}/.coveragerc +0 -0
  17. {graphinate-0.5.1 → graphinate-0.6.0}/.github/dependabot.yml +0 -0
  18. {graphinate-0.5.1 → graphinate-0.6.0}/.github/workflows/codeql.yml +0 -0
  19. {graphinate-0.5.1 → graphinate-0.6.0}/.github/workflows/publish-docs.yaml +0 -0
  20. {graphinate-0.5.1 → graphinate-0.6.0}/.github/workflows/test-beta.yml +0 -0
  21. {graphinate-0.5.1 → graphinate-0.6.0}/.gitignore +0 -0
  22. {graphinate-0.5.1 → graphinate-0.6.0}/.sonarcloud.properties +0 -0
  23. {graphinate-0.5.1 → graphinate-0.6.0}/LICENSE +0 -0
  24. {graphinate-0.5.1 → graphinate-0.6.0}/STATS.md +0 -0
  25. {graphinate-0.5.1 → graphinate-0.6.0}/docs/acknowledge.md +0 -0
  26. {graphinate-0.5.1 → graphinate-0.6.0}/docs/assets/badge/v0.json +0 -0
  27. {graphinate-0.5.1 → graphinate-0.6.0}/docs/assets/images/logo-128.png +0 -0
  28. {graphinate-0.5.1 → graphinate-0.6.0}/docs/assets/images/network_graph.png +0 -0
  29. {graphinate-0.5.1 → graphinate-0.6.0}/docs/assets/stylesheets/extra.css +0 -0
  30. {graphinate-0.5.1 → graphinate-0.6.0}/docs/dev.md +0 -0
  31. {graphinate-0.5.1 → graphinate-0.6.0}/docs/examples/code.md +0 -0
  32. {graphinate-0.5.1 → graphinate-0.6.0}/docs/examples/github.md +0 -0
  33. {graphinate-0.5.1 → graphinate-0.6.0}/docs/examples/math.md +0 -0
  34. {graphinate-0.5.1 → graphinate-0.6.0}/docs/examples/system.md +0 -0
  35. {graphinate-0.5.1 → graphinate-0.6.0}/docs/examples/web.md +0 -0
  36. {graphinate-0.5.1 → graphinate-0.6.0}/docs/gen_ref_pages.py +0 -0
  37. {graphinate-0.5.1 → graphinate-0.6.0}/docs/index.md +0 -0
  38. {graphinate-0.5.1 → graphinate-0.6.0}/docs/start.md +0 -0
  39. {graphinate-0.5.1 → graphinate-0.6.0}/docs/usage/lib.md +0 -0
  40. {graphinate-0.5.1 → graphinate-0.6.0}/examples/code/python_ast.py +0 -0
  41. {graphinate-0.5.1 → graphinate-0.6.0}/examples/code/python_dependencies.py +0 -0
  42. {graphinate-0.5.1 → graphinate-0.6.0}/examples/code/requirements.txt +0 -0
  43. {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/_client.py +0 -0
  44. {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/commits_visibilty_graph.py +0 -0
  45. {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/followers.graphql +0 -0
  46. {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/followers.py +0 -0
  47. {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/graphql.config.yml +0 -0
  48. {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/repositories.graphql +0 -0
  49. {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/repositories.py +0 -0
  50. {graphinate-0.5.1 → graphinate-0.6.0}/examples/github/requirements.txt +0 -0
  51. {graphinate-0.5.1 → graphinate-0.6.0}/examples/math/graphs.py +0 -0
  52. {graphinate-0.5.1 → graphinate-0.6.0}/examples/math/gui.py +0 -0
  53. {graphinate-0.5.1 → graphinate-0.6.0}/examples/math/polygonal_graph.py +0 -0
  54. {graphinate-0.5.1 → graphinate-0.6.0}/examples/math/requirements.txt +0 -0
  55. {graphinate-0.5.1 → graphinate-0.6.0}/examples/system/processes.py +0 -0
  56. {graphinate-0.5.1 → graphinate-0.6.0}/examples/system/requirements.txt +0 -0
  57. {graphinate-0.5.1 → graphinate-0.6.0}/examples/web/page_links.py +0 -0
  58. {graphinate-0.5.1 → graphinate-0.6.0}/examples/web/requirements.txt +0 -0
  59. {graphinate-0.5.1 → graphinate-0.6.0}/playground/ethernet/traceroute.py +0 -0
  60. {graphinate-0.5.1 → graphinate-0.6.0}/playground/genric_graph.graphql +0 -0
  61. {graphinate-0.5.1 → graphinate-0.6.0}/playground/graphql.config.yml +0 -0
  62. {graphinate-0.5.1 → graphinate-0.6.0}/playground/house_of_graphs.py +0 -0
  63. {graphinate-0.5.1 → graphinate-0.6.0}/playground/social/albums.json +0 -0
  64. {graphinate-0.5.1 → graphinate-0.6.0}/playground/social/musicisians.py +0 -0
  65. {graphinate-0.5.1 → graphinate-0.6.0}/playground/text/nlp_graph.py +0 -0
  66. {graphinate-0.5.1 → graphinate-0.6.0}/playground/text/requirements.txt +0 -0
  67. {graphinate-0.5.1 → graphinate-0.6.0}/playground/time_series/requirements.txt +0 -0
  68. {graphinate-0.5.1 → graphinate-0.6.0}/playground/time_series/visibility_graph.py +0 -0
  69. {graphinate-0.5.1 → graphinate-0.6.0}/sonar-project.properties +0 -0
  70. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/__init__.py +0 -0
  71. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/__main__.py +0 -0
  72. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/cli.py +0 -0
  73. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/color.py +0 -0
  74. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/materializers/__init__.py +0 -0
  75. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/materializers/matplotlib.py +0 -0
  76. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/modeling.py +0 -0
  77. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/starlette/__init__.py +0 -0
  78. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/starlette/views.py +0 -0
  79. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/__init__.py +0 -0
  80. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/elements/__init__.py +0 -0
  81. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/elements/index.html +0 -0
  82. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/graphiql/__init__.py +0 -0
  83. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/graphiql/index.html +0 -0
  84. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/rapidoc/__init__.py +0 -0
  85. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/static/images/logo-128.png +0 -0
  86. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/static/images/logo.svg +0 -0
  87. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/static/images/network_graph.png +0 -0
  88. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/viewer/__init__.py +0 -0
  89. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/voyager/__init__.py +0 -0
  90. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/server/web/voyager/index.html +0 -0
  91. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/tools/__init__.py +0 -0
  92. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/tools/converters.py +0 -0
  93. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/tools/mutators.py +0 -0
  94. {graphinate-0.5.1 → graphinate-0.6.0}/src/graphinate/typing.py +0 -0
  95. {graphinate-0.5.1 → graphinate-0.6.0}/tests/conftest.py +0 -0
  96. {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_cli.py +0 -0
  97. {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_color.py +0 -0
  98. {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_materializers.py +0 -0
  99. {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_modeling.py +0 -0
  100. {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_server.py +0 -0
  101. {graphinate-0.5.1 → graphinate-0.6.0}/tests/graphinate/test_tools.py +0 -0
@@ -28,7 +28,7 @@ jobs:
28
28
  - name: Build package
29
29
  run: python -m build
30
30
  - name: Publish package
31
- uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
31
+ uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc
32
32
  with:
33
33
  user: __token__
34
34
  password: ${{ secrets.PYPI_API_TOKEN }}
@@ -40,7 +40,7 @@ jobs:
40
40
  python -m pip install faker pytest pytest-asyncio pytest-cov pytest-randomly pytest-xdist starlette-prometheus uvicorn[standard]
41
41
  pytest tests --cov=src --cov-branch --cov-report=xml --junitxml=test_results.xml -n auto
42
42
  - name: Upload coverage reports to Codecov
43
- uses: codecov/codecov-action@v4
43
+ uses: codecov/codecov-action@v5
44
44
  with:
45
45
  token: ${{ secrets.CODECOV_TOKEN }}
46
46
  - name: Run codacy-coverage-reporter
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Graphinate
3
- Version: 0.5.1
3
+ Version: 0.6.0
4
4
  Summary: 𝔾raphinate. Data to Graphs.
5
5
  Project-URL: Homepage, https://erivlis.github.io/graphinate
6
6
  Project-URL: Documentation, https://erivlis.github.io/graphinate
@@ -221,6 +221,8 @@ Options:
221
221
 
222
222
  #### Server
223
223
 
224
+ > TIP: requires the `server` extra to be installed. e.g., `pip install graphinate[server]`
225
+
224
226
  ```text
225
227
  Usage: python -m graphinate server [OPTIONS]
226
228
 
@@ -179,6 +179,8 @@ Options:
179
179
 
180
180
  #### Server
181
181
 
182
+ > TIP: requires the `server` extra to be installed. e.g., `pip install graphinate[server]`
183
+
182
184
  ```text
183
185
  Usage: python -m graphinate server [OPTIONS]
184
186
 
@@ -15,21 +15,25 @@ In addition, there are several modes of output to enable examination of the Grap
15
15
 
16
16
  ### What is a Graph?
17
17
 
18
- “In a mathematician's terminology, a graph is a collection of points and lines connecting some (possibly empty) subset
19
- of them.
20
- The points of a graph are most commonly known as graph *vertices*, but may also be called *nodes* or *points*.
21
- Similarly, the lines connecting the vertices of a graph are most commonly known as graph *edges*, but may also
22
- be called *arcs* or *lines*.”
18
+ !!! quote
23
19
 
24
- — [https://mathworld.wolfram.com/Graph.html](https://mathworld.wolfram.com/Graph.html)
20
+ “In a mathematician's terminology, a graph is a collection of points and lines connecting some (possibly empty) subset
21
+ of them.
22
+ The points of a graph are most commonly known as graph *vertices*, but may also be called *nodes* or *points*.
23
+ Similarly, the lines connecting the vertices of a graph are most commonly known as graph *edges*, but may also
24
+ be called *arcs* or *lines*.”
25
+
26
+ — [https://mathworld.wolfram.com/Graph.html](https://mathworld.wolfram.com/Graph.html)
25
27
 
26
28
  ### What is Data?
27
29
 
28
- “...data is a collection of discrete or continuous values that convey information, describing the quantity, quality,
29
- fact, statistics, other basic units of meaning, or simply sequences of symbols that may be further interpreted
30
- formally.”
30
+ !!! quote
31
31
 
32
- — [https://en.wikipedia.org/wiki/Data](https://en.wikipedia.org/wiki/Data)
32
+ “...data is a collection of discrete or continuous values that convey information, describing the quantity, quality,
33
+ fact, statistics, other basic units of meaning, or simply sequences of symbols that may be further interpreted
34
+ formally.”
35
+
36
+ — [https://en.wikipedia.org/wiki/Data](https://en.wikipedia.org/wiki/Data)
33
37
 
34
38
  ## How?
35
39
 
@@ -28,6 +28,14 @@ Options:
28
28
 
29
29
  ### Server
30
30
 
31
+ !!! tip
32
+
33
+ requires the `server` extra to be installed.
34
+
35
+ ```shell
36
+ pip install graphinate[server]
37
+ ```
38
+
31
39
  ```console
32
40
  Usage: python -m graphinate server [OPTIONS]
33
41
 
@@ -38,13 +38,9 @@ def model(items: list[tuple[str, nx.Graph]]) -> graphinate.GraphModel:
38
38
  def nodes():
39
39
  yield from g.nodes(data='type')
40
40
 
41
- @graph_model.edge(operator.itemgetter(2),
42
- source=operator.itemgetter(0),
43
- target=operator.itemgetter(1),
44
- label=operator.itemgetter(0, 1),
45
- value=operator.itemgetter(0, 1))
41
+ @graph_model.edge(operator.itemgetter('type'))
46
42
  def edge():
47
- yield from g.edges.data('type')
43
+ yield from ({'source': e[0], 'target': e[1], **e[2]} for e in g.edges.data())
48
44
 
49
45
  return graph_model
50
46
 
@@ -101,8 +101,12 @@ extra:
101
101
  link: https://pypi.org/project/graphinate
102
102
  - icon: fontawesome/brands/mastodon
103
103
  link: https://mastodon.social/@erivlis
104
- - icon: fontawesome/brands/twitter
105
- link: https://twitter.com/erivlis
104
+ - icon: fontawesome/brands/bluesky
105
+ link: https://bsky.app/profile/erivlis.bsky.social
106
+ - icon: fontawesome/brands/x-twitter
107
+ link: https://x.com/erivlis
108
+ - icon: fontawesome/brands/linkedin
109
+ link: https://www.linkedin.com/in/eranrivlis
106
110
 
107
111
 
108
112
  plugins:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "Graphinate"
3
- version = "0.5.1"
3
+ version = "0.6.0"
4
4
  authors = [
5
5
  { name = "Eran Rivlis", email = "eran@rivlis.info" },
6
6
  ]
@@ -36,14 +36,6 @@ dependencies = [
36
36
  "strawberry-graphql[asgi,opentelemetry]"
37
37
  ]
38
38
 
39
-
40
- [project.urls]
41
- "Homepage" = "https://erivlis.github.io/graphinate"
42
- "Documentation" = "https://erivlis.github.io/graphinate"
43
- "Bug Tracker" = "https://github.com/erivlis/graphinate/issues"
44
- "Source" = "https://github.com/erivlis/graphinate"
45
-
46
-
47
39
  [project.optional-dependencies]
48
40
  plot = [
49
41
  "scipy"
@@ -53,8 +45,16 @@ server = [
53
45
  "uvicorn[standard]"
54
46
  ]
55
47
 
48
+ [project.urls]
49
+ "Homepage" = "https://erivlis.github.io/graphinate"
50
+ "Documentation" = "https://erivlis.github.io/graphinate"
51
+ "Bug Tracker" = "https://github.com/erivlis/graphinate/issues"
52
+ "Source" = "https://github.com/erivlis/graphinate"
53
+
54
+
56
55
  [dependency-groups]
57
56
  dev = [
57
+ "uv",
58
58
  "ruff",
59
59
  "pipdeptree"
60
60
  ]
@@ -30,7 +30,7 @@ from .tools import converters, mutators, utcnow
30
30
  from .typing import NodeTypeAbsoluteId, UniverseNode
31
31
 
32
32
  DEFAULT_NODE_DELIMITER = ' ∋ '
33
- DEFAULT_EDGE_DELIMITER = ' '
33
+ DEFAULT_EDGE_DELIMITER = ' '
34
34
 
35
35
  GraphRepresentation = Union[dict, nx.Graph, strawberry.Schema] # noqa: UP007
36
36
 
@@ -235,13 +235,14 @@ class NetworkxBuilder(Builder):
235
235
  for edge_generator in edge_generators:
236
236
  for edge in edge_generator(**kwargs):
237
237
  edge_id = ((edge.source,), (edge.target,))
238
+ edge_label = edge.label(edge_id) if callable(edge.label) else edge.label
238
239
  edge_weight = edge.weight or 1.0
239
240
  edge_type = edge.type.lower()
240
241
  logger.debug("Adding edge from: '{}' to: '{}'", *edge_id)
241
242
 
242
243
  if isinstance(self._graph, nx.MultiGraph) or edge_id not in self._graph.edges:
243
244
  self._graph.add_edge(*edge_id,
244
- label=edge.label,
245
+ label=edge_label,
245
246
  type=edge_type,
246
247
  value=[edge.value],
247
248
  weight=edge_weight,
@@ -277,7 +278,7 @@ class NetworkxBuilder(Builder):
277
278
  for name, default in defaults.items():
278
279
  if callable(default):
279
280
  values = {tuple(e): default(tuple(e)) for *e, a in self._graph_edges(data=name, default=None)
280
- if a is None}
281
+ if a is not None}
281
282
  elif isinstance(default, dict):
282
283
  values = default
283
284
  elif default:
@@ -4,6 +4,7 @@ import webbrowser
4
4
  import strawberry
5
5
  from starlette.applications import Starlette
6
6
  from starlette.requests import Request
7
+ from starlette.responses import RedirectResponse
7
8
  from starlette.schemas import SchemaGenerator
8
9
  from starlette.types import ASGIApp
9
10
  from strawberry.asgi import GraphQL
@@ -28,7 +29,7 @@ def openapi_schema(request: Request) -> ASGIApp:
28
29
  """
29
30
  schema_data = {
30
31
  'openapi': '3.0.0',
31
- 'info': {'title': 'Graphinate API', 'version': '0.5.1'},
32
+ 'info': {'title': 'Graphinate API', 'version': '0.6.0'},
32
33
  'paths': {
33
34
  '/graphql': {'get': {'responses': {200: {'description': 'GraphQL'}}}},
34
35
  '/graphiql': {'get': {'responses': {200: {'description': 'GraphiQL UI.'}}}},
@@ -54,11 +55,12 @@ def graphql(graphql_schema: strawberry.Schema, port: int = DEFAULT_PORT):
54
55
  """
55
56
  graphql_schema.extensions.append(OpenTelemetryExtension)
56
57
 
58
+ def open_url():
59
+ for app_name in ('viewer',):
60
+ webbrowser.open(f'http://localhost:{port}/{app_name}')
61
+
57
62
  @contextlib.asynccontextmanager
58
63
  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
64
 
63
65
  open_url()
64
66
  yield
@@ -75,6 +77,12 @@ def graphql(graphql_schema: strawberry.Schema, port: int = DEFAULT_PORT):
75
77
  app.add_middleware(PrometheusMiddleware)
76
78
  app.add_route("/metrics", metrics)
77
79
  app.add_route("/schema", route=openapi_schema, include_in_schema=False)
80
+ app.add_route("/openapi.json", route=openapi_schema, include_in_schema=False)
81
+
82
+ async def redirect_to_existing_route(request):
83
+ return RedirectResponse(url='/viewer')
84
+
85
+ app.add_route('/', redirect_to_existing_route)
78
86
 
79
87
  import uvicorn
80
88
  uvicorn.run(app, host='0.0.0.0', port=port)
@@ -2,8 +2,9 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8"> <!-- Important: rapi-doc uses utf8 characters -->
5
- <script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"
6
- integrity="sha384-x8lk+1kqb32UOR4ETiOR+bpfZZtNri15JJdU7sXAKtHk2m9yMRVvITZcxS0ILJpC"></script>
5
+ <script src="https://unpkg.com/rapidoc@9.3.8/dist/rapidoc-min.js"
6
+ integrity="sha384-szzoYhqSJqZH8X90KwbBjYL1CMLEa3U7xl/oAZg4ViKpYEY5GVhM+peBQB4u7ANM"
7
+ crossorigin="anonymous"></script>
7
8
  <title>Graphinate - OpenAPI RapiDoc UI</title>
8
9
  </head>
9
10
  <body>