pyproject.toml and tox introduction (modernization)

pull/1368/head
Chris Caron 2025-07-09 20:15:39 -04:00
parent 91faed0c6d
commit cbc4ee8003
195 changed files with 2587 additions and 1820 deletions

View File

@ -1,17 +0,0 @@
[run]
data_file = .coverage-reports/.coverage
branch = True
parallel = True
source =
apprise
[paths]
source =
apprise
.tox/*/lib/python*/site-packages/apprise
.tox/pypy/site-packages/apprise
[report]
show_missing = True
skip_covered = True
skip_empty = True

View File

@ -1,12 +1,54 @@
## Description: ## Description:
**Related issue (if applicable):** #<!--apprise issue number goes here--> **Related issue (if applicable):** #<!--apprise issue number goes here-->
<!-- Have anything else to describe? Define it here --> <!-- Have anything else to describe? Define it here; this helps build the wiki item later
## *ServiceName* Notifications
* **Source**: https://official.website.example.ca
* **Icon Support**: No
* **Message Format**: Plain Text
* **Message Limit**: ~10,000 Characters
Describe your service here..
### 🛠️ Setup Instructions
1. Visit [service.site](https://example.ca/) and sign in using your account credentials.
2. Once logged in, generate and copy your **token** ...
---
### ✅ Apprise Support
### Syntax
Valid syntax is as follows:
- `service://{variable}`
---
### 🔐 Parameter Breakdown
| Variable | Required | Description |
|-----------|----------|----------------|
| variable1 | Yes | Your variable1 |
| variable2 | No | Your variable2 |
---
### 📦 Examples
Sends a simple example
```bash
apprise -vv -t "Title" -b "Message content" \
service://token
```
-->
## New Service Completion Status ## New Service Completion Status
<!-- This section is only applicable if you're adding a new service --> <!-- This section is only applicable if you're adding a new service -->
* [ ] apprise/plugins/<!--new plugin name -->.py * [ ] apprise/plugins/<!--new plugin name -->.py
* [ ] KEYWORDS * [ ] pypackage.toml update `keywords` section to identify our new service
- add new service into this file (alphabetically). - add new service into this file (alphabetically).
* [ ] README.md * [ ] README.md
- add entry for new service to table (as a quick reference) - add entry for new service to table (as a quick reference)
@ -17,8 +59,8 @@
<!-- The following must be completed or your PR can't be merged --> <!-- The following must be completed or your PR can't be merged -->
* [ ] The code change is tested and works locally. * [ ] The code change is tested and works locally.
* [ ] There is no commented out code in this PR. * [ ] There is no commented out code in this PR.
* [ ] No lint errors (use `flake8`) * [ ] No lint errors (use `tox -e lint`)
* [ ] 100% test coverage * [ ] 100% test coverage (use `tox -e minimal`)
## Testing ## Testing
<!-- If this your code is testable by other users of the program <!-- If this your code is testable by other users of the program

View File

@ -1,60 +1,79 @@
# #
# Verify on CI/GHA that package building works. # Verify on CI/GHA that package building works.
# #
# TODO: Currently, this supports RPM-based systems only. name: RPM Packaging
# By adjusting a few details, it can be made work
# for other distribution types as well.
#
name: Test packaging
on: on:
# On which repository actions to trigger the build.
push: push:
branches: [ master ] branches: [main, master, 'release/**']
pull_request: pull_request:
branches: [ master ] branches: [main, master]
# Allow job to be triggered manually.
workflow_dispatch: workflow_dispatch:
# Cancel in-progress jobs when pushing to the same branch.
concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}
jobs: jobs:
tests: build:
name: Build RPMs
runs-on: ubuntu-latest
runs-on: "ubuntu-latest" container:
strategy: image: ghcr.io/caronc/apprise-rpmbuild:el9
options: --user root
credentials:
username: caronc
password: ${{ secrets.CR_PAT }}
# Run all jobs to completion (false), or cancel
# all jobs once the first one fails (true).
fail-fast: false
# Define a list of build targets. The labels should match the
# items within the `services` section of `docker-compose.yml`.
matrix:
target: [
"rpmbuild.el9",
]
defaults:
run:
shell: bash
name: Target ${{ matrix.target }}
steps: steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Acquire sources - name: Build RPMs
uses: actions/checkout@v4 run: ./bin/build-rpm.sh
env:
APPRISE_DIR: ${{ github.workspace }}
- name: Build package - name: Show RPMs found for upload
run: | run: |
docker compose run --user root --rm ${{ matrix.target }} build-rpm.sh echo "Listing dist/**/*.rpm:"
find dist -type f -name '*.rpm'
- name: Verify package has been produced - name: Upload RPM Artifacts
run: | uses: actions/upload-artifact@v4
ls -alF dist/rpm/noarch/*.noarch.rpm with:
name: built-rpms
path: |
dist/**/*.rpm
if-no-files-found: error
retention-days: 5
verify:
name: Verify RPMs
needs: build
runs-on: ubuntu-latest
container:
image: ghcr.io/caronc/apprise-rpmbuild:el9
options: --user root
credentials:
username: caronc
password: ${{ secrets.CR_PAT }}
steps:
- name: Download built RPMs
uses: actions/download-artifact@v4
with:
name: built-rpms
path: ./dist
- name: Lint RPMs
run: rpmlint ./dist/**/*.rpm
- name: Install and verify RPMs
run: |
echo "Installing RPMs from: ./dist/"
find ./dist -name '*.rpm'
dnf install -y ./dist/**/*.rpm
apprise --version
- name: Check Installed Files
run: rpm -qlp ./dist/**/*.rpm

View File

@ -1,149 +1,132 @@
name: Tests name: Run Tests
on: on:
# Run tests on push to main, master, or any release/ branch
# On which repository actions to trigger the build.
push: push:
branches: [ master ] branches: [main, master, 'release/**']
# Always test on pull requests targeting main/master
pull_request: pull_request:
branches: [ master ] branches: [main, master]
# Allow manual triggering via GitHub UI
# Allow job to be triggered manually.
workflow_dispatch: workflow_dispatch:
# Cancel in-progress jobs when pushing to the same branch.
concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}
jobs: jobs:
test:
name: Python ${{ matrix.python-version }} ${{ matrix.tox_env }} on ${{ matrix.os }}
runs-on: ubuntu-latest
tests:
runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false # Let all jobs run, even if one fails
# Run all jobs to completion (false), or cancel
# all jobs once the first one fails (true).
fail-fast: true
# Define a minimal test matrix, it will be
# expanded using subsequent `include` items.
matrix: matrix:
os: ["ubuntu-latest"]
python-version: ["3.11"]
bare: [false]
include: include:
- python-version: "3.8"
tox_env: qa
setup_python: true
# Within the `bare` environment, `all-plugin-requirements.txt` will NOT be # Modern Python versions (can rely on default runner environment)
# installed, to verify the application also works without those dependencies. - python-version: "3.9"
- os: "ubuntu-latest" tox_env: qa
setup_python: false
- python-version: "3.10"
tox_env: qa
setup_python: false
- python-version: "3.11"
tox_env: qa
setup_python: false
- python-version: "3.12"
tox_env: qa
setup_python: false
# Platform validation only (one version)
- os: windows-latest
python-version: "3.11" python-version: "3.11"
bare: true tox_env: qa
# Let's save resources and only build a single slot on macOS- and Windows. - os: macos-latest
- os: "macos-latest"
python-version: "3.11"
- os: "windows-latest"
python-version: "3.11" python-version: "3.11"
tox_env: qa
# Test more available versions of CPython on Linux. # Minimal test run on latest Python only
- os: "ubuntu-latest" # this verifies Apprise still works when extra libraries are not available
python-version: "3.8" - python-version: "3.12"
- os: "ubuntu-latest" tox_env: minimal
python-version: "3.9" setup_python: false
- os: "ubuntu-latest"
python-version: "3.10"
- os: "ubuntu-latest"
python-version: "3.11"
- os: "ubuntu-latest"
python-version: "3.12"
defaults:
run:
shell: bash
env:
OS: ${{ matrix.os }}
PYTHON: ${{ matrix.python-version }}
BARE: ${{ matrix.bare }}
name: Python ${{ matrix.python-version }} on ${{ matrix.os }} ${{ matrix.bare && '(bare)' || '' }}
steps: steps:
- uses: actions/checkout@v4
- name: Acquire sources # Legacy Python versions 3.8 are no longer on GitHub-hosted runners
uses: actions/checkout@v4 # Use setup-python to install them explicitly
- name: Set up Python (legacy)
if: matrix.setup_python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install prerequisites (Linux) # Install tox for isolated environment and plugin test orchestration
if: runner.os == 'Linux' - name: Install tox
run: | run: python -m pip install tox
sudo apt-get update
sudo apt-get install libdbus-1-dev
- name: Setup Python # Run tox with the specified environment (qa, minimal, etc.)
uses: actions/setup-python@v5 - name: Run tox for ${{ matrix.tox_env }}
with: run: tox -e ${{ matrix.tox_env }}
python-version: ${{ matrix.python-version }}
architecture: x64
cache: 'pip'
cache-dependency-path: |
setup.py
requirements.txt
dev-requirements.txt
all-plugin-requirements.txt
win-requirements.txt
- name: Install project dependencies (Baseline) - name: Verify .coverage file existence
run: | if: always()
pip install --use-pep517 wheel run: |
pip install --use-pep517 -r requirements.txt -r dev-requirements.txt echo "::group::Looking for .coverage file"
ls -alh .
echo "::endgroup::"
- name: Install project dependencies (All plugins) - name: Upload coverage report
if: matrix.bare != true if: always()
run: | uses: actions/upload-artifact@v4
pip install --use-pep517 -r all-plugin-requirements.txt with:
name: coverage-${{ matrix.os }}-${{ matrix.python-version }}-${{ matrix.tox_env }}
- name: Install project dependencies (Windows) path: .coverage
if: runner.os == 'Windows' include-hidden-files: true
run: |
pip install --use-pep517 -r win-requirements.txt || true
# Install package in editable mode, codecov:
# and run project-specific tasks. name: Upload merged coverage to Codecov
- name: Setup project runs-on: ubuntu-latest
run: | needs: test # Waits for all matrix jobs to complete
python -m pip install --upgrade pip setuptools wheel if: always() # Even if a test fails, still attempt to upload what we have
pip install --use-pep517 --editable=.
python setup.py compile_catalog
# For saving resources, code style checking is steps:
# only invoked within the `bare` environment. - uses: actions/checkout@v4
- name: Check code style
if: matrix.bare == true
run: |
flake8 . --count --show-source --statistics
- name: Run tests - name: Download all coverage reports
run: | uses: actions/download-artifact@v4
coverage run -m pytest --junitxml=test-results.xml with:
path: coverage-artifacts
- name: Process coverage data - name: Combine and generate coverage
run: | run: |
coverage combine pip install coverage
coverage xml
coverage report # Create a consistent temp dir
mkdir -p coverage-inputs
# Copy and rename each coverage file to .coverage.job_name
i=0
for f in $(find coverage-artifacts -name .coverage); do
cp "$f" "coverage-inputs/.coverage.$i"
i=$((i+1))
done
# Confirm files staged
ls -alh coverage-inputs
# Combine them all
coverage combine coverage-inputs
coverage report
coverage xml -o coverage.xml
- name: Upload coverage data # Upload merged coverage results to Codecov for visualization
uses: codecov/codecov-action@v4 - name: Upload to Codecov
with: uses: codecov/codecov-action@v4
files: ./coverage.xml with:
fail_ci_if_error: false token: ${{ secrets.CODECOV_TOKEN }}
token: ${{ secrets.CODECOV_TOKEN }} file: coverage.xml
fail_ci_if_error: false # Avoid failing job if Codecov is down
- name: Upload test results
uses: codecov/codecov-action@v4
with:
files: ./test-results.xml
fail_ci_if_error: false
type: test-results

