Graphinate 0.2.16__tar.gz → 0.2.18__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 (93) hide show
  1. {graphinate-0.2.16 → graphinate-0.2.18}/.github/workflows/publish-docs.yaml +1 -1
  2. {graphinate-0.2.16 → graphinate-0.2.18}/.github/workflows/publish.yml +1 -1
  3. {graphinate-0.2.16 → graphinate-0.2.18}/.github/workflows/test-beta.yml +1 -1
  4. {graphinate-0.2.16 → graphinate-0.2.18}/.github/workflows/test.yml +4 -4
  5. {graphinate-0.2.16 → graphinate-0.2.18}/PKG-INFO +10 -12
  6. {graphinate-0.2.16 → graphinate-0.2.18}/README.md +4 -3
  7. {graphinate-0.2.16 → graphinate-0.2.18}/docs/index.md +6 -5
  8. {graphinate-0.2.16 → graphinate-0.2.18}/pyproject.toml +5 -9
  9. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/builders.py +61 -46
  10. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/web/elements/index.html +3 -2
  11. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/web/rapidoc/index.html +1 -1
  12. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/web/viewer/index.html +2 -2
  13. graphinate-0.2.18/src/graphinate/tools/__init__.py +5 -0
  14. {graphinate-0.2.16 → graphinate-0.2.18}/tests/graphinate/test_materializers.py +10 -6
  15. graphinate-0.2.16/src/graphinate/tools/__init__.py +0 -0
  16. {graphinate-0.2.16 → graphinate-0.2.18}/.coveragerc +0 -0
  17. {graphinate-0.2.16 → graphinate-0.2.18}/.github/dependabot.yml +0 -0
  18. {graphinate-0.2.16 → graphinate-0.2.18}/.github/workflows/codeql.yml +0 -0
  19. {graphinate-0.2.16 → graphinate-0.2.18}/.gitignore +0 -0
  20. {graphinate-0.2.16 → graphinate-0.2.18}/LICENSE +0 -0
  21. {graphinate-0.2.16 → graphinate-0.2.18}/STATS.md +0 -0
  22. {graphinate-0.2.16 → graphinate-0.2.18}/docs/acknowledge.md +0 -0
  23. {graphinate-0.2.16 → graphinate-0.2.18}/docs/assets/images/logo-128.png +0 -0
  24. {graphinate-0.2.16 → graphinate-0.2.18}/docs/assets/images/network_graph.png +0 -0
  25. {graphinate-0.2.16 → graphinate-0.2.18}/docs/assets/stylesheets/extra.css +0 -0
  26. {graphinate-0.2.16 → graphinate-0.2.18}/docs/dev.md +0 -0
  27. {graphinate-0.2.16 → graphinate-0.2.18}/docs/examples/code.md +0 -0
  28. {graphinate-0.2.16 → graphinate-0.2.18}/docs/examples/github.md +0 -0
  29. {graphinate-0.2.16 → graphinate-0.2.18}/docs/examples/math.md +0 -0
  30. {graphinate-0.2.16 → graphinate-0.2.18}/docs/examples/web.md +0 -0
  31. {graphinate-0.2.16 → graphinate-0.2.18}/docs/gen_ref_pages.py +0 -0
  32. {graphinate-0.2.16 → graphinate-0.2.18}/docs/intro.md +0 -0
  33. {graphinate-0.2.16 → graphinate-0.2.18}/docs/start.md +0 -0
  34. {graphinate-0.2.16 → graphinate-0.2.18}/docs/usage/cli.md +0 -0
  35. {graphinate-0.2.16 → graphinate-0.2.18}/docs/usage/lib.md +0 -0
  36. {graphinate-0.2.16 → graphinate-0.2.18}/examples/code/python_ast.py +0 -0
  37. {graphinate-0.2.16 → graphinate-0.2.18}/examples/code/python_dependencies.py +0 -0
  38. {graphinate-0.2.16 → graphinate-0.2.18}/examples/code/requirements.txt +0 -0
  39. {graphinate-0.2.16 → graphinate-0.2.18}/examples/github/_client.py +0 -0
  40. {graphinate-0.2.16 → graphinate-0.2.18}/examples/github/commits_visibilty_graph.py +0 -0
  41. {graphinate-0.2.16 → graphinate-0.2.18}/examples/github/followers.graphql +0 -0
  42. {graphinate-0.2.16 → graphinate-0.2.18}/examples/github/followers.py +0 -0
  43. {graphinate-0.2.16 → graphinate-0.2.18}/examples/github/graphql.config.yml +0 -0
  44. {graphinate-0.2.16 → graphinate-0.2.18}/examples/github/repositories.graphql +0 -0
  45. {graphinate-0.2.16 → graphinate-0.2.18}/examples/github/repositories.py +0 -0
  46. {graphinate-0.2.16 → graphinate-0.2.18}/examples/github/requirements.txt +0 -0
  47. {graphinate-0.2.16 → graphinate-0.2.18}/examples/math/graph_atlas.py +0 -0
  48. {graphinate-0.2.16 → graphinate-0.2.18}/examples/math/polygonal_graph.py +0 -0
  49. {graphinate-0.2.16 → graphinate-0.2.18}/examples/web/page_links.py +0 -0
  50. {graphinate-0.2.16 → graphinate-0.2.18}/examples/web/requirements.txt +0 -0
  51. {graphinate-0.2.16 → graphinate-0.2.18}/mkdocs.yml +0 -0
  52. {graphinate-0.2.16 → graphinate-0.2.18}/playground/ethernet/traceroute.py +0 -0
  53. {graphinate-0.2.16 → graphinate-0.2.18}/playground/genric_graph.graphql +0 -0
  54. {graphinate-0.2.16 → graphinate-0.2.18}/playground/graphql.config.yml +0 -0
  55. {graphinate-0.2.16 → graphinate-0.2.18}/playground/house_of_graphs.py +0 -0
  56. {graphinate-0.2.16 → graphinate-0.2.18}/playground/social/albums.json +0 -0
  57. {graphinate-0.2.16 → graphinate-0.2.18}/playground/social/musicisians.py +0 -0
  58. {graphinate-0.2.16 → graphinate-0.2.18}/playground/text/nlp_graph.py +0 -0
  59. {graphinate-0.2.16 → graphinate-0.2.18}/playground/text/requirements.txt +0 -0
  60. {graphinate-0.2.16 → graphinate-0.2.18}/playground/time_series/requirements.txt +0 -0
  61. {graphinate-0.2.16 → graphinate-0.2.18}/playground/time_series/visibility_graph.py +0 -0
  62. {graphinate-0.2.16 → graphinate-0.2.18}/sonar-project.properties +0 -0
  63. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/__init__.py +0 -0
  64. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/__main__.py +0 -0
  65. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/cli.py +0 -0
  66. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/color.py +0 -0
  67. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/materializers/__init__.py +0 -0
  68. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/materializers/matplotlib.py +0 -0
  69. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/modeling.py +0 -0
  70. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/__init__.py +0 -0
  71. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/starlette/__init__.py +0 -0
  72. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/starlette/views.py +0 -0
  73. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/web/__init__.py +0 -0
  74. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/web/elements/__init__.py +0 -0
  75. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/web/graphiql/__init__.py +0 -0
  76. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/web/graphiql/index.html +0 -0
  77. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/web/rapidoc/__init__.py +0 -0
  78. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/web/static/images/logo-128.png +0 -0
  79. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/web/static/images/network_graph.png +0 -0
  80. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/web/viewer/__init__.py +0 -0
  81. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/web/voyager/__init__.py +0 -0
  82. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/server/web/voyager/index.html +0 -0
  83. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/tools/converters.py +0 -0
  84. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/tools/gui.py +0 -0
  85. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/tools/mutators.py +0 -0
  86. {graphinate-0.2.16 → graphinate-0.2.18}/src/graphinate/typing.py +0 -0
  87. {graphinate-0.2.16 → graphinate-0.2.18}/tests/conftest.py +0 -0
  88. {graphinate-0.2.16 → graphinate-0.2.18}/tests/graphinate/test_builders.py +0 -0
  89. {graphinate-0.2.16 → graphinate-0.2.18}/tests/graphinate/test_cli.py +0 -0
  90. {graphinate-0.2.16 → graphinate-0.2.18}/tests/graphinate/test_color.py +0 -0
  91. {graphinate-0.2.16 → graphinate-0.2.18}/tests/graphinate/test_modeling.py +0 -0
  92. {graphinate-0.2.16 → graphinate-0.2.18}/tests/graphinate/test_server.py +0 -0
  93. {graphinate-0.2.16 → graphinate-0.2.18}/tests/graphinate/test_tools.py +0 -0
