aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri@ouroboros.rocks>2026-03-07 22:46:56 +0100
committerDimitri Staessens <dimitri@ouroboros.rocks>2026-03-08 14:24:30 +0100
commit7d043001b956fb80116cf8eedcca1d5aaf2edbd4 (patch)
treed2f925b1f3085cabd0256949a454d15075a8dde8
parent7a4c37e8b673328dda59cec11ab9dce66c22a312 (diff)
downloadpyouroboros-7d043001b956fb80116cf8eedcca1d5aaf2edbd4.tar.gz
pyouroboros-7d043001b956fb80116cf8eedcca1d5aaf2edbd4.zip
build: Use git tags for versioningHEAD0.23.0master
Replace setup.py metadata with pyproject.toml and derive version from git tags with setuptools-scm. Adds git archive support for setuptools-scm version detection.
-rw-r--r--.git_archival.txt3
-rw-r--r--.gitattributes1
-rw-r--r--README.md11
-rw-r--r--ffi/pyouroboros_build_dev.py6
-rw-r--r--ffi/pyouroboros_build_irm.py6
-rw-r--r--ouroboros/__init__.py21
-rw-r--r--ouroboros/dev.py24
-rw-r--r--ouroboros/irm.py24
-rw-r--r--pyproject.toml23
-rwxr-xr-xsetup.py67
10 files changed, 164 insertions, 22 deletions
diff --git a/.git_archival.txt b/.git_archival.txt
new file mode 100644
index 0000000..3e26627
--- /dev/null
+++ b/.git_archival.txt
@@ -0,0 +1,3 @@
+node: $Format:%H$
+node-date: $Format:%cI$
+describe-name: $Format:%(describe:tags=true)$
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..00a7b00
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+.git_archival.txt export-subst
diff --git a/README.md b/README.md
index 96e6151..0d57a5e 100644
--- a/README.md
+++ b/README.md
@@ -388,5 +388,16 @@ unbind_process(pid, "my_name")
Some example code is in the examples folder.
+## Versioning
+
+pyOuroboros uses `setuptools_scm` to derive its version from git tags.
+
+**Compatibility contract across Ouroboros repositories:**
+
+| Scope | Rule |
+|---|---|
+| ouroboros (C) ↔ pyouroboros / rumba | Shared `major.minor` — pyouroboros requires at least the same ouroboros `major.minor` |
+| pyouroboros ↔ rumba ↔ ouroboros-integration | Strict lockstep `major.minor.patch` — always released together |
+
## License
pyOuroboros is LGPLv2.1. The examples are 3-clause BSD.
diff --git a/ffi/pyouroboros_build_dev.py b/ffi/pyouroboros_build_dev.py
index 751b492..778cc40 100644
--- a/ffi/pyouroboros_build_dev.py
+++ b/ffi/pyouroboros_build_dev.py
@@ -33,6 +33,11 @@ struct timespec {
...;
};
+/* OUROBOROS VERSION.H */
+#define OUROBOROS_VERSION_MAJOR ...
+#define OUROBOROS_VERSION_MINOR ...
+#define OUROBOROS_VERSION_PATCH ...
+
/* OUROBOROS QOS.H */
typedef struct qos_spec {
uint32_t delay;
@@ -139,6 +144,7 @@ ssize_t fevent(fset_t * set,
ffibuilder.set_source("_ouroboros_dev_cffi",
"""
+#include "ouroboros/version.h"
#include "ouroboros/qos.h"
#include "ouroboros/dev.h"
#include "fccntl_wrap.h"
diff --git a/ffi/pyouroboros_build_irm.py b/ffi/pyouroboros_build_irm.py
index e29287e..1fc515e 100644
--- a/ffi/pyouroboros_build_irm.py
+++ b/ffi/pyouroboros_build_irm.py
@@ -34,6 +34,11 @@ struct timespec {
...;
};
+/* OUROBOROS VERSION.H */
+#define OUROBOROS_VERSION_MAJOR ...
+#define OUROBOROS_VERSION_MINOR ...
+#define OUROBOROS_VERSION_PATCH ...
+
/* Network types */
struct in_addr { ...; };
struct in6_addr { ...; };
@@ -281,6 +286,7 @@ void free(void *ptr);
ffibuilder.set_source("_ouroboros_irm_cffi",
"""
+#include "ouroboros/version.h"
#include "ouroboros/qos.h"
#include "irm_wrap.h"
""",
diff --git a/ouroboros/__init__.py b/ouroboros/__init__.py
new file mode 100644
index 0000000..6034f7d
--- /dev/null
+++ b/ouroboros/__init__.py
@@ -0,0 +1,21 @@
+#
+# Ouroboros - Copyright (C) 2016 - 2026
+#
+# Python API for Ouroboros
+#
+# Dimitri Staessens <dimitri@ouroboros.rocks>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# version 2.1 as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., http://www.fsf.org/about/contact/.
+#
+
diff --git a/ouroboros/dev.py b/ouroboros/dev.py
index a2b58cf..d36a3ef 100644
--- a/ouroboros/dev.py
+++ b/ouroboros/dev.py
@@ -27,6 +27,30 @@ from typing import Optional
from _ouroboros_dev_cffi import ffi, lib
from ouroboros.qos import *
+
+def _check_ouroboros_version():
+ ouro_major = lib.OUROBOROS_VERSION_MAJOR
+ ouro_minor = lib.OUROBOROS_VERSION_MINOR
+ try:
+ from importlib.metadata import version, PackageNotFoundError
+ try:
+ pyouro_parts = version('PyOuroboros').split('.')
+ except PackageNotFoundError:
+ return # running from source, skip check
+ if ouro_major != int(pyouro_parts[0]) or \
+ ouro_minor != int(pyouro_parts[1]):
+ raise RuntimeError(
+ f"Ouroboros version mismatch: library is "
+ f"{ouro_major}.{ouro_minor}, "
+ f"pyouroboros is "
+ f"{pyouro_parts[0]}.{pyouro_parts[1]}"
+ )
+ except ImportError:
+ pass # Python < 3.8
+
+
+_check_ouroboros_version()
+
# Some constants
MILLION = 1000 * 1000
BILLION = 1000 * 1000 * 1000
diff --git a/ouroboros/irm.py b/ouroboros/irm.py
index 1e4fc2e..5c23aaa 100644
--- a/ouroboros/irm.py
+++ b/ouroboros/irm.py
@@ -26,6 +26,30 @@ from _ouroboros_irm_cffi import ffi, lib
from ouroboros.qos import QoSSpec
+def _check_ouroboros_version():
+ ouro_major = lib.OUROBOROS_VERSION_MAJOR
+ ouro_minor = lib.OUROBOROS_VERSION_MINOR
+ try:
+ from importlib.metadata import version, PackageNotFoundError
+ try:
+ pyouro_parts = version('PyOuroboros').split('.')
+ except PackageNotFoundError:
+ return # running from source, skip check
+ if ouro_major != int(pyouro_parts[0]) or \
+ ouro_minor != int(pyouro_parts[1]):
+ raise RuntimeError(
+ f"Ouroboros version mismatch: library is "
+ f"{ouro_major}.{ouro_minor}, "
+ f"pyouroboros is "
+ f"{pyouro_parts[0]}.{pyouro_parts[1]}"
+ )
+ except ImportError:
+ pass # Python < 3.8
+
+
+_check_ouroboros_version()
+
+
# Intentionally duplicated: irm uses a separate FFI (ouroboros-irm).
def _qos_to_qosspec(qos: QoSSpec):
if qos is None:
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..247142c
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,23 @@
+[build-system]
+requires = ["setuptools>=64", "setuptools-scm>=8", "cffi>=1.0.0"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "PyOuroboros"
+dynamic = ["version"]
+description = "Python API for Ouroboros"
+license = "LGPL-2.1-only"
+requires-python = ">=3.8"
+authors = [
+ { name = "Dimitri Staessens", email = "dimitri@ouroboros.rocks" }
+]
+keywords = ["ouroboros", "IPC"]
+dependencies = ["cffi>=1.0.0"]
+
+[project.urls]
+Homepage = "https://ouroboros.rocks"
+
+[tool.setuptools]
+packages = ["ouroboros"]
+
+[tool.setuptools_scm]
diff --git a/setup.py b/setup.py
index a22b7bd..cdf1f55 100755
--- a/setup.py
+++ b/setup.py
@@ -1,26 +1,49 @@
-#!/usr/bin/env python
-
-import setuptools
-
-setuptools.setup(
- name='PyOuroboros',
- version='0.23.0',
- url='https://ouroboros.rocks',
- keywords='ouroboros IPC subsystem',
- author='Dimitri Staessens',
- author_email='dimitri@ouroboros.rocks',
- license='LGPLv2.1',
- description='Python API for Ouroboros',
- packages=[
- 'ouroboros'
- ],
- setup_requires=[
- "cffi>=1.0.0"
- ],
+import subprocess
+import sys
+
+from setuptools import setup
+
+
+def _get_ouroboros_version():
+ try:
+ out = subprocess.check_output(
+ ['pkg-config', '--modversion', 'ouroboros-dev'],
+ stderr=subprocess.DEVNULL
+ )
+ return out.decode().strip()
+ except (subprocess.CalledProcessError, FileNotFoundError):
+ sys.exit("ERROR: ouroboros-dev not found via pkg-config. "
+ "Is Ouroboros installed?")
+
+
+def _check_build_version_compat():
+ try:
+ from setuptools_scm import get_version
+ pyouro_ver = get_version(root='.', relative_to=__file__)
+ except Exception:
+ return # no SCM info, skip check
+
+ ouro_ver = _get_ouroboros_version()
+
+ # setuptools_scm: '0.23.1.dev3+g<hash>' or '0.23.0'
+ # pkg-config: '0.23.0'
+ # Compare major.minor only.
+ ouro_parts = ouro_ver.split('.')
+ pyouro_parts = pyouro_ver.split('.')
+
+ if ouro_parts[0] != pyouro_parts[0] or ouro_parts[1] != pyouro_parts[1]:
+ sys.exit(
+ f"ERROR: Version mismatch: ouroboros {ouro_ver} "
+ f"vs pyouroboros {pyouro_ver} "
+ f"(major.minor must match)"
+ )
+
+
+_check_build_version_compat()
+
+setup(
cffi_modules=[
"ffi/pyouroboros_build_dev.py:ffibuilder",
"ffi/pyouroboros_build_irm.py:ffibuilder"
],
- install_requires=[
- "cffi>=1.0.0"
- ])
+)