Skip to content

Commit fab3ba1

Browse files
authored
Merge pull request #14 from CZL-AI/release-please--branches--main--changes--next
release: 0.1.0-alpha.4
2 parents 78b6a14 + 60f117d commit fab3ba1

14 files changed

Lines changed: 130 additions & 68 deletions

.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-alpha.3"
2+
".": "0.1.0-alpha.4"
33
}

CHANGELOG.md

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

3+
## 0.1.0-alpha.4 (2024-11-22)
4+
5+
Full Changelog: [v0.1.0-alpha.3...v0.1.0-alpha.4](https://github.com/CZL-AI/czlai-python/compare/v0.1.0-alpha.3...v0.1.0-alpha.4)
6+
7+
### Chores
8+
9+
* **internal:** fix compat model_dump method when warnings are passed ([#17](https://github.com/CZL-AI/czlai-python/issues/17)) ([e4e6d50](https://github.com/CZL-AI/czlai-python/commit/e4e6d50fa26706b601ee003d7e70a9b0f24492e4))
10+
* rebuild project due to codegen change ([#13](https://github.com/CZL-AI/czlai-python/issues/13)) ([654605e](https://github.com/CZL-AI/czlai-python/commit/654605e20a39dca97bcd51d11edff4ac510ca2cd))
11+
* rebuild project due to codegen change ([#15](https://github.com/CZL-AI/czlai-python/issues/15)) ([9c7f95b](https://github.com/CZL-AI/czlai-python/commit/9c7f95b397bd35058e46df7cd273444bec53e103))
12+
* rebuild project due to codegen change ([#16](https://github.com/CZL-AI/czlai-python/issues/16)) ([2b9734c](https://github.com/CZL-AI/czlai-python/commit/2b9734ceed8b55ff808e9da4c56fc617743b6b8d))
13+
14+
15+
### Documentation
16+
17+
* add info log level to readme ([#18](https://github.com/CZL-AI/czlai-python/issues/18)) ([0e1f0ab](https://github.com/CZL-AI/czlai-python/commit/0e1f0ab3f6c434065fff877406f8fec93387eba1))
18+
319
## 0.1.0-alpha.3 (2024-11-08)
420

521
Full Changelog: [v0.1.0-alpha.2...v0.1.0-alpha.3](https://github.com/CZL-AI/czlai-python/compare/v0.1.0-alpha.2...v0.1.0-alpha.3)

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,14 @@ Note that requests that time out are [retried twice by default](#retries).
159159

160160
We use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.
161161

162-
You can enable logging by setting the environment variable `CZLAI_LOG` to `debug`.
162+
You can enable logging by setting the environment variable `CZLAI_LOG` to `info`.
163163

164164
```shell
165-
$ export CZLAI_LOG=debug
165+
$ export CZLAI_LOG=info
166166
```
167167

168+
Or to `debug` for more verbose logging.
169+
168170
### How to tell whether `None` means `null` or missing
169171

170172
In an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "czlai"
3-
version = "0.1.0-alpha.3"
3+
version = "0.1.0-alpha.4"
44
description = "The official Python library for the czlai API"
55
dynamic = ["readme"]
66
license = "Apache-2.0"
@@ -55,6 +55,7 @@ dev-dependencies = [
5555
"dirty-equals>=0.6.0",
5656
"importlib-metadata>=6.7.0",
5757
"rich>=13.7.1",
58+
"nest_asyncio==1.6.0"
5859
]
5960

6061
[tool.rye.scripts]

requirements-dev.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ mdurl==0.1.2
5151
mypy==1.13.0
5252
mypy-extensions==1.0.0
5353
# via mypy
54+
nest-asyncio==1.6.0
5455
nodeenv==1.8.0
5556
# via pyright
5657
nox==2023.4.22

src/czlai/_compat.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ def model_dump(
145145
exclude=exclude,
146146
exclude_unset=exclude_unset,
147147
exclude_defaults=exclude_defaults,
148-
warnings=warnings,
148+
# warnings are not supported in Pydantic v1
149+
warnings=warnings if PYDANTIC_V2 else True,
149150
)
150151
return cast(
151152
"dict[str, Any]",

src/czlai/_utils/_sync.py

Lines changed: 40 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,62 @@
11
from __future__ import annotations
22

3+
import sys
4+
import asyncio
35
import functools
4-
from typing import TypeVar, Callable, Awaitable
6+
import contextvars
7+
from typing import Any, TypeVar, Callable, Awaitable
58
from typing_extensions import ParamSpec
69

7-
import anyio
8-
import anyio.to_thread
9-
10-
from ._reflection import function_has_argument
11-
1210
T_Retval = TypeVar("T_Retval")
1311
T_ParamSpec = ParamSpec("T_ParamSpec")
1412

1513

16-
# copied from `asyncer`, https://github.com/tiangolo/asyncer
17-
def asyncify(
18-
function: Callable[T_ParamSpec, T_Retval],
19-
*,
20-
cancellable: bool = False,
21-
limiter: anyio.CapacityLimiter | None = None,
22-
) -> Callable[T_ParamSpec, Awaitable[T_Retval]]:
14+
if sys.version_info >= (3, 9):
15+
to_thread = asyncio.to_thread
16+
else:
17+
# backport of https://docs.python.org/3/library/asyncio-task.html#asyncio.to_thread
18+
# for Python 3.8 support
19+
async def to_thread(
20+
func: Callable[T_ParamSpec, T_Retval], /, *args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs
21+
) -> Any:
22+
"""Asynchronously run function *func* in a separate thread.
23+
24+
Any *args and **kwargs supplied for this function are directly passed
25+
to *func*. Also, the current :class:`contextvars.Context` is propagated,
26+
allowing context variables from the main thread to be accessed in the
27+
separate thread.
28+
29+
Returns a coroutine that can be awaited to get the eventual result of *func*.
30+
"""
31+
loop = asyncio.events.get_running_loop()
32+
ctx = contextvars.copy_context()
33+
func_call = functools.partial(ctx.run, func, *args, **kwargs)
34+
return await loop.run_in_executor(None, func_call)
35+
36+
37+
# inspired by `asyncer`, https://github.com/tiangolo/asyncer
38+
def asyncify(function: Callable[T_ParamSpec, T_Retval]) -> Callable[T_ParamSpec, Awaitable[T_Retval]]:
2339
"""
2440
Take a blocking function and create an async one that receives the same
25-
positional and keyword arguments, and that when called, calls the original function
26-
in a worker thread using `anyio.to_thread.run_sync()`. Internally,
27-
`asyncer.asyncify()` uses the same `anyio.to_thread.run_sync()`, but it supports
28-
keyword arguments additional to positional arguments and it adds better support for
29-
autocompletion and inline errors for the arguments of the function called and the
30-
return value.
31-
32-
If the `cancellable` option is enabled and the task waiting for its completion is
33-
cancelled, the thread will still run its course but its return value (or any raised
34-
exception) will be ignored.
41+
positional and keyword arguments. For python version 3.9 and above, it uses
42+
asyncio.to_thread to run the function in a separate thread. For python version
43+
3.8, it uses locally defined copy of the asyncio.to_thread function which was
44+
introduced in python 3.9.
3545
36-
Use it like this:
46+
Usage:
3747
38-
```Python
39-
def do_work(arg1, arg2, kwarg1="", kwarg2="") -> str:
40-
# Do work
41-
return "Some result"
48+
```python
49+
def blocking_func(arg1, arg2, kwarg1=None):
50+
# blocking code
51+
return result
4252
4353
44-
result = await to_thread.asyncify(do_work)("spam", "ham", kwarg1="a", kwarg2="b")
45-
print(result)
54+
result = asyncify(blocking_function)(arg1, arg2, kwarg1=value1)
4655
```
4756
4857
## Arguments
4958
5059
`function`: a blocking regular callable (e.g. a function)
51-
`cancellable`: `True` to allow cancellation of the operation
52-
`limiter`: capacity limiter to use to limit the total amount of threads running
53-
(if omitted, the default limiter is used)
5460
5561
## Return
5662
@@ -60,22 +66,6 @@ def do_work(arg1, arg2, kwarg1="", kwarg2="") -> str:
6066
"""
6167

6268
async def wrapper(*args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs) -> T_Retval:
63-
partial_f = functools.partial(function, *args, **kwargs)
64-
65-
# In `v4.1.0` anyio added the `abandon_on_cancel` argument and deprecated the old
66-
# `cancellable` argument, so we need to use the new `abandon_on_cancel` to avoid
67-
# surfacing deprecation warnings.
68-
if function_has_argument(anyio.to_thread.run_sync, "abandon_on_cancel"):
69-
return await anyio.to_thread.run_sync(
70-
partial_f,
71-
abandon_on_cancel=cancellable,
72-
limiter=limiter,
73-
)
74-
75-
return await anyio.to_thread.run_sync(
76-
partial_f,
77-
cancellable=cancellable,
78-
limiter=limiter,
79-
)
69+
return await to_thread(function, *args, **kwargs)
8070

8171
return wrapper

src/czlai/_utils/_transform.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,11 @@ async def _async_transform_recursive(
316316
# Iterable[T]
317317
or (is_iterable_type(stripped_type) and is_iterable(data) and not isinstance(data, str))
318318
):
319+
# dicts are technically iterable, but it is an iterable on the keys of the dict and is not usually
320+
# intended as an iterable, so we don't transform it.
321+
if isinstance(data, dict):
322+
return cast(object, data)
323+
319324
inner_type = extract_type_arg(stripped_type, 0)
320325
return [await _async_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data]
321326

src/czlai/_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__ = "czlai"
4-
__version__ = "0.1.0-alpha.3" # x-release-please-version
4+
__version__ = "0.1.0-alpha.4" # x-release-please-version

tests/api_resources/test_medical_records.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,9 @@ def test_method_create_list(self, client: Czlai) -> None:
9797
def test_method_create_list_with_all_params(self, client: Czlai) -> None:
9898
medical_record = client.medical_records.create_list(
9999
limit=0,
100-
module_type=[0, 0, 0],
100+
module_type=[0],
101101
page=0,
102-
pet_profile_id=[0, 0, 0],
102+
pet_profile_id=[0],
103103
)
104104
assert_matches_type(MedicalRecordCreateListResponse, medical_record, path=["response"])
105105

@@ -237,9 +237,9 @@ async def test_method_create_list(self, async_client: AsyncCzlai) -> None:
237237
async def test_method_create_list_with_all_params(self, async_client: AsyncCzlai) -> None:
238238
medical_record = await async_client.medical_records.create_list(
239239
limit=0,
240-
module_type=[0, 0, 0],
240+
module_type=[0],
241241
page=0,
242-
pet_profile_id=[0, 0, 0],
242+
pet_profile_id=[0],
243243
)
244244
assert_matches_type(MedicalRecordCreateListResponse, medical_record, path=["response"])
245245

0 commit comments

Comments
 (0)