Skip to content

Commit

Permalink
use pre-commit/ruff to enforce a basic coding style
Browse files Browse the repository at this point in the history
  • Loading branch information
FelixSchwarz committed Jul 18, 2024
1 parent 3f730ba commit 3f7e36b
Show file tree
Hide file tree
Showing 30 changed files with 177 additions and 100 deletions.
17 changes: 17 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: debug-statements

- repo: https://github.com/charliermarsh/ruff-pre-commit
# Ruff version.
rev: 'v0.0.291'
hooks:
- id: ruff
# args: [--fix, --exit-non-zero-on-fix]
exclude: ^schwarz/mailqueue/lib/smtplib_py37.py
2 changes: 0 additions & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
include *.txt
include *.ini


2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,5 +243,3 @@ a Windows machine should be fine.
The code is licensed unter the MIT license with only few exceptions: It
contains a custom (slightly modified) version of Python's smtplib which is
licensed under the [Python License 2.0](https://spdx.org/licenses/Python-2.0.html).


34 changes: 34 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[tool.ruff]
line-length = 100
src = ["schwarz", "tests"]

ignore = [
# F405 "… may be undefined, or defined from star imports: …"
# Sometimes star imports are perfectly fine IMHO.
"F403",
"F405",
# E731: "Do not assign a `lambda` expression, use a `def`"
# I think assigning to lambda expressions is ok.
"E731",
]

select = [
# Pyflakes
"F",
# Pycodestyle
"E",
"W",
# isort
"I001",

# Special rule code to enforce that your noqa directives are "valid", in that
# the violations they say they ignore are actually being triggered on that line
# (and thus suppressed).
# replaces basically "yesqa"
"RUF100",
]

[tool.ruff.isort]
lines-after-imports = 2
known-first-party = ["schwarz.mailqueue"]
combine-as-imports = true
5 changes: 2 additions & 3 deletions schwarz/mailqueue/app_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import os
import sys

from schwarz.puzzle_plugins import parse_list_str, PluginLoader
from schwarz.puzzle_plugins import PluginLoader, parse_list_str

from .compat import configparser, SafeConfigParser
from .compat import SafeConfigParser, configparser
from .mailer import SMTPMailer
from .plugins import registry

Expand Down Expand Up @@ -163,4 +163,3 @@ def configure_logging(settings, options):
# the root logger (this might lead to duplicate lines shown to the user,
# e.g. in case of errors).
mq_logger.propagate = False

1 change: 0 additions & 1 deletion schwarz/mailqueue/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,3 @@ def send_test_message_main(argv=sys.argv, return_rc_code=False):
if return_rc_code:
return exit_code
sys.exit(exit_code)

2 changes: 1 addition & 1 deletion schwarz/mailqueue/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def os_makedirs(name, mode, exist_ok=False):

try:
import configparser

# in Python 3.2 "SafeConfigParser" was renamed to "ConfigParser"
from configparser import ConfigParser as SafeConfigParser
except ImportError:
Expand Down Expand Up @@ -98,4 +99,3 @@ def make_msgid(domain=None):
msg_id_str = email.utils.make_msgid('@'+domain)
msg_id = msg_id_str.rsplit('@', 1)[0] + '>'
return msg_id

4 changes: 2 additions & 2 deletions schwarz/mailqueue/lib/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def __setattr__(self, key, value):
self.__dict__[key] = value
return
if key not in self.data:
raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, key))
class_name = self.__class__.__name__, key
raise AttributeError("'%s' object has no attribute '%s'" % class_name)
setter = getattr(self, 'set_'+key)
setter(value)

7 changes: 3 additions & 4 deletions schwarz/mailqueue/maildir_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

import os

from boltons.fileutils import atomic_rename, atomic_save
import portalocker
from boltons.fileutils import atomic_rename, atomic_save

from .compat import os_makedirs, FileNotFoundError, IS_WINDOWS
from .compat import IS_WINDOWS, FileNotFoundError, os_makedirs


__all__ = ['create_maildir_directories', 'lock_file', 'move_message']
Expand Down Expand Up @@ -63,7 +63,7 @@ def create_maildir_directories(basedir, is_folder=False):
maildirfolder_path = os.path.join(basedir, 'maildirfolder')
# never overwrite an existing "maildirfolder" file (just being overcautious)
# in Python 3 we could also use "open(..., 'xb')" and catch FileExistsError
with atomic_save(maildirfolder_path, overwrite=False) as fp:
with atomic_save(maildirfolder_path, overwrite=False):
pass
return new_path

Expand Down Expand Up @@ -183,4 +183,3 @@ def move_message(file_, target_folder, open_file=True):
except (IOError, OSError):
pass
return None

12 changes: 8 additions & 4 deletions schwarz/mailqueue/mailer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

from __future__ import absolute_import, print_function, unicode_literals

import socket
from io import BytesIO
from smtplib import SMTPException
import socket

