python-open-router 0.2.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: python_open_router
3
- Version: 0.2.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,<4.0
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.2.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.11"
27
+ python = "^3.13"
30
28
  aiohttp = ">=3.0.0"
31
29
  yarl = ">=1.6.0"
32
30
  mashumaro = "^3.11"
@@ -35,17 +33,17 @@ 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.6.12", extras = ["toml"]}
39
- mypy = "1.15.0"
40
- pre-commit = "4.1.0"
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.6"
43
- pytest = "8.3.5"
44
- pytest-asyncio = "0.25.3"
45
- pytest-cov = "6.1.1"
46
- ruff = "0.9.6"
47
- safety = "3.3.1"
48
- yamllint = "1.35.1"
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"
49
47
  syrupy = "4.9.1"
50
48
  aioresponses = "0.7.8"
51
49
 
@@ -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.11"
67
+ python_version = "3.13"
69
68
 
70
69
  # show error messages from unrelated files
71
70
  follow_imports = "normal"
@@ -12,6 +12,11 @@ from python_open_router.models import (
12
12
  KeyData,
13
13
  KeyDataWrapper,
14
14
  KeysDataWrapper,
15
+ Modality,
16
+ Model,
17
+ ModelArchitecture,
18
+ ModelsDataWrapper,
19
+ SupportedParameter,
15
20
  )
16
21
  from python_open_router.open_router import OpenRouterClient
17
22
 
@@ -22,8 +27,13 @@ __all__ = [
22
27
  "KeyData",
23
28
  "KeyDataWrapper",
24
29
  "KeysDataWrapper",
30
+ "Modality",
31
+ "Model",
32
+ "ModelArchitecture",
33
+ "ModelsDataWrapper",
25
34
  "OpenRouterAuthenticationError",
26
35
  "OpenRouterClient",
27
36
  "OpenRouterConnectionError",
28
37
  "OpenRouterError",
38
+ "SupportedParameter",
29
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
@@ -19,6 +19,8 @@ from python_open_router.models import (
19
19
  KeyData,
20
20
  KeyDataWrapper,
21
21
  KeysDataWrapper,
22
+ Model,
23
+ ModelsDataWrapper,
22
24
  )
23
25
 
24
26
  if TYPE_CHECKING:
@@ -109,6 +111,11 @@ class OpenRouterClient:
109
111
  response = await self._request(METH_POST, "keys", data=data)
110
112
  return CreateKeyDataWrapper.from_json(response).data
111
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
+
112
119
  async def close(self) -> None:
113
120
  """Close open client session."""
114
121
  if self.session and self._close_session:
@@ -1,58 +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
26
-
27
-
28
- @dataclass
29
- class KeysDataWrapper(DataClassORJSONMixin):
30
- """Wrapper for OpenRouter key data."""
31
-
32
- data: list[Key]
33
-
34
-
35
- @dataclass
36
- class CreateKeyDataWrapper(DataClassORJSONMixin):
37
- """Wrapper for OpenRouter key data."""
38
-
39
- data: CreatedKey
40
-
41
-
42
- @dataclass
43
- class Key(DataClassORJSONMixin):
44
- """The OpenRouter key data."""
45
-
46
- hash: str
47
- name: str
48
- label: str
49
- disabled: bool
50
- limit: float
51
- usage: float = 0.0
52
-
53
-
54
- @dataclass(kw_only=True)
55
- class CreatedKey(Key):
56
- """Created key."""
57
-
58
- key: str