Graphinate 0.2.17__tar.gz → 0.2.19__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 (97) hide show
  1. {graphinate-0.2.17 → graphinate-0.2.19}/.github/workflows/test.yml +3 -3
  2. {graphinate-0.2.17 → graphinate-0.2.19}/PKG-INFO +4 -4
  3. graphinate-0.2.19/docs/examples/system.md +15 -0
  4. graphinate-0.2.19/examples/code/requirements.txt +1 -0
  5. graphinate-0.2.19/examples/system/processes.py +64 -0
  6. graphinate-0.2.19/examples/system/requirements.txt +1 -0
  7. {graphinate-0.2.17 → graphinate-0.2.19}/pyproject.toml +3 -3
  8. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/builders.py +59 -43
  9. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/web/elements/index.html +3 -2
  10. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/web/graphiql/index.html +1 -1
  11. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/web/rapidoc/index.html +1 -1
  12. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/web/viewer/index.html +2 -1
  13. graphinate-0.2.19/src/graphinate/tools/__init__.py +5 -0
  14. {graphinate-0.2.17 → graphinate-0.2.19}/tests/graphinate/test_materializers.py +10 -6
  15. graphinate-0.2.17/examples/code/requirements.txt +0 -1
  16. graphinate-0.2.17/src/graphinate/tools/__init__.py +0 -0
  17. {graphinate-0.2.17 → graphinate-0.2.19}/.coveragerc +0 -0
  18. {graphinate-0.2.17 → graphinate-0.2.19}/.github/dependabot.yml +0 -0
  19. {graphinate-0.2.17 → graphinate-0.2.19}/.github/workflows/codeql.yml +0 -0
  20. {graphinate-0.2.17 → graphinate-0.2.19}/.github/workflows/publish-docs.yaml +0 -0
  21. {graphinate-0.2.17 → graphinate-0.2.19}/.github/workflows/publish.yml +0 -0
  22. {graphinate-0.2.17 → graphinate-0.2.19}/.github/workflows/test-beta.yml +0 -0
  23. {graphinate-0.2.17 → graphinate-0.2.19}/.gitignore +0 -0
  24. {graphinate-0.2.17 → graphinate-0.2.19}/LICENSE +0 -0
  25. {graphinate-0.2.17 → graphinate-0.2.19}/README.md +0 -0
  26. {graphinate-0.2.17 → graphinate-0.2.19}/STATS.md +0 -0
  27. {graphinate-0.2.17 → graphinate-0.2.19}/docs/acknowledge.md +0 -0
  28. {graphinate-0.2.17 → graphinate-0.2.19}/docs/assets/images/logo-128.png +0 -0
  29. {graphinate-0.2.17 → graphinate-0.2.19}/docs/assets/images/network_graph.png +0 -0
  30. {graphinate-0.2.17 → graphinate-0.2.19}/docs/assets/stylesheets/extra.css +0 -0
  31. {graphinate-0.2.17 → graphinate-0.2.19}/docs/dev.md +0 -0
  32. {graphinate-0.2.17 → graphinate-0.2.19}/docs/examples/code.md +0 -0
  33. {graphinate-0.2.17 → graphinate-0.2.19}/docs/examples/github.md +0 -0
  34. {graphinate-0.2.17 → graphinate-0.2.19}/docs/examples/math.md +0 -0
  35. {graphinate-0.2.17 → graphinate-0.2.19}/docs/examples/web.md +0 -0
  36. {graphinate-0.2.17 → graphinate-0.2.19}/docs/gen_ref_pages.py +0 -0
  37. {graphinate-0.2.17 → graphinate-0.2.19}/docs/index.md +0 -0
  38. {graphinate-0.2.17 → graphinate-0.2.19}/docs/intro.md +0 -0
  39. {graphinate-0.2.17 → graphinate-0.2.19}/docs/start.md +0 -0
  40. {graphinate-0.2.17 → graphinate-0.2.19}/docs/usage/cli.md +0 -0
  41. {graphinate-0.2.17 → graphinate-0.2.19}/docs/usage/lib.md +0 -0
  42. {graphinate-0.2.17 → graphinate-0.2.19}/examples/code/python_ast.py +0 -0
  43. {graphinate-0.2.17 → graphinate-0.2.19}/examples/code/python_dependencies.py +0 -0
  44. {graphinate-0.2.17 → graphinate-0.2.19}/examples/github/_client.py +0 -0
  45. {graphinate-0.2.17 → graphinate-0.2.19}/examples/github/commits_visibilty_graph.py +0 -0
  46. {graphinate-0.2.17 → graphinate-0.2.19}/examples/github/followers.graphql +0 -0
  47. {graphinate-0.2.17 → graphinate-0.2.19}/examples/github/followers.py +0 -0
  48. {graphinate-0.2.17 → graphinate-0.2.19}/examples/github/graphql.config.yml +0 -0
  49. {graphinate-0.2.17 → graphinate-0.2.19}/examples/github/repositories.graphql +0 -0
  50. {graphinate-0.2.17 → graphinate-0.2.19}/examples/github/repositories.py +0 -0
  51. {graphinate-0.2.17 → graphinate-0.2.19}/examples/github/requirements.txt +0 -0
  52. {graphinate-0.2.17 → graphinate-0.2.19}/examples/math/graph_atlas.py +0 -0
  53. {graphinate-0.2.17 → graphinate-0.2.19}/examples/math/polygonal_graph.py +0 -0
  54. {graphinate-0.2.17 → graphinate-0.2.19}/examples/web/page_links.py +0 -0
  55. {graphinate-0.2.17 → graphinate-0.2.19}/examples/web/requirements.txt +0 -0
  56. {graphinate-0.2.17 → graphinate-0.2.19}/mkdocs.yml +0 -0
  57. {graphinate-0.2.17 → graphinate-0.2.19}/playground/ethernet/traceroute.py +0 -0
  58. {graphinate-0.2.17 → graphinate-0.2.19}/playground/genric_graph.graphql +0 -0
  59. {graphinate-0.2.17 → graphinate-0.2.19}/playground/graphql.config.yml +0 -0
  60. {graphinate-0.2.17 → graphinate-0.2.19}/playground/house_of_graphs.py +0 -0
  61. {graphinate-0.2.17 → graphinate-0.2.19}/playground/social/albums.json +0 -0
  62. {graphinate-0.2.17 → graphinate-0.2.19}/playground/social/musicisians.py +0 -0
  63. {graphinate-0.2.17 → graphinate-0.2.19}/playground/text/nlp_graph.py +0 -0
  64. {graphinate-0.2.17 → graphinate-0.2.19}/playground/text/requirements.txt +0 -0
  65. {graphinate-0.2.17 → graphinate-0.2.19}/playground/time_series/requirements.txt +0 -0
  66. {graphinate-0.2.17 → graphinate-0.2.19}/playground/time_series/visibility_graph.py +0 -0
  67. {graphinate-0.2.17 → graphinate-0.2.19}/sonar-project.properties +0 -0
  68. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/__init__.py +0 -0
  69. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/__main__.py +0 -0
  70. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/cli.py +0 -0
  71. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/color.py +0 -0
  72. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/materializers/__init__.py +0 -0
  73. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/materializers/matplotlib.py +0 -0
  74. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/modeling.py +0 -0
  75. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/__init__.py +0 -0
  76. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/starlette/__init__.py +0 -0
  77. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/starlette/views.py +0 -0
  78. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/web/__init__.py +0 -0
  79. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/web/elements/__init__.py +0 -0
  80. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/web/graphiql/__init__.py +0 -0
  81. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/web/rapidoc/__init__.py +0 -0
  82. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/web/static/images/logo-128.png +0 -0
  83. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/web/static/images/network_graph.png +0 -0
  84. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/web/viewer/__init__.py +0 -0
  85. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/web/voyager/__init__.py +0 -0
  86. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/server/web/voyager/index.html +0 -0
  87. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/tools/converters.py +0 -0
  88. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/tools/gui.py +0 -0
  89. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/tools/mutators.py +0 -0
  90. {graphinate-0.2.17 → graphinate-0.2.19}/src/graphinate/typing.py +0 -0
  91. {graphinate-0.2.17 → graphinate-0.2.19}/tests/conftest.py +0 -0
  92. {graphinate-0.2.17 → graphinate-0.2.19}/tests/graphinate/test_builders.py +0 -0
  93. {graphinate-0.2.17 → graphinate-0.2.19}/tests/graphinate/test_cli.py +0 -0
  94. {graphinate-0.2.17 → graphinate-0.2.19}/tests/graphinate/test_color.py +0 -0
  95. {graphinate-0.2.17 → graphinate-0.2.19}/tests/graphinate/test_modeling.py +0 -0
  96. {graphinate-0.2.17 → graphinate-0.2.19}/tests/graphinate/test_server.py +0 -0
  97. {graphinate-0.2.17 → graphinate-0.2.19}/tests/graphinate/test_tools.py +0 -0
