hassle.hassle_utilities

  1import os
  2import shutil
  3from pathlib import Path
  4
  5import packagelister
  6import tomlkit
  7import vermin
  8
  9from hassle import hassle_config
 10
 11root = Path(__file__).parent
 12
 13
 14def increment_version(pyproject_path: Path, increment_type: str):
 15    """Increment the project.version field in pyproject.toml.
 16
 17    :param package_path: Path to the package/project directory.
 18
 19    :param increment_type: One from 'major', 'minor', or 'patch'."""
 20    meta = tomlkit.loads(pyproject_path.read_text())
 21    major, minor, patch = [int(num) for num in meta["project"]["version"].split(".")]
 22    if increment_type == "major":
 23        major += 1
 24        minor = 0
 25        patch = 0
 26    elif increment_type == "minor":
 27        minor += 1
 28        patch = 0
 29    elif increment_type == "patch":
 30        patch += 1
 31    incremented_version = ".".join(str(num) for num in [major, minor, patch])
 32    meta["project"]["version"] = incremented_version
 33    pyproject_path.write_text(tomlkit.dumps(meta))
 34
 35
 36def update_minimum_python_version(pyproject_path: Path):
 37    """Use vermin to determine the minimum compatible
 38    Python version and update the corresponding field
 39    in pyproject.toml."""
 40    project_code = "\n".join(
 41        file.read_text() for file in (pyproject_path.parent / "src").rglob("*.py")
 42    )
 43    meta = tomlkit.loads(pyproject_path.read_text())
 44    minimum_version = vermin.visit(project_code, vermin.Config()).minimum_versions()[1]
 45    minimum_version = f">={minimum_version[0]}.{minimum_version[1]}"
 46    meta["project"]["requires-python"] = minimum_version
 47    pyproject_path.write_text(tomlkit.dumps(meta))
 48
 49
 50def generate_docs(package_path: Path):
 51    """Generate project documentation using pdoc."""
 52    try:
 53        shutil.rmtree(package_path / "docs")
 54    except Exception as e:
 55        pass
 56    os.system(
 57        f"pdoc -o {package_path / 'docs'} {package_path / 'src' / package_path.stem}"
 58    )
 59
 60
 61def update_dependencies(
 62    pyproject_path: Path, overwrite: bool, include_versions: bool = False
 63):
 64    """Update dependencies list in pyproject.toml.
 65
 66    :param overwrite: If True, replace the dependencies in pyproject.toml
 67    with the results of packagelister.scan() .
 68    If False, packages returned by packagelister are appended to
 69    the current dependencies in pyproject.toml if they don't already
 70    exist in the field."""
 71    packages = packagelister.scan(pyproject_path.parent)
 72
 73    packages = [
 74        f"{package}~={packages[package]['version']}"
 75        if packages[package]["version"] and include_versions
 76        else f"{package}"
 77        for package in packages
 78        if package != pyproject_path.parent.stem
 79    ]
 80    packages = [
 81        package.replace("speech_recognition", "speechRecognition")
 82        for package in packages
 83    ]
 84    meta = tomlkit.loads(pyproject_path.read_text())
 85    if overwrite:
 86        meta["project"]["dependencies"] = packages
 87    else:
 88        for package in packages:
 89            if "~" in package:
 90                name = package.split("~")[0]
 91            elif "=" in package:
 92                name = package.split("=")[0]
 93            else:
 94                name = package
 95            if all(
 96                name not in dependency for dependency in meta["project"]["dependencies"]
 97            ):
 98                meta["project"]["dependencies"].append(package)
 99    pyproject_path.write_text(tomlkit.dumps(meta))
100
101
102def update_changelog(pyproject_path: Path):
103    """Update project changelog."""
104    meta = tomlkit.loads(pyproject_path.read_text())
105    if hassle_config.config_exists():
106        config = hassle_config.load_config()
107    else:
108        hassle_config.warn()
109        print("Creating blank hassle_config.toml...")
110        config = hassle_config.load_config()
111    changelog_path = pyproject_path.parent / "CHANGELOG.md"
112    os.system(
113        f"auto-changelog -p {pyproject_path.parent} --tag-prefix {config['git']['tag_prefix']} --unreleased -v {meta['project']['version']} -o {changelog_path}"
114    )
115    changelog = changelog_path.read_text().splitlines()
116    changelog = [line for line in changelog if "Full set of changes:" not in line]
117    changelog_path.write_text("\n".join(changelog))
118
119
120def tag_version(package_path: Path):
121    """Add a git tag corresponding
122    to the version number in pyproject.toml."""
123    if hassle_config.config_exists():
124        tag_prefix = hassle_config.load_config()["git"]["tag_prefix"]
125    else:
126        hassle_config.warn()
127        tag_prefix = ""
128    version = tomlkit.loads((package_path / "pyproject.toml").read_text())["project"][
129        "version"
130    ]
131    os.chdir(package_path)
132    os.system(f"git tag {tag_prefix}{version}")
def increment_version(pyproject_path: pathlib.Path, increment_type: str):
15def increment_version(pyproject_path: Path, increment_type: str):
16    """Increment the project.version field in pyproject.toml.
17
18    :param package_path: Path to the package/project directory.
19
20    :param increment_type: One from 'major', 'minor', or 'patch'."""
21    meta = tomlkit.loads(pyproject_path.read_text())
22    major, minor, patch = [int(num) for num in meta["project"]["version"].split(".")]
23    if increment_type == "major":
24        major += 1
25        minor = 0
26        patch = 0
27    elif increment_type == "minor":
28        minor += 1
29        patch = 0
30    elif increment_type == "patch":
31        patch += 1
32    incremented_version = ".".join(str(num) for num in [major, minor, patch])
33    meta["project"]["version"] = incremented_version
34    pyproject_path.write_text(tomlkit.dumps(meta))

