Use ruff instead of black, flake8, autoflake, pyupgrade
Config adapted from pytest.
This commit is contained in:
@@ -1,14 +1,10 @@
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/PyCQA/autoflake
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v2.3.1
|
rev: "v0.3.5"
|
||||||
hooks:
|
hooks:
|
||||||
- id: autoflake
|
- id: ruff
|
||||||
args: ["--in-place", "--remove-unused-variables", "--remove-all-unused-imports"]
|
args: ["--fix"]
|
||||||
- repo: https://github.com/psf/black
|
- id: ruff-format
|
||||||
rev: 24.3.0
|
|
||||||
hooks:
|
|
||||||
- id: black
|
|
||||||
args: [--safe, --quiet, --target-version, py35]
|
|
||||||
- repo: https://github.com/asottile/blacken-docs
|
- repo: https://github.com/asottile/blacken-docs
|
||||||
rev: 1.16.0
|
rev: 1.16.0
|
||||||
hooks:
|
hooks:
|
||||||
@@ -17,19 +13,7 @@ repos:
|
|||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.5.0
|
rev: v4.5.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
|
||||||
- id: end-of-file-fixer
|
|
||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
- id: debug-statements
|
|
||||||
- repo: https://github.com/PyCQA/flake8
|
|
||||||
rev: 7.0.0
|
|
||||||
hooks:
|
|
||||||
- id: flake8
|
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
|
||||||
rev: v3.15.1
|
|
||||||
hooks:
|
|
||||||
- id: pyupgrade
|
|
||||||
args: [--py3-plus]
|
|
||||||
- repo: local
|
- repo: local
|
||||||
hooks:
|
hooks:
|
||||||
- id: rst
|
- id: rst
|
||||||
|
|||||||
@@ -67,10 +67,72 @@ include-package-data = false
|
|||||||
[tool.setuptools_scm]
|
[tool.setuptools_scm]
|
||||||
write_to = "src/xdist/_version.py"
|
write_to = "src/xdist/_version.py"
|
||||||
|
|
||||||
[tool.flake8]
|
[tool.ruff]
|
||||||
# Ignore any errors related to formatting, let black worry/fix them.
|
src = ["src"]
|
||||||
ignore = ["E501", "W503", "E203"]
|
|
||||||
max-line-length = 100
|
[tool.ruff.format]
|
||||||
|
docstring-code-format = true
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = [
|
||||||
|
"B", # bugbear
|
||||||
|
"D", # pydocstyle
|
||||||
|
"E", # pycodestyle
|
||||||
|
"F", # pyflakes
|
||||||
|
"I", # isort
|
||||||
|
"PYI", # flake8-pyi
|
||||||
|
"UP", # pyupgrade
|
||||||
|
"RUF", # ruff
|
||||||
|
"W", # pycodestyle
|
||||||
|
"T10", # flake8-debugger
|
||||||
|
"PIE", # flake8-pie
|
||||||
|
"PGH", # pygrep-hooks
|
||||||
|
"PLE", # pylint error
|
||||||
|
"PLW", # pylint warning
|
||||||
|
"PLR1714", # Consider merging multiple comparisons
|
||||||
|
]
|
||||||
|
ignore = [
|
||||||
|
# bugbear ignore
|
||||||
|
"B011", # Do not `assert False` (`python -O` removes these calls)
|
||||||
|
"B028", # No explicit `stacklevel` keyword argument found
|
||||||
|
# pydocstyle ignore
|
||||||
|
"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__`
|
||||||
|
"D209", # Multi-line docstring closing quotes should be on a separate line
|
||||||
|
"D205", # 1 blank line required between summary line and description
|
||||||
|
"D400", # First line should end with a period
|
||||||
|
"D401", # First line of docstring should be in imperative mood
|
||||||
|
# ruff ignore
|
||||||
|
"RUF012", # Mutable class attributes should be annotated with `typing.ClassVar`
|
||||||
|
# pylint ignore
|
||||||
|
"PLW0603", # Using the global statement
|
||||||
|
"PLW0120", # remove the else and dedent its contents
|
||||||
|
"PLW2901", # for loop variable overwritten by assignment target
|
||||||
|
"PLR5501", # Use `elif` instead of `else` then `if`
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.ruff.lint.pycodestyle]
|
||||||
|
# In order to be able to format for 88 char in ruff format
|
||||||
|
max-line-length = 120
|
||||||
|
|
||||||
|
[tool.ruff.lint.pydocstyle]
|
||||||
|
convention = "pep257"
|
||||||
|
|
||||||
|
[tool.ruff.lint.isort]
|
||||||
|
force-single-line = true
|
||||||
|
combine-as-imports = true
|
||||||
|
force-sort-within-sections = true
|
||||||
|
order-by-type = false
|
||||||
|
lines-after-imports = 2
|
||||||
|
|
||||||
|
[tool.ruff.lint.per-file-ignores]
|
||||||
|
"src/xdist/_version.py" = ["I001"]
|
||||||
|
|
||||||
[tool.mypy]
|
[tool.mypy]
|
||||||
mypy_path = ["src"]
|
mypy_path = ["src"]
|
||||||
|
|||||||
@@ -230,9 +230,7 @@ class DSession:
|
|||||||
)
|
)
|
||||||
if maximum_reached:
|
if maximum_reached:
|
||||||
if self._max_worker_restart == 0:
|
if self._max_worker_restart == 0:
|
||||||
msg = "worker {} crashed and worker restarting disabled".format(
|
msg = f"worker {node.gateway.id} crashed and worker restarting disabled"
|
||||||
node.gateway.id
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
msg = "maximum crashed workers reached: %d" % self._max_worker_restart
|
msg = "maximum crashed workers reached: %d" % self._max_worker_restart
|
||||||
self._summary_report = msg
|
self._summary_report = msg
|
||||||
@@ -463,7 +461,7 @@ class TerminalDistReporter:
|
|||||||
rinfo = gateway._rinfo()
|
rinfo = gateway._rinfo()
|
||||||
different_interpreter = rinfo.executable != sys.executable
|
different_interpreter = rinfo.executable != sys.executable
|
||||||
if different_interpreter:
|
if different_interpreter:
|
||||||
version = "%s.%s.%s" % rinfo.version_info[:3]
|
version = "{}.{}.{}".format(*rinfo.version_info[:3])
|
||||||
self.rewrite(
|
self.rewrite(
|
||||||
f"[{gateway.id}] {rinfo.platform} Python {version} cwd: {rinfo.cwd}",
|
f"[{gateway.id}] {rinfo.platform} Python {version} cwd: {rinfo.cwd}",
|
||||||
newline=True,
|
newline=True,
|
||||||
@@ -504,7 +502,7 @@ def get_default_max_worker_restart(config):
|
|||||||
|
|
||||||
|
|
||||||
def get_workers_status_line(
|
def get_workers_status_line(
|
||||||
status_and_items: Sequence[tuple[WorkerStatus, int]]
|
status_and_items: Sequence[tuple[WorkerStatus, int]],
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Return the line to display during worker setup/collection based on the
|
Return the line to display during worker setup/collection based on the
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ class StatRecorder:
|
|||||||
return
|
return
|
||||||
time.sleep(checkinterval)
|
time.sleep(checkinterval)
|
||||||
|
|
||||||
def check(self, removepycfiles: bool = True) -> bool: # noqa, too complex
|
def check(self, removepycfiles: bool = True) -> bool:
|
||||||
changed = False
|
changed = False
|
||||||
newstat: Dict[Path, os.stat_result] = {}
|
newstat: Dict[Path, os.stat_result] = {}
|
||||||
for rootdir in self.rootdirlist:
|
for rootdir in self.rootdirlist:
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ def pytest_cmdline_main(config):
|
|||||||
if not val("collectonly") and _is_distribution_mode(config) and usepdb:
|
if not val("collectonly") and _is_distribution_mode(config) and usepdb:
|
||||||
raise pytest.UsageError(
|
raise pytest.UsageError(
|
||||||
"--pdb is incompatible with distributing tests; try using -n0 or -nauto."
|
"--pdb is incompatible with distributing tests; try using -n0 or -nauto."
|
||||||
) # noqa: E501
|
)
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ def setup_config(config, basetemp):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__channelexec__":
|
if __name__ == "__channelexec__":
|
||||||
channel = channel # type: ignore[name-defined] # noqa: F821
|
channel = channel # type: ignore[name-defined] # noqa: F821, PLW0127
|
||||||
workerinput, args, option_dict, change_sys_path = channel.receive() # type: ignore[name-defined]
|
workerinput, args, option_dict, change_sys_path = channel.receive() # type: ignore[name-defined]
|
||||||
|
|
||||||
if change_sys_path is None:
|
if change_sys_path is None:
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ class LoadScheduling:
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Collections are identical, create the index of pending items.
|
# Collections are identical, create the index of pending items.
|
||||||
self.collection = list(self.node2collection.values())[0]
|
self.collection = next(iter(self.node2collection.values()))
|
||||||
self.pending[:] = range(len(self.collection))
|
self.pending[:] = range(len(self.collection))
|
||||||
if not self.collection:
|
if not self.collection:
|
||||||
return
|
return
|
||||||
@@ -260,7 +260,7 @@ class LoadScheduling:
|
|||||||
# to each node - which is suboptimal when you have less than
|
# to each node - which is suboptimal when you have less than
|
||||||
# 2 * len(nodes) tests.
|
# 2 * len(nodes) tests.
|
||||||
nodes = cycle(self.nodes)
|
nodes = cycle(self.nodes)
|
||||||
for i in range(len(self.pending)):
|
for _ in range(len(self.pending)):
|
||||||
self._send_tests(next(nodes), 1)
|
self._send_tests(next(nodes), 1)
|
||||||
else:
|
else:
|
||||||
# Send batches of consecutive tests. By default, pytest sorts tests
|
# Send batches of consecutive tests. By default, pytest sorts tests
|
||||||
|
|||||||
@@ -208,7 +208,6 @@ class LoadScopeScheduling:
|
|||||||
|
|
||||||
- ``DSession.worker_collectionfinish``.
|
- ``DSession.worker_collectionfinish``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Check that add_node() was called on the node before
|
# Check that add_node() was called on the node before
|
||||||
assert node in self.assigned_work
|
assert node in self.assigned_work
|
||||||
|
|
||||||
@@ -301,7 +300,6 @@ class LoadScopeScheduling:
|
|||||||
If there are any globally pending work units left then this will check
|
If there are any globally pending work units left then this will check
|
||||||
if the given node should be given any more tests.
|
if the given node should be given any more tests.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Do not add more work to a node shutting down
|
# Do not add more work to a node shutting down
|
||||||
if node.shutting_down:
|
if node.shutting_down:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
from collections import namedtuple
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
from typing import NamedTuple
|
||||||
|
|
||||||
from _pytest.runner import CollectReport
|
from _pytest.runner import CollectReport
|
||||||
|
|
||||||
@@ -7,7 +10,10 @@ from xdist.report import report_collection_diff
|
|||||||
from xdist.workermanage import parse_spec_config
|
from xdist.workermanage import parse_spec_config
|
||||||
|
|
||||||
|
|
||||||
NodePending = namedtuple("NodePending", ["node", "pending"])
|
class NodePending(NamedTuple):
|
||||||
|
node: Any
|
||||||
|
pending: list[int]
|
||||||
|
|
||||||
|
|
||||||
# Every worker needs at least 2 tests in queue - the current and the next one.
|
# Every worker needs at least 2 tests in queue - the current and the next one.
|
||||||
MIN_PENDING = 2
|
MIN_PENDING = 2
|
||||||
@@ -285,7 +291,7 @@ class WorkStealingScheduling:
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Collections are identical, create the index of pending items.
|
# Collections are identical, create the index of pending items.
|
||||||
self.collection = list(self.node2collection.values())[0]
|
self.collection = next(iter(self.node2collection.values()))
|
||||||
self.pending[:] = range(len(self.collection))
|
self.pending[:] = range(len(self.collection))
|
||||||
if not self.collection:
|
if not self.collection:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ class HostRSync(execnet.RSync):
|
|||||||
sourcedir: PathLike,
|
sourcedir: PathLike,
|
||||||
*,
|
*,
|
||||||
ignores: Optional[Sequence[PathLike]] = None,
|
ignores: Optional[Sequence[PathLike]] = None,
|
||||||
**kwargs: object
|
**kwargs: object,
|
||||||
) -> None:
|
) -> None:
|
||||||
if ignores is None:
|
if ignores is None:
|
||||||
ignores = []
|
ignores = []
|
||||||
@@ -322,8 +322,8 @@ class WorkerController:
|
|||||||
self.log(f"queuing {eventname}(**{kwargs})")
|
self.log(f"queuing {eventname}(**{kwargs})")
|
||||||
self.putevent((eventname, kwargs))
|
self.putevent((eventname, kwargs))
|
||||||
|
|
||||||
def process_from_remote(self, eventcall): # noqa too complex
|
def process_from_remote(self, eventcall):
|
||||||
"""this gets called for each object we receive from
|
"""This gets called for each object we receive from
|
||||||
the other side and if the channel closes.
|
the other side and if the channel closes.
|
||||||
|
|
||||||
Note that channel callbacks run in the receiver
|
Note that channel callbacks run in the receiver
|
||||||
@@ -400,7 +400,7 @@ class WorkerController:
|
|||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
# should not land in receiver-thread
|
# should not land in receiver-thread
|
||||||
raise
|
raise
|
||||||
except: # noqa
|
except BaseException:
|
||||||
from _pytest._code import ExceptionInfo
|
from _pytest._code import ExceptionInfo
|
||||||
|
|
||||||
excinfo = ExceptionInfo.from_current()
|
excinfo = ExceptionInfo.from_current()
|
||||||
|
|||||||
@@ -266,8 +266,8 @@ class TestDistribution:
|
|||||||
"-pfoobarplugin",
|
"-pfoobarplugin",
|
||||||
"--foobar=123",
|
"--foobar=123",
|
||||||
"--dist=load",
|
"--dist=load",
|
||||||
"--rsyncdir=%(subdir)s" % locals(),
|
f"--rsyncdir={subdir}",
|
||||||
"--tx=popen//chdir=%(dest)s" % locals(),
|
f"--tx=popen//chdir={dest}",
|
||||||
p,
|
p,
|
||||||
)
|
)
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
@@ -657,9 +657,7 @@ def test_crashing_item(pytester, when) -> None:
|
|||||||
|
|
||||||
def test_ok():
|
def test_ok():
|
||||||
pass
|
pass
|
||||||
""".format(
|
""".format(**code)
|
||||||
**code
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
passes = 2 if when == "teardown" else 1
|
passes = 2 if when == "teardown" else 1
|
||||||
result = pytester.runpytest("-n2", p)
|
result = pytester.runpytest("-n2", p)
|
||||||
@@ -1513,9 +1511,7 @@ class TestLocking:
|
|||||||
|
|
||||||
FILE_LOCK = filelock.FileLock("test.lock")
|
FILE_LOCK = filelock.FileLock("test.lock")
|
||||||
|
|
||||||
""" + (
|
""" + ((_test_content * 4) % ("A", "B", "C", "D"))
|
||||||
(_test_content * 4) % ("A", "B", "C", "D")
|
|
||||||
)
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("scope", ["each", "load", "loadscope", "loadfile", "no"])
|
@pytest.mark.parametrize("scope", ["each", "load", "loadscope", "loadfile", "no"])
|
||||||
def test_single_file(self, pytester, scope) -> None:
|
def test_single_file(self, pytester, scope) -> None:
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ class TestLoadScheduling:
|
|||||||
|
|
||||||
for i in range(7, 16):
|
for i in range(7, 16):
|
||||||
sched.mark_test_complete(node1, i - 3)
|
sched.mark_test_complete(node1, i - 3)
|
||||||
assert node1.sent == [0, 1] + list(range(4, i))
|
assert node1.sent == [0, 1, *range(4, i)]
|
||||||
assert node2.sent == [2, 3]
|
assert node2.sent == [2, 3]
|
||||||
assert sched.pending == list(range(i, 16))
|
assert sched.pending == list(range(i, 16))
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ class TestLoadScheduling:
|
|||||||
|
|
||||||
for complete_index, first_pending in enumerate(range(5, 16)):
|
for complete_index, first_pending in enumerate(range(5, 16)):
|
||||||
sched.mark_test_complete(node1, node1.sent[complete_index])
|
sched.mark_test_complete(node1, node1.sent[complete_index])
|
||||||
assert node1.sent == [0, 1] + list(range(4, first_pending))
|
assert node1.sent == [0, 1, *range(4, first_pending)]
|
||||||
assert node2.sent == [2, 3]
|
assert node2.sent == [2, 3]
|
||||||
assert sched.pending == list(range(first_pending, 16))
|
assert sched.pending == list(range(first_pending, 16))
|
||||||
|
|
||||||
@@ -251,9 +251,7 @@ class TestLoadScheduling:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
class CollectHook:
|
class CollectHook:
|
||||||
"""
|
"""Dummy hook that stores collection reports."""
|
||||||
Dummy hook that stores collection reports.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.reports = []
|
self.reports = []
|
||||||
@@ -295,7 +293,7 @@ class TestWorkStealingScheduling:
|
|||||||
sched.schedule()
|
sched.schedule()
|
||||||
assert not sched.pending
|
assert not sched.pending
|
||||||
assert not sched.tests_finished
|
assert not sched.tests_finished
|
||||||
assert node1.sent == list(range(0, 8))
|
assert node1.sent == list(range(8))
|
||||||
assert node2.sent == list(range(8, 16))
|
assert node2.sent == list(range(8, 16))
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
sched.mark_test_complete(node1, node1.sent[i])
|
sched.mark_test_complete(node1, node1.sent[i])
|
||||||
@@ -315,7 +313,7 @@ class TestWorkStealingScheduling:
|
|||||||
sched.add_node_collection(node2, collection)
|
sched.add_node_collection(node2, collection)
|
||||||
assert sched.collection_is_completed
|
assert sched.collection_is_completed
|
||||||
sched.schedule()
|
sched.schedule()
|
||||||
assert node1.sent == list(range(0, 8))
|
assert node1.sent == list(range(8))
|
||||||
assert node2.sent == list(range(8, 16))
|
assert node2.sent == list(range(8, 16))
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
sched.mark_test_complete(node1, node1.sent[i])
|
sched.mark_test_complete(node1, node1.sent[i])
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from xdist.workermanage import NodeManager
|
|||||||
def monkeypatch_3_cpus(monkeypatch: pytest.MonkeyPatch):
|
def monkeypatch_3_cpus(monkeypatch: pytest.MonkeyPatch):
|
||||||
"""Make pytest-xdist believe the system has 3 CPUs."""
|
"""Make pytest-xdist believe the system has 3 CPUs."""
|
||||||
# block import
|
# block import
|
||||||
monkeypatch.setitem(sys.modules, "psutil", None) # type: ignore
|
monkeypatch.setitem(sys.modules, "psutil", None)
|
||||||
monkeypatch.delattr(os, "sched_getaffinity", raising=False)
|
monkeypatch.delattr(os, "sched_getaffinity", raising=False)
|
||||||
monkeypatch.setattr(os, "cpu_count", lambda: 3)
|
monkeypatch.setattr(os, "cpu_count", lambda: 3)
|
||||||
|
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ WAIT_TIMEOUT = 10.0
|
|||||||
def check_marshallable(d):
|
def check_marshallable(d):
|
||||||
try:
|
try:
|
||||||
marshal.dumps(d)
|
marshal.dumps(d)
|
||||||
except ValueError:
|
except ValueError as e:
|
||||||
pprint.pprint(d)
|
pprint.pprint(d)
|
||||||
raise ValueError("not marshallable")
|
raise ValueError("not marshallable") from e
|
||||||
|
|
||||||
|
|
||||||
class EventCall:
|
class EventCall:
|
||||||
@@ -164,7 +164,7 @@ class TestWorkerInteractor:
|
|||||||
worker.sendcommand("runtests_all")
|
worker.sendcommand("runtests_all")
|
||||||
worker.sendcommand("shutdown")
|
worker.sendcommand("shutdown")
|
||||||
for func in "::test_func", "::test_func2":
|
for func in "::test_func", "::test_func2":
|
||||||
for i in range(3): # setup/call/teardown
|
for _ in range(3): # setup/call/teardown
|
||||||
ev = worker.popevent("testreport")
|
ev = worker.popevent("testreport")
|
||||||
assert ev.name == "testreport"
|
assert ev.name == "testreport"
|
||||||
rep = unserialize_report(ev.kwargs["data"])
|
rep = unserialize_report(ev.kwargs["data"])
|
||||||
@@ -329,12 +329,10 @@ def test_remote_mainargv(pytester: pytest.Pytester) -> None:
|
|||||||
outer_argv = sys.argv
|
outer_argv = sys.argv
|
||||||
|
|
||||||
pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
"""
|
f"""
|
||||||
def test_mainargv(request):
|
def test_mainargv(request):
|
||||||
assert request.config.workerinput["mainargv"] == {!r}
|
assert request.config.workerinput["mainargv"] == {outer_argv!r}
|
||||||
""".format(
|
"""
|
||||||
outer_argv
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
result = pytester.runpytest("-n1")
|
result = pytester.runpytest("-n1")
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
|
|||||||
4
tox.ini
4
tox.ini
@@ -63,7 +63,3 @@ commands =
|
|||||||
# it so they don't conflict with each other (#611).
|
# it so they don't conflict with each other (#611).
|
||||||
addopts = -ra -p no:pytest-services
|
addopts = -ra -p no:pytest-services
|
||||||
testpaths = testing
|
testpaths = testing
|
||||||
|
|
||||||
[flake8]
|
|
||||||
max-line-length = 120
|
|
||||||
ignore = E203,W503
|
|
||||||
|
|||||||
Reference in New Issue
Block a user