@@ -40,6 +40,6 @@ 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@v3
44
- env:
45
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
43
+ uses: codecov/codecov-action@v4
44
+ with:
45
+ token: ${{ secrets.CODECOV_TOKEN }}
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: Graphinate
3
- Version: 0.2.17
3
+ Version: 0.2.19
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
@@ -32,7 +32,7 @@ Requires-Dist: inflect==7.0.0
32
32
  Requires-Dist: loguru==0.7.2
33
33
  Requires-Dist: matplotlib==3.8.3
34
34
  Requires-Dist: networkx==3.2.1
35
- Requires-Dist: strawberry-graphql[asgi,opentelemetry]==0.220.0
35
+ Requires-Dist: strawberry-graphql[asgi,opentelemetry]==0.221.1
36
36
  Provides-Extra: dev
37
37
  Requires-Dist: pipdeptree; extra == 'dev'
38
38
  Requires-Dist: ruff; extra == 'dev'
@@ -48,7 +48,7 @@ Provides-Extra: plot
48
48
  Requires-Dist: scipy>=1.12.0; extra == 'plot'
49
49
  Provides-Extra: server
50
50
  Requires-Dist: starlette-prometheus; extra == 'server'
51
- Requires-Dist: uvicorn[standard]>=0.27.0; extra == 'server'
51
+ Requires-Dist: uvicorn[standard]>=0.29.0; extra == 'server'
52
52
  Provides-Extra: test
