pyproject.toml
[build-system]
build-backend = "poetry.core.masonry.api"
requires = ["poetry-core"]
[tool.poetry]
authors = ["Fedor Borshev <fedor@borshev.com>"]
description = ""
name = "education-backend"
readme = "README.md"
version = "2023.10.20"
[tool.poetry.dependencies]
babel = "^2.12.1"
bcrypt = "^4.0.1"
bleach = "^6.0.0"
boto3 = "^1.28.48"
celery = "5.4.0"
cmarkgfm = "^2024.0.0"
dj-rest-auth = "^5.0.0"
django = "^4.2.5"
django-anymail = "^10.1"
django-axes = "^6.1.1"
django-behaviors = "^0.5.1"
django-cachalot = "^2.6.1"
django-cors-headers = "^4.2.0"
django-debug-toolbar = "^4.2.0"
django-environ = "^0.11.2"
django-filter = "^23.2"
django-healthchecks = "^1.5.0"
django-ipware = "^6.0.0"
django-prettyjson = "^0.4.1"
django-split-settings = "^1.2.0"
django-storages = "^1.14"
django-tree-queries = "^0.19.0"
djangorestframework = "^3.14.0"
drf-jwt = "^1.19.2"
drf-recaptcha = "^3.0.0"
drf-spectacular = {extras = ["sidecar"], version = "^0.27.0"}
emoji = "^2.8.0"
httpx = {extras = ["http2"], version = "^0.27.0"}
pillow = "^10.1.0"
psycopg2-binary = "^2.9.7"
python = "~3.11"
python-benedict = "^0.33.0"
redis = "^5.0.0"
retry = "^0.9.2"
sentry-sdk = "^1.31.0"
shortuuid = "^1.0.11"
simplejson = "^3.19.1"
stripe = "^6.5.0"
whitenoise = "^6.5.0"
[tool.poetry.group.dev.dependencies]
boto3-stubs = "^1.28.48"
django-stubs = "^4.2.6"
djangorestframework-stubs = "^3.14.4"
freezegun = "^1.2.2"
ipython = "^8.15.0"
jedi = "^0.19.0"
mixer = "^7.2.2"
mypy = "^1.6.1"
pymarkdownlnt = "^0.9.13.4"
pytest-cov = "^5.0.0"
pytest-deadfixtures = "^2.2.1"
pytest-django = "^4.5.2"
pytest-env = "^1.0.1"
pytest-freezegun = "^0.4.2"
pytest-mock = "^3.11.1"
pytest-randomly = "^3.15.0"
pytest-repeat = "^0.9.1"
pytest-xdist = "^3.3.1"
requests-mock = "^1.11.0"
respx = "^0.21.0"
rope = "^1.10.0"
ruff = "^0.4.0"
toml-sort = "^0.23.1"
types-babel = "^2.11.0.15"
types-bleach = "^6.0.0.4"
types-freezegun = "^1.1.10"
types-markdown = "^3.4.2.10"
types-pillow = "^10.0.0.3"
types-requests = "^2.31.0.2"
types-retry = "^0.9.9.4"
types-simplejson = "^3.19.0.2"
types-stripe = "^3.5.2.14"
[tool.pymarkdown.plugins.md013]
enabled = false
[tool.pymarkdown.plugins.md045]
enabled = false
[tool.pytest.ini_options]
DJANGO_SETTINGS_MODULE = "core.settings"
addopts = "--reuse-db"
env = [
"CELERY_ALWAYS_EAGER = on",
"CI = 1",
"DEFAULT_FILE_STORAGE = django.core.files.storage.memory.InMemoryStorage",
"DISABLE_HOMEWORK_PERMISSIONS_CHECKING = on",
"DISABLE_NEW_ANSWER_NOTIFICATIONS = on",
"DISABLE_THROTTLING = on",
"RECAPTCHA_ENABLED = off",
]
filterwarnings = [
"error",
"ignore:'cgi' is deprecated",
"ignore:SelectableGroups dict interface is deprecated",
"ignore:distutils Version classes are deprecated. Use packaging.version instead.:DeprecationWarning:pytest_freezegun:17",
"ignore:pkg_resources is deprecated as an API",
"ignore:unclosed file:ResourceWarning",
]
markers = [
"auditlog: enable admin logging",
"dashamail: enable automatic dashamail subscription (may have to patch some code to avoid actual internet connection",
"freeze_time: freezing time marker (pytest-freezegun does not register it)",
"single_thread: marked tests should be ran only in single thread",
"slow: tests with inentional slow run",
"user_tags_rebuild: enable automatic user tags rebuilding where it supposed to happen in the production app (sloow)",
]
python_files = "test*.py"
pythonpath = ". src"
[tool.ruff]
line-length = 160
target-version = "py311"
[tool.ruff.lint]
ignore = [
"A001", # variable `{}` is shadowing a Python builtin
"A002", # argument `{}` is shadowing a Python builtin
"A003", # class attribute `{}` is shadowing a Python builtin
"ANN101", # missing type annotation for `self` in method
"ANN102", # missing type annotation for `cls` in classmethod
"ANN401", # dynamically typed expressions (typing.Any) are disallowed in `{}`
"ARG002", # unused method argument: `{}`
"ARG005", # unused lambda argument: `{}`
"B018", # found useless expression. Either assign it to a variable or remove it
"B904", # within an `except` clause, raise exceptions with [...]
"B904", # use `raise from` to specify exception cause
"C408", # unnecessary `dict` call (rewrite as a literal)
"COM812", # trailing comma missing
"COM819", # trailing comma prohibited
"D100", # missing docstring in public module
"D101", # missing docstring in public class
"D102", # missing docstring in public method
"D103", # missing docstring in public function
"D104", # missing docstring in public package
"D105", # missing docstring in magic method
"D106", # missing docstring in public nested class
"D107", # missing docstring in `__init__`
"D200", # one-line docstring should fit on one line
"D202", # no blank lines allowed after function docstring (found {})
"D203", # 1 blank line required before class docstring
"D205", # 1 blank line required between summary line and description
"D209", # multi-line docstring closing quotes should be on a separate line
"D210", # no whitespaces allowed surrounding docstring text
"D212", # multi-line docstring summary should start at the first line
"D213", # multi-line docstring summary should start at the second line
"D400", # first line should end with a period
"D401", # first line of docstring should be in imperative mood: "{}"
"D404", # first word of the docstring should not be "This"
"D415", # first line should end with a period, question mark, or exclamation point
"DJ007", # do not use `__all__` with `ModelForm`, use `fields` instead
"DTZ001", # the use of `datetime.datetime()` without `tzinfo` argument is not allowed
"E501", # line too long ({} > {})
"EM101", # exception must not use a string literal, assign to variable first
"EM102", # expection must not use an f-string literal, assign to variable first
"F811", # redefinition of unused `{}` from line {}
"FBT001", # boolean-typed position argument in function definition
"FBT002", # boolean default position argument in function definition
"FBT003", # boolean positional value in function call
"INP001", # file `{}` is part of an implicit namespace package. Add an `__init__.py`
"INT001", # f-string is resolved before function call; consider `_("string %s") % arg`
"ISC001", # implicitly concatenated string literals on one line
"N802", # function name `{}` should be lowercase
"N803", # argument name `{}` should be lowercase
"N804", # first argument of a class method should be named `cls`
"N806", # variable `{}` in function should be lowercase
"N812", # lowercase `{}` imported as non-lowercase `{}`
"N818", # exception name `{}` should be named with an Error suffix
"N999", # invalid module name: '{}'
"PERF401", # use a list comprehension to create a transformed list
"PGH003", # use specific rule codes when ignoring type issues
"PGH004", # use specific rule codes when using `noqa`
"PLR0913", # too many arguments in function definition ({} > {})
"PLR2004", # magic value used in comparison, consider replacing {} with constant variable
"PLR5501", # use `elif` instead of `else` then `if` to reduce indentation
"PLW0603", # using the global statement to update `{}` is discouraged
"PLW2901", # `for` loop variable `{}` overwritten by assignment target
"PT001", # use `@pytest.fixture()` over `@pytest.fixture`
"PT006", # wrong name(s) type in `@pytest.mark.parametrize`, expected `{}`
"PTH118", # `os.path.join()` should be replaced by `Path` with `/` operator
"PTH119", # `os.path.basename()` should be replaced by `Path.name`
"PTH120", # `os.path.dirname()` should be replaced by `Path.parent`
"PTH122", # `os.path.splitext()` should be replaced by `Path.suffix`, [...]
"PTH123", # `open()` should be replaced by `Path.open()`
"Q000", # single quotes found but double quotes preferred
"RET501", # do not explicitly `return None` in function if it is the only possible return value
"RET502", # do not implicitly `return None` in function able to return non-`None` value
"RET503", # missing explicit `return` at the end of function able to return non-`None` value
"RET504", # unnecessary assignment to `{}` before `return` statement
"RET505", # unnecessary `else` after `return` statement
"RSE102", # unnecessary parentheses on raised exception
"RUF001", # string contains ambiguous `{}` [...]
"RUF002", # docstring contains ambiguous `{}` [...]
"RUF005", # consider iterable unpacking instead of concatenation"
"RUF009", # do not perform function call `{}` in dataclass defaults
"RUF012", # mutable class attributes should be annotated with `typing.ClassVar`
"RUF015", # prefer next({iterable}) over single element slice
"RUF100", # unused `noqa` directive (unknown: `{}`)
"S101", # use of `assert` detected
"S105", # possible hardcoded password assigned to: "{}"
"S105", # possible hardcoded password assigned to: "{}"
"S106", # possible hardcoded password assigned to argument: "{}"
"S308", # use of `mark_safe` may expose cross-site scripting vulnerabilities
"S311", # standart pseudo-random generators are not suitable for cryptographic purposes
"S324", # probable use of insecure hash functions in `{}`: `{}`
"SIM102", # use a single `if` statement instead of nested `if` statements
"SIM108", # use ternary operator `{}` instead of `if`-`else`-block
"SIM300", # yoda conditions are discouraged, use `{}` instead
"SLF001", # private member accessed: `{}`
"TCH001", # move application import `{}` into a type-checking block
"TCH002", # move third-party import `{}` into a type-checking block
"TCH003", # move standart library import `{}` into a type-checking block
"TRY003", # avoid specifying long messages outside the exception class
"TRY300", # consider moving this statement to an `else` block
"UP006", # use `{}` instead of `{}` for type annotation
"UP015", # unnecessary open mode parameters
"UP017", # use `datetime.UTC` alias
"UP035", # `{}` is deprecated, use `{}` instead
]
select = ["ALL"]
[tool.ruff.lint.flake8-tidy-imports]
ban-relative-imports = "all"
[tool.ruff.lint.isort]
known-local-folder = ["apps", "core"]
[tool.ruff.lint.per-file-ignores]
"*/management/*" = [
"ANN", # flake8-annotations
]
"*/migrations/*" = [
"ANN", # flake8-annotations
]
"src/core/conf/*" = [
"ANN", # flake8-annotations
]
"src/core/test/api_client.py" = [
"ANN", # flake8-annotations
]
"tests/*" = [
"ANN", # flake8-annotations
]
[tool.tomlsort]
all = true
in_place = true
sort_first = ["tool.poetry"]
spaces_before_inline_comment = 2
spaces_indent_inline_array = 4
trailing_comma_inline_array = true