Skip to content
4 changes: 2 additions & 2 deletions tests/test_update_shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -1222,8 +1222,8 @@ def test_no_trailer_leaves_the_commit_carrying_none(root,
assert result.returncode == 0, result.stderr + result.stdout
assert trailers_of(root) == []
assert message_of(root).endswith(
"the copies are not hand-edited and the digests are recomputed, not "
"adjusted.\n")
"the copies re-copied from the upstream are not hand-edited and the "
"digests are recomputed, not adjusted.\n")
assert "Lane:" not in message_of(root)


Expand Down
374 changes: 374 additions & 0 deletions tests/test_update_shape_branch_any_directory.py

Large diffs are not rendered by default.

437 changes: 437 additions & 0 deletions tests/test_update_shape_header_comments.py

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions tests/test_update_shape_landing.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,11 @@
"--title " in line
assert f"`apply --push --pr` run again on {BRANCH}" in result.stderr
else:
assert line.endswith(f"&& gh pr create --repo testorg/{PROJECT} "
f"--base main --head {BRANCH}"), line
assert f"&& gh pr create --repo testorg/{PROJECT} --base main " \
f"--head {BRANCH} --title " in line, line
assert " --body " in line and "--fill" not in line, (
"a bare `gh pr create` has gh prompt for what a shell with no "
"terminal cannot answer (#535)")

Check warning on line 428 in tests/test_update_shape_landing.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Split this composite assertion into separate assertions.

See more on https://sonarcloud.io/project/issues?id=opensoft_openRepoShape&issues=AaE7iiU2eu8GDtkk7Emi&open=AaE7iiU2eu8GDtkk7Emi&pullRequest=558
assert "run again" not in result.stderr, (
"a re-run without --pr finishes nothing, so none is promised")
the_commit_stands(root, project)
Expand Down
704 changes: 704 additions & 0 deletions tests/test_update_shape_messages.py

Large diffs are not rendered by default.

35 changes: 30 additions & 5 deletions tests/test_update_shape_next_quoting.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@

sys.path.insert(0, str(REPO / "scripts"))
from repo_shape import PYTHON # noqa: E402
from shape_materialize import SHAPE_REPOSITORY # noqa: E402

UPDATE = REPO / "update-shape.py"
PIN = "contracts/shape-pin.yaml"
Expand Down Expand Up @@ -156,6 +157,23 @@ def steps(argv: list[str]) -> list[list[str]]:
return out


#: The first words of the body of every pull request this tool opens or tells a
#: person to open (#535). What the rest of it says is
#: `tests/test_update_shape_messages.py`'s.
BODY_OPENS = "Written by openRepoShape's `update-shape.py`: "


def pr_words(project: dict) -> tuple[str, str]:
"""`(title, body)` of the pull request for the run these tests make, spelled
out by hand: the line a person pastes carries both (#535), because a
`gh pr create` without them has `gh` prompt for them."""
return (f"Re-sync the shape copies to {SHAPE_REPOSITORY} @ "
f"{project['b'][:12]}",
BODY_OPENS + "`contracts/shape-pin.yaml` and `project.yaml` "
f"re-pinned onto {project['b']}. No copy re-copied from the "
"upstream was hand-edited and every digest was recomputed.")


def check_run(project, root, *, lane: str = "", upstream=None):
result = run_script(UPDATE, "check", "--root", str(root), "--upstream",
str(upstream or project["upstream"]),
Expand Down Expand Up @@ -241,10 +259,11 @@ def test_the_branch_next_line_is_one_argv(project, make_root, name):
branch = "shape/next-quoting-branch"
result = apply(root, project, "--branch", branch)
assert result.returncode == 0, result.stdout + result.stderr
title, body = pr_words(project)
assert argv_of(next_line_of(result.stdout)) == [
"git", "-C", str(root.resolve()), "push", "-u", "origin", branch,
"&&", "gh", "pr", "create", "--repo", f"{ORG}/{PROJECT}", "--base",
"main", "--head", branch]
"main", "--head", branch, "--title", title, "--body", body]


def test_the_branch_and_push_next_line_is_one_argv(project, make_root):
Expand All @@ -255,9 +274,10 @@ def test_the_branch_and_push_next_line_is_one_argv(project, make_root):
branch = "shape/next-quoting-pushed"
result = apply(root, project, "--branch", branch, "--push")
assert result.returncode == 0, result.stdout + result.stderr
title, body = pr_words(project)
assert argv_of(next_line_of(result.stdout)) == [
"gh", "pr", "create", "--repo", f"{ORG}/{PROJECT}", "--base", "main",
"--head", branch]
"--head", branch, "--title", title, "--body", body]