@@ -10,7 +10,7 @@ jobs:
10
10
  runs-on: ubuntu-latest
11
11
  steps:
12
12
  - uses: actions/checkout@v4
13
- - uses: actions/setup-python@v4
13
+ - uses: actions/setup-python@v5
14
14
  with:
15
15
  python-version: 3.x
16
16
  - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
@@ -18,7 +18,7 @@ jobs:
18
18
  steps:
19
19
  - uses: actions/checkout@v4
20
20
  - name: Set up Python
21
- uses: actions/setup-python@v4
21
+ uses: actions/setup-python@v5
22
22
  with:
23
23
  python-version: '3.x'
24
24
  - name: Install dependencies
@@ -19,7 +19,7 @@ jobs:
19
19
  steps:
20
20
  - uses: actions/checkout@v4
21
21
  - name: Set up Python ${{ matrix.python-version }}
22
- uses: actions/setup-python@v4
22
+ uses: actions/setup-python@v5
23
23
  with:
24
24
  python-version: ${{ matrix.python-version }}
25
25
  - name: Install dependencies
@@ -19,7 +19,7 @@ jobs:
19
19
  steps:
20
20
  - uses: actions/checkout@v4
21
21
  - name: Set up Python ${{ matrix.python-version }}
22
- uses: actions/setup-python@v4
22
+ uses: actions/setup-python@v5
23
23
  with:
