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:
**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
<!-- This section is only applicable if you're adding a new service -->
* [ ] apprise/plugins/<!--new plugin name -->.py
* [ ] KEYWORDS
* [ ] pypackage.toml update `keywords` section to identify our new service
- add new service into this file (alphabetically).
* [ ] README.md
- 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 code change is tested and works locally.
* [ ] There is no commented out code in this PR.
* [ ] No lint errors (use `flake8`)
* [ ] 100% test coverage
* [ ] No lint errors (use `tox -e lint`)
* [ ] 100% test coverage (use `tox -e minimal`)
## Testing
<!-- 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.
#
# TODO: Currently, this supports RPM-based systems only.
# By adjusting a few details, it can be made work
# for other distribution types as well.
#
name: Test packaging
name: RPM Packaging
on:
# On which repository actions to trigger the build.
push:
branches: [ master ]
branches: [main, master, 'release/**']
pull_request:
branches: [ master ]
# Allow job to be triggered manually.
branches: [main, master]
workflow_dispatch:
# Cancel in-progress jobs when pushing to the same branch.
concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
tests:
build:
name: Build RPMs
runs-on: ubuntu-latest
runs-on: "ubuntu-latest"
strategy:
container:
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:
- name: Acquire sources
- name: Checkout source
uses: actions/checkout@v4
- name: Build package
run: |
docker compose run --user root --rm ${{ matrix.target }} build-rpm.sh
- name: Build RPMs
run: ./bin/build-rpm.sh
env:
APPRISE_DIR: ${{ github.workspace }}
- name: Verify package has been produced
- name: Show RPMs found for upload
run: |
ls -alF dist/rpm/noarch/*.noarch.rpm
echo "Listing dist/**/*.rpm:"
find dist -type f -name '*.rpm'
- name: Upload RPM Artifacts
uses: actions/upload-artifact@v4
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 which repository actions to trigger the build.
# Run tests on push to main, master, or any release/ branch
push:
branches: [ master ]
branches: [main, master, 'release/**']
# Always test on pull requests targeting main/master
pull_request:
branches: [ master ]
# Allow job to be triggered manually.
branches: [main, master]
# Allow manual triggering via GitHub UI
workflow_dispatch:
# Cancel in-progress jobs when pushing to the same branch.
concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
test:
name: Python ${{ matrix.python-version }} ${{ matrix.tox_env }} on ${{ matrix.os }}
runs-on: ubuntu-latest
tests:
runs-on: ${{ matrix.os }}
strategy:
# 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.
fail-fast: false # Let all jobs run, even if one fails
matrix:
os: ["ubuntu-latest"]
python-version: ["3.11"]
bare: [false]
include:
- python-version: "3.8"
tox_env: qa
setup_python: true
# Within the `bare` environment, `all-plugin-requirements.txt` will NOT be
# installed, to verify the application also works without those dependencies.
- os: "ubuntu-latest"
# Modern Python versions (can rely on default runner environment)
- python-version: "3.9"
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"
bare: true
tox_env: qa
# Let's save resources and only build a single slot on macOS- and Windows.
- os: "macos-latest"
python-version: "3.11"
- os: "windows-latest"
- os: macos-latest
python-version: "3.11"
tox_env: qa
# Test more available versions of CPython on Linux.
- os: "ubuntu-latest"
python-version: "3.8"
- os: "ubuntu-latest"
python-version: "3.9"
- os: "ubuntu-latest"
python-version: "3.10"
- os: "ubuntu-latest"
python-version: "3.11"
- os: "ubuntu-latest"
python-version: "3.12"
# Minimal test run on latest Python only
# this verifies Apprise still works when extra libraries are not available
- python-version: "3.12"
tox_env: minimal
setup_python: false
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:
- uses: actions/checkout@v4
- name: Acquire sources
uses: actions/checkout@v4
- name: Install prerequisites (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install libdbus-1-dev
- name: Setup Python
# Legacy Python versions 3.8 are no longer on GitHub-hosted runners
# 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 }}
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)
run: |
pip install --use-pep517 wheel
pip install --use-pep517 -r requirements.txt -r dev-requirements.txt
# Install tox for isolated environment and plugin test orchestration
- name: Install tox
run: python -m pip install tox
- name: Install project dependencies (All plugins)
if: matrix.bare != true
run: |
pip install --use-pep517 -r all-plugin-requirements.txt
# Run tox with the specified environment (qa, minimal, etc.)
- name: Run tox for ${{ matrix.tox_env }}
run: tox -e ${{ matrix.tox_env }}
- name: Install project dependencies (Windows)
if: runner.os == 'Windows'
- name: Verify .coverage file existence
if: always()
run: |
pip install --use-pep517 -r win-requirements.txt || true
echo "::group::Looking for .coverage file"
ls -alh .
echo "::endgroup::"
# Install package in editable mode,
# and run project-specific tasks.
- name: Setup project
run: |
python -m pip install --upgrade pip setuptools wheel
pip install --use-pep517 --editable=.
python setup.py compile_catalog
- name: Upload coverage report
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.os }}-${{ matrix.python-version }}-${{ matrix.tox_env }}
path: .coverage
include-hidden-files: true
# For saving resources, code style checking is
# only invoked within the `bare` environment.
- name: Check code style
if: matrix.bare == true
run: |
flake8 . --count --show-source --statistics
codecov:
name: Upload merged coverage to Codecov
runs-on: ubuntu-latest
needs: test # Waits for all matrix jobs to complete
if: always() # Even if a test fails, still attempt to upload what we have
- name: Run tests
run: |
coverage run -m pytest --junitxml=test-results.xml
steps:
- uses: actions/checkout@v4
- name: Process coverage data
- name: Download all coverage reports
uses: actions/download-artifact@v4
with:
path: coverage-artifacts
- name: Combine and generate coverage
run: |
coverage combine
coverage xml
pip install coverage
# 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
- name: Upload to Codecov
uses: codecov/codecov-action@v4
with:
files: ./coverage.xml
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload test results
uses: codecov/codecov-action@v4
with:
files: ./test-results.xml
fail_ci_if_error: false
type: test-results
file: coverage.xml
fail_ci_if_error: false # Avoid failing job if Codecov is down

