Graphinate 0.8.6__tar.gz → 0.9.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. graphinate-0.9.0/.github/workflows/ci.yml +54 -0
  2. {graphinate-0.8.6 → graphinate-0.9.0}/.github/workflows/publish-docs.yaml +9 -6
  3. {graphinate-0.8.6 → graphinate-0.9.0}/.github/workflows/publish.yml +1 -1
  4. {graphinate-0.8.6 → graphinate-0.9.0}/.github/workflows/test-beta.yml +3 -3
  5. {graphinate-0.8.6 → graphinate-0.9.0}/.github/workflows/test.yml +4 -4
  6. {graphinate-0.8.6 → graphinate-0.9.0}/PKG-INFO +4 -4
  7. {graphinate-0.8.6 → graphinate-0.9.0}/README.md +0 -1
  8. {graphinate-0.8.6 → graphinate-0.9.0}/pyproject.toml +10 -6
  9. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/builders.py +1 -0
  10. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/color.py +1 -1
  11. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/modeling.py +15 -13
  12. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/renderers/graphql.py +2 -2
  13. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/starlette/__init__.py +2 -2
  14. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/viewer/index.html +2 -1
  15. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/voyager/index.html +5 -3
  16. graphinate-0.9.0/src/graphinate/typing.py +75 -0
  17. {graphinate-0.8.6 → graphinate-0.9.0}/tests/graphinate/renderers/test_matplotlib_draw.py +5 -5
  18. {graphinate-0.8.6 → graphinate-0.9.0}/tests/graphinate/server/test_starlette.py +8 -9
  19. graphinate-0.8.6/src/graphinate/typing.py +0 -74
  20. {graphinate-0.8.6 → graphinate-0.9.0}/.coveragerc +0 -0
  21. {graphinate-0.8.6 → graphinate-0.9.0}/.deepsource.toml +0 -0
  22. {graphinate-0.8.6 → graphinate-0.9.0}/.github/dependabot.yml +0 -0
  23. {graphinate-0.8.6 → graphinate-0.9.0}/.github/workflows/codeql.yml +0 -0
  24. {graphinate-0.8.6 → graphinate-0.9.0}/.gitignore +0 -0
  25. {graphinate-0.8.6 → graphinate-0.9.0}/.sonarcloud.properties +0 -0
  26. {graphinate-0.8.6 → graphinate-0.9.0}/LICENSE +0 -0
  27. {graphinate-0.8.6 → graphinate-0.9.0}/docs/.dates_cache.json +0 -0
  28. {graphinate-0.8.6 → graphinate-0.9.0}/docs/acknowledgements.md +0 -0
  29. {graphinate-0.8.6 → graphinate-0.9.0}/docs/assets/badge/v0.json +0 -0
  30. {graphinate-0.8.6 → graphinate-0.9.0}/docs/assets/images/logo-128.png +0 -0
  31. {graphinate-0.8.6 → graphinate-0.9.0}/docs/assets/images/network_graph.png +0 -0
  32. {graphinate-0.8.6 → graphinate-0.9.0}/docs/assets/stylesheets/extra.css +0 -0
  33. {graphinate-0.8.6 → graphinate-0.9.0}/docs/examples/code.md +0 -0
  34. {graphinate-0.8.6 → graphinate-0.9.0}/docs/examples/github.md +0 -0
  35. {graphinate-0.8.6 → graphinate-0.9.0}/docs/examples/math.md +0 -0
  36. {graphinate-0.8.6 → graphinate-0.9.0}/docs/examples/social.md +0 -0
  37. {graphinate-0.8.6 → graphinate-0.9.0}/docs/examples/system.md +0 -0
  38. {graphinate-0.8.6 → graphinate-0.9.0}/docs/examples/web.md +0 -0
  39. {graphinate-0.8.6 → graphinate-0.9.0}/docs/gen_ref_pages.py +0 -0
  40. {graphinate-0.8.6 → graphinate-0.9.0}/docs/index.md +0 -0
  41. {graphinate-0.8.6 → graphinate-0.9.0}/docs/introduction.md +0 -0
  42. {graphinate-0.8.6 → graphinate-0.9.0}/docs/start.md +0 -0
  43. {graphinate-0.8.6 → graphinate-0.9.0}/docs/tutorial.md +0 -0
  44. {graphinate-0.8.6 → graphinate-0.9.0}/docs/usage/cli.md +0 -0
  45. {graphinate-0.8.6 → graphinate-0.9.0}/docs/usage/lib.md +0 -0
  46. {graphinate-0.8.6 → graphinate-0.9.0}/examples/code/git_commits.py +0 -0
  47. {graphinate-0.8.6 → graphinate-0.9.0}/examples/code/python_ast.py +0 -0
  48. {graphinate-0.8.6 → graphinate-0.9.0}/examples/code/python_dependencies.py +0 -0
  49. {graphinate-0.8.6 → graphinate-0.9.0}/examples/code/requirements.txt +0 -0
  50. {graphinate-0.8.6 → graphinate-0.9.0}/examples/code/tokens.py +0 -0
  51. {graphinate-0.8.6 → graphinate-0.9.0}/examples/github/_client.py +0 -0
  52. {graphinate-0.8.6 → graphinate-0.9.0}/examples/github/commits_visibilty_graph.py +0 -0
  53. {graphinate-0.8.6 → graphinate-0.9.0}/examples/github/followers.graphql +0 -0
  54. {graphinate-0.8.6 → graphinate-0.9.0}/examples/github/followers.py +0 -0
  55. {graphinate-0.8.6 → graphinate-0.9.0}/examples/github/graphql.config.yml +0 -0
  56. {graphinate-0.8.6 → graphinate-0.9.0}/examples/github/repositories.graphql +0 -0
  57. {graphinate-0.8.6 → graphinate-0.9.0}/examples/github/repositories.py +0 -0
  58. {graphinate-0.8.6 → graphinate-0.9.0}/examples/github/requirements.txt +0 -0
  59. {graphinate-0.8.6 → graphinate-0.9.0}/examples/math/__init__.py +0 -0
  60. {graphinate-0.8.6 → graphinate-0.9.0}/examples/math/_test_materializers.py +0 -0
  61. {graphinate-0.8.6 → graphinate-0.9.0}/examples/math/graph_atlas.py +0 -0
  62. {graphinate-0.8.6 → graphinate-0.9.0}/examples/math/graphs.py +0 -0
  63. {graphinate-0.8.6 → graphinate-0.9.0}/examples/math/gui.py +0 -0
  64. {graphinate-0.8.6 → graphinate-0.9.0}/examples/math/materializers.py +0 -0
  65. {graphinate-0.8.6 → graphinate-0.9.0}/examples/math/polygonal_graph.py +0 -0
  66. {graphinate-0.8.6 → graphinate-0.9.0}/examples/math/requirements.txt +0 -0
  67. {graphinate-0.8.6 → graphinate-0.9.0}/examples/social/cache/13/dd/73ce25face7beb30b69b64feeb77.val +0 -0
  68. {graphinate-0.8.6 → graphinate-0.9.0}/examples/social/cache/21/9e/00846f323987ba16cfbe0127d8eb.val +0 -0
  69. {graphinate-0.8.6 → graphinate-0.9.0}/examples/social/cache/70/b6/2aefb0269adce7fedf877fa0d267.val +0 -0
  70. {graphinate-0.8.6 → graphinate-0.9.0}/examples/social/cache/87/f5/ec1739bc369e84c3fcb302bf532a.val +0 -0
  71. {graphinate-0.8.6 → graphinate-0.9.0}/examples/social/cache/ba/fe/3aca7b2c38abff60e7ce5eb486a8.val +0 -0
  72. {graphinate-0.8.6 → graphinate-0.9.0}/examples/social/cache/c7/9e/ce82b0288020b7152779df09bd73.val +0 -0
  73. {graphinate-0.8.6 → graphinate-0.9.0}/examples/social/cache/cache.db +0 -0
  74. {graphinate-0.8.6 → graphinate-0.9.0}/examples/social/cache/d2/53/3b88f2fc162561cfdbbe9abc352a.val +0 -0
  75. {graphinate-0.8.6 → graphinate-0.9.0}/examples/social/cache/e2/d5/5d079f200eabf9b625b0473f6fbe.val +0 -0
  76. {graphinate-0.8.6 → graphinate-0.9.0}/examples/social/gui.py +0 -0
  77. {graphinate-0.8.6 → graphinate-0.9.0}/examples/social/music_artists.py +0 -0
  78. {graphinate-0.8.6 → graphinate-0.9.0}/examples/social/requirements.txt +0 -0
  79. {graphinate-0.8.6 → graphinate-0.9.0}/examples/system/.ignore +0 -0
  80. {graphinate-0.8.6 → graphinate-0.9.0}/examples/system/files.py +0 -0
  81. {graphinate-0.8.6 → graphinate-0.9.0}/examples/system/processes.py +0 -0
  82. {graphinate-0.8.6 → graphinate-0.9.0}/examples/system/requirements.txt +0 -0
  83. {graphinate-0.8.6 → graphinate-0.9.0}/examples/web/html_dom.py +0 -0
  84. {graphinate-0.8.6 → graphinate-0.9.0}/examples/web/page_links.py +0 -0
  85. {graphinate-0.8.6 → graphinate-0.9.0}/examples/web/requirements.txt +0 -0
  86. {graphinate-0.8.6 → graphinate-0.9.0}/mkdocs.yml +0 -0
  87. {graphinate-0.8.6 → graphinate-0.9.0}/playground/ethernet/traceroute.py +0 -0
  88. {graphinate-0.8.6 → graphinate-0.9.0}/playground/genric_graph.graphql +0 -0
  89. {graphinate-0.8.6 → graphinate-0.9.0}/playground/graphql.config.yml +0 -0
  90. {graphinate-0.8.6 → graphinate-0.9.0}/playground/house_of_graphs.py +0 -0
  91. {graphinate-0.8.6 → graphinate-0.9.0}/playground/science/caffeine.py +0 -0
  92. {graphinate-0.8.6 → graphinate-0.9.0}/playground/social/albums.json +0 -0
  93. {graphinate-0.8.6 → graphinate-0.9.0}/playground/social/musicisians.py +0 -0
  94. {graphinate-0.8.6 → graphinate-0.9.0}/playground/text/nlp_graph.py +0 -0
  95. {graphinate-0.8.6 → graphinate-0.9.0}/playground/text/requirements.txt +0 -0
  96. {graphinate-0.8.6 → graphinate-0.9.0}/playground/time_series/requirements.txt +0 -0
  97. {graphinate-0.8.6 → graphinate-0.9.0}/playground/time_series/visibility_graph.py +0 -0
  98. {graphinate-0.8.6 → graphinate-0.9.0}/sonar-project.properties +0 -0
  99. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/__init__.py +0 -0
  100. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/__main__.py +0 -0
  101. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/cli.py +0 -0
  102. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/constants.py +0 -0
  103. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/converters.py +0 -0
  104. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/renderers/__init__.py +0 -0
  105. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/renderers/matplotlib.py +0 -0
  106. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/__init__.py +0 -0
  107. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/starlette/views.py +0 -0
  108. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/__init__.py +0 -0
  109. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/elements/__init__.py +0 -0
  110. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/elements/index.html +0 -0
  111. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/graphiql/__init__.py +0 -0
  112. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/graphiql/index.html +0 -0
  113. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/rapidoc/__init__.py +0 -0
  114. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/rapidoc/index.html +0 -0
  115. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/static/images/logo-128.png +0 -0
  116. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/static/images/logo.svg +0 -0
  117. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/static/images/network_graph.png +0 -0
  118. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/viewer/__init__.py +0 -0
  119. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/server/web/voyager/__init__.py +0 -0
  120. {graphinate-0.8.6 → graphinate-0.9.0}/src/graphinate/tools.py +0 -0
  121. {graphinate-0.8.6 → graphinate-0.9.0}/tests/conftest.py +0 -0
  122. {graphinate-0.8.6 → graphinate-0.9.0}/tests/graphinate/renderers/test_graphql.py +0 -0
  123. {graphinate-0.8.6 → graphinate-0.9.0}/tests/graphinate/renderers/test_matplotlib_plot.py +0 -0
  124. {graphinate-0.8.6 → graphinate-0.9.0}/tests/graphinate/test_builders.py +0 -0
  125. {graphinate-0.8.6 → graphinate-0.9.0}/tests/graphinate/test_cli.py +0 -0
  126. {graphinate-0.8.6 → graphinate-0.9.0}/tests/graphinate/test_color.py +0 -0
  127. {graphinate-0.8.6 → graphinate-0.9.0}/tests/graphinate/test_converters.py +0 -0
  128. {graphinate-0.8.6 → graphinate-0.9.0}/tests/graphinate/test_modeling.py +0 -0
  129. {graphinate-0.8.6 → graphinate-0.9.0}/tests/graphinate/test_server.py +0 -0
