-
Notifications
You must be signed in to change notification settings - Fork 96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Convert all test cases to pytest #202
Changes from all commits
9f85a15
a2066ca
607dd69
21afaad
f1b7a99
283ad5b
6270a91
53533cc
ce6fd20
952e47d
c5ff4ae
344386f
8bd5f1a
1723451
75ec0ba
9880b2d
766c755
d9dcaa9
d460da8
22fc1ab
3a40153
d10441e
2eb95b8
5def612
d634fab
4cc0bcc
5b7482c
c868b44
7386001
9a1b0c5
3e27ab3
3aa2199
5699904
46a4f22
82955ae
d8b4904
0e26566
b9d32f9
6995d90
b9d04c2
23aa4e6
cd88386
b5610a0
d67e319
9513824
1eb4552
67d206b
8c30893
725929c
fe5dabb
b6d6247
1141a7c
23e9f8e
e7bec6d
c09d458
b29d660
e5478ba
6e7668b
43755f8
37be1f0
4867719
3be1721
d6ea672
0b12e7d
376513f
717c0eb
257dc03
24f7cfc
cfc242b
a311892
cb8dd56
918d55e
e07b3c1
f8cd922
11d40b9
14f1f8e
dd3b131
4a7d7f9
4cd296c
d9fe241
8201665
e9c691b
de0bb31
c029e5c
0050cd4
cc78848
b4d8c38
c6ac674
cee54cf
be7f65c
e8a6ce5
c7ab35e
82439c4
b92142a
ecc317b
751df90
b56bb3d
292d08c
bea866c
5a91003
40bf400
062c33a
8880749
0104a97
b5c2e60
6ca6b17
ed0e21e
6ca3fdb
e099e4b
27a8433
f5fb356
a7d47bf
0555b05
f8fadb6
af1442c
d03e0d5
f748fef
127c21a
4eebc42
4f1621f
f9d0e27
f1fc12c
677c9d5
d0efcc3
267aa92
8d448c2
ee842db
330e91e
ef4bdd6
56562cf
2876245
1d422b5
071a5e1
cb89039
64ad916
9d7f4c0
eb1c59b
039f425
602001c
fbbb197
8cc34b7
709406c
6365656
36b4536
1e15258
34cc729
b0d603c
f9440da
126eec7
94f635f
4520639
ca0cb1f
62fce82
468fd09
80fe196
b0878ff
5df6415
6c946f2
ff31cb1
d01e0ae
63bf8ce
ac7af50
13ecefd
af05769
6c1abaa
7a69afd
9f06f0e
55cec6b
39bd52e
7c432c8
1d25613
7c799b5
4305c7a
0150ffd
312e78c
b436499
b995cc6
17a7cee
e353318
9184149
45d2b17
47402af
4047269
052dd49
77f5456
22ff4b0
bde7a62
b118b69
a4782c2
7177552
a2ecba2
99877cb
dabe3a9
a3b6f44
fbb03fc
6c047af
59ee8c4
f7c17c3
4114954
75a2167
4fda849
baa8d71
c926b28
460b02a
8017323
ce6aff9
e063618
cfe636e
71188bf
e833beb
a0e916c
471a547
09c63f1
076bf65
325186c
da33804
ae8be08
d58cafe
7a40f5a
c86a151
d73de8a
485f6a2
15050e8
2ce058a
84d102a
6ff6e41
4a2ffc8
6103bfa
bcc29f7
67a41dc
6b9ab76
d5514d5
7a1ae79
04df50a
cf90cd3
917b8c3
97bd3b3
fc4fd79
85a8e5a
632afe1
b569f0f
2a878b1
8e77d84
56b9d3e
762299a
a8d1f43
e1ff7f8
e426c11
f3229c9
e82ad38
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,63 +23,78 @@ jobs: | |
qa_docs: | ||
runs-on: ubuntu-20.04 | ||
steps: | ||
- name: "Checkout latest commit" | ||
- name: "Checkout latest PR commit" | ||
uses: actions/checkout@v2 | ||
- name: "Set up Python 3.8" | ||
- name: "Set up Python" | ||
uses: actions/setup-python@v2 | ||
with: | ||
# 3.8 is chosen because it seems to be the fastest for <3.9 | ||
# (3.9 excluded because it seems to be still very unstable) | ||
python-version: 3.8 | ||
- name: "Install dependencies" | ||
- name: "Update modules & install deps" | ||
# language=bash | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install tox | ||
- name: "Execute tox -e qa,docs" | ||
python -m pip install --upgrade pip setuptools wheel | ||
python setup.py develop | ||
- name: "flake8 Style Checking" | ||
# language=bash | ||
run: | | ||
tox -e qa,docs | ||
pip install colorama flake8 | ||
python -m flake8 aiosmtpd setup.py housekeep.py release.py | ||
- name: "Docs Checking" | ||
# language=bash | ||
run: | | ||
pip install colorama pytest pytest-mock sphinx sphinx-autofixture sphinx_rtd_theme | ||
pytest -v aiosmtpd/docs | ||
python setup.py build_sphinx | ||
- name: "Static Type Checking" | ||
# language=bash | ||
run: | | ||
pip install pytype | ||
pytype --keep-going --jobs auto . | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will NOT add this into tox.ini because currently |
||
- name: "Other QA Checks" | ||
# language=bash | ||
run: | | ||
pip install pytest pytest-mock check-manifest | ||
git fetch --no-tags --prune --no-recurse-submodules --depth=1 origin master:master | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line is needed because |
||
pytest -v aiosmtpd/qa | ||
check-manifest -v | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice tool, this; anyone knows a similar tool to double-check package health prior to pushing to PyPI? |
||
testing: | ||
needs: qa_docs | ||
strategy: | ||
# If a matrix fail, do NOT stop other matrix, let them run to completion | ||
fail-fast: false | ||
matrix: | ||
os: [ "ubuntu-18.04", "ubuntu-20.04", "macos-10.15" ] | ||
platform: [ "posix" ] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replaced with detection + env var setting in test step proper right before invoking pytest. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And it's now moot because we're using |
||
os: [ "ubuntu-18.04", "ubuntu-20.04", "macos-10.15", "windows-latest" ] | ||
python-version: [ "3.6", "3.7", "3.8", "3.9", "pypy3" ] | ||
include: | ||
- os: "windows-latest" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's just run GA's Windows runner for all supported Python versions. IIRC this "run just one version on Windows" decision stemmed from the need to be frugal with Travis CI minutes; GA's limits is quite lenient. |
||
platform: "mswin" | ||
# Only the latest frozen branch as indicated on | ||
# https://devguide.python.org/#branchstatus | ||
# ('frozen' means Status == "security") | ||
# Reason being that Windows users can change their Python anytime, | ||
# so there is no benefit in testing all released Python versions. | ||
# Plus pypy3 implementation in Windows is ... complicated. We | ||
# should stay away from all those complications; users choosing to | ||
# run aiosmtpd on pypy3 on Windows should be considered advanced | ||
# and know what they're doing. | ||
python-version: "3.7" | ||
runs-on: ${{ matrix.os }} | ||
steps: | ||
- name: "Checkout latest commit" | ||
uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: 0 # Required by codecov/codecov-action@v1 | ||
- name: "Set up Python ${{ matrix.python-version }}" | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
- name: "Install dependencies" | ||
# language=bash | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install tox | ||
- name: "Execute tox" | ||
env: | ||
PLATFORM: ${{ matrix.platform }} | ||
# "py" testenv means we'll use whatever Python provided by GA, | ||
# as specified in 'matrix' above. No need to specify exact version. | ||
python -m pip install --upgrade pip setuptools wheel | ||
# Test deps | ||
pip install colorama coverage[toml] coverage-conditional-plugin packaging pytest pytest-cov pytest-mock | ||
# Package deps | ||
python setup.py develop | ||
# Fetch master because some test cases might need its existence | ||
git fetch --no-tags --prune --no-recurse-submodules --depth=1 origin master:master | ||
- name: "Execute testing" | ||
shell: bash | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, Windows Runners on GA do support |
||
# language=bash | ||
run: | | ||
tox -e py-cov | ||
pytest --cov --cov-report=xml --cov-report=term | ||
- name: "Report to codecov" | ||
# Ubuntu 18.04 came out of the box with 3.6, and LOTS of system are still running | ||
# 18.04 happily, so we choose this as the 'canonical' code coverage testing. | ||
# One day we'll have to revisit this and bump the version ... | ||
if: always() && matrix.python-version == '3.6' && matrix.os == 'ubuntu-latest' | ||
if: matrix.python-version == '3.6' && matrix.os == 'ubuntu-18.04' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Explicit pointing to ubuntu-18.04 because ubuntu-latest is transitioning to 20.04 |
||
uses: codecov/codecov-action@v1 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ parts | |
coverage | ||
eggs | ||
sources | ||
build | ||
build/ | ||
dist | ||
venv | ||
.installed.cfg | ||
|
@@ -32,5 +32,6 @@ coverage-*.xml | |
diffcov.html | ||
diffcov-*.html | ||
.python-version | ||
prof/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the work directory for pytest-profiling. |
||
.pytype/ | ||
~temp* |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
graft aiosmtpd | ||
include LICENSE *.cfg *.ini *.py *.rst *.yml *.toml | ||
include LICENSE NOTICE *.cfg *.ini *.py *.rst *.yml *.toml | ||
global-exclude *.py[oc] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -142,6 +142,10 @@ You can also add the ``-s``/``--capture=no`` option to show output, e.g.:: | |
|
||
$ tox -e py36-nocov -- -s | ||
|
||
and these options can be combined:: | ||
|
||
$ tox -e py36-nocov -- -x -s <testname> | ||
|
||
(The ``-e`` parameter is explained in the next section about 'testenvs'. | ||
In general, you'll want to choose the ``nocov`` testenvs if you want to show output, | ||
so you can see which test is generating which output.) | ||
|
@@ -194,23 +198,22 @@ have been configured and tested: | |
|
||
* ``docs`` | ||
|
||
Builds HTML documentation using Sphinx | ||
Builds HTML documentation using Sphinx. A `pytest doctest`_ will run prior to | ||
actual building of the documentation. | ||
|
||
|
||
Environment Variables | ||
------------------------- | ||
|
||
``PLATFORM`` | ||
~~~~~~~~~~~~~~~~ | ||
``ASYNCIO_CATCHUP_DELAY`` | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Used on non-POSIX operating systems to specify tests to skip. | ||
Valid values: | ||
Due to how asyncio event loop works, some actions do not instantly get | ||
responded to. This is especially so on slower / overworked systems. | ||
In consideration of such situations, some test cases invoke a slight | ||
delay to let the event loop catch up. | ||
|
||
+-----------+-------------------------------------------------------+ | ||
| ``mswin`` | when running tox on Microsoft Windows (non-Cygwin) | | ||
+-----------+-------------------------------------------------------+ | ||
| ``wsl`` | when running tox on Windows Subsystem for Linux (WSL) | | ||
+-----------+-------------------------------------------------------+ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed because |
||
Defaults to `0.1` and can be set to any float value you want. | ||
|
||
|
||
Different Python Versions | ||
|
@@ -233,27 +236,36 @@ versions on your system by using ``pyenv``. General steps: | |
Python interpreter versions you want to make available to tox (see pyenv's | ||
documentation about this file) | ||
|
||
**Tip:** The 1st line of ``.python-version`` indicates your *preferred* Python version | ||
which will be used to run tox. | ||
|
||
5. Invoke tox with the option ``--tox-pyenv-no-fallback`` (see tox-pyenv's | ||
documentation about this option) | ||
|
||
|
||
``housekeep.py`` | ||
------------------- | ||
---------------- | ||
|
||
If you ever need to 'reset' your repo, you can use the ``housekeep.py`` utility | ||
like so:: | ||
|
||
$ python housekeep.py superclean | ||
|
||
It is `strongly` recommended to NOT do superclean too often, though. | ||
It is *strongly* recommended to NOT do superclean too often, though. | ||
Every time you invoke ``superclean``, | ||
tox will have to recreate all its testenvs, | ||
and this will make testing `much` longer to finish. | ||
and this will make testing *much* longer to finish. | ||
|
||
``superclean`` is typically only needed when you switch branches, | ||
or if you want to really ensure that artifacts from previous testing sessions | ||
won't interfere with your next testing sessions. | ||
|
||
For example, you want to force Sphinx to rebuild all documentation. | ||
Or, you're sharing a repo between environments (say, PSCore and Cygwin) | ||
and the cached Python bytecode messes up execution | ||
(e.g., sharing the exact same directory between Windows PowerShell and Cygwin | ||
will cause problems as Python becomes confused about the locations of the source code). | ||
|
||
|
||
License | ||
======= | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,7 +24,8 @@ div.body h4 { | |
} | ||
|
||
.pre, pre, code { | ||
font-family: Menlo,Consolas,"Ubuntu Mono",Inconsolata,"Bitstream Vera Sans Mono","lucida console","Courier New",monospace; | ||
font-family: "Fira Code",Menlo,Consolas,"Ubuntu Mono",Inconsolata,"Bitstream Vera Sans Mono","lucida console","Courier New",monospace; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm a great big fan of the Fira Code open-source font and I think everyone should use that :D |
||
font-size: 90%; | ||
} | ||
|
||
div.highlight pre { | ||
|
@@ -51,3 +52,7 @@ div#news-for-aiosmtpd h3 { | |
em.sig-param > span.default_value, em.sig-param > span.o { | ||
color: rgb(128, 128, 128); | ||
} | ||
|
||
a { | ||
text-decoration: underline dotted !important; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
# Copyright 2014-2021 The aiosmtpd Developers | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
__version__ = "1.3.0a4" | ||
__version__ = "1.3.0a9" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
from aiosmtpd.main import main | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,18 @@ | ||
# Copyright 2014-2021 The aiosmtpd Developers | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
import asyncio | ||
import os | ||
import ssl | ||
import asyncio | ||
import threading | ||
|
||
from aiosmtpd.smtp import SMTP | ||
from contextlib import ExitStack | ||
from public import public | ||
from socket import create_connection | ||
from typing import Any, Coroutine, Dict, Optional | ||
from warnings import warn | ||
|
||
from public import public | ||
|
||
from aiosmtpd.smtp import SMTP | ||
|
||
AsyncServer = asyncio.base_events.Server | ||
|
||
|
@@ -50,9 +51,11 @@ def __init__( | |
port=8025, | ||
*, | ||
ready_timeout=1.0, | ||
enable_SMTPUTF8=None, | ||
ssl_context: ssl.SSLContext = None, | ||
server_kwargs: Dict[str, Any] = None | ||
# SMTP parameters | ||
server_hostname: str = None, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need a kwarg that does NOT conflict with In 2.0 we'll drop |
||
server_kwargs: Dict[str, Any] = None, | ||
**SMTP_parameters, | ||
): | ||
""" | ||
`Documentation can be found here | ||
|
@@ -64,23 +67,28 @@ def __init__( | |
self.port = port | ||
self.ssl_context = ssl_context | ||
self.loop = asyncio.new_event_loop() if loop is None else loop | ||
self.ready_timeout = os.getenv("AIOSMTPD_CONTROLLER_TIMEOUT", ready_timeout) | ||
self.server_kwargs: Dict[str, Any] = server_kwargs or {} | ||
if enable_SMTPUTF8 is not None: | ||
# Uncomment next lines when we hit 1.3 | ||
# warn("enable_SMTPUTF8 will be removed in the future. " | ||
# "Please use server_kwargs instead.", DeprecationWarning) | ||
self.server_kwargs["enable_SMTPUTF8"] = enable_SMTPUTF8 | ||
else: | ||
# This line emulates previous behavior of defaulting enable_SMTPUTF8 to | ||
# True. Which actually kinda conflicts with SMTP class's default, but it's | ||
# explained in the documentation. | ||
self.server_kwargs.setdefault("enable_SMTPUTF8", True) | ||
self.ready_timeout = os.getenv( | ||
'AIOSMTPD_CONTROLLER_TIMEOUT', ready_timeout) | ||
if server_kwargs: | ||
warn( | ||
"server_kwargs will be removed in version 2.0. " | ||
"Just specify the keyword arguments to forward to SMTP " | ||
"as kwargs to this __init__ method.", | ||
DeprecationWarning | ||
) | ||
self.SMTP_kwargs: Dict[str, Any] = server_kwargs or {} | ||
self.SMTP_kwargs.update(SMTP_parameters) | ||
if server_hostname: | ||
self.SMTP_kwargs["hostname"] = server_hostname | ||
# Emulate previous behavior of defaulting enable_SMTPUTF8 to True | ||
# It actually conflicts with SMTP class's default, but the reasoning is | ||
# discussed in the docs. | ||
self.SMTP_kwargs.setdefault("enable_SMTPUTF8", True) | ||
|
||
def factory(self): | ||
"""Allow subclasses to customize the handler/server creation.""" | ||
return SMTP( | ||
self.handler, **self.server_kwargs | ||
self.handler, **self.SMTP_kwargs | ||
) | ||
|
||
def _factory_invoker(self): | ||
|
@@ -112,14 +120,14 @@ def _run(self, ready_event): | |
srv_coro | ||
) | ||
self.server = srv | ||
except Exception as error: # pragma: nowsl | ||
except Exception as error: # pragma: on-wsl | ||
# Usually will enter this part only if create_server() cannot bind to the | ||
# specified host:port. | ||
# | ||
# Somehow WSL1.0 (Windows Subsystem for Linux) allows multiple | ||
# Somehow WSL 1.0 (Windows Subsystem for Linux) allows multiple | ||
# listeners on one port?! | ||
# That is why we add "pragma: nowsl" there, so when testing on | ||
# WSL we can specify "PLATFORM=wsl". | ||
# That is why we add "pragma: on-wsl" there, so this block will not affect | ||
# coverage on WSL 1.0. | ||
self._thread_exception = error | ||
return | ||
self.loop.call_soon(ready_event.set) | ||
|
@@ -149,8 +157,9 @@ def start(self): | |
self._thread.start() | ||
# Wait a while until the server is responding. | ||
ready_event.wait(self.ready_timeout) | ||
if self._thread_exception is not None: # pragma: nowsl | ||
if self._thread_exception is not None: # pragma: on-wsl | ||
# See comment about WSL1.0 in the _run() method | ||
assert self._thread is not None # Stupid LGTM.com; see github/codeql#4918 | ||
raise self._thread_exception | ||
# Apparently create_server invokes factory() "lazily", so exceptions in | ||
# factory() go undetected. To trigger factory() invocation we need to open | ||
|
@@ -171,7 +180,7 @@ def _stop(self): | |
self.loop.stop() | ||
try: | ||
_all_tasks = asyncio.all_tasks | ||
except AttributeError: # pragma: skipif_gt_py36 | ||
except AttributeError: # pragma: py-gt-36 | ||
_all_tasks = asyncio.Task.all_tasks | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apparently Python 3.8 raises So we invert the attribute access. |
||
for task in _all_tasks(self.loop): | ||
task.cancel() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Unfolding" tox into separate, direct invocation of test stuff should make GA checks faster as the runner no longer has to first create virtualenvs.
The drawback is of course if the steps within tox.ini changes, we have to edit the GA steps as well, but I don't think we'll be changing them any time soon after this heavylift transition to pure pytest.