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