Skip to content
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
13 changes: 6 additions & 7 deletions tests/test_adopt_git_reads.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@

import pytest

from conftest import REPO, appended_to_command_scope, git, make_source_repo
from conftest import (REPO, appended_to_command_scope, git, make_source_repo,
skip_where_a_name_cannot_be_not_utf_8)
from test_adopt_template_values import (ADOPT_REFUSED, PLAN_FILE, PLAN_OK,
PROJECT, REMOTES, SPLIT_BRANCH,
VERIFIED, WORK, adopted, answer,
Expand Down Expand Up @@ -462,12 +463,10 @@ def test_a_utf8_clone_of_a_source_whose_path_is_not_utf8_adopts(tmp_path):
--source <the clone>` ended in this issue's traceback; it now adopts.
Skipped where no directory can be named with the byte 0xE9 (Windows,
macOS's APFS) or git will not work in one."""
try:
parent = Path(os.fsdecode(os.path.join(os.fsencode(tmp_path),
b"caf\xe9")))
parent.mkdir()
except (OSError, UnicodeError) as exc:
pytest.skip(f"no directory here is named b'caf\\xe9': {exc!r}")
skip_where_a_name_cannot_be_not_utf_8(tmp_path)
parent = Path(os.fsdecode(os.path.join(os.fsencode(tmp_path),
b"caf\xe9")))
parent.mkdir()
try:
source = make_source_repo(parent / "Thing")
except AssertionError as exc:
Expand Down
21 changes: 7 additions & 14 deletions tests/test_adopt_plan_escapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
import pytest

from conftest import (ADOPT, REPO, blank_unnamed_pin_sources, git,
make_source_repo, resolve)
make_source_repo, resolve,
skip_where_a_name_cannot_be_not_utf_8)

sys.path.insert(0, str(REPO / "scripts"))
import repo_shape # noqa: E402
Expand Down Expand Up @@ -398,12 +399,10 @@ def test_a_source_directory_that_is_not_utf8_is_shown_spelled(adopter,
`UnicodeEncodeError` on a strict UTF-8 stdout after the plan was written.
Both show it spelled now. Skipped where no directory can be named with
the byte 0xE9 (Windows, macOS's APFS) or git will not work in one."""
try:
parent = Path(os.fsdecode(os.path.join(os.fsencode(tmp_path),
b"caf\xe9")))
parent.mkdir()
except (OSError, UnicodeError) as exc:
pytest.skip(f"no directory here is named b'caf\\xe9': {exc!r}")
skip_where_a_name_cannot_be_not_utf_8(tmp_path)
parent = Path(os.fsdecode(os.path.join(os.fsencode(tmp_path),
b"caf\xe9")))
parent.mkdir()
try:
source = make_source_repo(parent / "Thing")
except AssertionError as exc:
Expand Down Expand Up @@ -458,13 +457,7 @@ def test_a_leg_extracts_a_path_that_is_not_utf8(adopter, tmp_path):
lifting that refusal reaches this, so the extraction is tested here,
directly. Skipped where no file can be named with that byte (Windows,
macOS's APFS): filter-repo works in a clone, which checks the name out."""
try:
probe = Path(os.fsdecode(os.path.join(os.fsencode(tmp_path),
b"caf\xe9.txt")))
probe.write_bytes(b"")
probe.unlink()
except (OSError, UnicodeError) as exc:
pytest.skip(f"no file here is named b'caf\\xe9.txt': {exc!r}")
skip_where_a_name_cannot_be_not_utf_8(tmp_path)
source = odd_source(tmp_path, b"caf\xe9.txt")
commit = git("rev-parse", "HEAD", cwd=source).stdout.strip()
remote = tmp_path / "Northwind-code.git"
Expand Down
13 changes: 6 additions & 7 deletions tests/test_adopt_template_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
import pytest

from conftest import (ADOPT, REPO, WINDOWS_SKIP, blank_unnamed_pin_sources,
make_source_repo, resolve)
make_source_repo, resolve,
skip_where_a_name_cannot_be_not_utf_8)

sys.path.insert(0, str(REPO / "scripts"))
import shape_materialize # noqa: E402
Expand Down Expand Up @@ -292,12 +293,10 @@ def test_execute_refuses_a_local_source_directory_that_is_not_utf8(tmp_path):
path, which `_remote_repository` reads as UTF-8. Skipped where no
directory can be named with the byte 0xE9 (Windows, macOS's APFS) or
git will not work in one."""
try:
parent = Path(os.fsdecode(os.path.join(os.fsencode(tmp_path),
b"caf\xe9")))
parent.mkdir()
except (OSError, UnicodeError) as exc:
pytest.skip(f"no directory here is named b'caf\\xe9': {exc!r}")
skip_where_a_name_cannot_be_not_utf_8(tmp_path)
parent = Path(os.fsdecode(os.path.join(os.fsencode(tmp_path),
b"caf\xe9")))
parent.mkdir()
refused_then_moved(tmp_path, parent, b"a byte that is not UTF-8")


Expand Down
39 changes: 28 additions & 11 deletions tests/test_clone_url_bytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@

import pytest

from conftest import ORG, SCAFFOLD, blank_unnamed_pin_sources
from conftest import (ORG, SCAFFOLD, blank_unnamed_pin_sources,
skip_where_a_name_cannot_be_not_utf_8)
# Fixtures of the #282 file, on the harness this one shares with it: the
# scaffold loaded as a module, and the guard that no process is started.
from test_scaffold_free_text_values import ( # noqa: F401 - fixtures
Expand Down Expand Up @@ -151,18 +152,34 @@ def family_refusal(url: str, reason: str) -> str:
f"{FAMILY_REMEDIATION}\n")


def skip_where_this_system_cannot_name(tmp_path: Path, raw: bytes) -> None:
"""Skip where `tmp_path/<raw>` cannot be made on this system. Two
questions, each asked only of the names it is about:

- a name that is not UTF-8 goes to `skip_where_a_name_cannot_be_not_utf_8`,
which skips on the two answers that mean "this system cannot carry
it" (Windows names its files in UTF-16, and macOS answers EILSEQ) and
raises any other error of the disk;
- a control character, 0x00 to 0x1F, is refused by Windows in any name,
and a name that holds one is skipped there.

Nothing else is skipped: U+202E, which NTFS holds, is a name Windows
makes as Linux does (#757; reasoned, no Windows run: CI is Linux only).
`tests/test_non_utf8_name_callers.py` holds the answers by emulation."""
try:
raw.decode("utf-8")
except UnicodeDecodeError:
skip_where_a_name_cannot_be_not_utf_8(tmp_path)
if os.name == "nt" and any(byte < 0x20 for byte in raw):
pytest.skip("Windows refuses a control character in a file name")


def directory_named(tmp_path: Path, raw: bytes) -> Path:
"""`tmp_path/<raw>` made from BYTES, empty; the test is skipped where the
disk cannot hold such a name (macOS refuses a name that is not UTF-8 and
Windows names its files in UTF-16, and refuses a control character)."""
if os.name == "nt":
pytest.skip("Windows names its files in UTF-16, which has no byte "
"that is not UTF-8, and refuses a control character")
"""`tmp_path/<raw>` made from BYTES, empty; the test is skipped where this
system cannot hold such a name, and fails on any other error of the disk."""
skip_where_this_system_cannot_name(tmp_path, raw)
made = os.fsencode(tmp_path) + os.fsencode(os.sep) + raw
try:
os.mkdir(made)
except (OSError, ValueError, UnicodeError) as error:
pytest.skip(f"this disk cannot hold the name {raw!r}: {error}")
os.mkdir(made)
path = Path(os.fsdecode(made))
assert path.is_dir()
assert os.listdir(path) == []
Expand Down
25 changes: 24 additions & 1 deletion tests/test_non_utf8_git_reads.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@ def test_make_file_skips_where_fsencode_makes_no_byte_and_writes_nothing(
def test_make_file_writes_a_name_that_is_utf8_where_fsencode_makes_no_byte(
tmp_path, monkeypatch):
"""The guard is for the byte and no wider: Windows holds `caf\\u00e9.yml`
as text, and the tests that use it must run there."""
as text, and the tests that use it must run there. Skipped, before the
Windows `os.fsencode` is put in, where this system's own file name
encoding cannot write `caf\\u00e9.yml` (ASCII); and for nothing else, so a
write the disk refuses fails the test (#757)."""
skip_where_the_environment_cannot_carry(UTF8)
monkeypatch.setattr(os, "fsencode", windows_fsencode)
target = tmp_path / UTF8
assert skip_message(make_file, target, b"on: [pull_request]\n") is None
Expand Down Expand Up @@ -495,6 +499,23 @@ def test_a_clean_standard_prints_no_warning(standard, tmp_path, run, warning,
"Windows converts it")
LEGACY_NAME = "Jos\udce9"


def skip_where_the_environment_cannot_carry(value: str) -> None:
"""Skip where this system's file name encoding cannot encode `value`, as
under `LC_ALL=C PYTHONUTF8=0 PYTHONCOERCECLOCALE=0` (ASCII). It is asked of
a file name (`make_file` cannot write `caf\\u00e9.yml`) and of an
environment value: `subprocess` puts each one through `os.fsencode`
before it starts the child, so a `user.name` of `Jos\\u00e9` raises
`UnicodeEncodeError` in the test and not in the tool (#757). Text that is
ASCII, or a lone surrogate that `os.fsencode` gives back as its byte, is
carried."""
try:
os.fsencode(value)
except UnicodeEncodeError:
pytest.skip(f"this system's file name encoding "
f"({sys.getfilesystemencoding()}) cannot carry {value!r}")


REFUSED = "REFUSED family-unwritable-value: "
#: How the refusal names the creator when no flag supplied it: `_manifest_flags`
#: (#307), so that the two refusals agree on who is meant.
Expand Down Expand Up @@ -628,6 +649,7 @@ def test_a_user_name_that_is_text_still_initialises(tmp_path, value, dry_run):
exit 0, `created_by: "Jose"`. Text a file holds is not refused: an
accent, a U+200C ZERO WIDTH NON-JOINER, a backslash and a quote, which
the scaffold lets through as well."""
skip_where_the_environment_cannot_carry(value)
result = init(tmp_path, user_name(value), dry_run=dry_run)
assert result.returncode == 0, result.stderr + result.stdout
assert "REFUSED" not in result.stderr, result.stderr
Expand All @@ -648,6 +670,7 @@ def test_every_other_name_no_file_can_hold_is_refused_the_same_way(
asks it of the same setting: a line break, a bidi control and a control
character in `git config user.name` are refused in its words, where the
byte that is not UTF-8 is the case the issue lists."""
skip_where_the_environment_cannot_carry(value)
result = init(tmp_path, user_name(value), dry_run=True)
assert result.returncode == 2, result.stderr + result.stdout
assert result.stderr.startswith(
Expand Down
Loading
Loading