24
24
  python-version: ${{ matrix.python-version }}
25
25
  - name: Install dependencies
@@ -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.16
3
+ Version: 0.2.18
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,10 +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.219.2
36
- Provides-Extra: dbs
37
- Requires-Dist: neo4j>=5.17.0; extra == 'dbs'
38
- Requires-Dist: pydgraph>=23.0.2; extra == 'dbs'
35
+ Requires-Dist: strawberry-graphql[asgi,opentelemetry]==0.221.1
39
36
  Provides-Extra: dev
40
37
  Requires-Dist: pipdeptree; extra == 'dev'
41
38
  Requires-Dist: ruff; extra == 'dev'
@@ -51,14 +48,14 @@ Provides-Extra: plot
51
48
  Requires-Dist: scipy>=1.12.0; extra == 'plot'
52
49
  Provides-Extra: server
53
50
  Requires-Dist: starlette-prometheus; extra == 'server'
54
- Requires-Dist: uvicorn[standard]>=0.27.0; extra == 'server'
51
+ Requires-Dist: uvicorn[standard]>=0.29.0; extra == 'server'
55
52
  Provides-Extra: test
56
53
  Requires-Dist: faker>=23.2.1; extra == 'test'
57
- Requires-Dist: pytest-asyncio>=0.23.4; extra == 'test'
54
+ Requires-Dist: pytest-asyncio>=0.23.5; extra == 'test'
58
55
  Requires-Dist: pytest-cov>=4.1.0; extra == 'test'
59
56
  Requires-Dist: pytest-randomly>=3.15.0; extra == 'test'
60
57
  Requires-Dist: pytest-xdist>=3.5.0; extra == 'test'
61
- Requires-Dist: pytest>=7.4.4; extra == 'test'
58
+ Requires-Dist: pytest>=8.1.1; extra == 'test'
62
59
  Description-Content-Type: text/markdown
63
60
 
64
61
  # [Graphinate. Data to Graphs.](https://erivlis.github.io/graphinate/)
@@ -78,15 +75,16 @@ Description-Content-Type: text/markdown
78
75
  <img alt="GitHub repo size" src="https://img.shields.io/github/repo-size/erivlis/graphinate">
79
76
  <img alt="GitHub last commit (by committer)" src="https://img.shields.io/github/last-commit/erivlis/graphinate">
80
77
  <a href="https://github.com/erivlis/graphinate/graphs/contributors"><img alt="Contributors" src="https://img.shields.io/github/contributors/erivlis/graphinate.svg"></a>
81
- <img alt="GitHub Watchers" src="https://img.shields.io/github/watchers/erivlis/graphinate.svg">
82
78
  </td>
83
79
  </tr>
84
80
  <tr>
85
81
  <td>Tools</td>
86
82
  <td>