6
.gitignore vendored
View File

@ -3,6 +3,9 @@ __pycache__/
*.py[cod] *.py[cod]
*$py.class *$py.class
# left-over-files from conflicts/merges
*.orig
# C extensions # C extensions
*.so *.so
@ -49,6 +52,7 @@ coverage.xml
# Translations # Translations
*.mo *.mo
*.pot
# Django stuff: # Django stuff:
*.log *.log
@ -69,4 +73,6 @@ target/
.project .project
.pydevproject .pydevproject
.settings .settings
# Others
.DS_Store .DS_Store

130
KEYWORDS
View File

@ -1,130 +0,0 @@
Africas Talking
Alerts
Apprise API
Automated Packet Reporting System
AWS
Bark
BlueSky
BulkSMS
BulkVS
Burst SMS
Chanify
Chat
CLI
Clickatell
ClickSend
D7Networks
Dapnet
DBus
DingTalk
Discord
Email
Emby
Enigma2
FCM
Feishu
Flock
Form
Free Mobile
Gnome
Google Chat
Gotify
Growl
Guilded
Home Assistant
httpSMS
IFTTT
Join
JSON
Kavenegar
KODI
Kumulos
LaMetric
Lark
Line
MacOSX
Mailgun
Mastodon
Matrix
Mattermost
MessageBird
Microsoft
Misskey
MQTT
MSG91
MSTeams
Nextcloud
NextcloudTalk
Notica
Notifiarr
Notifico
Ntfy
Office365
OneSignal
Opsgenie
PagerDuty
PagerTree
ParsePlatform
Plivo
PopcornNotify
Power Automate
Prowl
PushBullet
Pushed
Pushjet
PushMe
Push Notifications
Pushover
Pushplus
PushSafer
Pushy
PushDeer
QQ Push
Reddit
Resend
Revolt
Rocket.Chat
RSyslog
Ryver
SendGrid
ServerChan
Seven
SES
SFR
Signal
SimplePush
Sinch
Slack
SMPP
SMSEagle
SMS Manager
SMTP2Go
SNS
SparkPost
Splunk
Spike
SpugPush
Streamlabs
Stride
Synology Chat
Syslog
Techulus
Telegram
Threema Gateway
Twilio
Twist
Twitter
Vapid
VictorOps
Voipms
Vonage
Webpush
Webex
WeCom Bot
WhatsApp
Windows
Workflows
WxPusher
XBMC
XML
Zulip

View File

@ -1,10 +1,13 @@
include LICENSE include LICENSE
include KEYWORDS
include README.md include README.md
include pyproject.toml
include tox.ini
include requirements.txt include requirements.txt
include win-requirements.txt include win-requirements.txt
include dev-requirements.txt include dev-requirements.txt
recursive-include test * include all-plugin-requirements.txt
recursive-include tests *
recursive-include packaging * recursive-include packaging *
global-exclude *.pyc global-exclude *.pyc
global-exclude *.pyo
global-exclude __pycache__ global-exclude __pycache__

View File

@ -1,6 +1,8 @@
# #
# Plugin Dependencies # Note: This file is being kept for backwards compatibility with
# # legacy systems that point here. All future changes should
# occur in pyproject.toml. Contents of this file can be found
# in [project.optional-dependencies].all-plugins
# Provides fcm:// and spush:// # Provides fcm:// and spush://
cryptography cryptography

View File