@@ -0,0 +1,54 @@
1
+ # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
3
+
4
+ name: CI
5
+
6
+ on:
7
+ push:
8
+ branches:
9
+ - main
10
+ pull_request:
11
+ branches:
12
+ - main
13
+
14
+ jobs:
15
+ build:
16
+ runs-on: ubuntu-latest
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14"]
21
+ steps:
22
+ - uses: actions/checkout@v5
23
+ - name: Set up UV and Python ${{ matrix.python-version }}
24
+ uses: astral-sh/setup-uv@v7
25
+ with:
26
+ python-version: ${{ matrix.python-version }}
27
+ - name: Install dependencies
28
+ run: uv sync
29
+ - name: Run Ruff Linter
30
+ run: uvx ruff check .
31
+ - name: Check Ruff Formatting
32
+ run: uvx ruff format --check .
33
+ - name: Test with pytest
34
+ run: |
35
+ uv sync --group test
36
+ uvx pytest tests --cov=src --cov-branch --cov-report=xml --junitxml=junit.xml -o junit_family=legacy -n auto
37
+ - name: Upload coverage reports to Codecov
38
+ uses: codecov/codecov-action@v5
39
+ with:
40
+ token: ${{ secrets.CODECOV_TOKEN }}
41
+ - name: Upload test results to Codecov
42
+ if: ${{ !cancelled() }}
43
+ uses: codecov/test-results-action@v1
44
+ with:
45
+ token: ${{ secrets.CODECOV_TOKEN }}
46
+ - name: Run codacy-coverage-reporter
47
+ uses: codacy/codacy-coverage-reporter-action@v1.3.0
48
+ with:
49
+ #project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
50
+ # or
51
+ api-token: ${{ secrets.CODACY_API_TOKEN }}
52
+ coverage-reports: coverage.xml
53
+ # or a comma-separated list for multiple reports
54
+ # coverage-reports: <PATH_TO_REPORT>, <PATH_TO_REPORT>
@@ -9,21 +9,24 @@ jobs:
9
9
  deploy:
10
10
  runs-on: ubuntu-latest
11
11
  steps:
12
- - uses: actions/checkout@v5
13
- - uses: actions/setup-python@v5
12
+ - name: Checkout repository
13
+ uses: actions/checkout@v5
14
+ - name: Set up Python
15
+ uses: actions/setup-python@v6
14
16
  with:
15
17
  python-version: 3.x
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v7
16
20
  - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
17
- - uses: actions/cache@v4
21
+ - name: Cache mkdocs-material dependencies
22
+ uses: actions/cache@v4
18
23
  with:
19
24
  key: mkdocs-material-${{ env.cache_id }}
20
25
  path: .cache
21
26
  restore-keys: |
22
27
  mkdocs-material-
23
28
  - run: |
24
- python -m pip install pip --upgrade
25
- pip install uv
26
29
  uv venv
27
30
  source .venv/bin/activate
28
- uv pip install mkdocs-material mkdocstrings-python mkdocs-git-committers-plugin-2 "mkdocs-git-revision-date-localized-plugin<1.4.0" mkdocs-gen-files mkdocs-glightbox mkdocs-literate-nav mkdocs-section-index
31
+ uv sync --only-group docs
29
32
  mkdocs gh-deploy --force
@@ -18,7 +18,7 @@ jobs:
18
18
  steps:
19
19
  - uses: actions/checkout@v5
20
20
  - name: Set up Python
21
- uses: actions/setup-python@v5
21
+ uses: actions/setup-python@v6
22
22
  with:
23
23
  python-version: '3.x'
24
24
  - name: Install dependencies
@@ -16,11 +16,11 @@ 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-rc.2" ]
19
+ python-version: [ "3.15.0-alpha.1" ]
20
20
  steps:
21
21
  - uses: actions/checkout@v5
22
22
  - name: Set up Python ${{ matrix.python-version }}
23
- uses: actions/setup-python@v5
23
+ uses: actions/setup-python@v6
24
24
  with:
25
25
  python-version: ${{ matrix.python-version }}
26
26
  - name: Install dependencies
@@ -38,5 +38,5 @@ jobs:
38
38
  flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
39
39
  - name: Test with pytest
40
40
  run: |
41
- python -m pip install faker pytest pytest-asyncio pytest-cov pytest-mock pytest-randomly pytest-xdist starlette-prometheus uvicorn[standard]
41
+ python -m pip install faker httpx pytest pytest-asyncio pytest-cov pytest-mock pytest-randomly pytest-xdist starlette-prometheus uvicorn[standard]
42
42
  pytest tests --cov=src --cov-branch --cov-report=xml --junitxml=test_results.xml -n auto
@@ -15,18 +15,18 @@ jobs:
15
15
  strategy:
16
16
  fail-fast: false
17
17
  matrix:
18
- python-version: [ "3.10", "3.11", "3.12", "3.13"]
18
+ python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ]
19
19
  steps:
20
20
  - uses: actions/checkout@v5
21
21
  - name: Set up Python ${{ matrix.python-version }}
22
- uses: actions/setup-python@v5
22
+ uses: actions/setup-python@v6
23
23
  with:
24
24
  python-version: ${{ matrix.python-version }}
25
25
  - name: Install dependencies
26
26
  run: |
27
27
  python -m pip install --upgrade pip
28
28
  python -m pip install --upgrade setuptools wheel
29
- python -m pip install .
29
+ python -m pip install .[test]
30
30
  if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
31
31
  - name: Lint with flake8
32
32
  run: |
@@ -37,7 +37,7 @@ jobs:
37
37
  flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
38
38
  - name: Test with pytest
39
39
  run: |
40
- python -m pip install faker pytest pytest-asyncio pytest-cov pytest-mock pytest-randomly pytest-xdist starlette-prometheus uvicorn[standard]
40
+ python -m pip install faker httpx pytest pytest-asyncio pytest-cov pytest-mock pytest-randomly pytest-xdist starlette-prometheus uvicorn[standard]
41
41
  pytest tests --cov=src --cov-branch --cov-report=xml --junitxml=junit.xml -o junit_family=legacy -n auto
42
42
  - name: Upload coverage reports to Codecov
43
43
  uses: codecov/codecov-action@v5
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Graphinate
3
- Version: 0.8.6
3
+ Version: 0.9.0
4
4
  Summary: Graphinate. Data to Graphs.
5
5
  Project-URL: Homepage, https://erivlis.github.io/graphinate
6
6
  Project-URL: Documentation, https://erivlis.github.io/graphinate
@@ -22,18 +22,19 @@ Classifier: Programming Language :: Python :: 3.10
22
22
  Classifier: Programming Language :: Python :: 3.11
23
23
  Classifier: Programming Language :: Python :: 3.12
24
24
  Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
25
26
  Classifier: Programming Language :: Python :: Implementation :: CPython
26
27
  Classifier: Topic :: Scientific/Engineering
27
28
  Classifier: Topic :: Software Development :: Libraries
28
29
  Classifier: Typing :: Typed
29
- Requires-Python: >=3.10
30
+ Requires-Python: <3.15,>=3.10
30
31
  Requires-Dist: click
31
32
  Requires-Dist: inflect
32
33
  Requires-Dist: loguru
33
34
  Requires-Dist: mappingtools
34
35
  Requires-Dist: matplotlib
35
36
  Requires-Dist: networkx
36
- Requires-Dist: networkx-mermaid
37
+ Requires-Dist: networkx-mermaid>=0.3.0
37
38
  Requires-Dist: networkx-query>=2.1.3
38
39
  Requires-Dist: strawberry-graphql[asgi,opentelemetry]
39
40
  Provides-Extra: plot
@@ -73,7 +74,6 @@ Description-Content-Type: text/markdown
73
74
  <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>
74
75
  <a href="https://github.com/astral-sh/uv"><img alt="uv" src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json" style="max-width:100%;"></a>
75
76
  <a href="https://github.com/astral-sh/ruff"><img alt="ruff" src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" style="max-width:100%;"></a>
76
- <a href="https://github.com/tox-dev/pipdeptree"><img alt="pipdeptree" 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>
77
77
  <a href="https://squidfunk.github.io/mkdocs-material/"><img alt="mkdocs-material" src="https://img.shields.io/badge/Material_for_MkDocs-526CFE?&logo=MaterialForMkDocs&logoColor=white&labelColor=grey"></a>
78
78
  <a href="https://github.com/hukkin/mdformat"><img alt="mdformat" src="https://img.shields.io/badge/mdformat-526CFE?&logo=markdown&logoColor=white&labelColor=grey"></a>