53
53
  Requires-Dist: faker>=23.2.1; extra == 'test'
54
54
  Requires-Dist: pytest-asyncio>=0.23.5; extra == 'test'
@@ -0,0 +1,15 @@
1
+ # System
2
+
3
+ ## Processes
4
+
5
+ === "Processes"
6
+
7
+ ``` python title="examples/system/processes.py" linenums="1"
8
+ --8<-- "examples/system/processes.py"
9
+ ```
10
+
11
+ === "Dependencies"
12
+
13
+ ``` text title="examples/system/requirements.txt" linenums="1"
14
+ --8<-- "examples/system/requirements.txt"
15
+ ```
@@ -0,0 +1 @@
1
+ pipdeptree>=2.13.0
@@ -0,0 +1,64 @@
1
+ import operator
2
+ from collections.abc import Iterable
3
+
4
+ import networkx as nx
5
+ import psutil
6
+
7
+ import graphinate
8
+
9
+
10
+ def processes_graph_model():
11
+ graph_model = graphinate.model("Processes Graph")
12
+
13
+ def processes() -> Iterable[psutil.Process]:
14
+ for pid in psutil.pids():
15
+ if psutil.pid_exists(pid):
16
+ yield psutil.Process(pid)
17
+
18
+ processes_list = [{'pid': p.pid, 'name': p.name(), 'parent_pid': p.parent().pid if p.parent() else None} for p in
19
+ processes()]
20
+
21
+ @graph_model.node(key=operator.itemgetter('pid'), label=operator.itemgetter('name'))
22
+ def process():
23
+ yield from processes_list
24
+
25
+ @graph_model.edge()
26
+ def edge():
27
+ for p in processes_list:
28
+ parent_pid = p.get('parent_pid')
29
+ if parent_pid:
30
+ yield {'source': p.get('pid'), 'target': parent_pid}
31
+
32
+ return graph_model
33
+
34
+
35
+ model = processes_graph_model()
36
+
37
+ if __name__ == '__main__':
38
+ use_materialize = True
39
+
40
+ if use_materialize:
41
+ # Materialize the GraphModel
42
+ graphinate.materialize(
43
+ model,
44
+ builder=graphinate.builders.GraphQLBuilder,
45
+ actualizer=graphinate.graphql
46
+ )
47
+
48
+ else:
49
+ # Or
50
+
51
+ # 1. Define Graph Builder
52
+ builder = graphinate.builders.NetworkxBuilder(model=model)
53
+
54
+ # Then
55
+ # 2. Build the Graph object
56
+ graph: nx.Graph = builder.build()
57
+
58
+ # Then
59
+ # 3. Option A - Output to console
60
+ print(graph)
61
+
62
+ # Or
63
+ # 3. Option B - Output as a plot
64
+ graphinate.materializers.plot(graph)
@@ -0,0 +1 @@
1
+ psutil>=5.9.8
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "Graphinate"
3
- version = "0.2.17"
3
+ version = "0.2.19"
4
4
  authors = [
5
5
  { name = "Eran Rivlis", email = "eran@rivlis.info" },
6
6
  ]