@pytest.mark.parametrize("name", AWKWARD)
Expand Down Expand Up @@ -330,7 +350,9 @@ def test_the_branch_is_quoted_even_where_its_alphabet_makes_that_a_no_op(
"bare; `_by_hand` says so of its own lines")
def test_a_plain_root_prints_the_bytes_it_always_printed(project, make_root):
"""THE LINES BEFORE #325, spelled out by hand: for a root and an upstream
that need no quoting, not one byte of any of the three lines moved."""
that need no quoting, not one byte of any of the three lines moved. The
one change since is on purpose: the `gh pr create` the branch line ends
with carries `--title` and `--body` (#535), after everything it had."""
root = make_root("plain")
for path in (root.resolve(), project["upstream"].resolve()):
assert shlex.quote(str(path)) == str(path), (
Expand All @@ -349,9 +371,11 @@ def test_a_plain_root_prints_the_bytes_it_always_printed(project, make_root):
pushing = make_root("plain-too")
branched = apply(pushing, project, "--branch", branch)
assert branched.returncode == 0, branched.stdout + branched.stderr
title, body = pr_words(project)
assert next_line_of(branched.stdout) == (
f"NEXT git -C {pushing.resolve()} push -u origin {branch} && "
f"gh pr create --repo {ORG}/{PROJECT} --base main --head {branch}")
f"gh pr create --repo {ORG}/{PROJECT} --base main --head {branch} "
f"--title {shlex.quote(title)} --body {shlex.quote(body)}")

bare = make_root("plain-three")
unbranched = apply(bare, project)
Expand Down Expand Up @@ -449,9 +473,10 @@ def test_the_branch_line_pushes_and_opens_when_it_is_pasted(project, make_root,
pasted = paste(next_line_of(result.stdout), tmp_path, env)

assert pasted.returncode == 0, pasted.stdout + pasted.stderr
title, body = pr_words(project)
assert log.read_text(encoding="utf-8").split("\n")[:-1] == [
"pr", "create", "--repo", f"{ORG}/{PROJECT}", "--base", "main",
"--head", branch]
"--head", branch, "--title", title, "--body", body]
remote = git("config", "remote.origin.url", cwd=root).stdout.strip()
assert git("rev-parse", "--verify", "--quiet", f"refs/heads/{branch}",
cwd=Path(remote)).stdout.strip() == git(
Expand Down
65 changes: 46 additions & 19 deletions tests/test_update_shape_pr_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@
UPDATE = REPO / "update-shape.py"


def without_its_words(line: str) -> str:
"""A printed `gh pr create` less the `--title <t> --body <b>` it ends on
(#535): each is checked to be there, and what they say is
`tests/test_update_shape_messages.py`'s. What is left is the part these
tests are about, the repository, the base and the head."""
assert " --title " in line and " --body " in line, line

Check warning on line 49 in tests/test_update_shape_pr_base.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Split this composite assertion into separate assertions.

See more on https://sonarcloud.io/project/issues?id=opensoft_openRepoShape&issues=AaE7iiXoeu8GDtkk7Eml&open=AaE7iiXoeu8GDtkk7Eml&pullRequest=558
assert "--fill" not in line, line
return line.partition(" --title ")[0]


def project_with_an_upstream_fix(tmp_path_factory, subdir: str,
*scaffold_args: str) -> dict:
"""A project at A, and an upstream that has since moved to B — the shape
Expand Down Expand Up @@ -156,8 +166,9 @@
line = next_line_of(result.stdout)
assert "gh pr create" in line
assert line.count("--base") == 1, line
assert line.endswith(f"gh pr create --repo {ORG}/{PROJECT} --base "
f"{case.base} --head {branch}"), line
assert without_its_words(line).endswith(
f"gh pr create --repo {ORG}/{PROJECT} --base {case.base} --head "
f"{branch}"), line


def test_the_next_line_after_a_push_names_the_repository_not_a_placeholder(
Expand All @@ -170,8 +181,9 @@
assert result.returncode == 0, result.stdout + result.stderr
line = next_line_of(result.stdout)
assert "<" not in line and ">" not in line, line
assert line == (f"NEXT gh pr create --repo {ORG}/{PROJECT} --base "
f"{case.base} --head {branch}"), line
assert without_its_words(line) == (
f"NEXT gh pr create --repo {ORG}/{PROJECT} --base {case.base} "
f"--head {branch}"), line


def test_the_pull_request_is_opened_against_the_base_the_next_line_names(
Expand Down Expand Up @@ -205,11 +217,19 @@
assert opened_against == case.base
assert opened_in == f"{ORG}/{PROJECT}"
plain, branch = printed[()]
assert plain.endswith(f" && gh pr create --repo {opened_in} --base "
f"{opened_against} --head {branch}"), plain
assert without_its_words(plain).endswith(
f" && gh pr create --repo {opened_in} --base {opened_against} "
f"--head {branch}"), plain
pushed, branch = printed[("--push",)]
assert pushed == (f"NEXT gh pr create --repo {opened_in} --base "
f"{opened_against} --head {branch}"), pushed
assert without_its_words(pushed) == (
f"NEXT gh pr create --repo {opened_in} --base {opened_against} "
f"--head {branch}"), pushed
# THE WORDS TOO (#535): what a person pastes opens the pull request with
# the title and the body `--pr` opens it with.
for line in (plain, pushed):
words = shlex.split(line)[-4:]
assert words == ["--title", command[command.index("--title") + 1],
"--body", command[command.index("--body") + 1]], line


@pytest.mark.parametrize("kind_name", ["PROJECT_KIND", "FAMILY_KIND"])
Expand All @@ -231,7 +251,8 @@
update_shape.next_line(tmp_path, args, [], "0" * 40, [], kind)
line = capsys.readouterr().out.strip()
assert line.startswith("NEXT"), line
assert line.endswith(f"--base {base} --head shape/x"), line
assert without_its_words(line).endswith(
f"--base {base} --head shape/x"), line


#: Manifests a family holder and a project can declare their repository in,
Expand Down Expand Up @@ -269,8 +290,9 @@
args = SimpleNamespace(branch="shape/x", push=push, pr=False)
update_shape.next_line(tmp_path, args, [], "0" * 40, [], kind)
line = capsys.readouterr().out.strip()
assert line.endswith(f"gh pr create --repo {repository} --base main "
"--head shape/x"), line
assert without_its_words(line).endswith(
f"gh pr create --repo {repository} --base main --head shape/x"), \
line
assert line.startswith("NEXT gh pr create" if push else
"NEXT git -C "), line

Expand Down Expand Up @@ -315,18 +337,20 @@

args = SimpleNamespace(branch="shape/x", push=True, pr=False)
update_shape.next_line(tmp_path, args, [], "0" * 40, [], kind)
assert capsys.readouterr().out.strip() == (
assert without_its_words(capsys.readouterr().out.strip()) == (
"NEXT gh pr create --repo <org>/<Project> --base main --head shape/x")
args = SimpleNamespace(branch="shape/x", push=False, pr=False)
update_shape.next_line(tmp_path, args, [], "0" * 40, [], kind)
assert capsys.readouterr().out.strip().endswith(
assert without_its_words(capsys.readouterr().out.strip()).endswith(
" && gh pr create --base main --head shape/x")
# The line a failed `--push` prints (#204) leaves `--repo` off too: a
# placeholder would be one literal argument in a line quoted as an argv.
args = SimpleNamespace(branch="shape/x", push=True, pr=False)
assert update_shape.pull_request_line(
tmp_path, args, "0" * 40, SimpleNamespace(repository="o/r"),
kind) == ["gh", "pr", "create", "--base", "main", "--head", "shape/x"]
create = update_shape.pull_request_line(
tmp_path, args, "0" * 40, SimpleNamespace(repository="o/r"), kind)
assert create[:7] == ["gh", "pr", "create", "--base", "main", "--head",
"shape/x"], create
assert create[7] == "--title" and create[9] == "--body", create

Check warning on line 353 in tests/test_update_shape_pr_base.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Split this composite assertion into separate assertions.

See more on https://sonarcloud.io/project/issues?id=opensoft_openRepoShape&issues=AaE7iiXoeu8GDtkk7Emm&open=AaE7iiXoeu8GDtkk7Emm&pullRequest=558


def test_nothing_in_the_next_line_names_a_base_when_the_pull_request_is_open(
Expand Down Expand Up @@ -356,9 +380,11 @@
update_shape.next_line(tmp_path, args, [], "0" * 40, [])
line = capsys.readouterr().out.strip()
command = line.partition(" && ")[2] if not push else line[len("NEXT "):]
assert shlex.split(command) == [
words = shlex.split(command)
assert words[:9] == [
"gh", "pr", "create", "--repo", "acme/It's here", "--base", "a&b",
"--head", "shape/x"], line
assert words[9] == "--title" and words[11] == "--body", line

Check warning on line 387 in tests/test_update_shape_pr_base.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Split this composite assertion into separate assertions.

See more on https://sonarcloud.io/project/issues?id=opensoft_openRepoShape&issues=AaE7iiXoeu8GDtkk7Emn&open=AaE7iiXoeu8GDtkk7Emn&pullRequest=558


FAMILY_SOURCE = "templates/family-root/scripts/validate-family.py"
Expand Down Expand Up @@ -403,8 +429,9 @@
assert result.returncode == 0, result.stdout + result.stderr
assert f"committed on {branch}" in result.stdout, result.stdout
line = next_line_of(result.stdout)
assert line.endswith(f"gh pr create --repo {ORG}/{HOLDER} --base trunk "
f"--head {branch}"), line
assert without_its_words(line).endswith(
f"gh pr create --repo {ORG}/{HOLDER} --base trunk --head {branch}"), \
line
assert line.startswith("NEXT git -C " if not flags else
"NEXT gh pr create"), line
assert git("status", "--porcelain", cwd=holder).stdout == ""
Expand Down
Loading
Loading