Skip to content

Commit bf61092

Browse files
authored
Make --hashseed default to PYTHONHASHSEED, if defined (#3076)
1 parent 2cd8c00 commit bf61092

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

docs/changelog/2942.feature.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Make --hashseed default to PYTHONHASHSEED, if defined - by :user:`paravoid`.
2+
The main motivation for this is to able to set the hash seed when building the
3+
documentation with "tox -e docs", and thus avoid embedding a random value in
4+
the tox documentation for --help. This caused documentation builds to fail to
5+
build reproducibly.

src/tox/session/cmd/run/common.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,19 @@ def __call__(
135135
raise ArgumentError(self, str(exc)) from exc
136136
setattr(namespace, self.dest, result)
137137

138+
if os.environ.get("PYTHONHASHSEED", "random") != "random":
139+
hashseed_default = int(os.environ["PYTHONHASHSEED"])
140+
else:
141+
hashseed_default = random.randint(1, 1024 if sys.platform == "win32" else 4294967295) # noqa: S311
142+
138143
parser.add_argument(
139144
"--hashseed",
140145
metavar="SEED",
141146
help="set PYTHONHASHSEED to SEED before running commands. Defaults to a random integer in the range "
142147
"[1, 4294967295] ([1, 1024] on Windows). Passing 'noset' suppresses this behavior.",
143148
action=SeedAction,
144149
of_type=Optional[int],
145-
default=random.randint(1, 1024 if sys.platform == "win32" else 4294967295), # noqa: S311
150+
default=hashseed_default,
146151
dest="hash_seed",
147152
)
148153
parser.add_argument(

tests/tox_env/python/test_python_api.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import sys
44
from typing import TYPE_CHECKING, Callable
5+
from unittest.mock import patch
56

67
import pytest
78

@@ -220,6 +221,38 @@ def test_python_set_hash_seed_incorrect(tox_project: ToxProjectCreator) -> None:
220221
assert "tox run: error: argument --hashseed: invalid literal for int() with base 10: 'ok'" in result.err
221222

222223

224+
def test_python_use_hash_seed_from_env(tox_project: ToxProjectCreator) -> None:
225+
ini = "[testenv]\npackage=skip"
226+
with patch.dict("os.environ", {"PYTHONHASHSEED": "13"}):
227+
result = tox_project({"tox.ini": ini}).run("c", "-e", "py", "-k", "setenv")
228+
result.assert_success()
229+
assert "PYTHONHASHSEED=13" in result.out
230+
231+
232+
def test_python_hash_seed_from_env_random(tox_project: ToxProjectCreator) -> None:
233+
ini = "[testenv]\npackage=skip"
234+
with patch.dict("os.environ", {"PYTHONHASHSEED": "random"}):
235+
result = tox_project({"tox.ini": ini}).run("c", "-e", "py", "-k", "setenv")
236+
result.assert_success()
237+
assert "PYTHONHASHSEED=" in result.out
238+
239+
240+
def test_python_hash_seed_from_env_and_override(tox_project: ToxProjectCreator) -> None:
241+
ini = "[testenv]\npackage=skip\ncommands=python -c 'import os; print(os.environ.get(\"PYTHONHASHSEED\"))'"
242+
with patch.dict("os.environ", {"PYTHONHASHSEED": "14"}):
243+
result = tox_project({"tox.ini": ini}).run("r", "-e", "py", "--hashseed", "15")
244+
result.assert_success()
245+
assert result.out.splitlines()[1] == "15"
246+
247+
248+
def test_python_hash_seed_from_env_and_disable(tox_project: ToxProjectCreator) -> None:
249+
ini = "[testenv]\npackage=skip\ncommands=python -c 'import os; print(os.environ.get(\"PYTHONHASHSEED\"))'"
250+
with patch.dict("os.environ", {"PYTHONHASHSEED": "16"}):
251+
result = tox_project({"tox.ini": ini}).run("r", "-e", "py", "--hashseed", "notset")
252+
result.assert_success()
253+
assert result.out.splitlines()[1] == "None"
254+
255+
223256
@pytest.mark.parametrize("in_ci", [True, False])
224257
def test_list_installed_deps(in_ci: bool, tox_project: ToxProjectCreator, mocker: MockerFixture) -> None:
225258
mocker.patch("tox.session.cmd.run.common.is_ci", return_value=in_ci)

0 commit comments

Comments
 (0)