mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2025-12-23 18:29:23 -05:00
updated pytest and fixed ingredient parser
This commit is contained in:
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
|||||||
./cookbook/static
|
./cookbook/static
|
||||||
./staticfiles
|
./staticfiles
|
||||||
key: |
|
key: |
|
||||||
${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.node-version }}-collectstatic-${{ hashFiles('**/*.css', '**/*.js', 'vue/src/*') }}
|
${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.node-version }}-collectstatic-${{ hashFiles('**/*.css', '**/*.js', 'vue3/src/*') }}
|
||||||
|
|
||||||
# Build Vue frontend & Dependencies
|
# Build Vue frontend & Dependencies
|
||||||
- name: Set up Node ${{ matrix.node-version }}
|
- name: Set up Node ${{ matrix.node-version }}
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -89,3 +89,5 @@ venv/
|
|||||||
.idea/easy-i18n.xml
|
.idea/easy-i18n.xml
|
||||||
cookbook/static/vue3
|
cookbook/static/vue3
|
||||||
vue3/node_modules
|
vue3/node_modules
|
||||||
|
cookbook/tests/other/docs/reports/tests/tests.html
|
||||||
|
cookbook/tests/other/docs/reports/tests/pytest.xml
|
||||||
|
|||||||
@@ -211,44 +211,46 @@ class IngredientParser:
|
|||||||
# three arguments if it already has a unit there can't be
|
# three arguments if it already has a unit there can't be
|
||||||
# a fraction for the amount
|
# a fraction for the amount
|
||||||
if len(tokens) > 2:
|
if len(tokens) > 2:
|
||||||
|
never_unit_applied = False
|
||||||
if not self.ignore_rules:
|
if not self.ignore_rules:
|
||||||
tokens, never_unit_applied = self.automation.apply_never_unit_automation(tokens)
|
tokens, never_unit_applied = self.automation.apply_never_unit_automation(tokens)
|
||||||
if never_unit_applied:
|
|
||||||
unit = tokens[1]
|
if never_unit_applied:
|
||||||
food, note = self.parse_food(tokens[2:])
|
unit = tokens[1]
|
||||||
else:
|
food, note = self.parse_food(tokens[2:])
|
||||||
try:
|
else:
|
||||||
if unit is not None:
|
try:
|
||||||
# a unit is already found, no need to try the second argument for a fraction
|
if unit is not None:
|
||||||
# probably not the best method to do it, but I didn't want to make an if check and paste the exact same thing in the else as already is in the except
|
# a unit is already found, no need to try the second argument for a fraction
|
||||||
raise ValueError
|
# probably not the best method to do it, but I didn't want to make an if check and paste the exact same thing in the else as already is in the except
|
||||||
# try to parse second argument as amount and add that, in case of '2 1/2' or '2 ½'
|
raise ValueError
|
||||||
if tokens[1]:
|
# try to parse second argument as amount and add that, in case of '2 1/2' or '2 ½'
|
||||||
amount += self.parse_fraction(tokens[1])
|
if tokens[1]:
|
||||||
# assume that units can't end with a comma
|
amount += self.parse_fraction(tokens[1])
|
||||||
if len(tokens) > 3 and not tokens[2].endswith(','):
|
# assume that units can't end with a comma
|
||||||
# try to use third argument as unit and everything else as food, use everything as food if it fails
|
if len(tokens) > 3 and not tokens[2].endswith(','):
|
||||||
try:
|
# try to use third argument as unit and everything else as food, use everything as food if it fails
|
||||||
food, note = self.parse_food(tokens[3:])
|
try:
|
||||||
unit = tokens[2]
|
food, note = self.parse_food(tokens[3:])
|
||||||
except ValueError:
|
unit = tokens[2]
|
||||||
food, note = self.parse_food(tokens[2:])
|
except ValueError:
|
||||||
else:
|
|
||||||
food, note = self.parse_food(tokens[2:])
|
food, note = self.parse_food(tokens[2:])
|
||||||
except ValueError:
|
else:
|
||||||
# assume that units can't end with a comma
|
food, note = self.parse_food(tokens[2:])
|
||||||
if not tokens[1].endswith(','):
|
except ValueError:
|
||||||
# try to use second argument as unit and everything else as food, use everything as food if it fails
|
# assume that units can't end with a comma
|
||||||
try:
|
if not tokens[1].endswith(','):
|
||||||
food, note = self.parse_food(tokens[2:])
|
# try to use second argument as unit and everything else as food, use everything as food if it fails
|
||||||
if unit is None:
|
try:
|
||||||
unit = tokens[1]
|
food, note = self.parse_food(tokens[2:])
|
||||||
else:
|
if unit is None:
|
||||||
note = tokens[1]
|
unit = tokens[1]
|
||||||
except ValueError:
|
else:
|
||||||
food, note = self.parse_food(tokens[1:])
|
note = tokens[1]
|
||||||
else:
|
except ValueError:
|
||||||
food, note = self.parse_food(tokens[1:])
|
food, note = self.parse_food(tokens[1:])
|
||||||
|
else:
|
||||||
|
food, note = self.parse_food(tokens[1:])
|
||||||
else:
|
else:
|
||||||
# only two arguments, first one is the amount
|
# only two arguments, first one is the amount
|
||||||
# which means this is the food
|
# which means this is the food
|
||||||
@@ -269,6 +271,7 @@ class IngredientParser:
|
|||||||
|
|
||||||
if food and not self.ignore_rules:
|
if food and not self.ignore_rules:
|
||||||
food = self.automation.apply_food_automation(food)
|
food = self.automation.apply_food_automation(food)
|
||||||
|
|
||||||
if len(food) > Food._meta.get_field('name').max_length: # test if food name is to long
|
if len(food) > Food._meta.get_field('name').max_length: # test if food name is to long
|
||||||
# try splitting it at a space and taking only the first arg
|
# try splitting it at a space and taking only the first arg
|
||||||
if len(food.split()) > 1 and len(food.split()[0]) < Food._meta.get_field('name').max_length:
|
if len(food.split()) > 1 and len(food.split()[0]) < Food._meta.get_field('name').max_length:
|
||||||
|
|||||||
@@ -1,157 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><testsuites name="pytest tests"><testsuite name="pytest" errors="4" failures="0" skipped="0" tests="4" time="34.750" timestamp="2025-07-17T12:15:15.274960+02:00" hostname="DESKTOP-RM10LP5"><testcase classname="cookbook.tests.other.test_automations" name="test_never_unit_automation[arg0]" time="22.035"><error message="failed on setup with "TypeError: type 'Factory' is not subscriptable"">args = ()
|
|
||||||
kwargs = {'request': <SubRequest 'space_1' for <Function test_never_unit_automation[arg0]>>}
|
|
||||||
k = 'space_1__name'
|
|
||||||
|
|
||||||
@functools.wraps(fixture_function)
|
|
||||||
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
|
||||||
for k in set(kwargs.keys()) - function_args:
|
|
||||||
del kwargs[k]
|
|
||||||
> return fixture_function(*args, **kwargs)
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
..\..\..\venv\Lib\site-packages\pytest_factoryboy\fixturegen.py:88:
|
|
||||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
||||||
..\..\..\venv\Lib\site-packages\pytest_factoryboy\fixturegen.py:49: in fn
|
|
||||||
return function(*args, **kwargs)
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
||||||
|
|
||||||
request = <SubRequest 'space_1' for <Function test_never_unit_automation[arg0]>>
|
|
||||||
factory_name = 'space_factory'
|
|
||||||
|
|
||||||
def model_fixture(request: SubRequest, factory_name: str) -> object:
|
|
||||||
"""Model fixture implementation."""
|
|
||||||
factoryboy_request: FactoryboyRequest = request.getfixturevalue("factoryboy_request")
|
|
||||||
|
|
||||||
# Try to evaluate as much post-generation dependencies as possible
|
|
||||||
factoryboy_request.evaluate(request)
|
|
||||||
|
|
||||||
assert request.fixturename # NOTE: satisfy mypy
|
|
||||||
fixture_name = request.fixturename
|
|
||||||
prefix = "".join((fixture_name, SEPARATOR))
|
|
||||||
|
|
||||||
factory_class: type[Factory[object]] = request.getfixturevalue(factory_name)
|
|
||||||
|
|
||||||
# Create model fixture instance
|
|
||||||
> NewFactory: type[Factory[object]] = cast(type[Factory[object]], type("Factory", (factory_class,), {}))
|
|
||||||
^^^^^^^^^^^^^^^
|
|
||||||
E TypeError: type 'Factory' is not subscriptable
|
|
||||||
|
|
||||||
..\..\..\venv\Lib\site-packages\pytest_factoryboy\fixture.py:360: TypeError</error></testcase><testcase classname="cookbook.tests.other.test_automations" name="test_never_unit_automation[arg2]" time="22.047"><error message="failed on setup with "TypeError: type 'Factory' is not subscriptable"">args = ()
|
|
||||||
kwargs = {'request': <SubRequest 'space_1' for <Function test_never_unit_automation[arg2]>>}
|
|
||||||
k = 'space_1__name'
|
|
||||||
|
|
||||||
@functools.wraps(fixture_function)
|
|
||||||
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
|
||||||
for k in set(kwargs.keys()) - function_args:
|
|
||||||
del kwargs[k]
|
|
||||||
> return fixture_function(*args, **kwargs)
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
..\..\..\venv\Lib\site-packages\pytest_factoryboy\fixturegen.py:88:
|
|
||||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
||||||
..\..\..\venv\Lib\site-packages\pytest_factoryboy\fixturegen.py:49: in fn
|
|
||||||
return function(*args, **kwargs)
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
||||||
|
|
||||||
request = <SubRequest 'space_1' for <Function test_never_unit_automation[arg2]>>
|
|
||||||
factory_name = 'space_factory'
|
|
||||||
|
|
||||||
def model_fixture(request: SubRequest, factory_name: str) -> object:
|
|
||||||
"""Model fixture implementation."""
|
|
||||||
factoryboy_request: FactoryboyRequest = request.getfixturevalue("factoryboy_request")
|
|
||||||
|
|
||||||
# Try to evaluate as much post-generation dependencies as possible
|
|
||||||
factoryboy_request.evaluate(request)
|
|
||||||
|
|
||||||
assert request.fixturename # NOTE: satisfy mypy
|
|
||||||
fixture_name = request.fixturename
|
|
||||||
prefix = "".join((fixture_name, SEPARATOR))
|
|
||||||
|
|
||||||
factory_class: type[Factory[object]] = request.getfixturevalue(factory_name)
|
|
||||||
|
|
||||||
# Create model fixture instance
|
|
||||||
> NewFactory: type[Factory[object]] = cast(type[Factory[object]], type("Factory", (factory_class,), {}))
|
|
||||||
^^^^^^^^^^^^^^^
|
|
||||||
E TypeError: type 'Factory' is not subscriptable
|
|
||||||
|
|
||||||
..\..\..\venv\Lib\site-packages\pytest_factoryboy\fixture.py:360: TypeError</error></testcase><testcase classname="cookbook.tests.other.test_automations" name="test_never_unit_automation[arg3]" time="22.106"><error message="failed on setup with "TypeError: type 'Factory' is not subscriptable"">args = ()
|
|
||||||
kwargs = {'request': <SubRequest 'space_1' for <Function test_never_unit_automation[arg3]>>}
|
|
||||||
k = 'space_1__name'
|
|
||||||
|
|
||||||
@functools.wraps(fixture_function)
|
|
||||||
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
|
||||||
for k in set(kwargs.keys()) - function_args:
|
|
||||||
del kwargs[k]
|
|
||||||
> return fixture_function(*args, **kwargs)
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
..\..\..\venv\Lib\site-packages\pytest_factoryboy\fixturegen.py:88:
|
|
||||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
||||||
..\..\..\venv\Lib\site-packages\pytest_factoryboy\fixturegen.py:49: in fn
|
|
||||||
return function(*args, **kwargs)
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
||||||
|
|
||||||
request = <SubRequest 'space_1' for <Function test_never_unit_automation[arg3]>>
|
|
||||||
factory_name = 'space_factory'
|
|
||||||
|
|
||||||
def model_fixture(request: SubRequest, factory_name: str) -> object:
|
|
||||||
"""Model fixture implementation."""
|
|
||||||
factoryboy_request: FactoryboyRequest = request.getfixturevalue("factoryboy_request")
|
|
||||||
|
|
||||||
# Try to evaluate as much post-generation dependencies as possible
|
|
||||||
factoryboy_request.evaluate(request)
|
|
||||||
|
|
||||||
assert request.fixturename # NOTE: satisfy mypy
|
|
||||||
fixture_name = request.fixturename
|
|
||||||
prefix = "".join((fixture_name, SEPARATOR))
|
|
||||||
|
|
||||||
factory_class: type[Factory[object]] = request.getfixturevalue(factory_name)
|
|
||||||
|
|
||||||
# Create model fixture instance
|
|
||||||
> NewFactory: type[Factory[object]] = cast(type[Factory[object]], type("Factory", (factory_class,), {}))
|
|
||||||
^^^^^^^^^^^^^^^
|
|
||||||
E TypeError: type 'Factory' is not subscriptable
|
|
||||||
|
|
||||||
..\..\..\venv\Lib\site-packages\pytest_factoryboy\fixture.py:360: TypeError</error></testcase><testcase classname="cookbook.tests.other.test_automations" name="test_never_unit_automation[arg1]" time="22.143"><error message="failed on setup with "TypeError: type 'Factory' is not subscriptable"">args = ()
|
|
||||||
kwargs = {'request': <SubRequest 'space_1' for <Function test_never_unit_automation[arg1]>>}
|
|
||||||
k = 'space_1__name'
|
|
||||||
|
|
||||||
@functools.wraps(fixture_function)
|
|
||||||
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
|
||||||
for k in set(kwargs.keys()) - function_args:
|
|
||||||
del kwargs[k]
|
|
||||||
> return fixture_function(*args, **kwargs)
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
..\..\..\venv\Lib\site-packages\pytest_factoryboy\fixturegen.py:88:
|
|
||||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
||||||
..\..\..\venv\Lib\site-packages\pytest_factoryboy\fixturegen.py:49: in fn
|
|
||||||
return function(*args, **kwargs)
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
||||||
|
|
||||||
request = <SubRequest 'space_1' for <Function test_never_unit_automation[arg1]>>
|
|
||||||
factory_name = 'space_factory'
|
|
||||||
|
|
||||||
def model_fixture(request: SubRequest, factory_name: str) -> object:
|
|
||||||
"""Model fixture implementation."""
|
|
||||||
factoryboy_request: FactoryboyRequest = request.getfixturevalue("factoryboy_request")
|
|
||||||
|
|
||||||
# Try to evaluate as much post-generation dependencies as possible
|
|
||||||
factoryboy_request.evaluate(request)
|
|
||||||
|
|
||||||
assert request.fixturename # NOTE: satisfy mypy
|
|
||||||
fixture_name = request.fixturename
|
|
||||||
prefix = "".join((fixture_name, SEPARATOR))
|
|
||||||
|
|
||||||
factory_class: type[Factory[object]] = request.getfixturevalue(factory_name)
|
|
||||||
|
|
||||||
# Create model fixture instance
|
|
||||||
> NewFactory: type[Factory[object]] = cast(type[Factory[object]], type("Factory", (factory_class,), {}))
|
|
||||||
^^^^^^^^^^^^^^^
|
|
||||||
E TypeError: type 'Factory' is not subscriptable
|
|
||||||
|
|
||||||
..\..\..\venv\Lib\site-packages\pytest_factoryboy\fixture.py:360: TypeError</error></testcase></testsuite></testsuites>
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,3 +1,4 @@
|
|||||||
|
import pytest
|
||||||
from django.contrib import auth
|
from django.contrib import auth
|
||||||
from django.test import RequestFactory
|
from django.test import RequestFactory
|
||||||
from django_scopes import scope
|
from django_scopes import scope
|
||||||
@@ -5,7 +6,11 @@ from django_scopes import scope
|
|||||||
from cookbook.helper.ingredient_parser import IngredientParser
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
|
|
||||||
|
|
||||||
def test_ingredient_parser(u1_s1):
|
@pytest.mark.parametrize("arg", [
|
||||||
|
[True],
|
||||||
|
[False],
|
||||||
|
])
|
||||||
|
def test_ingredient_parser(arg, u1_s1):
|
||||||
expectations = {
|
expectations = {
|
||||||
"2¼ l Wasser": (2.25, "l", "Wasser", ""),
|
"2¼ l Wasser": (2.25, "l", "Wasser", ""),
|
||||||
"3¼l Wasser": (3.25, "l", "Wasser", ""),
|
"3¼l Wasser": (3.25, "l", "Wasser", ""),
|
||||||
@@ -67,7 +72,8 @@ def test_ingredient_parser(u1_s1):
|
|||||||
"1 Porreestange(n) , ca. 200 g": (1.0, None, 'Porreestange(n)', 'ca. 200 g'), # leading space before comma
|
"1 Porreestange(n) , ca. 200 g": (1.0, None, 'Porreestange(n)', 'ca. 200 g'), # leading space before comma
|
||||||
# test for over long food entries to get properly split into the note field
|
# test for over long food entries to get properly split into the note field
|
||||||
"1 Lorem ipsum dolor sit amet consetetur sadipscing elitr sed diam nonumy eirmod tempor invidunt ut l Lorem ipsum dolor sit amet consetetur sadipscing elitr sed diam nonumy eirmod tempor invidunt ut l": (
|
"1 Lorem ipsum dolor sit amet consetetur sadipscing elitr sed diam nonumy eirmod tempor invidunt ut l Lorem ipsum dolor sit amet consetetur sadipscing elitr sed diam nonumy eirmod tempor invidunt ut l": (
|
||||||
1.0, 'Lorem', 'ipsum', 'dolor sit amet consetetur sadipscing elitr sed diam nonumy eirmod tempor invidunt ut l Lorem ipsum dolor sit amet consetetur sadipscing elitr sed diam nonumy eirmod tempor invidunt ut l'),
|
1.0, 'Lorem', 'ipsum',
|
||||||
|
'dolor sit amet consetetur sadipscing elitr sed diam nonumy eirmod tempor invidunt ut l Lorem ipsum dolor sit amet consetetur sadipscing elitr sed diam nonumy eirmod tempor invidunt ut l'),
|
||||||
"1 LoremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemporinviduntutlLoremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemporinviduntutl": (
|
"1 LoremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemporinviduntutlLoremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemporinviduntutl": (
|
||||||
1.0, None, 'LoremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemporinviduntutlLoremipsumdolorsitametconsetetursadipscingeli',
|
1.0, None, 'LoremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemporinviduntutlLoremipsumdolorsitametconsetetursadipscingeli',
|
||||||
'LoremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemporinviduntutlLoremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemporinviduntutl'),
|
'LoremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemporinviduntutlLoremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemporinviduntutl'),
|
||||||
@@ -86,7 +92,7 @@ def test_ingredient_parser(u1_s1):
|
|||||||
request = RequestFactory()
|
request = RequestFactory()
|
||||||
request.user = user
|
request.user = user
|
||||||
request.space = space
|
request.space = space
|
||||||
ingredient_parser = IngredientParser(request, False, ignore_automations=True)
|
ingredient_parser = IngredientParser(request, False, ignore_automations=arg[0])
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
with scope(space=space):
|
with scope(space=space):
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ testpaths = cookbook/tests
|
|||||||
python_files = tests.py test_*.py *_tests.py
|
python_files = tests.py test_*.py *_tests.py
|
||||||
# uncomment to run coverage reports
|
# uncomment to run coverage reports
|
||||||
addopts = -n auto --cov=. --cov-report=html:docs/reports/coverage --cov-report=xml:docs/reports/coverage/coverage.xml --junitxml=docs/reports/tests/pytest.xml --html=docs/reports/tests/tests.html
|
addopts = -n auto --cov=. --cov-report=html:docs/reports/coverage --cov-report=xml:docs/reports/coverage/coverage.xml --junitxml=docs/reports/tests/pytest.xml --html=docs/reports/tests/tests.html
|
||||||
# addopts = -n auto --junitxml=docs/reports/tests/pytest.xml --html=docs/reports/tests/tests.html
|
# addopts = -n auto --junitxml=docs/reports/tests/pytest.xml --html=docs/reports/tests/tests.html
|
||||||
|
asyncio_default_fixture_loop_scope = fixture
|
||||||
@@ -55,11 +55,11 @@ litellm==1.64.1
|
|||||||
# Development
|
# Development
|
||||||
pytest==8.4.1
|
pytest==8.4.1
|
||||||
pytest-django==4.11.0
|
pytest-django==4.11.0
|
||||||
pytest-cov===6.0.0
|
pytest-cov===6.2.1
|
||||||
pytest-factoryboy==2.8.0
|
pytest-factoryboy==2.8.1
|
||||||
pytest-html==4.1.1
|
pytest-html==4.1.1
|
||||||
pytest-asyncio==0.25.3
|
pytest-asyncio==1.1.0
|
||||||
pytest-xdist==3.7.0
|
pytest-xdist==3.8.0
|
||||||
autopep8==2.3.2
|
autopep8==2.3.2
|
||||||
flake8==7.3.0
|
flake8==7.3.0
|
||||||
yapf==0.40.2
|
yapf==0.40.2
|
||||||
|
|||||||
Reference in New Issue
Block a user