Skip to content

Commit e388ba1

Browse files
release: 0.1.3 (#42)
* chore(internal): codegen related update (#41) * chore(internal): add jsonl unit tests (#43) * release: 0.1.3 --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
1 parent c16c250 commit e388ba1

File tree

6 files changed

+101
-9
lines changed

6 files changed

+101
-9
lines changed

Diff for: .release-please-manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "0.1.2"
2+
".": "0.1.3"
33
}

Diff for: CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
## 0.1.3 (2025-02-14)
4+
5+
Full Changelog: [v0.1.2...v0.1.3](https://github.com/gitpod-io/gitpod-sdk-python/compare/v0.1.2...v0.1.3)
6+
7+
### Chores
8+
9+
* **internal:** add jsonl unit tests ([#43](https://github.com/gitpod-io/gitpod-sdk-python/issues/43)) ([8641b53](https://github.com/gitpod-io/gitpod-sdk-python/commit/8641b53116b20dd8e329f229afd84ec6a100fcef))
10+
* **internal:** codegen related update ([#41](https://github.com/gitpod-io/gitpod-sdk-python/issues/41)) ([e5dceda](https://github.com/gitpod-io/gitpod-sdk-python/commit/e5dceda109bb01cf538dce83c3ab16d60461eb3d))
11+
312
## 0.1.2 (2025-02-14)
413

514
Full Changelog: [v0.1.1...v0.1.2](https://github.com/gitpod-io/gitpod-sdk-python/compare/v0.1.1...v0.1.2)

Diff for: pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "gitpod-sdk"
3-
version = "0.1.2"
3+
version = "0.1.3"
44
description = "The official Python library for the gitpod API"
55
dynamic = ["readme"]
66
license = "Apache-2.0"

Diff for: src/gitpod/_exceptions.py

+1-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from __future__ import annotations
44

5-
from typing import TYPE_CHECKING, Any, Optional, cast
5+
from typing import Any, Optional, cast
66
from typing_extensions import Literal
77

88
import httpx
@@ -53,11 +53,6 @@ class APIError(GitpodError):
5353
Contains an arbitrary serialized message along with a @type that describes the
5454
type of the serialized message.
5555
"""
56-
if TYPE_CHECKING:
57-
# Stub to indicate that arbitrary properties are accepted.
58-
# To access properties that are not valid identifiers you can use `getattr`, e.g.
59-
# `getattr(obj, '$type')`
60-
def __getattr__(self, attr: str) -> object: ...
6156

6257
def __init__(self, message: str, request: httpx.Request, *, body: object | None) -> None:
6358
super().__init__(message)

Diff for: src/gitpod/_version.py

+1-1
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__ = "gitpod"
4-
__version__ = "0.1.2" # x-release-please-version
4+
__version__ = "0.1.3" # x-release-please-version

Diff for: tests/decoders/test_jsonl.py

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
from __future__ import annotations
2+
3+
from typing import Any, Iterator, AsyncIterator
4+
from typing_extensions import TypeVar
5+
6+
import httpx
7+
import pytest
8+
9+
from gitpod._decoders.jsonl import JSONLDecoder, AsyncJSONLDecoder
10+
11+
_T = TypeVar("_T")
12+
13+
14+
@pytest.mark.asyncio
15+
@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"])
16+
async def test_basic(sync: bool) -> None:
17+
def body() -> Iterator[bytes]:
18+
yield b'{"foo":true}\n'
19+
yield b'{"bar":false}\n'
20+
21+
iterator = make_jsonl_iterator(
22+
content=body(),
23+
sync=sync,
24+
line_type=object,
25+
)
26+
27+
assert await iter_next(iterator) == {"foo": True}
28+
assert await iter_next(iterator) == {"bar": False}
29+
30+
await assert_empty_iter(iterator)
31+
32+
33+
@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"])
34+
async def test_new_lines_in_json(
35+
sync: bool,
36+
) -> None:
37+
def body() -> Iterator[bytes]:
38+
yield b'{"content":"Hello, world!\\nHow are you doing?"}'
39+
40+
iterator = make_jsonl_iterator(content=body(), sync=sync, line_type=object)
41+
42+
assert await iter_next(iterator) == {"content": "Hello, world!\nHow are you doing?"}
43+
44+
45+
@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"])
46+
async def test_multi_byte_character_multiple_chunks(
47+
sync: bool,
48+
) -> None:
49+
def body() -> Iterator[bytes]:
50+
yield b'{"content":"'
51+
# bytes taken from the string 'известни' and arbitrarily split
52+
# so that some multi-byte characters span multiple chunks
53+
yield b"\xd0"
54+
yield b"\xb8\xd0\xb7\xd0"
55+
yield b"\xb2\xd0\xb5\xd1\x81\xd1\x82\xd0\xbd\xd0\xb8"
56+
yield b'"}\n'
57+
58+
iterator = make_jsonl_iterator(content=body(), sync=sync, line_type=object)
59+
60+
assert await iter_next(iterator) == {"content": "известни"}
61+
62+
63+
async def to_aiter(iter: Iterator[bytes]) -> AsyncIterator[bytes]:
64+
for chunk in iter:
65+
yield chunk
66+
67+
68+
async def iter_next(iter: Iterator[_T] | AsyncIterator[_T]) -> _T:
69+
if isinstance(iter, AsyncIterator):
70+
return await iter.__anext__()
71+
return next(iter)
72+
73+
74+
async def assert_empty_iter(decoder: JSONLDecoder[Any] | AsyncJSONLDecoder[Any]) -> None:
75+
with pytest.raises((StopAsyncIteration, RuntimeError)):
76+
await iter_next(decoder)
77+
78+
79+
def make_jsonl_iterator(
80+
content: Iterator[bytes],
81+
*,
82+
sync: bool,
83+
line_type: type[_T],
84+
) -> JSONLDecoder[_T] | AsyncJSONLDecoder[_T]:
85+
if sync:
86+
return JSONLDecoder(line_type=line_type, raw_iterator=content, http_response=httpx.Response(200))
87+
88+
return AsyncJSONLDecoder(line_type=line_type, raw_iterator=to_aiter(content), http_response=httpx.Response(200))

0 commit comments

Comments
 (0)