ogdf-py 0.1.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.
- ogdf_py-0.1.1/.github/workflows/build-publish.yml +190 -0
- ogdf_py-0.1.1/.github/workflows/ci.yml +63 -0
- ogdf_py-0.1.1/.gitignore +46 -0
- ogdf_py-0.1.1/CHANGELOG.md +55 -0
- ogdf_py-0.1.1/CMakeLists.txt +88 -0
- ogdf_py-0.1.1/LICENSE +22 -0
- ogdf_py-0.1.1/Makefile +157 -0
- ogdf_py-0.1.1/PKG-INFO +93 -0
- ogdf_py-0.1.1/README.md +74 -0
- ogdf_py-0.1.1/demos/README.md +38 -0
- ogdf_py-0.1.1/demos/_common.py +31 -0
- ogdf_py-0.1.1/demos/algorithms_visual.py +110 -0
- ogdf_py-0.1.1/demos/gallery.py +118 -0
- ogdf_py-0.1.1/demos/generators_zoo.py +36 -0
- ogdf_py-0.1.1/demos/io_roundtrip.py +54 -0
- ogdf_py-0.1.1/demos/layouts_gallery.py +61 -0
- ogdf_py-0.1.1/demos/run_all.py +34 -0
- ogdf_py-0.1.1/demos/styling_showcase.py +44 -0
- ogdf_py-0.1.1/pyproject.toml +50 -0
- ogdf_py-0.1.1/scripts/bootstrap_ogdf.sh +83 -0
- ogdf_py-0.1.1/src/ogdf/__init__.py +22 -0
- ogdf_py-0.1.1/src/ogdf/_core.cpp +18 -0
- ogdf_py-0.1.1/src/ogdf/bind_algorithms.cpp +208 -0
- ogdf_py-0.1.1/src/ogdf/bind_generators.cpp +62 -0
- ogdf_py-0.1.1/src/ogdf/bind_graph.cpp +279 -0
- ogdf_py-0.1.1/src/ogdf/bind_io.cpp +134 -0
- ogdf_py-0.1.1/src/ogdf/bind_layouts.cpp +222 -0
- ogdf_py-0.1.1/src/ogdf/bindings.h +18 -0
- ogdf_py-0.1.1/src/ogdf/py.typed +0 -0
- ogdf_py-0.1.1/tests/test_algorithms.py +189 -0
- ogdf_py-0.1.1/tests/test_generators.py +70 -0
- ogdf_py-0.1.1/tests/test_layouts.py +70 -0
- ogdf_py-0.1.1/tests/test_ogdf.py +270 -0
- ogdf_py-0.1.1/tests/test_styling.py +73 -0
- ogdf_py-0.1.1/uv.lock +1025 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
name: Build and Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main, master]
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
inputs:
|
|
11
|
+
publish:
|
|
12
|
+
description: "Publish to PyPI"
|
|
13
|
+
required: false
|
|
14
|
+
default: false
|
|
15
|
+
type: boolean
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
concurrency:
|
|
21
|
+
group: build-${{ github.workflow }}-${{ github.ref }}
|
|
22
|
+
cancel-in-progress: true
|
|
23
|
+
|
|
24
|
+
env:
|
|
25
|
+
# Build CPython 3.10-3.13; skip musllinux (OGDF is bootstrapped on
|
|
26
|
+
# manylinux/glibc) and PyPy.
|
|
27
|
+
CIBW_BUILD: "cp310-* cp311-* cp312-* cp313-*"
|
|
28
|
+
CIBW_SKIP: "*-musllinux_* pp*"
|
|
29
|
+
# Clone + build OGDF once per platform before building any wheels. On Linux
|
|
30
|
+
# this runs inside the manylinux container (git present; install cmake).
|
|
31
|
+
CIBW_BEFORE_ALL_LINUX: >-
|
|
32
|
+
(command -v cmake >/dev/null 2>&1 || pipx install cmake) &&
|
|
33
|
+
bash scripts/bootstrap_ogdf.sh
|
|
34
|
+
CIBW_BEFORE_ALL_MACOS: bash scripts/bootstrap_ogdf.sh
|
|
35
|
+
# Exercise each wheel end-to-end (import + layouts + I/O).
|
|
36
|
+
CIBW_TEST_REQUIRES: pytest
|
|
37
|
+
CIBW_TEST_COMMAND: pytest {project}/tests -v
|
|
38
|
+
|
|
39
|
+
jobs:
|
|
40
|
+
build-sdist:
|
|
41
|
+
name: Build source distribution
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v7
|
|
45
|
+
|
|
46
|
+
- name: Install uv
|
|
47
|
+
uses: astral-sh/setup-uv@v8.3.0
|
|
48
|
+
|
|
49
|
+
- name: Build sdist
|
|
50
|
+
run: uv build --sdist
|
|
51
|
+
|
|
52
|
+
- name: Upload sdist
|
|
53
|
+
uses: actions/upload-artifact@v7
|
|
54
|
+
with:
|
|
55
|
+
name: sdist
|
|
56
|
+
path: dist/*.tar.gz
|
|
57
|
+
retention-days: 14
|
|
58
|
+
|
|
59
|
+
build-wheels:
|
|
60
|
+
name: Wheels (${{ matrix.os }} / ${{ matrix.arch }})
|
|
61
|
+
runs-on: ${{ matrix.os }}
|
|
62
|
+
strategy:
|
|
63
|
+
fail-fast: false
|
|
64
|
+
matrix:
|
|
65
|
+
include:
|
|
66
|
+
# Native runners only -- no QEMU, no cross-compilation, so the OGDF
|
|
67
|
+
# static library always matches the wheel's architecture.
|
|
68
|
+
- os: ubuntu-latest
|
|
69
|
+
arch: x86_64
|
|
70
|
+
- os: ubuntu-24.04-arm
|
|
71
|
+
arch: aarch64
|
|
72
|
+
- os: macos-15-intel
|
|
73
|
+
arch: x86_64
|
|
74
|
+
macos_target: "10.15" # C++17 libc++ (<filesystem>) needs 10.15+
|
|
75
|
+
- os: macos-14
|
|
76
|
+
arch: arm64
|
|
77
|
+
macos_target: "11.0"
|
|
78
|
+
env:
|
|
79
|
+
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macos_target }}
|
|
80
|
+
steps:
|
|
81
|
+
- uses: actions/checkout@v7
|
|
82
|
+
|
|
83
|
+
# Cache the cloned+built OGDF per platform/arch so reruns skip the build.
|
|
84
|
+
- name: Cache OGDF
|
|
85
|
+
uses: actions/cache@v4
|
|
86
|
+
with:
|
|
87
|
+
path: thirdparty/ogdf
|
|
88
|
+
key: ogdf-${{ runner.os }}-${{ matrix.arch }}-${{ hashFiles('scripts/bootstrap_ogdf.sh') }}
|
|
89
|
+
|
|
90
|
+
- name: Build wheels
|
|
91
|
+
uses: pypa/cibuildwheel@v4.1.0
|
|
92
|
+
env:
|
|
93
|
+
CIBW_ARCHS: ${{ matrix.arch }}
|
|
94
|
+
|
|
95
|
+
- name: Upload wheels
|
|
96
|
+
uses: actions/upload-artifact@v7
|
|
97
|
+
with:
|
|
98
|
+
name: wheels-${{ matrix.os }}-${{ matrix.arch }}
|
|
99
|
+
path: wheelhouse/*.whl
|
|
100
|
+
retention-days: 14
|
|
101
|
+
|
|
102
|
+
collect-artifacts:
|
|
103
|
+
name: Collect all build artifacts
|
|
104
|
+
needs: [build-sdist, build-wheels]
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
steps:
|
|
107
|
+
- name: Download all artifacts
|
|
108
|
+
uses: actions/download-artifact@v8
|
|
109
|
+
with:
|
|
110
|
+
path: dist
|
|
111
|
+
pattern: "*"
|
|
112
|
+
merge-multiple: true
|
|
113
|
+
|
|
114
|
+
- name: List all artifacts
|
|
115
|
+
run: |
|
|
116
|
+
echo "=== All build artifacts ==="
|
|
117
|
+
ls -la dist/
|
|
118
|
+
wheels=$(find dist -name '*.whl' | wc -l)
|
|
119
|
+
sdists=$(find dist -name '*.tar.gz' | wc -l)
|
|
120
|
+
echo "=== Wheels: ${wheels} | Sdists: ${sdists} ==="
|
|
121
|
+
|
|
122
|
+
- name: Upload combined artifacts
|
|
123
|
+
uses: actions/upload-artifact@v7
|
|
124
|
+
with:
|
|
125
|
+
name: all-dist
|
|
126
|
+
path: dist/
|
|
127
|
+
retention-days: 30
|
|
128
|
+
|
|
129
|
+
publish-testpypi:
|
|
130
|
+
name: Publish to TestPyPI
|
|
131
|
+
needs: collect-artifacts
|
|
132
|
+
runs-on: ubuntu-latest
|
|
133
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
134
|
+
environment:
|
|
135
|
+
name: testpypi
|
|
136
|
+
url: https://test.pypi.org/p/ogdf-py
|
|
137
|
+
permissions:
|
|
138
|
+
id-token: write
|
|
139
|
+
steps:
|
|
140
|
+
- name: Download all artifacts
|
|
141
|
+
uses: actions/download-artifact@v8
|
|
142
|
+
with:
|
|
143
|
+
name: all-dist
|
|
144
|
+
path: dist/
|
|
145
|
+
|
|
146
|
+
- name: Publish to TestPyPI
|
|
147
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
148
|
+
with:
|
|
149
|
+
repository-url: https://test.pypi.org/legacy/
|
|
150
|
+
skip-existing: true
|
|
151
|
+
|
|
152
|
+
publish-pypi:
|
|
153
|
+
name: Publish to PyPI
|
|
154
|
+
needs: [collect-artifacts, publish-testpypi]
|
|
155
|
+
runs-on: ubuntu-latest
|
|
156
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
157
|
+
environment:
|
|
158
|
+
name: pypi
|
|
159
|
+
url: https://pypi.org/p/ogdf-py
|
|
160
|
+
permissions:
|
|
161
|
+
id-token: write
|
|
162
|
+
steps:
|
|
163
|
+
- name: Download all artifacts
|
|
164
|
+
uses: actions/download-artifact@v8
|
|
165
|
+
with:
|
|
166
|
+
name: all-dist
|
|
167
|
+
path: dist/
|
|
168
|
+
|
|
169
|
+
- name: Publish to PyPI
|
|
170
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
171
|
+
|
|
172
|
+
publish-manual:
|
|
173
|
+
name: Manual publish to PyPI
|
|
174
|
+
needs: collect-artifacts
|
|
175
|
+
runs-on: ubuntu-latest
|
|
176
|
+
if: github.event_name == 'workflow_dispatch' && inputs.publish
|
|
177
|
+
environment:
|
|
178
|
+
name: pypi
|
|
179
|
+
url: https://pypi.org/p/ogdf-py
|
|
180
|
+
permissions:
|
|
181
|
+
id-token: write
|
|
182
|
+
steps:
|
|
183
|
+
- name: Download all artifacts
|
|
184
|
+
uses: actions/download-artifact@v8
|
|
185
|
+
with:
|
|
186
|
+
name: all-dist
|
|
187
|
+
path: dist/
|
|
188
|
+
|
|
189
|
+
- name: Publish to PyPI
|
|
190
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, master]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
qa:
|
|
19
|
+
name: QA (lint, typecheck, test)
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v7
|
|
23
|
+
|
|
24
|
+
# Cache the cloned+built OGDF so most runs skip the ~2 min build.
|
|
25
|
+
# Keyed on the bootstrap script (which pins the OGDF tag).
|
|
26
|
+
- name: Cache OGDF
|
|
27
|
+
uses: actions/cache@v4
|
|
28
|
+
with:
|
|
29
|
+
path: thirdparty/ogdf
|
|
30
|
+
key: ogdf-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('scripts/bootstrap_ogdf.sh') }}
|
|
31
|
+
|
|
32
|
+
- name: Bootstrap OGDF
|
|
33
|
+
run: ./scripts/bootstrap_ogdf.sh
|
|
34
|
+
|
|
35
|
+
- name: Install uv
|
|
36
|
+
uses: astral-sh/setup-uv@v8.3.0
|
|
37
|
+
with:
|
|
38
|
+
enable-cache: true
|
|
39
|
+
|
|
40
|
+
- name: Set up Python
|
|
41
|
+
run: uv python install 3.13
|
|
42
|
+
|
|
43
|
+
- name: Install dependencies (builds the extension)
|
|
44
|
+
run: uv sync --dev
|
|
45
|
+
|
|
46
|
+
- name: Lint with ruff
|
|
47
|
+
run: uv run ruff check src/ tests/
|
|
48
|
+
|
|
49
|
+
- name: Check formatting with ruff
|
|
50
|
+
run: uv run ruff format --check src/ tests/
|
|
51
|
+
|
|
52
|
+
- name: Type check with mypy
|
|
53
|
+
run: uv run mypy src/ogdf tests/
|
|
54
|
+
|
|
55
|
+
- name: Run tests
|
|
56
|
+
run: uv run pytest tests/ -v --cov=src/ogdf --cov-report=xml
|
|
57
|
+
|
|
58
|
+
- name: Upload coverage
|
|
59
|
+
uses: codecov/codecov-action@v7
|
|
60
|
+
with:
|
|
61
|
+
files: coverage.xml
|
|
62
|
+
fail_ci_if_error: false
|
|
63
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
ogdf_py-0.1.1/.gitignore
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Build
|
|
2
|
+
build/
|
|
3
|
+
dist/
|
|
4
|
+
*.egg-info/
|
|
5
|
+
*.so
|
|
6
|
+
*.pyd
|
|
7
|
+
|
|
8
|
+
# folders
|
|
9
|
+
thirdparty/
|
|
10
|
+
|
|
11
|
+
# Virtual environments
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
.uv/
|
|
15
|
+
|
|
16
|
+
# Cache
|
|
17
|
+
__pycache__/
|
|
18
|
+
*.pyc
|
|
19
|
+
*.pyo
|
|
20
|
+
.pytest_cache/
|
|
21
|
+
.mypy_cache/
|
|
22
|
+
.ruff_cache/
|
|
23
|
+
|
|
24
|
+
# Coverage
|
|
25
|
+
.coverage
|
|
26
|
+
coverage.xml
|
|
27
|
+
htmlcov/
|
|
28
|
+
|
|
29
|
+
# CMake
|
|
30
|
+
CMakeCache.txt
|
|
31
|
+
CMakeFiles/
|
|
32
|
+
cmake_install.cmake
|
|
33
|
+
|
|
34
|
+
# IDE
|
|
35
|
+
.idea/
|
|
36
|
+
.vscode/
|
|
37
|
+
*.swp
|
|
38
|
+
*~
|
|
39
|
+
|
|
40
|
+
# OS
|
|
41
|
+
.DS_Store
|
|
42
|
+
|
|
43
|
+
# agentic
|
|
44
|
+
.claude
|
|
45
|
+
CLAUDE.md
|
|
46
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.1]
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- OGDF bindings (curated subset): `Graph`/`Node`/`Edge` with iteration; `NodeArray`/`EdgeArray` in int/double/bool; `GraphAttributes` with coordinates, size, labels, and styling (colors, shapes, fill patterns, stroke, edge arrows, bends).
|
|
14
|
+
|
|
15
|
+
- Layout algorithms: `SugiyamaLayout`, `FMMMLayout`, `GEMLayout`, `SpringEmbedderKK`, `StressMinimization`, `PivotMDS`, `PlanarizationLayout` (with optional orthogonal routing), `SchnyderLayout`, `TreeLayout`, `CircularLayout`.
|
|
16
|
+
|
|
17
|
+
- Core graph algorithms: connectivity/structure predicates, connected / strong / biconnected components, topological numbering, Dijkstra shortest paths, minimum spanning tree, maximum flow, global minimum cut, matching, node coloring, and planar embedding.
|
|
18
|
+
|
|
19
|
+
- Graph generators: complete, complete-bipartite, wheel, cube, grid, Petersen, regular tree, plus random graphs, trees, digraphs, and regular / biconnected / planar variants.
|
|
20
|
+
|
|
21
|
+
- File I/O: interchange formats GML, GraphML, DOT, GEXF, GDF, TLP (with extension-based `read`/`write`) and drawing output as SVG and TikZ.
|
|
22
|
+
|
|
23
|
+
- `demos/` folder with illustrative scripts (layout gallery, styling showcase, algorithm visualizations, generator zoo, I/O round-trips) writing to `build/demo-output`; `make demos` also builds a self-contained HTML gallery (`index.html`) of every drawing.
|
|
24
|
+
|
|
25
|
+
- Bindings split into modular translation units (`bind_graph`, `bind_layouts`, `bind_algorithms`, `bind_io`, `bind_generators`).
|
|
26
|
+
|
|
27
|
+
- Auto-generated `_core.pyi` type stub for typed usage and IDE completion.
|
|
28
|
+
|
|
29
|
+
- `cibuildwheel` release workflow building CPython 3.10-3.13 wheels for Linux (x86_64, aarch64) and macOS (x86_64, arm64) on native runners, bootstrapping OGDF once per platform; trusted-publishing jobs for TestPyPI/PyPI on tags.
|
|
30
|
+
|
|
31
|
+
- CMake auto-bootstraps OGDF if missing, so `pip install` from an sdist works without a manual step (Unix only).
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- Reproducible OGDF dependency: `scripts/bootstrap_ogdf.sh` shallow-clones OGDF at a pinned tag (`foxglove-202510`) and builds its static libraries from source; the extension links them. `make build`/`make sync` auto-bootstrap if needed. Replaces reliance on a manually placed OGDF checkout.
|
|
36
|
+
|
|
37
|
+
- Persist the CMake build directory so only the bindings recompile on edits.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- `make build` targeted the wrong package name (`ogdf` vs `ogdf-py`), making it a silent no-op; it now rebuilds correctly.
|
|
42
|
+
|
|
43
|
+
- The generic `write` now raises `ValueError` for attribute-incapable formats (e.g. LEDA, Chaco) instead of crashing the interpreter.
|
|
44
|
+
|
|
45
|
+
## [0.1.0] - 2026-07-06
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- Initial project structure
|
|
50
|
+
|
|
51
|
+
- Core module with example functions
|
|
52
|
+
|
|
53
|
+
- Test suite with pytest
|
|
54
|
+
|
|
55
|
+
- Build system using scikit-build-core
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.15...3.31)
|
|
2
|
+
project(${SKBUILD_PROJECT_NAME} VERSION ${SKBUILD_PROJECT_VERSION} LANGUAGES CXX)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
5
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
7
|
+
|
|
8
|
+
find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)
|
|
9
|
+
find_package(nanobind CONFIG REQUIRED)
|
|
10
|
+
find_package(Threads REQUIRED)
|
|
11
|
+
|
|
12
|
+
# --- OGDF (prebuilt static libraries) ---------------------------------------
|
|
13
|
+
# OGDF is cloned at a pinned tag and built from source by
|
|
14
|
+
# scripts/bootstrap_ogdf.sh, which produces libOGDF.a / libCOIN.a and the
|
|
15
|
+
# generated config header. We link those static libs into the extension.
|
|
16
|
+
set(OGDF_ROOT "${CMAKE_SOURCE_DIR}/thirdparty/ogdf")
|
|
17
|
+
set(OGDF_BUILD "${OGDF_ROOT}/build")
|
|
18
|
+
|
|
19
|
+
# If OGDF has not been built yet, try to bootstrap it automatically (clone the
|
|
20
|
+
# pinned tag + build from source). This lets `pip install` from an sdist work
|
|
21
|
+
# without a separate manual step. Windows is not supported by the bash script.
|
|
22
|
+
if(NOT EXISTS "${OGDF_BUILD}/libOGDF.a"
|
|
23
|
+
AND EXISTS "${CMAKE_SOURCE_DIR}/scripts/bootstrap_ogdf.sh"
|
|
24
|
+
AND NOT WIN32)
|
|
25
|
+
message(STATUS "OGDF not built; running scripts/bootstrap_ogdf.sh ...")
|
|
26
|
+
execute_process(
|
|
27
|
+
COMMAND bash "${CMAKE_SOURCE_DIR}/scripts/bootstrap_ogdf.sh"
|
|
28
|
+
RESULT_VARIABLE _ogdf_bootstrap_result)
|
|
29
|
+
if(NOT _ogdf_bootstrap_result EQUAL 0)
|
|
30
|
+
message(FATAL_ERROR
|
|
31
|
+
"OGDF bootstrap failed (exit ${_ogdf_bootstrap_result}).")
|
|
32
|
+
endif()
|
|
33
|
+
endif()
|
|
34
|
+
|
|
35
|
+
if(NOT EXISTS "${OGDF_BUILD}/libOGDF.a")
|
|
36
|
+
message(FATAL_ERROR
|
|
37
|
+
"Prebuilt OGDF not found at ${OGDF_BUILD}/libOGDF.a.\n"
|
|
38
|
+
"Run the bootstrap script first:\n"
|
|
39
|
+
" scripts/bootstrap_ogdf.sh\n"
|
|
40
|
+
"(or `make bootstrap`), which clones OGDF at a pinned tag and builds it.")
|
|
41
|
+
endif()
|
|
42
|
+
|
|
43
|
+
# Public headers plus the build-time generated config header
|
|
44
|
+
# (config_autogen.h lives under build/include/ogdf-release).
|
|
45
|
+
set(OGDF_INCLUDE_DIRS
|
|
46
|
+
"${OGDF_ROOT}/include"
|
|
47
|
+
"${OGDF_BUILD}/include/ogdf-release")
|
|
48
|
+
|
|
49
|
+
set(OGDF_LIBRARIES
|
|
50
|
+
"${OGDF_BUILD}/libOGDF.a"
|
|
51
|
+
"${OGDF_BUILD}/libCOIN.a"
|
|
52
|
+
Threads::Threads)
|
|
53
|
+
|
|
54
|
+
nanobind_add_module(_core
|
|
55
|
+
src/ogdf/_core.cpp
|
|
56
|
+
src/ogdf/bind_graph.cpp
|
|
57
|
+
src/ogdf/bind_layouts.cpp
|
|
58
|
+
src/ogdf/bind_algorithms.cpp
|
|
59
|
+
src/ogdf/bind_io.cpp
|
|
60
|
+
src/ogdf/bind_generators.cpp)
|
|
61
|
+
|
|
62
|
+
target_include_directories(_core PRIVATE ${OGDF_INCLUDE_DIRS})
|
|
63
|
+
target_link_libraries(_core PRIVATE ${OGDF_LIBRARIES})
|
|
64
|
+
|
|
65
|
+
if(MSVC)
|
|
66
|
+
target_compile_options(_core PRIVATE /W4)
|
|
67
|
+
else()
|
|
68
|
+
target_compile_options(_core PRIVATE -Wall -Wextra)
|
|
69
|
+
endif()
|
|
70
|
+
|
|
71
|
+
install(TARGETS _core DESTINATION ogdf)
|
|
72
|
+
|
|
73
|
+
# Generate a type stub (_core.pyi) so the compiled module is typed for mypy and
|
|
74
|
+
# IDEs. nanobind imports the built module and introspects it at build time.
|
|
75
|
+
nanobind_add_stub(
|
|
76
|
+
_core_stub
|
|
77
|
+
MODULE _core
|
|
78
|
+
OUTPUT _core.pyi
|
|
79
|
+
PYTHON_PATH $<TARGET_FILE_DIR:_core>
|
|
80
|
+
DEPENDS _core
|
|
81
|
+
)
|
|
82
|
+
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/_core.pyi DESTINATION ogdf)
|
|
83
|
+
|
|
84
|
+
# Ship py.typed alongside the compiled module + stub. In an editable install the
|
|
85
|
+
# pure-Python files (including src/ogdf/py.typed) stay in the source tree, so
|
|
86
|
+
# without this the site-packages ogdf/ dir has _core.pyi but no py.typed marker,
|
|
87
|
+
# and mypy refuses to use the stub.
|
|
88
|
+
install(FILES ${CMAKE_SOURCE_DIR}/src/ogdf/py.typed DESTINATION ogdf)
|
ogdf_py-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 Shakeeb Alireza
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
ogdf_py-0.1.1/Makefile
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Makefile frontend for scikit-build-core project
|
|
2
|
+
# Generated by buildgen for: ogdf
|
|
3
|
+
#
|
|
4
|
+
# This Makefile wraps common build commands for convenience.
|
|
5
|
+
# The actual build is handled by scikit-build-core via pyproject.toml
|
|
6
|
+
|
|
7
|
+
.PHONY: all bootstrap sync build rebuild test demos lint lint-check format format-check typecheck qa clean distclean wheel sdist dist check publish-test publish upgrade coverage coverage-html docs release help
|
|
8
|
+
|
|
9
|
+
# Prebuilt OGDF static library; its presence marks a completed bootstrap.
|
|
10
|
+
OGDF_LIB := thirdparty/ogdf/build/libOGDF.a
|
|
11
|
+
|
|
12
|
+
# Default target
|
|
13
|
+
all: build
|
|
14
|
+
|
|
15
|
+
# Clone OGDF at the pinned tag and build its static libraries from source.
|
|
16
|
+
bootstrap:
|
|
17
|
+
@./scripts/bootstrap_ogdf.sh
|
|
18
|
+
|
|
19
|
+
# Auto-bootstrap: build OGDF only if it has not been built yet.
|
|
20
|
+
$(OGDF_LIB):
|
|
21
|
+
@./scripts/bootstrap_ogdf.sh
|
|
22
|
+
|
|
23
|
+
# Sync environment (initial setup, installs dependencies + package)
|
|
24
|
+
sync: $(OGDF_LIB)
|
|
25
|
+
@uv sync
|
|
26
|
+
|
|
27
|
+
# Build/rebuild the extension after code changes.
|
|
28
|
+
# The distribution is named "ogdf-py" (see pyproject.toml); --refresh-package
|
|
29
|
+
# busts uv's build cache so C++ source edits are actually recompiled.
|
|
30
|
+
build: $(OGDF_LIB)
|
|
31
|
+
@uv sync --reinstall-package ogdf-py --refresh-package ogdf-py
|
|
32
|
+
|
|
33
|
+
# Alias for build
|
|
34
|
+
rebuild: build
|
|
35
|
+
|
|
36
|
+
# Run tests
|
|
37
|
+
test:
|
|
38
|
+
@uv run pytest tests/ -v
|
|
39
|
+
|
|
40
|
+
# Run the illustrative demos (writes SVGs and data files to build/demo-output)
|
|
41
|
+
demos:
|
|
42
|
+
@uv run python demos/run_all.py
|
|
43
|
+
|
|
44
|
+
# Lint with ruff (applies fixes)
|
|
45
|
+
lint:
|
|
46
|
+
@uv run ruff check --fix src/ tests/
|
|
47
|
+
|
|
48
|
+
# Lint with ruff (check only, no fixes)
|
|
49
|
+
lint-check:
|
|
50
|
+
@uv run ruff check src/ tests/
|
|
51
|
+
|
|
52
|
+
# Format with ruff
|
|
53
|
+
format:
|
|
54
|
+
@uv run ruff format src/ tests/
|
|
55
|
+
|
|
56
|
+
# Check formatting without modifying files
|
|
57
|
+
format-check:
|
|
58
|
+
@uv run ruff format --check src/ tests/
|
|
59
|
+
|
|
60
|
+
# Type check with mypy
|
|
61
|
+
typecheck:
|
|
62
|
+
@uv run mypy src/ogdf
|
|
63
|
+
|
|
64
|
+
# Run a full quality assurance check (non-mutating; mirrors CI)
|
|
65
|
+
qa: lint-check format-check typecheck test
|
|
66
|
+
|
|
67
|
+
# Build wheel
|
|
68
|
+
wheel:
|
|
69
|
+
@uv build --wheel
|
|
70
|
+
|
|
71
|
+
# Build source distribution
|
|
72
|
+
sdist:
|
|
73
|
+
@uv build --sdist
|
|
74
|
+
|
|
75
|
+
# Check distributions with twine
|
|
76
|
+
check:
|
|
77
|
+
@uv run twine check dist/*
|
|
78
|
+
|
|
79
|
+
# Build both wheel and sdist
|
|
80
|
+
dist: wheel sdist check
|
|
81
|
+
|
|
82
|
+
# Publish to TestPyPI
|
|
83
|
+
publish-test: check
|
|
84
|
+
@uv run twine upload --repository testpypi dist/*
|
|
85
|
+
|
|
86
|
+
# Publish to PyPI
|
|
87
|
+
publish: check
|
|
88
|
+
@uv run twine upload dist/*
|
|
89
|
+
|
|
90
|
+
# Upgrade all dependencies
|
|
91
|
+
upgrade:
|
|
92
|
+
@uv lock --upgrade
|
|
93
|
+
@uv sync
|
|
94
|
+
|
|
95
|
+
# Run tests with coverage
|
|
96
|
+
coverage:
|
|
97
|
+
@uv run pytest tests/ -v --cov=src/ogdf --cov-report=term-missing
|
|
98
|
+
|
|
99
|
+
# Generate HTML coverage report
|
|
100
|
+
coverage-html:
|
|
101
|
+
@uv run pytest tests/ -v --cov=src/ogdf --cov-report=html
|
|
102
|
+
@echo "Coverage report: htmlcov/index.html"
|
|
103
|
+
|
|
104
|
+
# Build documentation (requires sphinx in dev dependencies)
|
|
105
|
+
docs:
|
|
106
|
+
@uv run sphinx-build -b html docs/ docs/_build/html
|
|
107
|
+
|
|
108
|
+
# Create a release (bump version, tag, push)
|
|
109
|
+
release:
|
|
110
|
+
@echo "Current version: $$(grep '^version' pyproject.toml | head -1)"
|
|
111
|
+
@read -p "New version: " version; sed "s/^version = .*/version = \"$$version\"/" pyproject.toml > pyproject.toml.tmp && mv pyproject.toml.tmp pyproject.toml; git add pyproject.toml; git commit -m "Bump version to $$version"; git tag -a "v$$version" -m "Release $$version"; echo "Tagged v$$version. Run 'git push && git push --tags' to publish."
|
|
112
|
+
|
|
113
|
+
# Clean build artifacts
|
|
114
|
+
clean:
|
|
115
|
+
@rm -rf build/
|
|
116
|
+
@rm -rf dist/
|
|
117
|
+
@rm -rf *.egg-info/
|
|
118
|
+
@rm -rf src/*.egg-info/
|
|
119
|
+
@rm -rf .pytest_cache/
|
|
120
|
+
@find . -name "*.so" -delete
|
|
121
|
+
@find . -name "*.pyd" -delete
|
|
122
|
+
@find . -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
|
|
123
|
+
|
|
124
|
+
# Clean everything including CMake cache
|
|
125
|
+
distclean: clean
|
|
126
|
+
@rm -rf CMakeCache.txt CMakeFiles/
|
|
127
|
+
|
|
128
|
+
# Show help
|
|
129
|
+
help:
|
|
130
|
+
@echo "Available targets:"
|
|
131
|
+
@echo " all - Build/rebuild the extension (default)"
|
|
132
|
+
@echo " bootstrap - Clone OGDF at the pinned tag and build it from source"
|
|
133
|
+
@echo " sync - Sync environment (initial setup)"
|
|
134
|
+
@echo " build - Rebuild extension after code changes"
|
|
135
|
+
@echo " rebuild - Alias for build"
|
|
136
|
+
@echo " test - Run tests"
|
|
137
|
+
@echo " demos - Run demos (output to build/demo-output)"
|
|
138
|
+
@echo " lint - Lint with ruff (applies fixes)"
|
|
139
|
+
@echo " lint-check - Lint with ruff (check only)"
|
|
140
|
+
@echo " format - Format with ruff"
|
|
141
|
+
@echo " format-check - Check formatting without modifying files"
|
|
142
|
+
@echo " typecheck - Type check with mypy"
|
|
143
|
+
@echo " qa - Run full quality assurance (non-mutating: lint-check, format-check, typecheck, test)"
|
|
144
|
+
@echo " wheel - Build wheel distribution"
|
|
145
|
+
@echo " sdist - Build source distribution"
|
|
146
|
+
@echo " dist - Build both wheel and sdist"
|
|
147
|
+
@echo " check - Check distributions with twine"
|
|
148
|
+
@echo " publish-test - Publish to TestPyPI"
|
|
149
|
+
@echo " publish - Publish to PyPI"
|
|
150
|
+
@echo " upgrade - Upgrade all dependencies"
|
|
151
|
+
@echo " coverage - Run tests with coverage"
|
|
152
|
+
@echo " coverage-html- Generate HTML coverage report"
|
|
153
|
+
@echo " docs - Build documentation with Sphinx"
|
|
154
|
+
@echo " release - Bump version, tag, and prepare release"
|
|
155
|
+
@echo " clean - Remove build artifacts"
|
|
156
|
+
@echo " distclean - Remove all generated files"
|
|
157
|
+
@echo " help - Show this help message"
|