from .message_utils import MsgInfo, SendResult
from .smtpclient import SMTPClient
Expand All @@ -16,7 +16,7 @@
class SMTPMailer(object):
def __init__(self, hostname=None, **kwargs):
if (hostname is None) and ('client' not in kwargs):
raise TypeError('not enough parameters for __init__(): please specify at least "hostname" or "client"')
raise TypeError('not enough parameters for __init__(): please specify at least "hostname" or "client"') # noqa: E501 (line too long)
self.hostname = hostname
# ensure "port" is numeric as "socket.connect()" in Python 2 only
# accepts ints (in Python 3 '25' works as well).
Expand All @@ -31,7 +31,12 @@ def __init__(self, hostname=None, **kwargs):
raise TypeError("__init__() got an unexpected keyword argument '%s'" % extra_name)

def init_smtp_client(self):
smtp_client = SMTPClient(self.hostname, self.port, timeout=self.connect_timeout, smtp_log=self.smtp_log)
smtp_client = SMTPClient(
self.hostname,
self.port,
timeout=self.connect_timeout,
smtp_log=self.smtp_log,
)
return smtp_client

def send(self, fromaddr, toaddrs, message):
Expand Down Expand Up @@ -80,4 +85,3 @@ def send(self, fromaddr, toaddrs, message):
msg_info = MsgInfo(fromaddr, toaddrs, BytesIO(message))
self.sent_mails.append(msg_info)
return was_sent

1 change: 0 additions & 1 deletion schwarz/mailqueue/mailflow_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,3 @@ def send_test_message(config_path, options):
mh = MessageHandler(transports=(mailer,))
was_sent = mh.send_message(msg)
return was_sent

12 changes: 6 additions & 6 deletions schwarz/mailqueue/message_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

from __future__ import absolute_import, print_function, unicode_literals

from io import BytesIO
import logging
from io import BytesIO

from .message_utils import dt_now, msg_as_bytes, MsgInfo, SendResult
from .message_utils import MsgInfo, SendResult, dt_now, msg_as_bytes
from .plugins import MQAction, MQSignal


Expand Down Expand Up @@ -46,7 +46,7 @@ def send_message(self, msg, **kwargs):
if not send_result:
msg_wrapper.retries += 1
msg_wrapper.last_delivery_attempt = dt_now()
discard_message = self._notify_plugins(MQSignal.delivery_failed, msg_wrapper, send_result)
discard_message = self._notify_plugins(MQSignal.delivery_failed, msg_wrapper, send_result) # noqa: E501 (line too long)
msg_wrapper.delivery_failed(discard=discard_message)
send_result.discarded = discard_message
return send_result
Expand All @@ -61,7 +61,8 @@ def _log_successful_delivery(self, msg, sender, recipients):
def _notify_plugins(self, signal, msg, send_result):
if self.plugins is None:
return
results = self.plugins.call_plugins(signal, signal_kwargs={'msg': msg, 'send_result': send_result})
signal_kwargs = {'msg': msg, 'send_result': send_result}
results = self.plugins.call_plugins(signal, signal_kwargs=signal_kwargs)

if not results:
return None
Expand All @@ -86,7 +87,7 @@ def _msg_metadata(self, msg, **kwargs):
recipient = kwargs.pop('recipient', None)
recipients = kwargs.pop('recipients', None)
if recipient and recipients:
raise ValueError('__init__() got conflicting parameters: recipient=%r, recipients=%r' % (recipient, recipients))
raise ValueError('__init__() got conflicting parameters: recipient=%r, recipients=%r' % (recipient, recipients)) # noqa: E501 (line too long)
if recipient:
recipients = (recipient,)
if not recipients:
Expand Down Expand Up @@ -166,4 +167,3 @@ def __init__(self, from_addr, to_addrs, msg_bytes):

def start_delivery(self):
return True

14 changes: 8 additions & 6 deletions schwarz/mailqueue/message_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
from __future__ import absolute_import, print_function, unicode_literals

import calendar
import email.utils
import re
from collections import namedtuple
from datetime import datetime as DateTime, timedelta as TimeDelta
from email.header import decode_header
from email.parser import FeedParser, HeaderParser
import email.utils
from io import BytesIO, TextIOWrapper
import re

from boltons.timeutils import ConstantTZInfo, LocalTZ

Expand Down Expand Up @@ -69,7 +69,7 @@ def dt_now():
return DateTime.now(tz=LocalTZ)


_MsgInfo = namedtuple('_MsgInfo', ('from_addr', 'to_addrs', 'msg_fp', 'queue_date', 'last', 'retries'))
_MsgInfo = namedtuple('_MsgInfo', ('from_addr', 'to_addrs', 'msg_fp', 'queue_date', 'last', 'retries')) # noqa: E501 (line too long)

