Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion .github/renovate.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["github>WeblateOrg/meta:renovate"]
"extends": ["github>WeblateOrg/meta:renovate"],
"customManagers": [
{
"customType": "regex",
"managerFilePatterns": [
"/^\\.github/scripts/build-gammu-wheel\\.sh$/"
],
Comment thread
nijel marked this conversation as resolved.
"matchStrings": [
"# renovate: datasource=github-release-attachments depName=gammu/gammu versioning=loose\\nreadonly GAMMU_VERSION=\"(?<currentValue>[^\"]+)\"\\nreadonly GAMMU_SHA256=\"(?<currentDigest>[a-f0-9]{64})\""
],
"datasourceTemplate": "github-release-attachments",
"depNameTemplate": "gammu/gammu",
"versioningTemplate": "loose",
"autoReplaceStringTemplate": "# renovate: datasource=github-release-attachments depName=gammu/gammu versioning=loose\nreadonly GAMMU_VERSION=\"{{{newValue}}}\"\nreadonly GAMMU_SHA256=\"{{{newDigest}}}\""
},
{
"customType": "regex",
"managerFilePatterns": ["/^README\\.rst$/"],
"matchStrings": [
"\\.\\. renovate: datasource=github-release-attachments depName=gammu/gammu versioning=loose\\n\\nThe bundled Gammu (?<currentValue>[^\\s]+) library is licensed under GPL-2\\.0-or-later\\. The\\ncorresponding source archive is available from:\\n\\nhttps://github\\.com/gammu/gammu/releases/download/[^/\\s]+/Gammu-[^/\\s]+\\.tar\\.gz"
],
"datasourceTemplate": "github-release-attachments",
"depNameTemplate": "gammu/gammu",
"versioningTemplate": "loose",
"autoReplaceStringTemplate": ".. renovate: datasource=github-release-attachments depName=gammu/gammu versioning=loose\n\nThe bundled Gammu {{{newValue}}} library is licensed under GPL-2.0-or-later. The\ncorresponding source archive is available from:\n\nhttps://github.com/gammu/gammu/releases/download/{{{newValue}}}/Gammu-{{{newValue}}}.tar.gz"
}
]
}
59 changes: 59 additions & 0 deletions .github/scripts/build-gammu-wheel.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env bash
#
# Build the deliberately minimal Gammu libraries used by Linux wheels.

set -euo pipefail

# renovate: datasource=github-release-attachments depName=gammu/gammu versioning=loose
readonly GAMMU_VERSION="1.43.3"
readonly GAMMU_SHA256="a340b8347f5b30c84aa2a48fc497560fdc0d613618baa14b1bad94b3f316c7ff"
readonly GAMMU_PREFIX="${GAMMU_WHEEL_PREFIX:-/opt/python-gammu-gammu}"
readonly GAMMU_ARCHIVE="Gammu-${GAMMU_VERSION}.tar.gz"
readonly GAMMU_URL="https://github.com/gammu/gammu/releases/download/${GAMMU_VERSION}/${GAMMU_ARCHIVE}"

if ! command -v cmake >/dev/null 2>&1; then
dnf install -y cmake
fi

build_root="$(mktemp -d /tmp/python-gammu-wheel.XXXXXX)"
trap 'rm -rf "$build_root"' EXIT

curl --fail --location --silent --show-error \
--output "${build_root}/${GAMMU_ARCHIVE}" \
"$GAMMU_URL"
printf "%s %s\n" "$GAMMU_SHA256" "${build_root}/${GAMMU_ARCHIVE}" \
| sha256sum --check -
tar --extract --file "${build_root}/${GAMMU_ARCHIVE}" --directory "$build_root"

cmake \
-S "${build_root}/Gammu-${GAMMU_VERSION}" \
-B "${build_root}/build" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DBUILD_SHARED_LIBS=OFF \
-DWITH_BLUETOOTH=OFF \
-DWITH_USB=OFF \
-DWITH_IRDA=OFF \
-DWITH_MySQL=OFF \
-DWITH_ODBC=OFF \
-DWITH_Postgres=OFF \
-DWITH_LibDBI=OFF \
-DWITH_CURL=OFF \
-DWITH_Glib=OFF \
-DWITH_GObject=OFF \
-DWITH_SystemD=OFF \
-DWITH_Libintl=OFF \
-DWITH_Iconv=OFF \
-DWITH_Gettext=OFF \
-DWITH_Doxygen=OFF \
-DWITH_BashCompletion=OFF
cmake --build "${build_root}/build" \
--parallel \
--target libGammu gsmsd