6
.gitignore vendored
View File

@ -3,6 +3,9 @@ __pycache__/
*.py[cod]
*$py.class
# left-over-files from conflicts/merges
*.orig
# C extensions
*.so
@ -49,6 +52,7 @@ coverage.xml
# Translations
*.mo
*.pot
# Django stuff:
*.log
@ -69,4 +73,6 @@ target/
.project
.pydevproject
.settings
# Others
.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 KEYWORDS
include README.md
include pyproject.toml
include tox.ini
include requirements.txt
include win-requirements.txt
include dev-requirements.txt
recursive-include test *
include all-plugin-requirements.txt
recursive-include tests *
recursive-include packaging *
global-exclude *.pyc
global-exclude *.pyo
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://
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)
# 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
# Directory where Apprise Source Code can be found
APPRISE_DIR="/apprise"
# Set Apprise root directory
APPRISE_DIR="${APPRISE_DIR:-/apprise}"
PYTHON=python3
PIP=pip3
VENV_CMD="$PYTHON -m venv"
TOX="tox -c $APPRISE_DIR/tox.ini"
DIST_DIR="${DIST_DIR:-$PWD/dist}"
mkdir -p "$DIST_DIR"
mkenv(){
# Prepares RPM Environment
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
}
echo "==> Cleaning previous builds"
$TOX -e clean --notest
clean(){
# Tidy .pyc files
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(){
# Test spec file for any issues
echo "==> Linting RPM spec"
rpmlint "$APPRISE_DIR/packaging/redhat/python-apprise.spec"
[ $? -ne 0 ] && echo "RPMLint Failed!" && return 1
# Prepare RPM Package
# Detect our version
local VER=$(rpmspec -q --qf "%{version}\n" \
"$APPRISE_DIR/packaging/redhat/python-apprise.spec" 2>/dev/null | head -n1)
[ -z "$VER" ] && echo "Could not detect Apprise RPM Version" && return 1
echo "==> Running tests"
$TOX -e py312
if [ ! -f "$APPRISE_DIR/dist/apprise-$VER.tar.gz" ]; then
# Build Apprise
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
echo "==> Generating man pages"
ronn --roff --organization="Chris Caron <lead2gold@gmail.com>" \
"$APPRISE_DIR/packaging/man/apprise.md"
pushd $APPRISE_DIR
# Build Man Page
ronn --roff $APPRISE_DIR/packaging/man/apprise.md
$PYTHON setup.py extract_messages
$PYTHON setup.py sdist
echo "==> Extracting translations"
$TOX -e i18n || { echo "Translation extraction failed!" ; exit 1; }
# exit from our virtual environment
deactivate
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; }
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"
exit 1
fi
# Prepare our RPM Source and SPEC dependencies
find "$APPRISE_DIR/packaging/man/" -type f -name '*.1' \
-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" \;
echo "==> Copying tarball to SOURCES directory"
mkdir -p "$APPRISE_DIR/SOURCES"
cp "$TARBALL" "$APPRISE_DIR/SOURCES/"
# Build and Test our RPM Package
rpmbuild -ba "$APPRISE_DIR/dist/python-apprise.spec"
return $?
}
echo "==> Building RPM"
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"
# Prepare our environment
mkenv
echo "✅ RPM build completed successfully"
# Clean
clean
# Build
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
flake8
mock
pytest
pytest-cov
pytest-mock
ruff
babel
validate-pyproject

