development environment improvements

pull/1385/head
Chris Caron 2025-08-04 16:27:01 -04:00
parent 808497b58a
commit 160420793c
11 changed files with 199 additions and 53 deletions

View File

@ -39,7 +39,7 @@ jobs:
with: with:
name: built-rpms name: built-rpms
path: | path: |
dist/**/*.rpm dist/rpm/*/*.rpm
if-no-files-found: error if-no-files-found: error
retention-days: 5 retention-days: 5

1
.gitignore vendored
View File

@ -17,6 +17,7 @@ __pycache__/
env/ env/
.venv* .venv*
build/ build/
BUILD/
BUILDROOT/ BUILDROOT/
SOURCES/ SOURCES/
SRPMS/ SRPMS/

22
.vscode/settings.json vendored
View File

@ -1,9 +1,17 @@
{ {
"python.testing.pytestArgs": [], "python.testing.pytestArgs": [
"python.testing.cwd": "${workspaceFolder}", "tests"
"python.testing.unittestEnabled": false, ],
"python.testing.pytestEnabled": true, "python.linting.enabled": true,
"terminal.integrated.env.linux": { "python.linting.ruffEnabled": true,
"PYTHONPATH": "${workspaceFolder}" "python.linting.ruffPath": "ruff",
} "python.formatting.provider": "none",
"editor.formatOnSave": true,
"python.testing.cwd": "${workspaceFolder}",
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"python.envFile": "${workspaceFolder}/.env",
"terminal.integrated.env.linux": {
"PYTHONPATH": "${workspaceFolder}"
}
} }

View File

@ -20,19 +20,87 @@ merge your contributions smoothly.
tox -e qa tox -e qa
``` ```
- ✔️ All tests pass locally.
- ✔️ Your code is clean and consistently formatted: - ✔️ Your code is clean and consistently formatted:
```bash ```bash
tox -e format tox -e format
``` ```
- ✔️ You followed the plugin template (if adding a new plugin). - ✔️ You followed the plugin template (if adding a new plugin).
- ✔️ You included inline docstrings and respected the BSD 2-Clause license. - ✔️ You included inline docstrings and respected the BSD 2-Clause license.
- ✔️ Your commit message is descriptive. - ✔️ Your commit message is descriptive.
--- ---
## 📦 Local Development Setup
To get started with development:
### 🧰 System Requirements
- Python >= 3.9
- `pip`
- `git`
- Optional: `VS Code` with the Python extension
### 🚀 One-Time Setup
```bash
git clone https://github.com/caronc/apprise.git
cd apprise
# Install all runtime + dev dependencies
pip install .[dev]
```
(Optional, but recommended if actively developing):
```bash
pip install -e .[dev]
```
---
## 🧪 Running Tests
```bash
pytest # Run all tests
pytest tests/foo.py # Run a specific test file
```
Run with coverage:
```bash
pytest --cov=apprise --cov-report=term
```
---
## 🧹 Linting & Formatting with ruff
```bash
ruff check apprise tests # Check linting
ruff check apprise tests --fix # Auto-fix
ruff format apprise tests # Format files
```
---
## 🧰 Optional: Using VS Code
1. Open the repo: `code .`
2. Press `Ctrl+Shift+P → Python: Select Interpreter`
3. Choose the same interpreter you used for `pip install .[dev]`
4. Press `Ctrl+Shift+P → Python: Discover Tests`
`.vscode/settings.json` is pre-configured with:
- pytest as the test runner
- ruff for linting
- PYTHONPATH set to project root
No `.venv` is required unless you choose to use one.
---
## 📌 How to Contribute ## 📌 How to Contribute
1. **Fork the repository** and create a new branch. 1. **Fork the repository** and create a new branch.

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: apprise 1.4.5\n" "Project-Id-Version: apprise 1.4.5\n"
"Report-Msgid-Bugs-To: lead2gold@gmail.com\n" "Report-Msgid-Bugs-To: lead2gold@gmail.com\n"
"POT-Creation-Date: 2025-08-02 17:51+0000\n" "POT-Creation-Date: 2025-08-03 13:22+0000\n"
"PO-Revision-Date: 2019-05-24 20:00-0400\n" "PO-Revision-Date: 2019-05-24 20:00-0400\n"
"Last-Translator: Chris Caron <lead2gold@gmail.com>\n" "Last-Translator: Chris Caron <lead2gold@gmail.com>\n"
"Language: en\n" "Language: en\n"

View File

View File

@ -27,56 +27,60 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE. # POSSIBILITY OF SUCH DAMAGE.
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -euo pipefail
# Set Apprise root directory # Set Apprise root directory
APPRISE_DIR="${APPRISE_DIR:-/apprise}" APPRISE_DIR="${APPRISE_DIR:-/apprise}"
DIST_DIR="${DIST_DIR:-$PWD/dist/rpm}"
SOURCES_DIR="$APPRISE_DIR/SOURCES"
SRPM_DIR="$DIST_DIR/"
PYTHON=python3 PYTHON=python3
TOX="tox -c $APPRISE_DIR/tox.ini" TOX="tox -c $APPRISE_DIR/tox.ini"
DIST_DIR="${DIST_DIR:-$PWD/dist}"
mkdir -p "$DIST_DIR"
echo "==> Cleaning previous builds" if [ ! -d "$DIST_DIR" ]; then
$TOX -e clean --notest echo "==> Cleaning previous builds"
$TOX -e clean --notest
echo "==> Linting RPM spec" echo "==> Linting RPM spec"
rpmlint "$APPRISE_DIR/packaging/redhat/python-apprise.spec" rpmlint "$APPRISE_DIR/packaging/redhat/python-apprise.spec"
echo "==> Running tests" echo "==> Generating man pages"
$TOX -e py312 ronn --roff --organization="Chris Caron <lead2gold@gmail.com>" \
"$APPRISE_DIR/packaging/man/apprise.md"
echo "==> Generating man pages" echo "==> Extracting translations"
ronn --roff --organization="Chris Caron <lead2gold@gmail.com>" \ $TOX -e i18n
"$APPRISE_DIR/packaging/man/apprise.md"
echo "==> Extracting translations" echo "==> Compiling translations"
$TOX -e i18n || { echo "Translation extraction failed!" ; exit 1; } $TOX -e compile
echo "==> Compiling translations" echo "==> Building source distribution"
$TOX -e compile || { echo "Translation compilation failed!" ; exit 1; } $TOX -e build-sdist
fi
echo "==> Building source distribution"
$TOX -e build-sdist || { echo "sdist build failed!" ; exit 1; }
VERSION=$(rpmspec -q --qf "%{version}\n" "$APPRISE_DIR/packaging/redhat/python-apprise.spec" | head -n1) VERSION=$(rpmspec -q --qf "%{version}\n" "$APPRISE_DIR/packaging/redhat/python-apprise.spec" | head -n1)
TARBALL="$APPRISE_DIR/dist/apprise-${VERSION}.tar.gz" TARBALL="$APPRISE_DIR/dist/apprise-${VERSION}.tar.gz"
if [[ ! -f "$TARBALL" ]]; then if [[ ! -f "$TARBALL" ]]; then
echo "Tarball not found: $TARBALL" echo "Tarball not found: $TARBALL"
exit 1 exit 1
fi fi
echo "==> Copying tarball to SOURCES directory" echo "==> Preparing SOURCES directory"
mkdir -p "$APPRISE_DIR/SOURCES" mkdir -p "$SOURCES_DIR"
cp "$TARBALL" "$APPRISE_DIR/SOURCES/" cp "$TARBALL" "$SOURCES_DIR/"
find $APPRISE_DIR/packaging/redhat/ -iname '*.patch' -exec cp {} "$SOURCES_DIR" \;
echo "==> Building RPM" echo "==> Building RPM (source and binary)"
mkdir -p "$DIST_DIR"
rpmbuild --define "_topdir $APPRISE_DIR" \ rpmbuild --define "_topdir $APPRISE_DIR" \
--define "_sourcedir $APPRISE_DIR/SOURCES" \ --define "_sourcedir $SOURCES_DIR" \
--define "_specdir $APPRISE_DIR/packaging/redhat" \ --define "_specdir $APPRISE_DIR/packaging/redhat" \
--define "_srcrpmdir $APPRISE_DIR/SRPMS" \ --define "_srcrpmdir $DIST_DIR" \
--define "_rpmdir $DIST_DIR" \ --define "_rpmdir $DIST_DIR" \
-ba "$APPRISE_DIR/packaging/redhat/python-apprise.spec" -ba "$APPRISE_DIR/packaging/redhat/python-apprise.spec"
echo "✅ RPM build completed successfully" echo "✅ RPM build completed successfully"
echo "📦 Artifacts:"
find "$DIST_DIR" -type f -name "*.rpm"

View File

@ -5,6 +5,8 @@ services:
dockerfile: tests/docker/Dockerfile.py39 dockerfile: tests/docker/Dockerfile.py39
volumes: volumes:
- ./:/apprise - ./:/apprise
working_dir: /apprise
user: "1000:1000"
test.py310: test.py310:
build: build:
@ -12,6 +14,8 @@ services:
dockerfile: tests/docker/Dockerfile.py310 dockerfile: tests/docker/Dockerfile.py310
volumes: volumes:
- ./:/apprise - ./:/apprise
working_dir: /apprise
user: "1000:1000"
test.py311: test.py311:
build: build:
@ -19,6 +23,8 @@ services:
dockerfile: tests/docker/Dockerfile.py311 dockerfile: tests/docker/Dockerfile.py311
volumes: volumes:
- ./:/apprise - ./:/apprise
working_dir: /apprise
user: "1000:1000"
test.py312: test.py312:
build: build:
@ -26,6 +32,8 @@ services:
dockerfile: tests/docker/Dockerfile.py312 dockerfile: tests/docker/Dockerfile.py312
volumes: volumes:
- ./:/apprise - ./:/apprise
working_dir: /apprise
user: "1000:1000"
rpmbuild.el9: rpmbuild.el9:
build: build:
@ -33,6 +41,8 @@ services:
dockerfile: tests/docker/Dockerfile.el9 dockerfile: tests/docker/Dockerfile.el9
volumes: volumes:
- ./:/apprise - ./:/apprise
working_dir: /apprise
user: "1000:1000"
rpmbuild.f42: rpmbuild.f42:
build: build:
@ -40,6 +50,8 @@ services:
dockerfile: tests/docker/Dockerfile.f42 dockerfile: tests/docker/Dockerfile.f42
volumes: volumes:
- ./:/apprise - ./:/apprise
working_dir: /apprise
user: "1000:1000"
rpmbuild.rawhide: rpmbuild.rawhide:
build: build:
@ -47,6 +59,8 @@ services:
dockerfile: tests/docker/Dockerfile.rawhide dockerfile: tests/docker/Dockerfile.rawhide
volumes: volumes:
- ./:/apprise - ./:/apprise
working_dir: /apprise
user: "1000:1000"
# #
# Every Day testing # Every Day testing

View File

@ -1,6 +1,8 @@
## Packaging ## Packaging
This directory contains any supporting files to grant usage of Apprise in various distributions. This directory contains any supporting files to grant usage of Apprise in various distributions.
Let me know if you'd like to help me host on more platforms or can offer to do it yourself!
### RPM Based Packages ### RPM Based Packages
* [EPEL](https://fedoraproject.org/wiki/EPEL) based distributions are only supported if they are of v9 or higher. This includes: * [EPEL](https://fedoraproject.org/wiki/EPEL) based distributions are only supported if they are of v9 or higher. This includes:
* Red Hat 9.x (or higher) * Red Hat 9.x (or higher)
@ -17,7 +19,17 @@ Provided you are connected to the [EPEL repositories](https://fedoraproject.org/
dnf install python3-apprise apprise dnf install python3-apprise apprise
``` ```
Let me know if you'd like to help me host on more platforms or can offer to do it yourself! You can build your own rpm packges with the following:
```bash
# EPEL9 (CentOS/Rocky/RedHat/Oracle Linux)
tox -e build-el9-rpm
# Fedora 42
tox -e build-f42-rpm
# Fedora Rawhide
tox -e build-rawhide-rpm
```
## Man Pages Information ## Man Pages Information
The man page were generated using [Ronn](http://github.com/rtomayko/ronn/tree/0.7.3). The man page were generated using [Ronn](http://github.com/rtomayko/ronn/tree/0.7.3).

View File

@ -205,7 +205,7 @@ LANG=C.UTF-8 PYTHONPATH=%{buildroot}%{python3_sitelib}:%{_builddir}/%{name}-%{ve
%endif %endif
# Localised Files # Localised Files
%lang(en) %{python3_sitelib}/%{pypi_name}/i18n/en/LC_MESSAGES/messages.mo %lang(en) %{python3_sitelib}/%{pypi_name}/i18n/en/LC_MESSAGES/apprise.mo
%files -n %{pypi_name} %files -n %{pypi_name}
%{_bindir}/%{pypi_name} %{_bindir}/%{pypi_name}

65
tox.ini
View File

@ -7,13 +7,12 @@ use_discover = False
[tox] [tox]
envlist = envlist =
clean clean
validate
i18n i18n
compile compile
minimal minimal
build
release release
validate
twine-check
minversion = 4.0 minversion = 4.0
requires = virtualenv>=20.0.0 requires = virtualenv>=20.0.0
isolated_build = True isolated_build = True
@ -27,13 +26,54 @@ ensurepip = true
setenv = setenv =
COVERAGE_RCFILE = {toxinidir}/pyproject.toml COVERAGE_RCFILE = {toxinidir}/pyproject.toml
[testenv:build-rpm] [testenv:build-src-rpm]
description = Run RPM packaging via Docker description = Build source RPM and place .src.rpm in dist/
skip_install = true
allowlist_externals =
bash
cp
mkdir
find
rpmbuild
setenv =
HOME = {envtmpdir}
RPMTOP = {envtmpdir}/rpmbuild
commands_pre =
mkdir -p {envtmpdir}/rpmbuild/SOURCES
mkdir -p {envtmpdir}/rpmbuild/SPECS
mkdir -p dist/rpm
cp packaging/man/apprise.1 {envtmpdir}/rpmbuild/SOURCES/
cp packaging/redhat/python-apprise.spec {envtmpdir}/rpmbuild/SPECS/
find packaging/redhat/ -iname '*.patch' -exec cp {} {envtmpdir}/rpmbuild/SOURCES/ \;
bash -c 'cp dist/*.tar.gz {envtmpdir}/rpmbuild/SOURCES/'
bash -c 'echo "%_topdir {envtmpdir}/rpmbuild" > {envtmpdir}/.rpmmacros'
commands =
rpmbuild --nodeps -bs {envtmpdir}/rpmbuild/SPECS/python-apprise.spec
find {envtmpdir}/rpmbuild/SRPMS -name '*.src.rpm' -exec mv {} dist/rpm \;
[testenv:build-el9-rpm]
description = Run RPM packaging for EPEL9 via Docker
skip_install = true
allowlist_externals = allowlist_externals =
docker docker
bash
commands = commands =
docker compose run --user root --rm rpmbuild.el9 bash build-rpm.sh docker compose run --rm rpmbuild.el9 bash /usr/bin/build-rpm.sh
[testenv:build-f42-rpm]
description = Run RPM packaging for Fedora 42 via Docker
skip_install = true
allowlist_externals =
docker
commands =
docker compose run --rm rpmbuild.f42 bash /usr/bin/build-rpm.sh
[testenv:build-rawhide-rpm]
description = Run RPM packaging for Fedora Rawhide via Docker
skip_install = true
allowlist_externals =
docker
commands =
docker compose run --rm rpmbuild.rawhide bash /usr/bin/build-rpm.sh
[testenv:lint] [testenv:lint]
description = Run static analysis using Ruff description = Run static analysis using Ruff
@ -104,8 +144,10 @@ commands =
find . -type f -name "*.pyc" -delete find . -type f -name "*.pyc" -delete
find . -type f -name "*.pyo" -delete find . -type f -name "*.pyo" -delete
find . -type f -name "*.orig" -delete find . -type f -name "*.orig" -delete
find . -type f -name "*.orig" -delete
find ./apprise/i18n -type f -name "*.mo" -delete
rm -rf BUILD SOURCES SRPMS BUILDROOT .cache .ruff_cache .coverage-reports .coverage coverage.xml dist build apprise.egg-info .mypy_cache .pytest_cache "__pycache__"
find . -type d -name "__pycache__" -delete find . -type d -name "__pycache__" -delete
rm -rf BUILD SOURCES SRPMS BUILDROOT .cache .ruff_cache .coverage-reports .coverage coverage.xml dist build apprise.egg-info .mypy_cache .pytest_cache
[testenv:i18n] [testenv:i18n]
description = Extract and update .pot/.po files for translation description = Extract and update .pot/.po files for translation
@ -115,13 +157,13 @@ ensurepip = true
commands = commands =
mkdir -p apprise/i18n mkdir -p apprise/i18n
pybabel extract -F babel.cfg -o apprise/i18n/apprise.pot apprise pybabel extract -F babel.cfg -o apprise/i18n/apprise.pot apprise
pybabel update -i apprise/i18n/apprise.pot -d apprise/i18n pybabel update --domain=apprise -i apprise/i18n/apprise.pot -d apprise/i18n
[testenv:compile] [testenv:compile]
description = Compile .mo files description = Compile .mo files
deps = Babel deps = Babel
commands = commands =
pybabel compile -d apprise/i18n pybabel compile --domain=apprise -d apprise/i18n
[testenv:build] [testenv:build]
description = Build sdist and wheel (assumes translations compiled) description = Build sdist and wheel (assumes translations compiled)
@ -151,11 +193,8 @@ commands =
[testenv:twine-check] [testenv:twine-check]
description = Run twine check on dist artifacts description = Run twine check on dist artifacts
deps = deps =
build
twine twine
commands = commands =
rm -rf dist
python -m build
twine check dist/* twine check dist/*
[testenv:man] [testenv:man]