Skip to content

Commit 38ae1a2

Browse files
authored
Merge branch 'main' into fix-pdf-upload
2 parents 359a9f5 + 4e28a42 commit 38ae1a2

File tree

66 files changed

+3459
-188
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+3459
-188
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
run: ./scripts/lint
3737

3838
build:
39-
if: github.repository == 'stainless-sdks/openai-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork)
39+
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
4040
timeout-minutes: 10
4141
name: build
4242
permissions:
@@ -61,12 +61,14 @@ jobs:
6161
run: rye build
6262

6363
- name: Get GitHub OIDC Token
64+
if: github.repository == 'stainless-sdks/openai-python'
6465
id: github-oidc
6566
uses: actions/github-script@v6
6667
with:
6768
script: core.setOutput('github_token', await core.getIDToken());
6869

6970
- name: Upload tarball
71+
if: github.repository == 'stainless-sdks/openai-python'
7072
env:
7173
URL: https://pkg.stainless.com/s
7274
AUTH: ${{ steps.github-oidc.outputs.github_token }}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: CI
2+
on:
3+
pull_request:
4+
branches:
5+
- main
6+
- next
7+
8+
jobs:
9+
detect_breaking_changes:
10+
runs-on: 'ubuntu-latest'
11+
name: detect-breaking-changes
12+
if: github.repository == 'openai/openai-python'
13+
steps:
14+
- name: Calculate fetch-depth
15+
run: |
16+
echo "FETCH_DEPTH=$(expr ${{ github.event.pull_request.commits }} + 1)" >> $GITHUB_ENV
17+
18+
- uses: actions/checkout@v4
19+
with:
20+
# Ensure we can check out the pull request base in the script below.
21+
fetch-depth: ${{ env.FETCH_DEPTH }}
22+
23+
- name: Install Rye
24+
run: |
25+
curl -sSf https://rye.astral.sh/get | bash
26+
echo "$HOME/.rye/shims" >> $GITHUB_PATH
27+
env:
28+
RYE_VERSION: '0.44.0'
29+
RYE_INSTALL_OPTION: '--yes'
30+
- name: Install dependencies
31+
run: |
32+
rye sync --all-features
33+
- name: Detect removed symbols
34+
run: |
35+
rye run python scripts/detect-breaking-changes.py "${{ github.event.pull_request.base.sha }}"
36+
37+
- name: Detect breaking changes
38+
run: |
39+
# Try to check out previous versions of the breaking change detection script. This ensures that
40+
# we still detect breaking changes when entire files and their tests are removed.
41+
git checkout "${{ github.event.pull_request.base.sha }}" -- ./scripts/detect-breaking-changes 2>/dev/null || true
42+
./scripts/detect-breaking-changes ${{ github.event.pull_request.base.sha }}

.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.100.0"
2+
".": "1.101.0"
33
}

.stats.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
configured_endpoints: 111
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-24be531010b354303d741fc9247c1f84f75978f9f7de68aca92cb4f240a04722.yml
3-
openapi_spec_hash: 3e46f439f6a863beadc71577eb4efa15
4-
config_hash: ed87b9139ac595a04a2162d754df2fed
1+
configured_endpoints: 119
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-ddbdf9343316047e8a773c54fb24e4a8d225955e202a1888fde6f9c8898ebf98.yml
3+
openapi_spec_hash: 9802f6dd381558466c897f6e387e06ca
4+
config_hash: fe0ea26680ac2075a6cd66416aefe7db

CHANGELOG.md

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

