Graphinate 0.4.0__tar.gz → 0.5.1__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.
- {graphinate-0.4.0 → graphinate-0.5.1}/.github/workflows/test-beta.yml +1 -1
- {graphinate-0.4.0 → graphinate-0.5.1}/PKG-INFO +26 -31
- {graphinate-0.4.0 → graphinate-0.5.1}/README.md +24 -11
- graphinate-0.5.1/docs/assets/badge/v0.json +7 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/index.md +10 -4
- graphinate-0.5.1/examples/math/graph_atlas.py +69 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/math/graphs.py +74 -20
- graphinate-0.5.1/examples/math/gui.py +108 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/web/page_links.py +12 -8
- {graphinate-0.4.0 → graphinate-0.5.1}/pyproject.toml +12 -9
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/builders.py +5 -5
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/modeling.py +14 -15
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/__init__.py +1 -1
- graphinate-0.5.1/src/graphinate/server/web/static/images/logo.svg +50 -0
- graphinate-0.5.1/src/graphinate/server/web/viewer/index.html +162 -0
- graphinate-0.4.0/examples/math/graph_atlas.py +0 -52
- graphinate-0.4.0/examples/math/gui.py +0 -133
- graphinate-0.4.0/src/graphinate/server/web/static/js/murmurhash3_gc.js +0 -64
- graphinate-0.4.0/src/graphinate/server/web/viewer/index.html +0 -66
- {graphinate-0.4.0 → graphinate-0.5.1}/.coveragerc +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/.github/dependabot.yml +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/.github/workflows/codeql.yml +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/.github/workflows/publish-docs.yaml +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/.github/workflows/publish.yml +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/.github/workflows/test.yml +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/.gitignore +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/.sonarcloud.properties +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/LICENSE +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/STATS.md +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/acknowledge.md +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/assets/images/logo-128.png +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/assets/images/network_graph.png +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/assets/stylesheets/extra.css +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/dev.md +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/examples/code.md +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/examples/github.md +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/examples/math.md +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/examples/system.md +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/examples/web.md +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/gen_ref_pages.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/intro.md +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/start.md +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/usage/cli.md +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/docs/usage/lib.md +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/code/python_ast.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/code/python_dependencies.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/code/requirements.txt +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/github/_client.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/github/commits_visibilty_graph.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/github/followers.graphql +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/github/followers.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/github/graphql.config.yml +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/github/repositories.graphql +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/github/repositories.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/github/requirements.txt +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/math/polygonal_graph.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/math/requirements.txt +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/system/processes.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/system/requirements.txt +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/examples/web/requirements.txt +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/mkdocs.yml +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/playground/ethernet/traceroute.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/playground/genric_graph.graphql +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/playground/graphql.config.yml +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/playground/house_of_graphs.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/playground/social/albums.json +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/playground/social/musicisians.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/playground/text/nlp_graph.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/playground/text/requirements.txt +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/playground/time_series/requirements.txt +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/playground/time_series/visibility_graph.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/sonar-project.properties +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/__init__.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/__main__.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/cli.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/color.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/materializers/__init__.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/materializers/matplotlib.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/starlette/__init__.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/starlette/views.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/web/__init__.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/web/elements/__init__.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/web/elements/index.html +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/web/graphiql/__init__.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/web/graphiql/index.html +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/web/rapidoc/__init__.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/web/rapidoc/index.html +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/web/static/images/logo-128.png +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/web/static/images/network_graph.png +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/web/viewer/__init__.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/web/voyager/__init__.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/server/web/voyager/index.html +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/tools/__init__.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/tools/converters.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/tools/mutators.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/src/graphinate/typing.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/tests/conftest.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/tests/graphinate/test_builders.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/tests/graphinate/test_cli.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/tests/graphinate/test_color.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/tests/graphinate/test_materializers.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/tests/graphinate/test_modeling.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/tests/graphinate/test_server.py +0 -0
- {graphinate-0.4.0 → graphinate-0.5.1}/tests/graphinate/test_tools.py +0 -0
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
fail-fast: false
|
|
17
17
|
matrix:
|
|
18
18
|
# https://github.com/actions/python-versions/blob/main/versions-manifest.json
|
|
19
|
-
python-version: [ "3.14.0-alpha.
|
|
19
|
+
python-version: [ "3.14.0-alpha.5" ]
|
|
20
20
|
steps:
|
|
21
21
|
- uses: actions/checkout@v4
|
|
22
22
|
- name: Set up Python ${{ matrix.python-version }}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Graphinate
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.5.1
|
|
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
|
|
7
7
|
Project-URL: Bug Tracker, https://github.com/erivlis/graphinate/issues
|
|
@@ -33,32 +33,14 @@ Requires-Dist: loguru
|
|
|
33
33
|
Requires-Dist: matplotlib
|
|
34
34
|
Requires-Dist: networkx
|
|
35
35
|
Requires-Dist: strawberry-graphql[asgi,opentelemetry]
|
|
36
|
-
Provides-Extra: dev
|
|
37
|
-
Requires-Dist: pipdeptree; extra == 'dev'
|
|
38
|
-
Requires-Dist: ruff; extra == 'dev'
|
|
39
|
-
Provides-Extra: docs
|
|
40
|
-
Requires-Dist: mkdocs-gen-files; extra == 'docs'
|
|
41
|
-
Requires-Dist: mkdocs-git-revision-date-localized-plugin; extra == 'docs'
|
|
42
|
-
Requires-Dist: mkdocs-glightbox; extra == 'docs'
|
|
43
|
-
Requires-Dist: mkdocs-literate-nav; extra == 'docs'
|
|
44
|
-
Requires-Dist: mkdocs-material; extra == 'docs'
|
|
45
|
-
Requires-Dist: mkdocs-section-index; extra == 'docs'
|
|
46
|
-
Requires-Dist: mkdocstrings-python; extra == 'docs'
|
|
47
36
|
Provides-Extra: plot
|
|
48
37
|
Requires-Dist: scipy; extra == 'plot'
|
|
49
38
|
Provides-Extra: server
|
|
50
39
|
Requires-Dist: starlette-prometheus; extra == 'server'
|
|
51
40
|
Requires-Dist: uvicorn[standard]; extra == 'server'
|
|
52
|
-
Provides-Extra: test
|
|
53
|
-
Requires-Dist: faker; extra == 'test'
|
|
54
|
-
Requires-Dist: pytest; extra == 'test'
|
|
55
|
-
Requires-Dist: pytest-asyncio; extra == 'test'
|
|
56
|
-
Requires-Dist: pytest-cov; extra == 'test'
|
|
57
|
-
Requires-Dist: pytest-randomly; extra == 'test'
|
|
58
|
-
Requires-Dist: pytest-xdist; extra == 'test'
|
|
59
41
|
Description-Content-Type: text/markdown
|
|
60
42
|
|
|
61
|
-
# [
|
|
43
|
+
# [𝔾raphinate. Data to Graphs.](https://erivlis.github.io/graphinate/)
|
|
62
44
|
|
|
63
45
|
<img height="360" src="https://github.com/erivlis/graphinate/assets/9897520/dae41f9f-69e5-4eb5-a488-87ce7f51fa32" alt="Graphinate. Data to Graphs.">
|
|
64
46
|
|
|
@@ -120,10 +102,21 @@ Description-Content-Type: text/markdown
|
|
|
120
102
|
<a href="https://snyk.io/test/github/erivlis/graphinate"><img alt="Snyk" src="https://snyk.io/test/github/erivlis/Graphinate/badge.svg"></a>
|
|
121
103
|
</td>
|
|
122
104
|
</tr>
|
|
105
|
+
<tr>
|
|
106
|
+
<td>Mentions</td>
|
|
107
|
+
<td>
|
|
108
|
+
<a href="https://www.youtube.com/live/k01G0b0Y0Jg?si=030OT8sK3BqPyy8r&t=1028"><img alt="PythonBytes Podcast" src="https://img.shields.io/badge/Python_Bytes-Ep. 361-D7F9FF?logo=applepodcasts&labelColor=blue"></a>
|
|
109
|
+
<a href="https://pythonhub.dev/digest/2024-03-10/"><img alt="Static Badge" src="https://img.shields.io/badge/PythonHub-2024.03.10-gold?labelColor=blue"></a>
|
|
110
|
+
</td>
|
|
111
|
+
</tr>
|
|
112
|
+
<tr>
|
|
113
|
+
<td>Badge</td>
|
|
114
|
+
<td>
|
|
115
|
+
<a href="https://img.shields.io/badge/%F0%9D%94%BE%3D%7B%F0%9D%95%8D%2C%F0%9D%94%BC%7D-Graphinate-darkviolet"><img alt="Graphinate" src="https://img.shields.io/badge/%F0%9D%94%BE%3D%7B%F0%9D%95%8D%2C%F0%9D%94%BC%7D-Graphinate-darkviolet"></a>
|
|
116
|
+
</td>
|
|
117
|
+
</tr>
|
|
123
118
|
</table>
|
|
124
119
|
|
|
125
|
-
---------------------
|
|
126
|
-
|
|
127
120
|
## Introduction
|
|
128
121
|
|
|
129
122
|
### What is Graphinate?
|
|
@@ -302,27 +295,29 @@ python -m mkdocs build
|
|
|
302
295
|
|
|
303
296
|
#### Python
|
|
304
297
|
|
|
305
|
-
<a href="https://palletsprojects.com/p/click/"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://click.palletsprojects.com/en/7.x/_images/click-logo.png" alt="Click Logo
|
|
306
|
-
<a href="https://github.com/Delgan/loguru"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://raw.githubusercontent.com/Delgan/loguru/master/docs/_static/img/logo.png" alt="Loguru Logo
|
|
298
|
+
<a href="https://palletsprojects.com/p/click/"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://click.palletsprojects.com/en/7.x/_images/click-logo.png" alt="Click Logo"></a>
|
|
299
|
+
<a href="https://github.com/Delgan/loguru"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://raw.githubusercontent.com/Delgan/loguru/master/docs/_static/img/logo.png" alt="Loguru Logo"></a>
|
|
307
300
|
<a href="https://matplotlib.org/"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://matplotlib.org/_static/logo_dark.svg" alt="matplotlib Logo."></a>
|
|
308
301
|
<a href="https://networkx.org/"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://networkx.org/_static/networkx_logo.svg" alt="NetworkX Logo."></a>
|
|
309
|
-
<a href="https://strawberry.rocks/"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://github.com/strawberry-graphql/strawberry/raw/main/.github/logo.png" alt="Strawberry GraphQL Logo
|
|
302
|
+
<a href="https://strawberry.rocks/"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://github.com/strawberry-graphql/strawberry/raw/main/.github/logo.png" alt="Strawberry GraphQL Logo"></a>
|
|
310
303
|
|
|
311
304
|
#### Javascript and HTML
|
|
312
305
|
|
|
313
|
-
<a href="https://vasturiano.github.io/3d-force-graph/"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="http://gist.github.com/vasturiano/02affe306ce445e423f992faeea13521/raw/preview.png" alt="3D Force-Directed Graph Logo
|
|
314
|
-
<a href="https://github.com/graphql-kit/graphql-voyager"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://github.com/graphql-kit/graphql-voyager/raw/main/docs/cover.png" alt="Graphql Voyager Logo
|
|
306
|
+
<a href="https://vasturiano.github.io/3d-force-graph/"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="http://gist.github.com/vasturiano/02affe306ce445e423f992faeea13521/raw/preview.png" alt="3D Force-Directed Graph Logo"></a>
|
|
307
|
+
<a href="https://github.com/graphql-kit/graphql-voyager"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://github.com/graphql-kit/graphql-voyager/raw/main/docs/cover.png" alt="Graphql Voyager Logo"></a>
|
|
308
|
+
<a href="https://github.com/cocopon/tweakpane"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://user-images.githubusercontent.com/602961/184479032-38f50be3-e235-4914-85c0-dce316b33ed2.png" alt="Tweakpane Logo"></a>
|
|
315
309
|
|
|
316
310
|
### Dev Tools
|
|
317
311
|
|
|
318
312
|
<a href="https://hatch.pypa.io/"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://hatch.pypa.io/latest/assets/images/logo.svg" alt="Hatch logo."></a>
|
|
319
313
|
<a href="https://squidfunk.github.io/mkdocs-material/"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://raw.githubusercontent.com/squidfunk/mkdocs-material/master/.github/assets/logo.svg" alt="Material for MkDocs"></a>
|
|
320
|
-
<a href="https://pytest.org"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://docs.pytest.org/en/7.4.x/_static/pytest_logo_curves.svg" alt="pytest logo
|
|
321
|
-
<a href="https://astral.sh/ruff"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://astralcms.wpengine.com/wp-content/uploads/2023/03/Ruff-Logo.svg" alt="Ruff logo
|
|
314
|
+
<a href="https://pytest.org"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://docs.pytest.org/en/7.4.x/_static/pytest_logo_curves.svg" alt="pytest logo"></a>
|
|
315
|
+
<a href="https://astral.sh/ruff"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://astralcms.wpengine.com/wp-content/uploads/2023/03/Ruff-Logo.svg" alt="Ruff logo"></a>
|
|
316
|
+
<a href="https://astral.sh/uv"><img height="60" style="padding: 16px; background: #261230;" src="https://docs.astral.sh/uv/assets/logo-letter.svg" alt="uv logo"></a>
|
|
322
317
|
|
|
323
318
|
### IDE
|
|
324
319
|
|
|
325
|
-
<a href="https://www.jetbrains.com/pycharm/"><img height="60" style="background: linear-gradient(-45deg, #FCF84A, #3DEA62, #21D789);" src="https://resources.jetbrains.com/storage/products/company/brand/logos/PyCharm.png" alt="PyCharm logo
|
|
320
|
+
<a href="https://www.jetbrains.com/pycharm/"><img height="60" style="background: linear-gradient(-45deg, #FCF84A, #3DEA62, #21D789);" src="https://resources.jetbrains.com/storage/products/company/brand/logos/PyCharm.png" alt="PyCharm logo"></a>
|
|
326
321
|
|
|
327
322
|
---------------------
|
|
328
323
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# [
|
|
1
|
+
# [𝔾raphinate. Data to Graphs.](https://erivlis.github.io/graphinate/)
|
|
2
2
|
|
|
3
3
|
<img height="360" src="https://github.com/erivlis/graphinate/assets/9897520/dae41f9f-69e5-4eb5-a488-87ce7f51fa32" alt="Graphinate. Data to Graphs.">
|
|
4
4
|
|
|
@@ -60,10 +60,21 @@
|
|
|
60
60
|
<a href="https://snyk.io/test/github/erivlis/graphinate"><img alt="Snyk" src="https://snyk.io/test/github/erivlis/Graphinate/badge.svg"></a>
|
|
61
61
|
</td>
|
|
62
62
|
</tr>
|
|
63
|
+
<tr>
|
|
64
|
+
<td>Mentions</td>
|
|
65
|
+
<td>
|
|
66
|
+
<a href="https://www.youtube.com/live/k01G0b0Y0Jg?si=030OT8sK3BqPyy8r&t=1028"><img alt="PythonBytes Podcast" src="https://img.shields.io/badge/Python_Bytes-Ep. 361-D7F9FF?logo=applepodcasts&labelColor=blue"></a>
|
|
67
|
+
<a href="https://pythonhub.dev/digest/2024-03-10/"><img alt="Static Badge" src="https://img.shields.io/badge/PythonHub-2024.03.10-gold?labelColor=blue"></a>
|
|
68
|
+
</td>
|
|
69
|
+
</tr>
|
|
70
|
+
<tr>
|
|
71
|
+
<td>Badge</td>
|
|
72
|
+
<td>
|
|
73
|
+
<a href="https://img.shields.io/badge/%F0%9D%94%BE%3D%7B%F0%9D%95%8D%2C%F0%9D%94%BC%7D-Graphinate-darkviolet"><img alt="Graphinate" src="https://img.shields.io/badge/%F0%9D%94%BE%3D%7B%F0%9D%95%8D%2C%F0%9D%94%BC%7D-Graphinate-darkviolet"></a>
|
|
74
|
+
</td>
|
|
75
|
+
</tr>
|
|
63
76
|
</table>
|
|
64
77
|
|
|
65
|
-
---------------------
|
|
66
|
-
|
|
67
78
|
## Introduction
|
|
68
79
|
|
|
69
80
|
### What is Graphinate?
|
|
@@ -242,27 +253,29 @@ python -m mkdocs build
|
|
|
242
253
|
|
|
243
254
|
#### Python
|
|
244
255
|
|
|
245
|
-
<a href="https://palletsprojects.com/p/click/"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://click.palletsprojects.com/en/7.x/_images/click-logo.png" alt="Click Logo
|
|
246
|
-
<a href="https://github.com/Delgan/loguru"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://raw.githubusercontent.com/Delgan/loguru/master/docs/_static/img/logo.png" alt="Loguru Logo
|
|
256
|
+
<a href="https://palletsprojects.com/p/click/"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://click.palletsprojects.com/en/7.x/_images/click-logo.png" alt="Click Logo"></a>
|
|
257
|
+
<a href="https://github.com/Delgan/loguru"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://raw.githubusercontent.com/Delgan/loguru/master/docs/_static/img/logo.png" alt="Loguru Logo"></a>
|
|
247
258
|
<a href="https://matplotlib.org/"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://matplotlib.org/_static/logo_dark.svg" alt="matplotlib Logo."></a>
|
|
248
259
|
<a href="https://networkx.org/"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://networkx.org/_static/networkx_logo.svg" alt="NetworkX Logo."></a>
|
|
249
|
-
<a href="https://strawberry.rocks/"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://github.com/strawberry-graphql/strawberry/raw/main/.github/logo.png" alt="Strawberry GraphQL Logo
|
|
260
|
+
<a href="https://strawberry.rocks/"><img height="60" style="padding: 5px; background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://github.com/strawberry-graphql/strawberry/raw/main/.github/logo.png" alt="Strawberry GraphQL Logo"></a>
|
|
250
261
|
|
|
251
262
|
#### Javascript and HTML
|
|
252
263
|
|
|
253
|
-
<a href="https://vasturiano.github.io/3d-force-graph/"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="http://gist.github.com/vasturiano/02affe306ce445e423f992faeea13521/raw/preview.png" alt="3D Force-Directed Graph Logo
|
|
254
|
-
<a href="https://github.com/graphql-kit/graphql-voyager"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://github.com/graphql-kit/graphql-voyager/raw/main/docs/cover.png" alt="Graphql Voyager Logo
|
|
264
|
+
<a href="https://vasturiano.github.io/3d-force-graph/"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="http://gist.github.com/vasturiano/02affe306ce445e423f992faeea13521/raw/preview.png" alt="3D Force-Directed Graph Logo"></a>
|
|
265
|
+
<a href="https://github.com/graphql-kit/graphql-voyager"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://github.com/graphql-kit/graphql-voyager/raw/main/docs/cover.png" alt="Graphql Voyager Logo"></a>
|
|
266
|
+
<a href="https://github.com/cocopon/tweakpane"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://user-images.githubusercontent.com/602961/184479032-38f50be3-e235-4914-85c0-dce316b33ed2.png" alt="Tweakpane Logo"></a>
|
|
255
267
|
|
|
256
268
|
### Dev Tools
|
|
257
269
|
|
|
258
270
|
<a href="https://hatch.pypa.io/"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://hatch.pypa.io/latest/assets/images/logo.svg" alt="Hatch logo."></a>
|
|
259
271
|
<a href="https://squidfunk.github.io/mkdocs-material/"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://raw.githubusercontent.com/squidfunk/mkdocs-material/master/.github/assets/logo.svg" alt="Material for MkDocs"></a>
|
|
260
|
-
<a href="https://pytest.org"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://docs.pytest.org/en/7.4.x/_static/pytest_logo_curves.svg" alt="pytest logo
|
|
261
|
-
<a href="https://astral.sh/ruff"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://astralcms.wpengine.com/wp-content/uploads/2023/03/Ruff-Logo.svg" alt="Ruff logo
|
|
272
|
+
<a href="https://pytest.org"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://docs.pytest.org/en/7.4.x/_static/pytest_logo_curves.svg" alt="pytest logo"></a>
|
|
273
|
+
<a href="https://astral.sh/ruff"><img height="60" style="background: linear-gradient(-45deg, #FFFFFF, #CCCCCC);" src="https://astralcms.wpengine.com/wp-content/uploads/2023/03/Ruff-Logo.svg" alt="Ruff logo"></a>
|
|
274
|
+
<a href="https://astral.sh/uv"><img height="60" style="padding: 16px; background: #261230;" src="https://docs.astral.sh/uv/assets/logo-letter.svg" alt="uv logo"></a>
|
|
262
275
|
|
|
263
276
|
### IDE
|
|
264
277
|
|
|
265
|
-
<a href="https://www.jetbrains.com/pycharm/"><img height="60" style="background: linear-gradient(-45deg, #FCF84A, #3DEA62, #21D789);" src="https://resources.jetbrains.com/storage/products/company/brand/logos/PyCharm.png" alt="PyCharm logo
|
|
278
|
+
<a href="https://www.jetbrains.com/pycharm/"><img height="60" style="background: linear-gradient(-45deg, #FCF84A, #3DEA62, #21D789);" src="https://resources.jetbrains.com/storage/products/company/brand/logos/PyCharm.png" alt="PyCharm logo"></a>
|
|
266
279
|
|
|
267
280
|
---------------------
|
|
268
281
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<table style="border-width: 0;">
|
|
4
4
|
<tr style="vertical-align: middle; border-width: 0;">
|
|
5
|
-
<td rowspan="
|
|
5
|
+
<td rowspan="7"><img height="240" src="https://github.com/erivlis/graphinate/assets/9897520/dae41f9f-69e5-4eb5-a488-87ce7f51fa32" alt="Graphinate. Data to Graphs."></td>
|
|
6
6
|
<td>Package</td>
|
|
7
7
|
<td>
|
|
8
8
|
<img alt="PyPI - version" src="https://img.shields.io/pypi/v/graphinate.svg?logo=pypi&logoColor=lightblue">
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
<tr style="vertical-align: middle;">
|
|
36
36
|
<td>CI/CD</td>
|
|
37
37
|
<td>
|
|
38
|
-
<a href="https://github.com/erivlis/graphinate/actions/workflows/test.yml"><img alt="
|
|
39
|
-
<a href="https://github.com/erivlis/graphinate/actions/workflows/test.yml"><img alt="
|
|
38
|
+
<a href="https://github.com/erivlis/graphinate/actions/workflows/test.yml"><img alt="Test" src="https://github.com/erivlis/graphinate/actions/workflows/test.yml/badge.svg"></a>
|
|
39
|
+
<a href="https://github.com/erivlis/graphinate/actions/workflows/test-beta.yml"><img alt="Test (Beta)" src="https://github.com/erivlis/graphinate/actions/workflows/test-beta.yml/badge.svg"></a>
|
|
40
40
|
<a href="https://github.com/erivlis/graphinate/actions/workflows/publish.yml"><img alt="Publish" src="https://github.com/erivlis/graphinate/actions/workflows/publish.yml/badge.svg"></a>
|
|
41
41
|
<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>
|
|
42
42
|
</td>
|
|
@@ -59,5 +59,11 @@
|
|
|
59
59
|
<a href="https://snyk.io/test/github/erivlis/graphinate"><img alt="Snyk" src="https://snyk.io/test/github/erivlis/Graphinate/badge.svg"></a>
|
|
60
60
|
</td>
|
|
61
61
|
</tr>
|
|
62
|
+
<tr>
|
|
63
|
+
<td>Mentions</td>
|
|
64
|
+
<td>
|
|
65
|
+
<a href="https://www.youtube.com/live/k01G0b0Y0Jg?si=030OT8sK3BqPyy8r&t=1028"><img alt="PythonBytes Podcast" src="https://img.shields.io/badge/Python_Bytes-Ep. 361-D7F9FF?logo=applepodcasts&labelColor=blue"></a>
|
|
66
|
+
<a href="https://pythonhub.dev/digest/2024-03-10/"><img alt="Static Badge" src="https://img.shields.io/badge/PythonHub-2024.03.10-gold?labelColor=blue"></a>
|
|
67
|
+
</td>
|
|
68
|
+
</tr>
|
|
62
69
|
</table>
|
|
63
|
-
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import operator
|
|
2
|
+
|
|
3
|
+
import graphs
|
|
4
|
+
import networkx as nx
|
|
5
|
+
|
|
6
|
+
import graphinate
|
|
7
|
+
from graphinate.materializers import Materializers
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def model(items: list[tuple[str, nx.Graph]]) -> graphinate.GraphModel:
|
|
11
|
+
"""
|
|
12
|
+
Generate a graph model based on the provided iterable of graphs.
|
|
13
|
+
The function creates a graph model named 'Graph Atlas' using the 'graphinate' library.
|
|
14
|
+
It then combines all the graphs from the input iterable into a single disjoint union graph using NetworkX library.
|
|
15
|
+
The function defines edges for the combined graph by iterating over all edges in the disjoint union graph and
|
|
16
|
+
yielding dictionaries with 'source' and 'target' keys representing the edge connections.
|
|
17
|
+
Finally, the function yields the created graph model containing the combined graph with defined edges.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
items: A list containing graphs to be combined into a single graph model.
|
|
21
|
+
|
|
22
|
+
Yields:
|
|
23
|
+
GraphModel: A graph model containing the combined graph with defined edges.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def items_iter(recs):
|
|
27
|
+
for name, g in recs:
|
|
28
|
+
print(name)
|
|
29
|
+
yield g
|
|
30
|
+
|
|
31
|
+
g = nx.disjoint_union_all(items_iter(items)) if len(items) > 1 else items[0][1]
|
|
32
|
+
|
|
33
|
+
graph_model = graphinate.model('Graph Atlas')
|
|
34
|
+
|
|
35
|
+
@graph_model.node(operator.itemgetter(1),
|
|
36
|
+
key=operator.itemgetter(0),
|
|
37
|
+
value=operator.itemgetter(0))
|
|
38
|
+
def nodes():
|
|
39
|
+
yield from g.nodes(data='type')
|
|
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))
|
|
46
|
+
def edge():
|
|
47
|
+
yield from g.edges.data('type')
|
|
48
|
+
|
|
49
|
+
return graph_model
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
if __name__ == '__main__':
|
|
53
|
+
from gui import ListboxChooser, RadiobuttonChooser
|
|
54
|
+
|
|
55
|
+
graph_atlas = graphs.atlas()
|
|
56
|
+
|
|
57
|
+
listbox_chooser = ListboxChooser('Choose Graph', graph_atlas)
|
|
58
|
+
choices = list(listbox_chooser.get_choices())
|
|
59
|
+
model = model(choices)
|
|
60
|
+
|
|
61
|
+
# or
|
|
62
|
+
# model(graph_atlas.values())
|
|
63
|
+
|
|
64
|
+
radiobutton_chooser = RadiobuttonChooser('Choose Materializer',
|
|
65
|
+
options={m.name: m.value for m in Materializers},
|
|
66
|
+
default=(None, None))
|
|
67
|
+
result = radiobutton_chooser.get_choice()
|
|
68
|
+
builder, handler = result[1]
|
|
69
|
+
graphinate.materialize(model, builder=builder, builder_output_handler=handler)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import itertools
|
|
2
|
+
import re
|
|
2
3
|
from collections.abc import Iterable
|
|
3
4
|
from typing import NewType
|
|
4
5
|
|
|
@@ -692,18 +693,20 @@ SPECIAL_GRAPHS_ADJACENCY_LISTS = {
|
|
|
692
693
|
AdjacencyList = NewType('AdjacencyList', dict[int, list[int]])
|
|
693
694
|
|
|
694
695
|
|
|
695
|
-
def ladder_ring_graph(size: int):
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
696
|
+
def ladder_ring_graph(size: int) -> nx.Graph:
|
|
697
|
+
g: nx.Graph = nx.ladder_graph(size)
|
|
698
|
+
g.add_edge(size, size * 2 - 1)
|
|
699
|
+
g.add_edge(0, size - 1)
|
|
700
|
+
g.name = f'Ladder Ring[{size}]'
|
|
701
|
+
return g
|
|
700
702
|
|
|
701
703
|
|
|
702
|
-
def ladder_mobius_graph(size: int):
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
704
|
+
def ladder_mobius_graph(size: int) -> nx.Graph:
|
|
705
|
+
g = nx.ladder_graph(size)
|
|
706
|
+
g.add_edge(size, size - 1)
|
|
707
|
+
g.add_edge(0, size * 2 - 1)
|
|
708
|
+
g.name = f'Ladder Möbius Ring[{size}]'
|
|
709
|
+
return g
|
|
707
710
|
|
|
708
711
|
|
|
709
712
|
def _cylinder_edges(circumference: int, length: int) -> Iterable[tuple[int, int]]:
|
|
@@ -721,7 +724,9 @@ def _cylinder_edges(circumference: int, length: int) -> Iterable[tuple[int, int]
|
|
|
721
724
|
|
|
722
725
|
|
|
723
726
|
def cylinder_graph(circumference: int, length: int) -> nx.Graph:
|
|
724
|
-
|
|
727
|
+
g = nx.Graph(_cylinder_edges(circumference, length))
|
|
728
|
+
g.name = f'Cylinder[circumference={circumference},length={length}]'
|
|
729
|
+
return g
|
|
725
730
|
|
|
726
731
|
|
|
727
732
|
def _spiral_edges(n, k) -> Iterable[tuple[int, int]]:
|
|
@@ -733,7 +738,9 @@ def _spiral_edges(n, k) -> Iterable[tuple[int, int]]:
|
|
|
733
738
|
|
|
734
739
|
|
|
735
740
|
def spiral_graph(n, k) -> nx.Graph:
|
|
736
|
-
|
|
741
|
+
g = nx.Graph(_spiral_edges(n, k))
|
|
742
|
+
g.name = f'Spiral[n={n},k={k}]'
|
|
743
|
+
return g
|
|
737
744
|
|
|
738
745
|
|
|
739
746
|
def _spiral_torus_edges(n, k) -> Iterable[tuple[int, int]]:
|
|
@@ -744,7 +751,20 @@ def _spiral_torus_edges(n, k) -> Iterable[tuple[int, int]]:
|
|
|
744
751
|
|
|
745
752
|
|
|
746
753
|
def spiral_torus_graph(n, k) -> nx.Graph:
|
|
747
|
-
|
|
754
|
+
g = nx.Graph(_spiral_torus_edges(n, k))
|
|
755
|
+
g.name = f'Spiral Torus[n={n},k={k}]'
|
|
756
|
+
return g
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
def k_regular_edges(n, k) -> Iterable[tuple[int, int]]:
|
|
760
|
+
yield from itertools.chain.from_iterable(
|
|
761
|
+
((i, j) for j in range(i + 1, i + k + 1))
|
|
762
|
+
for i in range(n-k))
|
|
763
|
+
|
|
764
|
+
def k_regular_graph(n, k) -> nx.Graph:
|
|
765
|
+
g = nx.Graph(k_regular_edges(n, k))
|
|
766
|
+
g.name = f'Generalized Buckyball[n={n},k={k}]'
|
|
767
|
+
return g
|
|
748
768
|
|
|
749
769
|
|
|
750
770
|
def adjacency_edges(adjacency_list: AdjacencyList) -> Iterable[tuple[int, int]]:
|
|
@@ -786,23 +806,57 @@ def atlas():
|
|
|
786
806
|
"""
|
|
787
807
|
|
|
788
808
|
graph_atlas = {
|
|
809
|
+
'Triangle': nx.cycle_graph(3),
|
|
810
|
+
'Square': nx.cycle_graph(4),
|
|
811
|
+
'Square Lattice[3,3]': nx.grid_2d_graph(3, 3),
|
|
812
|
+
'Pentagon': nx.cycle_graph(5),
|
|
813
|
+
'Hexagon': nx.cycle_graph(6),
|
|
814
|
+
'Heptagon': nx.cycle_graph(7),
|
|
815
|
+
'Octagon': nx.cycle_graph(8),
|
|
789
816
|
'Tetrahedron': nx.tetrahedral_graph(),
|
|
790
817
|
'Cube': nx.hypercube_graph(3),
|
|
791
818
|
'Octahedron': nx.octahedral_graph(),
|
|
792
819
|
'Dodecahedron': nx.dodecahedral_graph(),
|
|
793
820
|
'Icosahedron': nx.icosahedral_graph(),
|
|
794
821
|
'Tesseract': nx.hypercube_graph(4),
|
|
822
|
+
'Hypercube[5]': nx.hypercube_graph(5),
|
|
795
823
|
'Truncated Cube': nx.truncated_cube_graph(),
|
|
796
824
|
'Truncated Tetrahedron': nx.truncated_tetrahedron_graph(),
|
|
797
|
-
'Ladder': nx.ladder_graph(16),
|
|
798
|
-
'Ring': ladder_ring_graph(16),
|
|
799
|
-
'Möbius': ladder_mobius_graph(16),
|
|
800
|
-
'Cylinder': cylinder_graph(6, 8),
|
|
801
|
-
'Spiral': spiral_graph(
|
|
802
|
-
'Spiral Torus': spiral_torus_graph(128, 8),
|
|
803
|
-
'
|
|
825
|
+
'Ladder[16]': nx.ladder_graph(16),
|
|
826
|
+
'Ladder Ring[16]': ladder_ring_graph(16),
|
|
827
|
+
'Ladder Möbius Ring[16]': ladder_mobius_graph(16),
|
|
828
|
+
'Cylinder[6,8]': cylinder_graph(6, 8),
|
|
829
|
+
'Spiral[128,8]': spiral_graph(128, 8),
|
|
830
|
+
'Spiral Torus[128,8]': spiral_torus_graph(128, 8),
|
|
831
|
+
'Chvátal': nx.chvatal_graph(),
|
|
832
|
+
'Circulant[10,[2]]': nx.circulant_graph(10, [2]),
|
|
833
|
+
'Desargues': nx.desargues_graph(),
|
|
834
|
+
'Dorogovtsev-Goltsev-Mendes[4]': nx.dorogovtsev_goltsev_mendes_graph(4),
|
|
835
|
+
'Frucht': nx.frucht_graph(),
|
|
836
|
+
'Heawood': nx.heawood_graph(),
|
|
837
|
+
'Hoffman-Singleton': nx.hoffman_singleton_graph(),
|
|
838
|
+
# 'Margulis-Gabber-Galil[8]': nx.margulis_gabber_galil_graph(8),
|
|
839
|
+
'Papus': nx.pappus_graph(),
|
|
840
|
+
'Petersen': nx.petersen_graph(),
|
|
841
|
+
'Sedgewick Maze': nx.sedgewick_maze_graph(),
|
|
842
|
+
'Tutte': nx.tutte_graph(),
|
|
804
843
|
}
|
|
805
844
|
|
|
806
845
|
graph_atlas.update(special_graphs())
|
|
807
846
|
|
|
847
|
+
def clean(s: str):
|
|
848
|
+
# Remove invalid characters
|
|
849
|
+
s = re.sub('[^0-9a-zA-Z_]', '_', s)
|
|
850
|
+
|
|
851
|
+
# Remove leading characters until we find a letter or underscore
|
|
852
|
+
s = re.sub('^[^a-zA-Z_]+', '', s)
|
|
853
|
+
|
|
854
|
+
return s
|
|
855
|
+
|
|
856
|
+
for name, g in graph_atlas.items():
|
|
857
|
+
_type = clean(name).capitalize()
|
|
858
|
+
nx.set_node_attributes(g, _type, 'type')
|
|
859
|
+
nx.set_edge_attributes(g, _type, 'type')
|
|
860
|
+
|
|
808
861
|
return graph_atlas
|
|
862
|
+
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
import tkinter as tk
|
|
3
|
+
from tkinter import ttk
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ModalWindow(tk.Tk):
|
|
7
|
+
def __init__(self, title: str):
|
|
8
|
+
super().__init__()
|
|
9
|
+
self.title(title)
|
|
10
|
+
self.configure_window()
|
|
11
|
+
|
|
12
|
+
def configure_window(self):
|
|
13
|
+
if platform.system().lower() == 'windows':
|
|
14
|
+
self.wm_attributes('-toolwindow', 'True')
|
|
15
|
+
self.wm_attributes('-topmost', 'True')
|
|
16
|
+
self.resizable(False, False)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class RadiobuttonChooser(ModalWindow):
|
|
20
|
+
"""
|
|
21
|
+
Usage Example:
|
|
22
|
+
```python
|
|
23
|
+
radiobutton_chooser = RadiobuttonChooser("Choose an option", {"Option 1": 1, "Option 2": 2})
|
|
24
|
+
choice, value = radiobutton_chooser.get_choice()
|
|
25
|
+
print(choice, value)
|
|
26
|
+
```
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(self, window_title: str, options: dict, default=None):
|
|
30
|
+
super().__init__(window_title)
|
|
31
|
+
self.exit_button = None
|
|
32
|
+
self.choice_var = tk.StringVar(self, None)
|
|
33
|
+
self.default = default
|
|
34
|
+
self.options = options
|
|
35
|
+
self.create_widgets()
|
|
36
|
+
self.mainloop()
|
|
37
|
+
|
|
38
|
+
def create_widgets(self):
|
|
39
|
+
frame = ttk.Frame(self, borderwidth=5, relief='solid')
|
|
40
|
+
frame.pack(padx=4, pady=4)
|
|
41
|
+
|
|
42
|
+
ttk.Label(frame, text="Output Mode:").pack()
|
|
43
|
+
|
|
44
|
+
for option in self.options:
|
|
45
|
+
ttk.Radiobutton(
|
|
46
|
+
frame,
|
|
47
|
+
text=option,
|
|
48
|
+
variable=self.choice_var,
|
|
49
|
+
value=option,
|
|
50
|
+
command=self.enable_exit_button,
|
|
51
|
+
padding=4
|
|
52
|
+
).pack(side=tk.TOP, anchor="w")
|
|
53
|
+
|
|
54
|
+
self.exit_button = ttk.Button(self, text="OK", command=self.destroy, state=tk.DISABLED)
|
|
55
|
+
self.exit_button.pack(pady=4, side=tk.BOTTOM)
|
|
56
|
+
|
|
57
|
+
def enable_exit_button(self):
|
|
58
|
+
self.exit_button['state'] = tk.NORMAL
|
|
59
|
+
|
|
60
|
+
def get_choice(self):
|
|
61
|
+
return self.choice_var.get(), self.options.get(self.choice_var.get(), self.default)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class ListboxChooser(ModalWindow):
|
|
65
|
+
"""
|
|
66
|
+
Usage Example:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
listbox_chooser = ListboxChooser("Choose options", {"Option 1": 1, "Option 2": 2, "Option 3": 3})
|
|
70
|
+
for choice, value in listbox_chooser.get_choices():
|
|
71
|
+
print(choice, value)
|
|
72
|
+
```
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(self, window_title: str, options: dict, default=None):
|
|
76
|
+
super().__init__(window_title)
|
|
77
|
+
self.exit_button = None
|
|
78
|
+
self.choices = list(options.keys())
|
|
79
|
+
self.options = options
|
|
80
|
+
self.default = default
|
|
81
|
+
self.selection_var = tk.Variable(self)
|
|
82
|
+
self.create_widgets()
|
|
83
|
+
self.mainloop()
|
|
84
|
+
|
|
85
|
+
def create_widgets(self):
|
|
86
|
+
frame = ttk.Frame(self)
|
|
87
|
+
frame.pack(padx=2, pady=2)
|
|
88
|
+
|
|
89
|
+
listbox = tk.Listbox(frame, listvariable=tk.Variable(self, value=self.choices), selectmode="multiple",
|
|
90
|
+
height=min(len(self.choices), 50), width=max(len(c) for c in self.choices))
|
|
91
|
+
listbox.pack(side=tk.LEFT, fill=tk.BOTH)
|
|
92
|
+
|
|
93
|
+
scrollbar = ttk.Scrollbar(frame, command=listbox.yview)
|
|
94
|
+
scrollbar.pack(side=tk.RIGHT, fill=tk.BOTH)
|
|
95
|
+
listbox.config(yscrollcommand=scrollbar.set)
|
|
96
|
+
|
|
97
|
+
listbox.bind("<<ListboxSelect>>", self.on_select)
|
|
98
|
+
|
|
99
|
+
self.exit_button = ttk.Button(self, text="OK", command=self.destroy, state=tk.DISABLED)
|
|
100
|
+
self.exit_button.pack(pady=4, side=tk.BOTTOM)
|
|
101
|
+
|
|
102
|
+
def on_select(self, event):
|
|
103
|
+
self.exit_button['state'] = tk.NORMAL
|
|
104
|
+
self.selection_var.set(event.widget.curselection())
|
|
105
|
+
|
|
106
|
+
def get_choices(self):
|
|
107
|
+
for choice in self.selection_var.get():
|
|
108
|
+
yield self.choices[choice], self.options.get(self.choices[choice], self.default)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from urllib.parse import
|
|
1
|
+
from urllib.parse import urlparse
|
|
2
2
|
|
|
3
3
|
import requests
|
|
4
4
|
from bs4 import BeautifulSoup
|
|
@@ -28,13 +28,17 @@ def page_links_graph_model(max_depth: int = DEFAULT_MAX_DEPTH):
|
|
|
28
28
|
for link in soup.find_all('a', href=True):
|
|
29
29
|
child_url = link.get('href')
|
|
30
30
|
|
|
31
|
-
if child_url.startswith('javascript:'):
|
|
31
|
+
if child_url.startswith('javascript:'): # Skip JavaScript links
|
|
32
32
|
continue
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
if child_url.startswith('//'): # Handle protocol-relative URLs
|
|
34
35
|
child_url = f"https:{child_url}"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
|
|
37
|
+
if not bool(urlparse(child_url).netloc): # Skip relative URLs
|
|
38
|
+
# child_url = urljoin(url, child_url)
|
|
39
|
+
continue
|
|
40
|
+
|
|
41
|
+
if not child_url.startswith('http'): # Skip non-HTTP URLs
|
|
38
42
|
continue
|
|
39
43
|
|
|
40
44
|
yield {'source': url, 'target': child_url}
|
|
@@ -62,7 +66,7 @@ if __name__ == '__main__':
|
|
|
62
66
|
model=model,
|
|
63
67
|
graph_type=graphinate.GraphType.DiGraph,
|
|
64
68
|
default_node_attributes={'type': 'url'},
|
|
65
|
-
builder=graphinate.builders.
|
|
66
|
-
builder_output_handler=graphinate.
|
|
69
|
+
builder=graphinate.builders.GraphQLBuilder,
|
|
70
|
+
builder_output_handler=graphinate.graphql,
|
|
67
71
|
**params
|
|
68
72
|
)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "Graphinate"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.5.1"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name = "Eran Rivlis", email = "eran@rivlis.info" },
|
|
6
6
|
]
|
|
7
|
-
description = "
|
|
7
|
+
description = "𝔾raphinate. Data to Graphs."
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
requires-python = ">=3.10"
|
|
10
10
|
classifiers = [
|
|
@@ -45,6 +45,15 @@ dependencies = [
|
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
[project.optional-dependencies]
|
|
48
|
+
plot = [
|
|
49
|
+
"scipy"
|
|
50
|
+
]
|
|
51
|
+
server = [
|
|
52
|
+
"starlette-prometheus",
|
|
53
|
+
"uvicorn[standard]"
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[dependency-groups]
|
|
48
57
|
dev = [
|
|
49
58
|
"ruff",
|
|
50
59
|
"pipdeptree"
|
|
@@ -66,13 +75,7 @@ test = [
|
|
|
66
75
|
"pytest-randomly",
|
|
67
76
|
"pytest-xdist"
|
|
68
77
|
]
|
|
69
|
-
|
|
70
|
-
"scipy"
|
|
71
|
-
]
|
|
72
|
-
server = [
|
|
73
|
-
"starlette-prometheus",
|
|
74
|
-
"uvicorn[standard]"
|
|
75
|
-
]
|
|
78
|
+
|
|
76
79
|
|
|
77
80
|
|
|
78
81
|
[build-system]
|