@ -1,978 +0,0 @@
# Translations template for apprise.
# Copyright (C) 2025 Chris Caron
# This file is distributed under the same license as the apprise project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2025.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: apprise 1.9.3\n"
"Report-Msgid-Bugs-To: lead2gold@gmail.com\n"
"POT-Creation-Date: 2025-03-30 15:32-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.17.0\n"
msgid "A local Gnome environment is required."
msgstr ""
msgid "A local Microsoft Windows environment is required."
msgstr ""
msgid "API Access Token"
msgstr ""
msgid "API Key"
msgstr ""
msgid "API Secret"
msgstr ""
msgid "API Token"
msgstr ""
msgid "API Version"
msgstr ""
msgid "Access Key"
msgstr ""
msgid "Access Key ID"
msgstr ""
msgid "Access Secret"
msgstr ""
msgid "Access Token"
msgstr ""
msgid "Account Email or Object ID"
msgstr ""
msgid "Account SID"
msgstr ""
msgid "Action"
msgstr ""
msgid "Action Mapping"
msgstr ""
msgid "Add Tokens"
msgstr ""
msgid "Alert Type"
msgstr ""
msgid "Alias"
msgstr ""
msgid "Amount"
msgstr ""
msgid "App Access Token"
msgstr ""
msgid "App ID"
msgstr ""
msgid "App Token"
msgstr ""
msgid "App User Name"
msgstr ""
msgid "App Version"
msgstr ""
msgid "Application ID"
msgstr ""
msgid "Application Key"
msgstr ""
msgid "Application Secret"
msgstr ""
msgid "Attach"
msgstr ""
msgid "Attach File As"
msgstr ""
msgid "Attach Filename"
msgstr ""
msgid "Auth ID"
msgstr ""
msgid "Auth Token"
msgstr ""
msgid "Authentication Key"
msgstr ""
msgid "Authentication Type"
msgstr ""
msgid "Avatar Image"
msgstr ""
msgid "Avatar URL"
msgstr ""
msgid "Badge"
msgstr ""
msgid "Batch Mode"
msgstr ""
msgid "Blind Carbon Copy"
msgstr ""
msgid "Bot Name"
msgstr ""
msgid "Bot Token"
msgstr ""
msgid "Bot Webhook Key"
msgstr ""
msgid "Cache Age"
msgstr ""
msgid "Cache Results"
msgstr ""
msgid "Call"
msgstr ""
msgid "Carbon Copy"
msgstr ""
msgid "Category"
msgstr ""
msgid "Chanify"
msgstr ""
msgid "Channel ID"
msgstr ""
msgid "Channels"
msgstr ""
msgid "Class"
msgstr ""
msgid "Click"
msgstr ""
msgid "Client ID"
msgstr ""
msgid "Client Secret"
msgstr ""
msgid "Component"
msgstr ""
msgid "Consumer Key"
msgstr ""
msgid "Consumer Secret"
msgstr ""
msgid "Content Placement"
msgstr ""
msgid "Country"
msgstr ""
msgid "Currency"
msgstr ""
msgid "Custom Data"
msgstr ""
msgid "Custom Details"
msgstr ""
msgid "Custom Icon"
msgstr ""
msgid "Custom Image URL"
msgstr ""
msgid "Cycles"
msgstr ""
msgid "DBus Notification"
msgstr ""
msgid "Data Entries"
msgstr ""
msgid "Decode Template Args"
msgstr ""
msgid "Delay"
msgstr ""
msgid "Details"
msgstr ""
msgid "Detect Bot Owner"
msgstr ""
msgid "Device"
msgstr ""
msgid "Device API Key"
msgstr ""
msgid "Device ID"
msgstr ""
msgid "Device Name"
msgstr ""
msgid "Discord Event ID"
msgstr ""
msgid "Display Footer"
msgstr ""
msgid "Domain"
msgstr ""
msgid "Duration"
msgstr ""
msgid "Email"
msgstr ""
msgid "Email Header"
msgstr ""
msgid "Embed URL"
msgstr ""
msgid "Enable Contents"
msgstr ""
msgid "Entity"
msgstr ""
msgid "Entity ID"
msgstr ""
msgid "Event"
msgstr ""
msgid "Events"
msgstr ""
msgid "Expire"
msgstr ""
msgid "Facility"
msgstr ""
msgid "Feishu"
msgstr ""
msgid "Fetch Method"
msgstr ""
msgid "Flair ID"
msgstr ""
msgid "Flair Text"
msgstr ""
msgid "Flash"
msgstr ""
msgid "Footer Logo"
msgstr ""
msgid "Forced File Name"
msgstr ""
msgid "Forced Mime Type"
msgstr ""
msgid "Free-Mobile"
msgstr ""
msgid "From"
msgstr ""
msgid "From Email"
msgstr ""
msgid "From Name"
msgstr ""
msgid "From Phone ID"
msgstr ""
msgid "From Phone No"
msgstr ""
msgid "GET Params"
msgstr ""
msgid "Gateway"
msgstr ""
msgid "Gateway ID"
msgstr ""
msgid "Gnome Notification"
msgstr ""
msgid "Group"
msgstr ""
msgid "HTTP Header"
msgstr ""
msgid "Hostname"
msgstr ""
msgid "IRC Colors"
msgstr ""
msgid "Icon Type"
msgstr ""
msgid "Icon URL"
msgstr ""
msgid "Idempotency-Key"
msgstr ""
msgid "Identifier"
msgstr ""
msgid "Image Link"
msgstr ""
msgid "Include Footer"
msgstr ""
msgid "Include Image"
msgstr ""
msgid "Include Segment"
msgstr ""
msgid "Integration ID"
msgstr ""
msgid "Integration Key"
msgstr ""
msgid "Interpret Emojis"
msgstr ""
msgid "Is Ad?"
msgstr ""
msgid "Is Spoiler"
msgstr ""
msgid "Kind"
msgstr ""
msgid "Label"
msgstr ""
msgid "Language"
msgstr ""
msgid "Language Code"
msgstr ""
msgid "Level"
msgstr ""
msgid "Local File"
msgstr ""
msgid "Locale"
msgstr ""
msgid "Log PID"
msgstr ""
msgid "Log to STDERR"
msgstr ""
msgid "Long-Lived Access Token"
msgstr ""
msgid "MacOSX Notification"
msgstr ""
msgid "Markdown Version"
msgstr ""
msgid "Master Key"
msgstr ""
msgid "Matrix API Verion"
msgstr ""
msgid "Media Type"
msgstr ""
msgid "Memory"
msgstr ""
msgid "Message Hook"
msgstr ""
msgid "Message Mode"
msgstr ""
msgid "Message Type"
msgstr ""
msgid "Meta Extras"
msgstr ""
msgid "Modal"
msgstr ""
msgid "Mode"
msgstr ""
msgid "NSFW"
msgstr ""
msgid "Name"
msgstr ""
msgid "Nextcloud Talk"
msgstr ""
msgid "No dependencies."
msgstr ""
msgid "Notification Color"
msgstr ""
msgid "Notification ID"
msgstr ""
msgid "Notify Format"
msgstr ""
msgid "OAuth Access Token"
msgstr ""
msgid "OAuth2 KeyFile"
msgstr ""
msgid ""
"Only works with Mac OS X 10.8 and higher. Additionally requires that "
"/usr/local/bin/terminal-notifier is locally accessible."
msgstr ""
msgid "Open/Click URL"
msgstr ""
msgid "Organization"
msgstr ""
msgid "Originating Address"
msgstr ""
msgid "Overflow Mode"
msgstr ""
msgid "PGP Encryption"
msgstr ""
msgid "PGP Public Key Path"
msgstr ""
msgid "Packages are recommended to improve functionality."
msgstr ""
msgid "Packages are required to function."
msgstr ""
msgid "Password"
msgstr ""
msgid "Path"
msgstr ""
msgid "Payload Extras"
msgstr ""
msgid "Persistent Storage"
msgstr ""
msgid "Port"
msgstr ""
msgid "Postback Data"
msgstr ""
msgid "Prefix"
msgstr ""
msgid "Priority"
msgstr ""
msgid "Private Key"
msgstr ""
msgid "Project ID"
msgstr ""
msgid "Provider Key"
msgstr ""
msgid "Pushkey"
msgstr ""
msgid "QOS"
msgstr ""
msgid "Query Method"
msgstr ""
msgid "Recipient Phone Number"
msgstr ""
msgid "Region"
msgstr ""
msgid "Region Name"
msgstr ""
msgid "Remove Tokens"
msgstr ""
msgid "Reply To"
msgstr ""
msgid "Reply To Email"
msgstr ""
msgid "Resend Delay"
msgstr ""
msgid "Resubmit Flag"
msgstr ""
msgid "Retain Messages"
msgstr ""
msgid "Retry"
msgstr ""
msgid "Room ID"
msgstr ""
msgid "Route Group"
msgstr ""
msgid "SMS Mode"
msgstr ""
msgid "SMTP Server"
msgstr ""
msgid "Salt"
msgstr ""
msgid "Schema"
msgstr ""
msgid "Secret"
msgstr ""
msgid "Secret API Key"
msgstr ""
msgid "Secret Access Key"
msgstr ""
msgid "Secret Key"
msgstr ""
msgid "Secure Mode"
msgstr ""
msgid "Send Replies"
msgstr ""
msgid "Sender ID"
msgstr ""
msgid "Sender Name"
msgstr ""
msgid "Sensitive Attachments"
msgstr ""
msgid "Server Discovery"
msgstr ""
msgid "Server Key"
msgstr ""
msgid "Server Timeout"
msgstr ""
msgid "Service ID"
msgstr ""
msgid "Service Password"
msgstr ""
msgid "Severity"
msgstr ""
msgid "Short URL"
msgstr ""
msgid "Show Status"
msgstr ""
msgid "Signature"
msgstr ""
msgid "Silent Notification"
msgstr ""
msgid "Société Française du Radiotéléphone"
msgstr ""
msgid "Socket Connect Timeout"
msgstr ""
msgid "Socket Read Timeout"
msgstr ""
msgid "Sound"
msgstr ""
msgid "Sound Link"
msgstr ""
msgid "Source"
msgstr ""
msgid "Source Email"
msgstr ""
msgid "Source Phone No"
msgstr ""
msgid "Space ID"
msgstr ""
msgid "Special Text Color"
msgstr ""
msgid "Splunk On-Call"
msgstr ""
msgid "Spoiler Text"
msgstr ""
msgid "Sticky"
msgstr ""
msgid "Subtitle"
msgstr ""
msgid "TTS Voice"
msgstr ""
msgid "Tags"
msgstr ""
msgid "Target Callsign"
msgstr ""
msgid "Target Channel"
msgstr ""
msgid "Target Channel ID"
msgstr ""
msgid "Target Chat ID"
msgstr ""
msgid "Target Contact"
msgstr ""
msgid "Target Device"
msgstr ""
msgid "Target Email"
msgstr ""
msgid "Target Emails"
msgstr ""
msgid "Target Encoded ID"
msgstr ""
msgid "Target Escalation"
msgstr ""
msgid "Target Group"
msgstr ""
msgid "Target Group ID"
msgstr ""
msgid "Target Phone"
msgstr ""
msgid "Target Phone No"
msgstr ""
msgid "Target Player ID"
msgstr ""
msgid "Target Queue"
msgstr ""
msgid "Target Room Alias"
msgstr ""
msgid "Target Room ID"
msgstr ""
msgid "Target Routing Key"
msgstr ""
msgid "Target Schedule"
msgstr ""
msgid "Target Short Code"
msgstr ""
msgid "Target Stream"
msgstr ""
msgid "Target Subreddit"
msgstr ""
msgid "Target Team"
msgstr ""
msgid "Target Threema ID"
msgstr ""
msgid "Target Topic"
msgstr ""
msgid "Target User"
msgstr ""
msgid "Target User ID"
msgstr ""
msgid "Targets"
msgstr ""
msgid "Targets "
msgstr ""
msgid "Team Name"
msgstr ""
msgid "Template"
msgstr ""
msgid "Template Data"
msgstr ""
msgid "Template ID"
msgstr ""
msgid "Template Mapping"
msgstr ""
msgid "Template Name"
msgstr ""
msgid "Template Path"
msgstr ""
msgid "Template Tokens"
msgstr ""
msgid "Tenant Domain"
msgstr ""
msgid "Test Only"
msgstr ""
msgid "Text To Speech"
msgstr ""
msgid "Third Party ID"
msgstr ""
msgid "Thread ID"
msgstr ""
msgid "Thread Key"
msgstr ""
msgid "Timeout"
msgstr ""
msgid "To Channel ID"
msgstr ""
msgid "To Email"
msgstr ""
msgid "To User ID"
msgstr ""
msgid "Token"
msgstr ""
msgid "Token A"
msgstr ""
msgid "Token B"
msgstr ""
msgid "Token C"
msgstr ""
msgid "Token D"
msgstr ""
msgid "Topic"
msgstr ""
msgid "Topic Thread ID"
msgstr ""
msgid "Transmitter Groups"
msgstr ""
msgid "URL"
msgstr ""
msgid "URL Prefix"
msgstr ""
msgid "URL Title"
msgstr ""
msgid "Unicode Characters"
msgstr ""
msgid "Upload"
msgstr ""
msgid "Urgency"
msgstr ""
msgid "Use Avatar"
msgstr ""
msgid "Use Blocks"
msgstr ""
msgid "Use Fields"
msgstr ""
msgid "Use Session"
msgstr ""
msgid "User Email"
msgstr ""
msgid "User Key"
msgstr ""
msgid "User Name"
msgstr ""
msgid "Username"
msgstr ""
msgid "Verify SSL"
msgstr ""
msgid "Version"
msgstr ""
msgid "Vibration"
msgstr ""
msgid "Visibility"
msgstr ""
msgid "Volume"
msgstr ""
msgid "Web Based"
msgstr ""
msgid "Web Page Preview"
msgstr ""
msgid "Webhook"
msgstr ""
msgid "Webhook ID"
msgstr ""
msgid "Webhook Key"
msgstr ""
msgid "Webhook Mode"
msgstr ""
msgid "Webhook Token"
msgstr ""
msgid "Workflow ID"
msgstr ""
msgid "Workspace"
msgstr ""
msgid "Wrap Text"
msgstr ""
msgid "X-Axis"
msgstr ""
msgid "Y-Axis"
msgstr ""
msgid "libdbus-1.so.x must be installed."
msgstr ""
msgid "ttl"
msgstr ""
msgid "validity"
msgstr ""

