[build-system]
requires      = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "pymend"
version = "1.1.0"
authors = [{ name = "Jan-Eric Nitschke", email = "janericnitschke@gmail.com" }]
maintainers = [{ name = "Jan-Eric Nitschke", email = "janericnitschke@gmail.com" }]
license = { text = "MIT" }
description = "Generate, fix and convert docstrings."
readme = { file = "README.rst", content-type = "text/x-rst" }
requires-python = ">=3.9"
keywords = ["pymend", "docstring"]
classifiers = [
    "Intended Audience :: Developers",
    "Topic :: Documentation",
    "License :: OSI Approved :: MIT License",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
    "Programming Language :: Python :: 3.13",
    "Operating System :: OS Independent",
]
dependencies = [
    "typing-extensions>=4.0,<5.0",
    "tomli>=1.1.0; python_version < '3.11'",
    "click>=8.0.0",
]

[project.urls]
"Homepage"      = "https://github.com/JanEricNitschke/pymend"
"Documentation" = "https://pymend.readthedocs.io/en/latest/"
"GitHub"        = "https://github.com/JanEricNitschke/pymend"
"Bug Tracker"   = "https://github.com/JanEricNitschke/pymend/issues"


[project.scripts]
pymend = "pymend.pymendapp:main"

[tool.pymend]
extend-exclude             = "docs/|tests/"
output-style               = "numpydoc"
input-style                = "numpydoc"
ignored-functions          = ["main"]
check                      = true
force-meta-min-func-length = 5
force-params-min-n-params  = 2

[tool.ruff]
# Exclude a variety of commonly ignored directories.
exclude = [
    ".bzr",
    ".direnv",
    ".eggs",
    ".git",
    ".hg",
    ".mypy_cache",
    ".nox",
    ".pants.d",
    ".pytype",
    ".ruff_cache",
    ".svn",
    ".tox",
    ".venv",
    "__pypackages__",
    "_build",
    "buck-out",
    "build",
    "dist",
    "node_modules",
    "venv",
    "docs",
    "doc",
    "tests/test_pymend/refs",
    "*.html",
]

# Same as Black.
line-length = 88

# Assume Python 3.9.
target-version = "py39"

[tool.ruff.lint]
# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default.
select = ["ALL"]
# COM messes with black
# PTH is too much work, will enable when it can autofix
# Same for FA
ignore = [
    # Due to formatter conflict
    "COM812",
    "ISC001",
    "C901",   # Do not like
    "ANN101", # Super stupid rule
    "FA100",  # I do not like the import
    "PERF",   # False positives and no real benefit
]
# ignore = ["ANN101", "COM", "FA", "PTH", "C901", "PERF"]
# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"


[tool.ruff.lint.per-file-ignores]
"__init__.py"                     = ["E402", "F401"]
"tests/*/test_*.py"               = ["S101", "SLF001", "ANN101", "ANN102", "PLR2004"]
"pymend/docstring_parser/rest.py" = ["PLR2004"]
"pymend/const.py"                 = ["E501"]

[tool.ruff.lint.pydocstyle]
convention = "numpy" # Accepts: "google", "numpy", or "pep257".

[tool.ruff.lint.pylint]
max-args = 10

[tool.ruff.format]
# Like Black, use double quotes for strings.
quote-style = "double"

# Like Black, indent with spaces, rather than tabs.
indent-style = "space"

# Like Black, respect magic trailing commas.
skip-magic-trailing-comma = false


[tool.coverage.run]
branch = true
source = ["pymend"]

[tool.pytest.ini_options]
testpaths = ["tests"]

