Merge pull request #475 from hugovk/rm-3.4
Drop support for EOL Python 3.4
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- TOXENV: "py27-pytestlatest"
|
- TOXENV: "py27-pytestlatest"
|
||||||
- TOXENV: "py34-pytestlatest"
|
|
||||||
- TOXENV: "py35-pytestlatest"
|
- TOXENV: "py35-pytestlatest"
|
||||||
- TOXENV: "py36-pytestlatest"
|
- TOXENV: "py36-pytestlatest"
|
||||||
- TOXENV: "py37-pytestlatest"
|
- TOXENV: "py37-pytestlatest"
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/ambv/black
|
- repo: https://github.com/ambv/black
|
||||||
rev: 18.6b4
|
rev: 19.10b0
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
args: [--safe, --quiet]
|
args: [--safe, --quiet]
|
||||||
language_version: python3.7
|
language_version: python3.7
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v1.3.0
|
rev: v2.4.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
|
|||||||
@@ -36,9 +36,7 @@ jobs:
|
|||||||
env: TOXENV=py27-pytestlatest
|
env: TOXENV=py27-pytestlatest
|
||||||
|
|
||||||
- stage: test
|
- stage: test
|
||||||
python: "3.4"
|
python: "3.5"
|
||||||
env: TOXENV=py34-pytestlatest
|
|
||||||
- python: "3.5"
|
|
||||||
env: TOXENV=py35-pytestlatest
|
env: TOXENV=py35-pytestlatest
|
||||||
- python: "3.6"
|
- python: "3.6"
|
||||||
env: TOXENV=py36-pytestlatest
|
env: TOXENV=py36-pytestlatest
|
||||||
|
|||||||
1
changelog/475.removal
Normal file
1
changelog/475.removal
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Drop support for EOL Python 3.4.
|
||||||
3
setup.py
3
setup.py
@@ -24,7 +24,7 @@ setup(
|
|||||||
"pytest11": ["xdist = xdist.plugin", "xdist.looponfail = xdist.looponfail"]
|
"pytest11": ["xdist = xdist.plugin", "xdist.looponfail = xdist.looponfail"]
|
||||||
},
|
},
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
|
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*",
|
||||||
install_requires=install_requires,
|
install_requires=install_requires,
|
||||||
setup_requires=["setuptools_scm"],
|
setup_requires=["setuptools_scm"],
|
||||||
classifiers=[
|
classifiers=[
|
||||||
@@ -42,7 +42,6 @@ setup(
|
|||||||
"Programming Language :: Python :: 2",
|
"Programming Language :: Python :: 2",
|
||||||
"Programming Language :: Python :: 2.7",
|
"Programming Language :: Python :: 2.7",
|
||||||
"Programming Language :: Python :: 3",
|
"Programming Language :: Python :: 3",
|
||||||
"Programming Language :: Python :: 3.4",
|
|
||||||
"Programming Language :: Python :: 3.5",
|
"Programming Language :: Python :: 3.5",
|
||||||
"Programming Language :: Python :: 3.6",
|
"Programming Language :: Python :: 3.6",
|
||||||
"Programming Language :: Python :: 3.7",
|
"Programming Language :: Python :: 3.7",
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ class DSession(object):
|
|||||||
"""
|
"""
|
||||||
self.config.hook.pytest_testnodedown(node=node, error=None)
|
self.config.hook.pytest_testnodedown(node=node, error=None)
|
||||||
if node.workeroutput["exitstatus"] == 2: # keyboard-interrupt
|
if node.workeroutput["exitstatus"] == 2: # keyboard-interrupt
|
||||||
self.shouldstop = "%s received keyboard-interrupt" % (node,)
|
self.shouldstop = "{} received keyboard-interrupt".format(node)
|
||||||
self.worker_errordown(node, "keyboard-interrupt")
|
self.worker_errordown(node, "keyboard-interrupt")
|
||||||
return
|
return
|
||||||
if node in self.sched.nodes:
|
if node in self.sched.nodes:
|
||||||
@@ -321,7 +321,7 @@ class DSession(object):
|
|||||||
# XXX count no of failures and retry N times
|
# XXX count no of failures and retry N times
|
||||||
runner = self.config.pluginmanager.getplugin("runner")
|
runner = self.config.pluginmanager.getplugin("runner")
|
||||||
fspath = nodeid.split("::")[0]
|
fspath = nodeid.split("::")[0]
|
||||||
msg = "worker %r crashed while running %r" % (worker.gateway.id, nodeid)
|
msg = "worker {!r} crashed while running {!r}".format(worker.gateway.id, nodeid)
|
||||||
rep = runner.TestReport(
|
rep = runner.TestReport(
|
||||||
nodeid, (fspath, None, fspath), (), "failed", msg, "???"
|
nodeid, (fspath, None, fspath), (), "failed", msg, "???"
|
||||||
)
|
)
|
||||||
@@ -351,7 +351,9 @@ class TerminalDistReporter(object):
|
|||||||
|
|
||||||
def getstatus(self):
|
def getstatus(self):
|
||||||
if self.config.option.verbose >= 0:
|
if self.config.option.verbose >= 0:
|
||||||
parts = ["%s %s" % (spec.id, self._status[spec.id]) for spec in self._specs]
|
parts = [
|
||||||
|
"{} {}".format(spec.id, self._status[spec.id]) for spec in self._specs
|
||||||
|
]
|
||||||
return " / ".join(parts)
|
return " / ".join(parts)
|
||||||
else:
|
else:
|
||||||
return "bringing up nodes..."
|
return "bringing up nodes..."
|
||||||
@@ -386,14 +388,16 @@ class TerminalDistReporter(object):
|
|||||||
def pytest_testnodeready(self, node):
|
def pytest_testnodeready(self, node):
|
||||||
if self.config.option.verbose > 0:
|
if self.config.option.verbose > 0:
|
||||||
d = node.workerinfo
|
d = node.workerinfo
|
||||||
infoline = "[%s] Python %s" % (d["id"], d["version"].replace("\n", " -- "))
|
infoline = "[{}] Python {}".format(
|
||||||
|
d["id"], d["version"].replace("\n", " -- ")
|
||||||
|
)
|
||||||
self.rewrite(infoline, newline=True)
|
self.rewrite(infoline, newline=True)
|
||||||
self.setstatus(node.gateway.spec, "ok")
|
self.setstatus(node.gateway.spec, "ok")
|
||||||
|
|
||||||
def pytest_testnodedown(self, node, error):
|
def pytest_testnodedown(self, node, error):
|
||||||
if not error:
|
if not error:
|
||||||
return
|
return
|
||||||
self.write_line("[%s] node down: %s" % (node.gateway.id, error))
|
self.write_line("[{}] node down: {}".format(node.gateway.id, error))
|
||||||
|
|
||||||
|
|
||||||
def get_default_max_worker_restart(config):
|
def get_default_max_worker_restart(config):
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ def repr_pytest_looponfailinfo(failreports, rootdirs):
|
|||||||
tr.line(report, red=True)
|
tr.line(report, red=True)
|
||||||
tr.sep("#", "waiting for changes", bold=True)
|
tr.sep("#", "waiting for changes", bold=True)
|
||||||
for rootdir in rootdirs:
|
for rootdir in rootdirs:
|
||||||
tr.line("### Watching: %s" % (rootdir,), bold=True)
|
tr.line("### Watching: {}".format(rootdir), bold=True)
|
||||||
|
|
||||||
|
|
||||||
def init_worker_session(channel, args, option_dict):
|
def init_worker_session(channel, args, option_dict):
|
||||||
|
|||||||
@@ -358,12 +358,12 @@ class LoadScopeScheduling(object):
|
|||||||
extra_nodes = len(self.nodes) - len(self.workqueue)
|
extra_nodes = len(self.nodes) - len(self.workqueue)
|
||||||
|
|
||||||
if extra_nodes > 0:
|
if extra_nodes > 0:
|
||||||
self.log("Shuting down {0} nodes".format(extra_nodes))
|
self.log("Shuting down {} nodes".format(extra_nodes))
|
||||||
|
|
||||||
for _ in range(extra_nodes):
|
for _ in range(extra_nodes):
|
||||||
unused_node, assigned = self.assigned_work.popitem(last=True)
|
unused_node, assigned = self.assigned_work.popitem(last=True)
|
||||||
|
|
||||||
self.log("Shuting down unused node {0}".format(unused_node))
|
self.log("Shuting down unused node {}".format(unused_node))
|
||||||
unused_node.shutdown()
|
unused_node.shutdown()
|
||||||
|
|
||||||
# Assign initial workload
|
# Assign initial workload
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ class NodeManager(object):
|
|||||||
for root in candidates:
|
for root in candidates:
|
||||||
root = py.path.local(root).realpath()
|
root = py.path.local(root).realpath()
|
||||||
if not root.check():
|
if not root.check():
|
||||||
raise pytest.UsageError("rsyncdir doesn't exist: %r" % (root,))
|
raise pytest.UsageError("rsyncdir doesn't exist: {!r}".format(root))
|
||||||
if root not in roots:
|
if root not in roots:
|
||||||
roots.append(root)
|
roots.append(root)
|
||||||
return roots
|
return roots
|
||||||
@@ -179,7 +179,7 @@ class HostRSync(execnet.RSync):
|
|||||||
if self._verbose:
|
if self._verbose:
|
||||||
path = os.path.basename(self._sourcedir) + "/" + modified_rel_path
|
path = os.path.basename(self._sourcedir) + "/" + modified_rel_path
|
||||||
remotepath = gateway.spec.chdir
|
remotepath = gateway.spec.chdir
|
||||||
print("%s:%s <= %s" % (gateway.spec, remotepath, path))
|
print("{}:{} <= {}".format(gateway.spec, remotepath, path))
|
||||||
|
|
||||||
|
|
||||||
def make_reltoroot(roots, args):
|
def make_reltoroot(roots, args):
|
||||||
@@ -198,7 +198,7 @@ def make_reltoroot(roots, args):
|
|||||||
parts[0] = root.basename + "/" + x
|
parts[0] = root.basename + "/" + x
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise ValueError("arg %s not relative to an rsync root" % (arg,))
|
raise ValueError("arg {} not relative to an rsync root".format(arg))
|
||||||
result.append(splitcode.join(parts))
|
result.append(splitcode.join(parts))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -233,7 +233,7 @@ class WorkerController(object):
|
|||||||
py.log.setconsumer(self.log._keywords, None)
|
py.log.setconsumer(self.log._keywords, None)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s %s>" % (self.__class__.__name__, self.gateway.id)
|
return "<{} {}>".format(self.__class__.__name__, self.gateway.id)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def shutting_down(self):
|
def shutting_down(self):
|
||||||
@@ -293,11 +293,11 @@ class WorkerController(object):
|
|||||||
|
|
||||||
def sendcommand(self, name, **kwargs):
|
def sendcommand(self, name, **kwargs):
|
||||||
""" send a named parametrized command to the other side. """
|
""" send a named parametrized command to the other side. """
|
||||||
self.log("sending command %s(**%s)" % (name, kwargs))
|
self.log("sending command {}(**{})".format(name, kwargs))
|
||||||
self.channel.send((name, kwargs))
|
self.channel.send((name, kwargs))
|
||||||
|
|
||||||
def notify_inproc(self, eventname, **kwargs):
|
def notify_inproc(self, eventname, **kwargs):
|
||||||
self.log("queuing %s(**%s)" % (eventname, kwargs))
|
self.log("queuing {}(**{})".format(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): # noqa too complex
|
||||||
@@ -319,7 +319,7 @@ class WorkerController(object):
|
|||||||
return
|
return
|
||||||
eventname, kwargs = eventcall
|
eventname, kwargs = eventcall
|
||||||
if eventname in ("collectionstart",):
|
if eventname in ("collectionstart",):
|
||||||
self.log("ignoring %s(%s)" % (eventname, kwargs))
|
self.log("ignoring {}({})".format(eventname, kwargs))
|
||||||
elif eventname == "workerready":
|
elif eventname == "workerready":
|
||||||
self.notify_inproc(eventname, node=self, **kwargs)
|
self.notify_inproc(eventname, node=self, **kwargs)
|
||||||
elif eventname == "workerfinished":
|
elif eventname == "workerfinished":
|
||||||
@@ -359,7 +359,7 @@ class WorkerController(object):
|
|||||||
item=kwargs["item"],
|
item=kwargs["item"],
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise ValueError("unknown event: %s" % (eventname,))
|
raise ValueError("unknown event: {}".format(eventname))
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
# should not land in receiver-thread
|
# should not land in receiver-thread
|
||||||
raise
|
raise
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class EventCall:
|
|||||||
self.name, self.kwargs = eventcall
|
self.name, self.kwargs = eventcall
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "<EventCall %s(**%s)>" % (self.name, self.kwargs)
|
return "<EventCall {}(**{})>".format(self.name, self.kwargs)
|
||||||
|
|
||||||
|
|
||||||
class WorkerSetup:
|
class WorkerSetup:
|
||||||
@@ -59,7 +59,7 @@ class WorkerSetup:
|
|||||||
ev = EventCall(data)
|
ev = EventCall(data)
|
||||||
if name is None or ev.name == name:
|
if name is None or ev.name == name:
|
||||||
return ev
|
return ev
|
||||||
print("skipping %s" % (ev,))
|
print("skipping {}".format(ev))
|
||||||
|
|
||||||
def sendcommand(self, name, **kwargs):
|
def sendcommand(self, name, **kwargs):
|
||||||
self.slp.sendcommand(name, **kwargs)
|
self.slp.sendcommand(name, **kwargs)
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ class TestNodeManager:
|
|||||||
# assert nodemanager.config.topdir == source == config.topdir
|
# assert nodemanager.config.topdir == source == config.topdir
|
||||||
nodemanager.makegateways()
|
nodemanager.makegateways()
|
||||||
nodemanager.rsync_roots()
|
nodemanager.rsync_roots()
|
||||||
p, = nodemanager.gwmanager.multi_exec(
|
(p,) = nodemanager.gwmanager.multi_exec(
|
||||||
"import os ; channel.send(os.getcwd())"
|
"import os ; channel.send(os.getcwd())"
|
||||||
).receive_each()
|
).receive_each()
|
||||||
p = py.path.local(p)
|
p = py.path.local(p)
|
||||||
@@ -269,5 +269,5 @@ class TestNodeManager:
|
|||||||
reprec = testdir.inline_run(
|
reprec = testdir.inline_run(
|
||||||
"-d", "--rsyncdir=%s" % testdir.tmpdir, "--tx", specssh, testdir.tmpdir
|
"-d", "--rsyncdir=%s" % testdir.tmpdir, "--tx", specssh, testdir.tmpdir
|
||||||
)
|
)
|
||||||
rep, = reprec.getreports("pytest_runtest_logreport")
|
(rep,) = reprec.getreports("pytest_runtest_logreport")
|
||||||
assert rep.passed
|
assert rep.passed
|
||||||
|
|||||||
Reference in New Issue
Block a user