-
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
Code Hygiene #259
Code Hygiene #259
Conversation
Codecov Report
@@ Coverage Diff @@
## master #259 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 7 7
Lines 1656 1686 +30
Branches 306 307 +1
=========================================
+ Hits 1656 1686 +30
Continue to review full report at Codecov.
|
# A bunch of flake8 plugins... | ||
grab_f8_plugins=( | ||
"from configparser import ConfigParser;" | ||
"config = ConfigParser();" | ||
"config.read('tox.ini');" | ||
"print(config['flake8_plugins']['deps']);" | ||
) | ||
pip install colorama flake8 $(python -c "${grab_f8_plugins[*]}") |
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.
Figured out a way to tox.ini the SSOT for GA 😉
All checks green here and in my local test systems. However, I'm keeping this draft until 1.4.1 gets released. |
7ff1957
to
f0bffca
Compare
Selection criteria: * Must be useful, even if many warnings For example: Plugins related to annotations. As @warsaw raised in aio-libs#128, it's a good idea to type-annotate as much as possible. * If not simple, must be maintained "maintained" here is overly-simplified to mean only "master has an update in 2020 or later". Some plugins have not received updates for a long time, but their logic are simple and really does not need updates, so those can also be included on a case-by-case basis. * Will not need significant change in logic Adding annotations, removing temp vars used just for return values, those are not logic changes. So even if lots of instances need to be fixed, that is okay. Plugins that need a restructurization of the logic flow (e.g., "flake8-cognitive-complexity") should not be included; or, if included, should not be activated. At least not until the next Epic.
* Exclude all test modules from ANN001 because there are simply too many test cases to annotate :sweatsmile: * To partially compensate, we put in flake8-annotations-coverage * Finally, activate some leniency for flake8-annotations
As much as possible take care of TAE* and ANN* complaints.
No longer using %-formatting
Because many test modules are now annotated and pulls in some type hints from pytest_mock, and with no pytest-mock install autofixture raises some errors.
After some thinking I don't think this is that useful for aiosmtpd.
For autoprogramm.py, we excluded that from C801 because it's not really our code; we just adopt & adapt it (as allowed per license)
Apparently multiprocessing.Event is "just" a Callable, and pytype balked at that. The class proper is multiprocessing.synchronize.Event, which we import as MP_Event.
Conflicts with the Message handler
For unknown reasons, pytype now balked at importing these two funcs. Because the funcs are simple "shims" anyways, I decided to just inline them.
Too many pragmas to add.
Mostly annotations in the new (Base) Classes. Also one instance of func()-instead-of-compre.
Also allows bytearray.
Because, as the documentation explicitly mentions, aiosmtpd.handlers .Message _is_ an abstract base class and "must be subclassed" Previously, this "abc" status had never been enforced. The code hygiene push applies the abc.ABCMeta to the abstract base classes, resulting in failure of some test cases because they tried to instantiate the abc's.
Note: AST100 warnings (usage of assert) needs to be disabled via project configuration.
Bogged down due to trying to figure out the b0rkeness of #265 Will rebase & marinate today. |
Use the renamed import instead to fully disambiguate between email .message.Message and aiosmtpd.handlers.Message (which has been rename-imported as "AbstractMessageHandler")
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.
Here are some comments for possibly interesting decision points
import re | ||
import smtplib | ||
import sys | ||
from abc import ABCMeta, abstractmethod | ||
from email import message_from_bytes, message_from_string | ||
from argparse import ArgumentParser | ||
from email.message import Message as Em_Message |
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.
Need to rename-import because email.message.Message conflicts with the Message
handler defined in this module
from email import message_from_bytes, message_from_string | ||
from argparse import ArgumentParser | ||
from email.message import Message as Em_Message | ||
from email.parser import BytesParser, Parser |
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.
Import these because some validators (pytype? I forgot which exactly) seems can't grok that we're importing message_from_bytes
and message_from_string
functions. Upon checking their definitions (see below comment) I decided to just import these two classes and copy the wrapper funcs.
def message_from_bytes(s, *args, **kws): | ||
return BytesParser(*args, **kws).parsebytes(s) | ||
|
||
|
||
def message_from_string(s, *args, **kws): | ||
return Parser(*args, **kws).parsestr(s) |
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.
See previous comment about validators now grokking importation of these two funcs from email.parser
. The two funcs are apparently thin wrappers around *Parser(...).parseXXX(...)
, so I just 'inlined' them here.
__all__ = [ | ||
__all__ = ["struct", "partial", "IPv4Address", "IPv6Address"] | ||
__all__.extend( | ||
k for k in globals().keys() if k.startswith("V1_") or k.startswith("V2_") | ||
] + ["struct", "partial", "IPv4Address", "IPv6Address"] | ||
) |
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.
One of the validators puked at that list combining op.
|
||
import pytest | ||
|
||
from aiosmtpd.controller import Controller | ||
from aiosmtpd.handlers import AsyncMessage, Debugging, Mailbox, Proxy, Sink | ||
from aiosmtpd.handlers import Message as AbstractMessageHandler |
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.
Disambiguate with email.message.Message
(which actually has been rename-imported to Em_Message
, but let's just be very very clear)
class MessageHandler(AbstractMessageHandler): | ||
def handle_message(self, message: Em_Message) -> None: | ||
pass |
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.
because aiosmtpd.handler.Message
has been marked as an ABC, we can't use it directly without raising some qa errors. This is a simple concretion of the ABC for use in this test module.
@@ -10,11 +10,14 @@ envdir = | |||
py37: {toxworkdir}/3.7 | |||
py38: {toxworkdir}/3.8 | |||
py39: {toxworkdir}/3.9 | |||
py310: {toxworkdir}/3.10 |
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.
Early forays into 3.10. This is actually excluded from the envlist, so just for experimental testing purposes.
# Bandit is not needed on diffcov, and seems to be incompatible with 310 | ||
# So, run only if "not (310 or diffcov)" ==> "(not 310) and (not diffcov)" | ||
!py310-!diffcov: bandit -c bandit.yml -r aiosmtpd |
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.
In tox
logic, the 'and' operator - bounds less tightly than the 'no' operator !
[flake8_plugins] | ||
# This is a pseudo-section that feeds into [testenv:qa] and GA | ||
# Snippets of letters above these plugins are tests that need to be "select"-ed in flake8 config (in | ||
# setup.cfg) to activate the respective plugins. If no snippet is given, that means the plugin is | ||
# always active. | ||
deps = | ||
flake8-bugbear | ||
flake8-builtins | ||
flake8-coding | ||
# C4 | ||
flake8-comprehensions | ||
# JS | ||
flake8-multiline-containers | ||
# PIE | ||
flake8-pie | ||
# MOD | ||
flake8-printf-formatting | ||
# PT | ||
flake8-pytest-style | ||
# SIM | ||
flake8-simplify | ||
# Cognitive Complexity looks like a good idea, but to fix the complaints... it will be an epic effort. | ||
# So we disable it for now and reenable when we're ready, probably just before 2.0 | ||
# # CCR | ||
# flake8-cognitive-complexity | ||
# ECE | ||
flake8-expression-complexity | ||
# C801 | ||
flake8-copyright | ||
# DUO | ||
dlint | ||
# TAE | ||
flake8-annotations-complexity | ||
# TAE | ||
flake8-annotations-coverage | ||
# ANN | ||
flake8-annotations | ||
# YTT | ||
flake8-2020 | ||
# N400 | ||
flake8-broken-line |
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.
Extracted into a separate config section for easier reuse. Most notably the extraction code in the GA yml.
All checks green. Undrafting this and marinate for at least a day. |
Depends on #256 ; please merge that first and rebase this to master afterwards.
This PR will remain a draft until then.
What do these changes do?
Activates a lot of flake8 plugins. Then implement a whole bunch of fixes to make them all pass.
This is a partial answer to #128 , although purposefully staying away from outright mypy implementation (because I find some of mypy's demands to be impractical and/or inane).
Are there changes in behavior for the user?
None.
Related issue number
As mentioned, related to #128 although does not close that fully.
Checklist
NEWS.rst
file