Increment the project.version field in pyproject.toml.

Parameters
  • package_path: Path to the package/project directory.

  • increment_type: One from 'major', 'minor', or 'patch'.

def update_minimum_python_version(pyproject_path: pathlib.Path):
37def update_minimum_python_version(pyproject_path: Path):
38    """Use vermin to determine the minimum compatible
39    Python version and update the corresponding field
40    in pyproject.toml."""
41    project_code = "\n".join(
42        file.read_text() for file in (pyproject_path.parent / "src").rglob("*.py")
43    )
44    meta = tomlkit.loads(pyproject_path.read_text())
45    minimum_version = vermin.visit(project_code, vermin.Config()).minimum_versions()[1]
46    minimum_version = f">={minimum_version[0]}.{minimum_version[1]}"
47    meta["project"]["requires-python"] = minimum_version
48    pyproject_path.write_text(tomlkit.dumps(meta))

Use vermin to determine the minimum compatible Python version and update the corresponding field in pyproject.toml.

def generate_docs(package_path: pathlib.Path):
51def generate_docs(package_path: Path):
52    """Generate project documentation using pdoc."""
53    try:
54        shutil.rmtree(package_path / "docs")
55    except Exception as e:
56        pass
57    os.system(
58        f"pdoc -o {package_path / 'docs'} {package_path / 'src' / package_path.stem}"
59    )

Generate project documentation using pdoc.

def update_dependencies( pyproject_path: pathlib.Path, overwrite: bool, include_versions: bool = False):
 62def update_dependencies(
 63    pyproject_path: Path, overwrite: bool, include_versions: bool = False
 64):
 65    """Update dependencies list in pyproject.toml.
 66
 67    :param overwrite: If True, replace the dependencies in pyproject.toml
 68    with the results of packagelister.scan() .
 69    If False, packages returned by packagelister are appended to
 70    the current dependencies in pyproject.toml if they don't already
 71    exist in the field."""
 72    packages = packagelister.scan(pyproject_path.parent)
 73
 74    packages = [
 75        f"{package}~={packages[package]['version']}"
 76        if packages[package]["version"] and include_versions
 77        else f"{package}"
 78        for package in packages
 79        if package != pyproject_path.parent.stem
 80    ]
 81    packages = [
 82        package.replace("speech_recognition", "speechRecognition")
 83        for package in packages
 84    ]
 85    meta = tomlkit.loads(pyproject_path.read_text())
 86    if overwrite:
 87        meta["project"]["dependencies"] = packages
 88    else:
 89        for package in packages:
 90            if "~" in package:
 91                name = package.split("~")[0]
 92            elif "=" in package:
 93                name = package.split("=")[0]
 94            else:
 95                name = package
 96            if all(
 97                name not in dependency for dependency in meta["project"]["dependencies"]
 98            ):
 99                meta["project"]["dependencies"].append(package)
100    pyproject_path.write_text(tomlkit.dumps(meta))

Update dependencies list in pyproject.toml.

Parameters
  • overwrite: If True, replace the dependencies in pyproject.toml with the results of packagelister.scan() . If False, packages returned by packagelister are appended to the current dependencies in pyproject.toml if they don't already exist in the field.
def update_changelog(pyproject_path: pathlib.Path):
103def update_changelog(pyproject_path: Path):
104    """Update project changelog."""
105    meta = tomlkit.loads(pyproject_path.read_text())
106    if hassle_config.config_exists():
107        config = hassle_config.load_config()
108    else:
109        hassle_config.warn()
110        print("Creating blank hassle_config.toml...")
111        config = hassle_config.load_config()
112    changelog_path = pyproject_path.parent / "CHANGELOG.md"
113    os.system(
114        f"auto-changelog -p {pyproject_path.parent} --tag-prefix {config['git']['tag_prefix']} --unreleased -v {meta['project']['version']} -o {changelog_path}"
115    )
116    changelog = changelog_path.read_text().splitlines()
117    changelog = [line for line in changelog if "Full set of changes:" not in line]
118    changelog_path.write_text("\n".join(changelog))

Update project changelog.

def tag_version(package_path: pathlib.Path):
121def tag_version(package_path: Path):
122    """Add a git tag corresponding
123    to the version number in pyproject.toml."""
124    if hassle_config.config_exists():
125        tag_prefix = hassle_config.load_config()["git"]["tag_prefix"]
126    else:
127        hassle_config.warn()
128        tag_prefix = ""
129    version = tomlkit.loads((package_path / "pyproject.toml").read_text())["project"][
130        "version"
131    ]
132    os.chdir(package_path)
133    os.system(f"git tag {tag_prefix}{version}")

Add a git tag corresponding to the version number in pyproject.toml.