@@ -33,7 +33,7 @@ dependencies = [
33
33
  "loguru==0.7.2",
34
34
  "matplotlib==3.8.3",
35
35
  "networkx==3.2.1",
36
- "strawberry-graphql[asgi,opentelemetry]==0.220.0"
36
+ "strawberry-graphql[asgi,opentelemetry]==0.221.1"
37
37
  ]
38
38
 
39
39
 
@@ -71,7 +71,7 @@ plot = [
71
71
  ]
72
72
  server = [
73
73
  "starlette-prometheus",
74
- "uvicorn[standard]>=0.27.0"
74
+ "uvicorn[standard]>=0.29.0"
75
75
  ]
76
76
 
77
77
 
@@ -26,7 +26,7 @@ from strawberry.extensions import ParserCache, QueryDepthLimiter, ValidationCach
26
26
 
27
27
  from . import color
28
28
  from .modeling import UNIVERSE_NODE, GraphModel
29
- from .tools import converters, mutators
29
+ from .tools import converters, mutators, utcnow
30
30
  from .typing import NodeTypeAbsoluteId
31
31
 
32
32
  DEFAULT_NODE_DELIMITER = ' ∋ '
@@ -145,9 +145,9 @@ class NetworkxBuilder(Builder):
145
145
  super().__init__(model, graph_type)
146
146
 
147
147
  def _initialize_graph(self):
148
- self._graph = self.graph_type.value(name=self.model.name,
149
- node_types=Counter(),
150
- edge_types=Counter())
148
+ self._graph: nx.Graph = self.graph_type.value(name=self.model.name,
149
+ node_types=Counter(),
150
+ edge_types=Counter())
151
151
 
152
152
  def _graph_edges(self, data, default=None):
153
153
  params = {'data': data, 'default': default}
@@ -197,7 +197,7 @@ class NetworkxBuilder(Builder):
197
197
  if node_id in self._graph:
198
198
  self._graph.nodes[node_id]['value'].append(node.value)
199
199
  self._graph.nodes[node_id]['magnitude'] += 1
200
- self._graph.nodes[node_id]['updated'] = datetime.utcnow()
200
+ self._graph.nodes[node_id]['updated'] = utcnow()
201
201
  else:
202
202
  self._graph.add_node(node_id,
203
203
  label=label,
@@ -205,7 +205,7 @@ class NetworkxBuilder(Builder):
205
205
  value=[node.value],
206
206
  magnitude=1,
207
207
  lineage=list(node_lineage),
208
- created=datetime.utcnow())
208
+ created=utcnow())
209
209
 
210
210
  self._graph.graph['node_types'].update({node_type: 1})
211
211
 
@@ -213,7 +213,7 @@ class NetworkxBuilder(Builder):
213
213
  logger.debug("Adding edge from: '{}' to '{}'", parent_node_id, node_id)
214
214
  self._graph.add_edge(parent_node_id,
215
215
  node_id,
216
- created=datetime.utcnow())
216
+ created=utcnow())
217
217
 
218
218
  new_kwargs = kwargs.copy()
219
219
  new_kwargs[f"{node_type}_id"] = node.key
@@ -234,12 +234,12 @@ class NetworkxBuilder(Builder):
234
234
  type=edge_type,
235
235
  value=[edge.value],
236
236
  weight=edge_weight,
237
- created=datetime.utcnow())
237
+ created=utcnow())
238
238
  self._graph.graph['edge_types'].update({edge_type: 1})
239
239
  else:
240
240
  self._graph.edges[edge_id]['value'].append(edge.value)
241
241
  self._graph.edges[edge_id]['weight'] += edge_weight
242
- self._graph.edges[edge_id]['updated'] = datetime.utcnow()
242
+ self._graph.edges[edge_id]['updated'] = utcnow()
243
243
 
244
244
  def _rectify_node_attributes(self, **defaults):
245
245
 
@@ -294,7 +294,7 @@ class NetworkxBuilder(Builder):
294
294
  counter = self._graph.graph[counter_name]
295
295
  self._graph.graph[counter_name] = mutators.dictify(counter)
296
296
 
297
- self._graph.graph['created'] = datetime.utcnow()
297
+ self._graph.graph['created'] = utcnow()
298
298
 
299
299
  def build(self, **kwargs) -> GraphRepresentation:
300
300
  """
@@ -393,27 +393,60 @@ class GraphQLBuilder(NetworkxBuilder):
393
393
 
394
394
  @strawberry.type
395
395
  class Graph:
396
- graph: strawberry.Private[nx.Graph]
397
-
398
- name: str
399
- created: datetime
400
- hash: str
401
- node_type_counts: list['GraphQLBuilder.Measure']
402
- edge_type_counts: list['GraphQLBuilder.Measure']
403
- node_count: int
404
- edge_count: int
405
- order: int
406
- size: int
407
- # girth: int
408
- average_degree: float
396
+ nx_graph: strawberry.Private[nx.Graph]
409
397
 
410
398
  @strawberry.field()
411
399
  def radius(self) -> 'GraphQLBuilder.InfNumber':
412
- return nx.radius(self.graph) if nx.is_connected(self.graph) else math.inf
400
+ return nx.radius(self.nx_graph) if nx.is_connected(self.nx_graph) else math.inf
413
401
 
414
402
  @strawberry.field()
415
403
  def diameter(self) -> 'GraphQLBuilder.InfNumber':
416
- return nx.diameter(self.graph) if nx.is_connected(self.graph) else math.inf
404
+ return nx.diameter(self.nx_graph) if nx.is_connected(self.nx_graph) else math.inf
405
+
406
+ @strawberry.field()
407
+ def name(self) -> str:
408
+ return self.nx_graph.graph['name']
409
+
410
+ @strawberry.field()
411
+ def node_type_counts(self) -> list['GraphQLBuilder.Measure']:
412
+ return [GraphQLBuilder.Measure(name=t, value=c) for t, c in self.nx_graph.graph['node_types'].items()]
413
+
414
+ @strawberry.field()
415
+ def edge_type_counts(self) -> list['GraphQLBuilder.Measure']:
416
+ return [GraphQLBuilder.Measure(name=t, value=c) for t, c in self.nx_graph.graph['edge_types'].items()]
417
+
418
+ @strawberry.field()
419
+ def node_count(self) -> int:
420
+ return self.nx_graph.number_of_nodes()
421
+
422
+ @strawberry.field()
423
+ def edge_count(self) -> int:
424
+ return self.nx_graph.number_of_edges()
425
+
426
+ @strawberry.field()
427
+ def order(self) -> int:
428
+ return self.nx_graph.order()
429
+
430
+ @strawberry.field()
431
+ def size(self) -> int:
432
+ return self.nx_graph.size(weight='weight')
433
+
434
+ # @strawberry.field()
435
+ # def girth(self) -> int:
436
+ # return min(len(cycle) for cycle in nx.simple_cycles(self.graph))
437
+
438
+ @strawberry.field()
439
+ def average_degree(self) -> float:
440
+ return self.nx_graph.number_of_nodes() and (
441
+ 1.0 * sum(d for _, d in self.nx_graph.degree()) / self.nx_graph.number_of_nodes())
442
+
443
+ @strawberry.field()
444
+ def hash(self) -> str:
445
+ return nx.weisfeiler_lehman_graph_hash(self.nx_graph)
446
+
447
+ @strawberry.field()
448
+ def created(self) -> datetime:
449
+ return self.nx_graph.graph['created']
417
450
 
418
451
  @strawberry.enum(description="""
