Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
272 commits
Select commit Hold shift + click to select a range
a9fa255
codegen metadata
stainless-app[bot] Apr 13, 2026
b25f88c
codegen metadata
stainless-app[bot] Apr 13, 2026
6543263
codegen metadata
stainless-app[bot] Apr 13, 2026
d62ccbb
codegen metadata
stainless-app[bot] Apr 13, 2026
b7d3122
codegen metadata
stainless-app[bot] Apr 13, 2026
76856c8
codegen metadata
stainless-app[bot] Apr 13, 2026
cefb783
codegen metadata
stainless-app[bot] Apr 13, 2026
ce79db4
codegen metadata
stainless-app[bot] Apr 13, 2026
640c2cd
codegen metadata
stainless-app[bot] Apr 13, 2026
c0b5f77
codegen metadata
stainless-app[bot] Apr 13, 2026
c18a5d0
codegen metadata
stainless-app[bot] Apr 13, 2026
a667a13
codegen metadata
stainless-app[bot] Apr 14, 2026
6477bd3
codegen metadata
stainless-app[bot] Apr 14, 2026
2140b18
codegen metadata
stainless-app[bot] Apr 14, 2026
40e7fa5
codegen metadata
stainless-app[bot] Apr 14, 2026
6d6ae0c
codegen metadata
stainless-app[bot] Apr 14, 2026
2fda63f
codegen metadata
stainless-app[bot] Apr 14, 2026
c72748f
codegen metadata
stainless-app[bot] Apr 14, 2026
530c29d
codegen metadata
stainless-app[bot] Apr 14, 2026
1430bf8
codegen metadata
stainless-app[bot] Apr 14, 2026
f537746
codegen metadata
stainless-app[bot] Apr 14, 2026
dd459f6
codegen metadata
stainless-app[bot] Apr 14, 2026
edb6291
codegen metadata
stainless-app[bot] Apr 14, 2026
74480b0
codegen metadata
stainless-app[bot] Apr 14, 2026
cfe4526
codegen metadata
stainless-app[bot] Apr 14, 2026
bab8180
codegen metadata
stainless-app[bot] Apr 14, 2026
5989f08
codegen metadata
stainless-app[bot] Apr 14, 2026
287b516
codegen metadata
stainless-app[bot] Apr 15, 2026
e4031e5
codegen metadata
stainless-app[bot] Apr 15, 2026
cd4df15
codegen metadata
stainless-app[bot] Apr 15, 2026
7b7beea
codegen metadata
stainless-app[bot] Apr 15, 2026
c7f43ae
codegen metadata
stainless-app[bot] Apr 15, 2026
48b124a
codegen metadata
stainless-app[bot] Apr 15, 2026
02fa9c6
codegen metadata
stainless-app[bot] Apr 15, 2026
987ff54
codegen metadata
stainless-app[bot] Apr 15, 2026
e6fe346
codegen metadata
stainless-app[bot] Apr 15, 2026
bcce240
codegen metadata
stainless-app[bot] Apr 15, 2026
f576c34
codegen metadata
stainless-app[bot] Apr 15, 2026
d2b5f2c
codegen metadata
stainless-app[bot] Apr 15, 2026
911d657
codegen metadata
stainless-app[bot] Apr 15, 2026
398b7f2
codegen metadata
stainless-app[bot] Apr 15, 2026
564c56a
codegen metadata
stainless-app[bot] Apr 15, 2026
5a60c75
codegen metadata
stainless-app[bot] Apr 15, 2026
dcf6041
codegen metadata
stainless-app[bot] Apr 15, 2026
28cfd72
codegen metadata
stainless-app[bot] Apr 15, 2026
130c3ea
codegen metadata
stainless-app[bot] Apr 15, 2026
bdd46ed
codegen metadata
stainless-app[bot] Apr 16, 2026
6f2e27d
codegen metadata
stainless-app[bot] Apr 16, 2026
a93db36
codegen metadata
stainless-app[bot] Apr 16, 2026
11062de
codegen metadata
stainless-app[bot] Apr 16, 2026
e365430
codegen metadata
stainless-app[bot] Apr 16, 2026
5b2115c
codegen metadata
stainless-app[bot] Apr 16, 2026
66ce067
codegen metadata
stainless-app[bot] Apr 16, 2026
9fb1051
codegen metadata
stainless-app[bot] Apr 16, 2026
bdbb941
codegen metadata
stainless-app[bot] Apr 16, 2026
da059e2
codegen metadata
stainless-app[bot] Apr 16, 2026
86736c3
codegen metadata
stainless-app[bot] Apr 16, 2026
9ba019e
codegen metadata
stainless-app[bot] Apr 16, 2026
fc27869
codegen metadata
stainless-app[bot] Apr 16, 2026
2925eec
codegen metadata
stainless-app[bot] Apr 16, 2026
e69c877
codegen metadata
stainless-app[bot] Apr 16, 2026
6b51f2a
codegen metadata
stainless-app[bot] Apr 16, 2026
3334bc2
codegen metadata
stainless-app[bot] Apr 16, 2026
511d1b7
codegen metadata
stainless-app[bot] Apr 16, 2026
866ca9d
codegen metadata
stainless-app[bot] Apr 17, 2026
5d37328
codegen metadata
stainless-app[bot] Apr 17, 2026
686d49b
codegen metadata
stainless-app[bot] Apr 17, 2026
5468994
codegen metadata
stainless-app[bot] Apr 17, 2026
7134171
codegen metadata
stainless-app[bot] Apr 17, 2026
f1fb606
codegen metadata
stainless-app[bot] Apr 17, 2026
ded6dfa
codegen metadata
stainless-app[bot] Apr 17, 2026
f5813bb
codegen metadata
stainless-app[bot] Apr 17, 2026
fbf6ec8
codegen metadata
stainless-app[bot] Apr 17, 2026
9a9e2f3
codegen metadata
stainless-app[bot] Apr 17, 2026
23abd7a
codegen metadata
stainless-app[bot] Apr 17, 2026
8e772c8
codegen metadata
stainless-app[bot] Apr 17, 2026
128271f
codegen metadata
stainless-app[bot] Apr 17, 2026
6100e9c
codegen metadata
stainless-app[bot] Apr 17, 2026
d33d14e
codegen metadata
stainless-app[bot] Apr 18, 2026
815bea6
codegen metadata
stainless-app[bot] Apr 18, 2026
fab2933
codegen metadata
stainless-app[bot] Apr 18, 2026
241a556
perf(client): optimize file structure copying in multipart requests
stainless-app[bot] Apr 18, 2026
5cd1c1a
codegen metadata
stainless-app[bot] Apr 18, 2026
bfba315
codegen metadata
stainless-app[bot] Apr 18, 2026
986f59f
codegen metadata
stainless-app[bot] Apr 18, 2026
d749452
codegen metadata
stainless-app[bot] Apr 18, 2026
a5de6ae
codegen metadata
stainless-app[bot] Apr 18, 2026
7af7c5e
codegen metadata
stainless-app[bot] Apr 18, 2026
41fa453
codegen metadata
stainless-app[bot] Apr 18, 2026
2f6933a
codegen metadata
stainless-app[bot] Apr 18, 2026
694b823
codegen metadata
stainless-app[bot] Apr 18, 2026
c378815
codegen metadata
stainless-app[bot] Apr 18, 2026
22b4af1
codegen metadata
stainless-app[bot] Apr 19, 2026
cd2a2f0
codegen metadata
stainless-app[bot] Apr 19, 2026
5999a26
codegen metadata
stainless-app[bot] Apr 19, 2026
cd945f2
codegen metadata
stainless-app[bot] Apr 19, 2026
b546e45
codegen metadata
stainless-app[bot] Apr 19, 2026
f9b5f4b
codegen metadata
stainless-app[bot] Apr 19, 2026
afa2a10
codegen metadata
stainless-app[bot] Apr 19, 2026
1e57f3e
codegen metadata
stainless-app[bot] Apr 19, 2026
454a194
codegen metadata
stainless-app[bot] Apr 19, 2026
a26c307
codegen metadata
stainless-app[bot] Apr 19, 2026
2d8ab53
codegen metadata
stainless-app[bot] Apr 19, 2026
1e2022a
codegen metadata
stainless-app[bot] Apr 19, 2026
128647d
codegen metadata
stainless-app[bot] Apr 19, 2026
04c1cdd
codegen metadata
stainless-app[bot] Apr 19, 2026
eb6166e
codegen metadata
stainless-app[bot] Apr 19, 2026
5829650
codegen metadata
stainless-app[bot] Apr 19, 2026
10eaae0
codegen metadata
stainless-app[bot] Apr 19, 2026
7d40331
codegen metadata
stainless-app[bot] Apr 20, 2026
baa2b1b
codegen metadata
stainless-app[bot] Apr 20, 2026
5935aa3
codegen metadata
stainless-app[bot] Apr 20, 2026
3a9bc44
codegen metadata
stainless-app[bot] Apr 20, 2026
3b0d4bb
codegen metadata
stainless-app[bot] Apr 20, 2026
d9cafa1
codegen metadata
stainless-app[bot] Apr 20, 2026
7edf051
codegen metadata
stainless-app[bot] Apr 20, 2026
80b0956
codegen metadata
stainless-app[bot] Apr 20, 2026
01a9ffa
codegen metadata
stainless-app[bot] Apr 20, 2026
9c8a614
codegen metadata
stainless-app[bot] Apr 20, 2026
6667534
codegen metadata
stainless-app[bot] Apr 20, 2026
23d4283
codegen metadata
stainless-app[bot] Apr 20, 2026
a12b7bc
codegen metadata
stainless-app[bot] Apr 20, 2026
623b39e
codegen metadata
stainless-app[bot] Apr 20, 2026
c1e49a6
codegen metadata
stainless-app[bot] Apr 20, 2026
e6fe6ab
codegen metadata
stainless-app[bot] Apr 20, 2026
152941a
codegen metadata
stainless-app[bot] Apr 20, 2026
6b92ee5
codegen metadata
stainless-app[bot] Apr 20, 2026
e71ab03
codegen metadata
stainless-app[bot] Apr 20, 2026
986e3df
codegen metadata
stainless-app[bot] Apr 20, 2026
6bd5185
codegen metadata
stainless-app[bot] Apr 21, 2026
4da07c5
codegen metadata
stainless-app[bot] Apr 21, 2026
d73872a
codegen metadata
stainless-app[bot] Apr 21, 2026
20c02b3
codegen metadata
stainless-app[bot] Apr 21, 2026
abe8272
codegen metadata
stainless-app[bot] Apr 21, 2026
4c7ec12
codegen metadata
stainless-app[bot] Apr 21, 2026
f5c3496
codegen metadata
stainless-app[bot] Apr 21, 2026
90fa64a
codegen metadata
stainless-app[bot] Apr 21, 2026
ef69220
codegen metadata
stainless-app[bot] Apr 21, 2026
fbba293
codegen metadata
stainless-app[bot] Apr 21, 2026
d927b6b
codegen metadata
stainless-app[bot] Apr 21, 2026
058e43b
codegen metadata
stainless-app[bot] Apr 21, 2026
1751fa2
codegen metadata
stainless-app[bot] Apr 21, 2026
cda1db5
codegen metadata
stainless-app[bot] Apr 21, 2026
d5b4868
codegen metadata
stainless-app[bot] Apr 21, 2026
01f0e79
codegen metadata
stainless-app[bot] Apr 21, 2026
8952fb6
codegen metadata
stainless-app[bot] Apr 22, 2026
afc3b72
codegen metadata
stainless-app[bot] Apr 22, 2026
2a7c922
codegen metadata
stainless-app[bot] Apr 22, 2026
8de02c8
codegen metadata
stainless-app[bot] Apr 22, 2026
c72b6ea
codegen metadata
stainless-app[bot] Apr 22, 2026
36b3e8e
codegen metadata
stainless-app[bot] Apr 22, 2026
8448d0e
codegen metadata
stainless-app[bot] Apr 22, 2026
4461589
codegen metadata
stainless-app[bot] Apr 22, 2026
7c92497
codegen metadata
stainless-app[bot] Apr 22, 2026
167c829
codegen metadata
stainless-app[bot] Apr 22, 2026
3ed9ea1
codegen metadata
stainless-app[bot] Apr 22, 2026
d3b401a
codegen metadata
stainless-app[bot] Apr 22, 2026
1107342
codegen metadata
stainless-app[bot] Apr 22, 2026
b918101
codegen metadata
stainless-app[bot] Apr 22, 2026
3fd7e76
codegen metadata
stainless-app[bot] Apr 22, 2026
a6908c5
codegen metadata
stainless-app[bot] Apr 22, 2026
de47c0a
codegen metadata
stainless-app[bot] Apr 22, 2026
0ae0a72
codegen metadata
stainless-app[bot] Apr 23, 2026
85e5500
codegen metadata
stainless-app[bot] Apr 23, 2026
620a803
codegen metadata
stainless-app[bot] Apr 23, 2026
b5e6e87
chore(internal): more robust bootstrap script
stainless-app[bot] Apr 23, 2026
20ce7ea
codegen metadata
stainless-app[bot] Apr 23, 2026
4f93d3d
codegen metadata
stainless-app[bot] Apr 23, 2026
5a5484f
codegen metadata
stainless-app[bot] Apr 23, 2026
9fcce5b
codegen metadata
stainless-app[bot] Apr 23, 2026
f72b9fd
codegen metadata
stainless-app[bot] Apr 23, 2026
9d24287
codegen metadata
stainless-app[bot] Apr 23, 2026
cecf262
codegen metadata
stainless-app[bot] Apr 23, 2026
94e14c4
codegen metadata
stainless-app[bot] Apr 23, 2026
95cfffc
codegen metadata
stainless-app[bot] Apr 23, 2026
dbe8abc
codegen metadata
stainless-app[bot] Apr 23, 2026
12b1791
codegen metadata
stainless-app[bot] Apr 23, 2026
7e60cb1
codegen metadata
stainless-app[bot] Apr 23, 2026
5ab96ba
codegen metadata
stainless-app[bot] Apr 23, 2026
b489d71
codegen metadata
stainless-app[bot] Apr 23, 2026
291c017
codegen metadata
stainless-app[bot] Apr 23, 2026
7f1515f
codegen metadata
stainless-app[bot] Apr 24, 2026
db040a3
codegen metadata
stainless-app[bot] Apr 24, 2026
b1ea66e
codegen metadata
stainless-app[bot] Apr 24, 2026
e6f6ee5
codegen metadata
stainless-app[bot] Apr 24, 2026
3349242
codegen metadata
stainless-app[bot] Apr 24, 2026
f3ac885
codegen metadata
stainless-app[bot] Apr 24, 2026
2b18630
codegen metadata
stainless-app[bot] Apr 24, 2026
1937c51
codegen metadata
stainless-app[bot] Apr 24, 2026
32b8432
codegen metadata
stainless-app[bot] Apr 24, 2026
914177c
codegen metadata
stainless-app[bot] Apr 24, 2026
2c4ddef
codegen metadata
stainless-app[bot] Apr 24, 2026
5dfadd8
codegen metadata
stainless-app[bot] Apr 24, 2026
5d1353a
codegen metadata
stainless-app[bot] Apr 24, 2026
f36cb16
codegen metadata
stainless-app[bot] Apr 24, 2026
544c5a7
codegen metadata
stainless-app[bot] Apr 24, 2026
1e27c2d
codegen metadata
stainless-app[bot] Apr 24, 2026
c97e980
codegen metadata
stainless-app[bot] Apr 24, 2026
50939a2
codegen metadata
stainless-app[bot] Apr 25, 2026
5dbcb0e
codegen metadata
stainless-app[bot] Apr 25, 2026
3a1d029
codegen metadata
stainless-app[bot] Apr 25, 2026
33ece9c
codegen metadata
stainless-app[bot] Apr 25, 2026
10ae1f1
codegen metadata
stainless-app[bot] Apr 25, 2026
4cfbd4e
codegen metadata
stainless-app[bot] Apr 25, 2026
d5283ad
codegen metadata
stainless-app[bot] Apr 25, 2026
b91e763
codegen metadata
stainless-app[bot] Apr 25, 2026
7d1f3a8
codegen metadata
stainless-app[bot] Apr 25, 2026
da73858
codegen metadata
stainless-app[bot] Apr 25, 2026
39f37cc
codegen metadata
stainless-app[bot] Apr 25, 2026
3f713a5
codegen metadata
stainless-app[bot] Apr 25, 2026
b1b1a68
codegen metadata
stainless-app[bot] Apr 25, 2026
0d9602f
codegen metadata
stainless-app[bot] Apr 25, 2026
3af2ea2
codegen metadata
stainless-app[bot] Apr 25, 2026
b3651db
codegen metadata
stainless-app[bot] Apr 26, 2026
de0e70f
codegen metadata
stainless-app[bot] Apr 26, 2026
fc11829
codegen metadata
stainless-app[bot] Apr 26, 2026
39e02ac
codegen metadata
stainless-app[bot] Apr 26, 2026
5f66d6a
codegen metadata
stainless-app[bot] Apr 26, 2026
37e6559
codegen metadata
stainless-app[bot] Apr 26, 2026
376b005
codegen metadata
stainless-app[bot] Apr 26, 2026
6636955
codegen metadata
stainless-app[bot] Apr 26, 2026
e1fafbb
codegen metadata
stainless-app[bot] Apr 26, 2026
7f06001
codegen metadata
stainless-app[bot] Apr 26, 2026
74fa8d0
codegen metadata
stainless-app[bot] Apr 26, 2026
801c259
codegen metadata
stainless-app[bot] Apr 26, 2026
ada298d
codegen metadata
stainless-app[bot] Apr 26, 2026
28364c6
codegen metadata
stainless-app[bot] Apr 26, 2026
3f1b388
codegen metadata
stainless-app[bot] Apr 26, 2026
83d5840
codegen metadata
stainless-app[bot] Apr 26, 2026
7ff1a35
codegen metadata
stainless-app[bot] Apr 26, 2026
0878fff
codegen metadata
stainless-app[bot] Apr 27, 2026
ee5548e
codegen metadata
stainless-app[bot] Apr 27, 2026
f238b9e
codegen metadata
stainless-app[bot] Apr 27, 2026
2a4777e
codegen metadata
stainless-app[bot] Apr 27, 2026
949df4f
codegen metadata
stainless-app[bot] Apr 27, 2026
3a8a80f
codegen metadata
stainless-app[bot] Apr 27, 2026
402082e
codegen metadata
stainless-app[bot] Apr 27, 2026
63163f2
codegen metadata
stainless-app[bot] Apr 27, 2026
11a4987
codegen metadata
stainless-app[bot] Apr 27, 2026
107dc6f
codegen metadata
stainless-app[bot] Apr 27, 2026
ac03024
codegen metadata
stainless-app[bot] Apr 27, 2026
ee8b0ef
codegen metadata
stainless-app[bot] Apr 27, 2026
22eb2fa
codegen metadata
stainless-app[bot] Apr 27, 2026
f56c092
codegen metadata
stainless-app[bot] Apr 27, 2026
5c4046a
codegen metadata
stainless-app[bot] Apr 27, 2026
d00ae59
codegen metadata
stainless-app[bot] Apr 27, 2026
a409e19
codegen metadata
stainless-app[bot] Apr 27, 2026
536843a
codegen metadata
stainless-app[bot] Apr 27, 2026
eee3aca
codegen metadata
stainless-app[bot] Apr 27, 2026
6e1ff09
release: 0.3.3
stainless-app[bot] Apr 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.3.2"
".": "0.3.3"
}
2 changes: 1 addition & 1 deletion .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 42
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/albot%2Falbot-api-sdk-75906b2c3ecc3cf24cd2f0a23454271cbd670eeb38f8e226ba9f5bf4cfec123f.yml
openapi_spec_hash: 2274994e6917d66cc573be69423e4f1a
openapi_spec_hash: f55cf27cbed5c59f0dbaf4dc96cb0c05
config_hash: cdcae65deb496342d19067f314258060
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## 0.3.3 (2026-04-27)

