Skip to content

Commit 3bf7334

Browse files
committed
Release 0.0.2
1 parent c0ca950 commit 3bf7334

File tree

12 files changed

+948
-902
lines changed

12 files changed

+948
-902
lines changed

README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Humanloop Python Library
2+
3+
[![fern shield](https://img.shields.io/badge/%F0%9F%8C%BF-SDK%20generated%20by%20Fern-brightgreen)](https://github.com/fern-api/fern)
4+
[![pypi](https://img.shields.io/pypi/v/humanloop)](https://pypi.python.org/pypi/humanloop)
5+
6+
The Humanloop Python library provides convenient access to the Humanloop API from Python.
7+
8+
## Installation
9+
10+
```sh
11+
pip install humanloop
12+
```
13+
14+
## Usage
15+
16+
Instantiate and use the client with the following:
17+
18+
```python
19+
from humanloop.client import Humanloop
20+
21+
client = Humanloop(
22+
api_key="YOUR_API_KEY",
23+
)
24+
client.prompts.create(
25+
model="model",
26+
)
27+
```
28+
29+
## Async Client
30+
31+
The SDK also exports an `async` client so that you can make non-blocking calls to our API.
32+
33+
```python
34+
from humanloop.client import AsyncHumanloop
35+
36+
client = AsyncHumanloop(
37+
api_key="YOUR_API_KEY",
38+
)
39+
await client.prompts.create(
40+
model="model",
41+
)
42+
```
43+
44+
## Contributing
45+
46+
While we value open-source contributions to this SDK, this library is generated programmatically.
47+
Additions made directly to this library would have to be moved over to our generation code,
48+
otherwise they would be overwritten upon the next generated release. Feel free to open a PR as
49+
a proof of concept, but know that we will not be able to merge it as-is. We suggest opening
50+
an issue first to discuss with us!
51+
52+
On the other hand, contributions to the README are always very welcome!

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "humanloop"
3-
version = "0.0.1"
3+
version = "0.0.2"
44
description = ""
55
readme = "README.md"
66
authors = []

src/humanloop/core/client_wrapper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def get_headers(self) -> typing.Dict[str, str]:
1717
headers: typing.Dict[str, str] = {
1818
"X-Fern-Language": "Python",
1919
"X-Fern-SDK-Name": "humanloop",
20-
"X-Fern-SDK-Version": "0.0.1",
20+
"X-Fern-SDK-Version": "0.0.2",
2121
}
2222
headers["X-API-KEY"] = self.api_key
2323
return headers

src/humanloop/core/unchecked_base_model.py

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import typing_extensions
99

1010
from .datetime_utils import serialize_datetime
11-
from .pydantic_utilities import IS_PYDANTIC_V2, pydantic_v1
11+
from .pydantic_utilities import pydantic_v1
1212

1313

1414
class UnionMetadata:
@@ -46,49 +46,39 @@ def construct(
4646
_fields_set = set(values.keys())
4747

4848
for name, field in cls.__fields__.items():
49+
# Key here is only used to pull data from the values dict
50+
# you should always use the NAME of the field to for field_values, etc.
51+
# because that's how the object is constructed from a pydantic perspective
4952
key = field.alias
50-
if (
53+
if key is None or (
5154
key not in values and config.allow_population_by_field_name
5255
): # Added this to allow population by field name
5356
key = name
5457

5558
if key in values:
56-
if (
57-
values[key] is None and not field.required
58-
): # Moved this check since None value can be passed for Optional nested field
59-
fields_values[name] = field.get_default()
60-
else:
61-
type_ = typing.cast(typing.Type, field.outer_type_) # type: ignore
62-
fields_values[name] = construct_type(object_=values[key], type_=type_)
59+
type_ = typing.cast(typing.Type, field.outer_type_) # type: ignore
60+
fields_values[name] = construct_type(object_=values[key], type_=type_)
6361
_fields_set.add(name)
64-
elif not field.required:
62+
else:
6563
default = field.get_default()
6664
fields_values[name] = default
6765

6866
# If the default values are non-null act like they've been set
6967
# This effectively allows exclude_unset to work like exclude_none where
7068
# the latter passes through intentionally set none values.
7169
if default != None:
72-
_fields_set.add(key)
70+
_fields_set.add(name)
7371

7472
# Add extras back in
75-
_extra = {}
73+
alias_fields = [field.alias for field in cls.__fields__.values()]
7674
for key, value in values.items():
77-
if key not in _fields_set:
78-
_extra[key] = value
79-
# In v2 we'll need to exclude extra fields from fields_values
80-
if not IS_PYDANTIC_V2:
81-
_fields_set.add(key)
82-
fields_values[key] = value
83-
84-
if IS_PYDANTIC_V2:
85-
object.__setattr__(m, "__pydantic_private__", None)
86-
object.__setattr__(m, "__pydantic_extra__", _extra)
87-
object.__setattr__(m, "__pydantic_fields_set__", _fields_set)
75+
if key not in alias_fields and key not in cls.__fields__:
76+
_fields_set.add(key)
77+
fields_values[key] = value
8878

8979
object.__setattr__(m, "__dict__", fields_values)
90-
object.__setattr__(m, "__fields_set__", _fields_set)
9180
m._init_private_attributes()
81+
object.__setattr__(m, "__fields_set__", _fields_set)
9282
return m
9383

9484

0 commit comments

Comments
 (0)