419
452
  See NetworkX documentation for explanations:
@@ -599,24 +632,7 @@ class GraphQLBuilder(NetworkxBuilder):
599
632
 
600
633
  # region - Defining GraphQL Query Class dict - graph field
601
634
  def graphql_graph(self) -> GraphQLBuilder.Graph:
602
- graph = get_graph()
603
- return GraphQLBuilder.Graph(
604
- graph=graph,
605
- name=graph.graph['name'],
606
- node_type_counts=[GraphQLBuilder.Measure(name=t, value=c) for t, c in
607
- graph.graph['node_types'].items()],
608
- edge_type_counts=[GraphQLBuilder.Measure(name=t, value=c) for t, c in
609
- graph.graph['edge_types'].items()],
610
- node_count=graph.number_of_nodes(),
611
- edge_count=graph.number_of_edges(),
612
- order=graph.order(),
613
- size=graph.size(weight='weight'),
614
- # girth=min(len(cycle) for cycle in nx.simple_cycles(graph)),
615
- average_degree=graph.number_of_nodes() and (
616
- 1.0 * sum(d for _, d in graph.degree()) / graph.number_of_nodes()),
617
- hash=nx.weisfeiler_lehman_graph_hash(graph),
618
- created=graph.graph['created'],
619
- )
635
+ return GraphQLBuilder.Graph(nx_graph=get_graph())
620
636
 
621
637
  self.add_field_resolver(query_class_dict, 'graph', graphql_graph)
622
638
 
@@ -1,9 +1,10 @@
1
- <!doctype html>
1
+ <!DOCTYPE html>
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6
- <title>Graphinate OpenAPI Elements UI</title>
6
+
7
+ <title>Graphinate - OpanAPI Elements UI</title>
7
8
  <!-- Embed elements Elements via Web Component -->
8
9
  <script src="https://unpkg.com/@stoplight/elements/web-components.min.js"
9
10
  integrity="sha384-yR4p7dGVb43Z+zDGOg8xyIj71nVRZvN/IpUbptwjAtxcq+IcVQ+mNMiL7ppakjKc"></script>
@@ -151,7 +151,7 @@
151
151
  });
152
152
  }
153
153
 