87
- <img alt="Static Badge" src="https://img.shields.io/badge/PyCharm-21D789.svg?logo=PyCharm&logoColor=black&labelColor=21D789&color=FCF84A">
83
+ <a href="https://www.jetbrains.com/pycharm/"><img alt="PyCharm" src="https://img.shields.io/badge/PyCharm-FCF84A.svg?logo=PyCharm&logoColor=black&labelColor=21D789&color=FCF84A"></a>
88
84
  <a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff" style="max-width:100%;"></a>
89
- <a href="https://github.com/astral-sh/uv"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json" alt="Ruff" style="max-width:100%;"></a>
85
+ <a href="https://github.com/astral-sh/uv"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json" alt="uv" style="max-width:100%;"></a>
86
+ <a href="https://squidfunk.github.io/mkdocs-material/"><img src="https://img.shields.io/badge/Material_for_MkDocs-526CFE?&logo=MaterialForMkDocs&logoColor=white&labelColor=grey"></a>
87
+ <a href="https://github.com/tox-dev/pipdeptree"><img src="https://img.shields.io/badge/pipdeptree-526CFE.svg?labelColor=gray&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADFElEQVR4nFxTW2tcVRRe39773E/mliZjwKRmhBaKt4BWRKmGgihCH3xUKNWC/Q/ii76IP8AHpSIiRfqmD5YKCinalhgiCMZLSVtMM0mTdDLTuZyZc9l7yTlp7WXBgXPW+fa31rfWtxU9FLMN79Crr028e+iJsZfb7fJMp23xRlOvbTR3L/y5cuOL3Vbv7/vxuPviecI/eWr6k/mj4+8AkM11y+zs2MKwMJvNgIgYINZX/rlx+tIvf72fZXr4P0EQyOCjjw98P9vwn8+/+z3Bq6sek7AJkNhsOjQcyjvFmHd2upd+PP/zsSxNI5mnPvjw8U9fPFJ9XVkgNuDVayEbcgVEfgikNfFg4JAmh1LyyfGq06QqE9vN6+fEs4fHnjv25vjbAOA4AsL2MVZ1hRcI4QXIH7ilMqQXkiYXRBJRbFNQnTsRlqfmxFvH66ccFyAQMxP3I5cqNZBSxIWcKORMO9g3yeSHzFkGbnVCIkDUZ+beEy+8VJ4XguC6TMPYokwrCAHUJsBxYptoFBYSMi0oLIlcAkuFYhal8Zl5VanZU0zErgfurufMFjEkWZ7iRFY4SlgYfW9bUIJKFQNjiNPYf1QZOZn/hTaStPQKTI4eDCxSjsL4I6BeJzOjgcnT0HqPqwBJCdHZjW/miWjkkG3hzqKIe5FVlM3llGuWqOxTDMBkWlJ/6PB2p0Sb21gXixdvLeTtDGOHLFvQHpkiYyTuNU5kuxJercTdpEK3Bz4yLdFrXVsQ33x1/bModjhvyrKKVXB/YD9gb8PgKAlolAZipmFTOIYcxq21Xz8XS5dbi+e+2zqbA3MjxYninH3PpkyZljwYjZE2FoxBIWm6YVHaW/k66qwtF05curz509OHHzvqBqWp232fE+2AoCjOXNMfhcRcjAxxoijNFNpbG0vL588cNzpLC4I00cnCD1fPBuVqffbA5DMGNjR5MOSBpC+UYxGE5G5PmNXff/vy4rdnTmRJHD1wG+9G42D9qVfeePLk/oONI8qv7+/2fbq11f53ZfnqhStLi6d3b67/cT/+vwAAAP//Xo5dwOtdLi4AAAAASUVORK5CYII="></a>
90
88
  </td>
91
89
  </tr>
92
90
  <tr>
@@ -15,15 +15,16 @@
15
15
  <img alt="GitHub repo size" src="https://img.shields.io/github/repo-size/erivlis/graphinate">
16
16
  <img alt="GitHub last commit (by committer)" src="https://img.shields.io/github/last-commit/erivlis/graphinate">
17
17
  <a href="https://github.com/erivlis/graphinate/graphs/contributors"><img alt="Contributors" src="https://img.shields.io/github/contributors/erivlis/graphinate.svg"></a>
18
- <img alt="GitHub Watchers" src="https://img.shields.io/github/watchers/erivlis/graphinate.svg">
19
18
  </td>
