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

[project]
name = "parsel"
description = "Parsel is a library to extract data from HTML and XML using XPath and CSS selectors"
readme = "README.rst"
license = "BSD-3-Clause"
license-files = ["LICENSE"]
authors = [
    { name = "Scrapy project", email = "info@scrapy.org" },
]
keywords = [
    "parsel",
]
classifiers = [
    "Development Status :: 5 - Production/Stable",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: BSD License",
    "Natural Language :: English",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
    "Programming Language :: Python :: 3.13",
    "Programming Language :: Python :: 3.14",
    "Programming Language :: Python :: Implementation :: CPython",
    "Programming Language :: Python :: Implementation :: PyPy",
    "Topic :: Text Processing :: Markup",
    "Topic :: Text Processing :: Markup :: HTML",
    "Topic :: Text Processing :: Markup :: XML",
]
dependencies = [
    "cssselect>=1.2.0",
    "jmespath>=1.0.0",
    "lxml>=5.1.0",
    "packaging>=23.0",
    "w3lib>=1.19.0",
]
requires-python = ">=3.10"
dynamic = ["version"]

[project.urls]
Homepage = "https://github.com/scrapy/parsel"
Documentation = "https://parsel.readthedocs.io/en/latest/"
Source = "https://github.com/scrapy/parsel"
Tracker = "https://github.com/scrapy/parsel/issues"
"Release notes" = "https://parsel.readthedocs.io/en/latest/history.html"

[tool.hatch.version]
path = "parsel/__init__.py"

[tool.hatch.build.targets.sdist]
include = [
    "/docs",
    "/parsel",
    "/tests",
    "/NEWS",
    "/codecov.yml",
    "/tox.ini",
]

[tool.bumpversion]
current_version = "1.11.0"
commit = true
tag = true
tag_name = "v{new_version}"

[[tool.bumpversion.files]]
filename = "parsel/__init__.py"

[[tool.bumpversion.files]]
filename = "NEWS"
search = "\\(unreleased\\)$"
replace = "({now:%Y-%m-%d})"
regex = true

[tool.coverage.run]
branch = true

[tool.coverage.report]
exclude_also = [
    "@typing.overload",
]

[tool.mypy]
strict = true

[tool.pylint.MASTER]
ignore = "typing"
persistent = "no"
extension-pkg-allow-list = [
    "lxml",
]

[tool.pylint."MESSAGES CONTROL"]
enable = [
    "useless-suppression",
]
disable = [
    "fixme",
    "import-error",
    "import-outside-toplevel",
    "invalid-name",
    "line-too-long",
    "missing-class-docstring",
    "missing-function-docstring",
    "missing-module-docstring",
    "no-member",
    "not-callable",
    "protected-access",
    "raise-missing-from",
    "redefined-builtin",
    "too-few-public-methods",
    "too-many-arguments",
    "too-many-lines",
    "too-many-positional-arguments",
    "too-many-public-methods",
    "unused-argument",
    "use-implicit-booleaness-not-comparison",
    "wrong-import-position",
]

[tool.pytest.ini_options]
addopts = [
    "--doctest-modules",
]

[tool.ruff.lint]
extend-select = [
    # flake8-builtins
    "A",
    # flake8-async
    "ASYNC",
    # flake8-bugbear
    "B",
    # flake8-comprehensions
    "C4",
    # flake8-commas
    "COM",
    # pydocstyle
    "D",
    # flake8-future-annotations
    "FA",
    # flynt
    "FLY",
    # refurb
    "FURB",
    # isort
    "I",
    # flake8-implicit-str-concat
    "ISC",
    # flake8-logging
    "LOG",
    # Perflint
    "PERF",
    # pygrep-hooks
    "PGH",
    # flake8-pie
    "PIE",
    # pylint
    "PL",
    # flake8-pytest-style
    "PT",
    # flake8-use-pathlib
    "PTH",
    # flake8-pyi
    "PYI",
    # flake8-quotes
    "Q",
    # flake8-return
    "RET",
    # flake8-raise
    "RSE",
    # Ruff-specific rules
    "RUF",
    # flake8-bandit
    "S",
    # flake8-simplify
    "SIM",
    # flake8-slots
    "SLOT",
    # flake8-debugger
    "T10",
    # flake8-type-checking
    "TC",
    # pyupgrade
    "UP",
    # pycodestyle warnings
    "W",
    # flake8-2020
    "YTT",
]
ignore = [
    # Within an `except` clause, raise exceptions with `raise ... from`
    "B904",
    # Trailing comma missing
    "COM812",
    # Missing docstring in public module
    "D100",
    # Missing docstring in public class
    "D101",
    # Missing docstring in public method
    "D102",
    # Missing docstring in public function
    "D103",
    # Missing docstring in public package
    "D104",
    # Missing docstring in magic method
    "D105",
    # Missing docstring in public nested class
    "D106",
    # Missing docstring in __init__
    "D107",
    # One-line docstring should fit on one line with quotes
    "D200",
    # No blank lines allowed after function docstring
    "D202",
    # 1 blank line required between summary line and description
    "D205",
    # Multi-line docstring closing quotes should be on a separate line
    "D209",
    # First line should end with a period
    "D400",
    # First line should be in imperative mood; try rephrasing
    "D401",
    # First line should not be the function's "signature"
    "D402",
    # First word of the first line should be properly capitalized
    "D403",
    # No blank lines allowed between a section header and its content
    "D412",
    # Too many return statements
    "PLR0911",
    # Too many branches
    "PLR0912",
    # Too many arguments in function definition
    "PLR0913",
    # Too many statements
    "PLR0915",
    # Magic value used in comparison
    "PLR2004",
    # String contains ambiguous {}.
    "RUF001",
    # Docstring contains ambiguous {}.
    "RUF002",
    # Comment contains ambiguous {}.
    "RUF003",
    # Mutable class attributes should be annotated with `typing.ClassVar`
    "RUF012",
    # Use of `assert` detected
    "S101",

    # pending: https://github.com/scrapy/parsel/issues/312
    "B019",
]

[tool.ruff.lint.isort]
split-on-trailing-comma = false

[tool.ruff.lint.per-file-ignores]
"tests/typing/selector.py" = ["F841"]

[tool.ruff.lint.pydocstyle]
convention = "pep257"