View File

@ -1,290 +0,0 @@
# English translations for apprise.
# Copyright (C) 2019 Chris Caron
# This file is distributed under the same license as the apprise project.
# Chris Caron <lead2gold@gmail.com>, 2019.
#
msgid ""
msgstr ""
"Project-Id-Version: apprise 1.4.5\n"
"Report-Msgid-Bugs-To: lead2gold@gmail.com\n"
"POT-Creation-Date: 2019-05-28 16:56-0400\n"
"PO-Revision-Date: 2019-05-24 20:00-0400\n"
"Last-Translator: Chris Caron <lead2gold@gmail.com>\n"
"Language: en\n"
"Language-Team: en <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.6.0\n"
msgid "API Key"
msgstr "API Key"
msgid "Access Key"
msgstr "Access Key"
msgid "Access Key ID"
msgstr "Access Key ID"
msgid "Access Secret"
msgstr "Access Secret"
msgid "Access Token"
msgstr "Access Token"
msgid "Account SID"
msgstr "Account SID"
msgid "Add Tokens"
msgstr "Add Tokens"
msgid "Application Key"
msgstr "Application Key"
msgid "Application Secret"
msgstr "Application Secret"
msgid "Auth Token"
msgstr "Auth Token"
msgid "Authorization Token"
msgstr "Authorization Token"
msgid "Avatar Image"
msgstr "Avatar Image"
msgid "Bot Name"
msgstr "Bot Name"
msgid "Bot Token"
msgstr "Bot Token"
msgid "Channels"
msgstr "Channels"
msgid "Consumer Key"
msgstr "Consumer Key"
msgid "Consumer Secret"
msgstr "Consumer Secret"
msgid "Detect Bot Owner"
msgstr "Detect Bot Owner"
msgid "Device ID"
msgstr "Device ID"
msgid "Display Footer"
msgstr "Display Footer"
msgid "Domain"
msgstr "Domain"
msgid "Duration"
msgstr "Duration"
msgid "Events"
msgstr "Events"
msgid "Footer Logo"
msgstr "Footer Logo"
msgid "From Email"
msgstr "From Email"
msgid "From Name"
msgstr "From Name"
msgid "From Phone No"
msgstr "From Phone No"
msgid "Group"
msgstr "Group"
msgid "HTTP Header"
msgstr "HTTP Header"
msgid "Hostname"
msgstr "Hostname"
msgid "Include Image"
msgstr "Include Image"
msgid "Modal"
msgstr "Modal"
msgid "Notify Format"
msgstr "Notify Format"
msgid "Organization"
msgstr "Organization"
msgid "Overflow Mode"
msgstr "Overflow Mode"
msgid "Password"
msgstr "Password"
msgid "Port"
msgstr "Port"
msgid "Priority"
msgstr "Priority"
msgid "Provider Key"
msgstr "Provider Key"
msgid "Region"
msgstr "Region"
msgid "Region Name"
msgstr "Region Name"
msgid "Remove Tokens"
msgstr "Remove Tokens"
msgid "Rooms"
msgstr "Rooms"
msgid "SMTP Server"
msgstr "SMTP Server"
msgid "Schema"
msgstr "Schema"
msgid "Secret Access Key"
msgstr "Secret Access Key"
msgid "Secret Key"
msgstr "Secret Key"
msgid "Secure Mode"
msgstr "Secure Mode"
msgid "Server Timeout"
msgstr "Server Timeout"
msgid "Sound"
msgstr "Sound"
msgid "Source JID"
msgstr "Source JID"
msgid "Target Channel"
msgstr "Target Channel"
msgid "Target Chat ID"
msgstr "Target Chat ID"
msgid "Target Device"
msgstr "Target Device"
msgid "Target Device ID"
msgstr "Target Device ID"
msgid "Target Email"
msgstr "Target Email"
msgid "Target Emails"
msgstr "Target Emails"
msgid "Target Encoded ID"
msgstr "Target Encoded ID"
msgid "Target JID"
msgstr "Target JID"
msgid "Target Phone No"
msgstr "Target Phone No"
msgid "Target Room Alias"
msgstr "Target Room Alias"
msgid "Target Room ID"
msgstr "Target Room ID"
msgid "Target Short Code"
msgstr "Target Short Code"
msgid "Target Tag ID"
msgstr "Target Tag ID"
msgid "Target Topic"
msgstr "Target Topic"
msgid "Target User"
msgstr "Target User"
msgid "Targets"
msgstr "Targets"
msgid "Text To Speech"
msgstr "Text To Speech"
msgid "To Channel ID"
msgstr "To Channel ID"
msgid "To Email"
msgstr "To Email"
msgid "To User ID"
msgstr "To User ID"
msgid "Token"
msgstr "Token"
msgid "Token A"
msgstr "Token A"
msgid "Token B"
msgstr "Token B"
msgid "Token C"
msgstr "Token C"
msgid "Urgency"
msgstr "Urgency"
msgid "Use Avatar"
msgstr "Use Avatar"
msgid "User"
msgstr "User"
msgid "User Key"
msgstr "User Key"
msgid "User Name"
msgstr "User Name"
msgid "Username"
msgstr "Username"
msgid "Verify SSL"
msgstr "Verify SSL"
msgid "Version"
msgstr "Version"
msgid "Webhook"
msgstr "Webhook"
msgid "Webhook ID"
msgstr "Webhook ID"
msgid "Webhook Mode"
msgstr "Webhook Mode"
msgid "Webhook Token"
msgstr "Webhook Token"
msgid "X-Axis"
msgstr "X-Axis"
msgid "XEP"
msgstr "XEP"
msgid "Y-Axis"
msgstr "Y-Axis"

File diff suppressed because it is too large Load Diff

2
babel.cfg Normal file
View File

@ -0,0 +1,2 @@
[python: **.py]
encoding = utf-8

View File

@ -26,90 +26,57 @@
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# 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
set -e
# Directory where Apprise Source Code can be found # Set Apprise root directory
APPRISE_DIR="/apprise" APPRISE_DIR="${APPRISE_DIR:-/apprise}"
PYTHON=python3 PYTHON=python3
PIP=pip3 TOX="tox -c $APPRISE_DIR/tox.ini"
VENV_CMD="$PYTHON -m venv" DIST_DIR="${DIST_DIR:-$PWD/dist}"
mkdir -p "$DIST_DIR"
mkenv(){ echo "==> Cleaning previous builds"
# Prepares RPM Environment $TOX -e clean --notest
cat << _EOF > $HOME/.rpmmacros
# macros
%_topdir $APPRISE_DIR
%_sourcedir %{_topdir}/dist
%_specdir %{_topdir}/dist
%_rpmdir %{_topdir}/dist/rpm
%_srcrpmdir %{_topdir}/dist/rpm
%_builddir %{_topdir}/build/rpm
_EOF
# Prepare our working directories if not already present
mkdir -p $APPRISE_DIR/{dist/rpm,build/rpm}
return 0
}
clean(){ echo "==> Linting RPM spec"
# Tidy .pyc files rpmlint "$APPRISE_DIR/packaging/redhat/python-apprise.spec"
find $APPRISE_DIR -name '*.pyc' -delete &>/dev/null
find $APPRISE_DIR -type d -name '__pycache__' -exec rm -rf {} \ &>/dev/null;
# Remove previously build details
[ -d "$APPRISE_DIR/apprise.egg-info" ] && rm -rf $APPRISE_DIR/apprise.egg-info
[ -d "$APPRISE_DIR/build" ] && rm -rf $APPRISE_DIR/build
[ -d "$APPRISE_DIR/BUILDROOT" ] && rm -rf $APPRISE_DIR/BUILDROOT
}
build(){ echo "==> Running tests"
# Test spec file for any issues $TOX -e py312
rpmlint "$APPRISE_DIR/packaging/redhat/python-apprise.spec"
[ $? -ne 0 ] && echo "RPMLint Failed!" && return 1
# Prepare RPM Package echo "==> Generating man pages"
# Detect our version ronn --roff --organization="Chris Caron <lead2gold@gmail.com>" \
local VER=$(rpmspec -q --qf "%{version}\n" \ "$APPRISE_DIR/packaging/man/apprise.md"
"$APPRISE_DIR/packaging/redhat/python-apprise.spec" 2>/dev/null | head -n1)
[ -z "$VER" ] && echo "Could not detect Apprise RPM Version" && return 1
if [ ! -f "$APPRISE_DIR/dist/apprise-$VER.tar.gz" ]; then echo "==> Extracting translations"
# Build Apprise $TOX -e i18n || { echo "Translation extraction failed!" ; exit 1; }
if [ ! -x $HOME/dev/bin/activate ]; then
$VENV_CMD $HOME/dev
[ $? -ne 0 ] && echo "Could not create Virtual Python Environment" && return 1
fi
. $HOME/dev/bin/activate
$PIP install coverage babel wheel markdown
pushd $APPRISE_DIR echo "==> Compiling translations"
# Build Man Page $TOX -e compile || { echo "Translation compilation failed!" ; exit 1; }
ronn --roff $APPRISE_DIR/packaging/man/apprise.md
$PYTHON setup.py extract_messages
$PYTHON setup.py sdist
# exit from our virtual environment echo "==> Building source distribution"
deactivate $TOX -e build-sdist || { echo "sdist build failed!" ; exit 1; }
fi
# Prepare our RPM Source and SPEC dependencies VERSION=$(rpmspec -q --qf "%{version}\n" "$APPRISE_DIR/packaging/redhat/python-apprise.spec" | head -n1)
find "$APPRISE_DIR/packaging/man/" -type f -name '*.1' \ TARBALL="$APPRISE_DIR/dist/apprise-${VERSION}.tar.gz"
-exec cp --verbose {} "$APPRISE_DIR/dist" \;
find "$APPRISE_DIR/packaging/redhat" -type f -name '*.patch' \
-exec cp --verbose {} "$APPRISE_DIR/dist" \;
find "$APPRISE_DIR/packaging/redhat" -type f -name '*.spec' \
-exec cp --verbose {} "$APPRISE_DIR/dist" \;
# Build and Test our RPM Package if [[ ! -f "$TARBALL" ]]; then
rpmbuild -ba "$APPRISE_DIR/dist/python-apprise.spec" echo "Tarball not found: $TARBALL"
return $? exit 1
} fi
# Prepare our environment echo "==> Copying tarball to SOURCES directory"
mkenv mkdir -p "$APPRISE_DIR/SOURCES"
cp "$TARBALL" "$APPRISE_DIR/SOURCES/"
# Clean echo "==> Building RPM"
clean rpmbuild --define "_topdir $APPRISE_DIR" \
--define "_sourcedir $APPRISE_DIR/SOURCES" \
--define "_specdir $APPRISE_DIR/packaging/redhat" \
--define "_srcrpmdir $APPRISE_DIR/SRPMS" \
--define "_rpmdir $DIST_DIR" \
-ba "$APPRISE_DIR/packaging/redhat/python-apprise.spec"
# Build echo "✅ RPM build completed successfully"
build
# Return our build status
exit $?

View File

@ -1,6 +1,14 @@
#
# Note: This file is being kept for backwards compatibility with
# legacy systems that point here. All future changes should
# occur in pyproject.toml. Contents of this file can be found
# in [project.optional-dependencies].dev
coverage coverage
flake8 mock
pytest pytest
pytest-cov pytest-cov
pytest-mock pytest-mock
ruff
babel babel
validate-pyproject

View File

@ -1,58 +1,57 @@
version: "3.3"
services: services:
test.py39: test.py39:
build: build:
context: . context: .
dockerfile: test/docker/Dockerfile.py39 dockerfile: tests/docker/Dockerfile.py39
volumes: volumes:
- ./:/apprise - ./:/apprise
test.py310: test.py310:
build: build:
context: . context: .
dockerfile: test/docker/Dockerfile.py310 dockerfile: tests/docker/Dockerfile.py310
volumes: volumes:
- ./:/apprise - ./:/apprise
test.py311: test.py311:
build: build:
context: . context: .
dockerfile: test/docker/Dockerfile.py311 dockerfile: tests/docker/Dockerfile.py311
volumes: volumes:
- ./:/apprise - ./:/apprise
test.py312: test.py312:
build: build:
context: . context: .
dockerfile: test/docker/Dockerfile.py312 dockerfile: tests/docker/Dockerfile.py312
volumes: volumes:
- ./:/apprise - ./:/apprise
rpmbuild.el9: rpmbuild.el9:
build: build:
context: . context: .
dockerfile: test/docker/Dockerfile.el9 dockerfile: tests/docker/Dockerfile.el9
volumes: volumes:
- ./:/apprise - ./:/apprise
rpmbuild.f37: rpmbuild.f37:
build: build:
context: . context: .
dockerfile: test/docker/Dockerfile.f37 dockerfile: tests/docker/Dockerfile.f37
volumes: volumes:
- ./:/apprise - ./:/apprise
rpmbuild.f39: rpmbuild.f39:
build: build:
context: . context: .
dockerfile: test/docker/Dockerfile.f39 dockerfile: tests/docker/Dockerfile.f39
volumes: volumes:
- ./:/apprise - ./:/apprise
rpmbuild.rawhide: rpmbuild.rawhide:
build: build:
context: . context: .
dockerfile: test/docker/Dockerfile.rawhide dockerfile: tests/docker/Dockerfile.rawhide
volumes: volumes:
- ./:/apprise - ./:/apprise

View File

@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.9.1 .\" generated with Ronn-NG/v0.9.1
.\" http://github.com/apjanke/ronn-ng/tree/0.9.1 .\" http://github.com/apjanke/ronn-ng/tree/0.9.1
.TH "APPRISE" "1" "February 2025" "Chris Caron <lead2gold@gmail.com>" .TH "APPRISE" "1" "July 2025" "Chris Caron <lead2gold@gmail.com>"
.SH "NAME" .SH "NAME"
\fBapprise\fR \- Push Notifications that work with just about every platform! \fBapprise\fR \- Push Notifications that work with just about every platform!
.SH "SYNOPSIS" .SH "SYNOPSIS"

View File

