mirror of
https://github.com/codeflash-ai/codeflash-agent.git
synced 2026-05-04 18:25:19 +00:00
Defer heavy third-party imports in codeflash-core to cut import time 68%
Move requests, gitpython, sentry-sdk, and posthog imports from module level into the functions that use them. This drops `import codeflash_core` from ~230ms to ~74ms, making it viable for lightweight consumers (e.g. the project detector) to depend on core submodules without blowing startup budgets. - _telemetry: defer sentry_sdk + posthog into init functions (20ms → 0.2ms) - _git: use PEP 562 __getattr__ for lazy git import (59ms → 4ms) - _platform: defer requests + sentry_sdk into methods (55ms → 1ms) - _client: defer requests into post() method (72ms → 34ms) - _http: add shared _make_session() factory for deferred Session creation
This commit is contained in:
parent
cf67686b29
commit
31cdba9e3b
5 changed files with 70 additions and 28 deletions
|
|
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||
import contextlib
|
||||
import sys
|
||||
import uuid
|
||||
from typing import Any
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
from typing import Self
|
||||
|
|
@ -13,15 +13,22 @@ else:
|
|||
from typing_extensions import Self
|
||||
|
||||
import attrs
|
||||
import requests
|
||||
|
||||
from ._http import _resolve_api_key, _resolve_base_url, _strip_trailing_slash
|
||||
from ._http import (
|
||||
_make_session,
|
||||
_resolve_api_key,
|
||||
_resolve_base_url,
|
||||
_strip_trailing_slash,
|
||||
)
|
||||
from ._model import Candidate, OptimizationRequest, OptimizationReviewResult
|
||||
from .exceptions import (
|
||||
AIServiceConnectionError,
|
||||
AIServiceError,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import requests as requests_types
|
||||
|
||||
|
||||
@attrs.define
|
||||
class AIClient:
|
||||
|
|
@ -43,9 +50,9 @@ class AIClient:
|
|||
alias="timeout",
|
||||
default=120.0,
|
||||
)
|
||||
_session: requests.Session = attrs.field(
|
||||
_session: requests_types.Session = attrs.field(
|
||||
init=False,
|
||||
factory=requests.Session,
|
||||
factory=_make_session,
|
||||
)
|
||||
|
||||
def __attrs_post_init__(self) -> None:
|
||||
|
|
@ -72,6 +79,8 @@ class AIClient:
|
|||
service endpoints. *endpoint* should start with ``/``
|
||||
(e.g. ``/optimize``, ``/rank``).
|
||||
"""
|
||||
import requests # noqa: PLC0415
|
||||
|
||||
url = f"{self._base_url}/ai{endpoint}"
|
||||
try:
|
||||
resp = self._session.post(
|
||||
|
|
|
|||
|
|
@ -6,22 +6,36 @@ import logging
|
|||
import sys
|
||||
import time
|
||||
from functools import cache
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import git
|
||||
from types import ModuleType
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Callable
|
||||
|
||||
import git as git_types
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
git: ModuleType
|
||||
|
||||
|
||||
def __getattr__(name: str) -> Any:
|
||||
"""Lazy import for the ``git`` package."""
|
||||
if name == "git":
|
||||
import git as _git # noqa: PLC0415
|
||||
|
||||
globals()["git"] = _git
|
||||
return _git
|
||||
msg = f"module {__name__!r} has no attribute {name!r}"
|
||||
raise AttributeError(msg)
|
||||
|
||||
|
||||
def get_remote_url(
|
||||
repo: git.Repo | None = None,
|
||||
repo: git_types.Repo | None = None,
|
||||
git_remote: str = "origin",
|
||||
) -> str:
|
||||
"""Return the URL of the given git remote."""
|
||||
repository: git.Repo = repo or git.Repo(
|
||||
repository: git_types.Repo = repo or git.Repo(
|
||||
search_parent_directories=True,
|
||||
)
|
||||
return repository.remote(name=git_remote).url
|
||||
|
|
@ -29,7 +43,7 @@ def get_remote_url(
|
|||
|
||||
@cache
|
||||
def get_repo_owner_and_name(
|
||||
repo: git.Repo | None = None,
|
||||
repo: git_types.Repo | None = None,
|
||||
git_remote: str = "origin",
|
||||
) -> tuple[str, str]:
|
||||
"""Return (owner, repo_name) parsed from the git remote URL."""
|
||||
|
|
@ -61,7 +75,7 @@ def check_running_in_git_repo(module_root: str) -> bool:
|
|||
|
||||
|
||||
def check_and_push_branch(
|
||||
repo: git.Repo,
|
||||
repo: git_types.Repo,
|
||||
git_remote: str = "origin",
|
||||
*,
|
||||
wait_for_push: bool = False,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
from .exceptions import InvalidAPIKeyError
|
||||
|
||||
|
|
@ -36,6 +37,13 @@ def _strip_trailing_slash(url: str) -> str:
|
|||
return url.rstrip("/")
|
||||
|
||||
|
||||
def _make_session() -> Any:
|
||||
"""Create a ``requests.Session`` with a deferred import."""
|
||||
import requests # noqa: PLC0415
|
||||
|
||||
return requests.Session()
|
||||
|
||||
|
||||
def _resolve_api_key() -> str:
|
||||
"""
|
||||
Read and validate *CODEFLASH_API_KEY* from the environment.
|
||||
|
|
|
|||
|
|
@ -14,10 +14,9 @@ else:
|
|||
from typing_extensions import Self
|
||||
|
||||
import attrs
|
||||
import requests
|
||||
import sentry_sdk
|
||||
|
||||
from ._http import (
|
||||
_make_session,
|
||||
_resolve_api_key,
|
||||
_resolve_cfapi_base_url,
|
||||
_strip_trailing_slash,
|
||||
|
|
@ -29,6 +28,8 @@ from .exceptions import (
|
|||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import requests as requests_types
|
||||
|
||||
from ._model import FileDiffContent, PrComment
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
|
@ -53,7 +54,6 @@ def parse_repo_owner_and_name(remote_url: str) -> tuple[str, str]:
|
|||
url = remote_url.removesuffix(".git").rstrip("/")
|
||||
parts = url.split("/")
|
||||
owner_part, repo_name = parts[-2], parts[-1]
|
||||
# SSH URLs use "git@host:owner/repo" — split on ":" to isolate owner
|
||||
owner = owner_part.split(":")[1] if ":" in owner_part else owner_part
|
||||
return owner, repo_name
|
||||
|
||||
|
|
@ -80,9 +80,9 @@ class PlatformClient:
|
|||
alias="timeout",
|
||||
default=60.0,
|
||||
)
|
||||
_session: requests.Session = attrs.field(
|
||||
_session: requests_types.Session = attrs.field(
|
||||
init=False,
|
||||
factory=requests.Session,
|
||||
factory=_make_session,
|
||||
)
|
||||
|
||||
def __attrs_post_init__(self) -> None:
|
||||
|
|
@ -108,6 +108,8 @@ class PlatformClient:
|
|||
|
||||
def get_user_id(self) -> str | None:
|
||||
"""Fetch the current user's ID from the Codeflash API."""
|
||||
import requests # noqa: PLC0415
|
||||
|
||||
try:
|
||||
resp = self._session.get(
|
||||
f"{self._base_url}/cfapi/cli-get-user",
|
||||
|
|
@ -134,6 +136,8 @@ class PlatformClient:
|
|||
success. Network errors are re-raised as
|
||||
:class:`AIServiceConnectionError`.
|
||||
"""
|
||||
import requests # noqa: PLC0415
|
||||
|
||||
try:
|
||||
resp = self._session.get(
|
||||
f"{self._base_url}/cfapi/cli-get-user",
|
||||
|
|
@ -177,8 +181,10 @@ class PlatformClient:
|
|||
params: dict[str, Any] | None = None,
|
||||
*,
|
||||
suppress_errors: bool = False,
|
||||
) -> requests.Response:
|
||||
) -> requests_types.Response:
|
||||
"""Make an HTTP request to the platform API."""
|
||||
import requests # noqa: PLC0415
|
||||
|
||||
url = f"{self._base_url}/cfapi{endpoint}"
|
||||
try:
|
||||
if method.upper() == "POST":
|
||||
|
|
@ -245,6 +251,8 @@ class PlatformClient:
|
|||
"Server error getting blocklisted functions: %s",
|
||||
resp.status_code,
|
||||
)
|
||||
import sentry_sdk # noqa: PLC0415
|
||||
|
||||
sentry_sdk.capture_message(
|
||||
f"Server error in verify-existing-optimizations: {resp.status_code}",
|
||||
)
|
||||
|
|
@ -262,6 +270,8 @@ class PlatformClient:
|
|||
}
|
||||
except Exception as exc:
|
||||
log.exception("Error getting blocklisted functions")
|
||||
import sentry_sdk # noqa: PLC0415
|
||||
|
||||
sentry_sdk.capture_exception(exc)
|
||||
return {}
|
||||
|
||||
|
|
@ -382,7 +392,7 @@ class PlatformClient:
|
|||
optimization_review: str = "",
|
||||
original_line_profiler: str | None = None,
|
||||
optimized_line_profiler: str | None = None,
|
||||
) -> requests.Response:
|
||||
) -> requests_types.Response:
|
||||
"""Suggest changes to an existing pull request."""
|
||||
payload: dict[str, Any] = {
|
||||
"owner": owner,
|
||||
|
|
@ -418,7 +428,7 @@ class PlatformClient:
|
|||
optimization_review: str = "",
|
||||
original_line_profiler: str | None = None,
|
||||
optimized_line_profiler: str | None = None,
|
||||
) -> requests.Response:
|
||||
) -> requests_types.Response:
|
||||
"""Create a new pull request with optimized code."""
|
||||
payload: dict[str, Any] = {
|
||||
"owner": owner,
|
||||
|
|
@ -452,7 +462,7 @@ class PlatformClient:
|
|||
optimization_review: str = "",
|
||||
original_line_profiler: str | None = None,
|
||||
optimized_line_profiler: str | None = None,
|
||||
) -> requests.Response:
|
||||
) -> requests_types.Response:
|
||||
"""Create a staging pull request."""
|
||||
payload: dict[str, Any] = {
|
||||
"baseBranch": base_branch,
|
||||
|
|
@ -476,7 +486,7 @@ class PlatformClient:
|
|||
repo: str,
|
||||
base_branch: str,
|
||||
workflow_content: str,
|
||||
) -> requests.Response:
|
||||
) -> requests_types.Response:
|
||||
"""Set up GitHub Actions by creating a PR with a workflow file."""
|
||||
return self._request(
|
||||
"/setup-github-actions",
|
||||
|
|
|
|||
|
|
@ -5,15 +5,10 @@ from __future__ import annotations
|
|||
import logging
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import sentry_sdk
|
||||
from posthog import Posthog
|
||||
from sentry_sdk.integrations.logging import LoggingIntegration
|
||||
from sentry_sdk.integrations.stdlib import StdlibIntegration
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ._platform import PlatformClient
|
||||
|
||||
_posthog: Posthog | None = None
|
||||
_posthog: Any = None
|
||||
_user_id: str | None = None
|
||||
_version: str | None = None
|
||||
|
||||
|
|
@ -59,6 +54,10 @@ def ph(event: str, properties: dict[str, Any] | None = None) -> None:
|
|||
|
||||
def _init_sentry(*, exclude_errors: bool = False) -> None:
|
||||
"""Configure and initialize the Sentry SDK."""
|
||||
import sentry_sdk # noqa: PLC0415
|
||||
from sentry_sdk.integrations.logging import LoggingIntegration # noqa: PLC0415
|
||||
from sentry_sdk.integrations.stdlib import StdlibIntegration # noqa: PLC0415
|
||||
|
||||
sentry_logging = LoggingIntegration(
|
||||
level=logging.INFO,
|
||||
event_level=logging.CRITICAL if exclude_errors else logging.ERROR,
|
||||
|
|
@ -83,6 +82,8 @@ def _init_posthog(
|
|||
version: str = "",
|
||||
) -> None:
|
||||
"""Configure and initialize the PostHog analytics client."""
|
||||
from posthog import Posthog # noqa: PLC0415
|
||||
|
||||
global _posthog, _user_id, _version # noqa: PLW0603
|
||||
_user_id = user_id
|
||||
_version = version
|
||||
|
|
|
|||
Loading…
Reference in a new issue