style(dependencies): run ruff formatter

This commit is contained in:
Carlo Sala 2024-05-09 17:20:09 +02:00
parent 83110e8ce1
commit 13c8a10e39
2 changed files with 378 additions and 329 deletions

View File

@ -6,3 +6,6 @@ insert_final_newline = true
charset = utf-8 charset = utf-8
indent_size = 2 indent_size = 2
indent_style = space indent_style = space
[*.py]
indent_size = 4

View File

@ -1,12 +1,14 @@
import os import os
import shutil
import subprocess import subprocess
import sys import sys
import requests import timeit
import shutil
import yaml
from copy import deepcopy from copy import deepcopy
from typing import Optional, TypedDict from typing import Optional, TypedDict
import requests
import yaml
# Get TMP_DIR variable from environment # Get TMP_DIR variable from environment
TMP_DIR = os.path.join(os.environ.get("TMP_DIR", "/tmp"), "ohmyzsh") TMP_DIR = os.path.join(os.environ.get("TMP_DIR", "/tmp"), "ohmyzsh")
# Relative path to dependencies.yml file # Relative path to dependencies.yml file
@ -14,17 +16,17 @@ DEPS_YAML_FILE = ".github/dependencies.yml"
# Dry run flag # Dry run flag
DRY_RUN = os.environ.get("DRY_RUN", "0") == "1" DRY_RUN = os.environ.get("DRY_RUN", "0") == "1"
import timeit
class CodeTimer: class CodeTimer:
def __init__(self, name=None): def __init__(self, name=None):
self.name = " '" + name + "'" if name else '' self.name = " '" + name + "'" if name else ""
def __enter__(self): def __enter__(self):
self.start = timeit.default_timer() self.start = timeit.default_timer()
def __exit__(self, exc_type, exc_value, traceback): def __exit__(self, exc_type, exc_value, traceback):
self.took = (timeit.default_timer() - self.start) * 1000.0 self.took = (timeit.default_timer() - self.start) * 1000.0
print('Code block' + self.name + ' took: ' + str(self.took) + ' ms') print("Code block" + self.name + " took: " + str(self.took) + " ms")
### YAML representation ### YAML representation
@ -34,8 +36,9 @@ def str_presenter(dumper, data):
Ref: https://stackoverflow.com/a/33300001 Ref: https://stackoverflow.com/a/33300001
""" """
if len(data.splitlines()) > 1: # check for multiline string if len(data.splitlines()) > 1: # check for multiline string
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|') return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|")
return dumper.represent_scalar('tag:yaml.org,2002:str', data) return dumper.represent_scalar("tag:yaml.org,2002:str", data)
yaml.add_representer(str, str_presenter) yaml.add_representer(str, str_presenter)
yaml.representer.SafeRepresenter.add_representer(str, str_presenter) yaml.representer.SafeRepresenter.add_representer(str, str_presenter)
@ -49,9 +52,11 @@ class DependencyDict(TypedDict):
precopy: Optional[str] precopy: Optional[str]
postcopy: Optional[str] postcopy: Optional[str]
class DependencyYAML(TypedDict): class DependencyYAML(TypedDict):
dependencies: dict[str, DependencyDict] dependencies: dict[str, DependencyDict]
class UpdateStatus(TypedDict): class UpdateStatus(TypedDict):
has_updates: bool has_updates: bool
version: Optional[str] version: Optional[str]
@ -78,19 +83,18 @@ class CommandRunner:
if result.returncode != 0: if result.returncode != 0:
raise CommandRunner.Exception( raise CommandRunner.Exception(
f"{stage} command failed with exit code {result.returncode}", returncode=result.returncode, f"{stage} command failed with exit code {result.returncode}",
returncode=result.returncode,
stage=stage, stage=stage,
stdout=result.stdout.decode("utf-8"), stdout=result.stdout.decode("utf-8"),
stderr=result.stderr.decode("utf-8") stderr=result.stderr.decode("utf-8"),
) )
return result return result
class DependencyStore: class DependencyStore:
store: DependencyYAML = { store: DependencyYAML = {"dependencies": {}}
"dependencies": {}
}
@staticmethod @staticmethod
def set(data: DependencyYAML): def set(data: DependencyYAML):
@ -136,7 +140,7 @@ class Dependency:
def __str__(self): def __str__(self):
output: str = "" output: str = ""
for key in DependencyDict.__dict__['__annotations__'].keys(): for key in DependencyDict.__dict__["__annotations__"].keys():
if key not in self.values: if key not in self.values:
output += f"{key}: None\n" output += f"{key}: None\n"
continue continue
@ -176,7 +180,9 @@ class Dependency:
branch = Git.create_branch(self.path, new_version) branch = Git.create_branch(self.path, new_version)
# Update dependencies.yml file # Update dependencies.yml file
self.__update_yaml(f"tag:{new_version}" if is_tag else status["version"]) self.__update_yaml(
f"tag:{new_version}" if is_tag else status["version"]
)
# Update dependency files # Update dependency files
self.__apply_upstream_changes() self.__apply_upstream_changes()
@ -195,7 +201,7 @@ class Dependency:
Update for **{self.desc}**: update to version [{new_version}]({status['head_url']}). Update for **{self.desc}**: update to version [{new_version}]({status['head_url']}).
Check out the [list of changes]({status['compare_url']}). Check out the [list of changes]({status['compare_url']}).
""" """,
) )
# Clean up repository # Clean up repository
@ -205,7 +211,10 @@ Check out the [list of changes]({status['compare_url']}).
match type(e): match type(e):
case CommandRunner.Exception: case CommandRunner.Exception:
# Print error message # Print error message
print(f"Error running {e.stage} command: {e.returncode}", file=sys.stderr) print(
f"Error running {e.stage} command: {e.returncode}",
file=sys.stderr,
)
print(e.stderr, file=sys.stderr) print(e.stderr, file=sys.stderr)
case shutil.Error: case shutil.Error:
print(f"Error copying files: {e}", file=sys.stderr) print(f"Error copying files: {e}", file=sys.stderr)
@ -213,22 +222,23 @@ Check out the [list of changes]({status['compare_url']}).
try: try:
Git.clean_repo() Git.clean_repo()
except CommandRunner.Exception as e: except CommandRunner.Exception as e:
print(f"Error reverting repository to clean state: {e}", file=sys.stderr) print(
f"Error reverting repository to clean state: {e}",
file=sys.stderr,
)
sys.exit(1) sys.exit(1)
# Create a GitHub issue to notify maintainer # Create a GitHub issue to notify maintainer
title = f"{self.path}: update to {new_version}" title = f"{self.path}: update to {new_version}"
body = ( body = f"""## Description
f"""## Description
There is a new version of `{self.name}` {self.kind} available. There is a new version of `{self.name}` {self.kind} available.
New version: [{new_version}]({status['head_url']}) New version: [{new_version}]({status['head_url']})
Check out the [list of changes]({status['compare_url']}). Check out the [list of changes]({status['compare_url']}).
""" """
)
print(f"Creating GitHub issue", file=sys.stderr) print("Creating GitHub issue", file=sys.stderr)
print(f"{title}\n\n{body}", file=sys.stderr) print(f"{title}\n\n{body}", file=sys.stderr)
GitHub.create_issue(title, body) GitHub.create_issue(title, body)
except Exception as e: except Exception as e:
@ -240,11 +250,7 @@ Check out the [list of changes]({status['compare_url']}).
def __apply_upstream_changes(self) -> None: def __apply_upstream_changes(self) -> None:
# Patterns to ignore in copying files from upstream repo # Patterns to ignore in copying files from upstream repo
GLOBAL_IGNORE = [ GLOBAL_IGNORE = [".git", ".github", ".gitignore"]
".git",
".github",
".gitignore"
]
path = os.path.abspath(self.path) path = os.path.abspath(self.path)
precopy = self.values.get("precopy") precopy = self.values.get("precopy")
@ -261,18 +267,32 @@ Check out the [list of changes]({status['compare_url']}).
# Run precopy on tmp repo # Run precopy on tmp repo
if precopy is not None: if precopy is not None:
print("Running precopy script:", end="\n ", file=sys.stderr) print("Running precopy script:", end="\n ", file=sys.stderr)
print(precopy.replace("\n", "\n ", precopy.count("\n") - 1), file=sys.stderr) print(
CommandRunner.run_or_fail(["bash", "-c", precopy], cwd=repo_dir, stage="Precopy") precopy.replace("\n", "\n ", precopy.count("\n") - 1), file=sys.stderr
)
CommandRunner.run_or_fail(
["bash", "-c", precopy], cwd=repo_dir, stage="Precopy"
)
# Copy files from upstream repo # Copy files from upstream repo
print(f"Copying files from {repo_dir} to {path}", file=sys.stderr) print(f"Copying files from {repo_dir} to {path}", file=sys.stderr)
shutil.copytree(repo_dir, path, dirs_exist_ok=True, ignore=shutil.ignore_patterns(*GLOBAL_IGNORE)) shutil.copytree(
repo_dir,
path,
dirs_exist_ok=True,
ignore=shutil.ignore_patterns(*GLOBAL_IGNORE),
)
# Run postcopy on our repository # Run postcopy on our repository
if postcopy is not None: if postcopy is not None:
print("Running postcopy script:", end="\n ", file=sys.stderr) print("Running postcopy script:", end="\n ", file=sys.stderr)
print(postcopy.replace("\n", "\n ", postcopy.count("\n") - 1), file=sys.stderr) print(
CommandRunner.run_or_fail(["bash", "-c", postcopy], cwd=path, stage="Postcopy") postcopy.replace("\n", "\n ", postcopy.count("\n") - 1),
file=sys.stderr,
)
CommandRunner.run_or_fail(
["bash", "-c", postcopy], cwd=path, stage="Postcopy"
)
class Git: class Git:
@ -286,18 +306,28 @@ class Git:
# Clone repo in tmp directory and checkout branch # Clone repo in tmp directory and checkout branch
if not os.path.exists(repo_dir): if not os.path.exists(repo_dir):
print(f"Cloning {remote_url} to {repo_dir} and checking out {branch}", file=sys.stderr) print(
CommandRunner.run_or_fail(["git", "clone", "--depth=1", "-b", branch, remote_url, repo_dir], stage="Clone") f"Cloning {remote_url} to {repo_dir} and checking out {branch}",
file=sys.stderr,
)
CommandRunner.run_or_fail(
["git", "clone", "--depth=1", "-b", branch, remote_url, repo_dir],
stage="Clone",
)
@staticmethod @staticmethod
def create_branch(path: str, version: str): def create_branch(path: str, version: str):
# Get current branch name # Get current branch name
result = CommandRunner.run_or_fail(["git", "rev-parse", "--abbrev-ref", "HEAD"], stage="GetDefaultBranch") result = CommandRunner.run_or_fail(
["git", "rev-parse", "--abbrev-ref", "HEAD"], stage="GetDefaultBranch"
)
Git.default_branch = result.stdout.decode("utf-8").strip() Git.default_branch = result.stdout.decode("utf-8").strip()
# Create new branch and return created branch name # Create new branch and return created branch name
branch_name = f"update/{path}/{version}" branch_name = f"update/{path}/{version}"
CommandRunner.run_or_fail(["git", "checkout", "-b", branch_name], stage="CreateBranch") CommandRunner.run_or_fail(
["git", "checkout", "-b", branch_name], stage="CreateBranch"
)
return branch_name return branch_name
@staticmethod @staticmethod
@ -310,27 +340,40 @@ class Git:
# Reset environment and git config # Reset environment and git config
clean_env = os.environ.copy() clean_env = os.environ.copy()
clean_env["LANG"]="C.UTF-8" clean_env["LANG"] = "C.UTF-8"
clean_env["GIT_CONFIG_GLOBAL"]="/dev/null" clean_env["GIT_CONFIG_GLOBAL"] = "/dev/null"
clean_env["GIT_CONFIG_NOSYSTEM"]="1" clean_env["GIT_CONFIG_NOSYSTEM"] = "1"
# Commit with settings above # Commit with settings above
CommandRunner.run_or_fail([ CommandRunner.run_or_fail(
[
"git", "git",
"-c", f"user.name={user_name}", "-c",
"-c", f"user.email={user_email}", f"user.name={user_name}",
"-c",
f"user.email={user_email}",
"commit", "commit",
"-m", f"feat({scope}): update to {version}" "-m",
], stage="CreateCommit", env=clean_env) f"feat({scope}): update to {version}",
],
stage="CreateCommit",
env=clean_env,
)
@staticmethod @staticmethod
def push(branch: str): def push(branch: str):
CommandRunner.run_or_fail(["git", "push", "-u", "origin", branch], stage="PushBranch") CommandRunner.run_or_fail(
["git", "push", "-u", "origin", branch], stage="PushBranch"
)
@staticmethod @staticmethod
def clean_repo(): def clean_repo():
CommandRunner.run_or_fail(["git", "reset", "--hard", "HEAD"], stage="ResetRepository") CommandRunner.run_or_fail(
CommandRunner.run_or_fail(["git", "checkout", Git.default_branch], stage="CheckoutDefaultBranch") ["git", "reset", "--hard", "HEAD"], stage="ResetRepository"
)
CommandRunner.run_or_fail(
["git", "checkout", Git.default_branch], stage="CheckoutDefaultBranch"
)
class GitHub: class GitHub:
@ -369,7 +412,9 @@ class GitHub:
} }
else: else:
# If the request was not successful, raise an exception # If the request was not successful, raise an exception
raise Exception(f"GitHub API request failed with status code {response.status_code}: {response.json()}") raise Exception(
f"GitHub API request failed with status code {response.status_code}: {response.json()}"
)
@staticmethod @staticmethod
def check_updates(repo, branch, version) -> UpdateStatus: def check_updates(repo, branch, version) -> UpdateStatus:
@ -399,21 +444,17 @@ class GitHub:
"version": data["commits"][-1]["sha"], "version": data["commits"][-1]["sha"],
"compare_url": data["permalink_url"], "compare_url": data["permalink_url"],
"head_ref": data["commits"][-1]["sha"], "head_ref": data["commits"][-1]["sha"],
"head_url": data["commits"][-1]["html_url"] "head_url": data["commits"][-1]["html_url"],
} }
else: else:
# If the request was not successful, raise an exception # If the request was not successful, raise an exception
raise Exception(f"GitHub API request failed with status code {response.status_code}: {response.json()}") raise Exception(
f"GitHub API request failed with status code {response.status_code}: {response.json()}"
)
@staticmethod @staticmethod
def create_issue(title: str, body: str) -> None: def create_issue(title: str, body: str) -> None:
cmd = [ cmd = ["gh", "issue", "create", "-t", title, "-b", body]
"gh",
"issue",
"create",
"-t", title,
"-b", body
]
CommandRunner.run_or_fail(cmd, stage="CreateIssue") CommandRunner.run_or_fail(cmd, stage="CreateIssue")
@staticmethod @staticmethod
@ -422,10 +463,14 @@ class GitHub:
"gh", "gh",
"pr", "pr",
"create", "create",
"-B", Git.default_branch, "-B",
"-H", branch, Git.default_branch,
"-t", title, "-H",
"-b", body branch,
"-t",
title,
"-b",
body,
] ]
CommandRunner.run_or_fail(cmd, stage="CreatePullRequest") CommandRunner.run_or_fail(cmd, stage="CreatePullRequest")
@ -436,7 +481,7 @@ def main():
data: DependencyYAML = yaml.safe_load(yaml_file) data: DependencyYAML = yaml.safe_load(yaml_file)
if "dependencies" not in data: if "dependencies" not in data:
raise Exception(f"dependencies.yml not properly formatted") raise Exception("dependencies.yml not properly formatted")
# Cache YAML version # Cache YAML version
DependencyStore.set(data) DependencyStore.set(data)
@ -446,5 +491,6 @@ def main():
dependency = Dependency(path, dependencies[path]) dependency = Dependency(path, dependencies[path])
dependency.update_or_notify() dependency.update_or_notify()
if __name__ == "__main__": if __name__ == "__main__":
main() main()