Skip to content

Commit e5198f1

Browse files
committed
lint and agentic llm
1 parent da1370b commit e5198f1

File tree

33 files changed

+1156
-864
lines changed

33 files changed

+1156
-864
lines changed

patchwork/common/client/llm/anthropic.py

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -129,22 +129,22 @@ def __adapt_input_messages(self, messages: Iterable[ChatCompletionMessageParam])
129129
return new_messages
130130

131131
def __adapt_chat_completion_request(
132-
self,
133-
messages: Iterable[ChatCompletionMessageParam],
134-
model: str,
135-
frequency_penalty: Optional[float] | NotGiven = NOT_GIVEN,
136-
logit_bias: Optional[Dict[str, int]] | NotGiven = NOT_GIVEN,
137-
logprobs: Optional[bool] | NotGiven = NOT_GIVEN,
138-
max_tokens: Optional[int] | NotGiven = NOT_GIVEN,
139-
n: Optional[int] | NotGiven = NOT_GIVEN,
140-
presence_penalty: Optional[float] | NotGiven = NOT_GIVEN,
141-
response_format: completion_create_params.ResponseFormat | NotGiven = NOT_GIVEN,
142-
stop: Union[Optional[str], List[str]] | NotGiven = NOT_GIVEN,
143-
temperature: Optional[float] | NotGiven = NOT_GIVEN,
144-
tools: Iterable[ChatCompletionToolParam] | NotGiven = NOT_GIVEN,
145-
tool_choice: ChatCompletionToolChoiceOptionParam | NotGiven = NOT_GIVEN,
146-
top_logprobs: Optional[int] | NotGiven = NOT_GIVEN,
147-
top_p: Optional[float] | NotGiven = NOT_GIVEN,
132+
self,
133+
messages: Iterable[ChatCompletionMessageParam],
134+
model: str,
135+
frequency_penalty: Optional[float] | NotGiven = NOT_GIVEN,
136+
logit_bias: Optional[Dict[str, int]] | NotGiven = NOT_GIVEN,
137+
logprobs: Optional[bool] | NotGiven = NOT_GIVEN,
138+
max_tokens: Optional[int] | NotGiven = NOT_GIVEN,
139+
n: Optional[int] | NotGiven = NOT_GIVEN,
140+
presence_penalty: Optional[float] | NotGiven = NOT_GIVEN,
141+
response_format: completion_create_params.ResponseFormat | NotGiven = NOT_GIVEN,
142+
stop: Union[Optional[str], List[str]] | NotGiven = NOT_GIVEN,
143+
temperature: Optional[float] | NotGiven = NOT_GIVEN,
144+
tools: Iterable[ChatCompletionToolParam] | NotGiven = NOT_GIVEN,
145+
tool_choice: ChatCompletionToolChoiceOptionParam | NotGiven = NOT_GIVEN,
146+
top_logprobs: Optional[int] | NotGiven = NOT_GIVEN,
147+
top_p: Optional[float] | NotGiven = NOT_GIVEN,
148148
):
149149
system: Union[str, Iterable[TextBlockParam]] | NotGiven = NOT_GIVEN
150150
adapted_messages = self.__adapt_input_messages(messages)
@@ -208,22 +208,22 @@ def is_model_supported(self, model: str) -> bool:
208208
return model in self.__definitely_allowed_models or model.startswith(self.__allowed_model_prefix)
209209

