Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop Python 3.6 and add Python 3.11 #842

Merged
merged 5 commits into from
Nov 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: deploy

on:
push:
tags:
- "v*"

jobs:
deploy:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
with:
# Needed to fetch tags, which are required by setuptools-scm.
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: "3.10"
- name: Install build
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: |
python -m build
- name: Publish package to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.pypi_token }}
87 changes: 0 additions & 87 deletions .github/workflows/main.yml

This file was deleted.

67 changes: 67 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: test

on:
push:
branches:
- "*"

pull_request:
branches:
- "*"

jobs:
test:

runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
tox_env:
- "py37-pytestlatest"
- "py38-pytestlatest"
- "py39-pytestlatest"
- "py310-pytestlatest"
- "py310-pytestmain"
- "py311-pytestlatest"
- "py311-pytestmain"
- "py310-psutil"
- "py310-setproctitle"

os: [ubuntu-latest, windows-latest]
include:
- tox_env: "py37-pytestlatest"
python: "3.7"
- tox_env: "py38-pytestlatest"
python: "3.8"
- tox_env: "py39-pytestlatest"
python: "3.9"
- tox_env: "py310-pytestlatest"
python: "3.10"
- tox_env: "py310-pytestmain"
python: "3.10"
- tox_env: "py311-pytestlatest"
python: "3.11"
- tox_env: "py311-pytestmain"
python: "3.11"
- tox_env: "py310-psutil"
python: "3.10"
- tox_env: "py310-setproctitle"
python: "3.10"

steps:
- uses: actions/checkout@v3
with:
# Needed to fetch tags, which are required by setuptools-scm.
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python }}
- name: Install tox
run: |
python -m pip install --upgrade pip
pip install tox
- name: Test
run: |
tox -e ${{ matrix.tox_env }}
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pytest-xdist
:alt: Python versions
:target: https://pypi.python.org/pypi/pytest-xdist

.. image:: https://github.com/pytest-dev/pytest-xdist/workflows/build/badge.svg
.. image:: https://github.com/pytest-dev/pytest-xdist/workflows/test/badge.svg
:target: https://github.com/pytest-dev/pytest-xdist/actions

.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
Expand Down
1 change: 1 addition & 0 deletions changelog/842.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Python 3.11 is now officially supported.
1 change: 1 addition & 0 deletions changelog/842.removal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Python 3.6 is no longer supported.
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ classifiers =
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
license_file = LICENSE
project_urls =
Documentation=https://pytest-xdist.readthedocs.io/en/latest
Expand All @@ -40,7 +40,7 @@ project_urls =
packages = find:
package_dir = =src
zip_safe = False
python_requires = >=3.6
python_requires = >=3.7
install_requires =
execnet>=1.1
pytest>=6.2.0
Expand Down
12 changes: 5 additions & 7 deletions src/xdist/dsession.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def worker_workerfinished(self, node):
"""
self.config.hook.pytest_testnodedown(node=node, error=None)
if node.workeroutput["exitstatus"] == 2: # keyboard-interrupt
self.shouldstop = "{} received keyboard-interrupt".format(node)
self.shouldstop = f"{node} received keyboard-interrupt"
self.worker_errordown(node, "keyboard-interrupt")
return
if node in self.sched.nodes:
Expand Down Expand Up @@ -230,7 +230,7 @@ def worker_errordown(self, node, error):
@pytest.hookimpl
def pytest_terminal_summary(self, terminalreporter):
if self.config.option.verbose >= 0 and self._summary_report:
terminalreporter.write_sep("=", "xdist: {}".format(self._summary_report))
terminalreporter.write_sep("=", f"xdist: {self._summary_report}")

def worker_collectionfinish(self, node, ids):
"""worker has finished test collection.
Expand Down Expand Up @@ -345,7 +345,7 @@ def handle_crashitem(self, nodeid, worker):
# XXX count no of failures and retry N times
runner = self.config.pluginmanager.getplugin("runner")
fspath = nodeid.split("::")[0]
msg = "worker {!r} crashed while running {!r}".format(worker.gateway.id, nodeid)
msg = f"worker {worker.gateway.id!r} crashed while running {nodeid!r}"
rep = runner.TestReport(
nodeid, (fspath, None, fspath), (), "failed", msg, "???"
)
Expand Down Expand Up @@ -381,9 +381,7 @@ def setstatus(self, spec, status, show=True):

def getstatus(self):
if self.config.option.verbose >= 0:
parts = [
"{} {}".format(spec.id, self._status[spec.id]) for spec in self._specs
]
parts = [f"{spec.id} {self._status[spec.id]}" for spec in self._specs]
return " / ".join(parts)
else:
return "bringing up nodes..."
Expand Down Expand Up @@ -431,7 +429,7 @@ def pytest_testnodeready(self, node):
def pytest_testnodedown(self, node, error):
if not error:
return
self.write_line("[{}] node down: {}".format(node.gateway.id, error))
self.write_line(f"[{node.gateway.id}] node down: {error}")


