hassle.hassle_utilities
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):
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:
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:
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):
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):
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):
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):
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):
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):
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).