Files
kleinanzeigen-bot/pyproject.toml

300 lines
10 KiB
TOML

# https://pip.pypa.io/en/stable/reference/build-system/pyproject-toml/
#
# SPDX-FileCopyrightText: © Sebastian Thomschke and contributors
# SPDX-License-Identifier: AGPL-3.0-or-later
# SPDX-ArtifactOfProjectHomePage: https://github.com/Second-Hand-Friends/kleinanzeigen-bot/
#
[build-system] # https://backend.pdm-project.org/
requires = ["pdm-backend"]
build-backend = "pdm.backend"
[project]
name = "kleinanzeigen-bot"
dynamic = ["version"]
description = "Command line tool to publish ads on kleinanzeigen.de"
readme = "README.md"
authors = [
{name = "sebthom", email = "sebthom@users.noreply.github.com"},
]
license = {text = "AGPL-3.0-or-later"}
classifiers = [ # https://pypi.org/classifiers/
"Private :: Do Not Upload",
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"Operating System :: OS Independent",
"Intended Audience :: End Users/Desktop",
"Topic :: Office/Business",
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10"
]
requires-python = ">=3.10,<3.14"
dependencies = [
"certifi",
"colorama",
"jaraco.text", # required by pkg_resources during runtime
"nodriver==0.39.0", # 0.40-0.44 have issues starting browsers and evaluating self.web_execute("window.BelenConf") fails
"ruamel.yaml",
"psutil",
"wcmatch",
]
[dependency-groups] # https://peps.python.org/pep-0735/
dev = [
# testing:
"pytest>=8.3.4",
"pytest-asyncio>=0.25.3",
"pytest-rerunfailures",
"pytest-cov>=6.0.0",
# linting:
"autopep8",
"ruff",
"mypy",
"pyright",
# packaging:
"pyinstaller",
"platformdirs", # required by pyinstaller
]
[project.urls]
Homepage = "https://github.com/Second-Hand-Friends/kleinanzeigen-bot"
Repository = "https://github.com/Second-Hand-Friends/kleinanzeigen-bot.git"
Documentation = "https://github.com/Second-Hand-Friends/kleinanzeigen-bot/README.md"
Issues = "https://github.com/Second-Hand-Friends/kleinanzeigen-bot/issues"
#####################
# pdm https://github.com/pdm-project/pdm/
#####################
[tool.pdm.version] # https://backend.pdm-project.org/metadata/#dynamic-project-version
source = "call"
getter = "version:get_version" # uses get_version() of <project_root>/version.py
write_to = "kleinanzeigen_bot/_version.py"
write_template = "__version__ = '{}'\n"
[tool.pdm.scripts] # https://pdm-project.org/latest/usage/scripts/
app = "python -m kleinanzeigen_bot"
compile.cmd = "python -O -m PyInstaller pyinstaller.spec --clean"
compile.env = {PYTHONHASHSEED = "1", SOURCE_DATE_EPOCH = "0"} # https://pyinstaller.org/en/stable/advanced-topics.html#creating-a-reproducible-build
debug = "python -m pdb -m kleinanzeigen_bot"
format = "autopep8 --recursive --in-place src tests --verbose"
lint = {shell = "ruff check && mypy && pyright" }
fix = {shell = "ruff check --fix" }
test = "python -m pytest --capture=tee-sys -v"
utest = "python -m pytest --capture=tee-sys -v -m 'not itest'"
itest = "python -m pytest --capture=tee-sys -v -m 'itest'"
#####################
# autopep8
# https://pypi.org/project/autopep8/
# https://github.com/hhatto/autopep8
#####################
[tool.autopep8]
max_line_length = 160
ignore = [ # https://github.com/hhatto/autopep8#features
"E124", # Don't change indention of multi-line statements
"E128", # Don't change indention of multi-line statements
"E231", # Don't add whitespace after colon (:) on type declaration
"E251", # Don't remove whitespace around parameter '=' sign.
"E401" # Don't put imports on separate lines
]
aggressive = 3
#####################
# ruff
# https://pypi.org/project/ruff/
# https://docs.astral.sh/ruff/configuration/
#####################
[tool.ruff]
include = ["pyproject.toml", "src/**/*.py", "tests/**/*.py"]
line-length = 160
indent-width = 4
target-version = "py310"
[tool.ruff.lint]
# https://docs.astral.sh/ruff/rules/
select = [
"A", # flake8-builtins
"ARG", # flake8-unused-arguments
"ANN", # flake8-annotations
"ASYNC", # flake8-async
#"BLE", # flake8-blind-except
"B", # flake8-bugbear
"C4", # flake8-comprehensions
#"COM", # flake8-commas
#"CPY", # flake8-copyright
"DTZ", # flake8-datetimez
#"EM", # TODO flake8-errmsg
#"ERA", # eradicate commented-out code
"EXE", # flake8-executable
"FA", # flake8-future-annotations
"FBT", # flake8-boolean-trap
"FIX", # flake8-fixme
"G", # flake8-logging-format
"ICN", # flake8-import-conventions
"ISC", # flake8-implicit-str-concat
"INP", # flake8-no-pep420
"INT", # flake8-gettext
"LOG", # flake8-logging
"PIE", # flake8-pie
"PT", # flake8-pytest-style
#"PTH", # flake8-use-pathlib
"PYI", # flake8-pyi
"Q", # flake8-quotes
"RET", # flake8-return
"RSE", # flake8-raise
"S", # flake8-bandit
"SIM", # flake8-simplify
"SLF", # flake8-self
"SLOT", # flake8-slots
"T10", # flake8-debugger
#"T20", # flake8-print
"TC", # flake8-type-checking
"TD", # flake8-todo
"TID", # flake8-flake8-tidy-import
"YTT", # flake8-2020
"E", # pycodestyle-errors
"W", # pycodestyle-warnings
#"C90", # mccabe
"D", # pydocstyle
"F", # pyflakes
"FLY", # flynt
"I", # isort
"PERF", # perflint
"PGH", # pygrep-hooks
"PL", # pylint
]
ignore = [
"ANN401", # Dynamically typed expressions (typing.Any) are disallowed
"ASYNC210", # TODO Async functions should not call blocking HTTP methods
"ASYNC230", # TODO Async functions should not open files with blocking methods like `open`
"D1", # Missing docstring in ...
"D200", # One-line docstring should fit on one line
"D202", # No blank lines allowed after function docstring (found 1)
"D203", # 1 blank line required before class docstring
"D204", # 1 blank line required after class docstring
"D205", # 1 blank line required between summary line and description
"D209", # Multi-line docstring closing quotes should be on a separate line"
"D212", # Multi-line docstring summary should start at the first line
"D213", # Multi-line docstring summary should start at the second line
"D400", # First line should end with a period
"D401", # First line of docstring should be in imperative mood
"D402", # First line should not be the function's signature
"D404", # First word of the docstring should not be "This"
"D413", # Missing blank line after last section ("Returns")"
"D415", # First line should end with a period, question mark, or exclamation point
"D417", # Missing argument description in the docstring for
#"E124", # Don't change indention of multi-line statements
#"E128", # Don't change indention of multi-line statements
#"E231", # Don't add whitespace after colon (:) on type declaration
#"E251", # Don't remove whitespace around parameter '=' sign.
"E401", # Don't put imports on separate lines
"Q000", # TODO Single quotes found but double quotes preferred
"PERF203", # `try`-`except` within a loop incurs performance overhead
"RET504", # Unnecessary assignment to `...` before `return` statement
"PYI041", # Use `float` instead of `int | float`
"SIM102", # Use a single `if` statement instead of nested `if` statements
"SIM105", # Use `contextlib.suppress(TimeoutError)` instead of `try`-`except`-`pass`
"SIM114", # Combine `if` branches using logical `or` operator
"TC006", # Add quotes to type expression in `typing.cast()`
]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
line-ending = "native"
docstring-code-format = false
skip-magic-trailing-comma = false
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = [
"ARG",
"B",
"FBT",
"INP",
"SLF",
"S101", # Use of `assert` detected
"PLR2004" # Magic value used in comparison
]
[tool.ruff.lint.pylint]
# https://pylint.pycqa.org/en/latest/user_guide/configuration/all-options.html#design-checker
# https://pylint.pycqa.org/en/latest/user_guide/checkers/features.html#design-checker-messages
#max-args = 6 # max. number of args for function / method (R0913)
#max-attributes = 15 # max. number of instance attrs for a class (R0902)
max-branches = 40 # max. number of branch for function / method body (R0912)
#max-locals = 30 # max. number of local vars for function / method body (R0914)
max-returns = 15 # max. number of return / yield for function / method body (R0911)
max-statements = 150 # max. number of statements in function / method body (R0915)
#max-public-methods = 30 # max. number of public methods for a class (R0904)
#max-positional-arguments = 6 # max. number of positional args for function / method (R0917)
#####################
# mypy
# https://github.com/python/mypy
#####################
[tool.mypy]
# https://mypy.readthedocs.io/en/stable/config_file.html
#mypy_path = "$MYPY_CONFIG_FILE_DIR/tests/stubs"
python_version = "3.10"
files = "src,tests"
strict = true
disallow_untyped_calls = false
disallow_untyped_defs = true
disallow_incomplete_defs = true
ignore_missing_imports = true
show_error_codes = true
warn_unused_ignores = true
verbosity = 0
#####################
# pyright
# https://github.com/microsoft/pyright/
#####################
[tool.pyright]
# https://microsoft.github.io/pyright/#/configuration?id=main-configuration-options
include = ["src", "tests"]
defineConstant = { DEBUG = false }
pythonVersion = "3.10"
typeCheckingMode = "standard"
#####################
# pytest
# https://pypi.org/project/pytest/
#####################
[tool.pytest.ini_options]
testpaths = [
"src",
"tests"
]
# https://docs.pytest.org/en/stable/reference.html#confval-addopts
addopts = """
--strict-markers
-p no:cacheprovider
--doctest-modules
--cov=src/kleinanzeigen_bot
--cov-report=term-missing
"""
markers = [
"itest: marks a test as an integration test (i.e. a test with external dependencies)",
"asyncio: mark test as async"
]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
filterwarnings = [
"ignore:Exception ignored in:pytest.PytestUnraisableExceptionWarning",
"ignore::DeprecationWarning"
]