20
19
  </tr>
21
20
  <tr>
22
21
  <td>Tools</td>
23
22
  <td>
24
- <img alt="Static Badge" src="https://img.shields.io/badge/PyCharm-21D789.svg?logo=PyCharm&logoColor=black&labelColor=21D789&color=FCF84A">
23
+ <a href="https://www.jetbrains.com/pycharm/"><img alt="PyCharm" src="https://img.shields.io/badge/PyCharm-FCF84A.svg?logo=PyCharm&logoColor=black&labelColor=21D789&color=FCF84A"></a>
25
24
  <a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff" style="max-width:100%;"></a>
26
- <a href="https://github.com/astral-sh/uv"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json" alt="Ruff" style="max-width:100%;"></a>
25
+ <a href="https://github.com/astral-sh/uv"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json" alt="uv" style="max-width:100%;"></a>
26
+ <a href="https://squidfunk.github.io/mkdocs-material/"><img src="https://img.shields.io/badge/Material_for_MkDocs-526CFE?&logo=MaterialForMkDocs&logoColor=white&labelColor=grey"></a>
27
+ <a href="https://github.com/tox-dev/pipdeptree"><img src="https://img.shields.io/badge/pipdeptree-526CFE.svg?labelColor=gray&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADFElEQVR4nFxTW2tcVRRe39773E/mliZjwKRmhBaKt4BWRKmGgihCH3xUKNWC/Q/ii76IP8AHpSIiRfqmD5YKCinalhgiCMZLSVtMM0mTdDLTuZyZc9l7yTlp7WXBgXPW+fa31rfWtxU9FLMN79Crr028e+iJsZfb7fJMp23xRlOvbTR3L/y5cuOL3Vbv7/vxuPviecI/eWr6k/mj4+8AkM11y+zs2MKwMJvNgIgYINZX/rlx+tIvf72fZXr4P0EQyOCjjw98P9vwn8+/+z3Bq6sek7AJkNhsOjQcyjvFmHd2upd+PP/zsSxNI5mnPvjw8U9fPFJ9XVkgNuDVayEbcgVEfgikNfFg4JAmh1LyyfGq06QqE9vN6+fEs4fHnjv25vjbAOA4AsL2MVZ1hRcI4QXIH7ilMqQXkiYXRBJRbFNQnTsRlqfmxFvH66ccFyAQMxP3I5cqNZBSxIWcKORMO9g3yeSHzFkGbnVCIkDUZ+beEy+8VJ4XguC6TMPYokwrCAHUJsBxYptoFBYSMi0oLIlcAkuFYhal8Zl5VanZU0zErgfurufMFjEkWZ7iRFY4SlgYfW9bUIJKFQNjiNPYf1QZOZn/hTaStPQKTI4eDCxSjsL4I6BeJzOjgcnT0HqPqwBJCdHZjW/miWjkkG3hzqKIe5FVlM3llGuWqOxTDMBkWlJ/6PB2p0Sb21gXixdvLeTtDGOHLFvQHpkiYyTuNU5kuxJercTdpEK3Bz4yLdFrXVsQ33x1/bModjhvyrKKVXB/YD9gb8PgKAlolAZipmFTOIYcxq21Xz8XS5dbi+e+2zqbA3MjxYninH3PpkyZljwYjZE2FoxBIWm6YVHaW/k66qwtF05curz509OHHzvqBqWp232fE+2AoCjOXNMfhcRcjAxxoijNFNpbG0vL588cNzpLC4I00cnCD1fPBuVqffbA5DMGNjR5MOSBpC+UYxGE5G5PmNXff/vy4rdnTmRJHD1wG+9G42D9qVfeePLk/oONI8qv7+/2fbq11f53ZfnqhStLi6d3b67/cT/+vwAAAP//Xo5dwOtdLi4AAAAASUVORK5CYII="></a>
27
28
  </td>
28
29
  </tr>
29
30
  <tr>
@@ -17,15 +17,16 @@
17
17
  <img alt="GitHub Watchers" src="https://img.shields.io/github/watchers/erivlis/graphinate.svg">
18
18
  </td>
19
19
  </tr>
20
- <tr>
20
+ <tr style="vertical-align: middle; border-width: 0;">
21
21
  <td>Tools</td>
22
22
  <td>
23
- <img alt="Static Badge" src="https://img.shields.io/badge/PyCharm-21D789.svg?logo=PyCharm&logoColor=black&labelColor=21D789&color=FCF84A">
23
+ <a href="https://www.jetbrains.com/pycharm/"><img alt="PyCharm" src="https://img.shields.io/badge/PyCharm-FCF84A.svg?logo=PyCharm&logoColor=black&labelColor=21D789&color=FCF84A"></a>
24
24
  <a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff" style="max-width:100%;"></a>
25
- <a href="https://github.com/astral-sh/uv"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json" alt="Ruff" style="max-width:100%;"></a>
25
+ <a href="https://github.com/astral-sh/uv"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json" alt="uv" style="max-width:100%;"></a>
26
+ <a href="https://github.com/tox-dev/pipdeptree"><img src="https://img.shields.io/badge/pipdeptree-526CFE.svg?labelColor=gray&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADFElEQVR4nFxTW2tcVRRe39773E/mliZjwKRmhBaKt4BWRKmGgihCH3xUKNWC/Q/ii76IP8AHpSIiRfqmD5YKCinalhgiCMZLSVtMM0mTdDLTuZyZc9l7yTlp7WXBgXPW+fa31rfWtxU9FLMN79Crr028e+iJsZfb7fJMp23xRlOvbTR3L/y5cuOL3Vbv7/vxuPviecI/eWr6k/mj4+8AkM11y+zs2MKwMJvNgIgYINZX/rlx+tIvf72fZXr4P0EQyOCjjw98P9vwn8+/+z3Bq6sek7AJkNhsOjQcyjvFmHd2upd+PP/zsSxNI5mnPvjw8U9fPFJ9XVkgNuDVayEbcgVEfgikNfFg4JAmh1LyyfGq06QqE9vN6+fEs4fHnjv25vjbAOA4AsL2MVZ1hRcI4QXIH7ilMqQXkiYXRBJRbFNQnTsRlqfmxFvH66ccFyAQMxP3I5cqNZBSxIWcKORMO9g3yeSHzFkGbnVCIkDUZ+beEy+8VJ4XguC6TMPYokwrCAHUJsBxYptoFBYSMi0oLIlcAkuFYhal8Zl5VanZU0zErgfurufMFjEkWZ7iRFY4SlgYfW9bUIJKFQNjiNPYf1QZOZn/hTaStPQKTI4eDCxSjsL4I6BeJzOjgcnT0HqPqwBJCdHZjW/miWjkkG3hzqKIe5FVlM3llGuWqOxTDMBkWlJ/6PB2p0Sb21gXixdvLeTtDGOHLFvQHpkiYyTuNU5kuxJercTdpEK3Bz4yLdFrXVsQ33x1/bModjhvyrKKVXB/YD9gb8PgKAlolAZipmFTOIYcxq21Xz8XS5dbi+e+2zqbA3MjxYninH3PpkyZljwYjZE2FoxBIWm6YVHaW/k66qwtF05curz509OHHzvqBqWp232fE+2AoCjOXNMfhcRcjAxxoijNFNpbG0vL588cNzpLC4I00cnCD1fPBuVqffbA5DMGNjR5MOSBpC+UYxGE5G5PmNXff/vy4rdnTmRJHD1wG+9G42D9qVfeePLk/oONI8qv7+/2fbq11f53ZfnqhStLi6d3b67/cT/+vwAAAP//Xo5dwOtdLi4AAAAASUVORK5CYII="></a>
26
27
  </td>
27
28
  </tr>
28
- <tr>
29
+ <tr style="vertical-align: middle; border-width: 0;">
29
30
  <td>CI/CD</td>
30
31
  <td>
31
32
  <a href="https://github.com/erivlis/graphinate/actions/workflows/test.yml"><img alt="Tests" src="https://github.com/erivlis/graphinate/actions/workflows/test.yml/badge.svg?branch=master"></a>
@@ -33,7 +34,7 @@
33
34
  <a href="https://github.com/erivlis/graphinate/actions/workflows/publish-docs.yaml"><img alt="Publish Docs" src="https://github.com/erivlis/graphinate/actions/workflows/publish-docs.yaml/badge.svg"></a>
34
35
  </td>
35
36
  </tr>
36
- <tr>
37
+ <tr style="vertical-align: middle; border-width: 0;">
37
38
  <td>Scans</td>
