hassle.hassle_utilities

  1import os
  2import shutil
  3from pathlib import Path
  4
  5import tomlkit
  6import vermin
  7
  8import packagelister
  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(pyproject_path: Path, overwrite: bool):
 62    """Update dependencies list in pyproject.toml.
 63
 64    :param overwrite: If True, replace the dependencies in pyproject.toml
 65    with the results of packagelister.scan() .
 66    If False, packages returned by packagelister are appended to
 67    the current dependencies in pyproject.toml if they don't already
 68    exist in the field."""
 69    packages = packagelister.scan(pyproject_path.parent)
 70
 71    packages = [
 72        f"{package}~={packages[package]['version']}"
 73        if packages[package]["version"]
 74        else f"{package}"
 75        for package in packages
 76        if package != pyproject_path.parent.stem
 77    ]
 78    packages = [
 79        package.replace("speech_recognition", "speechRecognition")
 80        for package in packages
 81    ]
 82    meta = tomlkit.loads(pyproject_path.read_text())
 83    if overwrite:
 84        meta["project"]["dependencies"] = packages
 85    else:
 86        for package in packages:
 87            if "~" in package:
 88                name = package.split("~")[0]
 89            elif "=" in package:
 90                name = package.split("=")[0]
 91            else:
 92                name = package
 93            if all(
 94                name not in dependency for dependency in meta["project"]["dependencies"]
 95            ):
 96                meta["project"]["dependencies"].append(package)
 97    pyproject_path.write_text(tomlkit.dumps(meta))
 98
 99
100def update_changelog(pyproject_path: Path):
101    """Update project changelog."""
102    meta = tomlkit.loads(pyproject_path.read_text())
103    if hassle_config.config_exists():
104        config = hassle_config.load_config()
105    else:
106        hassle_config.warn()
107        print("Creating blank hassle_config.toml...")
108        config = hassle_config.load_config()
109    changelog_path = pyproject_path.parent / "CHANGELOG.md"
110    os.system(
111        f"auto-changelog -p {pyproject_path.parent} --tag-prefix {config['git']['tag_prefix']} --unreleased -v {meta['project']['version']} -o {changelog_path}"
112    )
113    changelog = changelog_path.read_text().splitlines()
114    changelog = [line for line in changelog if "Full set of changes:" not in line]
115    changelog_path.write_text("\n".join(changelog))
116
117
118def tag_version(package_path: Path):
119    """Add a git tag corresponding
120    to the version number in pyproject.toml."""
121    if hassle_config.config_exists():
122        tag_prefix = hassle_config.load_config()["git"]["tag_prefix"]
123    else:
124        hassle_config.warn()
125        tag_prefix = ""
126    version = tomlkit.loads((package_path / "pyproject.toml").read_text())["project"][
127        "version"
128    ]
129    os.chdir(package_path)
130    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):
62def update_dependencies(pyproject_path: Path, overwrite: bool):
63    """Update dependencies list in pyproject.toml.
64
65    :param overwrite: If True, replace the dependencies in pyproject.toml
66    with the results of packagelister.scan() .
67    If False, packages returned by packagelister are appended to
68    the current dependencies in pyproject.toml if they don't already
69    exist in the field."""
70    packages = packagelister.scan(pyproject_path.parent)
71
72    packages = [
73        f"{package}~={packages[package]['version']}"
74        if packages[package]["version"]
75        else f"{package}"
76        for package in packages
77        if package != pyproject_path.parent.stem
78    ]
79    packages = [
80        package.replace("speech_recognition", "speechRecognition")
81        for package in packages
82    ]
83    meta = tomlkit.loads(pyproject_path.read_text())
84    if overwrite:
85        meta["project"]["dependencies"] = packages
86    else:
87        for package in packages:
88            if "~" in package:
89                name = package.split("~")[0]
90            elif "=" in package:
91                name = package.split("=")[0]
92            else:
93                name = package
94            if all(
95                name not in dependency for dependency in meta["project"]["dependencies"]
96            ):
97                meta["project"]["dependencies"].append(package)
98    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):
101def update_changelog(pyproject_path: Path):
102    """Update project changelog."""
103    meta = tomlkit.loads(pyproject_path.read_text())
104    if hassle_config.config_exists():
105        config = hassle_config.load_config()
106    else:
107        hassle_config.warn()
108        print("Creating blank hassle_config.toml...")
109        config = hassle_config.load_config()
110    changelog_path = pyproject_path.parent / "CHANGELOG.md"
111    os.system(
112        f"auto-changelog -p {pyproject_path.parent} --tag-prefix {config['git']['tag_prefix']} --unreleased -v {meta['project']['version']} -o {changelog_path}"
113    )
114    changelog = changelog_path.read_text().splitlines()
115    changelog = [line for line in changelog if "Full set of changes:" not in line]
116    changelog_path.write_text("\n".join(changelog))

Update project changelog.

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

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