154
- ReactDOM.createRenderRoot(
154
+ ReactDOM.render(
155
155
  React.createElement(GraphiQLWithExplorer),
156
156
  document.getElementById("graphiql")
157
157
  );
@@ -4,7 +4,7 @@
4
4
  <meta charset="utf-8"> <!-- Important: rapi-doc uses utf8 characters -->
5
5
  <script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"
6
6
  integrity="sha384-x8lk+1kqb32UOR4ETiOR+bpfZZtNri15JJdU7sXAKtHk2m9yMRVvITZcxS0ILJpC"></script>
7
- <title>Graphinate OpenAPI RapiDoc UI</title>
7
+ <title>Graphinate - OpenAPI RapiDoc UI</title>
8
8
  </head>
9
9
  <body>
10
10
  <rapi-doc
@@ -4,8 +4,9 @@
4
4
  <title>Graphinate</title>
5
5
  <style> body { margin: 0; } </style>
6
6
  <script src="https://cdn.jsdelivr.net/npm/3d-force-graph@1.72.3/dist/3d-force-graph.min.js"
7
- integrity="sha384-oGNXGez54SiNIIRSFWGVG0UJ9MIswOOsd/MbPZVNZFy+ykbIp1A7Ge5liZVo5oQK"
7
+ integrity="sha256-X4nSjPQnyc5QqQ88WM5oVzMx2KUKXj3hxRAvt2WxDRI="
8
8
  crossorigin="anonymous"></script>
9
+
9
10
  <script src="/static/scripts/murmurhash3_gc.js"
10
11
  integrity="sha384-qmbe8KG4+frUnGS6DOKYZgFKbBvbhNNOL/LZ4hSpKauxmgrTX3LALg5+oQJS4AOn"></script>
11
12
  </head>
@@ -0,0 +1,5 @@
1
+ from datetime import datetime, timezone
2
+
3
+
4
+ def utcnow() -> datetime:
5
+ return datetime.now(timezone.utc)
@@ -1,10 +1,11 @@
1
1
  import functools
2
2
  from unittest.mock import patch
3
3
 
4
- import graphinate
5
4
  import pytest
6
5
  from matplotlib import pyplot as plt
7
6
 
7
+ import graphinate
8
+
8
9
  MODAL_RADIOBUTTON_CHOOSER = 'graphinate.materializers.modal_radiobutton_chooser'
9
10
 
10
11
 
@@ -33,6 +34,11 @@ def test_materialize_d3graph(map_graph_model, monkeypatch, capsys):
33
34
  assert captured.err == ""
34
35
 
35
36
 
37
+ def valid_materialization(graph_model) -> bool:
38
+ graphinate.materialize(graph_model)
39
+ return True
40
+
41
+
36
42
  def test_materialize_graphql(map_graph_model, monkeypatch):
37
43
  with patch(MODAL_RADIOBUTTON_CHOOSER) as modal_radiobutton_chooser:
38
44
  import uvicorn
@@ -40,8 +46,8 @@ def test_materialize_graphql(map_graph_model, monkeypatch):
40
46
  modal_radiobutton_chooser.return_value = ('Test', graphinate.materializers.Materializers.GraphQL.value)
41
47
 
42
48
  *_, graph_model = map_graph_model
43
- graphinate.materialize(graph_model)
44
- assert True
49
+
50
+ assert valid_materialization(graph_model)
45
51
 
46
52
 
47
53
  networkx_materializers = [
@@ -49,7 +55,6 @@ networkx_materializers = [
49
55
  graphinate.materializers.Materializers.NetworkX_with_edge_labels.value,
50
56
  (graphinate.builders.NetworkxBuilder,
51
57
  functools.partial(graphinate.materializers.matplotlib.plot, with_node_labels=False))
52
-
53
58
  ]
54
59
 
55
60
 
@@ -60,8 +65,7 @@ def test_materialize_networkx(map_graph_model, materializer, monkeypatch):
60
65
  with patch('graphinate.materializers.modal_radiobutton_chooser') as modal_radiobutton_chooser:
61
66
  modal_radiobutton_chooser.return_value = ('Test', materializer)
62
67
  *_, graph_model = map_graph_model
63
- graphinate.materialize(graph_model)
64
- assert True
68
+ assert valid_materialization(graph_model)
65
69
 
66
70
 
67
71
  def test_materialize_none(map_graph_model, monkeypatch):
@@ -1 +0,0 @@
1
- pipdeptree==2.13.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes