Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 30 additions & 11 deletions penify_hook/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ def send_file_for_docstring_generation(self, file_name, content, line_numbers, r
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.
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.

Raises:
Exception: If there is an error in processing the file and no specific error
message is provided.
"""
payload = {
'file_path': file_name,
Expand Down Expand Up @@ -65,6 +69,9 @@ def generate_commit_summary(self, git_diff, instruction: str = "", repo_details

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.
"""
payload = {
'git_diff': git_diff,
Expand Down Expand Up @@ -113,18 +120,20 @@ 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):
"""
Generate a commit summary using a local LLM client instead of the API.

"""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: Git diff of changes
message: User-provided commit message or instructions
repo_details: Details about the repository
llm_client: Instance of LLMClient
jira_context: Optional JIRA issue context to enhance the summary

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.

Returns:
Dict with title and description for the commit
dict: A dictionary containing the title and description for the commit.
"""
try:
return llm_client.generate_commit_summary(diff, message, generate_description, repo_details, jira_context)
Expand All @@ -134,6 +143,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):
"""Get an API key from the specified URL.

It constructs a request to fetch an API token using a Bearer token in
the headers. The function handles the response and returns the API key
if 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)
Expand Down
47 changes: 26 additions & 21 deletions penify_hook/commit_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,23 @@ def get_summary(self, instruction: str, generate_description: bool) -> dict:
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 an LLM client is provided, it will use that for generating
the summary, otherwise it will use the API client.
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:
str: The generated commit summary based on the staged changes and provided
instruction.
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:
Exception: If there are no changes staged for commit.
ValueError: If there are no changes staged for commit.
"""
diff = self.repo.git.diff('--cached')
if not diff:
Expand Down Expand Up @@ -68,17 +73,17 @@ 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 retrieves the list of modified files from the last commit
and processes each file. It stages any files that have been modified
during processing and creates an auto-commit if changes were made. A
progress bar is displayed to indicate the processing status of each
file. 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.
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.
Expand Down Expand Up @@ -106,16 +111,16 @@ 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:
"""
Process JIRA integration for the commit message.

"""Process JIRA integration for the commit message.

Args:
title: Generated commit title
description: Generated commit description
msg: Original user message that might contain JIRA references
title (str): Generated commit title.
description (str): Generated commit description.
msg (str): Original user message that might contain JIRA references.

Returns:
tuple: (updated_title, updated_description) with JIRA information
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 = []
Expand Down
9 changes: 8 additions & 1 deletion penify_hook/file_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,11 @@ def process_file(self, file_path, pbar):
return False

def print_processing(self, file_path):
"""Print a processing message for a file."""
"""Print a processing message for a file.

Args:
file_path (str): The path to the file being processed.
"""
formatted_path = format_file_path(file_path)
print(f"\n{format_highlight(f'Processing file: {formatted_path}')}")

Expand All @@ -116,6 +120,9 @@ def run(self):
an error message indicating that the file was not processed. The method
displays a progress bar and colored output to provide visual feedback on
the processing status.

Args:
self (PostCommitHook): An instance of the PostCommitHook class.
"""

# Create a progress bar with appropriate stages
Expand Down
28 changes: 26 additions & 2 deletions penify_hook/folder_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,21 @@ def __init__(self, dir_path: str, api_client: APIClient):
super().__init__(dir_path, api_client)

def list_all_files_in_dir(self, dir_path: str):
"""List all files in a directory and its subdirectories."""
"""List all files in a directory and its subdirectories.

This function traverses the specified directory using `os.walk`,
collecting paths of all non-hidden files into a list. It filters out
hidden directories (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.

Returns:
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):
Expand All @@ -24,7 +38,17 @@ def list_all_files_in_dir(self, dir_path: str):
return files

def run(self):
"""Run the post-commit hook."""
"""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.

Args:
self (PostCommitHook): The instance of the post-commit hook class.
"""
try:
file_list = self.list_all_files_in_dir(self.dir_path)
total_files = len(file_list)
Expand Down
Loading
Loading