def get_default_max_worker_restart(config):
Expand Down
2 changes: 1 addition & 1 deletion src/xdist/looponfail.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def repr_pytest_looponfailinfo(failreports, rootdirs):
tr.line(report, red=True)
tr.sep("#", "waiting for changes", bold=True)
for rootdir in rootdirs:
tr.line("### Watching: {}".format(rootdir), bold=True)
tr.line(f"### Watching: {rootdir}", bold=True)


def init_worker_session(channel, args, option_dict):
Expand Down
2 changes: 1 addition & 1 deletion src/xdist/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def pytest_collection_modifyitems(self, session, config, items):
if len(mark.args) > 0
else mark.kwargs.get("name", "default")
)
item._nodeid = "{}@{}".format(item.nodeid, gname)
item._nodeid = f"{item.nodeid}@{gname}"

@pytest.hookimpl
def pytest_collection_finish(self, session):
Expand Down
4 changes: 2 additions & 2 deletions src/xdist/scheduler/loadscope.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,12 +361,12 @@ def schedule(self):
extra_nodes = len(self.nodes) - len(self.workqueue)

if extra_nodes > 0:
self.log("Shutting down {} nodes".format(extra_nodes))
self.log(f"Shutting down {extra_nodes} nodes")

for _ in range(extra_nodes):
unused_node, assigned = self.assigned_work.popitem(last=True)

self.log("Shutting down unused node {}".format(unused_node))
self.log(f"Shutting down unused node {unused_node}")
unused_node.shutdown()

# Assign initial workload
Expand Down
16 changes: 8 additions & 8 deletions src/xdist/workermanage.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def get_dir(p):
for root in candidates:
root = Path(root).resolve()
if not root.exists():
raise pytest.UsageError("rsyncdir doesn't exist: {!r}".format(root))
raise pytest.UsageError(f"rsyncdir doesn't exist: {root!r}")
if root not in roots:
roots.append(root)
return roots
Expand Down Expand Up @@ -192,7 +192,7 @@ def _report_send_file(self, gateway, modified_rel_path):
if self._verbose > 0:
path = os.path.basename(self._sourcedir) + "/" + modified_rel_path
remotepath = gateway.spec.chdir
print("{}:{} <= {}".format(gateway.spec, remotepath, path))
print(f"{gateway.spec}:{remotepath} <= {path}")


def make_reltoroot(roots: Sequence[Path], args: List[str]) -> List[str]:
Expand All @@ -219,7 +219,7 @@ def make_reltoroot(roots: Sequence[Path], args: List[str]) -> List[str]:
parts[0] = root.name + "/" + str(x)
break
else:
raise ValueError("arg {} not relative to an rsync root".format(arg))
raise ValueError(f"arg {arg} not relative to an rsync root")
result.append(splitcode.join(parts))
return result

Expand Down Expand Up @@ -249,7 +249,7 @@ def __init__(self, nodemanager, gateway, config, putevent):
self.log = Producer(f"workerctl-{gateway.id}", enabled=config.option.debug)

def __repr__(self):
return "<{} {}>".format(self.__class__.__name__, self.gateway.id)
return f"<{self.__class__.__name__} {self.gateway.id}>"

@property
def shutting_down(self):
Expand Down Expand Up @@ -310,11 +310,11 @@ def shutdown(self):

def sendcommand(self, name, **kwargs):
"""send a named parametrized command to the other side."""
self.log("sending command {}(**{})".format(name, kwargs))
self.log(f"sending command {name}(**{kwargs})")
self.channel.send((name, kwargs))

def notify_inproc(self, eventname, **kwargs):
self.log("queuing {}(**{})".format(eventname, kwargs))
self.log(f"queuing {eventname}(**{kwargs})")
self.putevent((eventname, kwargs))

def process_from_remote(self, eventcall): # noqa too complex
Expand All @@ -336,7 +336,7 @@ def process_from_remote(self, eventcall): # noqa too complex
return
eventname, kwargs = eventcall
if eventname in ("collectionstart",):
self.log("ignoring {}({})".format(eventname, kwargs))
self.log(f"ignoring {eventname}({kwargs})")
elif eventname == "workerready":
self.notify_inproc(eventname, node=self, **kwargs)
elif eventname == "internal_error":
Expand Down Expand Up @@ -389,7 +389,7 @@ def process_from_remote(self, eventcall): # noqa too complex
location=kwargs["location"],
)
else:
raise ValueError("unknown event: {}".format(eventname))
raise ValueError(f"unknown event: {eventname}")
except KeyboardInterrupt:
# should not land in receiver-thread
raise
Expand Down
4 changes: 2 additions & 2 deletions testing/test_remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def __init__(self, eventcall):
self.name, self.kwargs = eventcall

def __str__(self):
return "<EventCall {}(**{})>".format(self.name, self.kwargs)
return f"<EventCall {self.name}(**{self.kwargs})>"


class WorkerSetup:
Expand Down Expand Up @@ -60,7 +60,7 @@ def popevent(self, name=None):
ev = EventCall(data)
if name is None or ev.name == name:
return ev
print("skipping {}".format(ev))
print(f"skipping {ev}")

def sendcommand(self, name, **kwargs):
self.slp.sendcommand(name, **kwargs)
Expand Down
Loading