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

Migrate tool settings from setup.cfg to pyproject.toml #363

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .github/workflows/unit-testing-and-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@ on:
branches: [ "master" ]
paths:
- "aiosmtpd/**"
- "setup.cfg" # To monitor changes in dependencies
- "pyproject.toml" # To monitor changes in dependencies
# This is for PRs
pull_request:
branches: [ "master" ]
paths:
- "aiosmtpd/**"
- "setup.cfg" # To monitor changes in dependencies
- "pyproject.toml" # To monitor changes in dependencies
# Manual/on-demand
workflow_dispatch:
Expand All @@ -38,7 +36,7 @@ jobs:
# language=bash
run: |
python -m pip install --upgrade pip setuptools wheel
python setup.py develop
python -m pip install .
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should that be install -e .?

that's more equivalent to develop

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe? Ahaha this "install using pyproject.toml" is so new to me 😅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, -e would be the direct equivalent.

# Common deps
pip install colorama
- name: "flake8 Style Checking"
Expand All @@ -53,7 +51,9 @@ jobs:
"print(config['flake8_plugins']['deps']);"
)
pip install "flake8>=5.0.4" $(python -c "${grab_f8_plugins[*]}")
python -m flake8 aiosmtpd setup.py housekeep.py release.py
echo "Running flake8 ... there will be no output if no errors:"
python -m flake8 aiosmtpd housekeep.py release.py
echo "flake8 done."
Comment on lines +54 to +56
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added just to ensure that flake8 actually runs. flake8's silence on no error sometimes make me wonder if it ran or not 😅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW it's quite common to wrap linters with the pre-commit.com too.

- name: "Docs Checking"
# language=bash
run: |
Expand All @@ -69,6 +69,8 @@ jobs:
pip install dnspython argon2-cffi
# Install pytype
pip install pytype
# List files & dirs so if pytype blows up we can see what else to exclude
ls -la
pytype --keep-going --jobs auto .
- name: "Other QA Checks"
shell: bash
Expand Down Expand Up @@ -110,7 +112,7 @@ jobs:
# Test deps
pip install colorama "coverage>=7.0.1" coverage[toml] "coverage-conditional-plugin>=0.5.0" packaging pytest pytest-cov pytest-mock
# Package deps
python setup.py develop
python -m pip install .
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question here, -e?

- name: "Security checking"
# language=bash
run: |
Expand Down
5 changes: 3 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,12 @@ You can also request help by submitting a question on StackOverflow.
Building
========

You can install this package in a virtual environment like so::
You can install this package -- after cloning -- in a virtual environment like so::

$ python3 -m venv /path/to/venv
$ source /path/to/venv/bin/activate
$ python setup.py install
$ python -m pip install -U pip setuptools
$ python -m pip install .
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think here we should definitely recommend editable mode, if we're suggesting folks clone flr dev. Otherwise they can just install from pypi

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before. Let me do some study / experiments.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pepoluan feel free to ask me if you have questions about Python packaging. I maintain PyPUG.


This will give you a command line script called ``aiosmtpd`` which implements the
SMTP server. Use ``aiosmtpd --help`` for a quick reference.
Expand Down
2 changes: 1 addition & 1 deletion aiosmtpd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import warnings


__version__ = "1.4.4"
__version__ = "1.5.0a1"


def _get_or_new_eventloop() -> asyncio.AbstractEventLoop:
Expand Down
1 change: 1 addition & 0 deletions aiosmtpd/docs/NEWS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Fixed/Improved
--------------
* All Controllers now have more rationale design, as they are now composited from a Base + a Mixin
* A whole bunch of annotations
* Stop using ``setup.cfg`` and use ``pyproject.toml`` instead


1.4.4 (2023-01-13)
Expand Down
142 changes: 142 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,67 @@
# region #### Project metadata ##########

[project]
name = "aiosmtpd"
requires-python = ">=3.7"
dynamic = [ "version" ]
description = "aiosmtpd - asyncio based SMTP server"
readme = "DESCRIPTION.rst"
urls."Home Page" = "https://aiosmtpd.readthedocs.io/"
urls."Bug Tracker" = "https://github.com/aio-libs/aiosmtpd/issues"
urls."Documentation" = "https://aiosmtpd.readthedocs.io/"
urls."Source Code" = "https://github.com/aio-libs/aiosmtpd"
maintainers = [
{ name = "The aiosmtpd Developers", email = "[email protected]"}
]
keywords = [ "email", "smtpd", "smtp", "async" ]
license.file = "LICENSE"
classifiers = [
"License :: OSI Approved",
"License :: OSI Approved :: Apache Software License",
"Intended Audience :: Developers",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX :: BSD :: FreeBSD",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Communications :: Email :: Mail Transport Agents",
"Framework :: AsyncIO",
]
dependencies = [
"atpublic",
"attrs",
"typing-extensions ; python_version < '3.8'",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are typing extensions require to run 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.

iirc it's to implement Protocol, I think that's in the Tproxy code.

Not really sure if that's actually needed to just run ...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming that it's not needed for running we can put it in an extras_require (yeah, not extra_requires) section. I'm not sure what the precise form is for that, tho.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that were true, it should be here, not in extras. FWIW it's only used in tests:

from typing_extensions import Protocol
. Judging by the lack of it in runtime code, it might be fine to drop it from the tests and deps.

]