79
79
  <a href="https://hatch.pypa.io"><img alt="Hatch project" class="off-glb" loading="lazy" src="https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg"></a>
@@ -28,7 +28,6 @@
28
28
  <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>
29
29
  <a href="https://github.com/astral-sh/uv"><img alt="uv" src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json" style="max-width:100%;"></a>
30
30
  <a href="https://github.com/astral-sh/ruff"><img alt="ruff" src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" style="max-width:100%;"></a>
31
- <a href="https://github.com/tox-dev/pipdeptree"><img alt="pipdeptree" 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>
32
31
  <a href="https://squidfunk.github.io/mkdocs-material/"><img alt="mkdocs-material" src="https://img.shields.io/badge/Material_for_MkDocs-526CFE?&logo=MaterialForMkDocs&logoColor=white&labelColor=grey"></a>
33
32
  <a href="https://github.com/hukkin/mdformat"><img alt="mdformat" src="https://img.shields.io/badge/mdformat-526CFE?&logo=markdown&logoColor=white&labelColor=grey"></a>
34
33
  <a href="https://hatch.pypa.io"><img alt="Hatch project" class="off-glb" loading="lazy" src="https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg"></a>
@@ -1,12 +1,12 @@
1
1
  [project]
2
2
  name = "Graphinate"
3
- version = "0.8.6"
3
+ version = "0.9.0"
4
4
  description = "Graphinate. Data to Graphs."
5
5
  authors = [
6
6
  { name = "Eran Rivlis", email = "eran@rivlis.info" },
7
7
  ]
8
8
  readme = "README.md"
