Skip to content

Commit a9a303f

Browse files
committed
add proxy gateways with --px arg
Proxy gateways do not run workers, and are meant to be passed with the `via` attribute to additional gateways. They are useful for running multiple workers on remote machines. Example usage: ``` pytest -sv --dist=load --px "id=my_proxy//socket=IP:PORT" --tx "5*popen//via=my_proxy" ``` Proxy gateways do not run workers, anda re meant to be passed
1 parent a82981f commit a9a303f

File tree

7 files changed

+35
-14
lines changed

7 files changed

+35
-14
lines changed

src/xdist/plugin.py

+11
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,17 @@ def pytest_addoption(parser: pytest.Parser) -> None:
139139
"--tx ssh=user@codespeak.net//chdir=testcache"
140140
),
141141
)
142+
group.addoption(
143+
"--px",
144+
dest="px",
145+
action="append",
146+
default=[],
147+
metavar="xspec",
148+
help=(
149+
"Add a proxy gateway to pass to test execution environments using `via`. Example:\n"
150+
"--px id=my_proxy//socket=192.168.1.102:8888 --tx 5*popen//via=my_proxy"
151+
),
152+
)
142153
group._addoption(
143154
"-d",
144155
action="store_true",

src/xdist/scheduler/each.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from xdist.remote import Producer
88
from xdist.report import report_collection_diff
9-
from xdist.workermanage import parse_spec_config
9+
from xdist.workermanage import parse_tx_spec_config
1010
from xdist.workermanage import WorkerController
1111

1212

@@ -26,7 +26,7 @@ class EachScheduling:
2626

2727
def __init__(self, config: pytest.Config, log: Producer | None = None) -> None:
2828
self.config = config
29-
self.numnodes = len(parse_spec_config(config))
29+
self.numnodes = len(parse_tx_spec_config(config))
3030
self.node2collection: dict[WorkerController, list[str]] = {}
3131
self.node2pending: dict[WorkerController, list[int]] = {}
3232
self._started: list[WorkerController] = []

src/xdist/scheduler/load.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from xdist.remote import Producer
99
from xdist.report import report_collection_diff
10-
from xdist.workermanage import parse_spec_config
10+
from xdist.workermanage import parse_tx_spec_config
1111
from xdist.workermanage import WorkerController
1212

1313

@@ -58,7 +58,7 @@ class LoadScheduling:
5858
"""
5959

6060
def __init__(self, config: pytest.Config, log: Producer | None = None) -> None:
61-
self.numnodes = len(parse_spec_config(config))
61+
self.numnodes = len(parse_tx_spec_config(config))
6262
self.node2collection: dict[WorkerController, list[str]] = {}
6363
self.node2pending: dict[WorkerController, list[int]] = {}
6464
self.pending: list[int] = []

src/xdist/scheduler/loadscope.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from xdist.remote import Producer
1010
from xdist.report import report_collection_diff
11-
from xdist.workermanage import parse_spec_config
11+
from xdist.workermanage import parse_tx_spec_config
1212
from xdist.workermanage import WorkerController
1313

1414

@@ -91,7 +91,7 @@ class LoadScopeScheduling:
9191
"""
9292

9393
def __init__(self, config: pytest.Config, log: Producer | None = None) -> None:
94-
self.numnodes = len(parse_spec_config(config))
94+
self.numnodes = len(parse_tx_spec_config(config))
9595
self.collection: list[str] | None = None
9696

9797
self.workqueue: OrderedDict[str, dict[str, bool]] = OrderedDict()

src/xdist/scheduler/worksteal.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from xdist.remote import Producer
99
from xdist.report import report_collection_diff
10-
from xdist.workermanage import parse_spec_config
10+
from xdist.workermanage import parse_tx_spec_config
1111
from xdist.workermanage import WorkerController
1212

1313

@@ -65,7 +65,7 @@ class WorkStealingScheduling:
6565
"""
6666

6767
def __init__(self, config: pytest.Config, log: Producer | None = None) -> None:
68-
self.numnodes = len(parse_spec_config(config))
68+
self.numnodes = len(parse_tx_spec_config(config))
6969
self.node2collection: dict[WorkerController, list[str]] = {}
7070
self.node2pending: dict[WorkerController, list[int]] = {}
7171
self.pending: list[int] = []

src/xdist/workermanage.py

+14-4
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from xdist.remote import WorkerInfo
2424

2525

26-
def parse_spec_config(config: pytest.Config) -> list[str]:
26+
def parse_tx_spec_config(config: pytest.Config) -> list[str]:
2727
xspeclist = []
2828
tx: list[str] = config.getvalue("tx")
2929
for xspec in tx:
@@ -57,8 +57,15 @@ def __init__(
5757
if self.testrunuid is None:
5858
self.testrunuid = uuid.uuid4().hex
5959
self.group = execnet.Group(execmodel="main_thread_only")
60+
for proxy_spec in self._getpxspecs():
61+
# Proxy gateways do not run workers, and are meant to be passed with the `via` attribute
62+
# to additional gateways.
63+
# They are useful for running multiple workers on remote machines.
64+
if getattr(proxy_spec, "id", None) is None:
65+
raise pytest.UsageError(f"Proxy gateway {proxy_spec} must include an id")
66+
self.group.makegateway(proxy_spec)
6067
if specs is None:
61-
specs = self._getxspecs()
68+
specs = self._gettxspecs()
6269
self.specs: list[execnet.XSpec] = []
6370
for spec in specs:
6471
if not isinstance(spec, execnet.XSpec):
@@ -107,8 +114,11 @@ def setup_node(
107114
def teardown_nodes(self) -> None:
108115
self.group.terminate(self.EXIT_TIMEOUT)
109116

110-
def _getxspecs(self) -> list[execnet.XSpec]:
111-
return [execnet.XSpec(x) for x in parse_spec_config(self.config)]
117+
def _gettxspecs(self) -> list[execnet.XSpec]:
118+
return [execnet.XSpec(x) for x in parse_tx_spec_config(self.config)]
119+
120+
def _getpxspecs(self) -> list[execnet.XSpec]:
121+
return [execnet.XSpec(x) for x in self.config.getoption("px")]
112122

113123
def _getrsyncdirs(self) -> list[Path]:
114124
for spec in self.specs:

testing/test_plugin.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -295,15 +295,15 @@ class TestDistOptions:
295295
def test_getxspecs(self, pytester: pytest.Pytester) -> None:
296296
config = pytester.parseconfigure("--tx=popen", "--tx", "ssh=xyz")
297297
nodemanager = NodeManager(config)
298-
xspecs = nodemanager._getxspecs()
298+
xspecs = nodemanager._gettxspecs()
299299
assert len(xspecs) == 2
300300
print(xspecs)
301301
assert xspecs[0].popen
302302
assert xspecs[1].ssh == "xyz"
303303

304304
def test_xspecs_multiplied(self, pytester: pytest.Pytester) -> None:
305305
config = pytester.parseconfigure("--tx=3*popen")
306-
xspecs = NodeManager(config)._getxspecs()
306+
xspecs = NodeManager(config)._gettxspecs()
307307
assert len(xspecs) == 3
308308
assert xspecs[1].popen
309309

0 commit comments

Comments
 (0)