pyproject.toml
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "integreat-cms"
description = "Content Management System for the Integreat App"
version = "2024.11.0"
authors = [{name = "Tür an Tür – Digitalfabrik gGmbH", email = "tech@integreat-app.de"}]
readme = "README.md"
requires-python = ">=3.11"
keywords = [
"integreat",
"cms",
"django",
"e-government",
"newcomers",
"refugees",
"multilingual",
]
license = {text = "Apache2 2.0 License"}
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Framework :: Django",
"Framework :: Django :: 3.2",
"Intended Audience :: Developers",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: Apache Software License",
"Natural Language :: English",
"Natural Language :: German",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content :: Content Management System",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
]
dependencies = [
"aiohttp",
"argon2-cffi",
"bcrypt",
"cffi",
"deepl",
"Django>=4.2,<5.0",
"django-cacheops",
"django-cors-headers",
"django-db-mutex",
"django-debug-toolbar",
"django-import-export==3.3.9",
"django-linkcheck",
"django-polymorphic",
"django-redis",
"django-treebeard",
"django-webpack-loader",
"django-widget-tweaks",
"feedparser",
"geopy",
"google-auth",
"google-cloud-translate",
"icalendar",
"idna",
"ipython",
"jsonschema",
"lxml",
"natsort",
"Pillow",
"psycopg[binary]",
"pyotp",
"python-dateutil",
"python-magic",
"pyyaml",
"qrcode",
"requests",
"rules",
"six",
"webauthn",
"xhtml2pdf==0.2.8",
"reportlab<4.0.0",
"zammad-py"
]
[project.optional-dependencies]
dev = [
"black",
"build",
"bumpver",
"djlint",
"freezegun",
"isort",
"mypy",
"pre-commit",
"pyjwt",
"pylint",
"pylint-django",
"pylint-per-file-ignores",
"pytest-circleci-parallelized",
"pytest-cov",
"pytest-django",
"pytest-httpserver",
"pytest-icdiff",
"pytest-order",
"pytest-testmon<=1.4.5",
"pytest-xdist",
"requests-mock",
"ruff",
"shellcheck-py",
"sphinx",
"sphinx-last-updated-by-git",
"sphinx-rtd-theme",
"sphinxcontrib-django",
"twine",
"types-python-dateutil",
"types-PyYAML",
"types-requests",
]
pinned = [
"aiohappyeyeballs==2.4.2",
"aiohttp==3.10.8",
"aiosignal==1.3.1",
"arabic-reshaper==3.0.0",
"argon2-cffi==23.1.0",
"argon2-cffi-bindings==21.2.0",
"asgiref==3.8.1",
"asn1crypto==1.5.1",
"asttokens==2.4.1",
"attrs==24.2.0",
"bcrypt==4.2.0",
"cachetools==5.5.0",
"cbor2==5.6.4",
"certifi==2024.8.30",
"cffi==1.17.1",
"charset-normalizer==3.3.2",
"click==8.1.7",
"cryptography==43.0.1",
"cssselect2==0.7.0",
"decorator==5.1.1",
"deepl==1.19.1",
"defusedxml==0.7.1",
"diff-match-patch==20230430",
"Django==4.2.16",
"django-cacheops==7.0.2",
"django-cors-headers==4.4.0",
"django-db-mutex==3.1.0",
"django-debug-toolbar==4.4.6",
"django-import-export==3.3.9",
"django-linkcheck==2.3.0",
"django-polymorphic==3.1.0",
"django-redis==5.4.0",
"django-treebeard==4.7.1",
"django-webpack-loader==3.1.1",
"django-widget-tweaks==1.5.0",
"et-xmlfile==1.1.0",
"executing==2.1.0",
"feedparser==6.0.11",
"frozenlist==1.4.1",
"funcy==2.0",
"geographiclib==2.0",
"geopy==2.4.1",
"google-api-core==2.20.0",
"googleapis-common-protos==1.65.0",
"google-auth==2.35.0",
"google-cloud-core==2.4.1",
"google-cloud-translate==3.16.0",
"grpc-google-iam-v1==0.13.1",
"grpcio==1.66.2",
"grpcio-status==1.66.2",
"html5lib==1.1",
"icalendar==6.0.0",
"idna==3.10",
"ipython==8.27.0",
"jedi==0.19.1",
"jsonschema==4.23.0",
"jsonschema-specifications==2023.12.1",
"lxml==5.3.0",
"MarkupPy==1.14",
"matplotlib-inline==0.1.7",
"multidict==6.1.0",
"natsort==8.4.0",
"odfpy==1.4.1",
"openpyxl==3.1.5",
"oscrypto==1.3.0",
"parso==0.8.4",
"pexpect==4.9.0",
"pillow==10.4.0",
"pip==24.0",
"prompt_toolkit==3.0.48",
"protobuf==5.28.2",
"proto-plus==1.24.0",
"psycopg==3.2.3",
"psycopg-binary==3.2.3",
"ptyprocess==0.7.0",
"pure_eval==0.2.3",
"pyasn1==0.6.1",
"pyasn1_modules==0.4.1",
"pycparser==2.22",
"Pygments==2.18.0",
"pyHanko==0.25.1",
"pyhanko-certvalidator==0.26.3",
"pyOpenSSL==24.2.1",
"pyotp==2.9.0",
"PyPDF3==1.0.6",
"pypng==0.20220715.0",
"python-bidi==0.6.0",
"python-dateutil==2.9.0.post0",
"python-magic==0.4.27",
"PyYAML==6.0.2",
"qrcode==7.4.2",
"redis==5.1.0",
"referencing==0.35.1",
"reportlab==3.6.13",
"requests==2.32.3",
"rpds-py==0.20.0",
"rsa==4.9",
"rules==3.5",
"setuptools==65.5.0",
"sgmllib3k==1.0.0",
"six==1.16.0",
"sqlparse==0.5.1",
"stack-data==0.6.3",
"svglib==1.5.1",
"tablib==3.5.0",
"tinycss2==1.3.0",
"tqdm==4.66.5",
"traitlets==5.14.3",
"typing_extensions==4.12.2",
"tzdata==2024.2",
"tzlocal==5.2",
"uritools==4.0.3",
"urllib3==2.2.3",
"wcwidth==0.2.13",
"webauthn==2.2.0",
"webencodings==0.5.1",
"xhtml2pdf==0.2.8",
"xlrd==2.0.1",
"xlwt==1.3.0",
"yarl==1.13.1",
"zammad-py==3.0.0",
]
dev-pinned = [
"alabaster==0.7.16",
"astroid==3.3.4",
"babel==2.16.0",
"backports.tarfile==1.2.0",
"black==24.8.0",
"build==1.2.2",
"bumpver==2023.1129",
"cfgv==3.4.0",
"colorama==0.4.6",
"coverage==7.6.1",
"cssbeautifier==1.15.1",
"dill==0.3.9",
"distlib==0.3.8",
"djlint==1.35.2",
"docutils==0.20.1",
"EditorConfig==0.12.4",
"execnet==2.1.1",
"filelock==3.16.1",
"freezegun==1.5.1",
"html-tag-names==0.1.2",
"html-void-elements==0.1.0",
"icdiff==2.0.7",
"identify==2.6.1",
"imagesize==1.4.1",
"importlib_metadata==8.5.0",
"iniconfig==2.0.0",
"isort==5.13.2",
"jaraco.classes==3.4.0",
"jaraco.context==6.0.1",
"jaraco.functools==4.1.0",
"jeepney==0.8.0",
"Jinja2==3.1.4",
"jsbeautifier==1.15.1",
"json5==0.9.25",
"keyring==25.4.1",
"lexid==2021.1006",
"looseversion==1.3.0",
"markdown-it-py==3.0.0",
"MarkupSafe==2.1.5",
"mccabe==0.7.0",
"mdurl==0.1.2",
"more-itertools==10.5.0",
"mypy==1.11.2",
"mypy-extensions==1.0.0",
"nh3==0.2.18",
"nodeenv==1.9.1",
"packaging==24.1",
"pathspec==0.12.1",
"pkginfo==1.10.0",
"platformdirs==4.3.6",
"pluggy==1.5.0",
"pprintpp==0.4.0",
"pre-commit==3.8.0",
"PyJWT==2.9.0",
"pylint==3.3.1",
"pylint-django==2.5.5",
"pylint-per-file-ignores==1.3.2",
"pylint-plugin-utils==0.8.2",
"pyproject_hooks==1.2.0",
"pytest==7.4.4",
"pytest-circleci-parallelized==0.1.0",
"pytest-cov==5.0.0",
"pytest-django==4.9.0",
"pytest_httpserver==1.1.0",
"pytest-icdiff==0.9",
"pytest-order==1.3.0",
"pytest-testmon==1.4.5",
"pytest-xdist==3.6.1",
"readme_renderer==43.0",
"regex==2024.9.11",
"requests-mock==1.12.1",
"requests-toolbelt==1.0.0",
"rfc3986==2.0.0",
"rich==13.8.1",
"ruff==0.6.8",
"SecretStorage==3.3.3",
"shellcheck-py==0.10.0.1",
"snowballstemmer==2.2.0",
"Sphinx==7.4.7",
"sphinxcontrib-applehelp==2.0.0",
"sphinxcontrib-devhelp==2.0.0",
"sphinxcontrib-django==2.5",
"sphinxcontrib-htmlhelp==2.1.0",
"sphinxcontrib-jquery==4.1",
"sphinxcontrib-jsmath==1.0.1",
"sphinxcontrib-qthelp==2.0.0",
"sphinxcontrib-serializinghtml==2.0.0",
"sphinx-last-updated-by-git==0.3.8",
"sphinx-rtd-theme==2.0.0",
"toml==0.10.2",
"tomlkit==0.13.2",
"twine==5.1.1",
"types-python-dateutil==2.9.0.20240906",
"types-PyYAML==6.0.12.20240917",
"types-requests==2.32.0.20240914",
"virtualenv==20.26.6",
"Werkzeug==3.0.4",
"zipp==3.20.2",
]
[project.urls]
"Homepage" = "https://integreat-app.de/en/"
"Source Code" = "https://github.com/digitalfabrik/integreat-cms"
"Issues" = "https://github.com/digitalfabrik/integreat-cms/issues"
"Release Notes" = "https://digitalfabrik.github.io/integreat-cms/release-notes.html"
"Documentation" = "https://digitalfabrik.github.io/integreat-cms/"
"Funding" = "https://integreat-app.de/en/donation/"
[tool.setuptools]
script-files = ["integreat_cms/integreat-cms-cli"]
license-files = ["LICENSE", "NOTICE.md"]
[tool.setuptools.packages.find]
include = ["integreat_cms*"]
[tool.bumpver]
current_version = "2024.11.0"
version_pattern = "YYYY.MM.INC0[-TAG]"
commit_message = """
Bump version to {new_version}
[skip ci]
"""
commit = true
tag = false
push = false
[tool.bumpver.file_patterns]
"pyproject.toml" = [
'current_version = "{version}"',
'version = "{version}"',
]
"integreat_cms/__init__.py" = [
'__version__ = "{version}"',
]
"docs/src/conf.py" = [
'release = "{version}"',
]
[tool.coverage.report]
exclude_also = [
"def __repr__",
"if TYPE_CHECKING:",
"raise NotImplementedError",
]
[tool.djlint]
profile="django"
line_break_after_multiline_tag=true
# exclude invalid html files until this is resolved https://github.com/djlint/djLint/issues/703
exclude = "integreat_cms/api/v3/templates/"
[tool.isort]
profile = "black"
order_by_type = false
[tool.pylint.main]
jobs = 0
load-plugins = [
"pylint_django",
"pylint_per_file_ignores",
"pylint.extensions.code_style",
"pylint.extensions.comparison_placement",
"pylint.extensions.consider_ternary_expression",
"pylint.extensions.docparams",
"pylint.extensions.for_any_all",
]
recursive = true
ignore-paths = [
".venv",
"node_modules",
"build",
]
fail-on = "I"
extension-pkg-whitelist = ["lxml"]
django-settings-module="integreat_cms.core.settings"
[tool.pylint.design]
max-args = 7
max-attributes = 7
max-branches = 12
max-locals = 15
max-parents = 8
max-position = 6
[tool.pylint.messages_control]
disable = [
"consider-using-namedtuple-or-dataclass",
"consider-using-tuple",
"duplicate-code",
"invalid-name",
"line-too-long",
"missing-module-docstring",
"no-member",
"too-many-lines",
"ungrouped-imports",
"unsupported-binary-operation",
"wrong-import-position",
]
enable = [
"consider-using-augmented-assign",
"use-implicit-booleaness-not-comparison-to-string",
"use-implicit-booleaness-not-comparison-to-zero",
"useless-suppression",
]
[tool.pylint.reports]
output-format = "colorized"
[tool.pylint-per-file-ignores]
"/tests/"="unused-argument,missing-function-docstring"
[tool.mypy]
disallow_untyped_defs = true
ignore_missing_imports = true
warn_redundant_casts = true
strict_equality = true
[tool.ruff]
line-length = 279
target-version = "py311"
[tool.ruff.lint]
select = [
"I", # isort
"A", # flake8-builtins
"AIR", # Airflow
"ASYNC", # flake8-async
"BLE", # flake8-blind-except
"C4", # flake8-comprehensions
"C90", # McCabe cyclomatic complexity
"DJ", # flake8-django
"E", # pycodestyle
"EXE", # flake8-executable
"F", # Pyflakes
"FA", # flake8-future-annotations
"FIX", # flake8-fixme
"FLY", # flynt
"G", # flake8-logging-format
"ICN", # flake8-import-conventions
"INP", # flake8-no-pep420
"INT", # flake8-gettext
"ISC", # flake8-implicit-str-concat
"LOG", # flake8-logging
"NPY", # NumPy-specific rules
"PD", # pandas-vet
"PERF", # Perflint
"PGH", # pygrep-hooks
"PIE", # flake8-pie
"PL", # Pylint
"PYI", # flake8-pyi
"RSE", # flake8-raise
"SLOT", # flake8-slots
"T10", # flake8-debugger
"TRIO", # flake8-trio
"W", # pycodestyle
"YTT", # flake8-2020
# "ANN", # flake8-annotations
# "ARG", # flake8-unused-arguments
# "B", # flake8-bugbear
# "COM", # flake8-commas
# "CPY", # flake8-copyright
# "D", # pydocstyle
# "DTZ", # flake8-datetimez
# "EM", # flake8-errmsg
# "ERA", # eradicate
# "FBT", # flake8-boolean-trap
# "FURB", # refurb
# "N", # pep8-naming
# "PT", # flake8-pytest-style
# "PTH", # flake8-use-pathlib
# "Q", # flake8-quotes
# "RET", # flake8-return
# "RUF", # Ruff-specific rules
# "S", # flake8-bandit
# "SIM", # flake8-simplify
# "SLF", # flake8-self
# "T20", # flake8-print
# "TCH", # flake8-type-checking
# "TD", # flake8-todos
# "TID", # flake8-tidy-imports
# "TRY", # tryceratops
# "UP", # pyupgrade
]
ignore = [
"F401",
"INP001",
]
[tool.ruff.lint.mccabe]
max-complexity = 23 # default is 10
[tool.ruff.lint.isort]
order-by-type = false
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401", "F403"]
"docs/src/conf.py" = ["A001"]
"integreat_cms/api/v3/*" = ["PERF401"]
"integreat_cms/api/v3/social_media_headers.py" = ["FIX002"]
"integreat_cms/cms/forms/custom_model_form.py" = ["G003", "PERF401"]
"integreat_cms/cms/forms/linkcheck/link_replace_form.py" = ["W605"]
"integreat_cms/cms/forms/pages/page_form.py" = ["PLR5501"]
"integreat_cms/cms/forms/regions/region_form.py" = ["FIX002"]
"integreat_cms/cms/models/abstract_base_model.py" = ["BLE001", "DJ012"]
"integreat_cms/cms/models/poi_categories/poi_category.py" = ["DJ001"]
"integreat_cms/cms/models/push_notifications/push_notification.py" = ["DJ001"]
"integreat_cms/cms/models/users/user.py" = ["DJ001"]
"integreat_cms/cms/views/*" = ["PIE804"]
"integreat_cms/cms/views/analytics/app_size_view.py" = ["FIX002"]
"integreat_cms/core/*_settings.py" = ["F403"]
"integreat_cms/core/circleci_settings.py" = ["F405"]
"integreat_cms/core/management/commands/find_large_files.py" = ["G004"]
"integreat_cms/core/sphinx_settings.py" = ["F405"]
"integreat_cms/google_translate_api/apps.py" = ["BLE001"]
"integreat_cms/google_translate_api/google_translate_api_client.py" = ["BLE001"]
"integreat_cms/nominatim_api/nominatim_api_client.py" = ["PERF401"]
"tests/*" = ["S101"]
"tests/core/management/commands/test_summ_ai_bulk.py" = ["FIX002"]
"tests/deepl_api/deepl_api_test.py" = ["PIE804"]
"tests/pdf/test_pdf_export.py" = ["PLW2901"]
"tests/summ_ai_api/summ_ai_test.py" = ["PLW0603"]
"tests/textlab_api/textlab_api_test.py" = ["A002"]
[tool.ruff.lint.pylint]
allow-magic-value-types = ["float", "int", "str"]
max-args = 8 # default is 5
max-bool-expr = 5 # default is 5
max-branches = 22 # default is 12
max-locals = 15 # default is 15
max-positional-args = 5 # default is 5
max-returns = 12 # default is 6
max-statements = 64 # default is 50