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
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,24 @@ jobs:
pip install -r doc/requirements.txt
- name: Build docs with warnings as errors
run: sphinx-build -W --keep-going -b html doc doc/_build/html

package:
name: Package build
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Build sdist and wheel
run: |
python -m pip install build
python -m build
- name: Validate metadata and install the wheel
run: |
python -m pip install twine
twine check dist/*
python -m pip install dist/*.whl
python -c "import pystrix; print('installed', pystrix.VERSION)"
9 changes: 4 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ pystrix/
└── core.py ~45 Action classes (Answer, StreamFile, SayNumber, ...)
doc/ Sphinx/reStructuredText docs + runnable examples in doc/examples/
setup.py Packaging; reads README.md for long_description
build-release.py Release helper
pyproject.toml Packaging (PEP 621) and ruff config; version read from pystrix.VERSION
```

## Architecture notes
Expand Down Expand Up @@ -88,8 +87,8 @@ Two bytes/string details at the I/O boundary are not Python 2 baggage and must s

## Working in this repo

- There is no test suite and no linter config. Verify changes against the runnable examples in `doc/examples/` and, where possible, a live Asterisk server.
- `VERSION` in `pystrix/__init__.py` is the single source of truth. `setup.py` imports it. Bump it for releases.
- `setup.py` reads `README.md`. Keep that filename in sync if the README is ever renamed again.
- Run `pytest` for the unit suite, and `ruff check .` / `ruff format --check .` for lint and format. CI enforces all of them across Python 3.9 through 3.13. There is no live-Asterisk integration test, so socket-level changes are still worth checking against a real server.
- `VERSION` in `pystrix/__init__.py` is the single source of truth. `pyproject.toml` reads it dynamically through `[tool.setuptools.dynamic]`. Bump it for releases.
- Packaging is `pyproject.toml` (PEP 621, setuptools backend). Build with `python -m build`.
- Docs are Sphinx reStructuredText under `doc/`. Update the relevant `.rst` when adding public actions or events.
- Keep inline docstrings complete and in reStructuredText. The project relies on them for its documentation.
10 changes: 5 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,21 @@ to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- A Contributing section and AGI, FastAGI, and AMI quick-start examples in the README.
- `.readthedocs.yaml` and `doc/requirements.txt` for reproducible documentation builds.
- A GitHub Actions CI workflow that runs the test suite with coverage across Python 3.9 through 3.13, plus a documentation build check.
- A `pytest` unit-test suite covering AMI message parsing and request building, AGI response parsing, and action and helper formatting, with `pytest` and `pytest-cov` in a `test` extra in `setup.py` (`pip install -e '.[test]'`).
- A `pytest` unit-test suite covering AMI message parsing and request building, AGI response parsing, and action and helper formatting, with `pytest` and `pytest-cov` in a `test` extra (`pip install -e '.[test]'`).
- Coverage measurement through `pytest-cov`, reported in the CI logs. No coverage data leaves CI.
- A CI status badge in the README.
- A curated `ruff` lint configuration (`ruff.toml`), a `.pre-commit-config.yaml`, and a CI lint job.
- A curated `ruff` configuration, a `.pre-commit-config.yaml`, and a CI lint job.
- This changelog.

### Changed
- Converted `README.rst` to `README.md` and corrected the version and install URL.
- Stated the license as the GNU LGPLv3 or later across the README and `setup.py`. pystrix is not dual-licensed. Both `COPYING` and `COPYING.LESSER` ship because the LGPL extends the GPL.
- Declared Python 3.9+ in `setup.py` through `python_requires` and trove classifiers (3.9 through 3.13), and dropped Python 2 and the end-of-life 3.x entries.
- Stated the license as the GNU LGPLv3 or later across the README and packaging metadata. pystrix is not dual-licensed. Both `COPYING` and `COPYING.LESSER` ship because the LGPL extends the GPL.
- Declared Python 3.9+ through `python_requires` and trove classifiers (3.9 through 3.13), and dropped Python 2 and the end-of-life 3.x entries.
- Narrowed the "any platform" claim. The FastAGI server runs on Linux and macOS only, because it reads `SOMAXCONN` with `sysctl`.
- Removed the `AUTHORS` file. Provenance now lives in the README, and the contributor list comes from git history and the GitHub contributors page.
- Modernized `doc/conf.py` (`exclude_patterns`, Read the Docs theme with a fallback, raw-string regex).
- Formatted the whole codebase with `ruff format` (line length 88) and enabled import sorting (ruff's `I` rule). Both are now enforced in pre-commit and CI. A `.git-blame-ignore-revs` file lets `git blame` skip the reformat commit.
- Migrated packaging from `setup.py` to `pyproject.toml` (PEP 621) with a PEP 639 SPDX license expression (`LGPL-3.0-or-later`). Moved the ruff config into `[tool.ruff]`, and removed `setup.py`, `build-release.py`, and `ruff.toml`. Build with `python -m build`; the version is read dynamically from `pystrix.VERSION`.

### Removed
- The Python 2 compatibility shims: the `queue` and `socketserver` import fallbacks, the `basestring` branch in `generic_transforms`, and the explicit `(object)` base classes. The codebase is now Python 3 only.
Expand All @@ -35,7 +36,6 @@ to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- Applied safe lint fixes surfaced by ruff: `not x is`/`not x in` rewritten to `x is not`/`x not in`, removed unused imports, and turned two invalid escape sequences (`\d`, `\*`) into raw strings. Intentional re-exports are marked with targeted ignores.
- `_Request.build_request` now honors its documented ActionID precedence: an explicit argument wins, then a value already set on the request, then a generated one. Previously a pre-set ActionID was dropped when no argument was passed, and it overrode an explicit argument. The resolved ActionID is also coerced to a string so a pre-set non-string value matches Asterisk's responses (#43).
- Replaced the removed `cgi.urlparse.parse_qs` in `pystrix/agi/fastagi.py` with `urllib.parse.parse_qs`. This fixes FastAGI query-string parsing on all Python 3 and restores Python 3.13 support (#36).
- `build-release.py` no longer fails on the missing `pystrix.spec`. The RPM packaging path was removed, and the release tarball now ships `README.md` and `CHANGELOG.md` so a build from the sdist can read the long description.
- Corrected the `_Response.time` description in the AMI docs and fixed several typos.
- Stopped tracking `doc/_build/` output and macOS `._` metadata files, and fixed the `.gitignore` rule that let them in.

Expand Down
3 changes: 1 addition & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
include README.md
include COPYING
include CHANGELOG.md
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ A few things to know before you send a change:
- **Lint and format with ruff.** `ruff check .` and `ruff format --check .` must pass, and CI enforces both. Install the hooks to run them on each commit: `pip install pre-commit && pre-commit install`.
- **Target Python 3.9+.** The codebase is Python 3 only; the old Python 2 compatibility shims have been removed, so don't reintroduce them.
- **Build the docs** when you touch them: `pip install -r doc/requirements.txt`, then `cd doc && make html`.
- **Version bumps** go in `pystrix/__init__.py`. `setup.py` reads `VERSION` from there.
- **Version bumps** go in `pystrix/__init__.py`. `pyproject.toml` reads `VERSION` from there dynamically.
- **Keep docstrings complete** and written in reStructuredText. The reference docs are generated from them.

## License
Expand Down
52 changes: 0 additions & 52 deletions build-release.py

This file was deleted.

62 changes: 62 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
[build-system]
# setuptools >= 77 is required for the PEP 639 SPDX license expression below.
# Build isolation supplies it regardless of the locally installed version.
requires = ["setuptools>=77"]
build-backend = "setuptools.build_meta"

[project]
name = "pystrix"
description = "Python bindings for Asterisk Manager Interface and Asterisk Gateway Interface"
readme = "README.md"
requires-python = ">=3.9"
license = "LGPL-3.0-or-later"
license-files = ["COPYING", "COPYING.LESSER"]
authors = [{ name = "Neil Tallim" }]
maintainers = [{ name = "IVR Technology Group" }]
keywords = ["asterisk", "ami", "agi", "fastagi", "telephony"]
classifiers = [
"Intended Audience :: Developers",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Communications :: Telephony",
]
dynamic = ["version"]

[project.optional-dependencies]
test = ["pytest", "pytest-cov"]

[project.urls]
Homepage = "https://github.com/IVRTech/pystrix"
Documentation = "https://pystrix.readthedocs.io/"
Repository = "https://github.com/IVRTech/pystrix"
Changelog = "https://github.com/IVRTech/pystrix/blob/master/CHANGELOG.md"

[tool.setuptools]
packages = ["pystrix", "pystrix.agi", "pystrix.ami"]

[tool.setuptools.dynamic]
version = { attr = "pystrix.VERSION" }

# Lint and format configuration (moved from ruff.toml).
[tool.ruff]
target-version = "py39"

[tool.ruff.lint]
# pycodestyle errors, pyflakes, import sorting (isort), and invalid escape
# sequences. Whitespace, indentation, and line length are owned by ruff format.
select = ["E4", "E7", "E9", "F", "I", "W605"]

[tool.ruff.lint.per-file-ignores]
# The __init__ modules deliberately re-export their public API.
"pystrix/__init__.py" = ["F401"]
"pystrix/agi/__init__.py" = ["F401"]
"pystrix/ami/__init__.py" = ["F401"]
# The AGI wrapper modules intentionally star-import the shared core.
"pystrix/agi/agi.py" = ["F403", "F405"]
"pystrix/agi/fastagi.py" = ["F403", "F405"]
20 changes: 0 additions & 20 deletions ruff.toml

This file was deleted.

52 changes: 0 additions & 52 deletions setup.py

This file was deleted.

Loading