Scaffolding
Pyproject.toml
Use poetry init to generate a pyproject.toml if you don't have one already.
Run it from the repo root (it won't make a repo folder for you), or
run poetry new instead for brand new projects.
Here's a basic package setup for poetry.
When Poetry supports PEP-621 and PEP-631 some of these should be moved to [project] instead of [tool.poetry]. See this issue.
[tool.poetry]
name = "..." # Name of the package
version = "0.1.0"
requires-python = "3.9"
description = "..." # A short description
authors = ["Eivind Fonn <evfonn@gmail.com>"]
maintainers = ["Eivind Fonn <evfonn@gmail.com>"]
license = "..." # I like LGPL-3.0-or-later
readme = "..." # A filename in the root directory
homepage = "..." # A githubpages URL or just the github URL
repository = "..." # The github repo URL
documentation = "..." # To githubpages if there is one
classifiers = [] # See https://pypi.org/classifiers/
# Add a classifier for the license too!
include = [
"...", # Path to a file to include when building
{ # Or like this, where format is
path = "...", # "sdist" or "wheel" or both
format = [],
},
]
# This is the entry point that pip and other tools use.
# This is what invokes poetry to do the building.
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
Compiled modules
Adding Cython modules is relatively easy.
Add setuptools to build-system.requires, then add this section.
[tool.poetry.build]
generate-setup-file = true
script = "build.py"
Then the build.py file needs to provide for the Cython extension.
from setupools import Extension
from Cython.Build import cythonize
def build(setup_kwargs):
setup_kwargs['ext_modules'] = cythonize(
Extension("module", ["source.pyx"])
)
Basically just update setup_kwargs as if you were using setuptools directly.
Dependencies
Add dependencies from the command line:
poetry add dependency
poetry add --group dev dependency
poetry add --optional -E extra -E extra dependency
You can also specify that the dependency is required for certain combinations of Python version and/or platform. See poetry documentation for more details.
For specifying version requirements it's probably best to use ^ or ~.
Use dep^version to require at least that version or later, but not a new major version number.
Use dep~version to require at least that version or later, but not a new minor version number.
It's good to regularly run poetry update to update dependencies.
When Poetry supports PEP-621 and PEP-631 dependencies should be moved to [project] instead of [tool.poetry].
Development dependencies
The following packages should basically always be added as dev dependencies: ruff, mypy, pytest.
Pytest
For now you can configure pytest like this. Although there isn't that much to do to be honest.
[tool.pytest.ini_options]
testpaths = ["...", "..."]
When Pytest adds proper pyproject.toml support, options in the [tool.pytest] namespace will be supported as well.
Mypy
Here's a basic mypy configuration that should be ok to start with.
[tool.mypy]
plugins = ["numpy.typing.mypy_plugin"] # If the package uses numpy heavily
files = ["source/**/*.py"] # Saves having to specify paths at the CLI
disallow_untyped_defs = true
disallow_any_unimported = true
no_implicit_optional = true
check_untyped_defs = true
warn_return_any = true
show_error_codes = true
# Add path to stubs directory if you need to write stubs
mypy_path = "$MYPY_CONFIG_FILE_DIR/stubs"
You can add more specific module-level instructions by adding to tool.mypy.overrides:
[[tool.mypy.overrides]]
module = "some.module.path"
ignore_errors = true
Ruff
Use ruff both as a linter and as a formatter. See here for a full list of rules. It's probably a good idea to select per project what might be most useful.
[tool.ruff]
line-length = 110
exclude = [] # List of files to ignore (these are paths, not modules)
[tool.ruff.lint]
select = [
"F", # Pyflakes rules
"W", # PyCodeStyle warnings
"E", # PyCodeStyle errors
"I", # Sort imports properly
"UP", # Warn if certain things can changed due to newer Python versions
"C4", # Catch incorrect use of comprehensions, dict, list, etc
"FA", # Enforce from __future__ import annotations
"ISC", # Good use of string concatenation
"ICN", # Use common import conventions
"RET", # Good return practices
"SIM", # Common simplification rules
"TID", # Some good import practices
"TCH", # Enforce importing certain types in a TYPE_CHECKING block
"PTH", # Use pathlib instead of os.path
"TD", # Be diligent with TODO comments
"NPY", # Some numpy-specific things
]
ignore = [
"E741", # Ambiguous variable name
"UP007", # Only if your project targets Python 3.9 or earlier
"SIM115", # Complains if we use __enter__ inside an __enter__ method
"ISC001", # Conflicts with rust formatting
"TD003", # Issue links for each todo comment
]
No Comments