diff --git a/penify_hook/api_client.py b/penify_hook/api_client.py index 6c527eb..a7deca9 100644 --- a/penify_hook/api_client.py +++ b/penify_hook/api_client.py @@ -5,33 +5,35 @@ class APIClient: def __init__(self, api_url, api_token: str = None, bearer_token: str = None): + """Initialize a new instance of the API client. + + Args: + api_url (str): The base URL of the API. + api_token (str?): An API token for authentication. Defaults to None. + bearer_token (str?): A Bearer token for authentication. Defaults to None. + """ self.api_url = api_url self.AUTH_TOKEN = api_token self.BEARER_TOKEN = bearer_token def send_file_for_docstring_generation(self, file_name, content, line_numbers, repo_details = None): - """Send file content and modified lines to the API and return modified - content. - - This function constructs a payload containing the file path, content, - and modified line numbers, and sends it to a specified API endpoint for - processing. It handles the response from the API, returning the modified - content if the request is successful. If the request fails, it logs the - error details and returns the original content. - + """Send file content and modified lines to the API and return modified content. + + This function constructs a payload containing the file path, content, and modified line numbers, and sends it to a + specified API endpoint for processing. It handles the response from the API, returning the modified content if the + request is successful. If the request fails, it logs the error details and returns the original content. + Args: file_name (str): The path to the file being sent. content (str): The content of the file to be processed. line_numbers (list): A list of line numbers that have been modified. - repo_details (str?): Additional repository details if applicable. Defaults to None. - + repo_details (str??): Additional repository details if applicable. Defaults to None. + Returns: - str: The modified content returned by the API, or the original content if the - request fails. - + str: The modified content returned by the API, or the original content if the request fails. + Raises: - Exception: If there is an error in processing the file and no specific error - message is provided. + Exception: If there is an error in processing the file and no specific error message is provided. """ payload = { 'file_path': file_name, @@ -54,22 +56,20 @@ def send_file_for_docstring_generation(self, file_name, content, line_numbers, r def generate_commit_summary(self, git_diff, instruction: str = "", repo_details = None, jira_context: dict = None): """Generate a commit summary by sending a POST request to the API endpoint. - - This function constructs a payload containing the git diff and any - additional instructions provided. It then sends this payload to a - specified API endpoint to generate a summary of the commit. If the - request is successful, it returns the response from the API; otherwise, - it returns None. - + + This function constructs a payload containing the git diff and any additional instructions provided. It then sends this + payload to a specified API endpoint to generate a summary of the commit. If the request is successful, it returns the + response from the API; otherwise, it returns None. + Args: git_diff (str): The git diff of the commit. - instruction (str??): Additional instruction for the commit. Defaults to "". - repo_details (dict??): Details of the git repository. Defaults to None. - jira_context (dict??): JIRA issue details to enhance the commit summary. Defaults to None. - + instruction (str?): Additional instruction for the commit. Defaults to "". + repo_details (dict?): Details of the git repository. Defaults to None. + jira_context (dict?): JIRA issue details to enhance the commit summary. Defaults to None. + Returns: dict: The response from the API if the request is successful, None otherwise. - + Raises: Exception: If there is an error during the API request. """ @@ -100,18 +100,16 @@ def generate_commit_summary(self, git_diff, instruction: str = "", repo_details return None def get_supported_file_types(self) -> list[str]: - """Retrieve the supported file types from the API. - - This function sends a request to the API endpoint - `/v1/file/supported_languages` to obtain a list of supported file types. - If the API call is successful (status code 200), it parses the JSON - response and returns the list of supported file types. If the API call - fails, it returns a default list of common file types. + """Retrieve the supported file types from the API. + + This function sends a request to the API endpoint `/v1/file/supported_languages` to obtain a list of supported file + types. If the API call is successful (status code 200), it parses the JSON response and returns the list of supported + file types. If the API call fails, it returns a default list of common file types. + Returns: list[str]: A list of supported file types, either from the API or a default set. """ - url = self.api_url+"/v1/file/supported_languages" response = requests.get(url) if response.status_code == 200: @@ -121,18 +119,17 @@ def get_supported_file_types(self) -> list[str]: return ["py", "js", "ts", "java", "kt", "cs", "c"] def generate_commit_summary_with_llm(self, diff, message, generate_description: bool, repo_details, llm_client : LLMClient, jira_context=None): - """Generates a commit summary using a local LLM client. If an error occurs - during the generation process, + """Generates a commit summary using a local LLM client. If an error occurs during the generation process, it falls back to using the API. - + Args: diff (str): The Git diff of changes. message (str): User-provided commit message or instructions. generate_description (bool): Flag indicating whether to generate a description for the commit. repo_details (dict): Details about the repository. llm_client (LLMClient): An instance of LLMClient used to generate the summary. - jira_context (JIRAContext?): Optional JIRA issue context to enhance the summary. - + jira_context (JIRAContext??): Optional JIRA issue context to enhance the summary. + Returns: dict: A dictionary containing the title and description for the commit. """ @@ -144,17 +141,16 @@ def generate_commit_summary_with_llm(self, diff, message, generate_description: return self.generate_commit_summary(diff, message, repo_details, jira_context) def get_api_key(self): - """Fetch an API key from a specified URL. - This function sends a GET request to retrieve an API token using a - Bearer token in the headers. It handles the response and returns the API - key if the request is successful, or `None` otherwise. + """Fetch an API key from a specified URL. + + This function sends a GET request to retrieve an API token using a Bearer token in the headers. It handles the response + and returns the API key if the request is successful, or `None` otherwise. + Returns: str: The API key if the request is successful, `None` otherwise. """ - - url = self.api_url+"/v1/apiToken/get" response = requests.get(url, headers={"Authorization": f"Bearer {self.BEARER_TOKEN}"}, timeout=60*10) if response.status_code == 200: diff --git a/penify_hook/base_analyzer.py b/penify_hook/base_analyzer.py index f1cda81..fa5646a 100644 --- a/penify_hook/base_analyzer.py +++ b/penify_hook/base_analyzer.py @@ -7,6 +7,15 @@ class BaseAnalyzer: def __init__(self, folder_path: str, api_client: APIClient): + """Manage a Git repository and interact with an API client. + + Initializes the repository manager with a folder path and an API client. It sets up the repository details, relative + file path, and supported file types. + + Args: + folder_path (str): The path to the local Git repository folder. + api_client (APIClient): An instance of the APIClient for API interactions. + """ self.folder_path = folder_path self.repo_path = recursive_search_git_folder(folder_path) self.repo = None diff --git a/penify_hook/commit_analyzer.py b/penify_hook/commit_analyzer.py index 31ab46b..2e3b922 100644 --- a/penify_hook/commit_analyzer.py +++ b/penify_hook/commit_analyzer.py @@ -13,6 +13,17 @@ class CommitDocGenHook(BaseAnalyzer): def __init__(self, repo_path: str, api_client: APIClient, llm_client=None, jira_client=None): + """Initialize a new instance of the class. + + This method initializes a new instance with the provided repository path, API client, and optionally LLM and JIRA + clients. + + Args: + repo_path (str): The path to the repository. + api_client (APIClient): The API client used for communication. + llm_client (LLMClient?): An optional LLM client for additional functionalities. Defaults to None. + jira_client (JiraClient?): An optional JIRA client for integration with JIRA. Defaults to None. + """ super().__init__(repo_path, api_client) self.llm_client = llm_client # Add LLM client as an optional parameter @@ -20,25 +31,20 @@ def __init__(self, repo_path: str, api_client: APIClient, llm_client=None, jira_ def get_summary(self, instruction: str, generate_description: bool) -> dict: """Generate a summary for the commit based on the staged changes. - - This function retrieves the differences of the staged changes in the - repository and generates a commit summary using the provided - instruction. If there are no changes staged for commit, an exception is - raised. If a JIRA client is connected, it will attempt to extract issue - keys from the current branch and use them to fetch context. The summary - can be generated either with a Language Model (LLM) client or through - the API client. - + + This function retrieves the differences of the staged changes in the repository and generates a commit summary using the + provided instruction. If there are no changes staged for commit, an exception is raised. If a JIRA client is connected, + it will attempt to extract issue keys from the current branch and use them to fetch context. The summary can be + generated either with a Language Model (LLM) client or through the API client. + Args: instruction (str): A string containing instructions for generating the commit summary. generate_description (bool): Whether to include detailed descriptions in the summary. - + Returns: - dict: The generated commit summary based on the staged changes, provided - instruction, and any relevant JIRA context. The dictionary contains keys - such as 'summary', 'description', etc., depending on whether a - description was requested. - + dict: The generated commit summary based on the staged changes, provided instruction, and any relevant JIRA context. The + dictionary contains keys such as 'summary', 'description', etc., depending on whether a description was requested. + Raises: ValueError: If there are no changes staged for commit. """ @@ -72,19 +78,16 @@ def get_summary(self, instruction: str, generate_description: bool) -> dict: def run(self, msg: Optional[str], edit_commit_message: bool, generate_description: bool): """Run the post-commit hook. - - This method processes the modified files from the last commit, stages - them, and creates an auto-commit with an optional message. It also - handles JIRA integration if available. If there is an error generating - the commit summary, an exception is raised. - + + This method processes the modified files from the last commit, stages them, and creates an auto-commit with an optional + message. It also handles JIRA integration if available. If there is an error generating the commit summary, an exception + is raised. + Args: msg (Optional[str]): An optional message to include in the commit. - edit_commit_message (bool): A flag indicating whether to open the git commit edit terminal after - committing. - generate_description (bool): A flag indicating whether to include a description in the commit - message. - + edit_commit_message (bool): A flag indicating whether to open the git commit edit terminal after committing. + generate_description (bool): A flag indicating whether to include a description in the commit message. + Raises: Exception: If there is an error generating the commit summary. """ @@ -111,18 +114,18 @@ def run(self, msg: Optional[str], edit_commit_message: bool, generate_descriptio self._amend_commit() def process_jira_integration(self, title: str, description: str, msg: str) -> tuple: + # Look for JIRA issue keys in commit message, title, description and user message """Process JIRA integration for the commit message. - + Args: title (str): Generated commit title. description (str): Generated commit description. msg (str): Original user message that might contain JIRA references. - + Returns: tuple: A tuple containing the updated commit title and description with included JIRA information. """ - # Look for JIRA issue keys in commit message, title, description and user message issue_keys = [] if self.jira_client: # Extract from message content @@ -161,11 +164,10 @@ def process_jira_integration(self, title: str, description: str, msg: str) -> tu def _amend_commit(self): """Open the default git editor for editing the commit message. - - This function changes the current working directory to the repository - path, runs the git command to amend the last commit, and opens the - default editor for the user to modify the commit message. After the - operation, it returns to the original directory. + + This function changes the current working directory to the repository path, runs the git command to amend the last + commit, and opens the default editor for the user to modify the commit message. After the operation, it returns to the + original directory. """ try: # Change to the repository directory diff --git a/penify_hook/config_command.py b/penify_hook/config_command.py index 1d9a6ab..f6ecece 100644 --- a/penify_hook/config_command.py +++ b/penify_hook/config_command.py @@ -2,19 +2,17 @@ def setup_config_parser(parent_parser): - """Set up a configuration parser with subparsers for different types of - configurations. - - This function configures and adds subcommands to the parent parser. Each - subcommand corresponds to a specific type of configuration, such as LLM - (Language Model) or JIRA. It allows users to configure settings for - these systems through command-line arguments. + # Config subcommand: Create subparsers for config types + """Set up a configuration parser with subparsers for different types of configurations. + + This function configures and adds subcommands to the parent parser. Each subcommand corresponds to a specific type of + configuration, such as LLM (Language Model) or JIRA. It allows users to configure settings for these systems through + command-line arguments. + Args: parent_parser (argparse.ArgumentParser): The parent parser to which the config subparsers will be added. """ - - # Config subcommand: Create subparsers for config types parser = parent_parser.add_subparsers(title="config_type", dest="config_type") # Config subcommand: llm @@ -39,20 +37,19 @@ def setup_config_parser(parent_parser): # Add all other necessary arguments for config command def handle_config(args): - """Handle configuration settings based on the specified config type. - - This function processes different types of configurations such as LLM - (Language Model) and JIRA. It saves configurations, sets up web-based - configurations, and verifies JIRA connections. + # Only import dependencies needed for config functionality here + """Handle configuration settings based on the specified config type. + + This function processes different types of configurations such as LLM (Language Model) and JIRA. It saves + configurations, sets up web-based configurations, and verifies JIRA connections. + Args: args (argparse.Namespace): Command-line arguments containing the type of configuration to handle. - + Returns: int: Exit code indicating success or failure. """ - - # Only import dependencies needed for config functionality here from penify_hook.commands.config_commands import save_llm_config from penify_hook.jira_client import JiraClient # Import moved here from penify_hook.commands.config_commands import config_jira_web, config_llm_web, save_jira_config diff --git a/penify_hook/folder_analyzer.py b/penify_hook/folder_analyzer.py index 15ec20f..3299be0 100644 --- a/penify_hook/folder_analyzer.py +++ b/penify_hook/folder_analyzer.py @@ -8,26 +8,32 @@ class FolderAnalyzerGenHook(BaseAnalyzer): def __init__(self, dir_path: str, api_client: APIClient): + """Initialize an instance of a class with directory path and API client. + + This constructor sets up the necessary attributes for managing files in a specified directory using an API client. It + calls the superclass constructor to ensure proper initialization. + + Args: + dir_path (str): The path to the directory where file operations will be performed. + api_client (APIClient): An instance of the APIClient class used for interacting with external APIs. + """ self.dir_path = dir_path super().__init__(dir_path, api_client) def list_all_files_in_dir(self, dir_path: str): - """List all non-hidden files in a directory and its subdirectories. - - This function recursively traverses the specified directory and its - subdirectories, collecting paths of all non-hidden files. It filters out - hidden directories and files (those starting with a dot) to ensure only - visible files are returned. + """List all non-hidden files in a directory and its subdirectories. + + This function recursively traverses the specified directory and its subdirectories, collecting paths of all non-hidden + files. It filters out hidden directories and files (those starting with a dot) to ensure only visible files are + returned. + Args: - dir_path (str): The path to the directory whose files and subdirectory files need to be - listed. - + dir_path (str): The path to the directory whose files and subdirectory files need to be listed. + Returns: - list: A list containing the full paths of all non-hidden files within the - specified directory and its subdirectories. + list: A list containing the full paths of all non-hidden files within the specified directory and its subdirectories. """ - files = [] for dirpath, dirnames, filenames in os.walk(dir_path): dirnames[:] = [d for d in dirnames if not d.startswith(".")] @@ -39,13 +45,11 @@ def list_all_files_in_dir(self, dir_path: str): def run(self): """Run the post-commit hook. - - This function processes all files in a specified directory using a - progress bar. It lists all files, initializes a `FileAnalyzerGenHook` - for each file, and runs it. Errors during processing of individual files - are caught and logged, but do not stop the processing of other files. A - progress bar is displayed indicating the number of files processed. - + + This function processes all files in a specified directory using a progress bar. It lists all files, initializes a + `FileAnalyzerGenHook` for each file, and runs it. Errors during processing of individual files are caught and logged, + but do not stop the processing of other files. A progress bar is displayed indicating the number of files processed. + Args: self (PostCommitHook): The instance of the post-commit hook class. """