mirror of
https://github.com/Crocmagnon/charasheet.git
synced 2024-11-22 14:38:03 +01:00
Introduce ruff
This commit is contained in:
parent
b54ffd73f4
commit
8003157daf
29 changed files with 206 additions and 142 deletions
2
.github/workflows/test.yaml
vendored
2
.github/workflows/test.yaml
vendored
|
@ -24,6 +24,8 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
pip install pip-tools
|
pip install pip-tools
|
||||||
pip-sync requirements.txt requirements-dev.txt
|
pip-sync requirements.txt requirements-dev.txt
|
||||||
|
- name: Ruff
|
||||||
|
run: ruff --format=github .
|
||||||
- name: Test
|
- name: Test
|
||||||
run: pytest --cov=. --cov-branch --cov-report term-missing:skip-covered
|
run: pytest --cov=. --cov-branch --cov-report term-missing:skip-covered
|
||||||
working-directory: ./src/
|
working-directory: ./src/
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<option name="workingDir" value="" />
|
<option name="workingDir" value="" />
|
||||||
<envs />
|
<envs />
|
||||||
</TaskOptions>
|
</TaskOptions>
|
||||||
<TaskOptions isEnabled="true">
|
<TaskOptions isEnabled="false">
|
||||||
<option name="arguments" value="run flakeheaven --file $FilePath$" />
|
<option name="arguments" value="run flakeheaven --file $FilePath$" />
|
||||||
<option name="checkSyntaxErrors" value="true" />
|
<option name="checkSyntaxErrors" value="true" />
|
||||||
<option name="description" />
|
<option name="description" />
|
||||||
|
@ -41,5 +41,25 @@
|
||||||
<option name="workingDir" value="" />
|
<option name="workingDir" value="" />
|
||||||
<envs />
|
<envs />
|
||||||
</TaskOptions>
|
</TaskOptions>
|
||||||
|
<TaskOptions isEnabled="true">
|
||||||
|
<option name="arguments" value="run ruff --file $FilePath$" />
|
||||||
|
<option name="checkSyntaxErrors" value="true" />
|
||||||
|
<option name="description" />
|
||||||
|
<option name="exitCodeBehavior" value="ERROR" />
|
||||||
|
<option name="fileExtension" value="py" />
|
||||||
|
<option name="immediateSync" value="false" />
|
||||||
|
<option name="name" value="ruff" />
|
||||||
|
<option name="output" value="$FilePath$" />
|
||||||
|
<option name="outputFilters">
|
||||||
|
<array />
|
||||||
|
</option>
|
||||||
|
<option name="outputFromStdout" value="false" />
|
||||||
|
<option name="program" value="$USER_HOME$/.local/pipx/venvs/pre-commit/bin/pre-commit" />
|
||||||
|
<option name="runOnExternalChanges" value="false" />
|
||||||
|
<option name="scopeName" value="Project Files" />
|
||||||
|
<option name="trackOnlyRoot" value="false" />
|
||||||
|
<option name="workingDir" value="" />
|
||||||
|
<envs />
|
||||||
|
</TaskOptions>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -33,11 +33,6 @@ repos:
|
||||||
hooks:
|
hooks:
|
||||||
- id: django-upgrade
|
- id: django-upgrade
|
||||||
args: [--target-version, "4.1"]
|
args: [--target-version, "4.1"]
|
||||||
- repo: https://github.com/PyCQA/isort
|
|
||||||
rev: 5.11.4
|
|
||||||
hooks:
|
|
||||||
- id: isort
|
|
||||||
args: [--profile, black]
|
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 22.12.0
|
rev: 22.12.0
|
||||||
hooks:
|
hooks:
|
||||||
|
@ -47,20 +42,11 @@ repos:
|
||||||
rev: v1.5.2
|
rev: v1.5.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: djhtml
|
- id: djhtml
|
||||||
- repo: https://github.com/flakeheaven/flakeheaven
|
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||||
rev: 3.2.1
|
rev: 'v0.0.237'
|
||||||
hooks:
|
hooks:
|
||||||
- id: flakeheaven
|
- id: ruff
|
||||||
additional_dependencies:
|
args: [--fix]
|
||||||
- flake8-annotations-complexity
|
|
||||||
- flake8-bandit
|
|
||||||
- flake8-builtins
|
|
||||||
- flake8-bugbear
|
|
||||||
- flake8-comprehensions
|
|
||||||
- flake8-docstrings
|
|
||||||
- flake8-eradicate
|
|
||||||
- flake8-noqa
|
|
||||||
- pep8-naming
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||||
rev: v3.0.0-alpha.4
|
rev: v3.0.0-alpha.4
|
||||||
hooks:
|
hooks:
|
||||||
|
|
107
pyproject.toml
107
pyproject.toml
|
@ -30,44 +30,81 @@ python_files = [
|
||||||
]
|
]
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# flake8 / flakeheaven
|
# ruff
|
||||||
###############################################################################
|
###############################################################################
|
||||||
[tool.flakeheaven]
|
[tool.ruff]
|
||||||
max_complexity = 10
|
src = ["src"]
|
||||||
format = "grouped"
|
target-version = "py311"
|
||||||
|
select = [
|
||||||
|
"F", # pyflakes
|
||||||
|
"E", "W", # pycodestyle
|
||||||
|
"C90", # mccabe
|
||||||
|
"I", # isort
|
||||||
|
"N", # pep8-naming
|
||||||
|
"D", # pydocstyle
|
||||||
|
"S", # flake8-bandit
|
||||||
|
"FBT", # flake8-boolean-trap
|
||||||
|
"B", # flake8-bugbear
|
||||||
|
"A", # flake8-builtins
|
||||||
|
"C4", # flake8-comprehensions
|
||||||
|
"DTZ", # flake8-datetimez
|
||||||
|
"T10", # flake8-debugger
|
||||||
|
"EXE", # flake8-executable
|
||||||
|
"ISC", # flake8-implicit-str-concat
|
||||||
|
"ICN", # flake8-import-conventions
|
||||||
|
"G", # flake8-logging-format
|
||||||
|
"INP", # flake8-no-pep420
|
||||||
|
"PIE", # flake8-pie
|
||||||
|
"T20", # flake8-print
|
||||||
|
"PT", # flake8-pytest-style
|
||||||
|
"RET", # flake8-return
|
||||||
|
"SIM", # flake8-simplify
|
||||||
|
"TID", # flake8-tidy-imports
|
||||||
|
"ARG", # flake8-unused-arguments
|
||||||
|
"PTH", # flake8-use-pathlib
|
||||||
|
"ERA", # eradicate
|
||||||
|
"PD", # pandas-vet
|
||||||
|
"PGH", # pygrep-hooks
|
||||||
|
"PL", # pylint
|
||||||
|
"TRY", # tryceratops
|
||||||
|
"RUF", # ruff-specific rules
|
||||||
|
]
|
||||||
|
unfixable = ["T20", "RUF001", "RUF002", "RUF003"]
|
||||||
|
|
||||||
# Base rules
|
ignore = [
|
||||||
#############################
|
"UP", # pyupgrade
|
||||||
[tool.flakeheaven.plugins]
|
"YTT", # flake8-2020
|
||||||
"*" = [
|
"ANN", # flake8-annotations
|
||||||
"+*",
|
"BLE", # flake8-blind-except
|
||||||
"-E501", # long lines
|
"COM", # flake8-commas
|
||||||
"-E203", # conflict with black on PEP8 interpretation
|
"EM", # flake8-errmsg
|
||||||
"-W503", # deprecated rule: https://www.flake8rules.com/rules/W503.html
|
"Q", # flake8-quotes
|
||||||
]
|
"TCH", # flake8-type-checking / TODO: revisit later ?
|
||||||
flake8-builtins = [
|
|
||||||
"+*",
|
"E501", # long lines
|
||||||
"-A003", # class attribute is shadowing a python builtin
|
"D1", # missing docstring
|
||||||
]
|
"TRY003", # Avoid specifying long messages outside the exception class
|
||||||
flake8-docstrings = [
|
|
||||||
"+*",
|
|
||||||
"-D1??", # missing docstring
|
|
||||||
]
|
|
||||||
flake8-bandit = [
|
|
||||||
"+*",
|
|
||||||
"-S308", # Use of mark_safe() may expose cross-site scripting vulnerabilities and should be reviewed.
|
|
||||||
"-S703", # Potential XSS on mark_safe function.
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Exceptions
|
[tool.ruff.per-file-ignores]
|
||||||
#############################
|
"**/tests/*" = [
|
||||||
[tool.flakeheaven.exceptions."**/tests/*"]
|
"S101", # Use of assert detected.
|
||||||
flake8-bandit = [
|
"S106", # Possible hardcoded password.
|
||||||
"+*",
|
"B011", # Do not call assert False since python -O removes these calls.
|
||||||
"-S101", # Use of assert detected.
|
"ARG001", # Unused function argument (mostly fixtures)
|
||||||
"-S106", # Possible hardcoded password.
|
"PLR2004", # Magic value used in comparison, consider replacing {value} with a constant variable
|
||||||
"-S311", # Standard pseudo-random generators are not suitable for security/cryptographic purposes.
|
|
||||||
]
|
]
|
||||||
flake8-bugbear = [
|
# File {name} is part of an implicit namespace package. Add an `__init__.py`.
|
||||||
"-B011", # Do not call assert False since python -O removes these calls.
|
"tasks.py" = ["INP001"]
|
||||||
|
"src/conftest.py" = ["INP001"]
|
||||||
|
"src/manage.py" = ["INP001"]
|
||||||
|
|
||||||
|
"src/character/management/commands/*" = [
|
||||||
|
"RUF001", # String contains ambiguous unicode character
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[tool.ruff.pydocstyle]
|
||||||
|
convention = "pep257"
|
||||||
|
|
||||||
|
[tool.ruff.mccabe]
|
||||||
|
max-complexity = 10
|
||||||
|
|
|
@ -14,3 +14,4 @@ hypothesis>=6.56.4
|
||||||
django-browser-reload>=1.6.0
|
django-browser-reload>=1.6.0
|
||||||
black>=22.12.0
|
black>=22.12.0
|
||||||
pip-tools>=6.0
|
pip-tools>=6.0
|
||||||
|
ruff>=0.0.237
|
||||||
|
|
|
@ -547,6 +547,24 @@ requests==2.28.2 \
|
||||||
# bpython
|
# bpython
|
||||||
# pytest-base-url
|
# pytest-base-url
|
||||||
# pytest-selenium
|
# pytest-selenium
|
||||||
|
ruff==0.0.237 \
|
||||||
|
--hash=sha256:0cc6cb7c1efcc260df5a939435649610a28f9f438b8b313384c8985ac6574f9f \
|
||||||
|
--hash=sha256:0d122433a21ce4a21fbba34b73fc3add0ccddd1643b3ff5abb8d2767952f872e \
|
||||||
|
--hash=sha256:2ea04d826ffca58a7ae926115a801960c757d53c9027f2ca9acbe84c9f2b2f04 \
|
||||||
|
--hash=sha256:3d6ed86d0d4d742360a262d52191581f12b669a68e59ae3b52e80d7483b3d7b3 \
|
||||||
|
--hash=sha256:46c5977b643aaf2b6f84641265f835b6c7f67fcca38dbae08c4f15602e084ca0 \
|
||||||
|
--hash=sha256:525e5ec81cee29b993f77976026a6bf44528a14aa6edb1ef47bd8079147395ae \
|
||||||
|
--hash=sha256:630c575f543733adf6c19a11d9a02ca9ecc364bd7140af8a4c854d4728be6b56 \
|
||||||
|
--hash=sha256:7eef0c7a1e45a4e30328ae101613575944cbf47a3a11494bf9827722da6c66b3 \
|
||||||
|
--hash=sha256:80ce10718abbf502818c0d650ebab99fdcef5e937a1ded3884493ddff804373c \
|
||||||
|
--hash=sha256:8d6a1d21ae15da2b1dcffeee2606e90de0e6717e72957da7d16ab6ae18dd0058 \
|
||||||
|
--hash=sha256:8ed113937fab9f73f8c1a6c0350bb4fe03e951370139c6e0adb81f48a8dcf4c6 \
|
||||||
|
--hash=sha256:b76311335adda4de3c1d471e64e89a49abfeebf02647e3db064e7740e7f36ed6 \
|
||||||
|
--hash=sha256:bb96796be5919871fa9ae7e88968ba9e14306d9a3f217ca6c204f68a5abeccdd \
|
||||||
|
--hash=sha256:e9bcb71a3efb5fe886eb48d739cfae5df4a15617e7b5a7668aa45ebf74c0d3fa \
|
||||||
|
--hash=sha256:ea239cfedf67b74ea4952e1074bb99a4281c2145441d70bc7e2f058d5c49f1c9 \
|
||||||
|
--hash=sha256:fedfb60f986c26cdb1809db02866e68508db99910c587d2c4066a5c07aa85593
|
||||||
|
# via -r requirements-dev.in
|
||||||
selenium==4.7.2 \
|
selenium==4.7.2 \
|
||||||
--hash=sha256:06a1c7d9f313130b21c3218ddd8852070d0e7419afdd31f96160cd576555a5ce \
|
--hash=sha256:06a1c7d9f313130b21c3218ddd8852070d0e7419afdd31f96160cd576555a5ce \
|
||||||
--hash=sha256:3aefa14a28a42e520550c1cd0f29cf1d566328186ea63aa9a3e01fb265b5894d
|
--hash=sha256:3aefa14a28a42e520550c1cd0f29cf1d566328186ea63aa9a3e01fb265b5894d
|
||||||
|
|
|
@ -43,10 +43,9 @@ class PathAdmin(admin.ModelAdmin):
|
||||||
category = models.Path.Category(instance.category)
|
category = models.Path.Category(instance.category)
|
||||||
if category == models.Path.Category.PROFILE:
|
if category == models.Path.Category.PROFILE:
|
||||||
return str(instance.profile)
|
return str(instance.profile)
|
||||||
elif category == models.Path.Category.RACE:
|
if category == models.Path.Category.RACE:
|
||||||
return str(instance.race)
|
return str(instance.race)
|
||||||
else:
|
return ""
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.RacialCapability)
|
@admin.register(models.RacialCapability)
|
||||||
|
|
|
@ -8,7 +8,7 @@ from character.models import Capability, Path
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options) -> None: # noqa: ARG002
|
||||||
url = "https://www.co-drs.org/fr/jeu/capacites"
|
url = "https://www.co-drs.org/fr/jeu/capacites"
|
||||||
self.setup_selenium()
|
self.setup_selenium()
|
||||||
self.selenium.get(url)
|
self.selenium.get(url)
|
||||||
|
@ -23,7 +23,7 @@ class Command(BaseCommand):
|
||||||
try:
|
try:
|
||||||
self.import_capability(card)
|
self.import_capability(card)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{type(e)}: {e}")
|
self.stderr.write(f"{type(e)}: {e}")
|
||||||
self.stdout.write(f"Finished processing {len(cards)} caps.")
|
self.stdout.write(f"Finished processing {len(cards)} caps.")
|
||||||
|
|
||||||
def import_capability(self, card: WebElement):
|
def import_capability(self, card: WebElement):
|
||||||
|
|
|
@ -7,7 +7,7 @@ from character.models.character import HarmfulState
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
def handle(self, *args, **options) -> None:
|
def handle(self, *args, **options) -> None: # noqa: ARG002
|
||||||
url = "https://www.co-drs.org/fr/jeu/etats-prejudiciables"
|
url = "https://www.co-drs.org/fr/jeu/etats-prejudiciables"
|
||||||
self.setup_selenium()
|
self.setup_selenium()
|
||||||
self.selenium.get(url)
|
self.selenium.get(url)
|
||||||
|
@ -16,7 +16,7 @@ class Command(BaseCommand):
|
||||||
try:
|
try:
|
||||||
self.import_row(url, state)
|
self.import_row(url, state)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{type(e)}: {e}")
|
self.stderr.write(f"{type(e)}: {e}")
|
||||||
self.stdout.write(f"Finished processing {len(states)} states.")
|
self.stdout.write(f"Finished processing {len(states)} states.")
|
||||||
|
|
||||||
def import_row(self, url: str, state_row: WebElement) -> None:
|
def import_row(self, url: str, state_row: WebElement) -> None:
|
||||||
|
|
|
@ -7,7 +7,7 @@ from character.models import Path, Profile, Race
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options) -> None: # noqa: ARG002
|
||||||
url = "https://www.co-drs.org/fr/jeu/voies"
|
url = "https://www.co-drs.org/fr/jeu/voies"
|
||||||
self.setup_selenium()
|
self.setup_selenium()
|
||||||
self.selenium.get(url)
|
self.selenium.get(url)
|
||||||
|
@ -23,7 +23,7 @@ class Command(BaseCommand):
|
||||||
try:
|
try:
|
||||||
self.import_path(url)
|
self.import_path(url)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{type(e)}: {e}")
|
self.stderr.write(f"{type(e)}: {e}")
|
||||||
self.stdout.write(f"Finished processing {len(urls)} paths.")
|
self.stdout.write(f"Finished processing {len(urls)} paths.")
|
||||||
|
|
||||||
def import_path(self, url: str):
|
def import_path(self, url: str):
|
||||||
|
@ -81,9 +81,10 @@ class Command(BaseCommand):
|
||||||
profile_name = self.selenium.find_element(
|
profile_name = self.selenium.find_element(
|
||||||
By.CSS_SELECTOR, ".field--name-type + strong + a"
|
By.CSS_SELECTOR, ".field--name-type + strong + a"
|
||||||
).text
|
).text
|
||||||
return Profile.objects.get_by_natural_key(profile_name)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
self.stdout.write(self.style.WARNING(f"Couldn't find profile for {name}"))
|
self.stdout.write(self.style.WARNING(f"Couldn't find profile for {name}"))
|
||||||
|
else:
|
||||||
|
return Profile.objects.get_by_natural_key(profile_name)
|
||||||
|
|
||||||
def get_race(self, path_name: str) -> Race | None:
|
def get_race(self, path_name: str) -> Race | None:
|
||||||
to_remove = ["voie de la", "voie de l'", "voie du"]
|
to_remove = ["voie de la", "voie de l'", "voie du"]
|
||||||
|
|
|
@ -7,7 +7,7 @@ from character.models.dice import Dice
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
def handle(self, *args, **options) -> None:
|
def handle(self, *args, **options) -> None: # noqa: ARG002
|
||||||
url = "https://www.co-drs.org/fr/jeu/profils"
|
url = "https://www.co-drs.org/fr/jeu/profils"
|
||||||
self.setup_selenium()
|
self.setup_selenium()
|
||||||
self.selenium.get(url)
|
self.selenium.get(url)
|
||||||
|
@ -17,7 +17,7 @@ class Command(BaseCommand):
|
||||||
try:
|
try:
|
||||||
self.import_profile(url)
|
self.import_profile(url)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{type(e)}: {e}")
|
self.stderr.write(f"{type(e)}: {e}")
|
||||||
|
|
||||||
def import_profile(self, url: str) -> None:
|
def import_profile(self, url: str) -> None:
|
||||||
self.selenium.get(url)
|
self.selenium.get(url)
|
||||||
|
@ -48,8 +48,7 @@ class Command(BaseCommand):
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
self.style.WARNING(f"Multiple dice for {name}: {number_of_dice}")
|
self.style.WARNING(f"Multiple dice for {name}: {number_of_dice}")
|
||||||
)
|
)
|
||||||
dice = Dice(dice_value)
|
return Dice(dice_value)
|
||||||
return dice
|
|
||||||
|
|
||||||
def get_magical_strength(self) -> Profile.MagicalStrength:
|
def get_magical_strength(self) -> Profile.MagicalStrength:
|
||||||
try:
|
try:
|
||||||
|
@ -79,7 +78,7 @@ class Command(BaseCommand):
|
||||||
def get_mana_max_compute(self, name) -> Profile.ManaMax:
|
def get_mana_max_compute(self, name) -> Profile.ManaMax:
|
||||||
if name in ["Barde", "Druide", "Forgesort", "Prêtre"]:
|
if name in ["Barde", "Druide", "Forgesort", "Prêtre"]:
|
||||||
return Profile.ManaMax.LEVEL
|
return Profile.ManaMax.LEVEL
|
||||||
elif name in ["Ensorceleur", "Magicien", "Nécromancien"]:
|
if name in ["Ensorceleur", "Magicien", "Nécromancien"]:
|
||||||
return Profile.ManaMax.DOUBLE_LEVEL
|
return Profile.ManaMax.DOUBLE_LEVEL
|
||||||
return Profile.ManaMax.NO_MANA
|
return Profile.ManaMax.NO_MANA
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ from character.models import Race, RacialCapability
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
def handle(self, *args, **options) -> None:
|
def handle(self, *args, **options) -> None: # noqa: ARG002
|
||||||
url = "https://www.co-drs.org/fr/jeu/races"
|
url = "https://www.co-drs.org/fr/jeu/races"
|
||||||
self.setup_selenium()
|
self.setup_selenium()
|
||||||
self.selenium.get(url)
|
self.selenium.get(url)
|
||||||
|
@ -16,7 +16,7 @@ class Command(BaseCommand):
|
||||||
try:
|
try:
|
||||||
self.import_race(url)
|
self.import_race(url)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{type(e)}: {e}")
|
self.stderr.write(f"{type(e)}: {e}")
|
||||||
self.stdout.write(f"Finished processing {len(urls)} races.")
|
self.stdout.write(f"Finished processing {len(urls)} races.")
|
||||||
|
|
||||||
def import_race(self, url: str) -> None:
|
def import_race(self, url: str) -> None:
|
||||||
|
|
|
@ -7,7 +7,7 @@ from character.models import Weapon
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
def handle(self, *args, **options) -> None:
|
def handle(self, *args, **options) -> None: # noqa: ARG002
|
||||||
url = "https://www.co-drs.org/fr/ressources/equipements/armes"
|
url = "https://www.co-drs.org/fr/ressources/equipements/armes"
|
||||||
self.setup_selenium()
|
self.setup_selenium()
|
||||||
self.selenium.get(url)
|
self.selenium.get(url)
|
||||||
|
@ -16,7 +16,7 @@ class Command(BaseCommand):
|
||||||
try:
|
try:
|
||||||
self.import_row(url, state)
|
self.import_row(url, state)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{type(e)}: {e}")
|
self.stderr.write(f"{type(e)}: {e}")
|
||||||
self.stdout.write(f"Finished processing {len(states)} weapons.")
|
self.stdout.write(f"Finished processing {len(states)} weapons.")
|
||||||
|
|
||||||
def import_row(self, url: str, state_row: WebElement) -> None:
|
def import_row(self, url: str, state_row: WebElement) -> None:
|
||||||
|
|
|
@ -22,7 +22,7 @@ class Migration(migrations.Migration):
|
||||||
null=True,
|
null=True,
|
||||||
upload_to="profile_pictures",
|
upload_to="profile_pictures",
|
||||||
validators=[
|
validators=[
|
||||||
functools.partial(
|
functools.partial( # noqa: PIE804
|
||||||
character.models.character.validate_image,
|
character.models.character.validate_image,
|
||||||
*(),
|
*(),
|
||||||
**{"megabytes_limit": 2},
|
**{"megabytes_limit": 2},
|
||||||
|
|
|
@ -59,10 +59,9 @@ class Path(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models.Model):
|
||||||
category = Path.Category(self.category)
|
category = Path.Category(self.category)
|
||||||
if category == Path.Category.PROFILE:
|
if category == Path.Category.PROFILE:
|
||||||
return self.profile
|
return self.profile
|
||||||
elif category == Path.Category.RACE:
|
if category == Path.Category.RACE:
|
||||||
return self.race
|
return self.race
|
||||||
else:
|
return None
|
||||||
return None
|
|
||||||
|
|
||||||
def get_next_capability(self, character) -> Capability:
|
def get_next_capability(self, character) -> Capability:
|
||||||
next_rank = self.max_rank(character) + 1
|
next_rank = self.max_rank(character) + 1
|
||||||
|
@ -71,9 +70,10 @@ class Path(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models.Model):
|
||||||
def has_next_capability(self, character) -> bool:
|
def has_next_capability(self, character) -> bool:
|
||||||
try:
|
try:
|
||||||
self.get_next_capability(character)
|
self.get_next_capability(character)
|
||||||
return True
|
|
||||||
except Capability.DoesNotExist:
|
except Capability.DoesNotExist:
|
||||||
return False
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
def max_rank(self, character) -> int:
|
def max_rank(self, character) -> int:
|
||||||
return character.capabilities.filter(path=self).count()
|
return character.capabilities.filter(path=self).count()
|
||||||
|
|
|
@ -66,7 +66,7 @@ class HarmfulState(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models
|
||||||
def modifier(value: int) -> int:
|
def modifier(value: int) -> int:
|
||||||
if not value:
|
if not value:
|
||||||
return 0
|
return 0
|
||||||
if 1 < value < 10:
|
if 1 < value < 10: # noqa: PLR2004
|
||||||
value -= 1
|
value -= 1
|
||||||
value -= 10
|
value -= 10
|
||||||
return int(value / 2)
|
return int(value / 2)
|
||||||
|
@ -343,10 +343,9 @@ class Character(models.Model):
|
||||||
mana_max_compute = self.profile.mana_max_compute
|
mana_max_compute = self.profile.mana_max_compute
|
||||||
if mana_max_compute == Profile.ManaMax.NO_MANA:
|
if mana_max_compute == Profile.ManaMax.NO_MANA:
|
||||||
return 0
|
return 0
|
||||||
elif mana_max_compute == Profile.ManaMax.LEVEL:
|
if mana_max_compute == Profile.ManaMax.LEVEL:
|
||||||
return self.level + self.modifier_magic
|
return self.level + self.modifier_magic
|
||||||
else:
|
return 2 * self.level + self.modifier_magic
|
||||||
return 2 * self.level + self.modifier_magic
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def height_m(self) -> float:
|
def height_m(self) -> float:
|
||||||
|
|
|
@ -10,8 +10,7 @@ register = template.Library()
|
||||||
def modifier(value):
|
def modifier(value):
|
||||||
if value > 0:
|
if value > 0:
|
||||||
return f"+{value}"
|
return f"+{value}"
|
||||||
else:
|
return value
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
|
@ -24,10 +23,9 @@ def weapon_modifier(character: Character, weapon: Weapon):
|
||||||
value = character.get_modifier_for_weapon(weapon)
|
value = character.get_modifier_for_weapon(weapon)
|
||||||
if value > 0:
|
if value > 0:
|
||||||
return f"+ {value}"
|
return f"+ {value}"
|
||||||
elif value < 0:
|
if value < 0:
|
||||||
return f"- {abs(value)}"
|
return f"- {abs(value)}"
|
||||||
else:
|
return ""
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from http import HTTPStatus
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
|
|
||||||
|
@ -6,7 +8,7 @@ from common.models import User
|
||||||
from party.models import Party
|
from party.models import Party
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_can_access_own_character(client):
|
def test_can_access_own_character(client):
|
||||||
player = User.objects.create_user("username", password="password")
|
player = User.objects.create_user("username", password="password")
|
||||||
|
|
||||||
|
@ -15,14 +17,14 @@ def test_can_access_own_character(client):
|
||||||
character = baker.make(Character, player=player, notes=notes, gm_notes=gm_notes)
|
character = baker.make(Character, player=player, notes=notes, gm_notes=gm_notes)
|
||||||
client.force_login(player)
|
client.force_login(player)
|
||||||
res = client.get(character.get_absolute_url())
|
res = client.get(character.get_absolute_url())
|
||||||
assert res.status_code == 200
|
assert res.status_code == HTTPStatus.OK
|
||||||
|
|
||||||
body = res.content.decode("utf-8")
|
body = res.content.decode("utf-8")
|
||||||
assert notes in body
|
assert notes in body
|
||||||
assert gm_notes not in body
|
assert gm_notes not in body
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_cant_access_random_character(client):
|
def test_cant_access_random_character(client):
|
||||||
player = User.objects.create_user("user", password="password")
|
player = User.objects.create_user("user", password="password")
|
||||||
other = User.objects.create_user("other", password="password")
|
other = User.objects.create_user("other", password="password")
|
||||||
|
@ -30,10 +32,10 @@ def test_cant_access_random_character(client):
|
||||||
character = baker.make(Character, player=other)
|
character = baker.make(Character, player=other)
|
||||||
client.force_login(player)
|
client.force_login(player)
|
||||||
res = client.get(character.get_absolute_url())
|
res = client.get(character.get_absolute_url())
|
||||||
assert res.status_code == 404
|
assert res.status_code == HTTPStatus.NOT_FOUND
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_can_access_character_in_party(client):
|
def test_can_access_character_in_party(client):
|
||||||
player = User.objects.create_user("user", password="password")
|
player = User.objects.create_user("user", password="password")
|
||||||
friend = User.objects.create_user("friend", password="password")
|
friend = User.objects.create_user("friend", password="password")
|
||||||
|
@ -49,14 +51,14 @@ def test_can_access_character_in_party(client):
|
||||||
party.characters.add(friend_character)
|
party.characters.add(friend_character)
|
||||||
client.force_login(player)
|
client.force_login(player)
|
||||||
res = client.get(friend_character.get_absolute_url())
|
res = client.get(friend_character.get_absolute_url())
|
||||||
assert res.status_code == 200
|
assert res.status_code == HTTPStatus.OK
|
||||||
|
|
||||||
body = res.content.decode("utf-8")
|
body = res.content.decode("utf-8")
|
||||||
assert notes not in body
|
assert notes not in body
|
||||||
assert gm_notes not in body
|
assert gm_notes not in body
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_game_master_can_access_character_in_party(client):
|
def test_game_master_can_access_character_in_party(client):
|
||||||
player = User.objects.create_user("user", password="password")
|
player = User.objects.create_user("user", password="password")
|
||||||
gm = User.objects.create_user("gm", password="password")
|
gm = User.objects.create_user("gm", password="password")
|
||||||
|
@ -68,7 +70,7 @@ def test_game_master_can_access_character_in_party(client):
|
||||||
party.characters.add(character)
|
party.characters.add(character)
|
||||||
client.force_login(gm)
|
client.force_login(gm)
|
||||||
res = client.get(character.get_absolute_url())
|
res = client.get(character.get_absolute_url())
|
||||||
assert res.status_code == 200
|
assert res.status_code == HTTPStatus.OK
|
||||||
|
|
||||||
body = res.content.decode("utf-8")
|
body = res.content.decode("utf-8")
|
||||||
assert notes in body
|
assert notes in body
|
||||||
|
|
|
@ -8,7 +8,7 @@ from character.tests.utils import ability_values, levels, modifier_test
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"value,expected",
|
("value", "expected"),
|
||||||
[
|
[
|
||||||
(1, -4),
|
(1, -4),
|
||||||
(2, -4),
|
(2, -4),
|
||||||
|
|
|
@ -12,7 +12,7 @@ from character.models import Character, Profile
|
||||||
from common.models import User
|
from common.models import User
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_create_character(selenium: WebDriver, live_server: LiveServer):
|
def test_create_character(selenium: WebDriver, live_server: LiveServer):
|
||||||
# Load fixtures
|
# Load fixtures
|
||||||
call_command("loaddata", "initial_data")
|
call_command("loaddata", "initial_data")
|
||||||
|
@ -93,7 +93,7 @@ def test_create_character(selenium: WebDriver, live_server: LiveServer):
|
||||||
assert getattr(character, name) == value
|
assert getattr(character, name) == value
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_list_characters(selenium: WebDriver, live_server: LiveServer):
|
def test_list_characters(selenium: WebDriver, live_server: LiveServer):
|
||||||
# Load fixtures
|
# Load fixtures
|
||||||
call_command("loaddata", "initial_data")
|
call_command("loaddata", "initial_data")
|
||||||
|
@ -125,7 +125,7 @@ def test_list_characters(selenium: WebDriver, live_server: LiveServer):
|
||||||
assert names == expected_names
|
assert names == expected_names
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_delete_character(selenium: WebDriver, live_server: LiveServer):
|
def test_delete_character(selenium: WebDriver, live_server: LiveServer):
|
||||||
call_command("loaddata", "initial_data")
|
call_command("loaddata", "initial_data")
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ def test_delete_character(selenium: WebDriver, live_server: LiveServer):
|
||||||
assert Character.objects.filter(pk=characters[0].pk).first() is None
|
assert Character.objects.filter(pk=characters[0].pk).first() is None
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_reset_stats_view(
|
def test_reset_stats_view(
|
||||||
selenium: WebDriver, live_server: LiveServer, initial_data: None
|
selenium: WebDriver, live_server: LiveServer, initial_data: None
|
||||||
):
|
):
|
||||||
|
|
|
@ -4,7 +4,7 @@ from character.models.character import modifier
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"value,expected",
|
("value", "expected"),
|
||||||
[
|
[
|
||||||
(1, -4),
|
(1, -4),
|
||||||
(2, -4),
|
(2, -4),
|
||||||
|
|
|
@ -316,13 +316,12 @@ def character_equipment_change(request, pk: int):
|
||||||
f"character/snippets/character_details/{field}_display.html",
|
f"character/snippets/character_details/{field}_display.html",
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
else:
|
context["errors"] = form.errors
|
||||||
context["errors"] = form.errors
|
return render(
|
||||||
return render(
|
request,
|
||||||
request,
|
f"character/snippets/character_details/{field}_update.html",
|
||||||
f"character/snippets/character_details/{field}_update.html",
|
context,
|
||||||
context,
|
)
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
def app(request):
|
def app(_):
|
||||||
return settings.APP
|
return settings.APP
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
def debug_toolbar_bypass_internal_ips(request) -> bool:
|
def debug_toolbar_bypass_internal_ips(_) -> bool:
|
||||||
"""
|
"""
|
||||||
Display debug toolbar according to the DEBUG_TOOLBAR setting only.
|
Display debug toolbar according to the DEBUG_TOOLBAR setting only.
|
||||||
|
|
||||||
|
|
|
@ -247,17 +247,17 @@ APP = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
with open("/app/git/build-date") as f:
|
with Path("/app/git/build-date").open() as f:
|
||||||
APP["build"]["date"] = f.read().strip()
|
APP["build"]["date"] = f.read().strip()
|
||||||
except Exception: # noqa: S110
|
except Exception:
|
||||||
pass
|
pass # noqa: S110
|
||||||
try:
|
try:
|
||||||
with open("/app/git/git-commit") as f:
|
with Path("/app/git/git-commit").open() as f:
|
||||||
APP["build"]["commit"] = f.read().strip()
|
APP["build"]["commit"] = f.read().strip()
|
||||||
except Exception: # noqa: S110
|
except Exception:
|
||||||
pass
|
pass # noqa: S110
|
||||||
try:
|
try:
|
||||||
with open("/app/git/git-describe") as f:
|
with Path("/app/git/git-describe").open() as f:
|
||||||
APP["build"]["describe"] = f.read().strip()
|
APP["build"]["describe"] = f.read().strip()
|
||||||
except Exception: # noqa: S110
|
except Exception:
|
||||||
pass
|
pass # noqa: S110
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from http import HTTPStatus
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
@ -9,17 +11,17 @@ class TestUserAdmin:
|
||||||
def test_changelist(self, admin_client):
|
def test_changelist(self, admin_client):
|
||||||
url = reverse("admin:common_user_changelist")
|
url = reverse("admin:common_user_changelist")
|
||||||
response = admin_client.get(url)
|
response = admin_client.get(url)
|
||||||
assert response.status_code == 200
|
assert response.status_code == HTTPStatus.OK
|
||||||
|
|
||||||
def test_search(self, admin_client):
|
def test_search(self, admin_client):
|
||||||
url = reverse("admin:common_user_changelist")
|
url = reverse("admin:common_user_changelist")
|
||||||
response = admin_client.get(url, data={"q": "test"})
|
response = admin_client.get(url, data={"q": "test"})
|
||||||
assert response.status_code == 200
|
assert response.status_code == HTTPStatus.OK
|
||||||
|
|
||||||
def test_add(self, admin_client):
|
def test_add(self, admin_client):
|
||||||
url = reverse("admin:common_user_add")
|
url = reverse("admin:common_user_add")
|
||||||
response = admin_client.get(url)
|
response = admin_client.get(url)
|
||||||
assert response.status_code == 200
|
assert response.status_code == HTTPStatus.OK
|
||||||
|
|
||||||
response = admin_client.post(
|
response = admin_client.post(
|
||||||
url,
|
url,
|
||||||
|
@ -29,11 +31,11 @@ class TestUserAdmin:
|
||||||
"password2": "My_R@ndom-P@ssw0rd",
|
"password2": "My_R@ndom-P@ssw0rd",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
assert response.status_code == 302
|
assert response.status_code == HTTPStatus.FOUND
|
||||||
assert get_user_model().objects.filter(username="test").exists()
|
assert get_user_model().objects.filter(username="test").exists()
|
||||||
|
|
||||||
def test_view_user(self, admin_client):
|
def test_view_user(self, admin_client):
|
||||||
user = get_user_model().objects.get(username="admin")
|
user = get_user_model().objects.get(username="admin")
|
||||||
url = reverse("admin:common_user_change", kwargs={"object_id": user.pk})
|
url = reverse("admin:common_user_change", kwargs={"object_id": user.pk})
|
||||||
response = admin_client.get(url)
|
response = admin_client.get(url)
|
||||||
assert response.status_code == 200
|
assert response.status_code == HTTPStatus.OK
|
||||||
|
|
|
@ -4,23 +4,23 @@ from selenium.webdriver.remote.webdriver import WebDriver
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session", autouse=True)
|
@pytest.fixture(scope="session", autouse=True)
|
||||||
def collectstatic():
|
def _collectstatic():
|
||||||
call_command("collectstatic", "--clear", "--noinput", "--verbosity=0")
|
call_command("collectstatic", "--clear", "--noinput", "--verbosity=0")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture()
|
||||||
def live_server(settings, live_server):
|
def live_server(settings, live_server):
|
||||||
settings.STATICFILES_STORAGE = "whitenoise.storage.CompressedStaticFilesStorage"
|
settings.STATICFILES_STORAGE = "whitenoise.storage.CompressedStaticFilesStorage"
|
||||||
return live_server
|
return live_server
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture()
|
||||||
def firefox_options(firefox_options):
|
def firefox_options(firefox_options):
|
||||||
firefox_options.add_argument("-headless")
|
firefox_options.add_argument("-headless")
|
||||||
return firefox_options
|
return firefox_options
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture()
|
||||||
def selenium(selenium: WebDriver) -> WebDriver:
|
def selenium(selenium: WebDriver) -> WebDriver:
|
||||||
selenium.implicitly_wait(3)
|
selenium.implicitly_wait(3)
|
||||||
selenium.set_window_size(3860, 2140)
|
selenium.set_window_size(3860, 2140)
|
||||||
|
@ -33,6 +33,7 @@ def settings(settings):
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture()
|
||||||
def initial_data(db: None) -> None:
|
@pytest.mark.django_db()
|
||||||
|
def initial_data() -> None: # noqa: PT004
|
||||||
call_command("loaddata", "initial_data")
|
call_command("loaddata", "initial_data")
|
||||||
|
|
|
@ -16,7 +16,7 @@ from common.models import User
|
||||||
from party.models import BattleEffect, Party
|
from party.models import BattleEffect, Party
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_add_character_to_existing_group(selenium: WebDriver, live_server: LiveServer):
|
def test_add_character_to_existing_group(selenium: WebDriver, live_server: LiveServer):
|
||||||
username, password = "gm", "password"
|
username, password = "gm", "password"
|
||||||
gm = User.objects.create_user(username, password=password)
|
gm = User.objects.create_user(username, password=password)
|
||||||
|
@ -39,7 +39,7 @@ def test_add_character_to_existing_group(selenium: WebDriver, live_server: LiveS
|
||||||
assert set(party.invited_characters.all()) == {character}
|
assert set(party.invited_characters.all()) == {character}
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_gm_observe_invited_character_in_group(
|
def test_gm_observe_invited_character_in_group(
|
||||||
selenium: WebDriver, live_server: LiveServer
|
selenium: WebDriver, live_server: LiveServer
|
||||||
):
|
):
|
||||||
|
@ -63,7 +63,7 @@ def test_gm_observe_invited_character_in_group(
|
||||||
assert title == character.name
|
assert title == character.name
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_gm_observe_invited_character_in_two_groups(
|
def test_gm_observe_invited_character_in_two_groups(
|
||||||
selenium: WebDriver, live_server: LiveServer
|
selenium: WebDriver, live_server: LiveServer
|
||||||
):
|
):
|
||||||
|
@ -89,7 +89,7 @@ def test_gm_observe_invited_character_in_two_groups(
|
||||||
assert title == character.name
|
assert title == character.name
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_reset_stats_view(
|
def test_reset_stats_view(
|
||||||
selenium: WebDriver, live_server: LiveServer, initial_data: None
|
selenium: WebDriver, live_server: LiveServer, initial_data: None
|
||||||
):
|
):
|
||||||
|
@ -117,7 +117,7 @@ def test_reset_stats_view(
|
||||||
assert character.luck_points_remaining == character.luck_points_max
|
assert character.luck_points_remaining == character.luck_points_max
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_player_can_add_effect_to_group(selenium: WebDriver, live_server: LiveServer):
|
def test_player_can_add_effect_to_group(selenium: WebDriver, live_server: LiveServer):
|
||||||
"""Any member of a group can add effects to the group."""
|
"""Any member of a group can add effects to the group."""
|
||||||
user, password = "player", "password"
|
user, password = "player", "password"
|
||||||
|
@ -146,7 +146,7 @@ def test_player_can_add_effect_to_group(selenium: WebDriver, live_server: LiveSe
|
||||||
assert effect.description in element.text
|
assert effect.description in element.text
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_gm_can_add_effect_to_group(selenium: WebDriver, live_server: LiveServer):
|
def test_gm_can_add_effect_to_group(selenium: WebDriver, live_server: LiveServer):
|
||||||
"""The GM of a group can add effects to the group."""
|
"""The GM of a group can add effects to the group."""
|
||||||
user, password = "gm", "password"
|
user, password = "gm", "password"
|
||||||
|
@ -175,7 +175,7 @@ def test_gm_can_add_effect_to_group(selenium: WebDriver, live_server: LiveServer
|
||||||
assert effect.description in element.text
|
assert effect.description in element.text
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_gm_can_change_remaining_rounds(selenium: WebDriver, live_server: LiveServer):
|
def test_gm_can_change_remaining_rounds(selenium: WebDriver, live_server: LiveServer):
|
||||||
"""The GM of a group can increase or decrease the remaining rounds of effects."""
|
"""The GM of a group can increase or decrease the remaining rounds of effects."""
|
||||||
user, password = "gm", "password"
|
user, password = "gm", "password"
|
||||||
|
@ -188,7 +188,7 @@ def test_gm_can_change_remaining_rounds(selenium: WebDriver, live_server: LiveSe
|
||||||
remaining_rounds=lambda: random.randint(3, 12),
|
remaining_rounds=lambda: random.randint(3, 12),
|
||||||
party=party,
|
party=party,
|
||||||
)
|
)
|
||||||
active_nearly_terminated = baker.make( # noqa: F841
|
active_nearly_terminated = baker.make(
|
||||||
BattleEffect, _quantity=3, remaining_rounds=1, party=party
|
BattleEffect, _quantity=3, remaining_rounds=1, party=party
|
||||||
)
|
)
|
||||||
terminated = baker.make( # noqa: F841
|
terminated = baker.make( # noqa: F841
|
||||||
|
@ -244,7 +244,7 @@ def test_gm_can_change_remaining_rounds(selenium: WebDriver, live_server: LiveSe
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_gm_can_delete_any_existing_effect(
|
def test_gm_can_delete_any_existing_effect(
|
||||||
selenium: WebDriver, live_server: LiveServer
|
selenium: WebDriver, live_server: LiveServer
|
||||||
):
|
):
|
||||||
|
@ -265,7 +265,7 @@ def test_gm_can_delete_any_existing_effect(
|
||||||
BattleEffect.objects.get(pk=effects[1].pk)
|
BattleEffect.objects.get(pk=effects[1].pk)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db()
|
||||||
def test_player_cant_change_existing_running_effect(
|
def test_player_cant_change_existing_running_effect(
|
||||||
selenium: WebDriver, live_server: LiveServer
|
selenium: WebDriver, live_server: LiveServer
|
||||||
):
|
):
|
||||||
|
|
4
tasks.py
4
tasks.py
|
@ -10,7 +10,7 @@ TEST_ENV = {"ENV_FILE": BASE_DIR / "envs" / "test-envs.env"}
|
||||||
|
|
||||||
|
|
||||||
@task
|
@task
|
||||||
def sync_dependencies(ctx: Context, update: bool = False):
|
def sync_dependencies(ctx: Context, *, update: bool = False):
|
||||||
common_args = "-q --allow-unsafe --resolver=backtracking"
|
common_args = "-q --allow-unsafe --resolver=backtracking"
|
||||||
if update:
|
if update:
|
||||||
common_args += " --upgrade"
|
common_args += " --upgrade"
|
||||||
|
@ -107,5 +107,5 @@ def import_from_co_drs(ctx: Context):
|
||||||
|
|
||||||
|
|
||||||
@task(pre=[import_from_co_drs, dump_initial])
|
@task(pre=[import_from_co_drs, dump_initial])
|
||||||
def update_fixtures(ctx: Context):
|
def update_fixtures(_: Context):
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Reference in a new issue