def make_recipe(out_dir: str = "./conda/"): """ Make a Conda ``meta.yaml`` recipe. """ # stdlib import warnings # 3rd party from consolekit.terminal_colours import Fore, resolve_color_default from domdf_python_tools.paths import PathPlus, traverse_to_file # this package from repo_helper import conda warnings.warn( "'repo-helper make-recipe' is deprecated. " "Please use 'mkrecipe' instead: https://mkrecipe.readthedocs.io/", DeprecationWarning, ) repo_dir = traverse_to_file(PathPlus.cwd(), "repo_helper.yml") recipe_file = PathPlus(out_dir).resolve() / "meta.yaml" recipe_file.parent.maybe_make() conda.make_recipe(repo_dir, recipe_file) click.echo(Fore.GREEN(f"Wrote recipe to {recipe_file!s}"), color=resolve_color_default())
def requirement(requirement: str, file: Optional[str] = None) -> int: """ Add a requirement. """ # 3rd party from consolekit.utils import abort from domdf_python_tools.paths import PathPlus, traverse_to_file from domdf_python_tools.stringlist import StringList from packaging.requirements import InvalidRequirement from packaging.specifiers import SpecifierSet from shippinglabel import normalize_keep_dot from shippinglabel.requirements import ComparableRequirement, combine_requirements, read_requirements repo_dir: PathPlus = traverse_to_file(PathPlus.cwd(), "repo_helper.yml", "git_helper.yml") if file is None: requirements_file = repo_dir / "requirements.txt" if not requirements_file.is_file(): raise abort(f"'{file}' not found.") else: requirements_file = PathPlus(file) if not requirements_file.is_file(): raise abort("'requirements.txt' not found.") try: req = ComparableRequirement(requirement) except InvalidRequirement as e: raise BadRequirement(requirement, e) response = (PYPI_API / req.name / "json/").get() if response.status_code != 200: raise click.BadParameter(f"No such project {req.name}") else: req.name = normalize(response.json()["info"]["name"]) if not req.specifier: req.specifier = SpecifierSet( f">={response.json()['info']['version']}") click.echo(f"Adding requirement '{req}'") requirements, comments, invalid_lines = read_requirements( req_file=requirements_file, include_invalid=True, normalize_func=normalize_keep_dot, ) requirements.add(req) buf = StringList([*comments, *invalid_lines]) buf.extend(str(req) for req in sorted(combine_requirements(requirements))) requirements_file.write_lines(buf) return 0
def determine_project_dir(project_dir: PathLike) -> PathPlus: """ Determine the project base directory. Subclasses may override this method to customise the behaviour. :param project_dir: """ return traverse_to_file(PathPlus(project_dir), "pyproject.toml")
def __init__(self, repo_path: PathPlus, force: bool = False): #: self.repo = RepoHelper(traverse_to_file(PathPlus(repo_path), "repo_helper.yml")) self.repo.load_settings() if not assert_clean(self.repo.target_repo): if force: click.echo(Fore.RED("Proceeding anyway"), err=True) else: raise click.Abort # pypi_secure_key = "travis_pypi_secure" # if self.repo.templates.globals["on_pypi"] and not self.repo.templates.globals[pypi_secure_key]: # raise abort(f"Cowardly refusing to bump the version when {pypi_secure_key!r} is unset.") # TODO: Handle this wrt github actions #: self.current_version = self.get_current_version() #: The path to the bumpversion configuration file. self.bumpversion_file = self.repo.target_repo / ".bumpversion.cfg"
def __init__( self, target_repo: PathLike, managed_message="This file is managed by 'repo_helper'. Don't edit it directly." ): import_registered_functions() # Walk up the tree until a "repo_helper.yml" or "git_helper.yml" (old name) file is found. self.target_repo = traverse_to_file(PathPlus(target_repo), "repo_helper.yml", "git_helper.yml") self.templates = Environment( # nosec: B701 loader=jinja2.FileSystemLoader(str(template_dir)), undefined=jinja2.StrictUndefined, ) self.templates.globals["managed_message"] = managed_message self.templates.globals["brace"] = brace # isort and formate.toml must always run last self.files = management + [(make_isort, "isort", [])] self.files = management + [(make_formate_toml, "formate", [])]
def test_traverse_to_file_errors(tmp_pathplus: PathPlus): (tmp_pathplus / "foo/bar/baz").parent.maybe_make(parents=True) if os.sep == '/': with pytest.raises(FileNotFoundError, match="'foo.yml' not found in .*/foo/bar/baz"): traverse_to_file(tmp_pathplus / "foo" / "bar" / "baz", "foo.yml") elif os.sep == '\\': with pytest.raises(FileNotFoundError, match=r"'foo.yml' not found in .*\\foo\\bar\\baz"): traverse_to_file(tmp_pathplus / "foo" / "bar" / "baz", "foo.yml") else: raise NotImplementedError with pytest.raises( TypeError, match="traverse_to_file expected 2 or more arguments, got 1"): traverse_to_file(tmp_pathplus)
def test_traverse_to_file(tmp_pathplus: PathPlus, location: str, expected: str): (tmp_pathplus / location).parent.maybe_make(parents=True) (tmp_pathplus / location).touch() assert traverse_to_file(tmp_pathplus / "foo" / "bar" / "baz", "foo.yml") == tmp_pathplus / expected