diff --git a/litellm/proxy/management_endpoints/roi_calculator_endpoints.py b/litellm/proxy/management_endpoints/roi_calculator_endpoints.py index 7d53f991844..e04ae75c87d 100644 --- a/litellm/proxy/management_endpoints/roi_calculator_endpoints.py +++ b/litellm/proxy/management_endpoints/roi_calculator_endpoints.py @@ -171,11 +171,7 @@ def _public_settings(settings: ROISettings) -> ROISettingsResponse: has_github_token=bool(settings.github_token.get_secret_value()), default_prompt=DEFAULT_PROMPT, available_models=models, - ready=bool( - settings.repos - and settings.estimator_model - and settings.estimator_model in models - ), + ready=bool(settings.repos and settings.estimator_model and settings.estimator_model in models), ) @@ -251,9 +247,7 @@ async def update_roi_calculator_settings( current: Final = await _load_settings(repository) if "github_api_url" in patch.model_fields_set and patch.github_api_url is None: raise HTTPException(status_code=422, detail="GitHub API URL cannot be null.") - github_api_url: Final = ( - patch.github_api_url if patch.github_api_url is not None else current.github_api_url - ) + github_api_url: Final = patch.github_api_url if patch.github_api_url is not None else current.github_api_url github_url_changed: Final = github_api_url.rstrip("/") != current.github_api_url.rstrip("/") token_was_supplied: Final = "github_token" in patch.model_fields_set plaintext_token, encrypted_token = ( @@ -273,19 +267,11 @@ async def update_roi_calculator_settings( github_api_url=github_api_url, github_token=SecretStr(plaintext_token), repos=patch.repos if patch.repos is not None else current.repos, - estimator_model=( - patch.estimator_model - if patch.estimator_model is not None - else current.estimator_model - ), + estimator_model=(patch.estimator_model if patch.estimator_model is not None else current.estimator_model), estimator_prompt=( - patch.estimator_prompt - if patch.estimator_prompt is not None - else current.estimator_prompt - ), - backfill_days=( - patch.backfill_days if patch.backfill_days is not None else current.backfill_days + patch.estimator_prompt if patch.estimator_prompt is not None else current.estimator_prompt ), + backfill_days=(patch.backfill_days if patch.backfill_days is not None else current.backfill_days), identity_map=current.identity_map, ) except ValidationError as exc: @@ -315,8 +301,7 @@ async def get_roi_calculator_repositories( await github.close() return ROIRepositoriesResponse( repositories=tuple( - ROIRepository(name=name, visibility=visibility, archived=archived) - for name, visibility, archived in repos + ROIRepository(name=name, visibility=visibility, archived=archived) for name, visibility, archived in repos ), page=page, has_more=has_more, @@ -403,11 +388,7 @@ async def update_roi_calculator_identity_map( if not login or (update.email is not None and not new_email): raise HTTPException(status_code=422, detail="Enter a GitHub login and a valid email address.") identity_map: Final[Mapping[str, str]] = MappingProxyType( - { - key: value - for key, value in current.identity_map.items() - if update.email is None and key != login - } + {key: value for key, value in current.identity_map.items() if update.email is None and key != login} if update.email is None else {**current.identity_map, login: new_email} ) diff --git a/litellm/proxy/roi_calculator/analytics.py b/litellm/proxy/roi_calculator/analytics.py index 4dfc99a2313..d4bf6361dd4 100644 --- a/litellm/proxy/roi_calculator/analytics.py +++ b/litellm/proxy/roi_calculator/analytics.py @@ -32,9 +32,7 @@ def match_identity( if mapped: return normalize_email(mapped), "manual" candidates: Final = frozenset( - address - for address in (normalize_email(candidate) for candidate in pull["emails"]) - if address + address for address in (normalize_email(candidate) for candidate in pull["emails"]) if address ) matched: Final = candidates & observed_emails if len(matched) == 1: @@ -84,32 +82,22 @@ def _summarize_person( pulls: tuple[tuple[ROIPullRecord, str, str], ...], ) -> ROIPersonSummary: spend_rows: Final = tuple( - row - for row in spend - if _person_key(normalize_email(row["email"]), "gateway:" + row["user_id"]) == key + row for row in spend if _person_key(normalize_email(row["email"]), "gateway:" + row["user_id"]) == key ) person_pulls: Final = tuple( - pull - for pull in pulls - if _person_key(pull[1], "github:" + pull[0]["login"].casefold()) == key + pull for pull in pulls if _person_key(pull[1], "github:" + pull[0]["login"].casefold()) == key ) addresses: Final = tuple(normalize_email(row["email"]) for row in spend_rows if row["email"]) person_email: Final = addresses[0] if addresses else (person_pulls[0][1] if person_pulls else "") spend_total: Final[float | None] = sum(row["spend"] for row in spend_rows) if spend_rows else None login_values: Final = tuple(pull[0]["login"] for pull in person_pulls) - logins: Final = tuple( - login for index, login in enumerate(login_values) if login not in login_values[:index] - ) + logins: Final = tuple(login for index, login in enumerate(login_values) if login not in login_values[:index]) method_values: Final = tuple(pull[2] for pull in person_pulls) - methods: Final = tuple( - method for index, method in enumerate(method_values) if method not in method_values[:index] - ) + methods: Final = tuple(method for index, method in enumerate(method_values) if method not in method_values[:index]) estimates: Final = tuple(pull[0]["estimate"] for pull in person_pulls) estimated_count: Final = sum(estimate["status"] == "estimated" for estimate in estimates) pending_count: Final = len(estimates) - estimated_count - hours: Final = sum( - estimate["hours"] or 0.0 for estimate in estimates if estimate["status"] == "estimated" - ) + hours: Final = sum(estimate["hours"] or 0.0 for estimate in estimates if estimate["status"] == "estimated") eligible: Final = spend_total is not None and estimated_count > 0 and pending_count == 0 return ROIPersonSummary( id=key, @@ -128,20 +116,16 @@ def _summarize_person( def summarize(report: ROIReport, mappings: Mapping[str, str]) -> ROISummary: observed: Final = frozenset( - normalized - for normalized in (normalize_email(row["email"]) for row in report["spend"]) - if normalized + normalized for normalized in (normalize_email(row["email"]) for row in report["spend"]) if normalized ) matched_pulls: Final[tuple[tuple[ROIPullRecord, str, str], ...]] = tuple( (pull, *match_identity(pull, observed, mappings)) for pull in report["pulls"] ) gateway_people: Final = frozenset( - _person_key(normalize_email(row["email"]), "gateway:" + row["user_id"]) - for row in report["spend"] + _person_key(normalize_email(row["email"]), "gateway:" + row["user_id"]) for row in report["spend"] ) github_people: Final = frozenset( - _person_key(address, "github:" + pull["login"].casefold()) - for pull, address, _ in matched_pulls + _person_key(address, "github:" + pull["login"].casefold()) for pull, address, _ in matched_pulls ) people_keys: Final = gateway_people | github_people people: Final = tuple( @@ -178,8 +162,7 @@ def summarize(report: ROIReport, mappings: Mapping[str, str]) -> ROISummary: and pull["estimate"]["status"] == "estimated" ), prs=sum( - pull["email"] in eligible_emails - and pull["estimate"]["status"] == "estimated" + pull["email"] in eligible_emails and pull["estimate"]["status"] == "estimated" for pull in pull_summaries if pull["merged_at"][:10] == day ), @@ -206,12 +189,8 @@ def summarize(report: ROIReport, mappings: Mapping[str, str]) -> ROISummary: people_with_prs=sum(person["prs"] > 0 for person in people), pending_prs=sum(person["pending_prs"] for person in people), ) - summary_people: Final = tuple( - sorted(people, key=lambda person: (-person["hours"], person["id"])) - ) - summary_pulls: Final = tuple( - sorted(pull_summaries, key=lambda pull: pull["merged_at"], reverse=True) - ) + summary_people: Final = tuple(sorted(people, key=lambda person: (-person["hours"], person["id"]))) + summary_pulls: Final = tuple(sorted(pull_summaries, key=lambda pull: pull["merged_at"], reverse=True)) return ROISummary( id=report.get("id"), mode=report["mode"], diff --git a/litellm/proxy/roi_calculator/estimator.py b/litellm/proxy/roi_calculator/estimator.py index 67d97e41f24..b811de77dd6 100644 --- a/litellm/proxy/roi_calculator/estimator.py +++ b/litellm/proxy/roi_calculator/estimator.py @@ -123,18 +123,14 @@ class Estimator: missing_metadata_estimate: Final[ROIEstimate] = { "status": "needs_review", "hours": None, - "reasoning": ( - "GitHub did not provide all file or commit metadata. It was not sent for estimation." - ), + "reasoning": ("GitHub did not provide all file or commit metadata. It was not sent for estimation."), } return missing_metadata_estimate if len(evidence) > MAX_EVIDENCE_CHARS: oversized_evidence_estimate: Final[ROIEstimate] = { "status": "needs_review", "hours": None, - "reasoning": ( - "This PR exceeds the estimator's input limit. It was not truncated or scored." - ), + "reasoning": ("This PR exceeds the estimator's input limit. It was not truncated or scored."), } return oversized_evidence_estimate system_message: Final[ROICompletionMessage] = { diff --git a/litellm/proxy/roi_calculator/github.py b/litellm/proxy/roi_calculator/github.py index a947135533a..cfb5b4608d5 100644 --- a/litellm/proxy/roi_calculator/github.py +++ b/litellm/proxy/roi_calculator/github.py @@ -175,12 +175,8 @@ class _GraphQLPayload(TypedDict): variables: ReadOnly[_GraphQLVariables] -_REPOSITORIES: Final[TypeAdapter[tuple[_RepositoryItem, ...]]] = TypeAdapter( - tuple[_RepositoryItem, ...] -) -_PULLS: Final[TypeAdapter[tuple[GitHubPullListItem, ...]]] = TypeAdapter( - tuple[GitHubPullListItem, ...] -) +_REPOSITORIES: Final[TypeAdapter[tuple[_RepositoryItem, ...]]] = TypeAdapter(tuple[_RepositoryItem, ...]) +_PULLS: Final[TypeAdapter[tuple[GitHubPullListItem, ...]]] = TypeAdapter(tuple[GitHubPullListItem, ...]) _PULL_FILES: Final[TypeAdapter[tuple[_PullFile, ...]]] = TypeAdapter(tuple[_PullFile, ...]) _REST_COMMITS: Final[TypeAdapter[tuple[_RestCommit, ...]]] = TypeAdapter(tuple[_RestCommit, ...]) _GRAPHQL_RESPONSE: Final = TypeAdapter(_GraphQLResponse) @@ -332,9 +328,7 @@ class GitHub: ), ) try: - repositories: Final[tuple[_RepositoryItem, ...]] = _REPOSITORIES.validate_python( - response.json() - ) + repositories: Final[tuple[_RepositoryItem, ...]] = _REPOSITORIES.validate_python(response.json()) except Exception: raise SourceError("GitHub returned an unexpected repository list.") from None filtered: Final = tuple( @@ -393,11 +387,7 @@ class GitHub: address for address in ( profile_email, - *( - normalize_email(author[1]) - for author in authors - if author[0].casefold() == login.casefold() - ), + *(normalize_email(author[1]) for author in authors if author[0].casefold() == login.casefold()), ) if address ) @@ -437,6 +427,7 @@ class GitHub: self, repo: str, number: int, detail: _PullDetail ) -> tuple[tuple[ROIPullCommit, ...], tuple[tuple[str, str], ...], int]: if not self.client.headers.get("Authorization"): + async def commit_pages() -> AsyncIterator[_RestCommit]: async for page in _pages( self.client, @@ -448,9 +439,7 @@ class GitHub: yield item rest_commits: Final = await _collect(commit_pages()) - commits: Final[tuple[ROIPullCommit, ...]] = tuple( - _rest_commit_evidence(item) for item in rest_commits - ) + commits: Final[tuple[ROIPullCommit, ...]] = tuple(_rest_commit_evidence(item) for item in rest_commits) authors: Final = tuple( ( item.author.login if item.author and item.author.login else "", diff --git a/litellm/types/roi_calculator.py b/litellm/types/roi_calculator.py index 9ffc63a38de..b57a169c0c8 100644 --- a/litellm/types/roi_calculator.py +++ b/litellm/types/roi_calculator.py @@ -47,13 +47,9 @@ class ROISettings(BaseModel): def validate_repositories(cls, values: tuple[str, ...]) -> tuple[str, ...]: import re - normalized_values: Final = tuple( - repo.strip().rstrip("/").removesuffix(".git") for repo in values - ) + normalized_values: Final = tuple(repo.strip().rstrip("/").removesuffix(".git") for repo in values) normalized: Final = tuple( - repo - for index, repo in enumerate(normalized_values) - if repo not in normalized_values[:index] + repo for index, repo in enumerate(normalized_values) if repo not in normalized_values[:index] ) invalid_repositories: Final = tuple( repo @@ -84,8 +80,7 @@ class ROISettings(BaseModel): { login.strip().casefold(): normalize_email(address) for login, address in values.items() - if re.fullmatch(r"[A-Za-z0-9_\[\]-]+", login.strip()) is not None - and normalize_email(address) + if re.fullmatch(r"[A-Za-z0-9_\[\]-]+", login.strip()) is not None and normalize_email(address) } ) if len(normalized) != len(values):