From 7bf00ddcce169fd09b4a8e3f2add7f13924dc00d Mon Sep 17 00:00:00 2001 From: Joseph Eng Date: Tue, 16 Jul 2024 13:43:53 -0700 Subject: [PATCH] Add docstrings --- upstream_utils/upstream_utils.py | 80 +++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/upstream_utils/upstream_utils.py b/upstream_utils/upstream_utils.py index 560fbe048a6..0dd3544d3ea 100644 --- a/upstream_utils/upstream_utils.py +++ b/upstream_utils/upstream_utils.py @@ -203,6 +203,14 @@ def git_am(patch, use_threeway=False, ignore_whitespace=False): def has_git_rev(rev): + """Checks whether the Git repository in the current directory has the given revision. + + Keyword arguments: + rev -- The revision to check + + Returns: + True if the revision exists, otherwise False. + """ cmd = ["git", "rev-parse", "--verify", "-q", rev] return subprocess.run(cmd, stdout=subprocess.DEVNULL).returncode == 0 @@ -212,7 +220,7 @@ def __init__( self, name, url, - old_tag, + tag, patch_list, copy_upstream_src, patch_options={}, @@ -220,9 +228,23 @@ def __init__( pre_patch_hook=None, pre_patch_commits=0, ): + """Initializes a Lib instance. + + Keyword arguments: + name -- The name of the library. + url -- The URL of the upstream repository. + tag -- The tag in the upstream repository to use. Can be any (e.g., commit hash or tag). + patch_list -- The list of patches in the patch directory to apply. + copy_upstream_src -- A callable that takes the path to the wpilib root and copies the files from the clone of the upstream into the appropriate thirdparty directory. Will only be called when the current directory is the upstream clone. + patch_options -- The dictionary of options to use when applying patches. Corresponds to the parameters of git_am. + + Keyword-only arguments: + pre_patch_hook -- Optional callable taking no parameters that will be called before applying patches. + pre_patch_commits -- Number of commits added by pre_patch_hook. + """ self.name = name self.url = url - self.old_tag = old_tag + self.old_tag = tag self.patch_list = patch_list self.copy_upstream_src = copy_upstream_src self.patch_options = patch_options @@ -231,6 +253,7 @@ def __init__( self.wpilib_root = get_repo_root() def check_patches(self): + """Checks the patch list supplied to the constructor against the patches in the patch directory.""" patch_directory_patches = set() patch_directory = os.path.join( self.wpilib_root, f"upstream_utils/{self.name}_patches" @@ -260,6 +283,14 @@ def check_patches(self): ) def get_repo_path(self, tempdir=None): + """Returns the path to the clone of the upstream repository. + + Keyword argument: + tempdir -- The path to the temporary directory to use. If None (the default), uses tempfile.gettempdir(). + + Returns: + The path to the clone of the upstream repository. Will be absolute if tempdir is absolute. + """ if tempdir is None: tempdir = tempfile.gettempdir() repo = os.path.basename(self.url) @@ -268,6 +299,11 @@ def get_repo_path(self, tempdir=None): return dest def open_repo(self, *, err_msg_if_absent): + """Changes the current working directory to the upstream repository. If err_msg_if_absent is not None and the upstream repository does not exist, the program exits with return code 1. + + Keyword-only argument: + err_msg_if_absent -- The error message to print to stderr if the upstream repository does not exist. If None, the upstream repository will be cloned without emitting any warnings. + """ os.chdir(tempfile.gettempdir()) dest = self.get_repo_path(os.getcwd()) @@ -283,6 +319,11 @@ def open_repo(self, *, err_msg_if_absent): os.chdir(dest) def get_root_tags(self): + """Returns a list of potential root tags. + + Returns: + A list of the potential root tags. + """ root_tag_output = subprocess.run( ["git", "tag", "--list", "upstream_utils_root-*"], capture_output=True, @@ -291,6 +332,11 @@ def get_root_tags(self): return root_tag_output.splitlines() def get_root_tag(self): + """Returns the root tag (the default tag to apply the patches relative to). If there are multiple candidates, prints an error to stderr and the program exits with return code 1. + + Returns: + The root tag. + """ root_tags = self.get_root_tags() if len(root_tags) == 0: print( @@ -307,6 +353,11 @@ def get_root_tag(self): return root_tags[0] def set_root_tag(self, tag): + """Sets the root tag, deleting any potential candidates first. + + Keyword argument: + tag -- The tag to set as the root tag. + """ root_tags = self.get_root_tags() if len(root_tags) > 1: @@ -318,6 +369,7 @@ def set_root_tag(self, tag): subprocess.run(["git", "tag", f"upstream_utils_root-{tag}", tag]) def apply_patches(self): + """Applies the patches listed in the patch list to the current directory.""" if self.pre_patch_hook is not None: self.pre_patch_hook() @@ -330,6 +382,11 @@ def apply_patches(self): ) def replace_tag(self, tag): + """Replaces the tag in the script. + + Keyword argument: + tag -- The tag to replace the script tag with. + """ path = os.path.join(self.wpilib_root, f"upstream_utils/{self.name}.py") with open(path, "r") as file: lines = file.readlines() @@ -349,6 +406,7 @@ def replace_tag(self, tag): file.writelines(lines) def info(self): + """Prints info about the library to stdout.""" print(f"Repository name: {self.name}") print(f"Upstream URL: {self.url}") print(f"Upstream tag: {self.old_tag}") @@ -359,6 +417,7 @@ def info(self): print(f"WPILib root: {self.wpilib_root}") def clone(self): + """Clones the upstream repository and sets it up.""" self.open_repo(err_msg_if_absent=None) subprocess.run(["git", "switch", "--detach", self.old_tag]) @@ -366,6 +425,7 @@ def clone(self): self.set_root_tag(self.old_tag) def reset(self): + """Resets the clone of the upstream repository to the state specified by the script and patches.""" self.open_repo( err_msg_if_absent='There\'s nothing to reset. Run the "clone" command first.' ) @@ -377,6 +437,11 @@ def reset(self): self.apply_patches() def rebase(self, new_tag): + """Rebases the patches. + + Keyword argument: + new_tag -- The tag to rebase onto. + """ self.open_repo( err_msg_if_absent='There\'s nothing to rebase. Run the "clone" command first.' ) @@ -399,6 +464,11 @@ def rebase(self, new_tag): ) def format_patch(self, tag=None): + """Generates patch files for the upstream repository and moves them into the patch directory. + + Keyword argument: + tag -- The tag of the commit of the upstream repository the patch commit were applied onto. If None (the default), the root tag will be used. + """ self.open_repo( err_msg_if_absent='There\'s nothing to run format-patch on. Run the "clone" and "rebase" commands first.' ) @@ -451,6 +521,7 @@ def format_patch(self, tag=None): self.replace_tag(script_tag) def copy_upstream_to_thirdparty(self): + """Copies files from the upstream repository into the thirdparty directory.""" self.open_repo( err_msg_if_absent='There\'s no repository to copy from. Run the "clone" command first.' ) @@ -462,6 +533,11 @@ def copy_upstream_to_thirdparty(self): self.copy_upstream_src(self.wpilib_root) def main(self, argv=sys.argv[1:]): + """Processes the given arguments. + + Keyword argument: + argv -- The arguments to process. Defaults to the arguments passed to the program. + """ parser = argparse.ArgumentParser( description=f"CLI manager of the {self.name} upstream library" )