runapi-core 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,46 @@
1
+ Metadata-Version: 2.4
2
+ Name: runapi-core
3
+ Version: 0.1.0
4
+ Summary: Core module for the RunAPI Python SDK
5
+ Project-URL: Homepage, https://runapi.ai
6
+ Project-URL: Documentation, https://runapi.ai/docs#sdk
7
+ Author-email: RunAPI <contact@runapi.ai>
8
+ License-Expression: Apache-2.0
9
+ Keywords: ai,api,runapi,sdk
10
+ Requires-Python: >=3.9
11
+ Requires-Dist: httpx>=0.27
12
+ Description-Content-Type: text/markdown
13
+
14
+ # RunAPI Core Python SDK
15
+
16
+ The RunAPI Core Python SDK provides shared authentication, HTTP, retry, error, and polling primitives for RunAPI model packages. Install `runapi-core` only when you are building SDK infrastructure or shared Python tooling; application code should normally install a concrete model package such as `runapi-flux-2`.
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ pip install runapi-core
22
+ ```
23
+
24
+ ## Notes
25
+
26
+ Use the core package for common client options, error classes, request helpers, file uploads, and task polling behavior that model SDKs share. Configure it globally or per client:
27
+
28
+ ```python
29
+ import runapi.core as runapi
30
+
31
+ runapi.configure(api_key="sk-...") # or set RUNAPI_API_KEY in the environment
32
+ ```
33
+
34
+ ```python
35
+ from runapi.core import FilesClient
36
+
37
+ files = FilesClient() # reads RUNAPI_API_KEY, or pass api_key="sk-..."
38
+ uploaded = files.create(file="./input.png")
39
+ print(uploaded.url)
40
+ ```
41
+
42
+ Public SDK docs live at https://runapi.ai/docs#runapi-sdks and the model catalog lives at https://runapi.ai/models.
43
+
44
+ ## License
45
+
46
+ Licensed under the Apache License, Version 2.0.
@@ -0,0 +1,33 @@
1
+ # RunAPI Core Python SDK
2
+
3
+ The RunAPI Core Python SDK provides shared authentication, HTTP, retry, error, and polling primitives for RunAPI model packages. Install `runapi-core` only when you are building SDK infrastructure or shared Python tooling; application code should normally install a concrete model package such as `runapi-flux-2`.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install runapi-core
9
+ ```
10
+
11
+ ## Notes
12
+
13
+ Use the core package for common client options, error classes, request helpers, file uploads, and task polling behavior that model SDKs share. Configure it globally or per client:
14
+
15
+ ```python
16
+ import runapi.core as runapi
17
+
18
+ runapi.configure(api_key="sk-...") # or set RUNAPI_API_KEY in the environment
19
+ ```
20
+
21
+ ```python
22
+ from runapi.core import FilesClient
23
+
24
+ files = FilesClient() # reads RUNAPI_API_KEY, or pass api_key="sk-..."
25
+ uploaded = files.create(file="./input.png")
26
+ print(uploaded.url)
27
+ ```
28
+
29
+ Public SDK docs live at https://runapi.ai/docs#runapi-sdks and the model catalog lives at https://runapi.ai/models.
30
+
31
+ ## License
32
+
33
+ Licensed under the Apache License, Version 2.0.
@@ -0,0 +1,30 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "runapi-core"
7
+ dynamic = ["version"]
8
+ description = "Core module for the RunAPI Python SDK"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "Apache-2.0"
12
+ authors = [{ name = "RunAPI", email = "contact@runapi.ai" }]
13
+ keywords = ["runapi", "ai", "sdk", "api"]
14
+ dependencies = ["httpx>=0.27"]
15
+
16
+ [project.urls]
17
+ Homepage = "https://runapi.ai"
18
+ Documentation = "https://runapi.ai/docs#sdk"
19
+
20
+ [tool.hatch.version]
21
+ path = "src/runapi/core/version.py"
22
+
23
+ [tool.hatch.build.targets.wheel]
24
+ packages = ["src/runapi"]
25
+
26
+ [tool.uv]
27
+ package = true
28
+
29
+ [dependency-groups]
30
+ dev = ["pytest>=8", "httpx>=0.27"]
@@ -0,0 +1,71 @@
1
+ """RunAPI Python SDK — shared core.
2
+
3
+ Configuration, errors, models, HTTP transport, polling, and the file upload
4
+ client shared by every per-model-line package.
5
+ """
6
+
7
+ from . import config, errors, polling
8
+ from .auth import resolve_api_key
9
+ from .config import configure
10
+ from .contract_gen import CONTRACT
11
+ from .errors import (
12
+ AuthenticationError,
13
+ ConflictError,
14
+ Error,
15
+ InsufficientCreditsError,
16
+ NetworkError,
17
+ NotFoundError,
18
+ RateLimitError,
19
+ ServerError,
20
+ ServiceUnavailableError,
21
+ TaskFailedError,
22
+ TaskTimeoutError,
23
+ TimeoutError,
24
+ ValidationError,
25
+ error_from_response,
26
+ )
27
+ from .files import FilesClient, UploadResponse
28
+ from .http_client import HttpClient
29
+ from .models import BaseModel, DynamicModel, TaskResponse, optional, required
30
+ from .multipart import MultipartBody, MultipartFile
31
+ from .options import ClientOptions, PollingOptions, RequestOptions
32
+ from .resource import Resource
33
+ from .version import __version__
34
+
35
+ __all__ = [
36
+ "__version__",
37
+ "config",
38
+ "configure",
39
+ "errors",
40
+ "polling",
41
+ "CONTRACT",
42
+ "resolve_api_key",
43
+ "Error",
44
+ "AuthenticationError",
45
+ "InsufficientCreditsError",
46
+ "NotFoundError",
47
+ "ConflictError",
48
+ "ValidationError",
49
+ "RateLimitError",
50
+ "ServiceUnavailableError",
51
+ "ServerError",
52
+ "NetworkError",
53
+ "TimeoutError",
54
+ "TaskTimeoutError",
55
+ "TaskFailedError",
56
+ "error_from_response",
57
+ "ClientOptions",
58
+ "RequestOptions",
59
+ "PollingOptions",
60
+ "BaseModel",
61
+ "DynamicModel",
62
+ "TaskResponse",
63
+ "required",
64
+ "optional",
65
+ "MultipartBody",
66
+ "MultipartFile",
67
+ "HttpClient",
68
+ "Resource",
69
+ "FilesClient",
70
+ "UploadResponse",
71
+ ]
@@ -0,0 +1,36 @@
1
+ """API key resolution."""
2
+
3
+ import os
4
+ from typing import Optional
5
+
6
+ from . import config
7
+ from .errors import AuthenticationError
8
+
9
+ ENV_VAR_NAME = "RUNAPI_API_KEY"
10
+
11
+ MISSING_KEY_MESSAGE = (
12
+ "API key is required. Pass api_key or set the RUNAPI_API_KEY environment variable."
13
+ )
14
+
15
+
16
+ def resolve_api_key(explicit: Optional[str] = None) -> str:
17
+ """Resolve the API key, in priority order:
18
+
19
+ 1. the explicit argument
20
+ 2. the global ``runapi.core`` configuration (``config.api_key``)
21
+ 3. the ``RUNAPI_API_KEY`` environment variable
22
+
23
+ All sources are trimmed; blank values are treated as missing. Raises
24
+ :class:`AuthenticationError` when no source yields a value.
25
+ """
26
+ resolved = _normalize(explicit) or _normalize(config.api_key) or _normalize(os.environ.get(ENV_VAR_NAME))
27
+ if not resolved:
28
+ raise AuthenticationError(MISSING_KEY_MESSAGE)
29
+ return resolved
30
+
31
+
32
+ def _normalize(value: Optional[str]) -> Optional[str]:
33
+ if not isinstance(value, str):
34
+ return None
35
+ trimmed = value.strip()
36
+ return trimmed or None
@@ -0,0 +1,23 @@
1
+ """Module-level configuration shared across RunAPI clients.
2
+
3
+ Mirrors Ruby's global ``RunApi.api_key`` / ``RunApi.base_url``. Values are read
4
+ at request time, so ``configure()`` (or assigning these attributes directly)
5
+ affects clients constructed afterwards.
6
+ """
7
+
8
+ import sys
9
+ from typing import Optional
10
+
11
+ from .constants import DEFAULT_BASE_URL
12
+
13
+ api_key: Optional[str] = None
14
+ base_url: str = DEFAULT_BASE_URL
15
+
16
+
17
+ def configure(api_key: Optional[str] = None, base_url: Optional[str] = None) -> None:
18
+ """Set global configuration. Only non-None arguments are applied."""
19
+ module = sys.modules[__name__]
20
+ if api_key is not None:
21
+ module.api_key = api_key
22
+ if base_url is not None:
23
+ module.base_url = base_url
@@ -0,0 +1,17 @@
1
+ from .version import __version__
2
+
3
+ HTTP_REQUEST_TIMEOUT = 900
4
+ POLLING_INTERVAL = 2
5
+ POLLING_MAX_WAIT = 900
6
+
7
+ MAX_RETRIES = 2
8
+ RETRY_BASE_DELAY = 0.5
9
+ RETRY_MAX_DELAY = 5.0
10
+
11
+ DEFAULT_BASE_URL = "https://runapi.ai"
12
+
13
+ SDK_USER_AGENT = f"runapi-sdk-python/{__version__}"
14
+
15
+ IDEMPOTENT_METHODS = frozenset({"GET", "HEAD", "PUT", "DELETE", "OPTIONS"})
16
+
17
+ RETRYABLE_STATUS_CODES = frozenset({429, 500, 502, 503, 504})