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:
Kevin Turcios 2026-04-21 01:08:17 -05:00
parent cf67686b29
commit 31cdba9e3b
5 changed files with 70 additions and 28 deletions

View file

@ -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(

View file

@ -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,

View file

@ -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.

View file

@ -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",

View file

@ -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