[project.scripts]
aiosmtpd = "aiosmtpd.main:main"

[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

# endregion

# region #### setuptools settings ##########

[tool.setuptools]
zip-safe = false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it unsafe?


[tool.setuptools.dynamic]
version = { attr = "aiosmtpd.__version__" }

[tool.setuptools.packages.find]
where = ["."]
include = ["aiosmtpd*"]

# endregion

[tool.pytest.ini_options]
addopts = """--strict-markers -rfEX"""
markers = [
Expand Down Expand Up @@ -82,3 +142,85 @@ known_local_folder = [
"aiosmtpd"
]
combine_as_imports = true


[tool.flake8]
max-line-length = 88
select = ["E", "F", "W", "C90", "C4", "MOD", "JS", "PIE", "PT", "SIM", "ECE", "C801", "DUO", "TAE", "ANN", "YTT", "N400"]
ignore = [
# black conflicts with E123 & E133
"E123",
"E133",
# W503 conflicts with PEP8...
"W503",
# W293 is a bit too noisy. Many files have been edited using editors that do not remove spaces from blank lines.
"W293",
# Sometimes spaces around colons improve readability
"E203",
# Sometimes we prefer the func()-based creation, not literal, for readability
"C408",
# Sometimes we need to catch Exception broadly
"PIE786",
# We don't really care about pytest.fixture vs pytest.fixture()
"PT001",
# Good idea, but too many changes. Remove this in the future, and create separate PR
"PT004",
# Sometimes exception needs to be explicitly raised in special circumstances, needing additional lines of code
"PT012",
# I still can't grok the need to annotate "self" or "cls" ...
"ANN101",
"ANN102",
# I don't think forcing annotation for *args and **kwargs is a wise idea...
"ANN002",
"ANN003",
# We have too many "if..elif..else: raise" structures that does not convert well to "error-first" design
"SIM106",
# We have too many 'Any' type annotations.
"ANN401",
# Classes for some reason aren't always just replaceable by modules.
"PIE798",
# It is cleaner sometimes to assign and return, especially when using 'await' expressions.
"PIE781",
# Use f'strings instead of % formatters, the performance impact isn't too bad and f'strings are awesome!
"PIE803",
# It is more readable to instantiate and add items on-by-one instead of all at once.
"PIE799",
# Explicit is better than implicit, range(0, val) is more explicit than range(val).
"PIE808",
]
per-file-ignores = [
"aiosmtpd/tests/test_*:ANN001",
"aiosmtpd/tests/test_proxyprotocol.py:DUO102",
"aiosmtpd/docs/_exts/autoprogramm.py:C801",
]
# flake8-coding
no-accept-encodings = true
# flake8-copyright
copyright-check = true
# The number below was determined empirically by bisecting from 100 until no copyright-unnecessary files appear
copyright-min-file-size = 44
copyright-author = "The aiosmtpd Developers"
# flake8-annotations-complexity
max-annotations-complexity = 4
# flake8-annotations-coverage
min-coverage-percents = 12
# flake8-annotations
mypy-init-return = true
suppress-none-returning = true
suppress-dummy-args = true
allow-untyped-defs = true


[tool.pytype]
exclude = [
"aiosmtpd/docs/_exts/*",
"_dump/*",
"aiosmtpd.egg-info/*",
"build/*",
"dist/*",
"Lib/*",
"Scripts/*",
]
disable = [
"not-supported-yet",
]
18 changes: 12 additions & 6 deletions release.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@
f"dist/aiosmtpd-{ver_str}-py3-none-any.whl",
]

RELEASE_TOOLKIT = ["setuptools", "wheel", "twine", "build"]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

build is the new build system created by PyPA that supports PEP 517.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. You need build for making dists and twine for linting them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, PyPI no longer supports GPG. It's possible to use Sigstore, though.

My PyPUG article has an example of that: https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
RELEASE_TOOLKIT = ["setuptools", "wheel", "twine", "build"]
RELEASE_TOOLKIT = ["build", "twine"]


printfl("Updating release toolkit first...", end="")
run_hidden([sys.executable] + shlex.split("-m pip install -U setuptools wheel twine"))
run_hidden(
[sys.executable] + shlex.split("-m pip install -U") + RELEASE_TOOLKIT
)
print()

printfl("Checking extra toolkit...", end="")
Expand Down Expand Up @@ -91,10 +95,12 @@

try:
# Let's use *this* python to build, please
print("### setup.py sdist")
subprocess.run([sys.executable, "setup.py", "sdist"], check=True)
print("### setup.py sdist")
subprocess.run([sys.executable, "setup.py", "bdist_wheel"], check=True)
# print("### setup.py sdist")
# subprocess.run([sys.executable, "setup.py", "sdist"], check=True)
# print("### setup.py sdist")
# subprocess.run([sys.executable, "setup.py", "bdist_wheel"], check=True)
print("### build (sdist and wheel")
subprocess.run([sys.executable, "-m", "build"])
for f in DISTFILES:
assert Path(f).exists(), f"{f} is missing!"

Expand All @@ -116,7 +122,7 @@
if has_verify:
print("Waiting for package to be received by PyPI...", end="")
for i in range(10, 0, -1):
printfl(i, end="..")
printfl(i, end="..", flush=True)
time.sleep(1.0)
print()
twine_verif = ["twine", "verify_upload"] + DISTFILES
Expand Down
Loading