[tool.pyright]
include                            = ["pymend"]
exclude                            = ["tests"]
typeCheckingMode                   = "strict"
strictListInference                = true
strictDictionaryInference          = true
reportDeprecated                   = "warning"
reportPropertyTypeMismatch         = "error"
reportFunctionMemberAccess         = "error"
reportMissingTypeStubs             = "error"
reportUntypedFunctionDecorator     = "error"
reportUntypedClassDecorator        = "error"
reportUntypedBaseClass             = "error"
reportUntypedNamedTuple            = "error"
reportPrivateUsage                 = "error"
reportConstantRedefinition         = "error"
reportOverlappingOverload          = "error"
reportMissingParameterType         = "error"
reportUnnecessaryIsInstance        = "error"
reportUnnecessaryCast              = "error"
reportUnnecessaryComparison        = "error"
reportUnnecessaryContains          = "error"
reportAssertAlwaysTrue             = "error"
reportUnnecessaryTypeIgnoreComment = "error"
reportImplicitOverride             = "error"
reportShadowedImports              = "error"

[tool.pylint.main]
# Specify a score threshold under which the program will exit with error.
fail-under = 10.0

[tool.pylint.basic]
# Good variable names which should always be accepted, separated by a comma.
good-names          = ["i", "j", "k", "ex", "Run", "_", "x", "y", "z", "e", "ok"]
include-naming-hint = true
typevar-rgx         = "^_{0,2}(?!T[A-Z])([A-Z]|T[0-9]?)(?:[A-Z]*[0-9]*)?(?:_co(?:ntra)?)?$"

[tool.pylint.design]
# Maximum number of arguments for function / method.
max-args = 10

# Maximum number of attributes for a class (see R0902).
# Should be lowered to 7 but got no time for that atm
max-attributes = 15

# Maximum number of boolean expressions in an if statement (see R0916).
max-bool-expr = 5

# Maximum number of branch for function / method body.
# Same as for max-attributes
max-branches = 12

# Maximum number of locals for function / method body.
# Same as for max-attributes
max-locals = 15

# Maximum number of public methods for a class (see R0904).
max-public-methods = 20

# Maximum number of return / yield for function / method body.
max-returns = 6

# Maximum number of statements in function / method body.
max-statements = 60

# Minimum number of public methods for a class (see R0903).
# Same as for max-attributes
min-public-methods = 2

[tool.pylint.exceptions]
# Exceptions that will emit a warning when caught.
overgeneral-exceptions = ["builtins.BaseException"]

[tool.pylint.format]
# Maximum number of characters on a single line.
max-line-length = 88

# Maximum number of lines in a module.
max-module-lines = 2000

[tool.pylint."messages control"]
# Only show warnings with the listed confidence levels. Leave empty to show all.
# Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
confidence = ["HIGH", "CONTROL_FLOW", "INFERENCE", "INFERENCE_FAILURE", "UNDEFINED"]

# Disable the message, report, category or checker with the given id(s). You can
# either give multiple identifiers separated by comma (,) or put this option
# multiple times (only on the command line, not in the configuration file where
# it should appear only once). You can also use "--disable=all" to disable
# everything first and then re-enable specific checks. For example, if you want
# to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable = ["unnecessary-ellipsis"] #  but needed for pyright

[tool.pylint.miscellaneous]
# List of note tags to take in consideration, separated by a comma.
notes = ["FIXME", "XXX", "TODO"]

[tool.pylint.refactoring]
# Maximum number of nested blocks for function / method body
max-nested-blocks = 5

# Complete name of functions that never returns. When checking for inconsistent-
# return-statements if a never returning function is called then it will be
# considered as an explicit return statement and no message will be printed.
never-returning-functions = ["sys.exit", "argparse.parse_error"]

[tool.pylint.reports]
# Python expression which should return a score less than or equal to 10. You
# have access to the variables 'fatal', 'error', 'warning', 'refactor',
# 'convention', and 'info' which contain the number of messages in each category,
# as well as 'statement' which is the total number of statements analyzed. This
# score is used by the global evaluation report (RP0004).
evaluation = "max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))"

[tool.pylint.similarities]
# Minimum lines number of a similarity.
min-similarity-lines = 20

[tool.pylint.spelling]
# Limits count of emitted suggestions for spelling mistakes.
max-spelling-suggestions = 4
