Skip to content

Commit

Permalink
Update pr_config.py (#92)
Browse files Browse the repository at this point in the history
* Update pr_config.py

Signed-off-by: gitworkflows <118260833+gitworkflows@users.noreply.github.com>

* Update pr_add_docs.py

Signed-off-by: gitworkflows <118260833+gitworkflows@users.noreply.github.com>

* Update pr_config.py

Signed-off-by: gitworkflows <118260833+gitworkflows@users.noreply.github.com>

* Update pr_config.py

Signed-off-by: gitworkflows <118260833+gitworkflows@users.noreply.github.com>

* Update pr_config.py

Signed-off-by: gitworkflows <118260833+gitworkflows@users.noreply.github.com>

* Update pr_config.py

Signed-off-by: gitworkflows <118260833+gitworkflows@users.noreply.github.com>

---------

Signed-off-by: gitworkflows <118260833+gitworkflows@users.noreply.github.com>
  • Loading branch information
gitworkflows authored Dec 30, 2024
1 parent 8aa4f46 commit f80e7e8
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 23 deletions.
69 changes: 68 additions & 1 deletion pr_insight/tools/pr_add_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,23 @@


class PRAddDocs:
"""
The PRAddDocs class is responsible for generating code documentation for a pull request.
"""

def __init__(self, pr_url: str, cli_mode=False, args: list = None,
ai_handler: partial[BaseAiHandler,] = LiteLLMAIHandler):

"""
Initialize the PRAddDocs object with the necessary attributes and objects for generating code documentation
using an AI model.
Args:
pr_url (str): The URL of the pull request.
cli_mode (bool, optional): Flag indicating if the CLI mode is enabled. Defaults to False.
args (list, optional): List of arguments passed to the PRAddDocs class. Defaults to None.
ai_handler (partial[BaseAiHandler,], optional): The AI handler to use for generating code documentation.
Defaults to LiteLLMAIHandler.
"""
self.git_provider = get_git_provider()(pr_url)
self.main_language = get_main_pr_language(
self.git_provider.get_languages(), self.git_provider.get_files()
Expand Down Expand Up @@ -48,6 +62,9 @@ def __init__(self, pr_url: str, cli_mode=False, args: list = None,
get_settings().pr_add_docs_prompt.user)

async def run(self):
"""
Generate code documentation for the pull request and publish it as inline code suggestions.
"""
try:
get_logger().info('Generating code Docs for PR...')
if get_settings().config.publish_output:
Expand All @@ -69,6 +86,12 @@ async def run(self):
get_logger().error(f"Failed to generate code documentation for PR, error: {e}")

async def _prepare_prediction(self, model: str):
"""
Prepare the AI prediction for generating code documentation.
Args:
model (str): The name of the AI model to use for generating code documentation.
"""
get_logger().info('Getting PR diff...')

self.patches_diff = get_pr_diff(self.git_provider,
Expand All @@ -81,6 +104,15 @@ async def _prepare_prediction(self, model: str):
self.prediction = await self._get_prediction(model)

async def _get_prediction(self, model: str):
"""
Get the AI prediction for generating code documentation.
Args:
model (str): The name of the AI model to use for generating code documentation.
Returns:
str: The AI prediction for generating code documentation.
"""
variables = copy.deepcopy(self.vars)
variables["diff"] = self.patches_diff # update diff
environment = Environment(undefined=StrictUndefined)
Expand All @@ -95,13 +127,25 @@ async def _get_prediction(self, model: str):
return response

def _prepare_pr_code_docs(self) -> Dict:
"""
Prepare the code documentation for the pull request.
Returns:
Dict: The code documentation for the pull request.
"""
docs = self.prediction.strip()
data = load_yaml(docs)
if isinstance(data, list):
data = {'Code Documentation': data}
return data

def push_inline_docs(self, data):
"""
Publish the code documentation as inline code suggestions.
Args:
data (Dict): The code documentation for the pull request.
"""
docs = []

if not data['Code Documentation']:
Expand Down Expand Up @@ -135,6 +179,19 @@ def push_inline_docs(self, data):

def dedent_code(self, relevant_file, relevant_lines_start, new_code_snippet, doc_placement='after',
add_original_line=False):
"""
Dedent the code snippet to match the indentation of the original code.
Args:
relevant_file (str): The relevant file for the code snippet.
relevant_lines_start (int): The starting line number of the relevant code.
new_code_snippet (str): The new code snippet to be added.
doc_placement (str, optional): The placement of the documentation. Defaults to 'after'.
add_original_line (bool, optional): Flag indicating if the original line should be added. Defaults to False.
Returns:
str: The dedented code snippet.
"""
try: # dedent code snippet
self.diff_files = self.git_provider.diff_files if self.git_provider.diff_files \
else self.git_provider.get_diff_files()
Expand Down Expand Up @@ -167,6 +224,16 @@ def dedent_code(self, relevant_file, relevant_lines_start, new_code_snippet, doc


def get_docs_for_language(language, style):
"""
Get the documentation style for the given programming language.
Args:
language (str): The programming language.
style (str): The documentation style.
Returns:
str: The documentation style for the given programming language.
"""
language = language.lower()
if language == 'java':
return "Javadocs"
Expand Down
90 changes: 68 additions & 22 deletions pr_insight/tools/pr_config.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import logging
from dynaconf import Dynaconf

from pr_insight.config_loader import get_settings
from pr_insight.git_providers import get_git_provider
from pr_insight.log import get_logger

logger = logging.getLogger(__name__)

class PRConfig:
"""
Expand All @@ -20,43 +20,89 @@ def __init__(self, pr_url: str, args=None, ai_handler=None):
self.git_provider = get_git_provider()(pr_url)

async def run(self):
get_logger().info('Getting configuration settings...')
get_logger().info('Preparing configs...')
pr_comment = self._prepare_pr_configs()
if get_settings().config.publish_output:
get_logger().info('Pushing configs...')
self.git_provider.publish_comment(pr_comment)
self.git_provider.remove_initial_comment()
"""
Run the PRConfig process to get and publish configuration settings.
This method retrieves the configuration settings, prepares them for display, and publishes them as a comment
on the pull request.
"""
try:
logger.info('Getting configuration settings...')
pr_comment = self._prepare_pr_configs()
if get_settings().config.publish_output:
logger.info('Pushing configs...')
self.git_provider.publish_comment(pr_comment)
self.git_provider.remove_initial_comment()
except Exception as e:
logger.error("Failed to run PRConfig: %s", e)
return ""

def _prepare_pr_configs(self) -> str:
conf_file = get_settings().find_file("configuration.toml")
conf_settings = Dynaconf(settings_files=[conf_file])
configuration_headers = [header.lower() for header in conf_settings.keys()]
relevant_configs = {
"""
Prepare the configuration settings for display.
This method retrieves the configuration settings from the configuration file, filters out irrelevant settings,
and formats them as a markdown string for display.
Returns:
str: The formatted configuration settings as a markdown string.
"""
try:
if conf_file := get_settings().find_file("configuration.toml"):
conf_settings = Dynaconf(settings_files=[conf_file])
configuration_headers = [header.lower() for header in conf_settings.keys()]
relevant_configs = self._filter_relevant_configs(configuration_headers)
markdown_text = self._format_configs_to_markdown(relevant_configs)
logger.info("Possible Configurations outputted to PR comment", extra={"artifact": markdown_text})
return markdown_text
except Exception as e:
logger.error("Error preparing PR configs: %s", e)
return ""

@staticmethod
def _filter_relevant_configs(configuration_headers):
"""
Filter relevant configuration settings.
Args:
configuration_headers (list): List of relevant configuration headers.
Returns:
dict: Filtered configuration settings.
"""
return {
header: configs for header, configs in get_settings().to_dict().items()
if (header.lower().startswith("pr_") or header.lower().startswith("config")) and header.lower() in configuration_headers
}

skip_keys = ['ai_disclaimer', 'ai_disclaimer_title', 'ANALYTICS_FOLDER', 'secret_provider', "skip_keys",
'trial_prefix_message', 'no_eligible_message', 'identity_provider', 'ALLOWED_REPOS',
'APP_NAME']
@staticmethod
def _format_configs_to_markdown(relevant_configs):
"""
Format configuration settings to markdown.
Args:
relevant_configs (dict): Relevant configuration settings.
Returns:
str: Formatted markdown string.
"""
skip_keys = [
'ai_disclaimer', 'ai_disclaimer_title', 'ANALYTICS_FOLDER', 'secret_provider', "skip_keys",
'trial_prefix_message', 'no_eligible_message', 'identity_provider', 'ALLOWED_REPOS', 'APP_NAME'
]
extra_skip_keys = get_settings().config.get('config.skip_keys', [])
if extra_skip_keys:
skip_keys.extend(extra_skip_keys)

markdown_text = "<details> <summary><strong>🛠️ PR-Insight Configurations:</strong></summary> \n\n"
markdown_text += f"\n\n```yaml\n\n"
markdown_text += "\n\n```yaml\n\n"
for header, configs in relevant_configs.items():
if configs:
markdown_text += "\n\n"
markdown_text += f"==================== {header} ===================="
for key, value in configs.items():
if key in skip_keys:
continue
markdown_text += f"\n{header.lower()}.{key.lower()} = {repr(value) if isinstance(value, str) else value}"
markdown_text += " "
if key not in skip_keys:
markdown_text += f"\n{header.lower()}.{key.lower()} = {repr(value) if isinstance(value, str) else value} "
markdown_text += "\n```"
markdown_text += "\n</details>\n"
get_logger().info(f"Possible Configurations outputted to PR comment", artifact=markdown_text)
return markdown_text

0 comments on commit f80e7e8

Please sign in to comment.