[tool.poetry]
name = "rdflib"
version = "7.4.0"
description = """RDFLib is a Python library for working with RDF, \
a simple yet powerful language for representing information."""
authors = ["Daniel 'eikeon' Krech <eikeon@eikeon.com>"]
maintainers = ["RDFLib Team <rdflib-dev@googlegroups.com>"]
repository = "https://github.com/RDFLib/rdflib"
documentation = "https://rdflib.readthedocs.org/"
license = "BSD-3-Clause"
classifiers=[
    "Programming Language :: Python",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.8",
    "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",
    "Programming Language :: Python :: 3.14",
    "License :: OSI Approved :: BSD License",
    "Topic :: Software Development :: Libraries :: Python Modules",
    "Operating System :: OS Independent",
    "Natural Language :: English"
]
readme = "README.md"
packages = [
    { include = "rdflib" },
]
include = [
    { path = "test", format = "sdist" },
    { path = "docs", format = "sdist" },
    { path = "examples", format = "sdist" },
]

[tool.poetry.scripts]
rdfpipe = 'rdflib.tools.rdfpipe:main'
csv2rdf = 'rdflib.tools.csv2rdf:main'
rdf2dot = 'rdflib.tools.rdf2dot:main'
rdfs2dot = 'rdflib.tools.rdfs2dot:main'
rdfgraphisomorphism = 'rdflib.tools.graphisomorphism:main'

[tool.poetry.dependencies]
python = ">=3.8.1"
isodate = {version=">=0.7.2,<1.0.0", python = "<3.11"}
pyparsing = ">=2.1.0,<4"
berkeleydb = {version = "^18.1.0", optional = true}
networkx = {version = ">=2,<4", optional = true}
html5rdf = {version = ">=1.2,<2", optional = true}
lxml = {version = ">=4.3,<6.0", optional = true}
orjson = {version = ">=3.9.14,<4", optional = true}

[tool.poetry.group.dev.dependencies]
black = "24.8.0"
mypy = "1.14.1"
lxml-stubs = ">=0.4,<0.6"
pip-tools = "^7.4.1"

[tool.poetry.group.tests.dependencies]
pytest = ">=7.1.3,<9.0.0"
pytest-cov = ">=4,<6"
coverage = {version = "^7.0.1", extras = ["toml"]}
types-setuptools = ">=68.0.0.3,<72.0.0.0"
setuptools = ">=68,<72"
wheel = ">=0.42,<0.46"

[tool.poetry.group.docs.dependencies]
typing-extensions = "^4.11.0"
mkdocs = ">=1.6.1"
mkdocs-material = ">=9.6.12"
# Set python to 3.11 or greater as that's what's used in the validate workflow to test doc builds.
mkdocstrings = {version = "^0.26.2", extras = ["python"], python = ">=3.11"}
mkdocs-gen-files = "^0.5.0"
# Set python to 3.11 or greater as that's what's used in the validate workflow to test doc builds.
mkdocs-include-markdown-plugin = {version = "^7.2.0", python = ">=3.11"}

[tool.poetry.group.lint.dependencies]
ruff = "0.14.2"

[tool.poetry.extras]
berkeleydb = ["berkeleydb"]
networkx = ["networkx"]
# html support is optional, it is used only in tokenizing `rdf:HTML` type Literals
html = ["html5rdf"]
# lxml support is optional, it is used only for parsing XML-formatted SPARQL results
lxml = ["lxml"]
orjson = ["orjson"]

[build-system]
requires = ["poetry-core>=1.4.0"]
build-backend = "poetry.core.masonry.api"

[tool.ruff]
# https://beta.ruff.rs/docs/configuration/
target-version = "py38"
# Same as Black.
line-length = 88

[tool.ruff.lint]
select = [
    "E", # pycodestyle errors
    "W", # pycodestyle warnings
    "F", # Pyflakes
    "I", # isort
    "N", # pep8-naming
    "RUF100", # Unused noqa directive
    "UP001", # Remove unused imports
    "UP003", # Use {} instead of type(...)
    "UP004", # Class inherits from object
    "UP005", # is deprecated, use
    "UP009", # UTF-8 encoding declaration is unnecessary
    "UP010", # Unnecessary __future__ import for target Python version
    "UP011", # Unnecessary parentheses to functools.lru_cache
    "UP012", # Unnecessary call to encode as UTF-8
    "UP017", # Use datetime.UTC alias
    "UP018", # Unnecessary {literal_type} call (rewrite as a literal)
    "UP019", # typing.Text is deprecated, use str
    "UP020", # Use builtin open
    "UP021", # universal_newlines is deprecated, use text
    "UP022", # Sending stdout and stderr to PIPE is deprecated, use capture_output
    "UP023", # cElementTree is deprecated, use ElementTree
    "UP024", # Replace aliased errors with OSError
    "UP025", # Remove unicode literals from strings
    "UP026", # mock is deprecated, use unittest.mock
    "UP029", # Unnecessary builtin import
    "UP034", # Avoid extraneous parentheses
    "UP035", # Import from {target} instead:
    "UP036", # Version block is outdated for minimum Python version
    "UP037", # Remove quotes from type annotation
    "UP039", # Unnecessary parentheses after class definition
    "FA", # flake8-future-annotations
]

