mirror of
https://github.com/craigerl/aprsd.git
synced 2024-11-21 23:55:17 -05:00
Update tox environment to fix formatting python errors
This patch includes lots of changes to tox environment for automatically detecting pep8 failures, which can cause python2 vs python3 failures after install. The following tox commands have been added tox -efmt-check - This checks the python syntax and formatting tox -efmt - Automatically fixes python syntax formatting that fmt-check complains about. tox -etype-check - check on types tox -elint - flake8 run This patch also changes where the default config file is located. The new location is ~/.config/aprsd/aprsd.yml You can now also specify a custom config file on the command line with the -c or --config option as well.
This commit is contained in:
parent
2bebd83449
commit
53b8f21535
22
.github/workflows/python.yml
vendored
Normal file
22
.github/workflows/python.yml
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
name: python
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
tox:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [2.7, 3.6, 3.7, 3.8, 3.9]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install tox tox-gh-actions
|
||||
- name: Test with tox
|
||||
run: tox
|
@ -14,6 +14,4 @@
|
||||
|
||||
import pbr.version
|
||||
|
||||
|
||||
__version__ = pbr.version.VersionInfo(
|
||||
'aprsd').version_string()
|
||||
__version__ = pbr.version.VersionInfo("aprsd").version_string()
|
||||
|
@ -1,33 +1,27 @@
|
||||
import argparse
|
||||
import logging
|
||||
import socketserver
|
||||
import sys
|
||||
import time
|
||||
import socketserver
|
||||
|
||||
from logging.handlers import RotatingFileHandler
|
||||
|
||||
from aprsd import utils
|
||||
|
||||
# command line args
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--loglevel",
|
||||
default='DEBUG',
|
||||
choices=['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'],
|
||||
help="The log level to use for aprsd.log")
|
||||
parser.add_argument("--quiet",
|
||||
action='store_true',
|
||||
help="Don't log to stdout")
|
||||
parser.add_argument(
|
||||
"--loglevel",
|
||||
default="DEBUG",
|
||||
choices=["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"],
|
||||
help="The log level to use for aprsd.log",
|
||||
)
|
||||
parser.add_argument("--quiet", action="store_true", help="Don't log to stdout")
|
||||
|
||||
parser.add_argument("--port",
|
||||
default=9099,
|
||||
type=int,
|
||||
help="The port to listen on .")
|
||||
parser.add_argument("--ip",
|
||||
default='127.0.0.1',
|
||||
help="The IP to listen on ")
|
||||
parser.add_argument("--port", default=9099, type=int, help="The port to listen on .")
|
||||
parser.add_argument("--ip", default="127.0.0.1", help="The IP to listen on ")
|
||||
|
||||
CONFIG = None
|
||||
LOG = logging.getLogger('ARPSSERVER')
|
||||
LOG = logging.getLogger("ARPSSERVER")
|
||||
|
||||
|
||||
# Setup the logging faciility
|
||||
@ -36,22 +30,19 @@ LOG = logging.getLogger('ARPSSERVER')
|
||||
def setup_logging(args):
|
||||
global LOG
|
||||
levels = {
|
||||
'CRITICAL': logging.CRITICAL,
|
||||
'ERROR': logging.ERROR,
|
||||
'WARNING': logging.WARNING,
|
||||
'INFO': logging.INFO,
|
||||
'DEBUG': logging.DEBUG}
|
||||
"CRITICAL": logging.CRITICAL,
|
||||
"ERROR": logging.ERROR,
|
||||
"WARNING": logging.WARNING,
|
||||
"INFO": logging.INFO,
|
||||
"DEBUG": logging.DEBUG,
|
||||
}
|
||||
log_level = levels[args.loglevel]
|
||||
|
||||
LOG.setLevel(log_level)
|
||||
log_format = ("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s]"
|
||||
" %(message)s")
|
||||
date_format = '%m/%d/%Y %I:%M:%S %p'
|
||||
log_formatter = logging.Formatter(fmt=log_format,
|
||||
datefmt=date_format)
|
||||
fh = RotatingFileHandler('aprs-server.log',
|
||||
maxBytes=(10248576 * 5),
|
||||
backupCount=4)
|
||||
log_format = "%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s]" " %(message)s"
|
||||
date_format = "%m/%d/%Y %I:%M:%S %p"
|
||||
log_formatter = logging.Formatter(fmt=log_format, datefmt=date_format)
|
||||
fh = RotatingFileHandler("aprs-server.log", maxBytes=(10248576 * 5), backupCount=4)
|
||||
fh.setFormatter(log_formatter)
|
||||
LOG.addHandler(fh)
|
||||
|
||||
@ -62,7 +53,6 @@ def setup_logging(args):
|
||||
|
||||
|
||||
class MyAPRSTCPHandler(socketserver.BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
# self.request is the TCP socket connected to the client
|
||||
self.data = self.request.recv(1024).strip()
|
||||
@ -81,8 +71,8 @@ def main():
|
||||
|
||||
CONFIG = utils.parse_config(args)
|
||||
|
||||
ip = CONFIG['aprs']['host']
|
||||
port = CONFIG['aprs']['port']
|
||||
ip = CONFIG["aprs"]["host"]
|
||||
port = CONFIG["aprs"]["port"]
|
||||
LOG.info("Start server listening on %s:%s" % (args.ip, args.port))
|
||||
|
||||
with socketserver.TCPServer((ip, port), MyAPRSTCPHandler) as server:
|
||||
|
@ -19,37 +19,49 @@ import time
|
||||
|
||||
|
||||
def fuzzy(hour, minute, degree=1):
|
||||
'''Implements the fuzzy clock.
|
||||
"""Implements the fuzzy clock.
|
||||
returns the the string that spells out the time - hour:minute
|
||||
Supports two degrees of fuzziness. Set with degree = 1 or degree = 2
|
||||
When degree = 1, time is in quantum of 5 minutes.
|
||||
When degree = 2, time is in quantum of 15 minutes.'''
|
||||
When degree = 2, time is in quantum of 15 minutes."""
|
||||
|
||||
if degree <= 0 or degree > 2:
|
||||
print('Please use a degree of 1 or 2. Using fuzziness degree=1')
|
||||
print("Please use a degree of 1 or 2. Using fuzziness degree=1")
|
||||
degree = 1
|
||||
|
||||
begin = 'It\'s '
|
||||
begin = "It's "
|
||||
|
||||
f0 = 'almost '
|
||||
f1 = 'exactly '
|
||||
f2 = 'around '
|
||||
f0 = "almost "
|
||||
f1 = "exactly "
|
||||
f2 = "around "
|
||||
|
||||
b0 = ' past '
|
||||
b1 = ' to '
|
||||
b0 = " past "
|
||||
b1 = " to "
|
||||
|
||||
hourList = ('One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight',
|
||||
'Nine', 'Ten', 'Eleven', 'Twelve')
|
||||
hourlist = (
|
||||
"One",
|
||||
"Two",
|
||||
"Three",
|
||||
"Four",
|
||||
"Five",
|
||||
"Six",
|
||||
"Seven",
|
||||
"Eight",
|
||||
"Nine",
|
||||
"Ten",
|
||||
"Eleven",
|
||||
"Twelve",
|
||||
)
|
||||
|
||||
s1 = s2 = s3 = s4 = ''
|
||||
s1 = s2 = s3 = s4 = ""
|
||||
base = 5
|
||||
|
||||
if degree == 1:
|
||||
base = 5
|
||||
val = ('Five', 'Ten', 'Quarter', 'Twenty', 'Twenty-Five', 'Half')
|
||||
val = ("Five", "Ten", "Quarter", "Twenty", "Twenty-Five", "Half")
|
||||
elif degree == 2:
|
||||
base = 15
|
||||
val = ('Quarter', 'Half')
|
||||
val = ("Quarter", "Half")
|
||||
|
||||
# to find whether we have to use 'almost', 'exactly' or 'around'
|
||||
dmin = minute % base
|
||||
@ -74,20 +86,20 @@ def fuzzy(hour, minute, degree=1):
|
||||
|
||||
if minute <= base / 2:
|
||||
# Case like "It's around/exactly Ten"
|
||||
s2 = s3 = ''
|
||||
s4 = hourList[hour - 12 - 1]
|
||||
s2 = s3 = ""
|
||||
s4 = hourlist[hour - 12 - 1]
|
||||
elif minute >= 60 - base / 2:
|
||||
# Case like "It's almost Ten"
|
||||
s2 = s3 = ''
|
||||
s4 = hourList[hour - 12]
|
||||
s2 = s3 = ""
|
||||
s4 = hourlist[hour - 12]
|
||||
else:
|
||||
# Other cases with all words, like "It's around Quarter past One"
|
||||
if minute > 30:
|
||||
s3 = b1 # to
|
||||
s4 = hourList[hour - 12]
|
||||
s4 = hourlist[hour - 12]
|
||||
else:
|
||||
s3 = b0 # past
|
||||
s4 = hourList[hour - 12 - 1]
|
||||
s4 = hourlist[hour - 12 - 1]
|
||||
|
||||
return begin + s1 + s2 + s3 + s4
|
||||
|
||||
@ -102,17 +114,17 @@ def main():
|
||||
try:
|
||||
deg = int(sys.argv[1])
|
||||
except Exception:
|
||||
print('Please use a degree of 1 or 2. Using fuzziness degree=1')
|
||||
print("Please use a degree of 1 or 2. Using fuzziness degree=1")
|
||||
|
||||
if len(sys.argv) >= 3:
|
||||
tm = sys.argv[2].split(':')
|
||||
tm = sys.argv[2].split(":")
|
||||
try:
|
||||
h = int(tm[0])
|
||||
m = int(tm[1])
|
||||
if h < 0 or h > 23 or m < 0 or m > 59:
|
||||
raise Exception
|
||||
except Exception:
|
||||
print('Bad time entered. Using the system time.')
|
||||
print("Bad time entered. Using the system time.")
|
||||
h = stm.tm_hour
|
||||
m = stm.tm_min
|
||||
print(fuzzy(h, m, deg))
|
||||
|
637
aprsd/main.py
637
aprsd/main.py
File diff suppressed because it is too large
Load Diff
175
aprsd/utils.py
175
aprsd/utils.py
@ -1,40 +1,44 @@
|
||||
"""Utilities and helper functions."""
|
||||
|
||||
import logging
|
||||
import errno
|
||||
import os
|
||||
import sys
|
||||
|
||||
import click
|
||||
import yaml
|
||||
|
||||
# an example of what should be in the ~/.aprsd/config.yml
|
||||
example_config = '''
|
||||
ham:
|
||||
callsign: KFART
|
||||
DEFAULT_CONFIG_DICT = {
|
||||
"ham": {"callsign": "KFART"},
|
||||
"aprs": {
|
||||
"login": "someusername",
|
||||
"password": "somepassword",
|
||||
"host": "noam.aprs2.net",
|
||||
"port": 14580,
|
||||
"logfile": "/tmp/arsd.log",
|
||||
},
|
||||
"shortcuts": {
|
||||
"aa": "5551239999@vtext.com",
|
||||
"cl": "craiglamparter@somedomain.org",
|
||||
"wb": "555309@vtext.com",
|
||||
},
|
||||
"smtp": {
|
||||
"login": "something",
|
||||
"password": "some lame password",
|
||||
"host": "imap.gmail.com",
|
||||
"port": 465,
|
||||
"use_ssl": False,
|
||||
},
|
||||
"imap": {
|
||||
"login": "imapuser",
|
||||
"password": "something here too",
|
||||
"host": "imap.gmail.com",
|
||||
"port": 993,
|
||||
"use_ssl": True,
|
||||
},
|
||||
}
|
||||
|
||||
aprs:
|
||||
login: someusername
|
||||
password: password
|
||||
host: noam.aprs2.net
|
||||
port: 14580
|
||||
logfile: /tmp/aprsd.log
|
||||
|
||||
shortcuts:
|
||||
'aa': '5551239999@vtext.com'
|
||||
'cl': 'craiglamparter@somedomain.org'
|
||||
'wb': '555309@vtext.com'
|
||||
|
||||
smtp:
|
||||
login: something
|
||||
password: some lame password
|
||||
host: imap.gmail.com
|
||||
port: 465
|
||||
|
||||
imap:
|
||||
login: imapuser
|
||||
password: something dumb
|
||||
host: imap.gmail.com
|
||||
'''
|
||||
|
||||
log = logging.getLogger('APRSD')
|
||||
DEFAULT_CONFIG_FILE = "~/.config/aprsd/aprsd.yml"
|
||||
|
||||
|
||||
def env(*vars, **kwargs):
|
||||
@ -45,20 +49,56 @@ def env(*vars, **kwargs):
|
||||
value = os.environ.get(v, None)
|
||||
if value:
|
||||
return value
|
||||
return kwargs.get('default', '')
|
||||
return kwargs.get("default", "")
|
||||
|
||||
|
||||
def get_config():
|
||||
"""This tries to read the yaml config from ~/.aprsd/config.yml."""
|
||||
config_file = os.path.expanduser("~/.aprsd/config.yml")
|
||||
if os.path.exists(config_file):
|
||||
with open(config_file, "r") as stream:
|
||||
def mkdir_p(path):
|
||||
"""Make directory and have it work in py2 and py3."""
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc: # Python >= 2.5
|
||||
if exc.errno == errno.EEXIST and os.path.isdir(path):
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
def create_default_config():
|
||||
"""Create a default config file."""
|
||||
# make sure the directory location exists
|
||||
config_file_expanded = os.path.expanduser(DEFAULT_CONFIG_FILE)
|
||||
config_dir = os.path.dirname(config_file_expanded)
|
||||
if not os.path.exists(config_dir):
|
||||
click.echo("Config dir '{}' doesn't exist, creating.".format(config_dir))
|
||||
mkdir_p(config_dir)
|
||||
with open(config_file_expanded, "w+") as cf:
|
||||
yaml.dump(DEFAULT_CONFIG_DICT, cf)
|
||||
|
||||
|
||||
def get_config(config_file):
|
||||
"""This tries to read the yaml config from <config_file>."""
|
||||
config_file_expanded = os.path.expanduser(config_file)
|
||||
if os.path.exists(config_file_expanded):
|
||||
with open(config_file_expanded, "r") as stream:
|
||||
config = yaml.load(stream, Loader=yaml.FullLoader)
|
||||
return config
|
||||
else:
|
||||
log.critical("%s is missing, please create config file" % config_file)
|
||||
print("\nCopy to ~/.aprsd/config.yml and edit\n\nSample config:\n %s"
|
||||
% example_config)
|
||||
if config_file == DEFAULT_CONFIG_FILE:
|
||||
click.echo(
|
||||
"{} is missing, creating config file".format(config_file_expanded)
|
||||
)
|
||||
create_default_config()
|
||||
msg = (
|
||||
"Default config file created at {}. Please edit with your "
|
||||
"settings.".format(config_file)
|
||||
)
|
||||
click.echo(msg)
|
||||
else:
|
||||
# The user provided a config file path different from the
|
||||
# Default, so we won't try and create it, just bitch and bail.
|
||||
msg = "Custom config file '{}' is missing.".format(config_file)
|
||||
click.echo(msg)
|
||||
|
||||
sys.exit(-1)
|
||||
|
||||
|
||||
@ -66,42 +106,55 @@ def get_config():
|
||||
# and consume the settings.
|
||||
# If the required params don't exist,
|
||||
# it will look in the environment
|
||||
def parse_config():
|
||||
def parse_config(config_file):
|
||||
# for now we still use globals....ugh
|
||||
global CONFIG, LOG
|
||||
global CONFIG
|
||||
|
||||
def fail(msg):
|
||||
LOG.critical(msg)
|
||||
click.echo(msg)
|
||||
sys.exit(-1)
|
||||
|
||||
def check_option(config, section, name=None, default=None):
|
||||
def check_option(config, section, name=None, default=None, default_fail=None):
|
||||
if section in config:
|
||||
|
||||
if name and name not in config[section]:
|
||||
if not default:
|
||||
fail("'%s' was not in '%s' section of config file" %
|
||||
(name, section))
|
||||
fail(
|
||||
"'%s' was not in '%s' section of config file" % (name, section)
|
||||
)
|
||||
else:
|
||||
config[section][name] = default
|
||||
else:
|
||||
if (
|
||||
default_fail
|
||||
and name in config[section]
|
||||
and config[section][name] == default_fail
|
||||
):
|
||||
# We have to fail and bail if the user hasn't edited
|
||||
# this config option.
|
||||
fail("Config file needs to be edited from provided defaults.")
|
||||
else:
|
||||
fail("'%s' section wasn't in config file" % section)
|
||||
return config
|
||||
|
||||
# Now read the ~/.aprds/config.yml
|
||||
config = get_config()
|
||||
check_option(config, 'shortcuts')
|
||||
check_option(config, 'ham', 'callsign')
|
||||
check_option(config, 'aprs', 'login')
|
||||
check_option(config, 'aprs', 'password')
|
||||
check_option(config, 'aprs', 'host')
|
||||
check_option(config, 'aprs', 'port')
|
||||
config = check_option(config, 'aprs', 'logfile', './aprsd.log')
|
||||
check_option(config, 'imap', 'host')
|
||||
check_option(config, 'imap', 'login')
|
||||
check_option(config, 'imap', 'password')
|
||||
check_option(config, 'smtp', 'host')
|
||||
check_option(config, 'smtp', 'port')
|
||||
check_option(config, 'smtp', 'login')
|
||||
check_option(config, 'smtp', 'password')
|
||||
config = get_config(config_file)
|
||||
check_option(config, "shortcuts")
|
||||
# special check here to make sure user has edited the config file
|
||||
# and changed the ham callsign
|
||||
check_option(
|
||||
config, "ham", "callsign", default_fail=DEFAULT_CONFIG_DICT["ham"]["callsign"]
|
||||
)
|
||||
check_option(config, "aprs", "login")
|
||||
check_option(config, "aprs", "password")
|
||||
check_option(config, "aprs", "host")
|
||||
check_option(config, "aprs", "port")
|
||||
check_option(config, "aprs", "logfile", "./aprsd.log")
|
||||
check_option(config, "imap", "host")
|
||||
check_option(config, "imap", "login")
|
||||
check_option(config, "imap", "password")
|
||||
check_option(config, "smtp", "host")
|
||||
check_option(config, "smtp", "port")
|
||||
check_option(config, "smtp", "login")
|
||||
check_option(config, "smtp", "password")
|
||||
|
||||
return config
|
||||
LOG.info("aprsd config loaded")
|
||||
|
9
dev-requirements.in
Normal file
9
dev-requirements.in
Normal file
@ -0,0 +1,9 @@
|
||||
tox
|
||||
pytest
|
||||
pytest-cov
|
||||
mypy
|
||||
flake8
|
||||
pep8-naming
|
||||
black
|
||||
isort
|
||||
Sphinx
|
60
dev-requirements.txt
Normal file
60
dev-requirements.txt
Normal file
@ -0,0 +1,60 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile dev-requirements.in
|
||||
#
|
||||
alabaster==0.7.12 # via sphinx
|
||||
appdirs==1.4.4 # via black, virtualenv
|
||||
attrs==20.3.0 # via pytest
|
||||
babel==2.9.0 # via sphinx
|
||||
black==20.8b1 # via -r dev-requirements.in
|
||||
certifi==2020.12.5 # via requests
|
||||
chardet==3.0.4 # via requests
|
||||
coverage==5.3 # via pytest-cov
|
||||
distlib==0.3.1 # via virtualenv
|
||||
docutils==0.16 # via sphinx
|
||||
filelock==3.0.12 # via tox, virtualenv
|
||||
flake8-polyfill==1.0.2 # via pep8-naming
|
||||
flake8==3.8.4 # via -r dev-requirements.in, flake8-polyfill
|
||||
idna==2.10 # via requests
|
||||
imagesize==1.2.0 # via sphinx
|
||||
iniconfig==1.1.1 # via pytest
|
||||
isort==5.6.4 # via -r dev-requirements.in
|
||||
jinja2==2.11.2 # via sphinx
|
||||
markupsafe==1.1.1 # via jinja2
|
||||
mccabe==0.6.1 # via flake8
|
||||
mypy-extensions==0.4.3 # via black, mypy
|
||||
mypy==0.790 # via -r dev-requirements.in
|
||||
packaging==20.7 # via pytest, sphinx, tox
|
||||
pathspec==0.8.1 # via black
|
||||
pep8-naming==0.11.1 # via -r dev-requirements.in
|
||||
pluggy==0.13.1 # via pytest, tox
|
||||
py==1.9.0 # via pytest, tox
|
||||
pycodestyle==2.6.0 # via flake8
|
||||
pyflakes==2.2.0 # via flake8
|
||||
pygments==2.7.3 # via sphinx
|
||||
pyparsing==2.4.7 # via packaging
|
||||
pytest-cov==2.10.1 # via -r dev-requirements.in
|
||||
pytest==6.1.2 # via -r dev-requirements.in, pytest-cov
|
||||
pytz==2020.4 # via babel
|
||||
regex==2020.11.13 # via black
|
||||
requests==2.25.0 # via sphinx
|
||||
six==1.15.0 # via tox, virtualenv
|
||||
snowballstemmer==2.0.0 # via sphinx
|
||||
sphinx==3.3.1 # via -r dev-requirements.in
|
||||
sphinxcontrib-applehelp==1.0.2 # via sphinx
|
||||
sphinxcontrib-devhelp==1.0.2 # via sphinx
|
||||
sphinxcontrib-htmlhelp==1.0.3 # via sphinx
|
||||
sphinxcontrib-jsmath==1.0.1 # via sphinx
|
||||
sphinxcontrib-qthelp==1.0.3 # via sphinx
|
||||
sphinxcontrib-serializinghtml==1.1.4 # via sphinx
|
||||
toml==0.10.2 # via black, pytest, tox
|
||||
tox==3.20.1 # via -r dev-requirements.in
|
||||
typed-ast==1.4.1 # via black, mypy
|
||||
typing-extensions==3.7.4.3 # via black, mypy
|
||||
urllib3==1.26.2 # via requests
|
||||
virtualenv==20.2.2 # via tox
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
# setuptools
|
@ -4,3 +4,4 @@ imapclient
|
||||
pbr
|
||||
pyyaml
|
||||
six
|
||||
requests
|
||||
|
4
setup.py
4
setup.py
@ -24,6 +24,4 @@ try:
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['pbr'],
|
||||
pbr=True)
|
||||
setuptools.setup(setup_requires=["pbr"], pbr=True)
|
||||
|
3
test-requirements-py2.txt
Normal file
3
test-requirements-py2.txt
Normal file
@ -0,0 +1,3 @@
|
||||
flake8
|
||||
pytest
|
||||
mock
|
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
23
tests/test_main.py
Normal file
23
tests/test_main.py
Normal file
@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import pytest
|
||||
|
||||
from aprsd import main
|
||||
|
||||
if sys.version_info >= (3, 2):
|
||||
from unittest import mock
|
||||
else:
|
||||
import mock
|
||||
|
||||
|
||||
class testMain(unittest.TestCase):
|
||||
@mock.patch("aprsd.main._imap_connect")
|
||||
@mock.patch("aprsd.main._smtp_connect")
|
||||
def test_validate_email(self, imap_mock, smtp_mock):
|
||||
"""Test to make sure we fail."""
|
||||
imap_mock.return_value = None
|
||||
smtp_mock.return_value = {"smaiof": "fire"}
|
||||
|
||||
main.validate_email()
|
89
tox.ini
89
tox.ini
@ -1,26 +1,51 @@
|
||||
[tox]
|
||||
minversion = 1.6
|
||||
minversion = 2.9.0
|
||||
skipdist = True
|
||||
envlist = py27,py36,py37,fast8,pep8,cover,docs
|
||||
skip_missing_interpreters = true
|
||||
envlist = py{27,36,37,38},pep8,fmt-check
|
||||
|
||||
# Activate isolated build environment. tox will use a virtual environment
|
||||
# to build a source distribution from the source tree. For build tools and
|
||||
# arguments use the pyproject.toml file as specified in PEP-517 and PEP-518.
|
||||
isolated_build = true
|
||||
|
||||
[testenv]
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
usedevelop = True
|
||||
install_command = pip install {opts} {packages}
|
||||
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
-r{toxinidir}/dev-requirements.txt
|
||||
commands =
|
||||
pytest aprsd/main.py {posargs}
|
||||
# Use -bb to enable BytesWarnings as error to catch str/bytes misuse.
|
||||
# Use -Werror to treat warnings as errors.
|
||||
# {envpython} -bb -Werror -m pytest \
|
||||
# --cov="{envsitepackagesdir}/aprsd" --cov-report=html --cov-report=term {posargs}
|
||||
{envpython} -bb -Werror -m pytest {posargs}
|
||||
|
||||
[testenv:cover]
|
||||
[testenv:py27]
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
usedevelop = True
|
||||
install_command = pip install {opts} {packages}
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements-py2.txt
|
||||
commands =
|
||||
pytest --cov=aprsd
|
||||
# Use -bb to enable BytesWarnings as error to catch str/bytes misuse.
|
||||
# Use -Werror to treat warnings as errors.
|
||||
# {envpython} -bb -Werror -m pytest \
|
||||
# --cov="{envsitepackagesdir}/aprsd" --cov-report=html --cov-report=term {posargs}
|
||||
{envpython} -bb -Werror -m pytest
|
||||
|
||||
[testenv:docs]
|
||||
deps = -r{toxinidir}/test-requirements.txt
|
||||
commands = sphinx-build -b html docs/source docs/html
|
||||
|
||||
[testenv:pep8-27]
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements-py2.txt
|
||||
commands =
|
||||
flake8 {posargs} aprsd
|
||||
|
||||
[testenv:pep8]
|
||||
commands =
|
||||
flake8 {posargs} aprsd
|
||||
@ -33,7 +58,57 @@ commands =
|
||||
{toxinidir}/tools/fast8.sh
|
||||
passenv = FAST8_NUM_COMMITS
|
||||
|
||||
[testenv:lint]
|
||||
skip_install = true
|
||||
deps =
|
||||
-r{toxinidir}/dev-requirements.txt
|
||||
commands =
|
||||
flake8 aprsd
|
||||
|
||||
[flake8]
|
||||
max-line-length = 99
|
||||
show-source = True
|
||||
ignore = E713,E501
|
||||
ignore = E713,E501,W503
|
||||
extend-ignore = E203,W503
|
||||
extend-exclude = venv
|
||||
exclude = .venv,.git,.tox,dist,doc,.ropeproject
|
||||
|
||||
# This is the configuration for the tox-gh-actions plugin for GitHub Actions
|
||||
# https://github.com/ymyzk/tox-gh-actions
|
||||
# This section is not needed if not using GitHub Actions for CI.
|
||||
[gh-actions]
|
||||
python =
|
||||
2.7: py27, pep8-27
|
||||
3.6: py36, pep8, fmt-check
|
||||
3.7: py38, pep8, fmt-check
|
||||
3.8: py38, pep8, fmt-check, type-check, docs
|
||||
3.9: py39
|
||||
|
||||
[testenv:fmt]
|
||||
# This will reformat your code to comply with pep8
|
||||
# and standard formatting
|
||||
skip_install = true
|
||||
deps =
|
||||
-r{toxinidir}/dev-requirements.txt
|
||||
commands =
|
||||
isort .
|
||||
black .
|
||||
|
||||
[testenv:fmt-check]
|
||||
# Runs a check only on code formatting.
|
||||
# you can fix imports by running isort standalone
|
||||
# you can fix code formatting by running black standalone
|
||||
skip_install = true
|
||||
deps =
|
||||
-r{toxinidir}/dev-requirements.txt
|
||||
commands =
|
||||
isort --check-only .
|
||||
black --check .
|
||||
|
||||
[testenv:type-check]
|
||||
skip_install = true
|
||||
deps =
|
||||
-r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/dev-requirements.txt
|
||||
commands =
|
||||
mypy aprsd
|
||||
|
Loading…
Reference in New Issue
Block a user