python-open-router 0.1.0__tar.gz → 0.3.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.
- {python_open_router-0.1.0 → python_open_router-0.3.0}/PKG-INFO +2 -4
- {python_open_router-0.1.0 → python_open_router-0.3.0}/pyproject.toml +15 -16
- python_open_router-0.3.0/src/python_open_router/__init__.py +39 -0
- python_open_router-0.3.0/src/python_open_router/models.py +146 -0
- {python_open_router-0.1.0 → python_open_router-0.3.0}/src/python_open_router/open_router.py +29 -2
- python_open_router-0.1.0/src/python_open_router/__init__.py +0 -15
- python_open_router-0.1.0/src/python_open_router/models.py +0 -25
- {python_open_router-0.1.0 → python_open_router-0.3.0}/LICENSE.md +0 -0
- {python_open_router-0.1.0 → python_open_router-0.3.0}/README.md +0 -0
- {python_open_router-0.1.0 → python_open_router-0.3.0}/src/python_open_router/exceptions.py +0 -0
- {python_open_router-0.1.0 → python_open_router-0.3.0}/src/python_open_router/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: python_open_router
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Asynchronous Python client for Open Router.
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: OpenRouter,api,async,client
|
|
@@ -8,15 +8,13 @@ Author: Joost Lekkerkerker
|
|
|
8
8
|
Author-email: joostlek@outlook.com
|
|
9
9
|
Maintainer: Joost Lekkerkerker
|
|
10
10
|
Maintainer-email: joostlek@outlook.com
|
|
11
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.13,<4.0
|
|
12
12
|
Classifier: Development Status :: 5 - Production/Stable
|
|
13
13
|
Classifier: Framework :: AsyncIO
|
|
14
14
|
Classifier: Intended Audience :: Developers
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
16
|
Classifier: Natural Language :: English
|
|
17
17
|
Classifier: Programming Language :: Python :: 3
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
20
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
19
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
20
|
Requires-Dist: aiohttp (>=3.0.0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "python_open_router"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
description = "Asynchronous Python client for Open Router."
|
|
5
5
|
authors = ["Joost Lekkerkerker <joostlek@outlook.com>"]
|
|
6
6
|
maintainers = ["Joost Lekkerkerker <joostlek@outlook.com>"]
|
|
@@ -15,8 +15,6 @@ classifiers = [
|
|
|
15
15
|
"Framework :: AsyncIO",
|
|
16
16
|
"Intended Audience :: Developers",
|
|
17
17
|
"Natural Language :: English",
|
|
18
|
-
"Programming Language :: Python :: 3.11",
|
|
19
|
-
"Programming Language :: Python :: 3.12",
|
|
20
18
|
"Programming Language :: Python :: 3.13",
|
|
21
19
|
"Programming Language :: Python :: 3",
|
|
22
20
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
@@ -26,7 +24,7 @@ packages = [
|
|
|
26
24
|
]
|
|
27
25
|
|
|
28
26
|
[tool.poetry.dependencies]
|
|
29
|
-
python = "^3.
|
|
27
|
+
python = "^3.13"
|
|
30
28
|
aiohttp = ">=3.0.0"
|
|
31
29
|
yarl = ">=1.6.0"
|
|
32
30
|
mashumaro = "^3.11"
|
|
@@ -35,18 +33,18 @@ orjson = ">=3.9.0"
|
|
|
35
33
|
[tool.poetry.group.dev.dependencies]
|
|
36
34
|
codespell = "2.4.1"
|
|
37
35
|
covdefaults = "2.3.0"
|
|
38
|
-
coverage = {version = "7.
|
|
39
|
-
mypy = "1.
|
|
40
|
-
pre-commit = "4.
|
|
36
|
+
coverage = {version = "7.9.2", extras = ["toml"]}
|
|
37
|
+
mypy = "1.16.1"
|
|
38
|
+
pre-commit = "4.2.0"
|
|
41
39
|
pre-commit-hooks = "5.0.0"
|
|
42
|
-
pylint = "3.3.
|
|
43
|
-
pytest = "8.
|
|
44
|
-
pytest-asyncio = "0.
|
|
45
|
-
pytest-cov = "6.
|
|
46
|
-
ruff = "0.
|
|
47
|
-
safety = "3.
|
|
48
|
-
yamllint = "1.
|
|
49
|
-
syrupy = "4.
|
|
40
|
+
pylint = "3.3.7"
|
|
41
|
+
pytest = "8.4.1"
|
|
42
|
+
pytest-asyncio = "1.0.0"
|
|
43
|
+
pytest-cov = "6.2.1"
|
|
44
|
+
ruff = "0.12.2"
|
|
45
|
+
safety = "3.5.2"
|
|
46
|
+
yamllint = "1.37.1"
|
|
47
|
+
syrupy = "4.9.1"
|
|
50
48
|
aioresponses = "0.7.8"
|
|
51
49
|
|
|
52
50
|
[tool.poetry.urls]
|
|
@@ -55,6 +53,7 @@ Changelog = "https://github.com/joostlek/python-open-router/releases"
|
|
|
55
53
|
|
|
56
54
|
[tool.coverage.report]
|
|
57
55
|
show_missing = true
|
|
56
|
+
fail_under = 50
|
|
58
57
|
|
|
59
58
|
[tool.coverage.run]
|
|
60
59
|
plugins = ["covdefaults"]
|
|
@@ -65,7 +64,7 @@ source = ["python_open_router"]
|
|
|
65
64
|
# free to run mypy on Windows, Linux, or macOS and get consistent
|
|
66
65
|
# results.
|
|
67
66
|
platform = "linux"
|
|
68
|
-
python_version = "3.
|
|
67
|
+
python_version = "3.13"
|
|
69
68
|
|
|
70
69
|
# show error messages from unrelated files
|
|
71
70
|
follow_imports = "normal"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Asynchronous Python client for Open Router."""
|
|
2
|
+
|
|
3
|
+
from python_open_router.exceptions import (
|
|
4
|
+
OpenRouterAuthenticationError,
|
|
5
|
+
OpenRouterConnectionError,
|
|
6
|
+
OpenRouterError,
|
|
7
|
+
)
|
|
8
|
+
from python_open_router.models import (
|
|
9
|
+
CreatedKey,
|
|
10
|
+
CreateKeyDataWrapper,
|
|
11
|
+
Key,
|
|
12
|
+
KeyData,
|
|
13
|
+
KeyDataWrapper,
|
|
14
|
+
KeysDataWrapper,
|
|
15
|
+
Modality,
|
|
16
|
+
Model,
|
|
17
|
+
ModelArchitecture,
|
|
18
|
+
ModelsDataWrapper,
|
|
19
|
+
SupportedParameter,
|
|
20
|
+
)
|
|
21
|
+
from python_open_router.open_router import OpenRouterClient
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"CreateKeyDataWrapper",
|
|
25
|
+
"CreatedKey",
|
|
26
|
+
"Key",
|
|
27
|
+
"KeyData",
|
|
28
|
+
"KeyDataWrapper",
|
|
29
|
+
"KeysDataWrapper",
|
|
30
|
+
"Modality",
|
|
31
|
+
"Model",
|
|
32
|
+
"ModelArchitecture",
|
|
33
|
+
"ModelsDataWrapper",
|
|
34
|
+
"OpenRouterAuthenticationError",
|
|
35
|
+
"OpenRouterClient",
|
|
36
|
+
"OpenRouterConnectionError",
|
|
37
|
+
"OpenRouterError",
|
|
38
|
+
"SupportedParameter",
|
|
39
|
+
]
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""Models for OpenRouter."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from enum import StrEnum
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from mashumaro.mixins.orjson import DataClassORJSONMixin
|
|
11
|
+
|
|
12
|
+
_LOGGER = logging.getLogger(__package__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class KeyDataWrapper(DataClassORJSONMixin):
|
|
17
|
+
"""Wrapper for OpenRouter key data."""
|
|
18
|
+
|
|
19
|
+
data: KeyData
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class KeyData(DataClassORJSONMixin):
|
|
24
|
+
"""The OpenRouter key data."""
|
|
25
|
+
|
|
26
|
+
label: str
|
|
27
|
+
usage: int
|
|
28
|
+
is_provisioning_key: bool
|
|
29
|
+
limit_remaining: int | None
|
|
30
|
+
is_free_tier: bool
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass
|
|
34
|
+
class KeysDataWrapper(DataClassORJSONMixin):
|
|
35
|
+
"""Wrapper for OpenRouter key data."""
|
|
36
|
+
|
|
37
|
+
data: list[Key]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass
|
|
41
|
+
class CreateKeyDataWrapper(DataClassORJSONMixin):
|
|
42
|
+
"""Wrapper for OpenRouter key data."""
|
|
43
|
+
|
|
44
|
+
data: CreatedKey
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class Key(DataClassORJSONMixin):
|
|
49
|
+
"""The OpenRouter key data."""
|
|
50
|
+
|
|
51
|
+
hash: str
|
|
52
|
+
name: str
|
|
53
|
+
label: str
|
|
54
|
+
disabled: bool
|
|
55
|
+
limit: float
|
|
56
|
+
usage: float = 0.0
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass(kw_only=True)
|
|
60
|
+
class CreatedKey(Key):
|
|
61
|
+
"""Created key."""
|
|
62
|
+
|
|
63
|
+
key: str
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass
|
|
67
|
+
class ModelsDataWrapper(DataClassORJSONMixin):
|
|
68
|
+
"""Wrapper for OpenRouter model data."""
|
|
69
|
+
|
|
70
|
+
data: list[Model]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class SupportedParameter(StrEnum):
|
|
74
|
+
"""Supported parameters for models."""
|
|
75
|
+
|
|
76
|
+
TEMPERATURE = "temperature"
|
|
77
|
+
TOP_P = "top_p"
|
|
78
|
+
MAX_TOKENS = "max_tokens"
|
|
79
|
+
REASONING = "reasoning"
|
|
80
|
+
INCLUDE_REASONING = "include_reasoning"
|
|
81
|
+
STOP = "stop"
|
|
82
|
+
TOK_K = "top_k"
|
|
83
|
+
SEED = "seed"
|
|
84
|
+
RESPONSE_FORMAT = "response_format"
|
|
85
|
+
TOOLS = "tools"
|
|
86
|
+
TOOL_CHOICE = "tool_choice"
|
|
87
|
+
FREQUENCY_PENALTY = "frequency_penalty"
|
|
88
|
+
PRESENCE_PENALTY = "presence_penalty"
|
|
89
|
+
MIN_P = "min_p"
|
|
90
|
+
REPETITION_PENALTY = "repetition_penalty"
|
|
91
|
+
LOGPROBS = "logprobs"
|
|
92
|
+
LOGIT_BIAS = "logit_bias"
|
|
93
|
+
TOP_LOGPROBS = "top_logprobs"
|
|
94
|
+
STRUCTURED_OUTPUTS = "structured_outputs"
|
|
95
|
+
WEB_SEARCH_OPTIONS = "web_search_options"
|
|
96
|
+
TOP_A = "top_a"
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class Modality(StrEnum):
|
|
100
|
+
"""Supported modalities for models."""
|
|
101
|
+
|
|
102
|
+
TEXT = "text"
|
|
103
|
+
IMAGE = "image"
|
|
104
|
+
FILE = "file"
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@dataclass(kw_only=True)
|
|
108
|
+
class ModelArchitecture(DataClassORJSONMixin):
|
|
109
|
+
"""Model data."""
|
|
110
|
+
|
|
111
|
+
input_modalities: list[Modality]
|
|
112
|
+
output_modalities: list[Modality]
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@dataclass(kw_only=True)
|
|
116
|
+
class Model(DataClassORJSONMixin):
|
|
117
|
+
"""Model data."""
|
|
118
|
+
|
|
119
|
+
id: str
|
|
120
|
+
canonical_slug: str
|
|
121
|
+
hugging_face_id: str | None
|
|
122
|
+
name: str
|
|
123
|
+
description: str
|
|
124
|
+
context_length: int
|
|
125
|
+
architecture: ModelArchitecture
|
|
126
|
+
supported_parameters: list[SupportedParameter]
|
|
127
|
+
|
|
128
|
+
@classmethod
|
|
129
|
+
def __pre_deserialize__(cls, d: dict[str, Any]) -> dict[str, Any]:
|
|
130
|
+
"""Pre deserialize hook."""
|
|
131
|
+
parameters = d.get("supported_parameters", [])
|
|
132
|
+
for parameter in parameters:
|
|
133
|
+
if parameter not in SupportedParameter:
|
|
134
|
+
_LOGGER.warning(
|
|
135
|
+
"Unsupported parameter: %s. Please report at https://github.com/joostlek/python-open-router/issues.",
|
|
136
|
+
parameter,
|
|
137
|
+
)
|
|
138
|
+
parameters.remove(parameter)
|
|
139
|
+
return d
|
|
140
|
+
|
|
141
|
+
@classmethod
|
|
142
|
+
def __post_deserialize__(cls, obj: Model) -> Model:
|
|
143
|
+
"""Post deserialize hook."""
|
|
144
|
+
if obj.hugging_face_id == "":
|
|
145
|
+
obj.hugging_face_id = None
|
|
146
|
+
return obj
|
|
@@ -9,11 +9,19 @@ import socket
|
|
|
9
9
|
from typing import TYPE_CHECKING, Any
|
|
10
10
|
|
|
11
11
|
from aiohttp import ClientError, ClientResponseError, ClientSession
|
|
12
|
-
from aiohttp.hdrs import METH_GET
|
|
12
|
+
from aiohttp.hdrs import METH_GET, METH_POST
|
|
13
13
|
from yarl import URL
|
|
14
14
|
|
|
15
15
|
from python_open_router.exceptions import OpenRouterConnectionError
|
|
16
|
-
from python_open_router.models import
|
|
16
|
+
from python_open_router.models import (
|
|
17
|
+
CreateKeyDataWrapper,
|
|
18
|
+
Key,
|
|
19
|
+
KeyData,
|
|
20
|
+
KeyDataWrapper,
|
|
21
|
+
KeysDataWrapper,
|
|
22
|
+
Model,
|
|
23
|
+
ModelsDataWrapper,
|
|
24
|
+
)
|
|
17
25
|
|
|
18
26
|
if TYPE_CHECKING:
|
|
19
27
|
from typing_extensions import Self
|
|
@@ -89,6 +97,25 @@ class OpenRouterClient:
|
|
|
89
97
|
response = await self._request(METH_GET, "key")
|
|
90
98
|
return KeyDataWrapper.from_json(response).data
|
|
91
99
|
|
|
100
|
+
async def get_keys(self) -> list[Key]:
|
|
101
|
+
"""Get all keys."""
|
|
102
|
+
response = await self._request(METH_GET, "keys")
|
|
103
|
+
return KeysDataWrapper.from_json(response).data
|
|
104
|
+
|
|
105
|
+
async def create_key(self, name: str, limit: float | None = None) -> Key:
|
|
106
|
+
"""Create a new key."""
|
|
107
|
+
data: dict[str, Any] = {"name": name}
|
|
108
|
+
if limit is not None:
|
|
109
|
+
data["limit"] = limit
|
|
110
|
+
|
|
111
|
+
response = await self._request(METH_POST, "keys", data=data)
|
|
112
|
+
return CreateKeyDataWrapper.from_json(response).data
|
|
113
|
+
|
|
114
|
+
async def get_models(self) -> list[Model]:
|
|
115
|
+
"""Get all available models."""
|
|
116
|
+
response = await self._request(METH_GET, "models")
|
|
117
|
+
return ModelsDataWrapper.from_json(response).data
|
|
118
|
+
|
|
92
119
|
async def close(self) -> None:
|
|
93
120
|
"""Close open client session."""
|
|
94
121
|
if self.session and self._close_session:
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"""Asynchronous Python client for Open Router."""
|
|
2
|
-
|
|
3
|
-
from python_open_router.exceptions import (
|
|
4
|
-
OpenRouterAuthenticationError,
|
|
5
|
-
OpenRouterConnectionError,
|
|
6
|
-
OpenRouterError,
|
|
7
|
-
)
|
|
8
|
-
from python_open_router.open_router import OpenRouterClient
|
|
9
|
-
|
|
10
|
-
__all__ = [
|
|
11
|
-
"OpenRouterAuthenticationError",
|
|
12
|
-
"OpenRouterClient",
|
|
13
|
-
"OpenRouterConnectionError",
|
|
14
|
-
"OpenRouterError",
|
|
15
|
-
]
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"""Models for OpenRouter."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from dataclasses import dataclass
|
|
6
|
-
|
|
7
|
-
from mashumaro.mixins.orjson import DataClassORJSONMixin
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@dataclass
|
|
11
|
-
class KeyDataWrapper(DataClassORJSONMixin):
|
|
12
|
-
"""Wrapper for OpenRouter key data."""
|
|
13
|
-
|
|
14
|
-
data: KeyData
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@dataclass
|
|
18
|
-
class KeyData(DataClassORJSONMixin):
|
|
19
|
-
"""The OpenRouter key data."""
|
|
20
|
-
|
|
21
|
-
label: str
|
|
22
|
-
usage: int
|
|
23
|
-
is_provisioning_key: bool
|
|
24
|
-
limit_remaining: int | None
|
|
25
|
-
is_free_tier: bool
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|