210210
def is_prompt_supported(
211-
self,
212-
messages: Iterable[ChatCompletionMessageParam],
213-
model: str,
214-
frequency_penalty: Optional[float] | NotGiven = NOT_GIVEN,
215-
logit_bias: Optional[Dict[str, int]] | NotGiven = NOT_GIVEN,
216-
logprobs: Optional[bool] | NotGiven = NOT_GIVEN,
217-
max_tokens: Optional[int] | NotGiven = NOT_GIVEN,
218-
n: Optional[int] | NotGiven = NOT_GIVEN,
219-
presence_penalty: Optional[float] | NotGiven = NOT_GIVEN,
220-
response_format: completion_create_params.ResponseFormat | NotGiven = NOT_GIVEN,
221-
stop: Union[Optional[str], List[str]] | NotGiven = NOT_GIVEN,
222-
temperature: Optional[float] | NotGiven = NOT_GIVEN,
223-
tools: Iterable[ChatCompletionToolParam] | NotGiven = NOT_GIVEN,
224-
tool_choice: ChatCompletionToolChoiceOptionParam | NotGiven = NOT_GIVEN,
225-
top_logprobs: Optional[int] | NotGiven = NOT_GIVEN,
226-
top_p: Optional[float] | NotGiven = NOT_GIVEN,
211+
self,
212+
messages: Iterable[ChatCompletionMessageParam],
213+
model: str,
214+
frequency_penalty: Optional[float] | NotGiven = NOT_GIVEN,
215+
logit_bias: Optional[Dict[str, int]] | NotGiven = NOT_GIVEN,
216+
logprobs: Optional[bool] | NotGiven = NOT_GIVEN,
217+
max_tokens: Optional[int] | NotGiven = NOT_GIVEN,
218+
n: Optional[int] | NotGiven = NOT_GIVEN,
219+
presence_penalty: Optional[float] | NotGiven = NOT_GIVEN,
220+
response_format: completion_create_params.ResponseFormat | NotGiven = NOT_GIVEN,
221+
stop: Union[Optional[str], List[str]] | NotGiven = NOT_GIVEN,
222+
temperature: Optional[float] | NotGiven = NOT_GIVEN,
223+
tools: Iterable[ChatCompletionToolParam] | NotGiven = NOT_GIVEN,
224+
tool_choice: ChatCompletionToolChoiceOptionParam | NotGiven = NOT_GIVEN,
225+
top_logprobs: Optional[int] | NotGiven = NOT_GIVEN,
226+
top_p: Optional[float] | NotGiven = NOT_GIVEN,
227227
) -> int:
228228
model_limit = self.__get_model_limit(model)
229229
input_kwargs = self.__adapt_chat_completion_request(
@@ -252,27 +252,27 @@ def is_prompt_supported(
252252
return model_limit - message_token_count.input_tokens
253253

254254
def truncate_messages(
255-
self, messages: Iterable[ChatCompletionMessageParam], model: str
255+
self, messages: Iterable[ChatCompletionMessageParam], model: str
256256
) -> Iterable[ChatCompletionMessageParam]:
257257
return self._truncate_messages(self, messages, model)
258258

259259
def chat_completion(
260-
self,
261-
messages: Iterable[ChatCompletionMessageParam],
262-
model: str,
263-
frequency_penalty: Optional[float] | NotGiven = NOT_GIVEN,
264-
logit_bias: Optional[Dict[str, int]] | NotGiven = NOT_GIVEN,
265-
logprobs: Optional[bool] | NotGiven = NOT_GIVEN,
266-
max_tokens: Optional[int] | NotGiven = NOT_GIVEN,
267-
n: Optional[int] | NotGiven = NOT_GIVEN,
268-
presence_penalty: Optional[float] | NotGiven = NOT_GIVEN,
269-
response_format: completion_create_params.ResponseFormat | NotGiven = NOT_GIVEN,
270-
stop: Union[Optional[str], List[str]] | NotGiven = NOT_GIVEN,
271-
temperature: Optional[float] | NotGiven = NOT_GIVEN,
272-
tools: Iterable[ChatCompletionToolParam] | NotGiven = NOT_GIVEN,
273-
tool_choice: ChatCompletionToolChoiceOptionParam | NotGiven = NOT_GIVEN,
274-
top_logprobs: Optional[int] | NotGiven = NOT_GIVEN,
275-
top_p: Optional[float] | NotGiven = NOT_GIVEN,
260+
self,
261+
messages: Iterable[ChatCompletionMessageParam],
262+
model: str,
263+
frequency_penalty: Optional[float] | NotGiven = NOT_GIVEN,
264+
logit_bias: Optional[Dict[str, int]] | NotGiven = NOT_GIVEN,
265+
logprobs: Optional[bool] | NotGiven = NOT_GIVEN,
266+
max_tokens: Optional[int] | NotGiven = NOT_GIVEN,
267+
n: Optional[int] | NotGiven = NOT_GIVEN,
268+
presence_penalty: Optional[float] | NotGiven = NOT_GIVEN,
269+
response_format: completion_create_params.ResponseFormat | NotGiven = NOT_GIVEN,
270+
stop: Union[Optional[str], List[str]] | NotGiven = NOT_GIVEN,
271+
temperature: Optional[float] | NotGiven = NOT_GIVEN,
272+
tools: Iterable[ChatCompletionToolParam] | NotGiven = NOT_GIVEN,
273+
tool_choice: ChatCompletionToolChoiceOptionParam | NotGiven = NOT_GIVEN,
274+
top_logprobs: Optional[int] | NotGiven = NOT_GIVEN,
275+
top_p: Optional[float] | NotGiven = NOT_GIVEN,
276276
) -> ChatCompletion:
277277
input_kwargs = self.__adapt_chat_completion_request(
278278
messages=messages,

patchwork/common/client/patched.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -245,12 +245,7 @@ def finish_record_patchflow_run(self, id: int, patchflow: str, repo: Repo, outpu
245245
response = self._post(
246246
url=self.url + "/v1/patchwork/",
247247
headers={"Authorization": f"Bearer {self.access_token}"},
248-
json={
249-
"id": id,
250-
"url": repo.remotes.origin.url,
251-
"patchflow": patchflow,
252-
"outputs": outputs
253-
},
248+
json={"id": id, "url": repo.remotes.origin.url, "patchflow": patchflow, "outputs": outputs},
254249
)
255250

256251
if response is None:

patchwork/common/client/scm.py

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,21 @@
1515
from azure.devops.released.client_factory import ClientFactory
1616
from azure.devops.released.core.core_client import CoreClient
1717
from azure.devops.released.git.git_client import GitClient
18-
from azure.devops.v7_1.git.models import GitPullRequest, GitPullRequestSearchCriteria, TeamProjectReference, \
19-
GitRepository, Comment, GitPullRequestCommentThread, GitTargetVersionDescriptor, GitBaseVersionDescriptor
18+
from azure.devops.v7_1.git.models import (
19+
Comment,
20+
GitPullRequest,
21+
GitPullRequestCommentThread,
22+
GitPullRequestSearchCriteria,
23+
GitRepository,
24+
TeamProjectReference,
25+
)
2026
from github import Auth, Consts, Github, GithubException, PullRequest
2127
from github.GithubException import UnknownObjectException
2228
from gitlab import Gitlab, GitlabAuthenticationError, GitlabError
2329
from gitlab.v4.objects import ProjectMergeRequest
2430
from giturlparse import GitUrlParsed, parse
2531
from msrest.authentication import BasicAuthentication
26-
from typing_extensions import Protocol, TypedDict, Iterator
32+
from typing_extensions import Iterator, Protocol, TypedDict
2733

2834
from patchwork.logger import logger
2935

@@ -359,6 +365,7 @@ def texts(self) -> PullRequestTexts:
359365
diffs={file.filename: file.patch for file in self._pr.get_files() if file.patch is not None},
360366
)
361367

368+
362369
class AzureDevopsPullRequest(PullRequestProtocol):
363370
def __init__(self, pr: GitPullRequest, git_client: GitClient, pr_base_url: str):
364371
self._pr: GitPullRequest = pr
@@ -378,24 +385,41 @@ def url(self) -> str:
378385
def set_pr_description(self, body: str) -> None:
379386
final_body = PullRequestProtocol._apply_pr_template(self, body)
380387
body = GitPullRequest(description=final_body)
381-
self._pr = self.git_client.update_pull_request(body, repository_id=self._pr.repository.id, pull_request_id=self._pr.pull_request_id, project=self._pr.repository.project.id)
388+
self._pr = self.git_client.update_pull_request(
389+
body,
390+
repository_id=self._pr.repository.id,
391+
pull_request_id=self._pr.pull_request_id,
392+
project=self._pr.repository.project.id,
393+
)
382394

383395
def create_comment(
384-
self, body: str, path: str | None = None, start_line: int | None = None, end_line: int | None = None
396+
self, body: str, path: str | None = None, start_line: int | None = None, end_line: int | None = None
385397
) -> str | None:
386398
try:
387399
comment_body = Comment(content=body)
388400
comment_thread_body = GitPullRequestCommentThread(comments=[comment_body])
389-
comment_thread = self.git_client.create_thread(comment_thread_body, repository_id=self._pr.repository.id, pull_request_id=self.id, project=self._pr.repository.project.id)
401+
comment_thread = self.git_client.create_thread(
402+
comment_thread_body,
403+
repository_id=self._pr.repository.id,
404+
pull_request_id=self.id,
405+
project=self._pr.repository.project.id,
406+
)
390407
return body
391408
except Exception as e:
392409
logger.error(e)
393410
return None
394411

395412
def __iter_comments(self) -> Iterator[tuple[GitPullRequestCommentThread, list[Comment]]]:
396-
threads = self.git_client.get_threads(repository_id=self._pr.repository.id, pull_request_id=self.id, project=self._pr.repository.project.id)
413+
threads = self.git_client.get_threads(
414+
repository_id=self._pr.repository.id, pull_request_id=self.id, project=self._pr.repository.project.id
415+
)
397416
for thread in threads:
398-
comments = self.git_client.get_comments(repository_id=self._pr.repository.id, pull_request_id=self.id, thread_id=thread.id, project=self._pr.repository.project.id)
417+
comments = self.git_client.get_comments(
418+
repository_id=self._pr.repository.id,
419+
pull_request_id=self.id,
420+
thread_id=thread.id,
421+
project=self._pr.repository.project.id,
422+
)
399423
yield thread, comments
400424

401425
def reset_comments(self) -> None:
@@ -406,7 +430,13 @@ def reset_comments(self) -> None:
406430
comment_ids_to_delete.append(comment.id)
407431
if len(comment_ids_to_delete) == len(comments):
408432
for comment_id in comment_ids_to_delete:
409-
self.git_client.delete_comment(repository_id=self._pr.repository.id, pull_request_id=self.id, thread_id=thread.id, comment_id=comment_id, project=self._pr.repository.project.id)
433+
self.git_client.delete_comment(
434+
repository_id=self._pr.repository.id,
435+
pull_request_id=self.id,
436+
thread_id=thread.id,
437+
comment_id=comment_id,
438+
project=self._pr.repository.project.id,
439+
)
410440

411441
def texts(self) -> PullRequestTexts:
412442
target_branch = self._pr.last_merge_source_commit.commit_id
@@ -425,7 +455,9 @@ def texts(self) -> PullRequestTexts:
425455
b_path = diff.b_path
426456
a_blob = diff.a_blob.data_stream.read().decode("utf-8")
427457
b_blob = diff.b_blob.data_stream.read().decode("utf-8")
428-
diff_lines = unified_diff(a_blob.splitlines(keepends=True), b_blob.splitlines(keepends=True), a_path, b_path)
458+
diff_lines = unified_diff(
459+
a_blob.splitlines(keepends=True), b_blob.splitlines(keepends=True), a_path, b_path
460+
)
429461
diff_content = "".join(diff_lines)
430462
diffs[a_path] = diff_content
431463

@@ -440,6 +472,7 @@ def texts(self) -> PullRequestTexts:
440472
diffs=diffs,
441473
)
442474

475+
443476
class GithubClient(ScmPlatformClientProtocol):
444477
DEFAULT_URL = Consts.DEFAULT_BASE_URL
445478

@@ -701,7 +734,7 @@ class AzureDevopsClient(ScmPlatformClientProtocol):
701734
DEFAULT_URL = "https://dev.azure.com/"
702735

703736
def __init__(self, access_token: str, url: str = DEFAULT_URL, remote: str = "origin"):
704-
self.credentials = BasicAuthentication('', access_token)
737+
self.credentials = BasicAuthentication("", access_token)
705738
self.__url = url
706739
self.__remote = remote
707740
git_repo = git.Repo(Path.cwd(), search_parent_directories=True)
@@ -717,7 +750,6 @@ def __pr_resource_html_url(self):
717750
url += "/"
718751
return f"{url}{self.__org_name}/{self.__project_name}/_git/{self.__repo_name}/pullrequest/"
719752

720-
721753
@functools.cached_property
722754
def clients(self) -> ClientFactory:
723755
url = self.__url
@@ -740,15 +772,19 @@ def project(self) -> TeamProjectReference:
740772
projs = self.core_client.get_projects()
741773
proj = next((proj for proj in projs if proj.name == self.__project_name), None)
742774
if proj is None:
743-
raise ValueError(f"Unable to determine project name from remote {self.__remote} url. Parsed project name: {self.__project_name}")
775+
raise ValueError(
776+
f"Unable to determine project name from remote {self.__remote} url. Parsed project name: {self.__project_name}"
777+
)
744778
return proj
745779

746780
@functools.cached_property
747781
def repo(self) -> GitRepository:
748782
repos = self.git_client.get_repositories(project=self.project.id)
749783
git_repo = next((r for r in repos if r.name == self.__repo_name), None)
750784
if git_repo is None:
751-
raise ValueError(f"Unable to determine repository name from remote {self.__remote} url. Parsed repository name: {self.__repo_name}")
785+
raise ValueError(
786+
f"Unable to determine repository name from remote {self.__remote} url. Parsed repository name: {self.__repo_name}"
787+
)
752788
return git_repo
753789

754790
def set_url(self, url: str) -> None:
@@ -788,7 +824,9 @@ def get_pr_by_url(self, url: str) -> AzureDevopsPullRequest | None:
788824
return self.find_pr_by_id(slug, resource_id)
789825

790826
def find_pr_by_id(self, slug: str, pr_id: int) -> AzureDevopsPullRequest | None:
791-
pr = self.git_client.get_pull_request(repository_id=self.repo.id, pull_request_id=pr_id, project=self.project.id)
827+
pr = self.git_client.get_pull_request(
828+
repository_id=self.repo.id, pull_request_id=pr_id, project=self.project.id
829+
)
792830
return AzureDevopsPullRequest(pr, self.git_client, self.__pr_resource_html_url())
793831

794832
def find_prs(
@@ -817,9 +855,7 @@ def find_prs(
817855
**kwargs,
818856
)
819857
pr_instances = self.git_client.get_pull_requests(
820-
project=self.project.id,
821-
repository_id=self.repo.id,
822-
search_criteria=git_pr_search
858+
project=self.project.id, repository_id=self.repo.id, search_criteria=git_pr_search
823859
)
824860
page_list.append(pr_instances)
825861

@@ -854,4 +890,3 @@ def create_issue_comment(
854890
self, slug: str, issue_text: str, title: str | None = None, issue_id: int | None = None
855891
) -> str:
856892
...
857-

patchwork/common/client/sonar.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from collections import defaultdict
2+
from dataclasses import dataclass
23
from typing import Optional, Union
34

45
import requests
5-
from dataclasses import dataclass
6+
67

78
@dataclass
89
class SonarVuln:
@@ -65,7 +66,12 @@ def _find_hotspots(self, project_key: str):
6566

6667
headers = {"Authorization": f"Bearer {self._access_token}"}
6768
# Define the parameters for Hotspot API request
68-
params: dict[str, Union[str, int]] = {"p": page, "ps": page_size, "projectKey": project_key, "status": "TO_REVIEW"}
69+
params: dict[str, Union[str, int]] = {
70+
"p": page,
71+
"ps": page_size,
72+
"projectKey": project_key,
73+
"status": "TO_REVIEW",
74+
}
6975

7076
url = self._url + self.__hotspot_path
7177

@@ -146,4 +152,4 @@ def find_issues(self, project_key: str):
146152
start=issue["textRange"]["startLine"],
147153
end=issue["textRange"]["endLine"],
148154
)
149-
yield path, vuln
155+
yield path, vuln

0 commit comments

Comments
 (0)