Skip to content

Commit f1b91ed

Browse files
authored
Merge pull request #117 from writer/release-please--branches--main--changes--next
release: 1.4.0
2 parents 8ecd22f + b130306 commit f1b91ed

12 files changed

Lines changed: 143 additions & 459 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-
".": "1.3.0"
2+
".": "1.4.0"
33
}

CHANGELOG.md

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

3+
## 1.4.0 (2024-11-20)
4+
5+
Full Changelog: [v1.3.0...v1.4.0](https://github.com/writer/writer-python/compare/v1.3.0...v1.4.0)
6+
7+
### Features
8+
9+
* **api:** default timeout increase to 3 min ([#119](https://github.com/writer/writer-python/issues/119)) ([f263e59](https://github.com/writer/writer-python/commit/f263e598c17328185c43247c34fa87aca3d9a1ce))
10+
11+
12+
### Chores
13+
14+
* rebuild project due to codegen change ([#116](https://github.com/writer/writer-python/issues/116)) ([66d114e](https://github.com/writer/writer-python/commit/66d114e2307f1e1bbcd70052a037e1ba1c5fd7d2))
15+
* rebuild project due to codegen change ([#118](https://github.com/writer/writer-python/issues/118)) ([c527530](https://github.com/writer/writer-python/commit/c5275300b56cc724795748bfbd9811904fa2e170))
16+
317
## 1.3.0 (2024-11-12)
418

519
Full Changelog: [v1.2.0...v1.3.0](https://github.com/writer/writer-python/compare/v1.2.0...v1.3.0)

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,15 +248,15 @@ client.with_options(max_retries=5).chat.chat(
248248

249249
### Timeouts
250250

251-
By default requests time out after 1 minute. You can configure this with a `timeout` option,
251+
By default requests time out after 3 minutes. You can configure this with a `timeout` option,
252252
which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/#fine-tuning-the-configuration) object:
253253

254254
```python
255255
from writerai import Writer
256256

257257
# Configure the default for all requests:
258258
client = Writer(
259-
# 20 seconds (default is 1 minute)
259+
# 20 seconds (default is 3 minutes)
260260
timeout=20.0,
261261
)
262262

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "writer-sdk"
3-
version = "1.3.0"
3+
version = "1.4.0"
44
description = "The official Python library for the writer 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
@@ -52,6 +52,7 @@ mdurl==0.1.2
5252
mypy==1.13.0
5353
mypy-extensions==1.0.0
5454
# via mypy
55+
nest-asyncio==1.6.0
5556
nodeenv==1.8.0
5657
# via pyright
5758
nox==2023.4.22

src/writerai/_constants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
RAW_RESPONSE_HEADER = "X-Stainless-Raw-Response"
66
OVERRIDE_CAST_TO_HEADER = "____stainless_override_cast_to"
77

8-
# default timeout is 1 minute
9-
DEFAULT_TIMEOUT = httpx.Timeout(timeout=60.0, connect=5.0)
8+
# default timeout is 3 minutes
9+
DEFAULT_TIMEOUT = httpx.Timeout(timeout=180.0, connect=5.0)
1010
DEFAULT_MAX_RETRIES = 2
1111
DEFAULT_CONNECTION_LIMITS = httpx.Limits(max_connections=100, max_keepalive_connections=20)
1212

src/writerai/_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/writerai/_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__ = "writerai"
4-
__version__ = "1.3.0" # x-release-please-version
4+
__version__ = "1.4.0" # x-release-please-version

tests/api_resources/test_applications.py

Lines changed: 16 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,8 @@ def test_method_generate_content(self, client: Writer) -> None:
2424
inputs=[
2525
{
2626
"id": "id",
27-
"value": ["string", "string", "string"],
28-
},
29-
{
30-
"id": "id",
31-
"value": ["string", "string", "string"],
32-
},
33-
{
34-
"id": "id",
35-
"value": ["string", "string", "string"],
36-
},
27+
"value": ["string"],
28+
}
3729
],
3830
)
3931
assert_matches_type(ApplicationGenerateContentResponse, application, path=["response"])
@@ -45,16 +37,8 @@ def test_raw_response_generate_content(self, client: Writer) -> None:
4537
inputs=[
4638
{
4739
"id": "id",
48-
"value": ["string", "string", "string"],
49-
},
50-
{
51-
"id": "id",
52-
"value": ["string", "string", "string"],
53-
},
54-
{
55-
"id": "id",
56-
"value": ["string", "string", "string"],
57-
},
40+
"value": ["string"],
41+
}
5842
],
5943
)
6044

@@ -70,16 +54,8 @@ def test_streaming_response_generate_content(self, client: Writer) -> None:
7054
inputs=[
7155
{
7256
"id": "id",
73-
"value": ["string", "string", "string"],
74-
},
75-
{
76-
"id": "id",
77-
"value": ["string", "string", "string"],
78-
},
79-
{
80-
"id": "id",
81-
"value": ["string", "string", "string"],
82-
},
57+
"value": ["string"],
58+
}
8359
],
8460
) as response:
8561
assert not response.is_closed
@@ -98,16 +74,8 @@ def test_path_params_generate_content(self, client: Writer) -> None:
9874
inputs=[
9975
{
10076
"id": "id",
101-
"value": ["string", "string", "string"],
102-
},
103-
{
104-
"id": "id",
105-
"value": ["string", "string", "string"],
106-
},
107-
{
108-
"id": "id",
109-
"value": ["string", "string", "string"],
110-
},
77+
"value": ["string"],
78+
}
11179
],
11280
)
11381

@@ -122,16 +90,8 @@ async def test_method_generate_content(self, async_client: AsyncWriter) -> None:
12290
inputs=[
12391
{
12492
"id": "id",
125-
"value": ["string", "string", "string"],
126-
},
127-
{
128-
"id": "id",
129-
"value": ["string", "string", "string"],
130-
},
131-
{
132-
"id": "id",
133-
"value": ["string", "string", "string"],
134-
},
93+
"value": ["string"],
94+
}
13595
],
13696
)
13797
assert_matches_type(ApplicationGenerateContentResponse, application, path=["response"])
@@ -143,16 +103,8 @@ async def test_raw_response_generate_content(self, async_client: AsyncWriter) ->
143103
inputs=[
144104
{
145105
"id": "id",
146-
"value": ["string", "string", "string"],
147-
},
148-
{
149-
"id": "id",
150-
"value": ["string", "string", "string"],
151-
},
152-
{
153-
"id": "id",
154-
"value": ["string", "string", "string"],
155-
},
106+
"value": ["string"],
107+
}
156108
],
157109
)
158110

@@ -168,16 +120,8 @@ async def test_streaming_response_generate_content(self, async_client: AsyncWrit
168120
inputs=[
169121
{
170122
"id": "id",
171-
"value": ["string", "string", "string"],
172-
},
173-
{
174-
"id": "id",
175-
"value": ["string", "string", "string"],
176-
},
177-
{
178-
"id": "id",
179-
"value": ["string", "string", "string"],
180-
},
123+
"value": ["string"],
124+
}
181125
],
182126
) as response:
183127
assert not response.is_closed
@@ -196,15 +140,7 @@ async def test_path_params_generate_content(self, async_client: AsyncWriter) ->
196140
inputs=[
197141
{
198142
"id": "id",
199-
"value": ["string", "string", "string"],
200-
},
201-
{
202-
"id": "id",
203-
"value": ["string", "string", "string"],
204-
},
205-
{
206-
"id": "id",
207-
"value": ["string", "string", "string"],
208-
},
143+
"value": ["string"],
144+
}
209145
],
210146
)

0 commit comments

Comments
 (0)