ignore = [
    "E501", # line too long:
    # Disabled based on black recommendations
    # https://black.readthedocs.io/en/stable/faq.html#why-are-flake8-s-e203-and-w503-violated
    "E203", # whitespace before ':'
    "E231", # missing whitespace after ','
]

[tool.ruff.lint.per-file-ignores]
"rdflib/plugins/sparql/*" = [
    "N801", # Class name should be UpperCamelCase
    "N802", # Function name should be lowercase
    "N803", # Argument name should be lowercase
    "N806", # Variable in function should be lowercase
    "N812", # Lowercase imported as non lowercase
    "N816", # Variable in class scope should be mixedCase
]
"rdflib/namespace/_*" = [
    "N815", # Variable in class scope should not be mixedCase
    "N999", # Invalid module name
]
"rdflib/plugins/parsers/{trix,rdfxml,notation3}.py" = [
    "N802", # Function name should be lowercase
    "N803", # Argument name should be lowercase
    "N806", # Variable in function should be lowercase
    "N816", # Variable in class scope should be mixedCase
]
"rdflib/plugins/serializers/{turtle,longturtle,trig}.py" = [
    "N802", # Function name should be lowercase
    "N806", # Variable in function should be lowercase
    "N815", # Variable in class scope should not be mixedCase
]
"test/utils/namespace/_*" = [
    "N815", # Variable in class scope should not be mixedCase
    "N999", # Invalid module name
]
"{test/conftest.py,rdflib/namespace/__init__.py,rdflib/__init__.py,rdflib/plugins/sparql/__init__.py}" = [
    "E402", # Module level import not at top of file
]

[tool.black]
line-length = 88
target-version = ['py38']
required-version = "24.8.0"
include = '\.pyi?$'
exclude = '''
(
  /(
      \.eggs         # exclude a few common directories in the
    | \.git          # root of the project
    | \.hg
    | \.mypy_cache
    | \.pytest_cache
    | \.tox
    | \.venv
    | \.var
    | \.github
    | site
    | htmlcov
    | benchmarks
    | test_reports
    | rdflib.egg-info
    | buck-out
    | build
    | dist
    | venv
  )/
)
'''

[tool.pytest.ini_options]
addopts = [
    "--doctest-modules",
    "--ignore=admin",
    "--ignore=devtools",
    "--ignore=rdflib/extras/external_graph_libs.py",
    "--ignore-glob=docs/*.py",
    "--ignore-glob=site/*",
    "--strict-markers",
]
filterwarnings = [
    # The below warning is a consequence of how pytest doctest detects mocks and how DefinedNamespace behaves when an undefined attribute is being accessed.
    "ignore:Code. pytest_mock_example_attribute_that_shouldnt_exist is not defined in namespace .*:UserWarning",
    # The below warning is a consequence of how pytest detects fixtures and how DefinedNamespace behaves when an undefined attribute is being accessed.
    "ignore:Code. _pytestfixturefunction is not defined in namespace .*:UserWarning",
]
markers = [
    "webtest: mark a test as using the internet",
]
# log_cli = true
# log_cli_level = "DEBUG"
log_format = "%(asctime)s.%(msecs)03d %(levelname)-8s %(name)-12s %(filename)s:%(lineno)s:%(funcName)s %(message)s"
log_date_format = "%Y-%m-%dT%H:%M:%S"
log_cli_format = "%(asctime)s.%(msecs)03d %(levelname)-8s %(name)-12s %(filename)s:%(lineno)s:%(funcName)s %(message)s"
log_cli_date_format = "%Y-%m-%dT%H:%M:%S"

[tool.isort]
profile = "black"
py_version = 38
line_length = 88
src_paths= ["rdflib", "test", "devtools", "examples"]
supported_extensions = ["pyw", "pyi", "py"]
skip = [
    '.eggs',         # exclude a few common directories in the
    '.git',          # root of the project
    '.hg',
    '.mypy_cache',
    '.pytest_cache',
    '.tox',
    '.venv',
    '.var',
    '.github',
    'site',
    'htmlcov',
    'benchmarks',
    'test_reports',
    'rdflib.egg-info',
    'buck-out',
    'build',
    'dist',
    'venv',
]

[tool.mypy]
files = ['rdflib', 'test', 'devtools', 'examples']
python_version = "3.8"
warn_unused_configs = true
ignore_missing_imports = true
disallow_subclassing_any = false
warn_unreachable = true
warn_unused_ignores = true
no_implicit_optional = false
implicit_reexport = false

[[tool.mypy.overrides]]
module = "rdflib.*"
check_untyped_defs = true

[tool.coverage.run]
branch = true
source = ["rdflib"]
omit = ["*/_type_checking.py"]

[tool.coverage.report]
exclude_lines = [
    # Have to re-enable the standard pragma
    "pragma: no cover",

    # TYPE_CHECKING guarded code only affects type checkers.
    "^ *if (False|TYPE_CHECKING):",
    # constant used in protocols and abstract methods, does not run anything
    # and has no side effects.
    '^ +\.\.\.$',

    # Don't complain if non-runnable code isn't run:
    "if 0:",
    "if __name__ == .__main__.:",
    "if __name__==.__main__.:"
]
