dynaplex 0.2.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.
@@ -0,0 +1,93 @@
1
+ name: Publish (PyPI – reuse artifacts)
2
+
3
+ on:
4
+ push:
5
+ tags: [ "v*" ] # e.g. v0.1.0
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ id-token: write
10
+ contents: read
11
+ actions: read
12
+
13
+ concurrency:
14
+ group: ${{ github.workflow }}-${{ github.ref }}
15
+ cancel-in-progress: true
16
+
17
+ jobs:
18
+ fetch-and-publish:
19
+ runs-on: ubuntu-latest
20
+ environment: pypi
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+
24
+ - name: Set up Python
25
+ uses: actions/setup-python@v5
26
+ with:
27
+ python-version: "3.12"
28
+ cache: "pip"
29
+
30
+ # Wheels from wheels workflow (download all OS-specific artifacts)
31
+ - name: Download wheel artifacts
32
+ uses: dawidd6/action-download-artifact@v3
33
+ with:
34
+ workflow: wheels.yaml
35
+ commit: ${{ github.sha }}
36
+ name: wheels-.*
37
+ name_is_regexp: true # match wheels-ubuntu, wheels-macos, wheels-windows
38
+ path: dist
39
+ workflow_conclusion: success
40
+
41
+ # sdist from sdist workflow
42
+ - name: Download sdist artifact
43
+ uses: dawidd6/action-download-artifact@v3
44
+ with:
45
+ workflow: sdist.yaml
46
+ commit: ${{ github.sha }}
47
+ name: sdist
48
+ path: dist
49
+ workflow_conclusion: success
50
+
51
+ # Flatten nested artifact dirs into a single folder for upload
52
+ - name: Collect distributions
53
+ run: |
54
+ mkdir -p dist_flat
55
+ find dist -type f \( -name "*.whl" -o -name "*.tar.gz" \) -exec cp {} dist_flat/ \;
56
+ echo "Contents to publish:"
57
+ ls -l dist_flat
58
+
59
+ # Optional: verify tag matches project version
60
+ - name: Check tag matches pyproject version
61
+ if: startsWith(github.ref, 'refs/tags/')
62
+ run: |
63
+ python - <<'PY'
64
+ import os, sys
65
+ try:
66
+ import tomllib
67
+ except Exception:
68
+ import tomli as tomllib
69
+ with open("pyproject.toml","rb") as f:
70
+ data = tomllib.load(f)
71
+ version = data["project"]["version"]
72
+ tag = os.environ["GITHUB_REF_NAME"].lstrip("v")
73
+ if version != tag:
74
+ print(f"ERROR: tag v{tag} != pyproject version {version}")
75
+ sys.exit(1)
76
+ print(f"OK: tag v{tag} matches pyproject version {version}")
77
+ PY
78
+
79
+ # Fail early if nothing was collected
80
+ - name: Ensure distributions exist
81
+ run: |
82
+ shopt -s nullglob
83
+ files=(dist_flat/*.whl dist_flat/*.tar.gz)
84
+ if [ ${#files[@]} -eq 0 ]; then
85
+ echo "No distributions found in dist_flat/"
86
+ exit 1
87
+ fi
88
+
89
+ - name: Publish to PyPI (OIDC)
90
+ uses: pypa/gh-action-pypi-publish@release/v1
91
+ with:
92
+ packages-dir: dist_flat
93
+ skip-existing: true
@@ -0,0 +1,46 @@
1
+ name: Build sdist
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ tags: [ 'v*' ]
7
+ paths:
8
+ - "src/**"
9
+ - "include/**"
10
+ - "CMakeLists.txt"
11
+ - "pyproject.toml"
12
+ - ".github/workflows/**"
13
+ pull_request:
14
+ paths:
15
+ - "src/**"
16
+ - "include/**"
17
+ - "CMakeLists.txt"
18
+ - "pyproject.toml"
19
+ - ".github/workflows/**"
20
+
21
+ concurrency:
22
+ group: ${{ github.workflow }}-${{ github.ref }}
23
+ cancel-in-progress: true
24
+
25
+ jobs:
26
+ sdist:
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: actions/setup-python@v5
31
+ with:
32
+ python-version: "3.12"
33
+ cache: "pip"
34
+ - name: Build sdist
35
+ run: |
36
+ python -m pip install --upgrade pip build
37
+ python -m build --sdist
38
+ ls -l dist || true
39
+ - name: Upload sdist
40
+ if: ${{ hashFiles('dist/*.tar.gz') != '' }}
41
+ uses: actions/upload-artifact@v4
42
+ with:
43
+ name: sdist
44
+ path: dist/*.tar.gz
45
+ if-no-files-found: error
46
+ retention-days: 7
@@ -0,0 +1,96 @@
1
+ name: Publish (TestPyPI – reuse artifacts)
2
+
3
+ on:
4
+ push:
5
+ tags: [ "v*" ] # e.g. v0.1.0
6
+ workflow_dispatch:
7
+
8
+ # Needed to read other workflows' runs/artifacts
9
+ permissions:
10
+ actions: read
11
+ contents: read
12
+
13
+ concurrency:
14
+ group: ${{ github.workflow }}-${{ github.ref }}
15
+ cancel-in-progress: true
16
+
17
+ jobs:
18
+ fetch-and-publish:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Set up Python
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: "3.12"
27
+ cache: "pip"
28
+
29
+ # Wheels from wheels workflow (download all OS-specific artifacts)
30
+ - name: Download wheel artifacts
31
+ uses: dawidd6/action-download-artifact@v3
32
+ with:
33
+ workflow: wheels.yaml
34
+ commit: ${{ github.sha }}
35
+ name: wheels-.*
36
+ name_is_regexp: true # match wheels-ubuntu, wheels-macos, wheels-windows
37
+ path: dist
38
+ workflow_conclusion: success
39
+
40
+ # sdist from sdist workflow
41
+ - name: Download sdist artifact
42
+ uses: dawidd6/action-download-artifact@v3
43
+ with:
44
+ workflow: sdist.yaml
45
+ commit: ${{ github.sha }}
46
+ name: sdist
47
+ path: dist
48
+ workflow_conclusion: success
49
+
50
+ # Flatten nested artifact dirs into a single folder for upload
51
+ - name: Collect distributions
52
+ run: |
53
+ mkdir -p dist_flat
54
+ find dist -type f \( -name "*.whl" -o -name "*.tar.gz" \) -exec cp {} dist_flat/ \;
55
+ echo "Contents to publish:"
56
+ ls -l dist_flat
57
+
58
+ # Optional: verify tag matches project version
59
+ - name: Check tag matches pyproject version
60
+ if: startsWith(github.ref, 'refs/tags/')
61
+ run: |
62
+ python - <<'PY'
63
+ import os, sys
64
+ try:
65
+ import tomllib
66
+ except Exception:
67
+ import tomli as tomllib
68
+ with open("pyproject.toml","rb") as f:
69
+ data = tomllib.load(f)
70
+ version = data["project"]["version"]
71
+ tag = os.environ["GITHUB_REF_NAME"].lstrip("v")
72
+ if version != tag:
73
+ print(f"ERROR: tag v{tag} != pyproject version {version}")
74
+ sys.exit(1)
75
+ print(f"OK: tag v{tag} matches pyproject version {version}")
76
+ PY
77
+
78
+ # Fail early if nothing was collected
79
+ - name: Ensure distributions exist
80
+ run: |
81
+ shopt -s nullglob
82
+ files=(dist_flat/*.whl dist_flat/*.tar.gz)
83
+ if [ ${#files[@]} -eq 0 ]; then
84
+ echo "No distributions found in dist_flat/"
85
+ exit 1
86
+ fi
87
+
88
+ # Publish to TestPyPI
89
+ - name: Publish to TestPyPI
90
+ uses: pypa/gh-action-pypi-publish@release/v1
91
+ with:
92
+ repository-url: https://test.pypi.org/legacy/
93
+ user: __token__
94
+ password: ${{ secrets.TEST_PYPI_API_TOKEN }}
95
+ packages-dir: dist_flat
96
+ skip-existing: true
@@ -0,0 +1,76 @@
1
+ name: Build wheels
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ tags: [ 'v*' ]
7
+ paths:
8
+ - "src/**"
9
+ - "include/**"
10
+ - "tests/**"
11
+ - "CMakeLists.txt"
12
+ - "pyproject.toml"
13
+ - ".github/workflows/**"
14
+ pull_request:
15
+ paths:
16
+ - "src/**"
17
+ - "include/**"
18
+ - "tests/**"
19
+ - "CMakeLists.txt"
20
+ - "pyproject.toml"
21
+ - ".github/workflows/**"
22
+
23
+ concurrency:
24
+ group: ${{ github.workflow }}-${{ github.ref }}
25
+ cancel-in-progress: true
26
+
27
+ jobs:
28
+ wheels:
29
+ name: Wheels • ${{ matrix.os }}
30
+ runs-on: ${{ matrix.os }}
31
+ strategy:
32
+ fail-fast: false
33
+ matrix:
34
+ os: [ubuntu-latest, windows-latest] # , macos-latest, windows-latest]
35
+
36
+ steps:
37
+ - uses: actions/checkout@v4
38
+
39
+ - name: Set up Python (runner)
40
+ uses: actions/setup-python@v5
41
+ with:
42
+ python-version: "3.12"
43
+ cache: "pip"
44
+
45
+ - name: Install build tooling
46
+ run: |
47
+ python -m pip install --upgrade pip
48
+ python -m pip install cibuildwheel==2.*
49
+
50
+ - name: Build wheels with cibuildwheel
51
+ env:
52
+ # Target CPython versions
53
+ CIBW_BUILD: "cp313-*" # cp310-* cp311-* cp312-*
54
+ CIBW_SKIP: "pp* *-musllinux_*"
55
+ # Run tests inside wheel env
56
+ CIBW_TEST_REQUIRES: "pytest"
57
+ CIBW_TEST_COMMAND: "pytest -q {project}/tests"
58
+ # Architectures
59
+ CIBW_ARCHS_LINUX: "x86_64"
60
+ CIBW_ARCHS_MACOS: "universal2"
61
+ # Install ccache in build envs
62
+ CIBW_BEFORE_BUILD_LINUX: "yum -y install ccache || true"
63
+ CIBW_BEFORE_BUILD_MACOS: "brew install ccache || true"
64
+ CIBW_BEFORE_BUILD_WINDOWS: "choco install -y ccache || ver>NUL"
65
+ # Speed up CMake builds
66
+ CIBW_ENVIRONMENT: >
67
+ CMAKE_BUILD_PARALLEL_LEVEL=4
68
+ CMAKE_CXX_COMPILER_LAUNCHER=ccache
69
+ run: python -m cibuildwheel --output-dir wheelhouse
70
+
71
+ - name: Upload wheels
72
+ uses: actions/upload-artifact@v4
73
+ with:
74
+ name: wheels-${{ matrix.os }}
75
+ path: wheelhouse/*.whl
76
+ retention-days: 7
@@ -0,0 +1,43 @@
1
+ __pycache__/
2
+ *.pyc
3
+ build/
4
+ cmake-build*/
5
+ CMakeCache.txt
6
+ CMakeFiles/
7
+ *.egg-info/
8
+ install/
9
+ .dist/
10
+ dist/
11
+ wheelhouse/
12
+ out/
13
+
14
+
15
+ # Visual Studio user-specific files
16
+ .vs/
17
+ *.suo
18
+ *.user
19
+ *.userosscache
20
+ *.sln.docstates
21
+
22
+ # Visual Studio database/cache
23
+ *.db
24
+ *.db-shm
25
+ *.db-wal
26
+ *.opendb
27
+ *.VC.db
28
+ *.VC.opendb
29
+
30
+ # Visual Studio project/solution if auto-generated
31
+ *.vcxproj*
32
+ *.vcproj*
33
+ *.vcxproj.filters
34
+
35
+ # Other IDE clutter
36
+ *.log
37
+ *.tmp
38
+ .idea
39
+ CMakeUserPresets.json
40
+
41
+ #virtual environments:
42
+ .venv/
43
+ venv/
@@ -0,0 +1,33 @@
1
+ cmake_minimum_required(VERSION 3.21)
2
+ project(dynaplex LANGUAGES CXX)
3
+
4
+ if(NOT CMAKE_BUILD_TYPE)
5
+ set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
6
+ endif()
7
+
8
+ set(CMAKE_CXX_STANDARD 20)
9
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
10
+
11
+ find_package(pybind11 CONFIG REQUIRED)
12
+
13
+ # Create the Python extension module named exactly "_core"
14
+ pybind11_add_module(_core
15
+ src/bindings.cpp
16
+ src/hello.cpp
17
+ )
18
+
19
+ target_include_directories(_core PRIVATE include)
20
+
21
+ # Put the compiled extension inside the Python package directory "dynaplex/"
22
+ install(TARGETS _core
23
+ LIBRARY DESTINATION dynaplex
24
+ RUNTIME DESTINATION dynaplex
25
+ ARCHIVE DESTINATION dynaplex
26
+ )
27
+
28
+ # Ship the pure-Python files as part of the package
29
+ install(FILES
30
+ python/dynaplex/__init__.py
31
+ python/dynaplex/ops.py
32
+ DESTINATION dynaplex
33
+ )
@@ -0,0 +1,14 @@
1
+ {
2
+ "version": 4,
3
+ "configurePresets": [
4
+ {
5
+ "name": "x64-release",
6
+ "displayName": "x64 release (MSVC)",
7
+ "generator": "Ninja",
8
+ "binaryDir": "${sourceDir}/out/${presetName}",
9
+ "cacheVariables": {
10
+ "CMAKE_BUILD_TYPE": "Release"
11
+ }
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,52 @@
1
+ Metadata-Version: 2.2
2
+ Name: dynaplex
3
+ Version: 0.2.0
4
+ Summary: DynaPlex toolbox
5
+ Author: Willem van Jaarsveld
6
+ Classifier: Programming Language :: Python
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: C++
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+
13
+ # DynaPlex
14
+
15
+
16
+ Minimal C++ extension (pybind11 + CMake) packaged as a Python wheel.
17
+
18
+
19
+ ## Build (local, tested on Windhoos)
20
+
21
+ Assumes a python installation (below assumes regular, not Conda python), and a c++ toolchain.
22
+
23
+ Create venv:
24
+ ```bash
25
+ python -m venv .venv
26
+ .\.venv\Scripts\activate.bat
27
+ python -m pip install --upgrade pip
28
+ python -m pip install build scikit-build-core pybind11 pytest
29
+ ```
30
+
31
+ Build wheels:
32
+
33
+ ```bash
34
+ python -m build # creates sdist and wheel in dist/ folder
35
+ ```
36
+
37
+ Install the wheel:
38
+
39
+ ```bash
40
+ python -m pip install dist/dynaplex-*.whl
41
+ ```
42
+
43
+ If the wheel cannot be found (Windows) use this command instead:
44
+ ```bash
45
+ for %f in (dist\dynaplex-*.whl) do python -m pip install --force-reinstall "%f"
46
+ ```
47
+
48
+ Run tests:
49
+
50
+ ```bash
51
+ pytest -q
52
+ ```
@@ -0,0 +1,40 @@
1
+ # DynaPlex
2
+
3
+
4
+ Minimal C++ extension (pybind11 + CMake) packaged as a Python wheel.
5
+
6
+
7
+ ## Build (local, tested on Windhoos)
8
+
9
+ Assumes a python installation (below assumes regular, not Conda python), and a c++ toolchain.
10
+
11
+ Create venv:
12
+ ```bash
13
+ python -m venv .venv
14
+ .\.venv\Scripts\activate.bat
15
+ python -m pip install --upgrade pip
16
+ python -m pip install build scikit-build-core pybind11 pytest
17
+ ```
18
+
19
+ Build wheels:
20
+
21
+ ```bash
22
+ python -m build # creates sdist and wheel in dist/ folder
23
+ ```
24
+
25
+ Install the wheel:
26
+
27
+ ```bash
28
+ python -m pip install dist/dynaplex-*.whl
29
+ ```
30
+
31
+ If the wheel cannot be found (Windows) use this command instead:
32
+ ```bash
33
+ for %f in (dist\dynaplex-*.whl) do python -m pip install --force-reinstall "%f"
34
+ ```
35
+
36
+ Run tests:
37
+
38
+ ```bash
39
+ pytest -q
40
+ ```
@@ -0,0 +1,14 @@
1
+ #pragma once
2
+ #include <string>
3
+
4
+
5
+ namespace dynaplex {
6
+
7
+
8
+ inline std::string hello() {
9
+ return "Hello from DynaPlex!";
10
+ }
11
+
12
+ std::string goodbye();
13
+
14
+ } // namespace dynaplex
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = [
3
+ "scikit-build-core>=0.10",
4
+ "pybind11>=2.11",
5
+ "setuptools_scm>=8",
6
+ ]
7
+ build-backend = "scikit_build_core.build"
8
+
9
+
10
+ [project]
11
+ name = "dynaplex"
12
+ version = "0.2.0"
13
+ description = "DynaPlex toolbox"
14
+ readme = "README.md"
15
+ authors = [{ name = "Willem van Jaarsveld" }]
16
+ requires-python = ">=3.10"
17
+ classifiers = [
18
+ "Programming Language :: Python",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: C++",
21
+ "Operating System :: OS Independent",
22
+ ]
23
+
24
+
25
+ [tool.setuptools_scm]
26
+ version_scheme = "no-guess-dev"
27
+ local_scheme = "no-local-version"
28
+
29
+ #note: .github/workflows/wheels.yaml drives the matrix, below is ignored when publishing:
30
+ [tool.cibuildwheel]
31
+ skip = "pp* cp37* cp38* cp39*"
32
+ build = "cp313-*"
33
+ test-command = "pytest -q {project}/tests"
@@ -0,0 +1,9 @@
1
+ from . import _core as _core
2
+ from .utils import greet
3
+ from .ops import add
4
+
5
+ # Re-export everything from the compiled extension
6
+ from ._core import *
7
+
8
+ # Public API
9
+ __all__ = list(globals().keys())
@@ -0,0 +1,2 @@
1
+ def add(a, b):
2
+ return a + b
@@ -0,0 +1,4 @@
1
+ from . import _core
2
+
3
+ def greet(name: str) -> str:
4
+ return f"{_core.hello()} {name}!"
@@ -0,0 +1,3 @@
1
+ import dynaplex as dp
2
+
3
+ print(dp.greet("World"))
@@ -0,0 +1,11 @@
1
+ #include <pybind11/pybind11.h>
2
+ #include "dynaplex/hello.h"
3
+
4
+ namespace py = pybind11;
5
+
6
+ PYBIND11_MODULE(_core, m) {
7
+ m.doc() = "dynaplex hybrid C++ core";
8
+ m.def("hello", []() { return dynaplex::hello(); }, "Return a friendly greeting");
9
+
10
+ m.def("goodbye", []() { return dynaplex::goodbye(); }, "Return a friendly farewell");
11
+ }
@@ -0,0 +1,7 @@
1
+ #include "dynaplex/hello.h"
2
+
3
+ namespace dynaplex {
4
+ std::string goodbye() {
5
+ return "Goodbye from DynaPlex!";
6
+ }
7
+ } // namespace dynaplex
@@ -0,0 +1,13 @@
1
+ import dynaplex as dp
2
+
3
+ def test_hello():
4
+ assert dp.hello() == "Hello from DynaPlex!"
5
+
6
+ def test_goodbye():
7
+ assert dp.goodbye() == "Goodbye from DynaPlex!"
8
+
9
+ def test_greet():
10
+ assert "Hello from DynaPlex!" in dp.greet("World")
11
+
12
+ def test_add():
13
+ assert dp.add(2, 3) == 5