From 1e92e6e0b6626ec3656cb9f87a50c76826a7144f Mon Sep 17 00:00:00 2001 From: Tom Cobb Date: Mon, 12 Sep 2022 13:38:29 +0000 Subject: [PATCH] Fixes for adopting pydata-docs branch --- src/python3_pip_skeleton/__main__.py | 42 ++----- tests/test_adopt.py | 173 +++++++++++++++++++++++++++ 2 files changed, 184 insertions(+), 31 deletions(-) create mode 100644 tests/test_adopt.py diff --git a/src/python3_pip_skeleton/__main__.py b/src/python3_pip_skeleton/__main__.py index 7710e7d8..1e493ff1 100644 --- a/src/python3_pip_skeleton/__main__.py +++ b/src/python3_pip_skeleton/__main__.py @@ -18,11 +18,7 @@ # Extensions to change CHANGE_SUFFIXES = [".py", ".rst", ".cfg", "", ".toml"] # Files not to change -IGNORE_FILES = ["CHANGELOG.rst", "test_boilerplate_removed.py"] -# Ranges to ignore between -IGNORE_RANGES = { - "CONTRIBUTING.rst": ("\nUpdating the tools\n", None), -} +IGNORE_FILES = ["update-tools.rst", "test_boilerplate_removed.py"] SKELETON_ROOT_COMMIT = "ededf00035e6ccfac78946213009c1ecd7c110a9" @@ -88,34 +84,15 @@ def replace_text(text: str) -> str: # will do the wrong thing shutil.rmtree(git_tmp / "src", ignore_errors=True) # Merge in the skeleton commits - git_tmp("pull", SKELETON, "main") + git_tmp("pull", "--rebase=false", SKELETON, "main") # Move things around git_tmp("mv", "src/python3_pip_skeleton", f"src/{package}") - git_tmp("mv", "tests/test_cli.py", f"tests/test_{package}.py") # Change contents of all children known to git for relative_child in git_tmp("ls-files").splitlines(): child = Path(git_tmp.name) / relative_child if child.suffix in CHANGE_SUFFIXES and child.name not in IGNORE_FILES: - text = child.read_text() - start_search, end_search = IGNORE_RANGES.get(child.name, (None, None)) - if start_search: - start_ignore = text.find(start_search) - assert start_ignore > 0, f"{start_search} not in {child.name}" - if end_search: - end_ignore = text.find(end_search, start_ignore) + len( - end_search - ) - assert end_ignore > 0, f"{end_search} not in {child.name}" - else: - end_ignore = len(text) - else: - start_ignore = 0 - end_ignore = 0 - child.write_text( - replace_text(text[:start_ignore]) - + text[start_ignore:end_ignore] - + replace_text(text[end_ignore:]) - ) + text = replace_text(child.read_text()) + child.write_text(text) # Commit what we have and push to the original repo git_tmp("commit", "-a", "-m", f"Rename python3-pip-skeleton -> {repo}") git_tmp("push", "origin", MERGE_BRANCH) @@ -127,7 +104,7 @@ def replace_text(text: str) -> str: print(f" git branch -d {MERGE_BRANCH}") else: git("branch", "-d", MERGE_BRANCH, cwd=path) - print("Instructions on how to develop this module are in CONTRIBUTING.rst") + print("Developer instructions in docs/developer/tutorials/dev-install.rst") def validate_package(args) -> str: @@ -154,9 +131,12 @@ def verify_not_adopted(root: Path): ] ) - assert ( - not_adopted - ), f"Package {root} has already adopted skeleton. use --force to re-adopt" + assert not_adopted, ( + f"Package {root} has already adopted skeleton. You can type:\n" + f" git pull --rebase=false {SKELETON}\n" + "to update. If there were significant upstream changes a re-adopt may be " + "better. use the --force flag to the command you just ran." + ) def new(args): diff --git a/tests/test_adopt.py b/tests/test_adopt.py new file mode 100644 index 00000000..c9204358 --- /dev/null +++ b/tests/test_adopt.py @@ -0,0 +1,173 @@ +import subprocess +import sys +from configparser import ConfigParser +from os import makedirs +from pathlib import Path + +import pytest + +from python3_pip_skeleton import __main__, __version__ + + +def check_output(*args, cwd=None) -> str: + try: + return subprocess.check_output( + args, stderr=subprocess.STDOUT, text=True, cwd=cwd + ) + except subprocess.CalledProcessError as e: + raise ValueError(e.output) + + +def test_cli_version(): + output = check_output(sys.executable, "-m", "python3_pip_skeleton", "--version") + assert output.strip() == __version__ + + +def test_new_module(tmp_path: Path): + module = tmp_path / "my-module" + output = check_output( + sys.executable, + "-m", + "python3_pip_skeleton", + "new", + "--org=myorg", + "--package=my_module", + "--full-name=Firstname Lastname", + "--email=me@myaddress.com", + str(module), + ) + assert output.strip().endswith( + "Developer instructions in docs/developer/tutorials/dev-install.rst" + ) + + conf = ConfigParser() + conf.read(module / "setup.cfg") + assert conf["metadata"]["author"] == "Firstname Lastname" + assert conf["metadata"]["author_email"] == "me@myaddress.com" + api_rst = module / "docs" / "user" / "reference" / "api.rst" + assert ( + "Version number as calculated by https://github.com/pypa/setuptools_scm" + in api_rst.read_text() + ) + assert (module / "src" / "my_module").is_dir() + assert check_output("git", "branch", cwd=module).strip() == "* main" + check_output("python", "-m", "venv", "venv", cwd=module) + check_output("venv/bin/pip", "install", ".[dev]", cwd=module) + check_output( + "venv/bin/python", + "-m", + "sphinx", + "-EWT", + "--keep-going", + "docs", + "build/html", + cwd=module, + ) + with pytest.raises(ValueError) as ctx: + check_output("venv/bin/python", "-m", "pytest", module / "tests", cwd=module) + out = ctx.value.args[0] + print(out) + assert "4 failed, 1 passed" in out + assert "Please change description in ./setup.cfg" in out + assert "Please change ./README.rst" in out + + +def test_new_module_existing_dir(tmp_path: Path): + module = tmp_path / "my-module" + makedirs(module / "existing_dir") + + with pytest.raises(Exception) as excinfo: + check_output( + sys.executable, + "-m", + "python3_pip_skeleton", + "new", + "--org=myorg", + "--package=my_module", + "--full-name=Firstname Lastname", + "--email=me@myaddress.com", + str(module), + ) + assert "to not exist, or be an empty dir" in str(excinfo.value) + + +def test_existing_module(tmp_path: Path): + module = tmp_path / "scanspec" + __main__.git( + "clone", + "--depth", + "1", + "--branch", + "0.5.3", + "https://github.com/dls-controls/scanspec", + str(module), + ) + output = check_output( + sys.executable, + "-m", + "python3_pip_skeleton", + "existing", + "--org=epics-containers", + str(module), + ) + assert output.endswith( + """ +Automatic merge failed; fix conflicts and then commit the result. + +Please fix the conflicts above, then you can run: + git branch -d skeleton-merge-branch +Developer instructions in docs/developer/tutorials/dev-install.rst +""" + ) + __main__.git("merge", "--abort", cwd=str(module)) + MERGE_BRANCH = "skeleton-merge-branch" + + with pytest.raises(Exception) as excinfo: + output = check_output( + sys.executable, + "-m", + "python3_pip_skeleton", + "existing", + "--org=epics-containers", + str(module), + ) + assert ( + f"{MERGE_BRANCH} already exists. \ + Please run 'python3-pip-skeleton clean' to remove it." + in str(excinfo.value) + ) + + branches = __main__.list_branches(module) + assert MERGE_BRANCH in branches + output = check_output( + sys.executable, + "-m", + "python3_pip_skeleton", + "clean", + ".", + cwd=str(module), + ) + assert output.strip("\n") == f"{MERGE_BRANCH} deleted from existing repo" + branches = __main__.list_branches(module) + assert MERGE_BRANCH not in branches + + +def test_existing_module_already_adopted(tmp_path: Path): + module = tmp_path / "scanspec" + __main__.git( + "clone", + "--branch", + "0.5.4", # dls-python3-skeleton was adopted in this release + "https://github.com/dls-controls/scanspec", + str(module), + ) + with pytest.raises(Exception) as excinfo: + check_output( + sys.executable, + "-m", + "python3_pip_skeleton", + "existing", + "--org=epics-containers", + str(module), + ) + assert "already adopted skeleton" in str(excinfo.value)