Skip to content
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

Merged
merged 39 commits into from
Mar 23, 2021
Merged

Code Hygiene #259

merged 39 commits into from
Mar 23, 2021

Conversation

pepoluan
Copy link
Collaborator

@pepoluan pepoluan commented Mar 2, 2021

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

  • I think the code is well written
  • Unit tests for the changes exist
  • tox testenvs have been executed in the following environments:
    • Windows 10 (via PyCharm tox runner)
    • Windows 10 (via PSCore 7.1.2)
    • Windows 10 (via Cygwin)
    • Ubuntu 18.04 on WSL 1.0
    • FreeBSD 12.2 on VBox
    • OpenSUSE Leap 15.2 on VBox
  • Documentation reflects the changes
  • Add a news fragment into the NEWS.rst file

@pepoluan pepoluan added tech-debt Things that needs to be tidied up to avoid being bitten in the future... documentation labels Mar 2, 2021
@pepoluan pepoluan added this to the 1.5 milestone Mar 2, 2021
@pepoluan pepoluan self-assigned this Mar 2, 2021
@codecov
Copy link

codecov bot commented Mar 2, 2021

Codecov Report

Merging #259 (641de3d) into master (747a7c4) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##            master      #259   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            7         7           
  Lines         1656      1686   +30     
  Branches       306       307    +1     
=========================================
+ Hits          1656      1686   +30     
Impacted Files Coverage Δ
aiosmtpd/__init__.py 100.00% <100.00%> (ø)
aiosmtpd/controller.py 100.00% <100.00%> (ø)
aiosmtpd/handlers.py 100.00% <100.00%> (ø)
aiosmtpd/lmtp.py 100.00% <100.00%> (ø)
aiosmtpd/main.py 100.00% <100.00%> (ø)
aiosmtpd/proxy_protocol.py 100.00% <100.00%> (ø)
aiosmtpd/smtp.py 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 747a7c4...641de3d. Read the comment docs.

Comment on lines +44 to +51
# 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[*]}")
Copy link
Collaborator Author

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 😉

aiosmtpd/__init__.py Outdated Show resolved Hide resolved
@pepoluan
Copy link
Collaborator Author

pepoluan commented Mar 2, 2021

All checks green here and in my local test systems. However, I'm keeping this draft until 1.4.1 gets released.

@pepoluan pepoluan mentioned this pull request Mar 5, 2021
11 tasks
@pepoluan pepoluan force-pushed the code-hygiene branch 4 times, most recently from 7ff1957 to f0bffca Compare March 8, 2021 14:20
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.
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.
@pepoluan
Copy link
Collaborator Author

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")
Copy link
Collaborator Author

@pepoluan pepoluan left a 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
Copy link
Collaborator Author

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
Copy link
Collaborator Author

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.

Comment on lines +47 to +52
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)
Copy link
Collaborator Author

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.

Comment on lines -76 to +80
__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"]
)
Copy link
Collaborator Author

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
Copy link
Collaborator Author

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)

Comment on lines +77 to +79
class MessageHandler(AbstractMessageHandler):
def handle_message(self, message: Em_Message) -> None:
pass
Copy link
Collaborator Author

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
Copy link
Collaborator Author

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.

Comment on lines +18 to +20
# 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
Copy link
Collaborator Author

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 !

Comment on lines +59 to +99
[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
Copy link
Collaborator Author

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.

@pepoluan
Copy link
Collaborator Author

All checks green. Undrafting this and marinate for at least a day.

@pepoluan pepoluan marked this pull request as ready for review March 22, 2021 05:48
@pepoluan pepoluan merged commit 1a1c1bb into aio-libs:master Mar 23, 2021
@pepoluan pepoluan deleted the code-hygiene branch March 24, 2021 03:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation tech-debt Things that needs to be tidied up to avoid being bitten in the future...
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant