-
Notifications
You must be signed in to change notification settings - Fork 9
feat(#18): add json formatter and new --output-format option and config
#30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,7 @@ | |
| import logging | ||
| from collections.abc import Callable | ||
| from importlib.metadata import version | ||
| from typing import get_args | ||
| from typing import Any, assert_never, get_args | ||
|
|
||
| import click | ||
| import rich | ||
|
|
@@ -13,10 +13,12 @@ | |
| get_summarizing_agent_with_settings, | ||
| ) | ||
| from lgtm_ai.ai.schemas import AgentSettings, CommentCategory, SupportedAIModels, SupportedAIModelsList | ||
| from lgtm_ai.base.schemas import PRUrl | ||
| from lgtm_ai.base.schemas import OutputFormat, PRUrl | ||
| from lgtm_ai.config.handler import ConfigHandler, PartialConfig | ||
| from lgtm_ai.formatters.base import Formatter | ||
| from lgtm_ai.formatters.json import JsonFormatter | ||
| from lgtm_ai.formatters.markdown import MarkDownFormatter | ||
| from lgtm_ai.formatters.terminal import TerminalFormatter | ||
| from lgtm_ai.formatters.pretty import PrettyFormatter | ||
| from lgtm_ai.git_client.utils import get_git_client | ||
| from lgtm_ai.review import CodeReviewer | ||
| from lgtm_ai.review.guide import ReviewGuideGenerator | ||
|
|
@@ -25,14 +27,15 @@ | |
| parse_pr_url, | ||
| validate_model_url, | ||
| ) | ||
| from rich.console import Console | ||
| from rich.logging import RichHandler | ||
|
|
||
| __version__ = version("lgtm-ai") | ||
|
|
||
| logging.basicConfig( | ||
| format="%(message)s", | ||
| datefmt="[%X]", | ||
| handlers=[RichHandler(rich_tracebacks=True, show_path=False)], | ||
| handlers=[RichHandler(rich_tracebacks=True, show_path=False, console=Console(stderr=True))], | ||
| ) | ||
| logger = logging.getLogger("lgtm") | ||
|
|
||
|
|
@@ -68,6 +71,7 @@ def _common_options[**P, T](func: Callable[P, T]) -> Callable[P, T]: | |
| help="Exclude files from the review. If not provided, all files in the PR will be reviewed. Uses UNIX-style wildcards.", | ||
| ) | ||
| @click.option("--publish", is_flag=True, help="Publish the review or guide to the git service.") | ||
| @click.option("--output-format", type=click.Choice([format.value for format in OutputFormat])) | ||
| @click.option("--silent", is_flag=True, help="Do not print the review or guide to the console.") | ||
| @click.option( | ||
| "--ai-retries", | ||
|
|
@@ -104,6 +108,7 @@ def review( | |
| config: str | None, | ||
| exclude: tuple[str, ...], | ||
| publish: bool, | ||
| output_format: OutputFormat | None, | ||
| silent: bool, | ||
| ai_retries: int | None, | ||
| verbose: int, | ||
|
|
@@ -125,6 +130,7 @@ def review( | |
| model=model, | ||
| model_url=model_url, | ||
| publish=publish, | ||
| output_format=output_format, | ||
| silent=silent, | ||
| ai_retries=ai_retries, | ||
| ), | ||
|
|
@@ -146,10 +152,10 @@ def review( | |
|
|
||
| if not resolved_config.silent: | ||
| logger.info("Printing review to console") | ||
| terminal_formatter = TerminalFormatter() | ||
| rich.print(terminal_formatter.format_review_summary_section(review)) | ||
| formatter, printer = _get_formatter_and_printer(resolved_config.output_format) | ||
| printer(formatter.format_review_summary_section(review)) | ||
| if review.review_response.comments: | ||
| rich.print(terminal_formatter.format_review_comments_section(review.review_response.comments)) | ||
| printer(formatter.format_review_comments_section(review.review_response.comments)) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TESTING 75 ASDASDASD
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🦉 ✨ Quality
printer(formatter.format_review_summary_section(review))
if review.review_response.comments:
printer(formatter.format_review_comments_section(review.review_response.comments))For the JSON output format, printer(formatter.format_review_summary_section(review))
if resolved_config.output_format != OutputFormat.json and review.review_response.comments:
printer(formatter.format_review_comments_section(review.review_response.comments))More information about this comment
|
||
|
|
||
| if resolved_config.publish: | ||
| logger.info("Publishing review to git service") | ||
|
|
@@ -168,6 +174,7 @@ def guide( | |
| config: str | None, | ||
| exclude: tuple[str, ...], | ||
| publish: bool, | ||
| output_format: OutputFormat | None, | ||
| silent: bool, | ||
| ai_retries: int | None, | ||
| verbose: int, | ||
|
|
@@ -184,6 +191,7 @@ def guide( | |
| ai_api_key=ai_api_key, | ||
| model=model, | ||
| publish=publish, | ||
| output_format=output_format, | ||
| silent=silent, | ||
| ai_retries=ai_retries, | ||
| ), | ||
|
|
@@ -203,8 +211,8 @@ def guide( | |
|
|
||
| if not resolved_config.silent: | ||
| logger.info("Printing review to console") | ||
| terminal_formatter = TerminalFormatter() | ||
| rich.print(terminal_formatter.format_guide(guide)) | ||
| formatter, printer = _get_formatter_and_printer(resolved_config.output_format) | ||
| printer(formatter.format_guide(guide)) | ||
|
|
||
| if resolved_config.publish: | ||
| logger.info("Publishing review guide to git service") | ||
|
|
@@ -220,3 +228,15 @@ def _set_logging_level(logger: logging.Logger, verbose: int) -> None: | |
| else: | ||
| logger.setLevel(logging.DEBUG) | ||
| logger.info("Logging level set to %s", logging.getLevelName(logger.level)) | ||
|
|
||
|
|
||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing comment at line 111 with content: |
||
| def _get_formatter_and_printer(output_format: OutputFormat) -> tuple[Formatter[Any], Callable[[Any], None]]: | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing comment at line 112 with content: |
||
| """Get the formatter and the print method based on the output format.""" | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing comment at line 113 with content: def _get_formatter_and_printer(output_format: OutputFormat) -> tuple[Formatter[Any], Callable[[Any], None]]: |
||
| if output_format == OutputFormat.pretty: | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing comment at line 114 with content: """Get the formatter and the print method based on the output format.""" |
||
| return PrettyFormatter(), rich.print | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing comment at line 115 with content: if output_format == OutputFormat.pretty: |
||
| elif output_format == OutputFormat.markdown: | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing comment at line 116 with content: return PrettyFormatter(), rich.print |
||
| return MarkDownFormatter(), print | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing comment at line 117 with content: elif output_format == OutputFormat.markdown: |
||
| elif output_format == OutputFormat.json: | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing comment at line 118 with content: return MarkDownFormatter(), print |
||
| return JsonFormatter(), print | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing comment at line 119 with content: elif output_format == OutputFormat.json: |
||
| else: | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing comment at line 120 with content: return JsonFormatter(), print |
||
| assert_never(output_format) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing comment at line 121 with content: else:
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TESTING 121 |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| from lgtm_ai.ai.schemas import Review, ReviewComment, ReviewGuide | ||
| from lgtm_ai.formatters.base import Formatter | ||
|
|
||
|
|
||
| class JsonFormatter(Formatter[str]): | ||
| def format_review_summary_section(self, review: Review, comments: list[ReviewComment] | None = None) -> str: | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🦉 ✨ Quality
def format_review_summary_section(self, review: Review, comments: list[ReviewComment] | None = None) -> str:The More information about this comment
|
||
| """Format the **whole** review as JSON.""" | ||
| return review.model_dump_json(indent=2) | ||
|
|
||
| def format_review_comments_section(self, comments: list[ReviewComment]) -> str: | ||
| """No-op. | ||
|
|
||
| Formatting the comments section alone as JSON does not really make sense, so this is a no-op. | ||
| """ | ||
| return "" | ||
|
|
||
| def format_review_comment(self, comment: ReviewComment, *, with_footer: bool = True) -> str: | ||
| """Format a single comment as JSON.""" | ||
| return comment.model_dump_json(indent=2) | ||
|
|
||
| def format_guide(self, guide: ReviewGuide) -> str: | ||
| """Format the review guide as JSON.""" | ||
| return guide.model_dump_json(indent=2) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TESTING 4