9
- requires-python = ">=3.10"
9
+ requires-python = ">=3.10, <3.15"
10
10
  classifiers = [
11
11
  "Development Status :: 4 - Beta",
12
12
  "Intended Audience :: Developers",
@@ -17,6 +17,7 @@ classifiers = [
17
17
  "Programming Language :: Python :: 3.11",
18
18
  "Programming Language :: Python :: 3.12",
19
19
  "Programming Language :: Python :: 3.13",
20
+ "Programming Language :: Python :: 3.14",
20
21
  "Programming Language :: Python :: 3 :: Only",
21
22
  "Programming Language :: Python :: Implementation :: CPython",
22
23
  "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)",
@@ -34,7 +35,7 @@ dependencies = [
34
35
  "mappingtools",
35
36
  "matplotlib",
36
37
  "networkx",
37
- "networkx-mermaid",
38
+ "networkx-mermaid>=0.3.0",
38
39
  "networkx-query>=2.1.3",
39
40
  "strawberry-graphql[asgi,opentelemetry]",
40
41
  ]
@@ -57,7 +58,6 @@ server = [
57
58
 
58
59
  [dependency-groups]
59
60
  dev = [
60
- "pipdeptree",
61
61
  "ruff",
62
62
  "uv"
63
63
  ]
@@ -73,7 +73,7 @@ mdformat = [
73
73
  "mdformat-tables"
74
74
  ]
75
75
  docs = [
76
- "mkdocs-material",
76
+ "mkdocs-material>=9.6.22",
77
77
  "mkdocstrings-python",
78
78
  "mkdocs-git-committers-plugin-2",
79
79
  "mkdocs-git-revision-date-localized-plugin",
@@ -134,6 +134,10 @@ line-length = 120
134
134
  [tool.ruff]
135
135
  line-length = 120
136
136
 
137
+
138
+ [tool.ruff.format]
139
+ quote-style = "single"
140
+
137
141
  [tool.ruff.lint]
138
142
  select = [
139
143
  "E",
@@ -151,7 +155,7 @@ select = [
151
155
  "TRY",
152
156
  "RUF",
153
157
  ]
154
- ignore = ["TRY003", "UP007", "UP038", "RUF100"]
158
+ ignore = ["TRY003", "UP007", "RUF100"]
155
159
  # Exclude a variety of commonly ignored directories.
156
160
  exclude = [
157
161
  ".bzr",
@@ -65,6 +65,7 @@ class GraphType(Enum):
65
65
 
66
66
  See more here: [NetworkX Reference](https://networkx.org/documentation/stable/reference/classes)
67
67
  """
68
+
68
69
  Graph = nx.Graph
69
70
  DiGraph = nx.DiGraph
70
71
  MultiDiGraph = nx.MultiDiGraph
@@ -50,7 +50,7 @@ def color_hex(color: Union[str, Sequence[Union[float, int]]]) -> Union[str, Sequ
50
50
  If the input is a tuple or list, it should contain either three floats (0-1) or three ints (0-255).
51
51
  The function will convert these to a HEX color code.
52
52
  """
53
- if isinstance(color, (tuple, list)): # noqa: UP038
53
+ if isinstance(color, (tuple, list)):
54
54
  rgb = color[:3]
55
55
 
56
56
  if all(isinstance(c, float) and 0 <= c <= 1 for c in rgb):
@@ -293,18 +293,19 @@ class GraphModel:
293
293
  key: Extractor | None = None,
294
294
  value: Extractor | None = None,
295
295
  label: Extractor | None = None):
296
- """Rectify the model.
297
- Add a default NodeModel in case of having just edge supplier/s and no node supplier/s.
298
-
299
- Args:
300
- _type
301
- parent_type
302
- key
303
- value
304
- label
305
-
306
- Returns:
307
- None
296
+ """
297
+ Rectify the model.
298
+ Add a default NodeModel in case of having just edge supplier/s and no node supplier/s.
299
+
300
+ Args:
301
+ _type
302
+ parent_type
303
+ key
304
+ value
305
+ label
306
+
307
+ Returns:
308
+ None
308
309
  """
309
310
  if self._edge_generators and not self._node_models:
310
311
  @self.node(
@@ -321,7 +322,8 @@ class GraphModel:
321
322
 
322
323
 
323
324
  def model(name: str):
324
- """Create a graph model
325
+ """
326
+ Create a graph model
325
327
 
326
328
  Args:
327
329
  name: model name
@@ -28,7 +28,7 @@ def _openapi_schema(request: Request) -> ASGIApp:
28
28
  """
29
29
  schema_data = {
30
30
  'openapi': '3.0.0',
31
- 'info': {'title': 'Graphinate API', 'version': '0.8.6'},
31
+ 'info': {'title': 'Graphinate API', 'version': '0.9.0'},
32
32
  'paths': {
33
33
  '/graphql': {'get': {'responses': {200: {'description': 'GraphQL'}}}},
34
34
  '/graphiql': {'get': {'responses': {200: {'description': 'GraphiQL UI.'}}}},
@@ -51,7 +51,7 @@ def _graphql_app(graphql_schema: strawberry.Schema) -> strawberry.asgi.GraphQL:
51
51
  Returns:
52
52
  strawberry.asgi.GraphQL: The GraphQL app configured with the provided schema.
53
53
  """
54
- graphql_app = GraphQL(graphql_schema, graphiql=True)
54
+ graphql_app = GraphQL(graphql_schema, graphql_ide='apollo-sandbox')
55
55
  return graphql_app
56
56
 
57
57
 
@@ -1,7 +1,7 @@
1
1
  from collections.abc import Mapping
2
2
  from pathlib import Path
3
3
 
4
- from starlette.routing import Mount
4
+ from starlette.routing import Mount, Route
5
5
  from starlette.staticfiles import StaticFiles
6
6
 
7
7
  from ..web import paths_mapping
@@ -20,7 +20,7 @@ def _mount_static_files(named_paths: Mapping[str, Path]) -> list[Mount]:
20
20
 
21
21
 
22
22
  def routes():
23
- route_list = _mount_static_files(paths_mapping)
23
+ route_list: list[Mount | Route] = _mount_static_files(paths_mapping)
24
24
  route_list.append(favicon_route())
25
25
  return route_list
26
26
 
@@ -678,7 +678,8 @@
678
678
  // Tools tab
679
679
  const toolsTab = tab.pages[2];
680
680
 
681
- toolsTab.addButton({title: 'GraphiQL'}).on('click', () => createFloatingIFramePanel('/graphql', 'Graph<i>i</i>QL'));
681
+ toolsTab.addButton({title: 'GraphQL IDE'}).on('click', () => createFloatingIFramePanel('/graphql', 'GraphQL IDE'));
682
+ toolsTab.addButton({title: 'GraphiQL IDE'}).on('click', () => createFloatingIFramePanel('/graphiql', 'Graph<i>i</i>QL'));
682
683
  toolsTab.addButton({title: 'GraphQL Voyager'}).on('click', () => createFloatingIFramePanel('/voyager', 'GraphQL Voyager'));
683
684
  toolsTab.addButton({title: 'RapiDoc'}).on('click', () => createFloatingIFramePanel('/rapidoc', 'RapiDoc'));
684
685
  toolsTab.addButton({title: 'Metrics'}).on('click', () => createFloatingIFramePanel('/metrics', 'Metrics'));
@@ -20,11 +20,13 @@
20
20
  favored resource bundler.
21
21
  -->
22
22
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/graphql-voyager@2.1.0/dist/voyager.min.css"
23
- integrity="sha384-uMCIGmHGAsTeyZfkgMw5M+CF/2kHMpt0yzElhu917b4VDq1CYxICM7wH6VtQ9Loj"
23
+ integrity="sha384-vmH7DGotMxRpiyCozw3vBUhhRegQ+95ffgla9zXAPkysqRrrTbnP6tXtCaaZ0xOh"
24
24
  crossorigin="anonymous"/>
25
25
  <script src="https://cdn.jsdelivr.net/npm/graphql-voyager@2.1.0/dist/voyager.standalone.min.js"
26
- integrity="sha384-96gRbvjukmyGsZx2Ro23/DHwN8ViZuJ1+Qxc5ry2+sec4pY1sHtegQo1B99vW8YJ"
27
- crossorigin="anonymous"></script>
26
+ integrity="sha384-mk0ZutpNRnjwlDdrlmHl3kTRcjBmge8wx4x0GE26f1xPsXpkxKvR2MV11i+yYlyF"
27
+ crossorigin="anonymous"
28
+
29
+ ></script>
28
30
  </head>
29
31
  <body>
30
32
  <div id="voyager">Loading...</div>
@@ -0,0 +1,75 @@
1
+ """
2
+ Typing Module
3
+
4
+ Attributes:
5
+ Node (Node): Node Type
6
+ Edge (Edge): Edge Type
7
+ Element (Element): Element Type
8
+ Extractor (Extractor): Source of data for an Element
9
+ UniverseNode (UniverseNode): The Universe Node Type. All Node Types are the implicit children of UniverseNodeType.
10
+ """
11
+
12
+ from collections.abc import Callable, Iterable
13
+ from types import NoneType
14
+ from typing import Any, NamedTuple, NewType, Protocol, TypeAlias, TypeVar, Union
15
+
16
+ NodeTuple: TypeAlias = tuple[str, Any]
17
+ EdgeTuple: TypeAlias = tuple[str, str, Any]
18
+
19
+ IdentifierStr = NewType('IdentifierStr', str)
20
+ IdentifierStr.__doc__ = 'A string that is a valid Python identifier (i.e., `isidentifier()` is True).'
21
+
22
+ NodeTypeAbsoluteId = NewType('NodeTypeAbsoluteId', tuple[str, str])
23
+ NodeTypeAbsoluteId.__doc__ = 'A unique identifier for a node type.'
24
+
25
+ UniverseNode = NewType('UniverseNode', NoneType)
26
+ UniverseNode.__doc__ = 'The UniverseNode Type. All Node Types are the implicit children of the Universe Node Type.'
27
+
28
+ # A node in a graph.
29
+ Node = Union[type[NamedTuple], NodeTuple] # noqa: UP007
30
+
31
+ # An edge in a graph.
32
+ Edge = Union[type[NamedTuple], EdgeTuple] # noqa: UP007
33
+
34
+ # An element in a graph.
35
+ Element = Union[Node, Edge] # noqa: UP007
36
+
37
+ # A source of data for an element.
38
+ Extractor = Union[str, Callable[[Any], str]] # noqa: UP007
39
+
40
+ T = TypeVar('T')
41
+
42
+
43
+ class Items(Protocol):
44
+ """Protocol for callable objects that return an iterable of items."""
45
+
46
+ def __call__(self, **kwargs) -> Iterable[T]: # pragma: no cover
47
+ ...
48
+
49
+
50
+ class Nodes(Protocol):
51
+ """Protocol for callable objects that return an iterable of nodes."""
52
+
53
+ def __call__(self, **kwargs) -> Iterable[Node]: # pragma: no cover
54
+ ...
55
+
56
+
57
+ class Edges(Protocol):
58
+ """Protocol for callable objects that return an iterable of edges."""
59
+
60
+ def __call__(self, **kwargs) -> Iterable[Edge]: # pragma: no cover
61
+ ...
62
+
63
+
64
+ class Predicate(Protocol):
65
+ """Protocol for callable objects that evaluate a condition."""
66
+
67
+ def __call__(self, **kwargs) -> bool: # pragma: no cover
68
+ ...
69
+
70
+
71
+ class Supplier(Protocol):
72
+ """Protocol for callable objects that supply a value."""
73
+
74
+ def __call__(self) -> Any: # pragma: no cover
75
+ ...
@@ -52,7 +52,7 @@ def test_draw_with_node_labels_off(mocker):
52
52
  mock_node_color_mapping.assert_called_once_with(graph)
53
53
  mock_nx_draw.assert_called_once()
54
54
  # Check that 'with_labels' is not in the draw parameters
55
- args, kwargs = mock_nx_draw.call_args
55
+ _args, kwargs = mock_nx_draw.call_args
56
56
  assert 'with_labels' not in kwargs
57
57
 
58
58
 
@@ -108,7 +108,7 @@ def test_draw_with_both_labels_on(mocker):
108
108
  mock_nx_draw_edge_labels.assert_called_once()
109
109
 
110
110
  # Check that node labels are enabled
111
- args, kwargs = mock_nx_draw.call_args
111
+ _args, kwargs = mock_nx_draw.call_args
112
112
  assert kwargs.get('with_labels') is True
113
113
 
114
114
 
@@ -185,7 +185,7 @@ def test_draw_empty_graph(mocker):
185
185
  mock_nx_draw.assert_called_once()
186
186
 
187
187
  # Check that node_color is an empty list for empty graph
188
- args, kwargs = mock_nx_draw.call_args
188
+ _args, kwargs = mock_nx_draw.call_args
189
189
  assert kwargs.get('node_color') == []
190
190
 
191
191
 
@@ -215,7 +215,7 @@ def test_draw_no_node_labels_attribute(mocker):
215
215
  mock_nx_draw.assert_called_once()
216
216
 
217
217
  # Check that labels parameter is empty dict
218
- args, kwargs = mock_nx_draw.call_args
218
+ _args, kwargs = mock_nx_draw.call_args
219
219
  assert kwargs.get('labels') == {}
220
220
 
221
221
 
@@ -247,5 +247,5 @@ def test_draw_no_edge_labels_attribute(mocker):
247
247
  mock_nx_draw_edge_labels.assert_called_once()
248
248
 
249
249
  # Check that the edge_labels parameter is an empty dict
250
- args, kwargs = mock_nx_draw_edge_labels.call_args
250
+ _args, kwargs = mock_nx_draw_edge_labels.call_args
251
251
  assert kwargs.get('edge_labels') == {}
@@ -1,4 +1,3 @@
1
- # python
2
1
  import pytest
3
2
  from starlette.routing import Route
4
3
 
@@ -7,13 +6,13 @@ from graphinate.server.starlette import routes
7
6
 
8
7
  @pytest.fixture
9
8
  def mock_mount(mocker):
10
- return mocker.patch("graphinate.server.starlette.__init__.Mount")
9
+ return mocker.patch("graphinate.server.starlette.Mount")
11
10
 
12
11
 
13
12
  def test_routes_returns_static_and_favicon_routes(mocker):
14
13
  # Arrange
15
14
  mock_paths_mapping = {"static": mocker.Mock()}
16
- mocker.patch("graphinate.server.starlette.__init__.paths_mapping", mock_paths_mapping)
15
+ mocker.patch("graphinate.server.web.paths_mapping", mock_paths_mapping)
17
16
 
18
17
  # Act
19
18
  result = routes()
@@ -29,10 +28,10 @@ def test_favicon_route_appended_last(mocker):
29
28
  mock_paths_mapping = {"foo": mocker.Mock(), "bar": mocker.Mock()}
30
29
  static_mounts = ["foo_mount", "bar_mount"]
31
30
  mocker.patch(
32
- "graphinate.server.starlette.__init__._mount_static_files",
31
+ "graphinate.server.starlette._mount_static_files",
33
32
  return_value=static_mounts
34
33
  )
35
- mocker.patch("graphinate.server.starlette.__init__.paths_mapping", mock_paths_mapping)
34
+ mocker.patch("graphinate.server.starlette.paths_mapping", mock_paths_mapping)
36
35
 
37
36
  # Act
38
37
  result = routes()
@@ -48,10 +47,10 @@ def test_routes_with_non_empty_static_files(mocker):
48
47
  mock_paths_mapping = {"static": mocker.Mock()}
49
48
  static_mounts = ["static_mount"]
50
49
  mocker.patch(
51
- "graphinate.server.starlette.__init__._mount_static_files",
50
+ "graphinate.server.starlette._mount_static_files",
52
51
  return_value=static_mounts
53
52
  )
54
- mocker.patch("graphinate.server.starlette.__init__.paths_mapping", mock_paths_mapping)
53
+ mocker.patch("graphinate.server.starlette.paths_mapping", mock_paths_mapping)
55
54
 
56
55
  # Act
57
56
  result = routes()
@@ -65,10 +64,10 @@ def test_routes_with_empty_static_files(mocker):
65
64
  # Arrange
66
65
  mock_paths_mapping = {}
67
66
  mocker.patch(
68
- "graphinate.server.starlette.__init__._mount_static_files",
67
+ "graphinate.server.starlette._mount_static_files",
69
68
  return_value=[]
70
69
  )
71
- mocker.patch("graphinate.server.starlette.__init__.paths_mapping", mock_paths_mapping)
70
+ mocker.patch("graphinate.server.starlette.paths_mapping", mock_paths_mapping)
72
71
 
73
72
  # Act
74
73
  result = routes()
@@ -1,74 +0,0 @@
1
- """Typing Module
2
-
3
- Attributes:
4
- Node (Node): Node Type
5
- Edge (Edge): Edge Type
6
- Element (Element): Element Type
7
- Extractor (Extractor): Source of data for an Element
8
- UniverseNode (UniverseNode): The Universe Node Type. All Node Types are the implicit children UniverseNodeType.
9
- """
10
-
11
- from collections.abc import Callable, Iterable
12
- from types import NoneType
13
- from typing import Any, NamedTuple, NewType, Protocol, TypeAlias, TypeVar, Union
14
-
15
- NodeTuple: TypeAlias = tuple[str, Any]
16
- EdgeTuple: TypeAlias = tuple[str, str, Any]
17
-
18
- IdentifierStr = NewType('IdentifierStr', str)
19
- IdentifierStr.__doc__ = "A string that is a valid Python identifier (i.e., `isidentifier()` is True)."
20
-
21
- NodeTypeAbsoluteId = NewType('NodeTypeAbsoluteId', tuple[str, str])
22
- NodeTypeAbsoluteId.__doc__ = "A unique identifier for a node type."
23
-
24
- UniverseNode = NewType('UniverseNode', NoneType)
25
- UniverseNode.__doc__ = "The UniverseNode Type. All Node Types are the implicit children of the Universe Node Type."
26
-
27
- Node = Union[type[NamedTuple], NodeTuple] # noqa: UP007
28
- Node.__doc__ = "A node in a graph."
29
-
30
- Edge = Union[type[NamedTuple], EdgeTuple] # noqa: UP007
31
- Edge.__doc__ = "An edge in a graph."
32
-
33
- Element = Union[Node, Edge] # noqa: UP007
34
- Element.__doc__ = "An element in a graph."
35
-
36
- Extractor = Union[str, Callable[[Any], str]] # noqa: UP007
37
- Extractor.__doc__ = "A source of data for an element."
38
-
39
- T = TypeVar("T")
40
-
41
-
42
- class Items(Protocol):
43
- """Protocol for callable objects that return an iterable of items."""
44
-
45
- def __call__(self, **kwargs) -> Iterable[T]:
46
- ... # pragma: no cover
47
-
48
-
49
- class Nodes(Protocol):
50
- """Protocol for callable objects that return an iterable of nodes."""
51
-
52
- def __call__(self, **kwargs) -> Iterable[Node]:
53
- ... # pragma: no cover
54
-
55
-
56
- class Edges(Protocol):
57
- """Protocol for callable objects that return an iterable of edges."""
58
-
59
- def __call__(self, **kwargs) -> Iterable[Edge]:
60
- ... # pragma: no cover
61
-
62
-
63
- class Predicate(Protocol):
64
- """Protocol for callable objects that evaluate a condition."""
65
-
66
- def __call__(self, **kwargs) -> bool:
67
- ... # pragma: no cover
68
-
69
-
70
- class Supplier(Protocol):
71
- """Protocol for callable objects that supply a value."""
72
-
73
- def __call__(self) -> Any:
74
- ... # pragma: no cover
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