38
39
  <td>
39
40
  <a href="https://codecov.io/gh/erivlis/graphinate"><img alt="Coverage" src="https://codecov.io/gh/erivlis/graphinate/graph/badge.svg?token=POODT8M9NV"/></a>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "Graphinate"
3
- version = "0.2.16"
3
+ version = "0.2.18"
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.219.2"
36
+ "strawberry-graphql[asgi,opentelemetry]==0.221.1"
37
37
  ]
38
38
 
39
39
 
@@ -60,22 +60,18 @@ docs = [
60
60
  ]
61
61
  test = [
62
62
  "faker>=23.2.1",
63
- "pytest>=7.4.4",
64
- "pytest-asyncio>=0.23.4",
63
+ "pytest>=8.1.1",
64
+ "pytest-asyncio>=0.23.5",
65
65
  "pytest-cov>=4.1.0",
66
66
  "pytest-randomly>=3.15.0",
67
67
  "pytest-xdist>=3.5.0"
68
68
  ]
69
- dbs = [
70
- "pydgraph>=23.0.2",
71
- "neo4j>=5.17.0"
72
- ]
73
69
  plot = [
74
70
  "scipy>=1.12.0"
75
71
  ]
76
72
  server = [
77
73
  "starlette-prometheus",
78
- "uvicorn[standard]>=0.27.0"
74
+ "uvicorn[standard]>=0.29.0"
79
75
  ]
80
76
 
81
77
 
@@ -26,12 +26,14 @@ 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 = ' ∋ '
33
33
  DEFAULT_EDGE_DELIMITER = ' ↔ '
34
34
 
35
+ GraphRepresentation = Union[dict, nx.Graph, strawberry.Schema]
36
+
35
37
 
36
38
  def label_converter(value, delimiter: str):
37
39
  if value:
@@ -101,9 +103,6 @@ class GraphType(Enum):
101
103
  MultiGraph = nx.MultiGraph
102
104
 
103
105
 
104
- GraphRepresentation = Union[dict, nx.Graph, strawberry.Schema]
105
-
106
-
107
106
  class Builder(ABC):
108
107
  """Builder abstract base class"""
109
108
 
@@ -146,9 +145,9 @@ class NetworkxBuilder(Builder):
146
145
  super().__init__(model, graph_type)
147
146
 
148
147
  def _initialize_graph(self):
149
- self._graph = self.graph_type.value(name=self.model.name,
150
- node_types=Counter(),
151
- edge_types=Counter())
148
+ self._graph: nx.Graph = self.graph_type.value(name=self.model.name,
149
+ node_types=Counter(),
150
+ edge_types=Counter())
152
151
 
153
152
  def _graph_edges(self, data, default=None):
154
153
  params = {'data': data, 'default': default}
@@ -198,7 +197,7 @@ class NetworkxBuilder(Builder):
198
197
  if node_id in self._graph:
199
198
  self._graph.nodes[node_id]['value'].append(node.value)
200
199
  self._graph.nodes[node_id]['magnitude'] += 1
201
- self._graph.nodes[node_id]['updated'] = datetime.utcnow()
200
+ self._graph.nodes[node_id]['updated'] = utcnow()
202
201
  else:
203
202
  self._graph.add_node(node_id,
204
203
  label=label,
@@ -206,7 +205,7 @@ class NetworkxBuilder(Builder):
206
205
  value=[node.value],
207
206
  magnitude=1,
208
207
  lineage=list(node_lineage),
209
- created=datetime.utcnow())
208
+ created=utcnow())
210
209
 
211
210
  self._graph.graph['node_types'].update({node_type: 1})
212
211
 
@@ -214,7 +213,7 @@ class NetworkxBuilder(Builder):
214
213
  logger.debug("Adding edge from: '{}' to '{}'", parent_node_id, node_id)
215
214
  self._graph.add_edge(parent_node_id,
216
215
  node_id,
217
- created=datetime.utcnow())
216
+ created=utcnow())
218
217
 
219
218
  new_kwargs = kwargs.copy()
220
219
  new_kwargs[f"{node_type}_id"] = node.key
@@ -235,12 +234,12 @@ class NetworkxBuilder(Builder):
235
234
  type=edge_type,
236
235
  value=[edge.value],
237
236
  weight=edge_weight,
