Skip to content

Commit ee82e01

Browse files
authored
Merge pull request #28 from digitalocean/release-please--branches--main--changes--next
release: 0.1.0-beta.3
2 parents b6bf022 + a5913f4 commit ee82e01

File tree

9 files changed

+79
-15
lines changed

9 files changed

+79
-15
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
.prism.log
2-
.vscode
32
_dev
43

54
__pycache__

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "0.1.0-beta.2"
2+
".": "0.1.0-beta.3"
33
}

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"python.analysis.importFormat": "relative",
3+
}

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Changelog
22

3+
## 0.1.0-beta.3 (2025-07-25)
4+
5+
Full Changelog: [v0.1.0-beta.2...v0.1.0-beta.3](https://github.com/digitalocean/gradientai-python/compare/v0.1.0-beta.2...v0.1.0-beta.3)
6+
7+
### Bug Fixes
8+
9+
* **parsing:** parse extra field types ([93bea71](https://github.com/digitalocean/gradientai-python/commit/93bea71735195fa3f32de6b64bbc0aaac60a6d6c))
10+
11+
12+
### Chores
13+
14+
* **project:** add settings file for vscode ([3b597aa](https://github.com/digitalocean/gradientai-python/commit/3b597aa96e1f588506de47d782444992383f5522))
15+
* update README with new gradient name ([03157fb](https://github.com/digitalocean/gradientai-python/commit/03157fb38616c68568024ab7e426b45d414bf432))
16+
317
## 0.1.0-beta.2 (2025-07-22)
418

519
Full Changelog: [v0.1.0-beta.1...v0.1.0-beta.2](https://github.com/digitalocean/gradientai-python/compare/v0.1.0-beta.1...v0.1.0-beta.2)

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
# GradientAI Python API library
1+
# Gradient Python API library
22

33
### 🚧 Preview Status
44

5-
> GradientAI SDK is currently in **preview**. It is reasonably stable and suitable for use, but **some features and APIs may still change** as development continues.
5+
> Gradient SDK is currently in **preview**. It is reasonably stable and suitable for use, but **some features and APIs may still change** as development continues.
66
> Use with care in production environments and keep an eye on releases for updates or breaking changes.
77
88
<!-- prettier-ignore -->
99
[![PyPI version](https://img.shields.io/pypi/v/do_gradientai.svg?label=pypi%20(stable))](https://pypi.org/project/do_gradientai/)
10-
[![Docs](https://img.shields.io/badge/Docs-8A2BE2)](https://gradientai-sdk.digitalocean.com/getting-started/overview/)
10+
[![Docs](https://img.shields.io/badge/Docs-8A2BE2)](https://gradientai.digitalocean.com/getting-started/overview/)
1111

12-
The GradientAI Python library provides convenient access to the GradientAI REST API from any Python 3.8+
12+
The Gradient Python library provides convenient access to the Gradient REST API from any Python 3.8+
1313
application. The library includes type definitions for all request params and response fields,
1414
and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).
1515

1616
It is generated with [Stainless](https://www.stainless.com/).
1717

1818
## Documentation
1919

20-
The getting started guide can be found on [gradientai-sdk.digitalocean.com](https://gradientai-sdk.digitalocean.com/getting-started/overview).
20+
The getting started guide can be found on [gradient-sdk.digitalocean.com](https://gradient-sdk.digitalocean.com/getting-started/overview).
2121
The REST API documentation can be found on [developers.digitalocean.com](https://developers.digitalocean.com/documentation/v2/).
2222
The full API of this library can be found in [api.md](api.md).
2323

@@ -30,10 +30,10 @@ pip install --pre do_gradientai
3030

3131
## Usage
3232

33-
The GradientAI SDK provides clients for:
33+
The Gradient SDK provides clients for:
3434
* DigitalOcean API
35-
* GradientAI Serverless Inference
36-
* GradientAI Agent Inference
35+
* Gradient Serverless Inference
36+
* Gradient Agent Inference
3737

3838
The full API of this library can be found in [api.md](api.md).
3939

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "do_gradientai"
3-
version = "0.1.0-beta.2"
3+
version = "0.1.0-beta.3"
44
description = "The official Python library for GradientAI"
55
dynamic = ["readme"]
66
license = "Apache-2.0"

src/do_gradientai/_models.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,18 @@ def construct( # pyright: ignore[reportIncompatibleMethodOverride]
208208
else:
209209
fields_values[name] = field_get_default(field)
210210

211+
extra_field_type = _get_extra_fields_type(__cls)
212+
211213
_extra = {}
212214
for key, value in values.items():
213215
if key not in model_fields:
216+
parsed = construct_type(value=value, type_=extra_field_type) if extra_field_type is not None else value
217+
214218
if PYDANTIC_V2:
215-
_extra[key] = value
219+
_extra[key] = parsed
216220
else:
217221
_fields_set.add(key)
218-
fields_values[key] = value
222+
fields_values[key] = parsed
219223

220224
object.__setattr__(m, "__dict__", fields_values)
221225

@@ -370,6 +374,23 @@ def _construct_field(value: object, field: FieldInfo, key: str) -> object:
370374
return construct_type(value=value, type_=type_, metadata=getattr(field, "metadata", None))
371375

372376

377+
def _get_extra_fields_type(cls: type[pydantic.BaseModel]) -> type | None:
378+
if not PYDANTIC_V2:
379+
# TODO
380+
return None
381+
382+
schema = cls.__pydantic_core_schema__
383+
if schema["type"] == "model":
384+
fields = schema["schema"]
385+
if fields["type"] == "model-fields":
386+
extras = fields.get("extras_schema")
387+
if extras and "cls" in extras:
388+
# mypy can't narrow the type
389+
return extras["cls"] # type: ignore[no-any-return]
390+
391+
return None
392+
393+
373394
def is_basemodel(type_: type) -> bool:
374395
"""Returns whether or not the given type is either a `BaseModel` or a union of `BaseModel`"""
375396
if is_union(type_):

src/do_gradientai/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
22

33
__title__ = "do_gradientai"
4-
__version__ = "0.1.0-beta.2" # x-release-please-version
4+
__version__ = "0.1.0-beta.3" # x-release-please-version

tests/test_models.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import json
2-
from typing import Any, Dict, List, Union, Optional, cast
2+
from typing import TYPE_CHECKING, Any, Dict, List, Union, Optional, cast
33
from datetime import datetime, timezone
44
from typing_extensions import Literal, Annotated, TypeAliasType
55

@@ -934,3 +934,30 @@ class Type2(BaseModel):
934934
)
935935
assert isinstance(model, Type1)
936936
assert isinstance(model.value, InnerType2)
937+
938+
939+
@pytest.mark.skipif(not PYDANTIC_V2, reason="this is only supported in pydantic v2 for now")
940+
def test_extra_properties() -> None:
941+
class Item(BaseModel):
942+
prop: int
943+
944+
class Model(BaseModel):
945+
__pydantic_extra__: Dict[str, Item] = Field(init=False) # pyright: ignore[reportIncompatibleVariableOverride]
946+
947+
other: str
948+
949+
if TYPE_CHECKING:
950+
951+
def __getattr__(self, attr: str) -> Item: ...
952+
953+
model = construct_type(
954+
type_=Model,
955+
value={
956+
"a": {"prop": 1},
957+
"other": "foo",
958+
},
959+
)
960+
assert isinstance(model, Model)
961+
assert model.a.prop == 1
962+
assert isinstance(model.a, Item)
963+
assert model.other == "foo"

0 commit comments

Comments
 (0)