From 1a79d5dd0254c48c40ba87d247820d7b87f0a297 Mon Sep 17 00:00:00 2001 From: Perry Kundert Date: Thu, 7 Nov 2024 06:46:44 -0700 Subject: [PATCH] Correct SMTP sending, avoid fragile doctest --- .github/workflows/main.yml | 7 +------ GNUmakefile | 4 ++-- pytest.ini | 2 +- setup.py | 4 ++++ slip39/communications.py | 13 +++++++++---- slip39/communications_test.py | 19 +++++++++++++++---- slip39/invoice/artifact_test.py | 13 ++++++++----- 7 files changed, 40 insertions(+), 22 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4b54135..5df04e8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,12 +30,7 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - python3 -m pip install --upgrade pip - python3 -m pip install -r requirements.txt - python3 -m pip install -r requirements-serial.txt - python3 -m pip install -r requirements-gui.txt - python3 -m pip install -r requirements-wallet.txt - python3 -m pip install -r requirements-tests.txt + python3 -m pip install .[all,tests] - name: Lint with flake8 run: | make analyze diff --git a/GNUmakefile b/GNUmakefile index 6f63a68..524636c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -64,7 +64,7 @@ else endif # To see all pytest output, uncomment --capture=no, ... -PYTESTOPTS = --capture=no --log-cli-level=WARNING +PYTESTOPTS = --capture=no --log-cli-level=WARNING # --doctest-modules PY3TEST = $(PY3) -m pytest $(PYTESTOPTS) @@ -211,7 +211,7 @@ $(VENV): @echo; echo "*** Building $@ VirtualEnv..." @rm -rf $@ && $(PY3) -m venv $(VENV_OPTS) $@ \ && source $@/bin/activate \ - && make install + && make install install-tests wheel: deps $(WHEEL) diff --git a/pytest.ini b/pytest.ini index 1e2ff92..8646bca 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,3 +1,3 @@ [pytest] testpaths = slip39 -addopts = -vv --doctest-modules --ignore-glob=**/__main__.py --ignore-glob=**/main.py --ignore-glob=**/ethereum.py --cov=slip39 --cov-config=.coveragerc +addopts = -v --ignore-glob=**/__main__.py --ignore-glob=**/main.py --ignore-glob=**/ethereum.py --cov=slip39 --cov-config=.coveragerc diff --git a/setup.py b/setup.py index fd7d3ea..512ae00 100644 --- a/setup.py +++ b/setup.py @@ -28,6 +28,10 @@ # Make python-slip39[all] install all extra (non-tests) requirements, excluding duplicates extras_require['all'] = list( set( sum( extras_require.values(), [] ))) +# Since setuptools is retiring tests_require, add it as another option (but not included in 'all') +extras_require['tests'] = tests_require +options_require.append( 'tests' ) + Executable = None if sys.platform == 'win32': # We use cx_Freeze for executable/installer packaging on Windows, only, for now. diff --git a/slip39/communications.py b/slip39/communications.py index 1951ed1..0e8f8ed 100755 --- a/slip39/communications.py +++ b/slip39/communications.py @@ -254,6 +254,8 @@ def send_message( for a in utils.getaddresses( addr_fields ) ] + log.info( "Message headers:\n" + tabulate( [[k, len(v), v] for k,v in msg.items()], headers=["Description", "Length", "Value"], tablefmt='orgtbl' )) + # Now that we have a to_addrs, construct a mapping of (mx, ...) --> [addr, ...]. For each # to_addrs, lookup its destination's mx records; we'll append all to_addrs w/ the same mx's # (sorted by priority). @@ -286,12 +288,15 @@ def send_message( if verifycert is None: verifycert = False - try: + # Obtain message, ensuring \r\n line termination + if sys.version_info[0:2] >= (3,0): # Python 3 libraries expect bytes. - msg_data = msg.as_bytes() - except Exception: + msg_data = b'\r\n'.join( msg.as_bytes().split( b'\n' )) + else: # Python 2 libraries expect strings. - msg_data = msg.as_string() + msg_data = '\r\n'.join( msg.as_string().split( '\n' )) + + log.info( "Message body:\n" + msg_data.decode('UTF-8')) smtp_kwds = dict() if usessl: diff --git a/slip39/communications_test.py b/slip39/communications_test.py index 2b650cc..4b768cd 100644 --- a/slip39/communications_test.py +++ b/slip39/communications_test.py @@ -2,17 +2,22 @@ import os import re import sys +import pytest from io import StringIO from pathlib import Path from subprocess import Popen, PIPE from email import message_from_string -import dkim from aiosmtpd.controller import Controller -from .communications import dkim_message, send_message, matchaddr, AutoResponder +try: + import dkim + from .communications import dkim_message, send_message, matchaddr, AutoResponder +except ImportError: + dkim = None + from .defaults import SMTP_TO, SMTP_FROM log = logging.getLogger( __package__ ) @@ -61,6 +66,8 @@ """ ) +@pytest.mark.skipif( not dkim, + reason="DKIM support unavailable; install w/ [invoice] option" ) def test_communications_matchaddr(): assert matchaddr( "abc+def@xyz", mailbox="abc", domain="xyz" ) == ("abc", "def", "xyz") assert matchaddr( "abc+def@xyz", domain="xYz" ) == ("abc", "def", "xyz") @@ -73,6 +80,8 @@ def test_communications_matchaddr(): assert matchaddr( "abc+def@xyz", mailbox="xxx" ) is None +@pytest.mark.skipif( not dkim, + reason="DKIM support unavailable; install w/ [invoice] option" ) def test_communications_dkim(): log.info( f"Using DKIM: {dkim_selector}: {dkim_key}" ) if dkim_key: @@ -135,6 +144,8 @@ def test_communications_dkim(): pass +@pytest.mark.skipif( not dkim, + reason="DKIM support unavailable; install w/ [invoice] option" ) def test_communications_autoresponder( monkeypatch ): """The Postfix-compatible auto-responder takes an email.Message from stdin, and auto-forwards it (via a relay; normally the same Postfix installation that it is running within). @@ -183,8 +194,8 @@ async def handle_DATA(self, server, session, envelope): controller = Controller( handler, hostname='localhost', port=11111 ) controller.start() - # Send the email.Message directly our SMTP daemon, w/ RCTP TO: licensing@dominionrnd.com (taken - # from the To: header) + # Send the email.Message directly to our SMTP daemon, w/ RCTP TO: licensing@dominionrnd.com + # (taken from the To: header) send_message( msg, relay = controller.hostname, diff --git a/slip39/invoice/artifact_test.py b/slip39/invoice/artifact_test.py index 3d31969..91e46aa 100644 --- a/slip39/invoice/artifact_test.py +++ b/slip39/invoice/artifact_test.py @@ -497,11 +497,14 @@ def test_tabulate( tmp_path ): # Generate a sequence of Invoices w/ unique accounts -with open( '/usr/share/dict/words', 'r' ) as words_f: - words = list( - w.strip() for w in words_f.readlines() - ) - +words = list( + ( + "Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua " + " Ut enim ad minim veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat" + " Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur" + " Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum" + ).split( " " ) +) line_currencies = [ "Bitcoin",