View File

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

View File

@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.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"
\fBapprise\fR \- Push Notifications that work with just about every platform!
.SH "SYNOPSIS"

View File

@ -32,28 +32,50 @@
%bcond_without tests
%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 common_description %{expand: \
Apprise is a Python package for simplifying access to all of the different
notification services that are out there. Apprise opens the door and makes
it easy to access:
# Handle rpmlint false positives
# - Prevent warnings:
# en_US ntfy -> notify
# en_US httpSMS -> HTTP
# rpmlint: ignore-spelling httpSMS ntfy
Africas Talking, Apprise API, APRS, AWS SES, AWS SNS, Bark, BlueSky, Burst SMS,
BulkSMS, BulkVS, Chanify, Clickatell, ClickSend, DAPNET, DingTalk, Discord, E-Mail, Emby,
FCM, Feishu, Flock, Free Mobile, Google Chat, Gotify, Growl, Guilded, Home
Assistant, httpSMS, IFTTT, Join, Kavenegar, KODI, Kumulos, LaMetric, Lark, Line,
MacOSX, Mailgun, Mastodon, Mattermost, Matrix, MessageBird, Microsoft
Windows, 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, XBMC}
# - RHEL9 does not recognize: BSD-2-Clause which is correct
# rpmlint: ignore invalid-license
%global common_description %{expand: \
Apprise is a Python package that simplifies access to many popular \
notification services. It supports sending alerts to platforms such as: \
\
`AfricasTalking`, `Apprise API`, `APRS`, `AWS SES`, `AWS SNS`, `Bark`, \
`BlueSky`, `Burst SMS`, `BulkSMS`, `BulkVS`, `Chanify`, `Clickatell`, \
`ClickSend`, `DAPNET`, `DingTalk`, `Discord`, `E-Mail`, `Emby`, `FCM`, \
`Feishu`, `Flock`, `Free Mobile`, `Google Chat`, `Gotify`, `Growl`, \
`Guilded`, `Home Assistant`, `httpSMS`, `IFTTT`, `Join`, `Kavenegar`, `KODI`, \
`Kumulos`, `LaMetric`, `Lark`, `Line`, `MacOSX`, `Mailgun`, `Mastodon`, \
`Mattermost`, `Matrix`, `MessageBird`, `Microsoft Windows`, \
`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}
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
BuildArch: noarch
Obsoletes: python%{python3_pkgversion}-%{pypi_name} < %{version}-%{release}
Provides: python%{python3_pkgversion}-%{pypi_name} = %{version}-%{release}
%description %{common_description}
%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}-%{pypi_name} = %{version}-%{release}
@ -83,7 +108,11 @@ Summary: A simple wrapper to many popular notification services used today
BuildRequires: gettext
BuildRequires: python%{python3_pkgversion}-devel
%if %{legacy_python_build}
# backwards compatible
BuildRequires: python%{python3_pkgversion}-setuptools
%endif
BuildRequires: python%{python3_pkgversion}-wheel
BuildRequires: python%{python3_pkgversion}-requests
BuildRequires: python%{python3_pkgversion}-requests-oauthlib
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}-certifi
BuildRequires: python%{python3_pkgversion}-paho-mqtt
BuildRequires: python%{python3_pkgversion}-tox
Requires: python%{python3_pkgversion}-requests
Requires: python%{python3_pkgversion}-requests-oauthlib
Requires: python%{python3_pkgversion}-markdown
@ -108,6 +138,12 @@ BuildRequires: python%{python3_pkgversion}-pytest-runner
BuildRequires: python%{python3_pkgversion}-pytest-cov
%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}
%prep
@ -117,30 +153,47 @@ BuildRequires: python%{python3_pkgversion}-pytest-cov
# 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
# Preparation
%{__rm} test/test_plugin_bulksms.py
%{__rm} tests/test_plugin_bulksms.py
# 2023.08.27: rawhide does not install translationfiles for some reason
# at this time; remove failing test until this is resolved
%{__rm} test/test_apprise_translations.py
%{__rm} tests/test_apprise_translations.py
%build
%if %{legacy_python_build}
# backwards compatible
%py3_build
%else
%pyproject_wheel
%endif
%install
%if %{legacy_python_build}
# backwards compatible
%py3_install
%else
%pyproject_install
%endif
%{__install} -p -D -T -m 0644 packaging/man/%{pypi_name}.1 \
%{buildroot}%{_mandir}/man1/%{pypi_name}.1
%if %{with tests}
%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
%files -n python%{python3_pkgversion}-%{pypi_name}
%license LICENSE
%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.*
%{python3_sitelib}/*.egg-info
@ -148,6 +201,7 @@ LANG=C.UTF-8 PYTHONPATH=%{buildroot}%{python3_sitelib} py.test-%{python3_version
%{_bindir}/%{pypi_name}
%{_mandir}/man1/%{pypi_name}.1*
%{python3_sitelib}/%{pypi_name}/cli.*
%{python3_sitelib}/%{pypi_name}/__pycache__/cli*.pyc
%changelog
* 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
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
# 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 platform
import sys
import re
from setuptools import setup, find_packages
from setuptools import find_packages, setup
cmdclass = {}
try:
from babel.messages import frontend as babel
cmdclass = {
'compile_catalog': babel.compile_catalog,
'extract_messages': babel.extract_messages,
'init_catalog': babel.init_catalog,
'update_catalog': babel.update_catalog,
}
except ImportError:
pass
def read_version() -> str:
with open(os.path.join("apprise", "__init__.py"), encoding="utf-8") as f:
for line in f:
m = re.match(r'^__version__\s*=\s*[\'"]([^\'"]+)', line)
if m:
return m.group(1)
raise RuntimeError("Version not found")
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(
name='apprise',
version='1.9.3',
description='Push Notifications that work with just about every platform!',
license='BSD 2-Clause',
long_description=open('README.md', encoding="utf-8").read(),
long_description_content_type='text/markdown',
cmdclass=cmdclass,
url='https://github.com/caronc/apprise',
keywords=' '.join(re.split(r'\s+', open('KEYWORDS').read())),
author='Chris Caron',
author_email='lead2gold@gmail.com',
packages=find_packages(),
name="apprise",
version=read_version(),
packages=find_packages(
exclude=["tests*", "packaging*"]
),
entry_points={
'console_scripts': [
'apprise = apprise.cli:main',
],
},
package_data={
'apprise': [
'assets/NotifyXML-*.xsd',
@ -86,29 +74,4 @@ setup(
'*/*.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
FROM rockylinux:9
ENV container docker
ENV container=docker
RUN \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
@ -42,11 +42,11 @@ RUN \
dnf install -y rpm-build rpmlint python3-pip rubygem-ronn \
dnf-plugins-core 'dnf-command(config-manager)' \
'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
COPY bin/build-rpm.sh /usr/bin
COPY packaging/redhat/python-apprise.spec /
RUN rpmspec -q --buildrequires /python-apprise.spec | cut -f1 -d' ' | \
xargs dnf install -y && dnf clean all

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -38,7 +38,7 @@
#
# Base
FROM fedora:rawhide
ENV container docker
ENV container=docker
# https://bugzilla.redhat.com/show_bug.cgi?id=2216807 workaround
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