@ -32,28 +32,50 @@
%bcond_without tests %bcond_without tests
%endif %endif
# Handling of new python building structure (for backwards compatiblity)
%global legacy_python_build 0
%if 0%{?fedora} && 0%{?fedora} <= 29
%global legacy_python_build 1
%endif
%if 0%{?rhel} && 0%{?rhel} <= 9
%global legacy_python_build 1
%endif
%global pypi_name apprise %global pypi_name apprise
%global common_description %{expand: \ # Handle rpmlint false positives
Apprise is a Python package for simplifying access to all of the different # - Prevent warnings:
notification services that are out there. Apprise opens the door and makes # en_US ntfy -> notify
it easy to access: # en_US httpSMS -> HTTP
# rpmlint: ignore-spelling httpSMS ntfy
Africas Talking, Apprise API, APRS, AWS SES, AWS SNS, Bark, BlueSky, Burst SMS, # - RHEL9 does not recognize: BSD-2-Clause which is correct
BulkSMS, BulkVS, Chanify, Clickatell, ClickSend, DAPNET, DingTalk, Discord, E-Mail, Emby, # rpmlint: ignore invalid-license
FCM, Feishu, Flock, Free Mobile, Google Chat, Gotify, Growl, Guilded, Home
Assistant, httpSMS, IFTTT, Join, Kavenegar, KODI, Kumulos, LaMetric, Lark, Line, %global common_description %{expand: \
MacOSX, Mailgun, Mastodon, Mattermost, Matrix, MessageBird, Microsoft Apprise is a Python package that simplifies access to many popular \
Windows, Microsoft Teams, Misskey, MQTT, MSG91, MyAndroid, Nexmo, Nextcloud, notification services. It supports sending alerts to platforms such as: \
NextcloudTalk, Notica, Notifiarr, Notifico, ntfy, Office365, OneSignal, \
Opsgenie, PagerDuty, PagerTree, ParsePlatform, Plivo, PopcornNotify, Prowl, `AfricasTalking`, `Apprise API`, `APRS`, `AWS SES`, `AWS SNS`, `Bark`, \
Pushalot, PushBullet, Pushjet, PushMe, Pushover, Pushplus, PushSafer, Pushy, `BlueSky`, `Burst SMS`, `BulkSMS`, `BulkVS`, `Chanify`, `Clickatell`, \
PushDeer, QQ Push, Revolt, Reddit, Resend, Rocket.Chat, RSyslog, SendGrid, `ClickSend`, `DAPNET`, `DingTalk`, `Discord`, `E-Mail`, `Emby`, `FCM`, \
ServerChan, Seven, SFR, Signal, SimplePush, Sinch, Slack, SMPP, SMSEagle, `Feishu`, `Flock`, `Free Mobile`, `Google Chat`, `Gotify`, `Growl`, \
SMS Manager, SMTP2Go, SparkPost, Splunk, Spike, Spug Push, Super Toasty, `Guilded`, `Home Assistant`, `httpSMS`, `IFTTT`, `Join`, `Kavenegar`, `KODI`, \
Streamlabs, Stride, Synology Chat, Syslog, Techulus Push, Telegram, Threema `Kumulos`, `LaMetric`, `Lark`, `Line`, `MacOSX`, `Mailgun`, `Mastodon`, \
Gateway, Twilio, Twitter, Twist, Vapid, VictorOps, Voipms, Vonage, WebPush, `Mattermost`, `Matrix`, `MessageBird`, `Microsoft Windows`, \
WeCom Bot, WhatsApp, Webex Teams, Workflows, WxPusher, XBMC} `Microsoft Teams`, `Misskey`, `MQTT`, `MSG91`, `MyAndroid`, `Nexmo`, \
`Nextcloud`, `NextcloudTalk`, `Notica`, `Notifiarr`, `Notifico`, `ntfy`, \
`Office365`, `OneSignal`, `Opsgenie`, `PagerDuty`, `PagerTree`, \
`ParsePlatform`, `Plivo`, `PopcornNotify`, `Prowl`, `Pushalot`, \
`PushBullet`, `Pushjet`, `PushMe`, `Pushover`, `Pushplus`, `PushSafer`, \
`Pushy`, `PushDeer`, `QQ Push`, `Revolt`, `Reddit`, `Resend`, `Rocket.Chat`, \
`RSyslog`, `SendGrid`, `ServerChan`, `Seven`, `SFR`, `Signal`, \
`SimplePush`, `Sinch`, `Slack`, `SMPP`, `SMSEagle`, `SMS Manager`, \
`SMTP2Go`, `SparkPost`, `Splunk`, `Spike`, `Spug Push`, `Super Toasty`, \
`Streamlabs`, `Stride`, `Synology Chat`, `Syslog`, `Techulus Push`, \
`Telegram`, `Threema Gateway`, `Twilio`, `Twitter`, `Twist`, `Vapid`, \
`VictorOps`, `Voipms`, `Vonage`, `WebPush`, `WeCom Bot`, `WhatsApp`, \
`Webex Teams`, `Workflows`, `WxPusher`, and `XBMC`.}
Name: python-%{pypi_name} Name: python-%{pypi_name}
Version: 1.9.3 Version: 1.9.3
@ -64,10 +86,13 @@ URL: https://github.com/caronc/%{pypi_name}
Source0: %{url}/archive/v%{version}/%{pypi_name}-%{version}.tar.gz Source0: %{url}/archive/v%{version}/%{pypi_name}-%{version}.tar.gz
BuildArch: noarch BuildArch: noarch
Obsoletes: python%{python3_pkgversion}-%{pypi_name} < %{version}-%{release}
Provides: python%{python3_pkgversion}-%{pypi_name} = %{version}-%{release}
%description %{common_description} %description %{common_description}
%package -n %{pypi_name} %package -n %{pypi_name}
Summary: Apprise CLI Tool Summary: Notify messaging platforms from the command line
Requires: python%{python3_pkgversion}-click >= 5.0 Requires: python%{python3_pkgversion}-click >= 5.0
Requires: python%{python3_pkgversion}-%{pypi_name} = %{version}-%{release} Requires: python%{python3_pkgversion}-%{pypi_name} = %{version}-%{release}
@ -83,7 +108,11 @@ Summary: A simple wrapper to many popular notification services used today
BuildRequires: gettext BuildRequires: gettext
BuildRequires: python%{python3_pkgversion}-devel BuildRequires: python%{python3_pkgversion}-devel
%if %{legacy_python_build}
# backwards compatible
BuildRequires: python%{python3_pkgversion}-setuptools BuildRequires: python%{python3_pkgversion}-setuptools
%endif
BuildRequires: python%{python3_pkgversion}-wheel
BuildRequires: python%{python3_pkgversion}-requests BuildRequires: python%{python3_pkgversion}-requests
BuildRequires: python%{python3_pkgversion}-requests-oauthlib BuildRequires: python%{python3_pkgversion}-requests-oauthlib
BuildRequires: python%{python3_pkgversion}-click >= 5.0 BuildRequires: python%{python3_pkgversion}-click >= 5.0
@ -93,6 +122,7 @@ BuildRequires: python%{python3_pkgversion}-babel
BuildRequires: python%{python3_pkgversion}-cryptography BuildRequires: python%{python3_pkgversion}-cryptography
BuildRequires: python%{python3_pkgversion}-certifi BuildRequires: python%{python3_pkgversion}-certifi
BuildRequires: python%{python3_pkgversion}-paho-mqtt BuildRequires: python%{python3_pkgversion}-paho-mqtt
BuildRequires: python%{python3_pkgversion}-tox
Requires: python%{python3_pkgversion}-requests Requires: python%{python3_pkgversion}-requests
Requires: python%{python3_pkgversion}-requests-oauthlib Requires: python%{python3_pkgversion}-requests-oauthlib
Requires: python%{python3_pkgversion}-markdown Requires: python%{python3_pkgversion}-markdown
@ -108,6 +138,12 @@ BuildRequires: python%{python3_pkgversion}-pytest-runner
BuildRequires: python%{python3_pkgversion}-pytest-cov BuildRequires: python%{python3_pkgversion}-pytest-cov
%endif %endif
%if 0%{?legacy_python_build} == 0
# Logic for non-RHEL ≤ 9 systems
%generate_buildrequires
%pyproject_buildrequires
%endif
%description -n python%{python3_pkgversion}-%{pypi_name} %{common_description} %description -n python%{python3_pkgversion}-%{pypi_name} %{common_description}
%prep %prep
@ -117,30 +153,47 @@ BuildRequires: python%{python3_pkgversion}-pytest-cov
# section of this RPM, but works completley fine under all other circumstances. # section of this RPM, but works completley fine under all other circumstances.
# As a workaround, just remove the file so it doesn't hold up the RPM # As a workaround, just remove the file so it doesn't hold up the RPM
# Preparation # Preparation
%{__rm} test/test_plugin_bulksms.py %{__rm} tests/test_plugin_bulksms.py
# 2023.08.27: rawhide does not install translationfiles for some reason # 2023.08.27: rawhide does not install translationfiles for some reason
# at this time; remove failing test until this is resolved # at this time; remove failing test until this is resolved
%{__rm} test/test_apprise_translations.py %{__rm} tests/test_apprise_translations.py
%build %build
%if %{legacy_python_build}
# backwards compatible
%py3_build %py3_build
%else
%pyproject_wheel
%endif
%install %install
%if %{legacy_python_build}
# backwards compatible
%py3_install %py3_install
%else
%pyproject_install
%endif
%{__install} -p -D -T -m 0644 packaging/man/%{pypi_name}.1 \ %{__install} -p -D -T -m 0644 packaging/man/%{pypi_name}.1 \
%{buildroot}%{_mandir}/man1/%{pypi_name}.1 %{buildroot}%{_mandir}/man1/%{pypi_name}.1
%if %{with tests} %if %{with tests}
%check %check
LANG=C.UTF-8 PYTHONPATH=%{buildroot}%{python3_sitelib} py.test-%{python3_version} %if %{legacy_python_build}
# backwards compatible
LANG=C.UTF-8 PYTHONPATH=%{buildroot}%{python3_sitelib}:%{_builddir}/%{name}-%{version} py.test-%{python3_version}
%else
%pytest
%endif
%endif %endif
%files -n python%{python3_pkgversion}-%{pypi_name} %files -n python%{python3_pkgversion}-%{pypi_name}
%license LICENSE %license LICENSE
%doc README.md %doc README.md
%{python3_sitelib}/%{pypi_name} %{python3_sitelib}/%{pypi_name}/
%lang(en) %{python3_sitelib}/%{pypi_name}/i18n/en/LC_MESSAGES/messages.mo
%exclude %{python3_sitelib}/%{pypi_name}/cli.* %exclude %{python3_sitelib}/%{pypi_name}/cli.*
%{python3_sitelib}/*.egg-info %{python3_sitelib}/*.egg-info
@ -148,6 +201,7 @@ LANG=C.UTF-8 PYTHONPATH=%{buildroot}%{python3_sitelib} py.test-%{python3_version
%{_bindir}/%{pypi_name} %{_bindir}/%{pypi_name}
%{_mandir}/man1/%{pypi_name}.1* %{_mandir}/man1/%{pypi_name}.1*
%{python3_sitelib}/%{pypi_name}/cli.* %{python3_sitelib}/%{pypi_name}/cli.*
%{python3_sitelib}/%{pypi_name}/__pycache__/cli*.pyc
%changelog %changelog
* Sun Mar 30 2025 Chris Caron <lead2gold@gmail.com> - 1.9.3 * Sun Mar 30 2025 Chris Caron <lead2gold@gmail.com> - 1.9.3

334
pyproject.toml Normal file
View File

@ -0,0 +1,334 @@
[build-system]
requires = [
"setuptools>=69",
"wheel",
"babel",
]
build-backend = "setuptools.build_meta"
[project]
name = "apprise"
description = "Push Notifications that work with just about every platform!"
readme = "README.md"
authors = [
{ name = "Chris Caron", email = "lead2gold@gmail.com" },
]
dynamic = ["version"]
# Not supported yet for all Distributions
license = { text = "BSD-2-Clause" }
requires-python = ">=3.8"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Intended Audience :: System Administrators",
"Operating System :: OS Independent",
"Natural Language :: English",
"Programming Language :: Python",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Libraries :: Application Frameworks",
]
dependencies = [
# Application dependencies
"requests",
"requests-oauthlib",
"click>=5.0",
"markdown",
"PyYAML",
# Root certificate authority bundle
"certifi",
]
# Identifies all of the supported plugins
keywords = [
"Africas Talking",
"Alerts",
"Apprise API",
"Automated Packet Reporting System",
"AWS",
"Bark",
"BlueSky",
"BulkSMS",
"BulkVS",
"Burst SMS",
"Chanify",
"Chat",
"CLI",
"Clickatell",
"ClickSend",
"D7Networks",
"Dapnet",
"DBus",
"DingTalk",
"Discord",
"Email",
"Emby",
"Enigma2",
"FCM",
"Feishu",
"Flock",
"Form",
"Free Mobile",
"Gnome",
"Google Chat",
"Gotify",
"Growl",
"Guilded",
"Home Assistant",
"httpSMS",
"IFTTT",
"Join",
"JSON",
"Kavenegar",
"KODI",
"Kumulos",
"LaMetric",
"Lark",
"Line",
"MacOSX",
"Mailgun",
"Mastodon",
"Matrix",
"Mattermost",
"MessageBird",
"Microsoft",
"Misskey",
"MQTT",
"MSG91",
"MSTeams",
"Nextcloud",
"NextcloudTalk",
"Notica",
"Notifiarr",
"Notifico",
"Ntfy",
"Office365",
"OneSignal",
"Opsgenie",
"PagerDuty",
"PagerTree",
"ParsePlatform",
"Plivo",
"PopcornNotify",
"Power Automate",
"Prowl",
"Push Notifications",
"PushBullet",
"PushDeer",
"Pushed",
"Pushjet",
"PushMe",
"Pushover",
"Pushplus",
"PushSafer",
"Pushy",
"QQ Push",
"Reddit",
"Resend",
"Revolt",
"Rocket.Chat",
"RSyslog",
"Ryver",
"SendGrid",
"ServerChan",
"SES",
"Seven",
"SFR",
"Signal",
"SimplePush",
"Sinch",
"Slack",
"SMPP",
"SMS Manager",
"SMSEagle",
"SMTP2Go",
"SNS",
"SparkPost",
"Spike",
"Splunk",
"SpugPush",
"Streamlabs",
"Stride",
"Synology Chat",
"Syslog",
"Techulus",
"Telegram",
"Threema Gateway",
"Twilio",
"Twist",
"Twitter",
"Vapid",
"VictorOps",
"Voipms",
"Vonage",
"Webex",
"Webpush",
"WeCom Bot",
"WhatsApp",
"Windows",
"Workflows",
"WxPusher",
"XBMC",
"XML",
"Zulip",
]
[project.optional-dependencies]
# All packages required to test/build against
dev = [
"coverage",
"mock",
"tox",
"pytest",
"pytest-cov",
"pytest-mock",
"ruff",
"babel",
"validate-pyproject",
]
# Defines all Python libraries for Apprise to work with
# all plugins
all-plugins = [
# Used in many applications requiring cryptography
# such as fcm://, splush:// and much more
"cryptography",
# provides growl:// support
"gntp",
# Provides mqtt:// support
# use any version other than 2.0.x due to:
# - https://github.com/eclipse/paho.mqtt.python/issues/814
"paho-mqtt != 2.0.*",
# Pretty Good Privacy (PGP) Provides mailto:// and deltachat:// support
"PGPy",
# Provides smpp:// support
"smpplib",
]
windows = [
"pywin32",
]
[project.urls]
Homepage = "https://github.com/caronc/apprise"
Source = "https://github.com/caronc/apprise"
Tracker = "https://github.com/caronc/apprise/issues"
Documentation = "https://github.com/caronc/apprise/wiki"
[project.scripts]
apprise = "apprise.cli:main"
[tool.setuptools]
include-package-data = true
[tool.setuptools.package-data]
apprise = [
"assets/NotifyXML-*.xsd",
"assets/themes/default/*.png",
"assets/themes/default/*.ico",
"i18n/*.py",
"i18n/*/LC_MESSAGES/*.mo",
"py.typed",
"*.pyi",
"*/*.pyi",
]
[tool.setuptools.packages.find]
where = [
".",
]
exclude = [
"tests*",
"tools*",
]
include = ["apprise*"]
[tool.setuptools.dynamic]
version = {attr = "apprise.__version__"}
[tool.ruff]
line-length = 79 # Respecting BSD-style 79-char limit
extend-select = ["I"] # Automatically sort imports with isort logic
target-version = "py38"
exclude = [
"tests/data",
"bin",
"build",
"dist",
".eggs",
".tox",
".local",
".venv",
"venv",
]
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"W", # pycodestyle warnings
"I", # isort
"UP", # pyupgrade
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"SIM", # flake8-simplify
"T20", # flake8-print (catches stray `print`)
"RUF", # Ruff-native rules
]
ignore = [
"E501", # line length
"ANN101", # missing type on `self`
"D100", # missing docstring in public module
"D104", # missing docstring in public package
"B008", # do not call `dict()` with keyword args
"E722", # bare except (Apprise uses it reasonably)
"E741", # Ambiguous variable name (e.g., l, O, I)
"W605", # Invalid escape sequence
]
[tool.ruff.isort]
known-first-party = ["apprise"]
force-sort-within-sections = true
combine-as-imports = true
[tool.ruff.flake8-builtins]
builtins-ignorelist = ["_"]
[tool.pytest.ini_options]
addopts = "-ra"
python_files = ["tests/test_*.py"]
norecursedirs = ["tests/helpers", "dist"]
filterwarnings = ["once::Warning"]
[tool.coverage.run]
branch = true
parallel = false
data_file = ".coverage"
source = ["apprise"]
relative_files = true
[tool.coverage.paths]
source = [
"apprise",
"/apprise/apprise",
".tox/*/lib/python*/site-packages/apprise",
".tox/pypy/site-packages/apprise"
]
[tool.coverage.report]
show_missing = true
skip_covered = true
skip_empty = true