Full Changelog: [v0.3.2...v0.3.3](https://github.com/ALbot-developers/api-sdk-py/compare/v0.3.2...v0.3.3)

### Performance Improvements

* **client:** optimize file structure copying in multipart requests ([241a556](https://github.com/ALbot-developers/api-sdk-py/commit/241a5566f6badb021985785ceee21309771c91dc))


### Chores

* **internal:** more robust bootstrap script ([b5e6e87](https://github.com/ALbot-developers/api-sdk-py/commit/b5e6e877f9ae989bfe3d75796cb4124d5e8498ba))

## 0.3.2 (2026-04-11)

Full Changelog: [v0.3.1...v0.3.2](https://github.com/ALbot-developers/api-sdk-py/compare/v0.3.1...v0.3.2)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "albot_api_sdk"
version = "0.3.2"
version = "0.3.3"
description = "The official Python library for the albot-api-sdk API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion scripts/bootstrap
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -e

cd "$(dirname "$0")/.."

if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then
if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then
brew bundle check >/dev/null 2>&1 || {
echo -n "==> Install Homebrew dependencies? (y/N): "
read -r response
Expand Down
56 changes: 53 additions & 3 deletions src/albot_api_sdk/_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import io
import os
import pathlib
from typing import overload
from typing_extensions import TypeGuard
from typing import Sequence, cast, overload
from typing_extensions import TypeVar, TypeGuard

import anyio

Expand All @@ -17,7 +17,9 @@
HttpxFileContent,
HttpxRequestFiles,
)
from ._utils import is_tuple_t, is_mapping_t, is_sequence_t
from ._utils import is_list, is_mapping, is_tuple_t, is_mapping_t, is_sequence_t

_T = TypeVar("_T")


def is_base64_file_input(obj: object) -> TypeGuard[Base64FileInput]:
Expand Down Expand Up @@ -121,3 +123,51 @@ async def async_read_file_content(file: FileContent) -> HttpxFileContent:
return await anyio.Path(file).read_bytes()

return file


def deepcopy_with_paths(item: _T, paths: Sequence[Sequence[str]]) -> _T:
"""Copy only the containers along the given paths.

Used to guard against mutation by extract_files without copying the entire structure.
Only dicts and lists that lie on a path are copied; everything else
is returned by reference.

For example, given paths=[["foo", "files", "file"]] and the structure:
{
"foo": {
"bar": {"baz": {}},
"files": {"file": <content>}
}
}
The root dict, "foo", and "files" are copied (they lie on the path).
"bar" and "baz" are returned by reference (off the path).
"""
return _deepcopy_with_paths(item, paths, 0)


def _deepcopy_with_paths(item: _T, paths: Sequence[Sequence[str]], index: int) -> _T:
if not paths:
return item
if is_mapping(item):
key_to_paths: dict[str, list[Sequence[str]]] = {}
for path in paths:
if index < len(path):
key_to_paths.setdefault(path[index], []).append(path)

# if no path continues through this mapping, it won't be mutated and copying it is redundant
if not key_to_paths:
return item

result = dict(item)
for key, subpaths in key_to_paths.items():
if key in result:
result[key] = _deepcopy_with_paths(result[key], subpaths, index + 1)
return cast(_T, result)
if is_list(item):
array_paths = [path for path in paths if index < len(path) and path[index] == "<array>"]

# if no path expects a list here, nothing will be mutated inside it - return by reference
if not array_paths:
return cast(_T, item)
return cast(_T, [_deepcopy_with_paths(entry, array_paths, index + 1) for entry in item])
return item
1 change: 0 additions & 1 deletion src/albot_api_sdk/_utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
coerce_integer as coerce_integer,
file_from_path as file_from_path,
strip_not_given as strip_not_given,
deepcopy_minimal as deepcopy_minimal,
get_async_library as get_async_library,
maybe_coerce_float as maybe_coerce_float,
get_required_header as get_required_header,
Expand Down
15 changes: 0 additions & 15 deletions src/albot_api_sdk/_utils/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,21 +177,6 @@ def is_iterable(obj: object) -> TypeGuard[Iterable[object]]:
return isinstance(obj, Iterable)


def deepcopy_minimal(item: _T) -> _T:
"""Minimal reimplementation of copy.deepcopy() that will only copy certain object types:

- mappings, e.g. `dict`
- list

This is done for performance reasons.
"""
if is_mapping(item):
return cast(_T, {k: deepcopy_minimal(v) for k, v in item.items()})
if is_list(item):
return cast(_T, [deepcopy_minimal(entry) for entry in item])
return item


# copied from https://github.com/Rapptz/RoboDanny
def human_join(seq: Sequence[str], *, delim: str = ", ", final: str = "or") -> str:
size = len(seq)
Expand Down
2 changes: 1 addition & 1 deletion src/albot_api_sdk/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "albot_api_sdk"
__version__ = "0.3.2" # x-release-please-version
__version__ = "0.3.3" # x-release-please-version
58 changes: 0 additions & 58 deletions tests/test_deepcopy.py

This file was deleted.

99 changes: 98 additions & 1 deletion tests/test_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import pytest
from dirty_equals import IsDict, IsList, IsBytes, IsTuple

from albot_api_sdk._files import to_httpx_files, async_to_httpx_files
from albot_api_sdk._files import to_httpx_files, deepcopy_with_paths, async_to_httpx_files
from albot_api_sdk._utils import extract_files

readme_path = Path(__file__).parent.parent.joinpath("README.md")

Expand Down Expand Up @@ -49,3 +50,99 @@ def test_string_not_allowed() -> None:
"file": "foo", # type: ignore
}
)


def assert_different_identities(obj1: object, obj2: object) -> None:
assert obj1 == obj2
assert obj1 is not obj2


class TestDeepcopyWithPaths:
def test_copies_top_level_dict(self) -> None:
original = {"file": b"data", "other": "value"}
result = deepcopy_with_paths(original, [["file"]])
assert_different_identities(result, original)

def test_file_value_is_same_reference(self) -> None:
file_bytes = b"contents"
original = {"file": file_bytes}
result = deepcopy_with_paths(original, [["file"]])
assert_different_identities(result, original)
assert result["file"] is file_bytes

def test_list_popped_wholesale(self) -> None:
files = [b"f1", b"f2"]
original = {"files": files, "title": "t"}
result = deepcopy_with_paths(original, [["files", "<array>"]])
assert_different_identities(result, original)
result_files = result["files"]
assert isinstance(result_files, list)
assert_different_identities(result_files, files)

def test_nested_array_path_copies_list_and_elements(self) -> None:
elem1 = {"file": b"f1", "extra": 1}
elem2 = {"file": b"f2", "extra": 2}
original = {"items": [elem1, elem2]}
result = deepcopy_with_paths(original, [["items", "<array>", "file"]])
assert_different_identities(result, original)
result_items = result["items"]
assert isinstance(result_items, list)
assert_different_identities(result_items, original["items"])
assert_different_identities(result_items[0], elem1)
assert_different_identities(result_items[1], elem2)

def test_empty_paths_returns_same_object(self) -> None:
original = {"foo": "bar"}
result = deepcopy_with_paths(original, [])
assert result is original

def test_multiple_paths(self) -> None:
f1 = b"file1"
f2 = b"file2"
original = {"a": f1, "b": f2, "c": "unchanged"}
result = deepcopy_with_paths(original, [["a"], ["b"]])
assert_different_identities(result, original)
assert result["a"] is f1
assert result["b"] is f2
assert result["c"] is original["c"]

def test_extract_files_does_not_mutate_original_top_level(self) -> None:
file_bytes = b"contents"
original = {"file": file_bytes, "other": "value"}

copied = deepcopy_with_paths(original, [["file"]])
extracted = extract_files(copied, paths=[["file"]])

assert extracted == [("file", file_bytes)]
assert original == {"file": file_bytes, "other": "value"}
assert copied == {"other": "value"}

def test_extract_files_does_not_mutate_original_nested_array_path(self) -> None:
file1 = b"f1"
file2 = b"f2"
original = {
"items": [
{"file": file1, "extra": 1},
{"file": file2, "extra": 2},
],
"title": "example",
}

copied = deepcopy_with_paths(original, [["items", "<array>", "file"]])
extracted = extract_files(copied, paths=[["items", "<array>", "file"]])

assert extracted == [("items[][file]", file1), ("items[][file]", file2)]
assert original == {
"items": [
{"file": file1, "extra": 1},
{"file": file2, "extra": 2},
],
"title": "example",
}
assert copied == {
"items": [
{"extra": 1},
{"extra": 2},
],
"title": "example",
}
Loading