PEP E501 (file length) fix applied

pull/1368/head
Chris Caron 2025-07-20 12:20:45 -04:00
parent 2d4ad01829
commit 8a18e6b6e4
51 changed files with 189 additions and 172 deletions

View File

@ -25,6 +25,7 @@
# 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 contextlib
import os import os
import re import re
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
@ -286,13 +287,10 @@ class AttachHTTP(AttachBase):
self.logger.trace("Attachment cleanup of %s", self._temp_file.name) self.logger.trace("Attachment cleanup of %s", self._temp_file.name)
self._temp_file.close() self._temp_file.close()
try: with contextlib.suppress(OSError):
# Ensure our file is removed (if it exists) # Ensure our file is removed (if it exists)
os.unlink(self._temp_file.name) os.unlink(self._temp_file.name)
except OSError:
pass
# Reset our temporary file to prevent from entering # Reset our temporary file to prevent from entering
# this block again # this block again
self._temp_file = None self._temp_file = None

View File

@ -25,6 +25,7 @@
# 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 contextlib
from io import StringIO from io import StringIO
import logging import logging
import os import os
@ -186,12 +187,8 @@ class LogCapture:
self.__buffer_ptr.close() self.__buffer_ptr.close()
self.__handler.close() self.__handler.close()
if self.__delete: if self.__delete:
try: with contextlib.suppress(OSError):
# Always remove file afterwards # Always remove file afterwards
os.unlink(self.__path) os.unlink(self.__path)
except OSError:
# It's okay if the file does not exist
pass
return exc_type is None return exc_type is None

View File

@ -23,6 +23,7 @@
# THE SOFTWARE. # THE SOFTWARE.
import base64 import base64
import binascii import binascii
import contextlib
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
import glob import glob
import gzip import gzip
@ -52,13 +53,9 @@ def _ntf_tidy(ntf):
"""Reusable NamedTemporaryFile cleanup.""" """Reusable NamedTemporaryFile cleanup."""
if ntf: if ntf:
# Cleanup # Cleanup
try: with contextlib.suppress(OSError):
ntf.close() ntf.close()
except OSError:
# Already closed
pass
try: try:
os.unlink(ntf.name) os.unlink(ntf.name)
logger.trace("Persistent temporary file removed: %s", ntf.name) logger.trace("Persistent temporary file removed: %s", ntf.name)

View File

@ -66,6 +66,7 @@
# http://www.aprs.org/doc/APRS101.PDF # http://www.aprs.org/doc/APRS101.PDF
# #
import contextlib
from itertools import chain from itertools import chain
import re import re
import socket import socket
@ -321,13 +322,8 @@ class NotifyAprs(NotifyBase):
def socket_close(self): def socket_close(self):
"""Closes the socket connection whereas present.""" """Closes the socket connection whereas present."""
if self.sock: if self.sock:
try: with contextlib.suppress(Exception):
self.sock.close() self.sock.close()
except Exception:
# No worries if socket exception thrown on close()
pass
self.sock = None self.sock = None
def socket_open(self): def socket_open(self):

View File

@ -187,10 +187,11 @@ class NotifyBase(URLBase):
"default": overflow_mode, "default": overflow_mode,
# look up default using the following parent class value at # look up default using the following parent class value at
# runtime. The variable name identified here (in this case # runtime. The variable name identified here (in this case
# overflow_mode) is checked and it's result is placed over-top of # overflow_mode) is checked and it's result is placed over-top
# the 'default'. This is done because once a parent class inherits # of the 'default'. This is done because once a parent class
# this one, the overflow_mode already set as a default 'could' be # inherits this one, the overflow_mode already set as a default
# potentially over-ridden and changed to a different value. # 'could' be potentially over-ridden and changed to a different
# value.
"_lookup_default": "overflow_mode", "_lookup_default": "overflow_mode",
}, },
"format": { "format": {

View File

@ -133,10 +133,11 @@ class NotifyD7Networks(NotifyBase):
"alias_of": "targets", "alias_of": "targets",
}, },
"source": { "source": {
# Originating address,In cases where the rewriting of the sender's # Originating address,In cases where the rewriting of the
# address is supported or permitted by the SMS-C. This is used to # sender's address is supported or permitted by the SMS-C.
# transmit the message, this number is transmitted as the # This is used to transmit the message, this number is
# originating address and is completely optional. # transmitted as the originating address and is completely
# optional.
"name": _("Originating Address"), "name": _("Originating Address"),
"type": "string", "type": "string",
"map_to": "source", "map_to": "source",

View File

@ -144,9 +144,9 @@ class NotifyGnome(NotifyBase):
"default": GnomeUrgency.NORMAL, "default": GnomeUrgency.NORMAL,
}, },
"priority": { "priority": {
# Apprise uses 'priority' everywhere; it's just a nice consistent # Apprise uses 'priority' everywhere; it's just a nice
# feel to be able to use it here as well. Just map the # consistent feel to be able to use it here as well. Just map
# value back to 'priority' # the value back to 'priority'
"alias_of": "urgency", "alias_of": "urgency",
}, },
"image": { "image": {

View File

@ -86,6 +86,7 @@
# - https://developer.lametric.com/icons # - https://developer.lametric.com/icons
import contextlib
from json import dumps from json import dumps
import re import re
@ -1103,13 +1104,9 @@ class NotifyLametric(NotifyBase):
) )
# Set cycles # Set cycles
try: with contextlib.suppress(TypeError, ValueError):
results["cycles"] = abs(int(results["qsd"].get("cycles"))) results["cycles"] = abs(int(results["qsd"].get("cycles")))
except (TypeError, ValueError):
# Not a valid integer; ignore entry
pass
return results return results
@staticmethod @staticmethod