install -d "${GAMMU_PREFIX}/include/gammu" "${GAMMU_PREFIX}/lib"
install -m 0644 "${build_root}/build/include/"*.h \
"${GAMMU_PREFIX}/include/gammu/"
Comment on lines +55 to +56

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Install the source-tree public headers

During every cibuildwheel build, this copies only CMake's binary-tree generated headers, while Gammu's public headers such as gammu.h and gammu-smsd.h remain in the extracted source tree. Because setup.py points the compiler at ${GAMMU_PREFIX}/include/gammu, compiling gammu/src/gammu.c will fail with a missing-header error. Copy the source-tree headers as well, or use Gammu's install target to populate the prefix.

Useful? React with 👍 / 👎.

install -m 0644 "${build_root}/build/libgammu/libGammu.a" \
"${build_root}/build/smsd/libgsmsd.a" \
"${GAMMU_PREFIX}/lib/"
42 changes: 39 additions & 3 deletions .github/workflows/setup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ permissions:
contents: read

jobs:
linux:
sdist:
runs-on: ubuntu-24.04

steps:
Expand All @@ -19,12 +19,34 @@ jobs:
- uses: ./.github/actions/install-gammu
- name: build
run: uv build --sdist
- name: Store the binary wheel
- name: Store the source distribution
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: dist-linux
name: dist-sdist
path: dist

linux:
strategy:
matrix:
include:
- architecture: x86_64
runner: ubuntu-24.04
- architecture: aarch64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}

steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Build wheels
uses: pypa/cibuildwheel@8d2b08b68458a16aeb24b64e68a09ab1c8e82084 # v3.4.1
env:
CIBW_ARCHS_LINUX: ${{ matrix.architecture }}
- name: Store the Linux wheels
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: dist-linux-${{ matrix.architecture }}
path: wheelhouse

windows:
runs-on: windows-latest
strategy:
Expand Down Expand Up @@ -55,6 +77,7 @@ jobs:
check:
needs:
- linux
- sdist
- windows
runs-on: ubuntu-24.04
steps:
Expand All @@ -75,6 +98,17 @@ jobs:
merge-multiple: true
- run: uvx twine check --strict dist/*
- run: uvx abi3audit dist/*abi3*.whl
- name: Check Linux wheel contents
shell: bash
run: |
test "$(find dist -maxdepth 1 -name '*manylinux*.whl' | wc -l)" -eq 10
for wheel in dist/*manylinux*.whl; do
uvx auditwheel show "$wheel"
if unzip -Z1 "$wheel" | grep -E '(^|/)[^/]+[.]libs/'; then
echo "Unexpected bundled shared libraries in $wheel"
exit 1
fi
done
- run: uvx pydistcheck --inspect dist/*
- run: uvx check-wheel-contents dist/*.whl
- run: uvx check-manifest -v
Expand All @@ -87,6 +121,7 @@ jobs:
needs:
- check
- linux
- sdist
- windows
if: startsWith(github.ref, 'refs/tags/') && github.repository == 'gammu/python-gammu'

Expand All @@ -107,6 +142,7 @@ jobs:
needs:
- check
- linux
- sdist
- windows
permissions:
contents: write
Expand Down
28 changes: 26 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,35 @@ Install it using pip installer::

pip install python-gammu

Linux wheels
============

Binary wheels are available for CPython 3.10 and newer on 64-bit x86 and ARM
Linux systems using glibc 2.28 or newer. They include a minimal, statically
linked Gammu library, so installing Gammu separately is not necessary.

The wheels support core phone protocols, serial connections, converters,
backups, and the SMSD file and null services. Bluetooth, native USB, IrDA,
database-backed SMSD services, CURL, GLib/GObject, systemd, gettext, and iconv
integration are not included.

.. renovate: datasource=github-release-attachments depName=gammu/gammu versioning=loose

The bundled Gammu 1.43.3 library is licensed under GPL-2.0-or-later. The
corresponding source archive is available from:

https://github.com/gammu/gammu/releases/download/1.43.3/Gammu-1.43.3.tar.gz

To use those optional features, install a fully featured Gammu development
package and force a source build::

pip install --no-binary python-gammu python-gammu

Requirements
============

To compile python-gammu, you need Gammu development files (usually shipped as
``libgammu-dev`` or ``gammu-devel`` in Linux distributions).
To compile python-gammu from source, you need Gammu development files (usually
shipped as ``libgammu-dev`` or ``gammu-devel`` in Linux distributions).

The location of the libraries is discovered using ``pkg-config``,
``GAMMU_PATH`` environment variable and falls back to generic locations. In
Expand Down
18 changes: 17 additions & 1 deletion gammu/src/gammu.c
Original file line number Diff line number Diff line change
Expand Up @@ -5455,7 +5455,23 @@ StateMachine_str(StateMachineObject *self)
static void
StateMachine_dealloc(StateMachineObject *self)
{
BEGIN_PHONE_COMM
if (self->in_callback) {
PyObject *error_type = NULL;
PyObject *error_value = NULL;
PyObject *error_traceback = NULL;

PyErr_Fetch(&error_type, &error_value, &error_traceback);
PyErr_SetString(PyExc_RuntimeError, "Can not call Gammu functions from within callback");
PyErr_WriteUnraisable((PyObject *)self);
PyErr_Clear();
PyErr_Restore(error_type, error_value, error_traceback);
return;
}
Comment on lines +5458 to +5469

#ifdef WITH_THREAD
Py_BEGIN_ALLOW_THREADS
PyThread_acquire_lock(self->mutex, 1);
#endif
if (GSM_IsConnected(self->s)) {
/* Disable any possible incoming notifications */
GSM_SetIncomingSMS(self->s, FALSE);
Expand Down
13 changes: 13 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,19 @@ ignore = [
"admin/*"
]

