Skip to content

Commit 05ddc1e

Browse files
authored
fix: change the way we reexec mergify to enable PYTHONUTF8 (#777)
poetry/setuptools creates a windows binary on windows. The current reexec code does not work with this binary as we expect the sys.argv[0] to be python script. This changes the way we enable UTF8 mode to reexec the exact binary that launch the initial process. This should works on all platforms whatever the console script file is a python file or a binary.
1 parent 86d8a20 commit 05ddc1e

File tree

2 files changed

+14
-35
lines changed

2 files changed

+14
-35
lines changed

mergify_cli/cli.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
from __future__ import annotations
1717

1818
import os
19-
import subprocess
2019
import sys
2120

2221
import click
@@ -51,11 +50,8 @@ def enforce_utf8_mode() -> None:
5150
if sys.flags.utf8_mode:
5251
return
5352

54-
argv = [sys.executable, "-X", "utf8"]
55-
argv.extend(subprocess._args_from_interpreter_flags()) # type: ignore[attr-defined] # noqa: SLF001
56-
argv.extend(sys.argv)
57-
58-
os.execv(argv[0], argv) # noqa: S606
53+
os.environ["PYTHONUTF8"] = "1"
54+
os.execvpe(sys.argv[0], sys.argv, os.environ) # noqa: S606
5955

6056

6157
def main() -> None:
@@ -65,4 +61,10 @@ def main() -> None:
6561
# Let's try our best by forcing utf-8 and if it's impossible, just returns escaped character
6662
if os.name == "nt":
6763
enforce_utf8_mode()
64+
65+
# We do that to test the console script generated by poetry
66+
if os.getenv("MERGIFY_CLI_TESTING_UTF8_MODE"):
67+
print(f"utf8_mode={int(sys.flags.utf8_mode)}") # noqa: T201
68+
print("✅") # noqa: T201
69+
6870
cli()

mergify_cli/tests/test_cli.py

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,28 @@
11
import os
2-
import pathlib
32
import subprocess
4-
import sys
5-
import textwrap
63

74

8-
def test_reexec_enables_utf8_and_prints_emoji(
9-
tmp_path: pathlib.Path,
10-
) -> None:
5+
def test_reexec_enables_utf8_and_prints_emoji() -> None:
116
"""
127
Run in a child process so os.execv can safely replace it.
138
We patch mymodule.cli inside the child (no mocks), then call main().
149
We assert:
1510
- sys.flags.utf8_mode == 1 at print time
1611
- the emoji is present in stdout
1712
"""
18-
script = tmp_path / "runner.py"
19-
script.write_text(
20-
textwrap.dedent(
21-
"""
22-
import sys
23-
import os
24-
25-
from mergify_cli import cli
26-
27-
# Make cli() print a probe + the emoji
28-
def _cli():
29-
print(f"utf8_mode={int(sys.flags.utf8_mode)}")
30-
print("✅")
31-
32-
cli.cli = _cli
33-
cli.main()
34-
""",
35-
),
36-
encoding="utf-8",
37-
)
38-
3913
# Force utf8_mode OFF initially so enforce_utf8_mode triggers on Windows.
4014
env = os.environ.copy()
4115
env["PYTHONUTF8"] = "0" # ensure not already in UTF-8 mode
16+
env["MERGIFY_CLI_TESTING_UTF8_MODE"] = "1"
4217

43-
proc = subprocess.run(
44-
[sys.executable, str(script)],
18+
# We need to use shell to get binary PATH lookup working on windows
19+
proc = subprocess.run( # noqa: S602
20+
"mergify --help",
4521
check=False,
4622
env=env,
4723
capture_output=True,
4824
text=True,
25+
shell=True,
4926
)
5027

5128
assert proc.returncode == 0, proc.stderr

0 commit comments

Comments
 (0)