View File

@ -96,7 +96,9 @@ class NotifyLark(NotifyBase):
"""Returns the URL built dynamically based on specified arguments.""" """Returns the URL built dynamically based on specified arguments."""
params = self.url_parameters(privacy=privacy, *args, **kwargs) params = self.url_parameters(privacy=privacy, *args, **kwargs)
return ( return (
f"{self.secure_protocol}://{self.pprint(self.token, privacy, mode=PrivacyMode.Secret)}/?{NotifyLark.urlencode(params)}" f"{self.secure_protocol}://"
f"{self.pprint(self.token, privacy, mode=PrivacyMode.Secret)}/"
f"?{NotifyLark.urlencode(params)}"
) )
def send(self, body, title="", notify_type=NotifyType.INFO, **kwargs): def send(self, body, title="", notify_type=NotifyType.INFO, **kwargs):

View File

@ -25,6 +25,7 @@
# 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 contextlib
from copy import deepcopy from copy import deepcopy
from datetime import datetime, timezone from datetime import datetime, timezone
from json import dumps, loads from json import dumps, loads
@ -828,13 +829,10 @@ class NotifyMastodon(NotifyBase):
# 'emojis': [], # 'emojis': [],
# 'fields': [] # 'fields': []
# } # }
try: with contextlib.suppress(TypeError, KeyError):
# Cache our response for future references # Cache our response for future references
self._whoami_cache = {response["username"]: response["id"]} self._whoami_cache = {response["username"]: response["id"]}
except (TypeError, KeyError):
pass
elif response and "authorized scopes" in response.get("error", ""): elif response and "authorized scopes" in response.get("error", ""):
self.logger.warning( self.logger.warning(
"Failed to lookup Mastodon Auth details; " "Failed to lookup Mastodon Auth details; "

View File

@ -108,8 +108,8 @@ class NotifyNextcloud(NotifyBase):
NotifyBase.template_args, NotifyBase.template_args,
**{ **{
# Nextcloud uses different API end points depending on the version # Nextcloud uses different API end points depending on the version
# being used however the (API) payload remains the same. Allow users # being used however the (API) payload remains the same. Allow
# to specify the version they are using: # users to specify the version they are using:
"version": { "version": {
"name": _("Version"), "name": _("Version"),
"type": "int", "type": "int",

View File

@ -454,7 +454,8 @@ class NotifyOneSignal(NotifyBase):
self.logger.debug( self.logger.debug(
"OneSignal POST URL:" "OneSignal POST URL:"
f" {self.notify_url} (cert_verify={self.verify_certificate!r})" f" {self.notify_url} "
f"(cert_verify={self.verify_certificate!r})"
) )
self.logger.debug(f"OneSignal Payload: {payload!s}") self.logger.debug(f"OneSignal Payload: {payload!s}")

View File

@ -179,8 +179,8 @@ class NotifyPagerDuty(NotifyBase):
"default": PagerDutyRegion.US, "default": PagerDutyRegion.US,
"map_to": "region_name", "map_to": "region_name",
}, },
# The severity is automatically determined, however you can optionally # The severity is automatically determined, however you can
# over-ride its value and force it to be what you want # optionally over-ride its value and force it to be what you want
"severity": { "severity": {
"name": _("Severity"), "name": _("Severity"),
"type": "choice:string", "type": "choice:string",
@ -276,8 +276,9 @@ class NotifyPagerDuty(NotifyBase):
if self.region_name not in PAGERDUTY_REGIONS: if self.region_name not in PAGERDUTY_REGIONS:
# allow the outer except to handle this common response # allow the outer except to handle this common response
raise raise IndexError()
except:
except (AttributeError, IndexError, TypeError):
# Invalid region specified # Invalid region specified
msg = f"The PagerDuty region specified ({region_name}) is invalid." msg = f"The PagerDuty region specified ({region_name}) is invalid."
self.logger.warning(msg) self.logger.warning(msg)

View File

@ -240,8 +240,8 @@ class NotifyPopcornNotify(NotifyBase):
except requests.RequestException as e: except requests.RequestException as e:
self.logger.warning( self.logger.warning(
"A Connection error occured sending" "A Connection error occured sending"
f" {len(self.targets[index:index + batch_size])} PopcornNotify" f" {len(self.targets[index:index + batch_size])} "
" notification(s)." "PopcornNotify notification(s)."
) )
self.logger.debug(f"Socket Exception: {e!s}") self.logger.debug(f"Socket Exception: {e!s}")

View File

@ -25,6 +25,7 @@
# 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 contextlib
from itertools import chain from itertools import chain
import re import re
@ -339,19 +340,15 @@ class NotifyPushover(NotifyBase):
# How often to resend notification, in seconds # How often to resend notification, in seconds
self.retry = self.template_args["retry"]["default"] self.retry = self.template_args["retry"]["default"]
try: with contextlib.suppress(ValueError, TypeError):
# Get our retry value
self.retry = int(retry) self.retry = int(retry)
except (ValueError, TypeError):
# Do nothing
pass
# How often to resend notification, in seconds # How often to resend notification, in seconds
self.expire = self.template_args["expire"]["default"] self.expire = self.template_args["expire"]["default"]
try: with contextlib.suppress(ValueError, TypeError):
# Acquire our expiry value
self.expire = int(expire) self.expire = int(expire)
except (ValueError, TypeError):
# Do nothing
pass
if self.retry < 30: if self.retry < 30:
msg = "Pushover retry must be at least 30 seconds." msg = "Pushover retry must be at least 30 seconds."

View File

@ -90,7 +90,9 @@ class NotifyPushplus(NotifyBase):
"""Returns the URL built dynamically based on specified arguments.""" """Returns the URL built dynamically based on specified arguments."""
params = self.url_parameters(privacy=privacy, *args, **kwargs) params = self.url_parameters(privacy=privacy, *args, **kwargs)
return ( return (
f"{self.secure_protocol}://{self.pprint(self.token, privacy, mode=PrivacyMode.Secret)}/?{self.urlencode(params)}" f"{self.secure_protocol}://"
f"{self.pprint(self.token, privacy, mode=PrivacyMode.Secret)}/"
f"?{self.urlencode(params)}"
) )
@property @property

View File

@ -94,7 +94,9 @@ class NotifyQQ(NotifyBase):
"""Returns the URL built dynamically based on specified arguments.""" """Returns the URL built dynamically based on specified arguments."""
params = self.url_parameters(privacy=privacy, *args, **kwargs) params = self.url_parameters(privacy=privacy, *args, **kwargs)
return ( return (
f"{self.secure_protocol}://{self.pprint(self.token, privacy, mode=PrivacyMode.Secret)}/?{self.urlencode(params)}" f"{self.secure_protocol}://"
f"{self.pprint(self.token, privacy, mode=PrivacyMode.Secret)}/"
f"?{self.urlencode(params)}"
) )
@property @property

View File

@ -692,7 +692,8 @@ class NotifySES(NotifyBase):
# Our Authorization header # Our Authorization header
headers["Authorization"] = ", ".join([ headers["Authorization"] = ", ".join([
( (
f"{self.aws_auth_algorithm} Credential={self.aws_access_key_id}/{scope}" f"{self.aws_auth_algorithm} "
f"Credential={self.aws_access_key_id}/{scope}"
), ),
"SignedHeaders={signed_headers}".format( "SignedHeaders={signed_headers}".format(
signed_headers=";".join(signed_headers.keys()), signed_headers=";".join(signed_headers.keys()),

View File

@ -99,10 +99,11 @@ class NotifySeven(NotifyBase):
"alias_of": "targets", "alias_of": "targets",
}, },
"source": { "source": {
# Originating address,In cases where the rewriting of the sender's # Originating address,In cases where the rewriting of the
# address is supported or permitted by the SMS-C. This is used to # sender's address is supported or permitted by the SMS-C.
# transmit the message, this number is transmitted as the # This is used to transmit the message, this number is
# originating address and is completely optional. # transmitted as the originating address and is completely
# optional.
"name": _("Originating Address"), "name": _("Originating Address"),
"type": "string", "type": "string",
"map_to": "source", "map_to": "source",

View File

@ -71,6 +71,7 @@
# - You will be able to select the Bot App you previously created # - You will be able to select the Bot App you previously created
# - Your bot will join your channel. # - Your bot will join your channel.
import contextlib
from json import dumps, loads from json import dumps, loads
import re import re
from time import time from time import time
@ -815,14 +816,13 @@ class NotifySlack(NotifyBase):
) )
# Attachment posts return a JSON string # Attachment posts return a JSON string
try: with contextlib.suppress(AttributeError, TypeError, ValueError):
response = loads(r.content) # Load our JSON object if we can
except (AttributeError, TypeError, ValueError):
# ValueError = r.content is Unparsable # ValueError = r.content is Unparsable
# TypeError = r.content is None # TypeError = r.content is None
# AttributeError = r is None # AttributeError = r is None
pass response = loads(r.content)
# We can get a 200 response, but still fail. A failure message # We can get a 200 response, but still fail. A failure message
# might look like this (missing bot permissions): # might look like this (missing bot permissions):
@ -980,14 +980,12 @@ class NotifySlack(NotifyBase):
) )
# Posts return a JSON string # Posts return a JSON string
try: with contextlib.suppress(AttributeError, TypeError, ValueError):
response = loads(r.content) # Load our JSON object if we can
except (AttributeError, TypeError, ValueError):
# ValueError = r.content is Unparsable # ValueError = r.content is Unparsable
# TypeError = r.content is None # TypeError = r.content is None
# AttributeError = r is None # AttributeError = r is None
pass response = loads(r.content)
# Another response type is: # Another response type is:
# { # {

View File

@ -419,7 +419,8 @@ class NotifySNS(NotifyBase):
("content-type", headers["Content-Type"]), ("content-type", headers["Content-Type"]),
( (
"host", "host",
f"{self.aws_service_name}.{self.aws_region_name}.amazonaws.com", f"{self.aws_service_name}"
f".{self.aws_region_name}.amazonaws.com",
), ),
("x-amz-date", headers["X-Amz-Date"]), ("x-amz-date", headers["X-Amz-Date"]),
]) ])
@ -455,7 +456,8 @@ class NotifySNS(NotifyBase):
# Our Authorization header # Our Authorization header
headers["Authorization"] = ", ".join([ headers["Authorization"] = ", ".join([
( (
f"{self.aws_auth_algorithm} Credential={self.aws_access_key_id}/{scope}" f"{self.aws_auth_algorithm} "
f"Credential={self.aws_access_key_id}/{scope}"
), ),
"SignedHeaders={signed_headers}".format( "SignedHeaders={signed_headers}".format(
signed_headers=";".join(signed_headers.keys()), signed_headers=";".join(signed_headers.keys()),

View File

@ -53,6 +53,7 @@
# #
# API Documentation: https://developers.sparkpost.com/api/ # API Documentation: https://developers.sparkpost.com/api/
# Specifically: https://developers.sparkpost.com/api/transmissions/ # Specifically: https://developers.sparkpost.com/api/transmissions/
import contextlib
from email.utils import formataddr from email.utils import formataddr
from json import dumps, loads from json import dumps, loads
@ -273,8 +274,9 @@ class NotifySparkPost(NotifyBase):
if self.region_name not in SPARKPOST_REGIONS: if self.region_name not in SPARKPOST_REGIONS:
# allow the outer except to handle this common response # allow the outer except to handle this common response
raise raise IndexError()
except:
except (AttributeError, IndexError, TypeError):
# Invalid region specified # Invalid region specified
msg = f"The SparkPost region specified ({region_name}) is invalid." msg = f"The SparkPost region specified ({region_name}) is invalid."
self.logger.warning(msg) self.logger.warning(msg)
@ -448,18 +450,13 @@ class NotifySparkPost(NotifyBase):
# ] # ]
# } # }
# #
try: with contextlib.suppress(
# Update our status response if we can AttributeError, TypeError, ValueError):
json_response = loads(r.content) # Load our JSON Object if we can
except (AttributeError, TypeError, ValueError):
# ValueError = r.content is Unparsable # ValueError = r.content is Unparsable
# TypeError = r.content is None # TypeError = r.content is None
# AttributeError = r is None # AttributeError = r is None
json_response = loads(r.content)
# We could not parse JSON response.
# We will just use the status we already have.
pass
status_code = r.status_code status_code = r.status_code

View File

@ -101,7 +101,9 @@ class NotifySpike(NotifyBase):
"""Returns the URL built dynamically based on specified arguments.""" """Returns the URL built dynamically based on specified arguments."""
params = self.url_parameters(privacy=privacy, *args, **kwargs) params = self.url_parameters(privacy=privacy, *args, **kwargs)
return ( return (
f"{self.secure_protocol}://{self.pprint(self.token, privacy, mode=PrivacyMode.Secret)}/?{self.urlencode(params)}" f"{self.secure_protocol}://"
f"{self.pprint(self.token, privacy, mode=PrivacyMode.Secret)}/"
f"?{self.urlencode(params)}"
) )
def send(self, body, title="", notify_type=NotifyType.INFO, **kwargs): def send(self, body, title="", notify_type=NotifyType.INFO, **kwargs):

View File

@ -92,7 +92,9 @@ class NotifySpugpush(NotifyBase):
"""Returns the URL built dynamically based on specified arguments.""" """Returns the URL built dynamically based on specified arguments."""
params = self.url_parameters(privacy=privacy, *args, **kwargs) params = self.url_parameters(privacy=privacy, *args, **kwargs)
return ( return (
f"{self.secure_protocol}://{self.pprint(self.token, privacy, mode=PrivacyMode.Secret)}/?{self.urlencode(params)}" f"{self.secure_protocol}://"
f"{self.pprint(self.token, privacy, mode=PrivacyMode.Secret)}/"
f"?{self.urlencode(params)}"
) )
@property @property

View File

@ -25,6 +25,7 @@
# 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 contextlib
from itertools import chain from itertools import chain
from json import dumps from json import dumps
import os import os
@ -172,7 +173,8 @@ class NotifyVapid(NotifyBase):
"map_to": "mode", "map_to": "mode",
}, },
# Default Time To Live (defined in seconds) # Default Time To Live (defined in seconds)
# 0 (Zero) - message will be delivered only if the device is reacheable # 0 (Zero) - message will be delivered only if the device is
# reacheable
"ttl": { "ttl": {
"name": _("ttl"), "name": _("ttl"),
"type": "int", "type": "int",
@ -241,13 +243,10 @@ class NotifyVapid(NotifyBase):
# Set our Time to Live Flag # Set our Time to Live Flag
self.ttl = self.template_args["ttl"]["default"] self.ttl = self.template_args["ttl"]["default"]
if ttl is not None: if ttl is not None:
try: with contextlib.suppress(ValueError, TypeError):
# Store our TTL (Time To live) if it is a valid integer
self.ttl = int(ttl) self.ttl = int(ttl)
except (ValueError, TypeError):
# Do nothing
pass
if ( if (
self.ttl < self.template_args["ttl"]["min"] self.ttl < self.template_args["ttl"]["min"]
or self.ttl > self.template_args["ttl"]["max"] or self.ttl > self.template_args["ttl"]["max"]
@ -280,8 +279,9 @@ class NotifyVapid(NotifyBase):
if self.mode not in VAPID_PUSH_MODES: if self.mode not in VAPID_PUSH_MODES:
# allow the outer except to handle this common response # allow the outer except to handle this common response
raise raise IndexError()
except:
except (AttributeError, IndexError, TypeError):
# Invalid region specified # Invalid region specified
msg = f"The Vapid mode specified ({mode}) is invalid." msg = f"The Vapid mode specified ({mode}) is invalid."
self.logger.warning(msg) self.logger.warning(msg)

View File

@ -33,6 +33,7 @@
# Read more about VoIP.ms API here: # Read more about VoIP.ms API here:
# - https://voip.ms/m/apidocs.php # - https://voip.ms/m/apidocs.php
import contextlib
from json import loads from json import loads
import requests import requests
@ -250,14 +251,13 @@ class NotifyVoipms(NotifyBase):
timeout=self.request_timeout, timeout=self.request_timeout,
) )
try: with contextlib.suppress(
response = loads(r.content) AttributeError, TypeError, ValueError):
# Load our JSON object if valid
except (AttributeError, TypeError, ValueError):
# ValueError = r.content is Unparsable # ValueError = r.content is Unparsable
# TypeError = r.content is None # TypeError = r.content is None
# AttributeError = r is None # AttributeError = r is None
pass response = loads(r.content)
if r.status_code != requests.codes.ok: if r.status_code != requests.codes.ok:
# We had a problem # We had a problem

View File

@ -30,6 +30,8 @@
# Get your (api) key and secret here: # Get your (api) key and secret here:
# - https://dashboard.nexmo.com/getting-started-guide # - https://dashboard.nexmo.com/getting-started-guide
# #
import contextlib
import requests import requests
from ..common import NotifyType from ..common import NotifyType
@ -126,10 +128,10 @@ class NotifyVonage(NotifyBase):
"alias_of": "secret", "alias_of": "secret",
}, },
# Default Time To Live # Default Time To Live
# By default Vonage attempt delivery for 72 hours, however the maximum # By default Vonage attempt delivery for 72 hours, however the
# effective value depends on the operator and is typically 24 - 48 # maximum effective value depends on the operator and is typically
# hours. We recommend this value should be kept at its default or at # 24 - 48 hours. We recommend this value should be kept at its
# least 30 minutes. # default or at least 30 minutes.
"ttl": { "ttl": {
"name": _("ttl"), "name": _("ttl"),
"type": "int", "type": "int",
@ -166,13 +168,10 @@ class NotifyVonage(NotifyBase):
# Set our Time to Live Flag # Set our Time to Live Flag
self.ttl = self.template_args["ttl"]["default"] self.ttl = self.template_args["ttl"]["default"]
try: with contextlib.suppress(ValueError, TypeError):
# update our ttl if we're dealing with an integer
self.ttl = int(ttl) self.ttl = int(ttl)
except (ValueError, TypeError):
# Do nothing
pass
if ( if (
self.ttl < self.template_args["ttl"]["min"] self.ttl < self.template_args["ttl"]["min"]
or self.ttl > self.template_args["ttl"]["max"] or self.ttl > self.template_args["ttl"]["max"]

View File

@ -93,7 +93,8 @@ class NotifyWeComBot(NotifyBase):
template_tokens = dict( template_tokens = dict(
NotifyBase.template_tokens, NotifyBase.template_tokens,
**{ **{
# The Bot Key can be found at the end of the webhook provided (?key=) # The Bot Key can be found at the end of the webhook provided
# (?key=)
"key": { "key": {
"name": _("Bot Webhook Key"), "name": _("Bot Webhook Key"),
"type": "string", "type": "string",

View File

@ -25,6 +25,7 @@
# 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 contextlib
from time import sleep from time import sleep
from ..common import NotifyImageSize, NotifyType from ..common import NotifyImageSize, NotifyType
@ -276,12 +277,9 @@ class NotifyWindows(NotifyBase):
) )
# Set duration # Set duration
try: with contextlib.suppress(TypeError, ValueError):
# Update our duration if we're dealing with an integer
results["duration"] = int(results["qsd"].get("duration")) results["duration"] = int(results["qsd"].get("duration"))
except (TypeError, ValueError):
# Not a valid integer; ignore entry
pass
# return results # return results
return results return results

View File

@ -467,13 +467,13 @@ def parse_qsd(qs, simple=False, plus_to_space=False, sanitize=True):
# Our return result set: # Our return result set:
result = ( result = (
{ {
# The arguments passed in (the parsed query). This is in a dictionary # The arguments passed in (the parsed query). This is in a
# of {'key': 'val', etc }. Keys are all made lowercase before storing # dictionary of {'key': 'val', etc }. Keys are all made lowercase
# to simplify access to them. # before storing to simplify access to them.
"qsd": {}, "qsd": {},
# Detected Entries that start with + or - are additionally stored in # Detected Entries that start with + or - are additionally stored
# these values (un-touched). The :,+,- however are stripped from their # in these values (un-touched). The :,+,- however are stripped
# name before they are stored here. # from their name before they are stored here.
"qsd+": {}, "qsd+": {},
"qsd-": {}, "qsd-": {},
"qsd:": {}, "qsd:": {},
@ -624,14 +624,14 @@ def parse_url(
"schema": None, "schema": None,
# The schema # The schema
"url": None, "url": None,
# The arguments passed in (the parsed query). This is in a dictionary # The arguments passed in (the parsed query). This is in a
# of {'key': 'val', etc }. Keys are all made lowercase before storing # dictionary of {'key': 'val', etc }. Keys are all made lowercase
# to simplify access to them. # before storing to simplify access to them.
# qsd = Query String Dictionary # qsd = Query String Dictionary
"qsd": {}, "qsd": {},
# Detected Entries that start with +, - or : are additionally stored in # Detected Entries that start with +, - or : are additionally
# these values (un-touched). The +, -, and : however are stripped # stored in these values (un-touched). The +, -, and : however
# from their name before they are stored here. # are stripped from their name before they are stored here.
"qsd+": {}, "qsd+": {},
"qsd-": {}, "qsd-": {},
"qsd:": {}, "qsd:": {},

View File

@ -518,8 +518,8 @@ class ApprisePEMController:
if ( if (
self.load_public_key(path) self.load_public_key(path)
or or
# Try to see if we can load a private key (which we can generate a # Try to see if we can load a private key (which we ca
# public from) # generate a public from)
self.private_key(*names, autogen=autogen) self.private_key(*names, autogen=autogen)
) )
else None else None

View File

@ -323,11 +323,6 @@ ignore = [
# The following needs to be supported at some point and is of great value # The following needs to be supported at some point and is of great value
"RUF012", # typing.ClassVar implimentation "RUF012", # typing.ClassVar implimentation
"E501", # Enforcing wordrap at 79 characters per BSD should be enforced
# it broke when ruff-autofixed over 600+ entries to accomodate
# other PEP styles.
"SIM105", # leverage contextlib.supress() so signifigantly simply the
# readability of the code
"UP032", # This is a massive undertaking and requires a massive rewrite "UP032", # This is a massive undertaking and requires a massive rewrite
# of test cases; this will take a while to fix, so turning off # of test cases; this will take a while to fix, so turning off
# for now # for now
@ -340,6 +335,8 @@ inline-quotes = "double"
known-first-party = ["apprise"] known-first-party = ["apprise"]
force-sort-within-sections = true force-sort-within-sections = true
combine-as-imports = true combine-as-imports = true
order-by-type = true
section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"]
[tool.ruff.lint.flake8-builtins] [tool.ruff.lint.flake8-builtins]
builtins-ignorelist = ["_"] builtins-ignorelist = ["_"]

View File

@ -90,7 +90,8 @@ apprise_url_tests = (
"a" * 5, "b" * 10, "3" * 11 "a" * 5, "b" * 10, "3" * 11
), ),
{ {
# included phone, short number (123) and garbage string (abcd) dropped # included phone, short number (123) and garbage string (abcd)
# dropped
"instance": NotifyBulkVS, "instance": NotifyBulkVS,
"privacy_url": "bulkvs://a...a:****@9876543210/33333333333", "privacy_url": "bulkvs://a...a:****@9876543210/33333333333",
}, },

View File

@ -136,7 +136,8 @@ apprise_url_tests = (
( (
"d7sms://token@{}?batch=yes&source=apprise".format("3" * 14), "d7sms://token@{}?batch=yes&source=apprise".format("3" * 14),
{ {
# valid number, utilizing the optional source= variable (same as from) # valid number, utilizing the optional source= variable (same as
# from)
"instance": NotifyD7Networks, "instance": NotifyD7Networks,
}, },
), ),

View File

@ -900,7 +900,8 @@ def test_plugin_email_smtplib_internationalization(mock_smtp):
# Further test encoding through the message content as well # Further test encoding through the message content as well
assert ( assert (
obj.notify( obj.notify(
# Google Translated to Arabic: "Let's make the world a better place." # Google Translated to Arabic:
# "Let's make the world a better place."
title="دعونا نجعل العالم مكانا أفضل.", title="دعونا نجعل العالم مكانا أفضل.",
# Google Translated to Hungarian: "One line of code at a time.' # Google Translated to Hungarian: "One line of code at a time.'
body="Egy sor kódot egyszerre.", body="Egy sor kódot egyszerre.",

View File

@ -59,7 +59,8 @@ apprise_url_tests = (
"enigma2://localhost", "enigma2://localhost",
{ {
"instance": NotifyEnigma2, "instance": NotifyEnigma2,
# This will fail because we're also expecting a server acknowledgement # This will fail because we're also expecting a server
# acknowledgement
"notify_response": False, "notify_response": False,
}, },
), ),

View File

@ -81,7 +81,8 @@ apprise_url_tests = (
( (
"httpsms://{}@9876543210/{}/abcd/".format("b" * 10, "3" * 11), "httpsms://{}@9876543210/{}/abcd/".format("b" * 10, "3" * 11),
{ {
# included phone, short number (123) and garbage string (abcd) dropped # included phone, short number (123) and garbage string (abcd)
# dropped
"instance": NotifyHttpSMS, "instance": NotifyHttpSMS,
"privacy_url": "httpsms://b...b@9876543210/33333333333", "privacy_url": "httpsms://b...b@9876543210/33333333333",
}, },

View File

@ -144,8 +144,8 @@ apprise_url_tests = (
"mastodon://access_token@hostname/?key=My%20Idempotency%20Key", "mastodon://access_token@hostname/?key=My%20Idempotency%20Key",
{ {
# Prevent duplicate submissions of the same status. Idempotency # Prevent duplicate submissions of the same status. Idempotency
# keys are stored for up to 1 hour, and can be any arbitrary string. # keys are stored for up to 1 hour, and can be any arbitrary
# Consider using a hash or UUID generated client-side. # string. Consider using a hash or UUID generated client-side.
"instance": NotifyMastodon, "instance": NotifyMastodon,
}, },
), ),

View File

@ -68,7 +68,8 @@ apprise_url_tests = (
"psafer://{}".format("a" * 20), "psafer://{}".format("a" * 20),
{ {
"instance": NotifyPushSafer, "instance": NotifyPushSafer,
# This will fail because we're also expecting a server acknowledgement # This will fail because we're also expecting a server
# acknowledgement
"notify_response": False, "notify_response": False,
}, },
), ),

View File

@ -95,7 +95,8 @@ apprise_url_tests = (
{ {
# Invalid topic specified # Invalid topic specified
"instance": NotifyPushy, "instance": NotifyPushy,
# Expected notify() response False because there is no one to notify # Expected notify() response False because there is no one to
# notify
"notify_response": False, "notify_response": False,
"requests_response_text": GOOD_RESPONSE, "requests_response_text": GOOD_RESPONSE,
}, },

View File

@ -108,7 +108,8 @@ apprise_url_tests = (
( (
"seven://{}/15551232000?source=apprise".format("3" * 14), "seven://{}/15551232000?source=apprise".format("3" * 14),
{ {
# valid number, utilizing the optional source= variable (same as from) # valid number, utilizing the optional source= variable (same as
# from)
"instance": NotifySeven, "instance": NotifySeven,
}, },
), ),
@ -122,14 +123,16 @@ apprise_url_tests = (
( (
"seven://{}/15551232000?source=apprise&flash=true".format("3" * 14), "seven://{}/15551232000?source=apprise&flash=true".format("3" * 14),
{ {
# valid number, utilizing the optional source= variable (same as from) # valid number, utilizing the optional source= variable (same as
# from)
"instance": NotifySeven, "instance": NotifySeven,
}, },
), ),
( (
"seven://{}/15551232000?source=AR&flash=1&label=123".format("3" * 14), "seven://{}/15551232000?source=AR&flash=1&label=123".format("3" * 14),
{ {
# valid number, utilizing the optional source= variable (same as from) # valid number, utilizing the optional source= variable (same as
# from)
"instance": NotifySeven, "instance": NotifySeven,
}, },
), ),

View File

@ -157,21 +157,24 @@ apprise_url_tests = (
"1" * 11, "2" * 11, "3" * 11 "1" * 11, "2" * 11, "3" * 11
), ),
{ {
# If we have from= specified, then all elements take on the to= value # If we have from= specified, then all elements take on the to=
# value
"instance": NotifySignalAPI, "instance": NotifySignalAPI,
}, },
), ),
( (
"signals://user@localhost/{}/{}".format("1" * 11, "3" * 11), "signals://user@localhost/{}/{}".format("1" * 11, "3" * 11),
{ {
# use get args to acomplish the same thing (use source instead of from) # use get args to acomplish the same thing (use source instead of
# from)
"instance": NotifySignalAPI, "instance": NotifySignalAPI,
}, },
), ),
( (
"signals://user:password@localhost/{}/{}".format("1" * 11, "3" * 11), "signals://user:password@localhost/{}/{}".format("1" * 11, "3" * 11),
{ {
# use get args to acomplish the same thing (use source instead of from) # use get args to acomplish the same thing (use source instead of
# from)
"instance": NotifySignalAPI, "instance": NotifySignalAPI,
}, },
), ),

View File

@ -147,7 +147,8 @@ apprise_url_tests = (
"a" * 32, "b" * 32, "5" * 11 "a" * 32, "b" * 32, "5" * 11
), ),
{ {
# use get args to acomplish the same thing (use source instead of from) # use get args to acomplish the same thing (use source instead of
# from)
"instance": NotifySinch, "instance": NotifySinch,
}, },
), ),

View File

@ -77,7 +77,8 @@ apprise_url_tests = (
"slack://T1JJ3T3L2/A1BRTD4JD/TIiajkdnlazkcOXrIdevi7FQ/#hmm/#-invalid-", "slack://T1JJ3T3L2/A1BRTD4JD/TIiajkdnlazkcOXrIdevi7FQ/#hmm/#-invalid-",
{ {
# No username specified; this is still okay as we sub in # No username specified; this is still okay as we sub in
# default; The one invalid channel is skipped when sending a message # default; The one invalid channel is skipped when sending a
# message
"instance": NotifySlack, "instance": NotifySlack,
# There is an invalid channel that we will fail to deliver to # There is an invalid channel that we will fail to deliver to
# as a result the response type will be false # as a result the response type will be false
@ -92,7 +93,8 @@ apprise_url_tests = (
"slack://T1JJ3T3L2/A1BRTD4JD/TIiajkdnlazkcOXrIdevi7FQ/#channel", "slack://T1JJ3T3L2/A1BRTD4JD/TIiajkdnlazkcOXrIdevi7FQ/#channel",
{ {
# No username specified; this is still okay as we sub in # No username specified; this is still okay as we sub in
# default; The one invalid channel is skipped when sending a message # default; The one invalid channel is skipped when sending a
# message
"instance": NotifySlack, "instance": NotifySlack,
# don't include an image by default # don't include an image by default
"include_image": False, "include_image": False,
@ -121,7 +123,8 @@ apprise_url_tests = (
}, },
), ),
( (
"slack://username@T1JJ3T3L2/A1BRTD4JD/TIiajkdnlazkcOXrIdevi7FQ/#nuxref", ("slack://username@T1JJ3T3L2/A1BRTD4JD/"
"TIiajkdnlazkcOXrIdevi7FQ/#nuxref"),
{ {
"instance": NotifySlack, "instance": NotifySlack,
"requests_response_text": "ok", "requests_response_text": "ok",
@ -147,7 +150,8 @@ apprise_url_tests = (
), ),
# Specify Token and channels on argument string (no username) # Specify Token and channels on argument string (no username)
( (
"slack://?token=T1JJ3T3L2/A1BRTD4JD/TIiajkdnlazkcOXrIdevi7FQ/&to=#chan", ("slack://?token=T1JJ3T3L2/A1BRTD4JD"
"/TIiajkdnlazkcOXrIdevi7FQ/&to=#chan"),
{ {
"instance": NotifySlack, "instance": NotifySlack,
"requests_response_text": "ok", "requests_response_text": "ok",
@ -155,7 +159,8 @@ apprise_url_tests = (
), ),
# Test webhook that doesn't have a proper response # Test webhook that doesn't have a proper response
( (
"slack://username@T1JJ3T3L2/A1BRTD4JD/TIiajkdnlazkcOXrIdevi7FQ/#nuxref", ("slack://username@T1JJ3T3L2/A1BRTD4JD/"
"TIiajkdnlazkcOXrIdevi7FQ/#nuxref"),
{ {
"instance": NotifySlack, "instance": NotifySlack,
"requests_response_text": "fail", "requests_response_text": "fail",
@ -244,8 +249,8 @@ apprise_url_tests = (
"ok": True, "ok": True,
"message": "", "message": "",
}, },
# we'll fail to send attachments because we had no 'file' response in # we'll fail to send attachments because we had no 'file' response
# our object # in our object
"response": False, "response": False,
}, },
), ),

View File

@ -270,7 +270,8 @@ apprise_url_tests = (
( (
"smseagle://token@localhost:8088/{}/{}/".format("2" * 11, "3" * 11), "smseagle://token@localhost:8088/{}/{}/".format("2" * 11, "3" * 11),
{ {
# If we have from= specified, then all elements take on the to= value # If we have from= specified, then all elements take on the
# to= value
"instance": NotifySMSEagle, "instance": NotifySMSEagle,
# Our response expected server response # Our response expected server response
"requests_response_text": SMSEAGLE_GOOD_RESPONSE, "requests_response_text": SMSEAGLE_GOOD_RESPONSE,
@ -279,7 +280,8 @@ apprise_url_tests = (
( (
"smseagles://token@localhost/{}".format("3" * 11), "smseagles://token@localhost/{}".format("3" * 11),
{ {
# use get args to acomplish the same thing (use source instead of from) # use get args to acomplish the same thing (use source instead of
# from)
"instance": NotifySMSEagle, "instance": NotifySMSEagle,
# Our response expected server response # Our response expected server response
"requests_response_text": SMSEAGLE_GOOD_RESPONSE, "requests_response_text": SMSEAGLE_GOOD_RESPONSE,

View File

@ -165,7 +165,8 @@ apprise_url_tests = (
"a" * 32, "b" * 32, "5" * 11 "a" * 32, "b" * 32, "5" * 11
), ),
{ {
# use get args to acomplish the same thing (use source instead of from) # use get args to acomplish the same thing (use source instead of
# from)
"instance": NotifyTwilio, "instance": NotifyTwilio,
}, },
), ),
@ -258,7 +259,8 @@ def test_plugin_twilio_auth(mock_post):
assert ( assert (
first_call[0][0] first_call[0][0]
== second_call[0][0] == second_call[0][0]
== f"https://api.twilio.com/2010-04-01/Accounts/{account_sid}/Messages.json" == ("https://api.twilio.com/2010-04-01/Accounts"
f"/{account_sid}/Messages.json")
) )
assert ( assert (
first_call[1]["data"]["Body"] first_call[1]["data"]["Body"]

View File

@ -80,8 +80,8 @@ apprise_url_tests = (
( (
"vapid://user@example.com", "vapid://user@example.com",
{ {
# bare bone requirements met, but we don't have our subscription file # bare bone requirements met, but we don't have our subscription
# or our private key (pem) # file or our private key (pem)
"instance": NotifyVapid, "instance": NotifyVapid,
# We'll fail to respond because we would not have found any # We'll fail to respond because we would not have found any
# configuration to load # configuration to load

View File

@ -116,7 +116,8 @@ apprise_url_tests = (
"a" * 8, "b" * 16, "5" * 11 "a" * 8, "b" * 16, "5" * 11
), ),
{ {
# use get args to acomplish the same thing (use source instead of from) # use get args to acomplish the same thing (use source instead
# of from)
"instance": NotifyVonage, "instance": NotifyVonage,
}, },
), ),
@ -223,7 +224,8 @@ apprise_url_tests = (
"a" * 8, "b" * 16, "5" * 11 "a" * 8, "b" * 16, "5" * 11
), ),
{ {
# use get args to acomplish the same thing (use source instead of from) # use get args to acomplish the same thing (use source instead of
# from)
"instance": NotifyVonage, "instance": NotifyVonage,
}, },
), ),

View File

@ -157,7 +157,8 @@ apprise_url_tests = (
), ),
{ {
# template with kwarg assignments # template with kwarg assignments
# Invalid keyword specified; cna only be a digit OR `body' or 'type' # Invalid keyword specified; cna only be a digit OR `body'
# or 'type'
"instance": TypeError, "instance": TypeError,
}, },
), ),
@ -200,7 +201,8 @@ apprise_url_tests = (
"d" * 32, "5" * 11, "6" * 11 "d" * 32, "5" * 11, "6" * 11
), ),
{ {
# use get args to acomplish the same thing (use source instead of from) # use get args to acomplish the same thing (use source instead
# of from)
"instance": NotifyWhatsApp, "instance": NotifyWhatsApp,
}, },
), ),

View File

@ -218,7 +218,8 @@ apprise_url_tests = (
( (
"wxpusher://AT_appid/{}/{}/".format("2" * 11, "3" * 11), "wxpusher://AT_appid/{}/{}/".format("2" * 11, "3" * 11),
{ {
# If we have from= specified, then all elements take on the to= value # If we have from= specified, then all elements take on the
# to= value
"instance": NotifyWxPusher, "instance": NotifyWxPusher,
# Our response expected server response # Our response expected server response
"requests_response_text": WXPUSHER_GOOD_RESPONSE, "requests_response_text": WXPUSHER_GOOD_RESPONSE,
@ -227,7 +228,8 @@ apprise_url_tests = (
( (
"wxpusher://AT_appid/{}".format("3" * 11), "wxpusher://AT_appid/{}".format("3" * 11),
{ {
# use get args to acomplish the same thing (use source instead of from) # use get args to acomplish the same thing (use source instead
# of from)
"instance": NotifyWxPusher, "instance": NotifyWxPusher,
# Our response expected server response # Our response expected server response
"requests_response_text": WXPUSHER_GOOD_RESPONSE, "requests_response_text": WXPUSHER_GOOD_RESPONSE,