238
- created=datetime.utcnow())
237
+ created=utcnow())
239
238
  self._graph.graph['edge_types'].update({edge_type: 1})
240
239
  else:
241
240
  self._graph.edges[edge_id]['value'].append(edge.value)
242
241
  self._graph.edges[edge_id]['weight'] += edge_weight
243
- self._graph.edges[edge_id]['updated'] = datetime.utcnow()
242
+ self._graph.edges[edge_id]['updated'] = utcnow()
244
243
 
245
244
  def _rectify_node_attributes(self, **defaults):
246
245
 
@@ -295,7 +294,7 @@ class NetworkxBuilder(Builder):
295
294
  counter = self._graph.graph[counter_name]
296
295
  self._graph.graph[counter_name] = mutators.dictify(counter)
297
296
 
298
- self._graph.graph['created'] = datetime.utcnow()
297
+ self._graph.graph['created'] = utcnow()
299
298
 
300
299
  def build(self, **kwargs) -> GraphRepresentation:
301
300
  """
@@ -394,27 +393,60 @@ class GraphQLBuilder(NetworkxBuilder):
394
393
 
395
394
  @strawberry.type
396
395
  class Graph:
397
- graph: strawberry.Private[nx.Graph]
398
-
399
- name: str
400
- created: datetime
401
- hash: str
402
- node_type_counts: list['GraphQLBuilder.Measure']
403
- edge_type_counts: list['GraphQLBuilder.Measure']
404
- node_count: int
405
- edge_count: int
406
- order: int
407
- size: int
408
- # girth: int
409
- average_degree: float
396
+ nx_graph: strawberry.Private[nx.Graph]
410
397
 
411
398
  @strawberry.field()
412
399
  def radius(self) -> 'GraphQLBuilder.InfNumber':
413
- 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
414
401
 
415
402
  @strawberry.field()
416
403
  def diameter(self) -> 'GraphQLBuilder.InfNumber':
417
- 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']
418
450
 
419
451
  @strawberry.enum(description="""
420
452
  See NetworkX documentation for explanations:
@@ -600,24 +632,7 @@ class GraphQLBuilder(NetworkxBuilder):
600
632
 
601
633
  # region - Defining GraphQL Query Class dict - graph field
602
634
  def graphql_graph(self) -> GraphQLBuilder.Graph:
603
- graph = get_graph()
604
- return GraphQLBuilder.Graph(
605
- graph=graph,
606
- name=graph.graph['name'],
607
- node_type_counts=[GraphQLBuilder.Measure(name=t, value=c) for t, c in
608
- graph.graph['node_types'].items()],
609
- edge_type_counts=[GraphQLBuilder.Measure(name=t, value=c) for t, c in
610
- graph.graph['edge_types'].items()],
611
- node_count=graph.number_of_nodes(),
612
- edge_count=graph.number_of_edges(),
613
- order=graph.order(),
614
- size=graph.size(weight='weight'),
615
- # girth=min(len(cycle) for cycle in nx.simple_cycles(graph)),
616
- average_degree=graph.number_of_nodes() and (
617
- 1.0 * sum(d for _, d in graph.degree()) / graph.number_of_nodes()),
618
- hash=nx.weisfeiler_lehman_graph_hash(graph),
619
- created=graph.graph['created'],
620
- )
635
+ return GraphQLBuilder.Graph(nx_graph=get_graph())
621
636
 
622
637
  self.add_field_resolver(query_class_dict, 'graph', graphql_graph)
623
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>
@@ -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
@@ -3,8 +3,8 @@
3
3
  <head>
4
4
  <title>Graphinate</title>
5
5
  <style> body { margin: 0; } </style>
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"
6
+ <script src="https://cdn.jsdelivr.net/npm/3d-force-graph@1.73.2/dist/3d-force-graph.min.js"
7
+ integrity="sha384-GvVjcMDlxnFkYfcqa18cpupB8NqHsk7/vla5sjyVcZ7Gjzc4fzSiQgCRB4zYFqCa"
8
8
  crossorigin="anonymous"></script>
9
9
  <script src="/static/scripts/murmurhash3_gc.js"
10
10
  integrity="sha384-qmbe8KG4+frUnGS6DOKYZgFKbBvbhNNOL/LZ4hSpKauxmgrTX3LALg5+oQJS4AOn"></script>
@@ -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):
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