View File

@ -1,3 +1,9 @@
#
# Note: This file is being kept for backwards compatibility with
# legacy systems that point here. All future changes should
# occur in pyproject.toml. Contents of this file can be found
# in project.dependencies
# Root certificate authority bundle # Root certificate authority bundle
certifi certifi

View File

@ -1,47 +0,0 @@
[bdist_wheel]
universal = 0
[metadata]
# ensure LICENSE is included in wheel metadata
license_files = LICENSE
[flake8]
# We exclude packages we don't maintain
exclude = .eggs,.tox,.local,dist,.venv,venv
ignore = E741,E722,W503,W504,W605
statistics = true
builtins = _
[aliases]
test=pytest
[tool:pytest]
addopts = -ra
python_files = test/test_*.py
norecursedirs=test/helpers, dist
filterwarnings =
once::Warning
[extract_messages]
output-file = apprise/i18n/apprise.pot
sort-output = true
copyright-holder = Chris Caron
msgid-bugs-address = lead2gold@gmail.com
charset = utf-8
no-location = true
add-comments = false
[compile_catalog]
domain = apprise
directory = apprise/i18n
statistics = true
[init_catalog]
domain = apprise
input-file = apprise/i18n/apprise.pot
output-dir = apprise/i18n
[update_catalog]
domain = apprise
input-file = apprise/i18n/apprise.pot
output-dir = apprise/i18n