[tool.cibuildwheel]
build = "cp3{10,11,12,13,14}-manylinux*"
test-command = "pytest test"
test-requires = ["pytest==9.1.1"]
test-sources = ["test"]

[tool.cibuildwheel.linux]
before-all = "bash {package}/.github/scripts/build-gammu-wheel.sh"
environment = {GAMMU_PATH = "/opt/python-gammu-gammu"}
manylinux-aarch64-image = "manylinux_2_28"
manylinux-x86_64-image = "manylinux_2_28"
repair-wheel-command = "auditwheel repair --strip -w {dest_dir} {wheel}"

[tool.coverage.paths]
source = [
"."
Expand Down
18 changes: 11 additions & 7 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def get_libs(self) -> list[str]:
["pkg-config", "--libs-only-l", "gammu", "gammu-smsd"]
).decode("utf-8")
return output.replace("-l", "").strip().split()
libs = ["Gammu", "gsmsd"]
libs = ["gsmsd", "Gammu"]
if self.on_windows:
libs.extend(("Advapi32", "shfolder", "shell32"))
else:
Expand Down Expand Up @@ -186,12 +186,16 @@ def get_module():
"gammu/src/smsd.c",
],
)
flags = config.get_cflags()
if flags:
module.extra_compile_args.append(flags)
flags = config.get_ldflags()
if flags:
module.extra_link_args.append(flags)
if config.use_pkgconfig:
flags = config.get_cflags()
if flags:
module.extra_compile_args.append(flags)
flags = config.get_ldflags()
if flags:
module.extra_link_args.append(flags)
else:
module.include_dirs.append((config.path / "include" / "gammu").as_posix())
module.library_dirs.append((config.path / "lib").as_posix())
return module


Expand Down
33 changes: 33 additions & 0 deletions test/test_smsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,39 @@
MAX_STATUS_RETRIES = 2


@pytest.mark.parametrize("service", ["files", "null"])
def test_builtin_service(tmp_path: Path, service: str) -> None:
"""Verify SMSD services included in the minimal Linux wheels."""
Comment on lines +48 to +50
paths = {}
for name in ("inbox", "outbox", "sent", "error"):
path = tmp_path / name
path.mkdir()
paths[name] = f"{path.as_posix()}/"

config = tmp_path / "smsdrc"
dummy_path = (Path(__file__).parent / "data" / "gammu-dummy").as_posix()
config.write_text(
f"""
[gammu]
model = dummy
connection = none
port = {dummy_path}
gammuloc = /dev/null

[smsd]
service = {service}
inboxpath = {paths["inbox"]}
outboxpath = {paths["outbox"]}
sentsmspath = {paths["sent"]}
errorsmspath = {paths["error"]}
""",
encoding="utf-8",
)

smsd = gammu.smsd.SMSD(config.as_posix())
del smsd


def get_script() -> Path:
"""
Returns SQL script to create database.
Expand Down