From 160420793c4f8da35396a5d636dd75a7fc75fd08 Mon Sep 17 00:00:00 2001 From: Chris Caron Date: Mon, 4 Aug 2025 16:27:01 -0400 Subject: [PATCH] development environment improvements --- .github/workflows/pkgbuild.yml | 2 +- .gitignore | 1 + .vscode/settings.json | 22 ++++-- CONTRIBUTING.md | 72 ++++++++++++++++++- .../LC_MESSAGES/{messages.po => apprise.po} | 2 +- apprise/py.typed | 0 bin/build-rpm.sh | 58 ++++++++------- docker-compose.yml | 14 ++++ packaging/README.md | 14 +++- packaging/redhat/python-apprise.spec | 2 +- tox.ini | 65 +++++++++++++---- 11 files changed, 199 insertions(+), 53 deletions(-) rename apprise/i18n/en/LC_MESSAGES/{messages.po => apprise.po} (99%) delete mode 100644 apprise/py.typed diff --git a/.github/workflows/pkgbuild.yml b/.github/workflows/pkgbuild.yml index 006af1eb..0cd0dcf4 100644 --- a/.github/workflows/pkgbuild.yml +++ b/.github/workflows/pkgbuild.yml @@ -39,7 +39,7 @@ jobs: with: name: built-rpms path: | - dist/**/*.rpm + dist/rpm/*/*.rpm if-no-files-found: error retention-days: 5 diff --git a/.gitignore b/.gitignore index c79a0c07..4a054b79 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ __pycache__/ env/ .venv* build/ +BUILD/ BUILDROOT/ SOURCES/ SRPMS/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 718798e9..62c9399d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,17 @@ { - "python.testing.pytestArgs": [], - "python.testing.cwd": "${workspaceFolder}", - "python.testing.unittestEnabled": false, - "python.testing.pytestEnabled": true, - "terminal.integrated.env.linux": { - "PYTHONPATH": "${workspaceFolder}" - } + "python.testing.pytestArgs": [ + "tests" + ], + "python.linting.enabled": true, + "python.linting.ruffEnabled": true, + "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}" + } } \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c49560ec..9bbe6240 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,19 +20,87 @@ merge your contributions smoothly. tox -e qa ``` -- ✔️ All tests pass locally. - - ✔️ Your code is clean and consistently formatted: ```bash tox -e format ``` + - ✔️ You followed the plugin template (if adding a new plugin). - ✔️ You included inline docstrings and respected the BSD 2-Clause license. - ✔️ 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 1. **Fork the repository** and create a new branch. diff --git a/apprise/i18n/en/LC_MESSAGES/messages.po b/apprise/i18n/en/LC_MESSAGES/apprise.po similarity index 99% rename from apprise/i18n/en/LC_MESSAGES/messages.po rename to apprise/i18n/en/LC_MESSAGES/apprise.po index f14a27e4..e96b7634 100644 --- a/apprise/i18n/en/LC_MESSAGES/messages.po +++ b/apprise/i18n/en/LC_MESSAGES/apprise.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: apprise 1.4.5\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" "Last-Translator: Chris Caron \n" "Language: en\n" diff --git a/apprise/py.typed b/apprise/py.typed deleted file mode 100644 index e69de29b..00000000 diff --git a/bin/build-rpm.sh b/bin/build-rpm.sh index e27f0251..8ae69eeb 100755 --- a/bin/build-rpm.sh +++ b/bin/build-rpm.sh @@ -27,56 +27,60 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. #!/usr/bin/env bash -set -e +set -euo pipefail # Set Apprise root directory APPRISE_DIR="${APPRISE_DIR:-/apprise}" +DIST_DIR="${DIST_DIR:-$PWD/dist/rpm}" +SOURCES_DIR="$APPRISE_DIR/SOURCES" +SRPM_DIR="$DIST_DIR/" + PYTHON=python3 TOX="tox -c $APPRISE_DIR/tox.ini" -DIST_DIR="${DIST_DIR:-$PWD/dist}" -mkdir -p "$DIST_DIR" -echo "==> Cleaning previous builds" -$TOX -e clean --notest +if [ ! -d "$DIST_DIR" ]; then + echo "==> Cleaning previous builds" + $TOX -e clean --notest -echo "==> Linting RPM spec" -rpmlint "$APPRISE_DIR/packaging/redhat/python-apprise.spec" + echo "==> Linting RPM spec" + rpmlint "$APPRISE_DIR/packaging/redhat/python-apprise.spec" -echo "==> Running tests" -$TOX -e py312 + echo "==> Generating man pages" + ronn --roff --organization="Chris Caron " \ + "$APPRISE_DIR/packaging/man/apprise.md" -echo "==> Generating man pages" -ronn --roff --organization="Chris Caron " \ - "$APPRISE_DIR/packaging/man/apprise.md" + echo "==> Extracting translations" + $TOX -e i18n -echo "==> Extracting translations" -$TOX -e i18n || { echo "Translation extraction failed!" ; exit 1; } + echo "==> Compiling translations" + $TOX -e compile -echo "==> Compiling translations" -$TOX -e compile || { echo "Translation compilation failed!" ; exit 1; } - -echo "==> Building source distribution" -$TOX -e build-sdist || { echo "sdist build failed!" ; exit 1; } + echo "==> Building source distribution" + $TOX -e build-sdist +fi VERSION=$(rpmspec -q --qf "%{version}\n" "$APPRISE_DIR/packaging/redhat/python-apprise.spec" | head -n1) TARBALL="$APPRISE_DIR/dist/apprise-${VERSION}.tar.gz" if [[ ! -f "$TARBALL" ]]; then - echo "Tarball not found: $TARBALL" + echo "❌ Tarball not found: $TARBALL" exit 1 fi -echo "==> Copying tarball to SOURCES directory" -mkdir -p "$APPRISE_DIR/SOURCES" -cp "$TARBALL" "$APPRISE_DIR/SOURCES/" +echo "==> Preparing SOURCES directory" +mkdir -p "$SOURCES_DIR" +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" \ - --define "_sourcedir $APPRISE_DIR/SOURCES" \ + --define "_sourcedir $SOURCES_DIR" \ --define "_specdir $APPRISE_DIR/packaging/redhat" \ - --define "_srcrpmdir $APPRISE_DIR/SRPMS" \ + --define "_srcrpmdir $DIST_DIR" \ --define "_rpmdir $DIST_DIR" \ -ba "$APPRISE_DIR/packaging/redhat/python-apprise.spec" echo "✅ RPM build completed successfully" - +echo "📦 Artifacts:" +find "$DIST_DIR" -type f -name "*.rpm" diff --git a/docker-compose.yml b/docker-compose.yml index a710891d..6d1a8255 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,8 @@ services: dockerfile: tests/docker/Dockerfile.py39 volumes: - ./:/apprise + working_dir: /apprise + user: "1000:1000" test.py310: build: @@ -12,6 +14,8 @@ services: dockerfile: tests/docker/Dockerfile.py310 volumes: - ./:/apprise + working_dir: /apprise + user: "1000:1000" test.py311: build: @@ -19,6 +23,8 @@ services: dockerfile: tests/docker/Dockerfile.py311 volumes: - ./:/apprise + working_dir: /apprise + user: "1000:1000" test.py312: build: @@ -26,6 +32,8 @@ services: dockerfile: tests/docker/Dockerfile.py312 volumes: - ./:/apprise + working_dir: /apprise + user: "1000:1000" rpmbuild.el9: build: @@ -33,6 +41,8 @@ services: dockerfile: tests/docker/Dockerfile.el9 volumes: - ./:/apprise + working_dir: /apprise + user: "1000:1000" rpmbuild.f42: build: @@ -40,6 +50,8 @@ services: dockerfile: tests/docker/Dockerfile.f42 volumes: - ./:/apprise + working_dir: /apprise + user: "1000:1000" rpmbuild.rawhide: build: @@ -47,6 +59,8 @@ services: dockerfile: tests/docker/Dockerfile.rawhide volumes: - ./:/apprise + working_dir: /apprise + user: "1000:1000" # # Every Day testing diff --git a/packaging/README.md b/packaging/README.md index c7c5339e..c41e0bc2 100644 --- a/packaging/README.md +++ b/packaging/README.md @@ -1,6 +1,8 @@ ## Packaging 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 * [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) @@ -17,7 +19,17 @@ Provided you are connected to the [EPEL repositories](https://fedoraproject.org/ 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 The man page were generated using [Ronn](http://github.com/rtomayko/ronn/tree/0.7.3). diff --git a/packaging/redhat/python-apprise.spec b/packaging/redhat/python-apprise.spec index 3d7b9f57..453189df 100644 --- a/packaging/redhat/python-apprise.spec +++ b/packaging/redhat/python-apprise.spec @@ -205,7 +205,7 @@ LANG=C.UTF-8 PYTHONPATH=%{buildroot}%{python3_sitelib}:%{_builddir}/%{name}-%{ve %endif # 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} %{_bindir}/%{pypi_name} diff --git a/tox.ini b/tox.ini index 24ee94cc..72ddbb13 100644 --- a/tox.ini +++ b/tox.ini @@ -7,13 +7,12 @@ use_discover = False [tox] envlist = clean + validate i18n compile minimal - build release - validate - twine-check + minversion = 4.0 requires = virtualenv>=20.0.0 isolated_build = True @@ -27,13 +26,54 @@ ensurepip = true setenv = COVERAGE_RCFILE = {toxinidir}/pyproject.toml -[testenv:build-rpm] -description = Run RPM packaging via Docker +[testenv:build-src-rpm] +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 = docker - bash 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] description = Run static analysis using Ruff @@ -104,8 +144,10 @@ commands = find . -type f -name "*.pyc" -delete find . -type f -name "*.pyo" -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 - 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] description = Extract and update .pot/.po files for translation @@ -115,13 +157,13 @@ ensurepip = true commands = mkdir -p apprise/i18n 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] description = Compile .mo files deps = Babel commands = - pybabel compile -d apprise/i18n + pybabel compile --domain=apprise -d apprise/i18n [testenv:build] description = Build sdist and wheel (assumes translations compiled) @@ -151,11 +193,8 @@ commands = [testenv:twine-check] description = Run twine check on dist artifacts deps = - build twine commands = - rm -rf dist - python -m build twine check dist/* [testenv:man]