hassle.hassle_utilities API documentation

# hassle.hassle_utilities

View Source

      1import os
      2
      3import black
      4import packagelister
      5import vermin
      6from gitbetter import git
      7from pathier import Pathier
      8
      9from hassle import hassle_config
     10
     11root = Pathier(__file__).parent
     12
     13
     14def increment_version(pyproject_path: Pathier, 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 = pyproject_path.loads()
     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.dumps(meta)
     34
     35
     36def get_minimum_py_version(src: str) -> str:
     37    """Scan src with vermin and return minimum
     38    python version."""
     39    config = vermin.Config()
     40    config.add_backport("typing")
     41    config.add_backport("typing_extensions")
     42    config.set_eval_annotations(True)
     43    result = vermin.visit(src, config).minimum_versions()[1]
     44    return f"{result[0]}.{result[1]}"
     45
     46
     47def get_project_code(project_path: Pathier) -> str:
     48    """Read and return all code from project_path
     49    as one string."""
     50    return "\n".join(file.read_text() for file in project_path.rglob("*.py"))
     51
     52
     53def update_minimum_python_version(pyproject_path: Pathier):
     54    """Use vermin to determine the minimum compatible
     55    Python version and update the corresponding field
     56    in pyproject.toml."""
     57    project_code = get_project_code(pyproject_path.parent / "src")
     58    meta = pyproject_path.loads()
     59    minimum_version = get_minimum_py_version(project_code)
     60    minimum_version = f">={minimum_version}"
     61    meta["project"]["requires-python"] = minimum_version
     62    pyproject_path.dumps(meta)
     63
     64
     65def generate_docs(package_path: Pathier):
     66    """Generate project documentation using pdoc."""
     67    try:
     68        (package_path / "docs").delete()
     69    except Exception as e:
     70        pass
     71    os.system(
     72        f"pdoc -o {package_path / 'docs'} {package_path / 'src' / package_path.stem}"
     73    )
     74
     75
     76def update_dependencies(
     77    pyproject_path: Pathier, overwrite: bool, include_versions: bool = False
     78):
     79    """Update dependencies list in pyproject.toml.
     80
     81    :param overwrite: If True, replace the dependencies in pyproject.toml
     82    with the results of packagelister.scan() .
     83    If False, packages returned by packagelister are appended to
     84    the current dependencies in pyproject.toml if they don't already
     85    exist in the field."""
     86    packages = packagelister.scan(pyproject_path.parent)
     87
     88    packages = [
     89        f"{package}~={packages[package]['version']}"
     90        if packages[package]["version"] and include_versions
     91        else f"{package}"
     92        for package in packages
     93        if package != pyproject_path.parent.stem
     94    ]
     95    packages = [
     96        package.replace("speech_recognition", "speechRecognition")
     97        for package in packages
     98    ]
     99    meta = pyproject_path.loads()
    100    if overwrite:
    101        meta["project"]["dependencies"] = packages
    102    else:
    103        for package in packages:
    104            if "~" in package:
    105                name = package.split("~")[0]
    106            elif "=" in package:
    107                name = package.split("=")[0]
    108            else:
    109                name = package
    110            if all(
    111                name not in dependency for dependency in meta["project"]["dependencies"]
    112            ):
    113                meta["project"]["dependencies"].append(package)
    114    pyproject_path.dumps(meta)
    115
    116
    117def update_changelog(pyproject_path: Pathier):
    118    """Update project changelog."""
    119    meta = pyproject_path.loads()
    120    if hassle_config.config_exists():
    121        config = hassle_config.load_config()
    122    else:
    123        hassle_config.warn()
    124        print("Creating blank hassle_config.toml...")
    125        config = hassle_config.load_config()
    126    changelog_path = pyproject_path.parent / "CHANGELOG.md"
    127    os.system(
    128        f"auto-changelog -p {pyproject_path.parent} --tag-prefix {config['git']['tag_prefix']} --unreleased -v {meta['project']['version']} -o {changelog_path}"
    129    )
    130    changelog = changelog_path.read_text().splitlines()
    131    changelog = [line for line in changelog if "Full set of changes:" not in line]
    132    changelog_path.write_text("\n".join(changelog))
    133
    134
    135def tag_version(package_path: Pathier):
    136    """Add a git tag corresponding
    137    to the version number in pyproject.toml."""
    138    if hassle_config.config_exists():
    139        tag_prefix = hassle_config.load_config()["git"]["tag_prefix"]
    140    else:
    141        hassle_config.warn()
    142        tag_prefix = ""
    143    version = (package_path / "pyproject.toml").loads()["project"]["version"]
    144    os.chdir(package_path)
    145    git.tag(f"{tag_prefix}{version}")
    146
    147
    148def format_files(path: Pathier):
    149    """Use `Black` to format file(s)."""
    150    try:
    151        black.main([str(path)])
    152    except SystemExit:
    153        ...

def increment_version(pyproject_path: pathier.pathier.Pathier, increment_type: str): View Source

    15def increment_version(pyproject_path: Pathier, 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 = pyproject_path.loads()
    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.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 get_minimum_py_version(src: str) -> str: View Source

    37def get_minimum_py_version(src: str) -> str:
    38    """Scan src with vermin and return minimum
    39    python version."""
    40    config = vermin.Config()
    41    config.add_backport("typing")
    42    config.add_backport("typing_extensions")
    43    config.set_eval_annotations(True)
    44    result = vermin.visit(src, config).minimum_versions()[1]
    45    return f"{result[0]}.{result[1]}"

Scan src with vermin and return minimum python version.

def get_project_code(project_path: pathier.pathier.Pathier) -> str: View Source

    48def get_project_code(project_path: Pathier) -> str:
    49    """Read and return all code from project_path
    50    as one string."""
    51    return "\n".join(file.read_text() for file in project_path.rglob("*.py"))

Read and return all code from project_path as one string.

def update_minimum_python_version(pyproject_path: pathier.pathier.Pathier): View Source

    54def update_minimum_python_version(pyproject_path: Pathier):
    55    """Use vermin to determine the minimum compatible
    56    Python version and update the corresponding field
    57    in pyproject.toml."""
    58    project_code = get_project_code(pyproject_path.parent / "src")
    59    meta = pyproject_path.loads()
    60    minimum_version = get_minimum_py_version(project_code)
    61    minimum_version = f">={minimum_version}"
    62    meta["project"]["requires-python"] = minimum_version
    63    pyproject_path.dumps(meta)

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

def generate_docs(package_path: pathier.pathier.Pathier): View Source

    66def generate_docs(package_path: Pathier):
    67    """Generate project documentation using pdoc."""
    68    try:
    69        (package_path / "docs").delete()
    70    except Exception as e:
    71        pass
    72    os.system(
    73        f"pdoc -o {package_path / 'docs'} {package_path / 'src' / package_path.stem}"
    74    )

Generate project documentation using pdoc.

def update_dependencies( pyproject_path: pathier.pathier.Pathier, overwrite: bool, include_versions: bool = False): View Source

     77def update_dependencies(
     78    pyproject_path: Pathier, overwrite: bool, include_versions: bool = False
     79):
     80    """Update dependencies list in pyproject.toml.
     81
     82    :param overwrite: If True, replace the dependencies in pyproject.toml
     83    with the results of packagelister.scan() .
     84    If False, packages returned by packagelister are appended to
     85    the current dependencies in pyproject.toml if they don't already
     86    exist in the field."""
     87    packages = packagelister.scan(pyproject_path.parent)
     88
     89    packages = [
     90        f"{package}~={packages[package]['version']}"
     91        if packages[package]["version"] and include_versions
     92        else f"{package}"
     93        for package in packages
     94        if package != pyproject_path.parent.stem
     95    ]
     96    packages = [
     97        package.replace("speech_recognition", "speechRecognition")
     98        for package in packages
     99    ]
    100    meta = pyproject_path.loads()
    101    if overwrite:
    102        meta["project"]["dependencies"] = packages
    103    else:
    104        for package in packages:
    105            if "~" in package:
    106                name = package.split("~")[0]
    107            elif "=" in package:
    108                name = package.split("=")[0]
    109            else:
    110                name = package
    111            if all(
    112                name not in dependency for dependency in meta["project"]["dependencies"]
    113            ):
    114                meta["project"]["dependencies"].append(package)
    115    pyproject_path.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: pathier.pathier.Pathier): View Source

    118def update_changelog(pyproject_path: Pathier):
    119    """Update project changelog."""
    120    meta = pyproject_path.loads()
    121    if hassle_config.config_exists():
    122        config = hassle_config.load_config()
    123    else:
    124        hassle_config.warn()
    125        print("Creating blank hassle_config.toml...")
    126        config = hassle_config.load_config()
    127    changelog_path = pyproject_path.parent / "CHANGELOG.md"
    128    os.system(
    129        f"auto-changelog -p {pyproject_path.parent} --tag-prefix {config['git']['tag_prefix']} --unreleased -v {meta['project']['version']} -o {changelog_path}"
    130    )
    131    changelog = changelog_path.read_text().splitlines()
    132    changelog = [line for line in changelog if "Full set of changes:" not in line]
    133    changelog_path.write_text("\n".join(changelog))

Update project changelog.

def tag_version(package_path: pathier.pathier.Pathier): View Source

    136def tag_version(package_path: Pathier):
    137    """Add a git tag corresponding
    138    to the version number in pyproject.toml."""
    139    if hassle_config.config_exists():
    140        tag_prefix = hassle_config.load_config()["git"]["tag_prefix"]
    141    else:
    142        hassle_config.warn()
    143        tag_prefix = ""
    144    version = (package_path / "pyproject.toml").loads()["project"]["version"]
    145    os.chdir(package_path)
    146    git.tag(f"{tag_prefix}{version}")

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

def format_files(path: pathier.pathier.Pathier): View Source

    149def format_files(path: Pathier):
    150    """Use `Black` to format file(s)."""
    151    try:
    152        black.main([str(path)])
    153    except SystemExit:
    154        ...

Use `Black` to format file(s).