View File

@ -27,53 +27,41 @@
# 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.
import re #
# 2025.07.10 NOTE:
# setup.py (Temporary shim for RHEL9 Package Building Only)
# Refer to tox for everything else; this will be removed once RHEL9 support
# is dropped.
#
import os import os
import platform import re
import sys from setuptools import setup, find_packages
from setuptools import find_packages, setup
cmdclass = {} def read_version() -> str:
try: with open(os.path.join("apprise", "__init__.py"), encoding="utf-8") as f:
from babel.messages import frontend as babel for line in f:
cmdclass = { m = re.match(r'^__version__\s*=\s*[\'"]([^\'"]+)', line)
'compile_catalog': babel.compile_catalog, if m:
'extract_messages': babel.extract_messages, return m.group(1)
'init_catalog': babel.init_catalog, raise RuntimeError("Version not found")
'update_catalog': babel.update_catalog,
}
except ImportError:
pass
install_options = os.environ.get("APPRISE_INSTALL", "").split(",")
install_requires = open('requirements.txt').readlines()
if platform.system().lower().startswith('win') \
and not hasattr(sys, "pypy_version_info"):
# Windows Notification Support
install_requires += open('win-requirements.txt').readlines()
libonly_flags = set(["lib-only", "libonly", "no-cli", "without-cli"])
if libonly_flags.intersection(install_options):
console_scripts = []
else:
# Load our CLI
console_scripts = ['apprise = apprise.cli:main']
# tox is not supported well in RHEL9 so this stub file is the only way to
# successfully build the RPM; packaging/redhat/python-apprise.spec has
# been updated accordingly to accomodate reference to this for older
# versions of the distribution only
setup( setup(
name='apprise', name="apprise",
version='1.9.3', version=read_version(),
description='Push Notifications that work with just about every platform!', packages=find_packages(
license='BSD 2-Clause', exclude=["tests*", "packaging*"]
long_description=open('README.md', encoding="utf-8").read(), ),
long_description_content_type='text/markdown', entry_points={
cmdclass=cmdclass, 'console_scripts': [
url='https://github.com/caronc/apprise', 'apprise = apprise.cli:main',
keywords=' '.join(re.split(r'\s+', open('KEYWORDS').read())), ],
author='Chris Caron', },
author_email='lead2gold@gmail.com',
packages=find_packages(),
package_data={ package_data={
'apprise': [ 'apprise': [
'assets/NotifyXML-*.xsd', 'assets/NotifyXML-*.xsd',
@ -86,29 +74,4 @@ setup(
'*/*.pyi' '*/*.pyi'
], ],
}, },
install_requires=install_requires,
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'Operating System :: OS Independent',
'Natural Language :: English',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'License :: OSI Approved :: BSD License',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Software Development :: Libraries :: Application Frameworks',
],
entry_points={'console_scripts': console_scripts},
python_requires='>=3.6',
setup_requires=['babel', ],
) )

View File

@ -28,7 +28,7 @@
# Base # Base
FROM rockylinux:9 FROM rockylinux:9
ENV container docker ENV container=docker
RUN \ RUN \
rm -f /lib/systemd/system/multi-user.target.wants/*;\ rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\ rm -f /etc/systemd/system/*.wants/*;\
@ -42,11 +42,11 @@ RUN \
dnf install -y rpm-build rpmlint python3-pip rubygem-ronn \ dnf install -y rpm-build rpmlint python3-pip rubygem-ronn \
dnf-plugins-core 'dnf-command(config-manager)' \ dnf-plugins-core 'dnf-command(config-manager)' \
'dnf-command(builddep)' sudo rsync rpmdevtools; \ 'dnf-command(builddep)' sudo rsync rpmdevtools; \
dnf config-manager --set-enabled crb; dnf config-manager --set-enabled crb
COPY packaging/redhat/python-apprise.spec /
# Place our build file into the path # Place our build file into the path
COPY bin/build-rpm.sh /usr/bin COPY bin/build-rpm.sh /usr/bin
COPY packaging/redhat/python-apprise.spec /
RUN rpmspec -q --buildrequires /python-apprise.spec | cut -f1 -d' ' | \ RUN rpmspec -q --buildrequires /python-apprise.spec | cut -f1 -d' ' | \
xargs dnf install -y && dnf clean all xargs dnf install -y && dnf clean all

View File

@ -28,7 +28,7 @@
# Base # Base
FROM fedora:37 FROM fedora:37
ENV container docker ENV container=docker
RUN \ RUN \
rm -f /usr/lib/systemd/system/multi-user.target.wants/*;\ rm -f /usr/lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\ rm -f /etc/systemd/system/*.wants/*;\

View File

@ -38,7 +38,7 @@
# #
# Base # Base
FROM fedora:39 FROM fedora:39
ENV container docker ENV container=docker
# https://bugzilla.redhat.com/show_bug.cgi?id=2216807 workaround # https://bugzilla.redhat.com/show_bug.cgi?id=2216807 workaround
RUN dnf download -y --destdir BZ2216807 --resolve dnf-data && \ RUN dnf download -y --destdir BZ2216807 --resolve dnf-data && \

View File

@ -38,8 +38,8 @@ VOLUME ["/apprise"]
WORKDIR /apprise WORKDIR /apprise
COPY requirements.txt / COPY requirements.txt /
COPY dev-requirements.txt / COPY dev-requirements.txt /
ENV PYTHONPATH /apprise ENV PYTHONPATH=/apprise
ENV PYTHONPYCACHEPREFIX /apprise/__pycache__/py310 ENV PYTHONPYCACHEPREFIX=/apprise/__pycache__/py310
RUN pip install --no-cache-dir -r /requirements.txt -r /dev-requirements.txt RUN pip install --no-cache-dir -r /requirements.txt -r /dev-requirements.txt

View File

@ -38,8 +38,8 @@ VOLUME ["/apprise"]
WORKDIR /apprise WORKDIR /apprise
COPY requirements.txt / COPY requirements.txt /
COPY dev-requirements.txt / COPY dev-requirements.txt /
ENV PYTHONPATH /apprise ENV PYTHONPATH=/apprise
ENV PYTHONPYCACHEPREFIX /apprise/__pycache__/py311 ENV PYTHONPYCACHEPREFIX=/apprise/__pycache__/py311
RUN pip install --no-cache-dir -r /requirements.txt -r /dev-requirements.txt RUN pip install --no-cache-dir -r /requirements.txt -r /dev-requirements.txt

View File

@ -38,8 +38,8 @@ VOLUME ["/apprise"]
WORKDIR /apprise WORKDIR /apprise
COPY requirements.txt / COPY requirements.txt /
COPY dev-requirements.txt / COPY dev-requirements.txt /
ENV PYTHONPATH /apprise ENV PYTHONPATH=/apprise
ENV PYTHONPYCACHEPREFIX /apprise/__pycache__/py312 ENV PYTHONPYCACHEPREFIX=/apprise/__pycache__/py312
RUN pip install --no-cache-dir -r /requirements.txt -r /dev-requirements.txt RUN pip install --no-cache-dir -r /requirements.txt -r /dev-requirements.txt

View File

@ -38,8 +38,8 @@ VOLUME ["/apprise"]
WORKDIR /apprise WORKDIR /apprise
COPY requirements.txt / COPY requirements.txt /
COPY dev-requirements.txt / COPY dev-requirements.txt /
ENV PYTHONPATH /apprise ENV PYTHONPATH=/apprise
ENV PYTHONPYCACHEPREFIX /apprise/__pycache__/py39 ENV PYTHONPYCACHEPREFIX=/apprise/__pycache__/py39
RUN pip install --no-cache-dir -r /requirements.txt -r /dev-requirements.txt RUN pip install --no-cache-dir -r /requirements.txt -r /dev-requirements.txt

View File

@ -38,7 +38,7 @@
# #
# Base # Base
FROM fedora:rawhide FROM fedora:rawhide
ENV container docker ENV container=docker
# https://bugzilla.redhat.com/show_bug.cgi?id=2216807 workaround # https://bugzilla.redhat.com/show_bug.cgi?id=2216807 workaround
RUN dnf download -y --destdir BZ2216807 --resolve dnf-data && \ RUN dnf download -y --destdir BZ2216807 --resolve dnf-data && \

Some files were not shown because too many files have changed in this diff Show More