3+
## 1.101.0 (2025-08-21)
4+
5+
Full Changelog: [v1.100.3...v1.101.0](https://github.com/openai/openai-python/compare/v1.100.3...v1.101.0)
6+
7+
### Features
8+
9+
* **api:** Add connectors support for MCP tool ([a47f962](https://github.com/openai/openai-python/commit/a47f962daf579c142b8af5579be732772b688a29))
10+
* **api:** adding support for /v1/conversations to the API ([e30bcbc](https://github.com/openai/openai-python/commit/e30bcbc0cb7c827af779bee6971f976261abfb67))
11+
12+
13+
### Chores
14+
15+
* update github action ([7333b28](https://github.com/openai/openai-python/commit/7333b282718a5f6977f30e1a2548207b3a089bd4))
16+
17+
## 1.100.3 (2025-08-20)
18+
19+
Full Changelog: [v1.100.2...v1.100.3](https://github.com/openai/openai-python/compare/v1.100.2...v1.100.3)
20+
21+
### Chores
22+
23+
* **internal/ci:** setup breaking change detection ([ca2f936](https://github.com/openai/openai-python/commit/ca2f93600238e875f26395faf6afbefaf15b7c97))
24+
25+
## 1.100.2 (2025-08-19)
26+
27+
Full Changelog: [v1.100.1...v1.100.2](https://github.com/openai/openai-python/compare/v1.100.1...v1.100.2)
28+
29+
### Chores
30+
31+
* **api:** accurately represent shape for verbosity on Chat Completions ([c39d5fd](https://github.com/openai/openai-python/commit/c39d5fd3f5429c6d41f257669a1dd4c67a477455))
32+
33+
## 1.100.1 (2025-08-18)
34+
35+
Full Changelog: [v1.100.0...v1.100.1](https://github.com/openai/openai-python/compare/v1.100.0...v1.100.1)
36+
37+
### Bug Fixes
38+
39+
* **types:** revert response text config deletion ([ac4fb19](https://github.com/openai/openai-python/commit/ac4fb1922ae125c8310c30e402932e8bb2976f58))
40+
341
## 1.100.0 (2025-08-18)
442

543
Full Changelog: [v1.99.9...v1.100.0](https://github.com/openai/openai-python/compare/v1.99.9...v1.100.0)

api.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,7 @@ from openai.types.responses import (
751751
ResponseContent,
752752
ResponseContentPartAddedEvent,
753753
ResponseContentPartDoneEvent,
754+
ResponseConversationParam,
754755
ResponseCreatedEvent,
755756
ResponseCustomToolCall,
756757
ResponseCustomToolCallInputDeltaEvent,
@@ -854,6 +855,54 @@ Methods:
854855

855856
- <code title="get /responses/{response_id}/input_items">client.responses.input_items.<a href="./src/openai/resources/responses/input_items.py">list</a>(response_id, \*\*<a href="src/openai/types/responses/input_item_list_params.py">params</a>) -> <a href="./src/openai/types/responses/response_item.py">SyncCursorPage[ResponseItem]</a></code>
856857

858+
# Conversations
859+
860+
Types:
861+
862+
```python
863+
from openai.types.conversations import (
864+
ComputerScreenshotContent,
865+
ContainerFileCitationBody,
866+
Conversation,
867+
ConversationDeleted,
868+
ConversationDeletedResource,
869+
FileCitationBody,
870+
InputFileContent,
871+
InputImageContent,
872+
InputTextContent,
873+
LobProb,
874+
Message,
875+
OutputTextContent,
876+
RefusalContent,
877+
SummaryTextContent,
878+
TextContent,
879+
TopLogProb,
880+
URLCitationBody,
881+
)
882+
```
883+
884+
Methods:
885+
886+
- <code title="post /conversations">client.conversations.<a href="./src/openai/resources/conversations/conversations.py">create</a>(\*\*<a href="src/openai/types/conversations/conversation_create_params.py">params</a>) -> <a href="./src/openai/types/conversations/conversation.py">Conversation</a></code>
887+
- <code title="get /conversations/{conversation_id}">client.conversations.<a href="./src/openai/resources/conversations/conversations.py">retrieve</a>(conversation_id) -> <a href="./src/openai/types/conversations/conversation.py">Conversation</a></code>
888+
- <code title="post /conversations/{conversation_id}">client.conversations.<a href="./src/openai/resources/conversations/conversations.py">update</a>(conversation_id, \*\*<a href="src/openai/types/conversations/conversation_update_params.py">params</a>) -> <a href="./src/openai/types/conversations/conversation.py">Conversation</a></code>
889+
- <code title="delete /conversations/{conversation_id}">client.conversations.<a href="./src/openai/resources/conversations/conversations.py">delete</a>(conversation_id) -> <a href="./src/openai/types/conversations/conversation_deleted_resource.py">ConversationDeletedResource</a></code>
890+
891+
## Items
892+
893+
Types:
894+
895+
```python
896+
from openai.types.conversations import ConversationItem, ConversationItemList
897+
```
898+
899+
Methods:
900+
901+
- <code title="post /conversations/{conversation_id}/items">client.conversations.items.<a href="./src/openai/resources/conversations/items.py">create</a>(conversation_id, \*\*<a href="src/openai/types/conversations/item_create_params.py">params</a>) -> <a href="./src/openai/types/conversations/conversation_item_list.py">ConversationItemList</a></code>
902+
- <code title="get /conversations/{conversation_id}/items/{item_id}">client.conversations.items.<a href="./src/openai/resources/conversations/items.py">retrieve</a>(item_id, \*, conversation_id, \*\*<a href="src/openai/types/conversations/item_retrieve_params.py">params</a>) -> <a href="./src/openai/types/conversations/conversation_item.py">ConversationItem</a></code>
903+
- <code title="get /conversations/{conversation_id}/items">client.conversations.items.<a href="./src/openai/resources/conversations/items.py">list</a>(conversation_id, \*\*<a href="src/openai/types/conversations/item_list_params.py">params</a>) -> <a href="./src/openai/types/conversations/conversation_item.py">SyncConversationCursorPage[ConversationItem]</a></code>
904+
- <code title="delete /conversations/{conversation_id}/items/{item_id}">client.conversations.items.<a href="./src/openai/resources/conversations/items.py">delete</a>(item_id, \*, conversation_id) -> <a href="./src/openai/types/conversations/conversation.py">Conversation</a></code>
905+
857906
# Evals
858907

859908
Types:

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "openai"
3-
version = "1.100.0"
3+
version = "1.101.0"
44
description = "The official Python library for the openai API"
55
dynamic = ["readme"]
66
license = "Apache-2.0"
@@ -71,6 +71,7 @@ dev-dependencies = [
7171
"trio >=0.22.2",
7272
"nest_asyncio==1.6.0",
7373
"pytest-xdist>=3.6.1",
74+
"griffe>=1",
7475
]
7576

7677
[tool.rye.scripts]

requirements-dev.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ cffi==1.16.0
4444
# via sounddevice
4545
charset-normalizer==3.3.2
4646
# via requests
47+
colorama==0.4.6
48+
# via griffe
4749
colorlog==6.7.0
4850
# via nox
4951
cryptography==42.0.7
@@ -68,6 +70,7 @@ filelock==3.12.4
6870
frozenlist==1.7.0
6971
# via aiohttp
7072
# via aiosignal
73+
griffe==1.12.1
7174
h11==0.16.0
7275
# via httpcore
7376
httpcore==1.0.9

scripts/detect-breaking-changes

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
cd "$(dirname "$0")/.."
6+
7+
echo "==> Detecting breaking changes"
8+
9+
TEST_PATHS=(
10+
tests/api_resources
11+
tests/test_client.py
12+
tests/test_response.py
13+
tests/test_legacy_response.py
14+
)
15+
16+
for PATHSPEC in "${TEST_PATHS[@]}"; do
17+
# Try to check out previous versions of the test files
18+
# with the current SDK.
19+
git checkout "$1" -- "${PATHSPEC}" 2>/dev/null || true
20+
done
21+
22+
# Instead of running the tests, use the linter to check if an
23+
# older test is no longer compatible with the latest SDK.
24+
./scripts/lint

scripts/detect-breaking-changes.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from __future__ import annotations
2+
3+
import sys
4+
from typing import Iterator
5+
from pathlib import Path
6+
7+
import rich
8+
import griffe
9+
from rich.text import Text
10+
from rich.style import Style
11+
12+
13+
def public_members(obj: griffe.Object | griffe.Alias) -> dict[str, griffe.Object | griffe.Alias]:
14+
if isinstance(obj, griffe.Alias):
15+
# ignore imports for now, they're technically part of the public API
16+
# but we don't have good preventative measures in place to prevent
17+
# changing them
18+
return {}
19+
20+
return {name: value for name, value in obj.all_members.items() if not name.startswith("_")}
21+
22+
23+
def find_breaking_changes(
24+
new_obj: griffe.Object | griffe.Alias,
25+
old_obj: griffe.Object | griffe.Alias,
26+
*,
27+
path: list[str],
28+
) -> Iterator[Text | str]:
29+
new_members = public_members(new_obj)
30+
old_members = public_members(old_obj)
31+
32+
for name, old_member in old_members.items():
33+
if isinstance(old_member, griffe.Alias) and len(path) > 2:
34+
# ignore imports in `/types/` for now, they're technically part of the public API
35+
# but we don't have good preventative measures in place to prevent changing them
36+
continue
37+
38+
new_member = new_members.get(name)
39+
if new_member is None:
40+
cls_name = old_member.__class__.__name__
41+
yield Text(f"({cls_name})", style=Style(color="rgb(119, 119, 119)"))
42+
yield from [" " for _ in range(10 - len(cls_name))]
43+
yield f" {'.'.join(path)}.{name}"
44+
yield "\n"
45+
continue
46+
47+
yield from find_breaking_changes(new_member, old_member, path=[*path, name])
48+
49+
50+
def main() -> None:
51+
try:
52+
against_ref = sys.argv[1]
53+
except IndexError as err:
54+
raise RuntimeError("You must specify a base ref to run breaking change detection against") from err
55+
56+
package = griffe.load(
57+
"openai",
58+
search_paths=[Path(__file__).parent.parent.joinpath("src")],
59+
)
60+
old_package = griffe.load_git(
61+
"openai",
62+
ref=against_ref,
63+
search_paths=["src"],
64+
)
65+
assert isinstance(package, griffe.Module)
66+
assert isinstance(old_package, griffe.Module)
67+
68+
output = list(find_breaking_changes(package, old_package, path=["openai"]))
69+
if output:
70+
rich.print(Text("Breaking changes detected!", style=Style(color="rgb(165, 79, 87)")))
71+
rich.print()
72+
73+
for text in output:
74+
rich.print(text, end="")
75+
76+
sys.exit(1)
77+
78+
79+
main()

0 commit comments

Comments
 (0)