class MsgInfo(_MsgInfo):
def __new__(cls, from_addr, to_addrs, msg_fp, queue_date=None, last=None, retries=None):
Expand Down Expand Up @@ -138,7 +138,10 @@ def decode_header_value(encoded_str):
def strip_brackets(value):
if value is None:
return None
angle_regex = _re_angle_brackets if isinstance(value, bytes) else _re_angle_brackets_str
if isinstance(value, bytes):
angle_regex = _re_angle_brackets
else:
angle_regex = _re_angle_brackets_str
match = angle_regex.search(value)
return match.group(1)

Expand All @@ -161,7 +164,7 @@ def parse_datetime(dt_str):
def parse_number(number_str):
if number_str is None:
return None
return int(re.search('^(\d+)$', number_str).group(1))
return int(re.search(r'^(\d+)$', number_str).group(1))

def msg_as_bytes(msg):
if hasattr(msg, 'as_bytes'):
Expand All @@ -174,4 +177,3 @@ def msg_as_bytes(msg):
else:
msg_bytes = msg
return msg_bytes

1 change: 0 additions & 1 deletion schwarz/mailqueue/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,3 @@ class MQSignal(object):

class MQAction(object):
DISCARD = 'discard'

28 changes: 20 additions & 8 deletions schwarz/mailqueue/queue_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@

import email.utils
import logging
from mailbox import _sync_close, Maildir
import os
import time
from mailbox import Maildir, _sync_close

from boltons.timeutils import dt_to_timestamp

from .app_helpers import init_app, init_smtp_mailer
from .compat import queue, IS_WINDOWS
from .compat import IS_WINDOWS, queue
from .maildir_utils import create_maildir_directories, find_messages, move_message
from .message_handler import BaseMsg, MessageHandler
from .message_utils import dt_now, msg_as_bytes, parse_message_envelope, SendResult
from .message_utils import SendResult, dt_now, msg_as_bytes, parse_message_envelope
from .plugins import registry


Expand All @@ -26,13 +26,25 @@
'MaildirBackend',
]

def enqueue_message(msg, queue_path, sender, recipients, return_msg=False, in_progress=False, **queue_args):
msg_bytes = serialize_message_with_queue_data(msg, sender=sender, recipients=recipients, **queue_args)
def enqueue_message(msg, queue_path, sender, recipients, return_msg=False,
in_progress=False, **queue_args):
msg_bytes = serialize_message_with_queue_data(
msg,
sender=sender,
recipients=recipients,
**queue_args
)
create_maildir_directories(queue_path)

mailbox = Maildir(queue_path)
sub_dir = 'cur' if in_progress else 'new'
return inject_message_into_maildir(msg_bytes, mailbox, sub_dir=sub_dir, return_msg=return_msg)
msg = inject_message_into_maildir(
msg_bytes,
mailbox,
sub_dir=sub_dir,
return_msg=return_msg,
)
return msg


def inject_message_into_maildir(msg_bytes, maildir, sub_dir='new', return_msg=False):
Expand All @@ -51,7 +63,8 @@ def inject_message_into_maildir(msg_bytes, maildir, sub_dir='new', return_msg=Fa
return MaildirBackedMsg(target_.name, fp=target_)


def serialize_message_with_queue_data(msg, sender, recipients, queue_date=None, last=None, retries=None):
def serialize_message_with_queue_data(msg, sender, recipients, queue_date=None,
last=None, retries=None):
sender_bytes = _email_address_as_bytes(sender)
b_recipients = [_email_address_as_bytes(recipient) for recipient in recipients]
queue_lines = [
Expand Down Expand Up @@ -297,4 +310,3 @@ def one_shot_queue_run(queue_dir, config_path=None, options=None, settings=None)
plugin_loader = settings['plugin_loader']
send_all_queued_messages(queue_dir, mailer, plugins=registry, mh=mh)
plugin_loader.terminate_all_activated_plugins()

14 changes: 8 additions & 6 deletions schwarz/mailqueue/smtpclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,21 @@

from __future__ import absolute_import, print_function, unicode_literals

from contextlib import contextmanager
import logging
import re
import six
import socket
from contextlib import contextmanager

import six

from .lib.smtplib_py37 import (
_fix_eols,
bCRLF,
CRLF,
SMTP,
SMTPDataError,
SMTPResponseException,
SMTPSenderRefused
SMTPSenderRefused,
_fix_eols,
bCRLF,
)


Expand Down Expand Up @@ -88,7 +89,8 @@ def connect(self, host='localhost', port=0, source_address=None):
# gets all the interesting info anyway so we can just disable all
# logging here.
with disable_debug(self):
return super(SMTPClient, self).connect(host=host, port=port, source_address=source_address)
_super_instance = super(SMTPClient, self)
return _super_instance.connect(host=host, port=port, source_address=source_address)

def _get_socket(self, host, port, timeout):
# This wrapper method is big because it contains superior logging which
Expand Down
Loading

0 comments on commit 3f7e36b

Please sign in to comment.