weblate/pyproject.toml
Michal Čihař b71d340f42 fix(auth): manually filter OTP devices when authenticating
We know the class we want to use, so there is no need to iterate over
other class (which might fail due to issues like
https://github.com/Stormbase/django-otp-webauthn/issues/22).

Fixes #12369
Fixes WEBLATE-DYJ
2024-08-30 13:07:13 +02:00

447 lines
12 KiB
TOML

[build-system]
build-backend = "setuptools.build_meta"
requires = [
"setuptools>=69.0.0",
"translate-toolkit"
]
[project]
authors = [{name = "Michal Čihař", email = "michal@weblate.org"}]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Framework :: Django",
"Intended Audience :: Developers",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Software Development :: Internationalization",
"Topic :: Software Development :: Localization",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content"
]
dependencies = [
"aeidon>=1.14.1,<1.16",
"ahocorasick-rs>=0.20.0,<0.23.0",
"borgbackup>=1.2.5,<1.5",
"celery[redis]>=5.4.0,<5.5",
"certifi>=2023.7.22",
"charset-normalizer>=2.0.12,<4.0",
"crispy-bootstrap3==2024.1",
"cryptography>=42.0.2",
"cssselect>=1.2,<1.3",
"Cython>=3.0.0,<3.1",
"cyrtranslit>=1.1.0,<1.2.0",
"diff-match-patch==20230430",
"django-appconf>=1.0.3,<1.1",
"django-celery-beat>=2.6.0,<2.8",
"django-compressor>=4.4,<5",
"django-cors-headers>=4.3.0,<4.5",
"django-crispy-forms>=2.1,<2.4",
"django-filter>=23.4,<24.4",
"django-redis>=5.4.0,<6.0",
"django-otp>=1.5.2,<2.0",
"django-otp-webauthn>=0.3.0,<0.4",
"Django[argon2]>=5.0,<5.2",
"djangorestframework>=3.15.0,<3.16",
"filelock<4,>=3.12.2",
"fluent.syntax>=0.18.1,<0.20",
"GitPython>=3.1.0,<3.2",
"hiredis>=2.2.1,<3.1",
"html2text>=2024.2.25,<2024.2.27",
"iniparse==0.5",
"jsonschema>=4.5,<5",
"lxml>=5.2.0,<5.4",
"mistletoe>=1.3.0,<1.5",
"nh3>=0.2.14,<0.3",
"openpyxl>=3.1.0,<3.2",
"packaging>=22,<24.2",
"phply>=1.2.6,<1.3",
"Pillow>=10.3.0,<11",
"pycairo>=1.20.0",
"Pygments>=2.15.0,<3.0",
"PyGObject>=3.40.1",
"pyicumessageformat>=1.0.0,<1.1",
"pyparsing>=3.1.1,<3.2",
"python-dateutil>=2.8.2",
"python-redis-lock[django]>=4,<4.1",
"qrcode>=7.4.1,<8.0",
"rapidfuzz>=2.6.0,<3.10",
"redis>=5.0.2,<5.1.0",
"requests>=2.32.2,<2.33",
"ruamel.yaml>=0.17.2,<0.19.0",
"sentry-sdk>=2.2,<3.0",
"siphashc>=2.1,<3.0",
"social-auth-app-django>=5.4.0,<6.0.0",
"social-auth-core>=4.5.0,<5.0.0",
"tesserocr>=2.6.1,<2.8.0",
"translate-toolkit>=3.13.1,<3.14",
"translation-finder>=2.16,<3.0",
"user-agents>=2.0,<2.3",
"weblate-language-data>=2024.6",
"weblate-schemas==2024.1"
]
description = "A web-based continuous localization system with tight version control integration"
dynamic = ["version"]
keywords = [
"i18n",
"l10n",
"gettext",
"git",
"mercurial",
"translate"
]
license = {text = "GPLv3+"}
name = "Weblate"
requires-python = ">=3.10"
[project.optional-dependencies]
alibaba = [
"aliyun-python-sdk-alimt>=3.2.0,<4.0.0"
]
all = [
"Weblate[alibaba,amazon,antispam,gerrit,google,ldap,mercurial,openai,postgres,saml,zxcvbn]"
]
amazon = [
"boto3>=1.28.62,<1.36.0"
]
antispam = [
"python-akismet>=0.4.2,<0.5"
]
ci = [
"build==1.2.1",
"coverage==7.6.1",
"uv==0.4.0",
"twine==5.1.1"
]
dev = [
"Weblate[all,ci,test,lint,mypy]",
"django-debug-toolbar==4.4.6",
"PyICU==2.13.1",
"reuse==4.0.3",
"scour==0.38.2",
"tinyunicodeblock==1.3",
"tomli"
]
gerrit = [
"git-review>=2.2.0,<2.5.0"
]
google = [
"google-cloud-translate>=3.13.0,<4.0"
]
ldap = [
"django-auth-ldap>=4.6.0,<5.0.0"
]
lint = [
"pre-commit==3.8.0",
"pylint==3.2.6"
]
mercurial = [
"mercurial>=6.2,<7.0"
]
mypy = [
"boto3-stubs==1.35.9",
"celery-types==0.22.0",
"django-stubs-ext==5.0.4",
"django-stubs==5.0.4",
"djangorestframework-stubs==3.15.0",
"types-lxml==2024.8.7",
"mypy==1.11.2",
"types-jsonschema==4.23.0.20240813",
"types-openpyxl==3.1.5.20240822",
"types-Pillow==10.2.0.20240822",
"types-python-dateutil==2.9.0.20240821",
"types-requests==2.32.0.20240712"
]
mysql = [
"mysqlclient>=2.1.1,<3"
]
openai = [
"openai>=1.28.1,<2.0"
]
postgres = [
"psycopg[binary]>=3.1.8,<4"
]
saml = [
"python3-saml>=1.2.1"
]
test = [
"pytest==8.3.2",
"pytest-cov==5.0.0",
"pytest-django==4.8.0",
"responses==0.25.3",
"respx==0.21.1",
"selenium==4.24.0"
]
zxcvbn = ["django-zxcvbn-password==2.1.1"]
[project.readme]
content-type = "text/x-rst"
file = "README.rst"
[project.scripts]
weblate = "weblate.runner:main"
weblate-generate-secret-key = "weblate.utils.generate_secret_key:main"
[project.urls]
Documentation = "https://docs.weblate.org/"
Download = "https://weblate.org/download/"
Funding = "https://weblate.org/donate/"
Homepage = "https://weblate.org/"
"Issue Tracker" = "https://github.com/WeblateOrg/weblate/issues"
"Release Notes" = "https://docs.weblate.org/en/latest/changes.html"
"Source Code" = "https://github.com/WeblateOrg/weblate"
Twitter = "https://twitter.com/WeblateOrg"
[tool.codespell]
count = true
ignore-words-list = "assertIn"
skip = '*.po,*.pot,*.json,*.tmx,*.tbx,*.csv,*/vendor/*,weblate/trans/specialchars.py,scripts/yarn/yarn.lock,weblate/trans/tests/data/known_hosts,docs/user/checks.rst,docs/toc-devel.rst,docs/changes/contributors/*.rst'
[tool.coverage.paths]
source = [
"."
]
[tool.coverage.report]
exclude_also = [
"@(abc\\.)?abstractmethod",
# Have to re-enable the standard pragma
"pragma: no cover",
# Don't complain about missing debug-only code:
"def __repr__",
"if self\\.debug",
# Don't complain if tests don't hit defensive assertion code:
"raise AssertionError",
"raise NotImplementedError",
# Don't complain if non-runnable code isn't run:
"if 0:",
"if __name__ == .__main__.:",
# Type checking
"if TYPE_CHECKING:"
]
[tool.coverage.run]
branch = true
concurrency = ["thread", "multiprocessing"]
omit = [
"weblate/settings_*.py",
"weblate/settings.py",
".venv*/*"
]
[tool.django-stubs]
django_settings_module = "weblate.settings_example"
strict_settings = false
[tool.mypy]
check_untyped_defs = true
plugins = [
"mypy_django_plugin.main",
"mypy_drf_plugin.main"
]
[[tool.mypy.overrides]]
# TODO: remove this once core can be validated with mypy
ignore_errors = true
module = [
"weblate.*.tests",
"weblate.*.tests.*"
]
[[tool.mypy.overrides]]
disallow_untyped_defs = true
ignore_missing_imports = true
module = [
"cyrtranslit.*",
"mistletoe.*",
"simple_sso.*",
"social_django.*",
"social_core.*",
"ruamel.*",
"aliyunsdkcore.*",
"aliyunsdkalimt.*",
"google.oauth2.*",
"user_agents.*",
"translation_finder.*",
"weblate_language_data.*",
"django_redis.*",
"pygments.*",
"redis_lock.*",
"borg.*",
"rollbar.*",
"crispy_forms.*",
"akismet.*",
"gi.*",
"diff_match_patch.*",
"saml2.*",
"ldap.*",
"django_auth_ldap.*",
"pyicumessageformat.*",
"django_filters.*",
"tesserocr.*",
"django_celery_beat.*",
"translate.*",
"appconf.*",
"wllegal.*",
"wlhosted.*",
"djangosaml2idp.*",
"debug_toolbar.*",
"weblate_schemas.*",
"django.db.backends.postgresql.psycopg_any"
]
[tool.pylint.main]
disable = [
"C",
"W",
"R",
"I",
"no-member",
"not-a-mapping",
"unsubscriptable-object",
"unsupported-membership-test",
"not-an-iterable",
"unsupported-binary-operation",
"c-extension-no-member",
"not-callable",
"invalid-str-returned",
"raising-bad-type",
"no-name-in-module",
"import-error"
]
extension-pkg-whitelist = ["siphashc"]
ignore = [
"migrations",
"settings.py",
"settings_test.py",
".git",
"test-repos",
"repos",
"build",
".venv"
]
[tool.pytest.ini_options]
DJANGO_SETTINGS_MODULE = "weblate.settings_test"
# TODO: enable FAIL_INVALID_TEMPLATE_VARS = true
addopts = "--reuse-db --cov=weblate --cov-report="
python_files = ["test_*.py", "tests.py"]
[tool.ruff.lint]
extend-safe-fixes = [
"D",
"TCH",
"FLY",
"SIM",
"ANN",
"FA102",
"UP"
]
# CONFIG - intentional configuration
# TODO - needs decision whether intention, add noqa tags or fix
# WONTFIX - not fixable in current codebase, might be better to go for noqa
ignore = [
"COM", # CONFIG: No trailing commas
"PT", # CONFIG: Not using pytest
"D203", # CONFIG: incompatible with D211
"D212", # CONFIG: incompatible with D213
"FIX002", # CONFIG: we use TODO
"TD002", # CONFIG: no detailed TODO documentation is required
"TD003", # CONFIG: no detailed TODO documentation is required
"S404", # CONFIG: `subprocess` module is possibly insecure
"S603", # CONFIG: `subprocess` call: check for execution of untrusted input
"S607", # CONFIG: executing system installed tools
"D206", # CONFIG: formatter
'ISC001', # CONFIG: formatter
'Q000', # CONFIG: formatter
'Q001', # CONFIG: formatter
'Q002', # CONFIG: formatter
'Q003', # CONFIG: formatter
'W191', # CONFIG: formatter
"E203", # CONFIG: formatter
"EM", # TODO: Exception strings
"PTH", # TODO: Not using pathlib
"FBT", # TODO: Boolean in function definition
"BLE001", # WONTFIX: Do not catch blind exception: `Exception`, third-party modules do not have defined exceptions
"ARG001", # TODO: Unused function argument (mostly for API compatibility)
"ARG002", # TODO: Unused method argument (mostly for API compatibility)
"ANN001", # TODO: Missing type annotation for function argument
"ANN002", # TODO: Missing type annotation for `*args`
"ANN003", # TODO: Missing type annotation for `**kwargs`
"ANN201", # TODO: Missing return type annotation for public function
"ANN202", # TODO: Missing return type annotation for private function
"ANN204", # TODO: Missing return type annotation for special method
"ANN205", # TODO: Missing return type annotation for staticmethod
"ANN206", # TODO: Missing return type annotation for classmethod
"D100", # TODO: Missing docstring in public module
"D101", # TODO: Missing docstring in public class
"D102", # TODO: Missing docstring in public method
"D103", # TODO: Missing docstring in public function
"D104", # TODO: Missing docstring in public package
"D105", # TODO: Missing docstring in magic method
"D106", # TODO: Missing docstring in public nested class
"D107", # TODO: Missing docstring in `__init__`
"DOC", # TODO: Ignore all pydoclint rules for now
"TRY003", # WONTFIX: Avoid specifying long messages outside the exception class
"PERF203", # WONTFIX: This rule is only enforced for Python versions prior to 3.11
"PLR6301", # TODO: Method could be a function, class method, or static method
"PLR2004", # TODO: Magic value used in comparison, consider replacing 201 with a constant variable
"PLC0415", # TODO: `import` should be at the top-level of a file
"RUF001", # WONTFIX: String contains ambiguous unicode character, we are using Unicode
"RUF012", # TODO: Mutable class attributes should be annotated with `typing.ClassVar`
"E501", # WONTFIX: we accept long strings (rest is formatted by black)
"A005", # WONTFIX: Module is shadowing a Python builtin module
"PLW2901", # TODO: overwriting variables inside loop
"PLW1514", # TODO: `open` in text mode without explicit `encoding` argument
"FURB101", # TODO: `open` and `read` should be replaced by `Path(hostsfile).read_text()`
"FURB103" # TODO: `open` and `write` should be replaced by `Path(name).write_text(content)`
]
preview = true
select = ["ALL"]
[tool.ruff.lint.flake8-copyright]
min-file-size = 2
# Copyright without a year, see https://github.com/astral-sh/ruff/issues/10062
notice-rgx = "(?i)Copyright\\s+©\\s+"
[tool.ruff.lint.mccabe]
max-complexity = 16 # TODO: should be lower
[tool.ruff.lint.per-file-ignores]
"docs/_ext/djangodocs.py" = ["INP001"]
"docs/conf.py" = ["INP001", "ERA001"]
"scripts/*" = ["T201", "T203"]
"weblate/*/tests**.py" = ["S106", "S105"]
"weblate/auth/migrations/0003_fixup_teams.py" = ["T201"]
"weblate/examples/*.py" = ["INP001"]
"weblate/settings_*.py" = ["F405"]
"weblate/settings_example.py" = ["ERA001"]
"weblate/utils/generate_secret_key.py" = ["T201"]
[tool.ruff.lint.pylint]
# TODO: all these should be lower (or use defaults)
max-args = 12
max-bool-expr = 8
max-branches = 36
max-locals = 23
max-nested-blocks = 9
max-positional-args = 8
max-public-methods = 180
max-returns = 21
max-statements = 100
[tool.setuptools]
include-package-data = true
zip-safe = false
[tool.setuptools.dynamic]
version = {attr = "weblate.utils.version.VERSION"}
[tool.setuptools.packages]
find = {namespaces = false}