[build-system] requires = ["hatchling", "babel", "setuptools >= 50.0.0; python_version<'3.13'"] build-backend = "hatchling.build" [project] name = "Canaille" version = "0.0.56" description = "Lightweight identity and authorization management software" license = {file = "LICENSE.rst"} readme = "README.md" keywords = ["oidc", "oauth", "oauth2", "openid", "identity", "authentication"] classifiers = [ "Intended Audience :: Developers", "Development Status :: 3 - Alpha", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: Implementation :: CPython", "License :: OSI Approved :: MIT License", "Environment :: Web Environment", "Programming Language :: Python", "Operating System :: OS Independent", "Topic :: System :: Systems Administration :: Authentication/Directory", "Topic :: System :: Systems Administration :: Authentication/Directory :: LDAP", ] authors = [{name="Yaal Coop", email="contact@yaal.coop"}] maintainers = [{name="Éloi Rivard", email="eloi@yaal.coop"}] requires-python = ">=3.10" dependencies = [ "flask >= 3.0.0", "flask-wtf >= 1.2.1", "pydantic-settings >= 2.0.3", "requests>=2.32.3", "wtforms >= 3.1.1", ] [project.optional-dependencies] front = [ "email_validator >= 2.0.0", "flask-babel >= 4.0.0", "flask-themer >= 2.0.0", "pycountry >= 23.12.7", "pytz >= 2022.7", "toml >= 0.10.0", "zxcvbn-rs-py >= 0.2.0", ] oidc = [ "authlib >= 1.3.0", ] ldap = [ "python-ldap >= 3.4.0", ] sentry = [ "sentry-sdk >= 2.0.0", ] sqlite = [ "passlib >= 1.7.4", "sqlalchemy >= 2.0.23", "sqlalchemy-json >= 0.7.0", "sqlalchemy-utils >= 0.41.1", ] postgresql = [ "passlib >= 1.7.4", "sqlalchemy[postgresql-psycopg2binary] >= 2.0.23", "sqlalchemy-json >= 0.7.0", "sqlalchemy-utils >= 0.41.1", ] mysql = [ "passlib >= 1.7.4", "sqlalchemy[mysql-connector] >= 2.0.23", "sqlalchemy-json >= 0.7.0", "sqlalchemy-utils >= 0.41.1", ] otp = [ "otpauth>=2.1.1", "pillow>=11.0.0", "qrcode>=8.0", ] sms = [ "smpplib>=2.2.3", ] [project.urls] homepage = "https://canaille.yaal.coop" documentation = "https://canaille.readthedocs.io/en/latest/" repository = "https://gitlab.com/yaal/canaille" [dependency-groups] dev = [ "babel >= 2.14.0", "coverage[toml] >= 6.0.0", "faker >= 30.0.0", "flask-webtest >= 0.1.6", # pre-commit version is fixed until docformatted hook is compatible # https://github.com/PyCQA/docformatter/issues/293 "pre-commit < 4.0.0", "pre-commit-uv>=4.1.4", "pyquery >= 2.0.0", "pytest >= 8.0.0", "pytest-cov >= 6.0.0", "pytest-httpserver >= 1.1.0", "pytest-lazy-fixtures >= 1.0.7", "pytest-smtpd >= 0.1.0", "pytest-xdist >= 3.3.1", "slapd >= 0.1.5", "time-machine >= 2.14.1", "toml >= 0.10.0", "tox-uv >= 1.16.0", # Babel 2.14 does not directly depend on setuptools # https://github.com/python-babel/babel/blob/40e60a1f6cf178d9f57fcc14f157ea1b2ab77361/CHANGES.rst?plain=1#L22-L24 # and neither python 3.12 due to PEP 632 # https://peps.python.org/pep-0632/ "setuptools >= 50.0.0; python_version>='3.12'", ] doc = [ "autodoc-pydantic >= 2.0.1", "shibuya >= 2024.3.1", "sphinx >= 7.0.0", "sphinx-design >= 0.6.0", "sphinx-issues >= 5.0.0", "sphinx-click >= 6.0.0", "sphinx-intl>=2.3.0", ] demo = [ "faker", "honcho", "slapd", "requests", "watchdog >= 4.0.0", ] [project.scripts] canaille = "canaille.commands:cli" [options.packages.find] exclude = [ "tests", "tests.*", "doc", "doc.*", ] [tool.hatch.build] include = [ "canaille/", "doc/", "tests/", "CHANGES.rst", "CONTRIBUTING.rst", "README.md", ] exclude = [ "docs/_build/", ] artifacts = ["canaille/translations/*/LC_MESSAGES/*.mo"] [tool.hatch.build.hooks.custom] dependencies = [ "Babel>=2.6.0", "setuptools >= 50.0.0; python_version>='3.12'", ] [tool.coverage.run] source = [ "canaille", "tests", ] omit = [".tox/*"] branch = true [tool.coverage.report] exclude_lines = [ "@pytest.mark.skip", "pragma: no cover", "raise NotImplementedError", "except ImportError", "if app.debug", ] [tool.ruff.lint] select = [ "B", # flake8-bugbear "E", # pycodestyle "F", # pyflakes "I", # isort "UP", # pyupgrade ] ignore = [ "E501", # line-too-long "E722", # bare-except ] [tool.ruff.lint.isort] force-single-line = true [tool.ruff.format] docstring-code-format = true [tool.tox] requires = ["tox>=4.19"] env_list = [ "style", "py310", "py311", "py312", "py313", "minversions", "doc", "coverage", ] [tool.tox.env_run_base] runner = "uv-venv-lock-runner" dependency_groups = ["dev"] uv_sync_flags = ["--extra", "front", "--extra", "oidc", "--extra", "sqlite", "--extra", "ldap"] commands = [ ["pytest", "--showlocals", "--full-trace", "{posargs}"], ] [tool.tox.env.style] skip_install = true runner = "uv-venv-runner" commands = [ ["pre-commit", "run", "--all-files", "--show-diff-on-failure"], ] [tool.tox.env.minversions] uv_resolution = "lowest-direct" basepython = ["python3.10"] [tool.tox.env.doc] dependency_groups = ["doc"] commands = [ ["sphinx-build", "--builder", "html", "--fail-on-warning", "doc", "build/sphinx/html"], ["sphinx-build", "--builder", "man", "doc", "build/sphinx/html"], ] [tool.tox.env.coverage] commands = [ ["pytest", "--cov", "--cov-fail-under=100", "--cov-report", "term:skip-covered", "{posargs}"], ["coverage", "html"], ] [[tool.babel.mappings]] method = "python" pattern = "**.py" [[tool.babel.mappings]] method = "jinja2" pattern = "**/templates/**.html" trimmed = "true" [[tool.babel.mappings]] method = "jinja2" pattern = "**/themes/**.html" trimmed = "true" [[tool.babel.mappings]] method = "jinja2" pattern = "**/templates/**.txt" trimmed = "true"