diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index ac9a2e75..ff261bad 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -3,7 +3,7 @@ FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}
USER vscode
-RUN curl -sSf https://rye.astral.sh/get | RYE_VERSION="0.35.0" RYE_INSTALL_OPTION="--yes" bash
+RUN curl -sSf https://rye.astral.sh/get | RYE_VERSION="0.44.0" RYE_INSTALL_OPTION="--yes" bash
ENV PATH=/home/vscode/.rye/shims:$PATH
-RUN echo "[[ -d .venv ]] && source .venv/bin/activate" >> /home/vscode/.bashrc
+RUN echo "[[ -d .venv ]] && source .venv/bin/activate || export PATH=\$PATH" >> /home/vscode/.bashrc
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index bbeb30b1..c17fdc16 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -24,6 +24,9 @@
}
}
}
+ },
+ "features": {
+ "ghcr.io/devcontainers/features/node:1": {}
}
// Features to add to the dev container. More info: https://containers.dev/features.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 40293964..0b0a288b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,19 +1,18 @@
name: CI
on:
push:
- branches:
- - main
- pull_request:
- branches:
- - main
- - next
+ branches-ignore:
+ - 'generated'
+ - 'codegen/**'
+ - 'integrated/**'
+ - 'stl-preview-head/**'
+ - 'stl-preview-base/**'
jobs:
lint:
+ timeout-minutes: 10
name: lint
- runs-on: ubuntu-latest
-
-
+ runs-on: ${{ github.repository == 'stainless-sdks/braintrust-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v4
@@ -22,7 +21,7 @@ jobs:
curl -sSf https://rye.astral.sh/get | bash
echo "$HOME/.rye/shims" >> $GITHUB_PATH
env:
- RYE_VERSION: '0.35.0'
+ RYE_VERSION: '0.44.0'
RYE_INSTALL_OPTION: '--yes'
- name: Install dependencies
@@ -30,10 +29,35 @@ jobs:
- name: Run lints
run: ./scripts/lint
+
+ upload:
+ if: github.repository == 'stainless-sdks/braintrust-sdk-python'
+ timeout-minutes: 10
+ name: upload
+ permissions:
+ contents: read
+ id-token: write
+ runs-on: depot-ubuntu-24.04
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Get GitHub OIDC Token
+ id: github-oidc
+ uses: actions/github-script@v6
+ with:
+ script: core.setOutput('github_token', await core.getIDToken());
+
+ - name: Upload tarball
+ env:
+ URL: https://pkg.stainless.com/s
+ AUTH: ${{ steps.github-oidc.outputs.github_token }}
+ SHA: ${{ github.sha }}
+ run: ./scripts/utils/upload-artifact.sh
+
test:
+ timeout-minutes: 10
name: test
- runs-on: ubuntu-latest
-
+ runs-on: ${{ github.repository == 'stainless-sdks/braintrust-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v4
@@ -42,7 +66,7 @@ jobs:
curl -sSf https://rye.astral.sh/get | bash
echo "$HOME/.rye/shims" >> $GITHUB_PATH
env:
- RYE_VERSION: '0.35.0'
+ RYE_VERSION: '0.44.0'
RYE_INSTALL_OPTION: '--yes'
- name: Bootstrap
@@ -50,4 +74,3 @@ jobs:
- name: Run tests
run: ./scripts/test
-
diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml
index a203b657..d11b76b1 100755
--- a/.github/workflows/publish-pypi.yml
+++ b/.github/workflows/publish-pypi.yml
@@ -21,7 +21,7 @@ jobs:
curl -sSf https://rye.astral.sh/get | bash
echo "$HOME/.rye/shims" >> $GITHUB_PATH
env:
- RYE_VERSION: '0.35.0'
+ RYE_VERSION: '0.44.0'
RYE_INSTALL_OPTION: '--yes'
- name: Publish to PyPI
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 4208b5cb..1b77f506 100755
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.6.0"
+ ".": "0.7.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index bb136169..91f6c416 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,2 +1,4 @@
configured_endpoints: 110
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/manugoyal%2Fbraintrust-sdk-ce135a587d4ea037e39949984ed8f98578043e8c3a90fa203d24f28d234d8675.yml
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/manugoyal%2Fbraintrust-sdk-f0d64ce0e0efde75f9c171f7f3c3d4a72f00a77abb3bc5a7d65b7be1e715689b.yml
+openapi_spec_hash: a027e48cc6aea2fab3cbdd38f4081119
+config_hash: 1ea10787f4def6c54a53f0e6f776f0a5
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0df187f6..936af3c3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,101 @@
# Changelog
+## 0.7.0 (2025-05-16)
+
+Full Changelog: [v0.6.0...v0.7.0](https://github.com/braintrustdata/braintrust-api-py/compare/v0.6.0...v0.7.0)
+
+### Features
+
+* **api:** manual updates ([#118](https://github.com/braintrustdata/braintrust-api-py/issues/118)) ([e06c7c2](https://github.com/braintrustdata/braintrust-api-py/commit/e06c7c2d2a365e6e59c885358485bdfa1413bc40))
+* **api:** manual updates ([#119](https://github.com/braintrustdata/braintrust-api-py/issues/119)) ([e37a8c1](https://github.com/braintrustdata/braintrust-api-py/commit/e37a8c1b81f31ea4795150dae1ce1a92474b6b6f))
+* **api:** manual updates ([#120](https://github.com/braintrustdata/braintrust-api-py/issues/120)) ([bcf8542](https://github.com/braintrustdata/braintrust-api-py/commit/bcf854293c2afc6d093ccdb84a9eb8d397f5831e))
+* **client:** allow passing `NotGiven` for body ([#109](https://github.com/braintrustdata/braintrust-api-py/issues/109)) ([731a3a1](https://github.com/braintrustdata/braintrust-api-py/commit/731a3a13b3f1cad4e5211684078f020487262076))
+* **client:** send `X-Stainless-Read-Timeout` header ([#104](https://github.com/braintrustdata/braintrust-api-py/issues/104)) ([a81d0cb](https://github.com/braintrustdata/braintrust-api-py/commit/a81d0cb7af62e5cbcf4a7492652e873737575afc))
+
+
+### Bug Fixes
+
+* **api:** better support union schemas with common properties ([#92](https://github.com/braintrustdata/braintrust-api-py/issues/92)) ([12e53c2](https://github.com/braintrustdata/braintrust-api-py/commit/12e53c2d042af021874740c0442d1dd8f691e68d))
+* asyncify on non-asyncio runtimes ([#108](https://github.com/braintrustdata/braintrust-api-py/issues/108)) ([2cd0b7e](https://github.com/braintrustdata/braintrust-api-py/commit/2cd0b7eadcef42310cdaaab88e261661baf66e07))
+* **ci:** ensure pip is always available ([#123](https://github.com/braintrustdata/braintrust-api-py/issues/123)) ([62dff95](https://github.com/braintrustdata/braintrust-api-py/commit/62dff9577d3888dfbcb811a1d95f2d19950711e7))
+* **ci:** remove publishing patch ([#124](https://github.com/braintrustdata/braintrust-api-py/issues/124)) ([e0320a6](https://github.com/braintrustdata/braintrust-api-py/commit/e0320a6eb1d40e8d15453d97ed53ccd5e4ec87cd))
+* **client:** mark some request bodies as optional ([731a3a1](https://github.com/braintrustdata/braintrust-api-py/commit/731a3a13b3f1cad4e5211684078f020487262076))
+* **client:** only call .close() when needed ([#89](https://github.com/braintrustdata/braintrust-api-py/issues/89)) ([b17e41e](https://github.com/braintrustdata/braintrust-api-py/commit/b17e41e01a865ecce9fb7dd53fe0e454ee831a91))
+* correctly handle deserialising `cls` fields ([#94](https://github.com/braintrustdata/braintrust-api-py/issues/94)) ([72ebbe1](https://github.com/braintrustdata/braintrust-api-py/commit/72ebbe1fb979d13e557b5728b914ec07c59c307a))
+* **package:** support direct resource imports ([b14060f](https://github.com/braintrustdata/braintrust-api-py/commit/b14060f4bfe687f593518165d5c7ab8e1f0ea748))
+* **perf:** optimize some hot paths ([8aa7193](https://github.com/braintrustdata/braintrust-api-py/commit/8aa71935dbdb15e65aa50ea14eabd1f5ae27524e))
+* **perf:** skip traversing types for NotGiven values ([cdf262b](https://github.com/braintrustdata/braintrust-api-py/commit/cdf262bf241b311addbbac638b97b99bf5038f46))
+* **pydantic v1:** more robust ModelField.annotation check ([640f98b](https://github.com/braintrustdata/braintrust-api-py/commit/640f98bf04edb7148d4e217dffe7f20d403185fa))
+* **tests:** make test_get_platform less flaky ([#97](https://github.com/braintrustdata/braintrust-api-py/issues/97)) ([539f898](https://github.com/braintrustdata/braintrust-api-py/commit/539f898c0ef3bd3b97889a6f25debd058fbbb0b0))
+* **types:** add missing total=False ([#126](https://github.com/braintrustdata/braintrust-api-py/issues/126)) ([74ea3e8](https://github.com/braintrustdata/braintrust-api-py/commit/74ea3e86731ebd651f4051865a636f06b16998d3))
+* **types:** handle more discriminated union shapes ([#122](https://github.com/braintrustdata/braintrust-api-py/issues/122)) ([fcf590f](https://github.com/braintrustdata/braintrust-api-py/commit/fcf590f9015ed87e8c52661460535f3cf38a8ac0))
+
+
+### Chores
+
+* add missing isclass check ([#87](https://github.com/braintrustdata/braintrust-api-py/issues/87)) ([bfb504b](https://github.com/braintrustdata/braintrust-api-py/commit/bfb504b89946d937964fa6b11ad9ec759f44ca5f))
+* broadly detect json family of content-type headers ([eb1c4af](https://github.com/braintrustdata/braintrust-api-py/commit/eb1c4af14b0c59330ac2abf8b948d26f3991189c))
+* **ci:** add timeout thresholds for CI jobs ([8eb40d8](https://github.com/braintrustdata/braintrust-api-py/commit/8eb40d826eebb275e0c6d23cade9accbe94fe729))
+* **ci:** fix installation instructions ([8aa8c86](https://github.com/braintrustdata/braintrust-api-py/commit/8aa8c861b4914dc2fbf935591c7d6f1cd8498e89))
+* **ci:** only use depot for staging repos ([3740879](https://github.com/braintrustdata/braintrust-api-py/commit/3740879ac2684ca7a65a6ba828dee58bcc3230a0))
+* **ci:** upload sdks to package manager ([28aed61](https://github.com/braintrustdata/braintrust-api-py/commit/28aed610cacb5a18f5769af481417ba4c7a0ae29))
+* **client:** minor internal fixes ([fa4d5c4](https://github.com/braintrustdata/braintrust-api-py/commit/fa4d5c402e177ad66b99927daec35a5879edb35d))
+* **client:** simplify `Optional[object]` to just `object` ([#86](https://github.com/braintrustdata/braintrust-api-py/issues/86)) ([edc7ec8](https://github.com/braintrustdata/braintrust-api-py/commit/edc7ec8b753f0966b0dc46fbf67889d5600ebf12))
+* **docs:** update client docstring ([#113](https://github.com/braintrustdata/braintrust-api-py/issues/113)) ([ef563e2](https://github.com/braintrustdata/braintrust-api-py/commit/ef563e21b1746f8836b218626d65e92b7bfb62e4))
+* fix typos ([#125](https://github.com/braintrustdata/braintrust-api-py/issues/125)) ([15f7e02](https://github.com/braintrustdata/braintrust-api-py/commit/15f7e0208fc481b67bad494d393c7d364574c514))
+* **internal:** avoid errors for isinstance checks on proxies ([dcde56a](https://github.com/braintrustdata/braintrust-api-py/commit/dcde56ab1f270935868e289287141ad5891ac0e5))
+* **internal:** avoid pytest-asyncio deprecation warning ([#98](https://github.com/braintrustdata/braintrust-api-py/issues/98)) ([58f4215](https://github.com/braintrustdata/braintrust-api-py/commit/58f4215a46c8acb0676defb807ef1bb2dbd5888b))
+* **internal:** base client updates ([ab8ab97](https://github.com/braintrustdata/braintrust-api-py/commit/ab8ab979c40c40b7c1cc97fd65dcf10f29af5d02))
+* **internal:** bummp ruff dependency ([#103](https://github.com/braintrustdata/braintrust-api-py/issues/103)) ([704af11](https://github.com/braintrustdata/braintrust-api-py/commit/704af11b4f64bbdf5ec673c20bfb3ddbae4fee66))
+* **internal:** bump httpx dependency ([#88](https://github.com/braintrustdata/braintrust-api-py/issues/88)) ([f37b2d0](https://github.com/braintrustdata/braintrust-api-py/commit/f37b2d035467e512ecc0676a2b1643b0fcbb1f4f))
+* **internal:** bump pydantic dependency ([#75](https://github.com/braintrustdata/braintrust-api-py/issues/75)) ([cee4d9d](https://github.com/braintrustdata/braintrust-api-py/commit/cee4d9d69b1cd28992af885f09392757af3e9859))
+* **internal:** bump pyright version ([019fea9](https://github.com/braintrustdata/braintrust-api-py/commit/019fea9772ccb410b2b8c624854037b2c63352b2))
+* **internal:** bump rye to 0.44.0 ([#121](https://github.com/braintrustdata/braintrust-api-py/issues/121)) ([97b0d81](https://github.com/braintrustdata/braintrust-api-py/commit/97b0d817a4909467cff0caaf143411bf5d904434))
+* **internal:** change default timeout to an int ([#102](https://github.com/braintrustdata/braintrust-api-py/issues/102)) ([02ff898](https://github.com/braintrustdata/braintrust-api-py/commit/02ff898796501d1baf9b7f79113796f7d61ef9e6))
+* **internal:** codegen related update ([0a80ffd](https://github.com/braintrustdata/braintrust-api-py/commit/0a80ffd780ef8d3b4fa4227d5259799f9811740a))
+* **internal:** codegen related update ([#101](https://github.com/braintrustdata/braintrust-api-py/issues/101)) ([74c72a3](https://github.com/braintrustdata/braintrust-api-py/commit/74c72a341c219b85a081bf4606a6caf0eac117ba))
+* **internal:** codegen related update ([#72](https://github.com/braintrustdata/braintrust-api-py/issues/72)) ([c8d3baf](https://github.com/braintrustdata/braintrust-api-py/commit/c8d3baf536473fc7b2d85e39ce8a498228c03bea))
+* **internal:** codegen related update ([#77](https://github.com/braintrustdata/braintrust-api-py/issues/77)) ([e6d7e6d](https://github.com/braintrustdata/braintrust-api-py/commit/e6d7e6d31b02f43cb1a6b83ed78482c73e99567d))
+* **internal:** codegen related update ([#78](https://github.com/braintrustdata/braintrust-api-py/issues/78)) ([3805a84](https://github.com/braintrustdata/braintrust-api-py/commit/3805a841cf5e78904c2e25984a13d948b8cdf12f))
+* **internal:** codegen related update ([#79](https://github.com/braintrustdata/braintrust-api-py/issues/79)) ([d02caf0](https://github.com/braintrustdata/braintrust-api-py/commit/d02caf0bd34c711cec98358243b6b370eb78edf7))
+* **internal:** codegen related update ([#81](https://github.com/braintrustdata/braintrust-api-py/issues/81)) ([0f9e170](https://github.com/braintrustdata/braintrust-api-py/commit/0f9e17051ea65e878c5a02de502e80a292918294))
+* **internal:** codegen related update ([#82](https://github.com/braintrustdata/braintrust-api-py/issues/82)) ([c62a02c](https://github.com/braintrustdata/braintrust-api-py/commit/c62a02cb45f7191c6058e5d667499228918351db))
+* **internal:** codegen related update ([#85](https://github.com/braintrustdata/braintrust-api-py/issues/85)) ([04d214e](https://github.com/braintrustdata/braintrust-api-py/commit/04d214e0ba25d375fc3c816f68bad370e0b0b63d))
+* **internal:** codegen related update ([#91](https://github.com/braintrustdata/braintrust-api-py/issues/91)) ([f4ff2a9](https://github.com/braintrustdata/braintrust-api-py/commit/f4ff2a98ab561f6e4e03a78ee358af17f7a27132))
+* **internal:** codegen related update ([#95](https://github.com/braintrustdata/braintrust-api-py/issues/95)) ([2a4460a](https://github.com/braintrustdata/braintrust-api-py/commit/2a4460a7446ed72b958ee1f5257effe850a1802d))
+* **internal:** expand CI branch coverage ([a3a2656](https://github.com/braintrustdata/braintrust-api-py/commit/a3a265646ff09013b603bffb3b7358590b112fd0))
+* **internal:** fix devcontainers setup ([#110](https://github.com/braintrustdata/braintrust-api-py/issues/110)) ([d782782](https://github.com/braintrustdata/braintrust-api-py/commit/d78278233d819b0ae3d2ebfb16eae38b522f9771))
+* **internal:** fix list file params ([b6639ab](https://github.com/braintrustdata/braintrust-api-py/commit/b6639abffec648d42b94373c98d5a889a62aae22))
+* **internal:** fix some typos ([#84](https://github.com/braintrustdata/braintrust-api-py/issues/84)) ([1afb368](https://github.com/braintrustdata/braintrust-api-py/commit/1afb368da87a73c1df3db45c758c7d50827daf27))
+* **internal:** fix type traversing dictionary params ([#105](https://github.com/braintrustdata/braintrust-api-py/issues/105)) ([46076eb](https://github.com/braintrustdata/braintrust-api-py/commit/46076ebb88673834f48110408883fb5387a94c47))
+* **internal:** import reformatting ([dbac172](https://github.com/braintrustdata/braintrust-api-py/commit/dbac172106ee60ea78d749d974557cc9ff90d891))
+* **internal:** minor formatting changes ([77de939](https://github.com/braintrustdata/braintrust-api-py/commit/77de9399a9ff9e2b98359f590cf806ae2f6da11e))
+* **internal:** minor formatting changes ([#100](https://github.com/braintrustdata/braintrust-api-py/issues/100)) ([ff3d099](https://github.com/braintrustdata/braintrust-api-py/commit/ff3d099982eecfafda24f00ed8fbe3d3fd7b5162))
+* **internal:** minor style changes ([#99](https://github.com/braintrustdata/braintrust-api-py/issues/99)) ([b40d0f4](https://github.com/braintrustdata/braintrust-api-py/commit/b40d0f4efd5aba49466a07567158aefeead39614))
+* **internal:** minor type handling changes ([#106](https://github.com/braintrustdata/braintrust-api-py/issues/106)) ([2c42ae6](https://github.com/braintrustdata/braintrust-api-py/commit/2c42ae6dec7232ff806c0320840ffdd2036fc543))
+* **internal:** properly set __pydantic_private__ ([#111](https://github.com/braintrustdata/braintrust-api-py/issues/111)) ([0cde4b1](https://github.com/braintrustdata/braintrust-api-py/commit/0cde4b1f436edc303aec5a3ac8e68899c84fa02a))
+* **internal:** reduce CI branch coverage ([1997d9b](https://github.com/braintrustdata/braintrust-api-py/commit/1997d9b5d408d96d2fae5d8d1b8d565250ea4690))
+* **internal:** refactor retries to not use recursion ([9105502](https://github.com/braintrustdata/braintrust-api-py/commit/9105502535ea87fe89eb43173da10b0ecaa7f9cc))
+* **internal:** remove extra empty newlines ([#117](https://github.com/braintrustdata/braintrust-api-py/issues/117)) ([10305c5](https://github.com/braintrustdata/braintrust-api-py/commit/10305c5c85a0767ba4cc9c6f12b5df2c0b850a3e))
+* **internal:** remove trailing character ([#127](https://github.com/braintrustdata/braintrust-api-py/issues/127)) ([e49928a](https://github.com/braintrustdata/braintrust-api-py/commit/e49928a4e121ece341f97140c49654992b356e3e))
+* **internal:** remove unused http client options forwarding ([#114](https://github.com/braintrustdata/braintrust-api-py/issues/114)) ([0a60d39](https://github.com/braintrustdata/braintrust-api-py/commit/0a60d3912df8fd72902d9467742f75b9b43ab7e1))
+* **internal:** slight transform perf improvement ([#128](https://github.com/braintrustdata/braintrust-api-py/issues/128)) ([7254708](https://github.com/braintrustdata/braintrust-api-py/commit/7254708f928fd60b5c211af8fc92b5fb3498e2bf))
+* **internal:** update client tests ([#107](https://github.com/braintrustdata/braintrust-api-py/issues/107)) ([ef75a36](https://github.com/braintrustdata/braintrust-api-py/commit/ef75a36384ab8f0a9d2db94af5df59f8387991e0))
+* **internal:** update models test ([e33fb48](https://github.com/braintrustdata/braintrust-api-py/commit/e33fb48b58e327e3ad908e926cd4104e10e360f0))
+* **internal:** update pyright settings ([279561f](https://github.com/braintrustdata/braintrust-api-py/commit/279561f0479b4133dec3c182a59ccce3e30ed7d1))
+* **internal:** updated imports ([#80](https://github.com/braintrustdata/braintrust-api-py/issues/80)) ([3bc669f](https://github.com/braintrustdata/braintrust-api-py/commit/3bc669fe9661325e0d10f94a89f982afecbea043))
+* make the `Omit` type public ([#74](https://github.com/braintrustdata/braintrust-api-py/issues/74)) ([e5ea14a](https://github.com/braintrustdata/braintrust-api-py/commit/e5ea14afcd44cb9562c9c0ccc557bbee5531f685))
+
+
+### Documentation
+
+* fix typos ([#90](https://github.com/braintrustdata/braintrust-api-py/issues/90)) ([d717022](https://github.com/braintrustdata/braintrust-api-py/commit/d717022b9e153a081f750b2d4aa30bf1a9ec25b6))
+* **raw responses:** fix duplicate `the` ([#96](https://github.com/braintrustdata/braintrust-api-py/issues/96)) ([2af70ba](https://github.com/braintrustdata/braintrust-api-py/commit/2af70ba015d6b0f7bc70586b29f651514001784b))
+* **readme:** example snippet for client context manager ([#83](https://github.com/braintrustdata/braintrust-api-py/issues/83)) ([d38014d](https://github.com/braintrustdata/braintrust-api-py/commit/d38014dcb54bc8a869f0ddc4afc987cd46e8f659))
+* **readme:** fix http client proxies example ([#76](https://github.com/braintrustdata/braintrust-api-py/issues/76)) ([eebb262](https://github.com/braintrustdata/braintrust-api-py/commit/eebb2621dc7c847f3ab458ef9292269df342ab04))
+* revise readme docs about nested params ([#115](https://github.com/braintrustdata/braintrust-api-py/issues/115)) ([c372084](https://github.com/braintrustdata/braintrust-api-py/commit/c372084db61445d20d918aaa44b036480ea60020))
+* update URLs from stainlessapi.com to stainless.com ([#112](https://github.com/braintrustdata/braintrust-api-py/issues/112)) ([f369b75](https://github.com/braintrustdata/braintrust-api-py/commit/f369b750d0de33ac22a20fa6b525b242987627b1))
+
## 0.6.0 (2024-11-28)
Full Changelog: [v0.5.0...v0.6.0](https://github.com/braintrustdata/braintrust-api-py/compare/v0.5.0...v0.6.0)
diff --git a/LICENSE b/LICENSE
index 5e03e95a..f3b9e7e5 100755
--- a/LICENSE
+++ b/LICENSE
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright 2024 Braintrust
+ Copyright 2025 Braintrust
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/README.md b/README.md
index 3f1b9b67..c342bf05 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ The Braintrust Python library provides convenient access to the Braintrust REST
application. The library includes type definitions for all request params and response fields,
and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).
-It is generated with [Stainless](https://www.stainlessapi.com/).
+It is generated with [Stainless](https://www.stainless.com/).
## Documentation
@@ -140,6 +140,33 @@ for project in first_page.objects:
# Remove `await` for non-async usage.
```
+## Nested params
+
+Nested parameters are dictionaries, typed using `TypedDict`, for example:
+
+```python
+from braintrust_api import Braintrust
+
+client = Braintrust()
+
+project = client.projects.update(
+ project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ settings={
+ "baseline_experiment_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "comparison_key": "comparison_key",
+ "span_field_order": [
+ {
+ "column_id": "column_id",
+ "object_type": "object_type",
+ "position": "position",
+ "layout": "full",
+ }
+ ],
+ },
+)
+print(project.settings)
+```
+
## Handling errors
When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `braintrust_api.APIConnectionError` is raised.
@@ -170,7 +197,7 @@ except braintrust_api.APIStatusError as e:
print(e.response)
```
-Error codes are as followed:
+Error codes are as follows:
| Status Code | Error Type |
| ----------- | -------------------------- |
@@ -309,8 +336,7 @@ If you need to access undocumented endpoints, params, or response properties, th
#### Undocumented endpoints
To make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other
-http verbs. Options on the client will be respected (such as retries) will be respected when making this
-request.
+http verbs. Options on the client will be respected (such as retries) when making this request.
```py
import httpx
@@ -339,18 +365,19 @@ can also get all the extra fields on the Pydantic model as a dict with
You can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:
-- Support for proxies
-- Custom transports
+- Support for [proxies](https://www.python-httpx.org/advanced/proxies/)
+- Custom [transports](https://www.python-httpx.org/advanced/transports/)
- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality
```python
+import httpx
from braintrust_api import Braintrust, DefaultHttpxClient
client = Braintrust(
# Or use the `BRAINTRUST_BASE_URL` env var
base_url="http://my.test.server.example.com:8083",
http_client=DefaultHttpxClient(
- proxies="http://my.test.proxy.example.com",
+ proxy="http://my.test.proxy.example.com",
transport=httpx.HTTPTransport(local_address="0.0.0.0"),
),
)
@@ -366,12 +393,22 @@ client.with_options(http_client=DefaultHttpxClient(...))
By default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting.
+```py
+from braintrust_api import Braintrust
+
+with Braintrust() as client:
+ # make requests here
+ ...
+
+# HTTP client is now closed
+```
+
## Versioning
This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:
1. Changes that only affect static types, without breaking runtime behavior.
-2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals)_.
+2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_
3. Changes that we do not expect to impact the vast majority of users in practice.
We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
diff --git a/SECURITY.md b/SECURITY.md
index 9e161b9a..0923aae0 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -2,9 +2,9 @@
## Reporting Security Issues
-This SDK is generated by [Stainless Software Inc](http://stainlessapi.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken.
+This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken.
-To report a security issue, please contact the Stainless team at security@stainlessapi.com.
+To report a security issue, please contact the Stainless team at security@stainless.com.
## Responsible Disclosure
diff --git a/api.md b/api.md
index 337683fb..dcc2ef0a 100644
--- a/api.md
+++ b/api.md
@@ -5,6 +5,7 @@ from braintrust_api.types import (
AISecret,
ACL,
ACLBatchUpdateResponse,
+ ACLObjectType,
APIKey,
ChatCompletionContentPartImage,
ChatCompletionContentPartText,
@@ -16,6 +17,7 @@ from braintrust_api.types import (
Dataset,
DatasetEvent,
EnvVar,
+ EnvVarObjectType,
Experiment,
ExperimentEvent,
FeedbackDatasetItem,
@@ -32,14 +34,17 @@ from braintrust_api.types import (
InsertExperimentEvent,
InsertProjectLogsEvent,
MetricSummary,
+ ObjectReference,
OnlineScoreConfig,
Organization,
PatchOrganizationMembersOutput,
+ Permission,
Project,
ProjectLogsEvent,
ProjectScore,
ProjectScoreCategory,
ProjectScoreConfig,
+ ProjectScoreType,
ProjectSettings,
ProjectTag,
Prompt,
@@ -50,6 +55,7 @@ from braintrust_api.types import (
ScoreSummary,
SpanAttributes,
SpanIFrame,
+ SpanType,
SummarizeDatasetResponse,
SummarizeExperimentResponse,
User,
@@ -57,6 +63,7 @@ from braintrust_api.types import (
ViewData,
ViewDataSearch,
ViewOptions,
+ ViewType,
)
```
@@ -162,7 +169,7 @@ Methods:
- client.acls.retrieve(acl_id) -> ACL
- client.acls.list(\*\*params) -> SyncListObjects[ACL]
- client.acls.delete(acl_id) -> ACL
-- client.acls.batch_update(\*\*params) -> ACLBatchUpdateResponse
+- client.acls.batch_update(\*\*params) -> ACLBatchUpdateResponse
- client.acls.find_and_delete(\*\*params) -> ACL
# Users
diff --git a/bin/publish-pypi b/bin/publish-pypi
index 05bfccbb..826054e9 100755
--- a/bin/publish-pypi
+++ b/bin/publish-pypi
@@ -3,7 +3,4 @@
set -eux
mkdir -p dist
rye build --clean
-# Patching importlib-metadata version until upstream library version is updated
-# https://github.com/pypa/twine/issues/977#issuecomment-2189800841
-"$HOME/.rye/self/bin/python3" -m pip install 'importlib-metadata==7.2.1'
rye publish --yes --token=$PYPI_TOKEN
diff --git a/mypy.ini b/mypy.ini
index 862082c9..ab3e1b9c 100644
--- a/mypy.ini
+++ b/mypy.ini
@@ -41,7 +41,7 @@ cache_fine_grained = True
# ```
# Changing this codegen to make mypy happy would increase complexity
# and would not be worth it.
-disable_error_code = func-returns-value
+disable_error_code = func-returns-value,overload-cannot-match
# https://github.com/python/mypy/issues/12162
[mypy.overrides]
diff --git a/pyproject.toml b/pyproject.toml
index 18fbdd40..55c42eac 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "braintrust-api"
-version = "0.6.0"
+version = "0.7.0"
description = "The official Python library for the braintrust API"
dynamic = ["readme"]
license = "Apache-2.0"
@@ -10,7 +10,7 @@ authors = [
dependencies = [
"httpx>=0.23.0, <1",
"pydantic>=1.9.0, <3",
- "typing-extensions>=4.7, <5",
+ "typing-extensions>=4.10, <5",
"anyio>=3.5.0, <5",
"distro>=1.7.0, <2",
"sniffio",
@@ -38,12 +38,11 @@ Homepage = "https://github.com/braintrustdata/braintrust-api-py"
Repository = "https://github.com/braintrustdata/braintrust-api-py"
-
[tool.rye]
managed = true
# version pins are in requirements-dev.lock
dev-dependencies = [
- "pyright>=1.1.359",
+ "pyright==1.1.399",
"mypy",
"respx",
"pytest",
@@ -54,7 +53,7 @@ dev-dependencies = [
"dirty-equals>=0.6.0",
"importlib-metadata>=6.7.0",
"rich>=13.7.1",
- "nest_asyncio==1.6.0"
+ "nest_asyncio==1.6.0",
]
[tool.rye.scripts]
@@ -87,7 +86,7 @@ typecheck = { chain = [
"typecheck:mypy" = "mypy ."
[build-system]
-requires = ["hatchling", "hatch-fancy-pypi-readme"]
+requires = ["hatchling==1.26.3", "hatch-fancy-pypi-readme"]
build-backend = "hatchling.build"
[tool.hatch.build]
@@ -129,6 +128,7 @@ testpaths = ["tests"]
addopts = "--tb=short"
xfail_strict = true
asyncio_mode = "auto"
+asyncio_default_fixture_loop_scope = "session"
filterwarnings = [
"error"
]
@@ -147,11 +147,11 @@ exclude = [
]
reportImplicitOverride = true
+reportOverlappingOverload = false
reportImportCycles = false
reportPrivateUsage = false
-
[tool.ruff]
line-length = 120
output-format = "grouped"
@@ -176,7 +176,7 @@ select = [
"T201",
"T203",
# misuse of typing.TYPE_CHECKING
- "TCH004",
+ "TC004",
# import rules
"TID251",
]
diff --git a/requirements-dev.lock b/requirements-dev.lock
index 0cf1d5b6..969996f0 100644
--- a/requirements-dev.lock
+++ b/requirements-dev.lock
@@ -7,6 +7,7 @@
# all-features: true
# with-sources: false
# generate-hashes: false
+# universal: false
-e file:.
annotated-types==0.6.0
@@ -35,7 +36,7 @@ h11==0.14.0
# via httpcore
httpcore==1.0.2
# via httpx
-httpx==0.25.2
+httpx==0.28.1
# via braintrust-api
# via respx
idna==3.4
@@ -48,7 +49,7 @@ markdown-it-py==3.0.0
# via rich
mdurl==0.1.2
# via markdown-it-py
-mypy==1.13.0
+mypy==1.14.1
mypy-extensions==1.0.0
# via mypy
nest-asyncio==1.6.0
@@ -62,13 +63,13 @@ platformdirs==3.11.0
# via virtualenv
pluggy==1.5.0
# via pytest
-pydantic==2.9.2
+pydantic==2.10.3
# via braintrust-api
-pydantic-core==2.23.4
+pydantic-core==2.27.1
# via pydantic
pygments==2.18.0
# via rich
-pyright==1.1.380
+pyright==1.1.399
pytest==8.3.3
# via pytest-asyncio
pytest-asyncio==0.24.0
@@ -76,9 +77,9 @@ python-dateutil==2.8.2
# via time-machine
pytz==2023.3.post1
# via dirty-equals
-respx==0.20.2
+respx==0.22.0
rich==13.7.1
-ruff==0.6.9
+ruff==0.9.4
setuptools==68.2.2
# via nodeenv
six==1.16.0
@@ -86,7 +87,6 @@ six==1.16.0
sniffio==1.3.0
# via anyio
# via braintrust-api
- # via httpx
time-machine==2.9.0
tomli==2.0.2
# via mypy
@@ -97,6 +97,7 @@ typing-extensions==4.12.2
# via mypy
# via pydantic
# via pydantic-core
+ # via pyright
virtualenv==20.24.5
# via nox
zipp==3.17.0
diff --git a/requirements.lock b/requirements.lock
index a45b16a1..e863e9a7 100644
--- a/requirements.lock
+++ b/requirements.lock
@@ -7,6 +7,7 @@
# all-features: true
# with-sources: false
# generate-hashes: false
+# universal: false
-e file:.
annotated-types==0.6.0
@@ -25,19 +26,18 @@ h11==0.14.0
# via httpcore
httpcore==1.0.2
# via httpx
-httpx==0.25.2
+httpx==0.28.1
# via braintrust-api
idna==3.4
# via anyio
# via httpx
-pydantic==2.9.2
+pydantic==2.10.3
# via braintrust-api
-pydantic-core==2.23.4
+pydantic-core==2.27.1
# via pydantic
sniffio==1.3.0
# via anyio
# via braintrust-api
- # via httpx
typing-extensions==4.12.2
# via anyio
# via braintrust-api
diff --git a/scripts/bootstrap b/scripts/bootstrap
index 8c5c60eb..e84fe62c 100755
--- a/scripts/bootstrap
+++ b/scripts/bootstrap
@@ -4,7 +4,7 @@ set -e
cd "$(dirname "$0")/.."
-if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ]; then
+if ! command -v rye >/dev/null 2>&1 && [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ]; then
brew bundle check >/dev/null 2>&1 || {
echo "==> Installing Homebrew dependencies…"
brew bundle
diff --git a/scripts/lint b/scripts/lint
index 705a8db8..24ab8ddc 100755
--- a/scripts/lint
+++ b/scripts/lint
@@ -9,4 +9,3 @@ rye run lint
echo "==> Making sure it imports"
rye run python -c 'import braintrust_api'
-
diff --git a/scripts/test b/scripts/test
index 4fa5698b..2b878456 100755
--- a/scripts/test
+++ b/scripts/test
@@ -52,6 +52,8 @@ else
echo
fi
+export DEFER_PYDANTIC_BUILD=false
+
echo "==> Running tests"
rye run pytest "$@"
diff --git a/scripts/utils/ruffen-docs.py b/scripts/utils/ruffen-docs.py
index 37b3d94f..0cf2bd2f 100644
--- a/scripts/utils/ruffen-docs.py
+++ b/scripts/utils/ruffen-docs.py
@@ -47,7 +47,7 @@ def _md_match(match: Match[str]) -> str:
with _collect_error(match):
code = format_code_block(code)
code = textwrap.indent(code, match["indent"])
- return f'{match["before"]}{code}{match["after"]}'
+ return f"{match['before']}{code}{match['after']}"
def _pycon_match(match: Match[str]) -> str:
code = ""
@@ -97,7 +97,7 @@ def finish_fragment() -> None:
def _md_pycon_match(match: Match[str]) -> str:
code = _pycon_match(match)
code = textwrap.indent(code, match["indent"])
- return f'{match["before"]}{code}{match["after"]}'
+ return f"{match['before']}{code}{match['after']}"
src = MD_RE.sub(_md_match, src)
src = MD_PYCON_RE.sub(_md_pycon_match, src)
diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh
new file mode 100755
index 00000000..81f556a7
--- /dev/null
+++ b/scripts/utils/upload-artifact.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+set -exuo pipefail
+
+RESPONSE=$(curl -X POST "$URL" \
+ -H "Authorization: Bearer $AUTH" \
+ -H "Content-Type: application/json")
+
+SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url')
+
+if [[ "$SIGNED_URL" == "null" ]]; then
+ echo -e "\033[31mFailed to get signed URL.\033[0m"
+ exit 1
+fi
+
+UPLOAD_RESPONSE=$(tar -cz . | curl -v -X PUT \
+ -H "Content-Type: application/gzip" \
+ --data-binary @- "$SIGNED_URL" 2>&1)
+
+if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then
+ echo -e "\033[32mUploaded build to Stainless storage.\033[0m"
+ echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/braintrust-sdk-python/$SHA'\033[0m"
+else
+ echo -e "\033[31mFailed to upload artifact.\033[0m"
+ exit 1
+fi
diff --git a/src/braintrust_api/__init__.py b/src/braintrust_api/__init__.py
index 2cd76262..fc417eae 100755
--- a/src/braintrust_api/__init__.py
+++ b/src/braintrust_api/__init__.py
@@ -1,7 +1,9 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+import typing as _t
+
from . import types
-from ._types import NOT_GIVEN, NoneType, NotGiven, Transport, ProxiesTypes
+from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes
from ._utils import file_from_path
from ._client import (
Client,
@@ -46,6 +48,7 @@
"ProxiesTypes",
"NotGiven",
"NOT_GIVEN",
+ "Omit",
"BraintrustError",
"APIError",
"APIStatusError",
@@ -77,6 +80,9 @@
"DefaultAsyncHttpxClient",
]
+if not _t.TYPE_CHECKING:
+ from ._utils._resources_proxy import resources as resources
+
_setup_logging()
# Update the __module__ attribute for exported symbols so that
diff --git a/src/braintrust_api/_base_client.py b/src/braintrust_api/_base_client.py
index 5bedb988..f3e84403 100755
--- a/src/braintrust_api/_base_client.py
+++ b/src/braintrust_api/_base_client.py
@@ -9,7 +9,6 @@
import inspect
import logging
import platform
-import warnings
import email.utils
from types import TracebackType
from random import random
@@ -36,7 +35,7 @@
import httpx
import distro
import pydantic
-from httpx import URL, Limits
+from httpx import URL
from pydantic import PrivateAttr
from . import _exceptions
@@ -51,19 +50,16 @@
Timeout,
NotGiven,
ResponseT,
- Transport,
AnyMapping,
PostParser,
- ProxiesTypes,
RequestFiles,
HttpxSendArgs,
- AsyncTransport,
RequestOptions,
HttpxRequestFiles,
ModelBuilderProtocol,
)
from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping
-from ._compat import model_copy, model_dump
+from ._compat import PYDANTIC_V2, model_copy, model_dump
from ._models import GenericModel, FinalRequestOptions, validate_type, construct_type
from ._response import (
APIResponse,
@@ -102,7 +98,11 @@
_AsyncStreamT = TypeVar("_AsyncStreamT", bound=AsyncStream[Any])
if TYPE_CHECKING:
- from httpx._config import DEFAULT_TIMEOUT_CONFIG as HTTPX_DEFAULT_TIMEOUT
+ from httpx._config import (
+ DEFAULT_TIMEOUT_CONFIG, # pyright: ignore[reportPrivateImportUsage]
+ )
+
+ HTTPX_DEFAULT_TIMEOUT = DEFAULT_TIMEOUT_CONFIG
else:
try:
from httpx._config import DEFAULT_TIMEOUT_CONFIG as HTTPX_DEFAULT_TIMEOUT
@@ -119,6 +119,7 @@ class PageInfo:
url: URL | NotGiven
params: Query | NotGiven
+ json: Body | NotGiven
@overload
def __init__(
@@ -134,19 +135,30 @@ def __init__(
params: Query,
) -> None: ...
+ @overload
+ def __init__(
+ self,
+ *,
+ json: Body,
+ ) -> None: ...
+
def __init__(
self,
*,
url: URL | NotGiven = NOT_GIVEN,
+ json: Body | NotGiven = NOT_GIVEN,
params: Query | NotGiven = NOT_GIVEN,
) -> None:
self.url = url
+ self.json = json
self.params = params
@override
def __repr__(self) -> str:
if self.url:
return f"{self.__class__.__name__}(url={self.url})"
+ if self.json:
+ return f"{self.__class__.__name__}(json={self.json})"
return f"{self.__class__.__name__}(params={self.params})"
@@ -195,6 +207,19 @@ def _info_to_options(self, info: PageInfo) -> FinalRequestOptions:
options.url = str(url)
return options
+ if not isinstance(info.json, NotGiven):
+ if not is_mapping(info.json):
+ raise TypeError("Pagination is only supported with mappings")
+
+ if not options.json_data:
+ options.json_data = {**info.json}
+ else:
+ if not is_mapping(options.json_data):
+ raise TypeError("Pagination is only supported with mappings")
+
+ options.json_data = {**options.json_data, **info.json}
+ return options
+
raise ValueError("Unexpected PageInfo state")
@@ -207,6 +232,9 @@ def _set_private_attributes(
model: Type[_T],
options: FinalRequestOptions,
) -> None:
+ if PYDANTIC_V2 and getattr(self, "__pydantic_private__", None) is None:
+ self.__pydantic_private__ = {}
+
self._model = model
self._client = client
self._options = options
@@ -292,6 +320,9 @@ def _set_private_attributes(
client: AsyncAPIClient,
options: FinalRequestOptions,
) -> None:
+ if PYDANTIC_V2 and getattr(self, "__pydantic_private__", None) is None:
+ self.__pydantic_private__ = {}
+
self._model = model
self._client = client
self._options = options
@@ -331,9 +362,6 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
_base_url: URL
max_retries: int
timeout: Union[float, Timeout, None]
- _limits: httpx.Limits
- _proxies: ProxiesTypes | None
- _transport: Transport | AsyncTransport | None
_strict_response_validation: bool
_idempotency_header: str | None
_default_stream_cls: type[_DefaultStreamT] | None = None
@@ -346,9 +374,6 @@ def __init__(
_strict_response_validation: bool,
max_retries: int = DEFAULT_MAX_RETRIES,
timeout: float | Timeout | None = DEFAULT_TIMEOUT,
- limits: httpx.Limits,
- transport: Transport | AsyncTransport | None,
- proxies: ProxiesTypes | None,
custom_headers: Mapping[str, str] | None = None,
custom_query: Mapping[str, object] | None = None,
) -> None:
@@ -356,9 +381,6 @@ def __init__(
self._base_url = self._enforce_trailing_slash(URL(base_url))
self.max_retries = max_retries
self.timeout = timeout
- self._limits = limits
- self._proxies = proxies
- self._transport = transport
self._custom_headers = custom_headers or {}
self._custom_query = custom_query or {}
self._strict_response_validation = _strict_response_validation
@@ -415,13 +437,20 @@ def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0
headers = httpx.Headers(headers_dict)
idempotency_header = self._idempotency_header
- if idempotency_header and options.method.lower() != "get" and idempotency_header not in headers:
- headers[idempotency_header] = options.idempotency_key or self._idempotency_key()
+ if idempotency_header and options.idempotency_key and idempotency_header not in headers:
+ headers[idempotency_header] = options.idempotency_key
- # Don't set the retry count header if it was already set or removed by the caller. We check
+ # Don't set these headers if they were already set or removed by the caller. We check
# `custom_headers`, which can contain `Omit()`, instead of `headers` to account for the removal case.
- if "x-stainless-retry-count" not in (header.lower() for header in custom_headers):
+ lower_custom_headers = [header.lower() for header in custom_headers]
+ if "x-stainless-retry-count" not in lower_custom_headers:
headers["x-stainless-retry-count"] = str(retries_taken)
+ if "x-stainless-read-timeout" not in lower_custom_headers:
+ timeout = self.timeout if isinstance(options.timeout, NotGiven) else options.timeout
+ if isinstance(timeout, Timeout):
+ timeout = timeout.read
+ if timeout is not None:
+ headers["x-stainless-read-timeout"] = str(timeout)
return headers
@@ -511,7 +540,7 @@ def _build_request(
# so that passing a `TypedDict` doesn't cause an error.
# https://github.com/microsoft/pyright/issues/3526#event-6715453066
params=self.qs.stringify(cast(Mapping[str, Any], params)) if params else None,
- json=json_data,
+ json=json_data if is_given(json_data) else None,
files=files,
**kwargs,
)
@@ -767,6 +796,9 @@ def __init__(self, **kwargs: Any) -> None:
class SyncHttpxClientWrapper(DefaultHttpxClient):
def __del__(self) -> None:
+ if self.is_closed:
+ return
+
try:
self.close()
except Exception:
@@ -784,46 +816,11 @@ def __init__(
base_url: str | URL,
max_retries: int = DEFAULT_MAX_RETRIES,
timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
- transport: Transport | None = None,
- proxies: ProxiesTypes | None = None,
- limits: Limits | None = None,
http_client: httpx.Client | None = None,
custom_headers: Mapping[str, str] | None = None,
custom_query: Mapping[str, object] | None = None,
_strict_response_validation: bool,
) -> None:
- kwargs: dict[str, Any] = {}
- if limits is not None:
- warnings.warn(
- "The `connection_pool_limits` argument is deprecated. The `http_client` argument should be passed instead",
- category=DeprecationWarning,
- stacklevel=3,
- )
- if http_client is not None:
- raise ValueError("The `http_client` argument is mutually exclusive with `connection_pool_limits`")
- else:
- limits = DEFAULT_CONNECTION_LIMITS
-
- if transport is not None:
- kwargs["transport"] = transport
- warnings.warn(
- "The `transport` argument is deprecated. The `http_client` argument should be passed instead",
- category=DeprecationWarning,
- stacklevel=3,
- )
- if http_client is not None:
- raise ValueError("The `http_client` argument is mutually exclusive with `transport`")
-
- if proxies is not None:
- kwargs["proxies"] = proxies
- warnings.warn(
- "The `proxies` argument is deprecated. The `http_client` argument should be passed instead",
- category=DeprecationWarning,
- stacklevel=3,
- )
- if http_client is not None:
- raise ValueError("The `http_client` argument is mutually exclusive with `proxies`")
-
if not is_given(timeout):
# if the user passed in a custom http client with a non-default
# timeout set then we use that timeout.
@@ -844,12 +841,9 @@ def __init__(
super().__init__(
version=version,
- limits=limits,
# cast to a valid type because mypy doesn't understand our type narrowing
timeout=cast(Timeout, timeout),
- proxies=proxies,
base_url=base_url,
- transport=transport,
max_retries=max_retries,
custom_query=custom_query,
custom_headers=custom_headers,
@@ -859,9 +853,6 @@ def __init__(
base_url=base_url,
# cast to a valid type because mypy doesn't understand our type narrowing
timeout=cast(Timeout, timeout),
- limits=limits,
- follow_redirects=True,
- **kwargs, # type: ignore
)
def is_closed(self) -> bool:
@@ -911,7 +902,6 @@ def request(
self,
cast_to: Type[ResponseT],
options: FinalRequestOptions,
- remaining_retries: Optional[int] = None,
*,
stream: Literal[True],
stream_cls: Type[_StreamT],
@@ -922,7 +912,6 @@ def request(
self,
cast_to: Type[ResponseT],
options: FinalRequestOptions,
- remaining_retries: Optional[int] = None,
*,
stream: Literal[False] = False,
) -> ResponseT: ...
@@ -932,7 +921,6 @@ def request(
self,
cast_to: Type[ResponseT],
options: FinalRequestOptions,
- remaining_retries: Optional[int] = None,
*,
stream: bool = False,
stream_cls: Type[_StreamT] | None = None,
@@ -942,121 +930,109 @@ def request(
self,
cast_to: Type[ResponseT],
options: FinalRequestOptions,
- remaining_retries: Optional[int] = None,
*,
stream: bool = False,
stream_cls: type[_StreamT] | None = None,
) -> ResponseT | _StreamT:
- if remaining_retries is not None:
- retries_taken = options.get_max_retries(self.max_retries) - remaining_retries
- else:
- retries_taken = 0
-
- return self._request(
- cast_to=cast_to,
- options=options,
- stream=stream,
- stream_cls=stream_cls,
- retries_taken=retries_taken,
- )
+ cast_to = self._maybe_override_cast_to(cast_to, options)
- def _request(
- self,
- *,
- cast_to: Type[ResponseT],
- options: FinalRequestOptions,
- retries_taken: int,
- stream: bool,
- stream_cls: type[_StreamT] | None,
- ) -> ResponseT | _StreamT:
# create a copy of the options we were given so that if the
# options are mutated later & we then retry, the retries are
# given the original options
input_options = model_copy(options)
+ if input_options.idempotency_key is None and input_options.method.lower() != "get":
+ # ensure the idempotency key is reused between requests
+ input_options.idempotency_key = self._idempotency_key()
- cast_to = self._maybe_override_cast_to(cast_to, options)
- options = self._prepare_options(options)
+ response: httpx.Response | None = None
+ max_retries = input_options.get_max_retries(self.max_retries)
- remaining_retries = options.get_max_retries(self.max_retries) - retries_taken
- request = self._build_request(options, retries_taken=retries_taken)
- self._prepare_request(request)
+ retries_taken = 0
+ for retries_taken in range(max_retries + 1):
+ options = model_copy(input_options)
+ options = self._prepare_options(options)
- kwargs: HttpxSendArgs = {}
- if self.custom_auth is not None:
- kwargs["auth"] = self.custom_auth
+ remaining_retries = max_retries - retries_taken
+ request = self._build_request(options, retries_taken=retries_taken)
+ self._prepare_request(request)
- log.debug("Sending HTTP Request: %s %s", request.method, request.url)
+ kwargs: HttpxSendArgs = {}
+ if self.custom_auth is not None:
+ kwargs["auth"] = self.custom_auth
- try:
- response = self._client.send(
- request,
- stream=stream or self._should_stream_response_body(request=request),
- **kwargs,
- )
- except httpx.TimeoutException as err:
- log.debug("Encountered httpx.TimeoutException", exc_info=True)
+ log.debug("Sending HTTP Request: %s %s", request.method, request.url)
- if remaining_retries > 0:
- return self._retry_request(
- input_options,
- cast_to,
- retries_taken=retries_taken,
- stream=stream,
- stream_cls=stream_cls,
- response_headers=None,
- )
-
- log.debug("Raising timeout error")
- raise APITimeoutError(request=request) from err
- except Exception as err:
- log.debug("Encountered Exception", exc_info=True)
-
- if remaining_retries > 0:
- return self._retry_request(
- input_options,
- cast_to,
- retries_taken=retries_taken,
- stream=stream,
- stream_cls=stream_cls,
- response_headers=None,
+ response = None
+ try:
+ response = self._client.send(
+ request,
+ stream=stream or self._should_stream_response_body(request=request),
+ **kwargs,
)
+ except httpx.TimeoutException as err:
+ log.debug("Encountered httpx.TimeoutException", exc_info=True)
+
+ if remaining_retries > 0:
+ self._sleep_for_retry(
+ retries_taken=retries_taken,
+ max_retries=max_retries,
+ options=input_options,
+ response=None,
+ )
+ continue
+
+ log.debug("Raising timeout error")
+ raise APITimeoutError(request=request) from err
+ except Exception as err:
+ log.debug("Encountered Exception", exc_info=True)
+
+ if remaining_retries > 0:
+ self._sleep_for_retry(
+ retries_taken=retries_taken,
+ max_retries=max_retries,
+ options=input_options,
+ response=None,
+ )
+ continue
+
+ log.debug("Raising connection error")
+ raise APIConnectionError(request=request) from err
+
+ log.debug(
+ 'HTTP Response: %s %s "%i %s" %s',
+ request.method,
+ request.url,
+ response.status_code,
+ response.reason_phrase,
+ response.headers,
+ )
- log.debug("Raising connection error")
- raise APIConnectionError(request=request) from err
-
- log.debug(
- 'HTTP Response: %s %s "%i %s" %s',
- request.method,
- request.url,
- response.status_code,
- response.reason_phrase,
- response.headers,
- )
+ try:
+ response.raise_for_status()
+ except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code
+ log.debug("Encountered httpx.HTTPStatusError", exc_info=True)
+
+ if remaining_retries > 0 and self._should_retry(err.response):
+ err.response.close()
+ self._sleep_for_retry(
+ retries_taken=retries_taken,
+ max_retries=max_retries,
+ options=input_options,
+ response=response,
+ )
+ continue
- try:
- response.raise_for_status()
- except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code
- log.debug("Encountered httpx.HTTPStatusError", exc_info=True)
-
- if remaining_retries > 0 and self._should_retry(err.response):
- err.response.close()
- return self._retry_request(
- input_options,
- cast_to,
- retries_taken=retries_taken,
- response_headers=err.response.headers,
- stream=stream,
- stream_cls=stream_cls,
- )
+ # If the response is streamed then we need to explicitly read the response
+ # to completion before attempting to access the response text.
+ if not err.response.is_closed:
+ err.response.read()
- # If the response is streamed then we need to explicitly read the response
- # to completion before attempting to access the response text.
- if not err.response.is_closed:
- err.response.read()
+ log.debug("Re-raising status error")
+ raise self._make_status_error_from_response(err.response) from None
- log.debug("Re-raising status error")
- raise self._make_status_error_from_response(err.response) from None
+ break
+ assert response is not None, "could not resolve response (should never happen)"
return self._process_response(
cast_to=cast_to,
options=options,
@@ -1066,37 +1042,20 @@ def _request(
retries_taken=retries_taken,
)
- def _retry_request(
- self,
- options: FinalRequestOptions,
- cast_to: Type[ResponseT],
- *,
- retries_taken: int,
- response_headers: httpx.Headers | None,
- stream: bool,
- stream_cls: type[_StreamT] | None,
- ) -> ResponseT | _StreamT:
- remaining_retries = options.get_max_retries(self.max_retries) - retries_taken
+ def _sleep_for_retry(
+ self, *, retries_taken: int, max_retries: int, options: FinalRequestOptions, response: httpx.Response | None
+ ) -> None:
+ remaining_retries = max_retries - retries_taken
if remaining_retries == 1:
log.debug("1 retry left")
else:
log.debug("%i retries left", remaining_retries)
- timeout = self._calculate_retry_timeout(remaining_retries, options, response_headers)
+ timeout = self._calculate_retry_timeout(remaining_retries, options, response.headers if response else None)
log.info("Retrying request to %s in %f seconds", options.url, timeout)
- # In a synchronous context we are blocking the entire thread. Up to the library user to run the client in a
- # different thread if necessary.
time.sleep(timeout)
- return self._request(
- options=options,
- cast_to=cast_to,
- retries_taken=retries_taken + 1,
- stream=stream,
- stream_cls=stream_cls,
- )
-
def _process_response(
self,
*,
@@ -1334,6 +1293,9 @@ def __init__(self, **kwargs: Any) -> None:
class AsyncHttpxClientWrapper(DefaultAsyncHttpxClient):
def __del__(self) -> None:
+ if self.is_closed:
+ return
+
try:
# TODO(someday): support non asyncio runtimes here
asyncio.get_running_loop().create_task(self.aclose())
@@ -1353,45 +1315,10 @@ def __init__(
_strict_response_validation: bool,
max_retries: int = DEFAULT_MAX_RETRIES,
timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
- transport: AsyncTransport | None = None,
- proxies: ProxiesTypes | None = None,
- limits: Limits | None = None,
http_client: httpx.AsyncClient | None = None,
custom_headers: Mapping[str, str] | None = None,
custom_query: Mapping[str, object] | None = None,
) -> None:
- kwargs: dict[str, Any] = {}
- if limits is not None:
- warnings.warn(
- "The `connection_pool_limits` argument is deprecated. The `http_client` argument should be passed instead",
- category=DeprecationWarning,
- stacklevel=3,
- )
- if http_client is not None:
- raise ValueError("The `http_client` argument is mutually exclusive with `connection_pool_limits`")
- else:
- limits = DEFAULT_CONNECTION_LIMITS
-
- if transport is not None:
- kwargs["transport"] = transport
- warnings.warn(
- "The `transport` argument is deprecated. The `http_client` argument should be passed instead",
- category=DeprecationWarning,
- stacklevel=3,
- )
- if http_client is not None:
- raise ValueError("The `http_client` argument is mutually exclusive with `transport`")
-
- if proxies is not None:
- kwargs["proxies"] = proxies
- warnings.warn(
- "The `proxies` argument is deprecated. The `http_client` argument should be passed instead",
- category=DeprecationWarning,
- stacklevel=3,
- )
- if http_client is not None:
- raise ValueError("The `http_client` argument is mutually exclusive with `proxies`")
-
if not is_given(timeout):
# if the user passed in a custom http client with a non-default
# timeout set then we use that timeout.
@@ -1413,11 +1340,8 @@ def __init__(
super().__init__(
version=version,
base_url=base_url,
- limits=limits,
# cast to a valid type because mypy doesn't understand our type narrowing
timeout=cast(Timeout, timeout),
- proxies=proxies,
- transport=transport,
max_retries=max_retries,
custom_query=custom_query,
custom_headers=custom_headers,
@@ -1427,9 +1351,6 @@ def __init__(
base_url=base_url,
# cast to a valid type because mypy doesn't understand our type narrowing
timeout=cast(Timeout, timeout),
- limits=limits,
- follow_redirects=True,
- **kwargs, # type: ignore
)
def is_closed(self) -> bool:
@@ -1478,7 +1399,6 @@ async def request(
options: FinalRequestOptions,
*,
stream: Literal[False] = False,
- remaining_retries: Optional[int] = None,
) -> ResponseT: ...
@overload
@@ -1489,7 +1409,6 @@ async def request(
*,
stream: Literal[True],
stream_cls: type[_AsyncStreamT],
- remaining_retries: Optional[int] = None,
) -> _AsyncStreamT: ...
@overload
@@ -1500,7 +1419,6 @@ async def request(
*,
stream: bool,
stream_cls: type[_AsyncStreamT] | None = None,
- remaining_retries: Optional[int] = None,
) -> ResponseT | _AsyncStreamT: ...
async def request(
@@ -1510,116 +1428,111 @@ async def request(
*,
stream: bool = False,
stream_cls: type[_AsyncStreamT] | None = None,
- remaining_retries: Optional[int] = None,
- ) -> ResponseT | _AsyncStreamT:
- if remaining_retries is not None:
- retries_taken = options.get_max_retries(self.max_retries) - remaining_retries
- else:
- retries_taken = 0
-
- return await self._request(
- cast_to=cast_to,
- options=options,
- stream=stream,
- stream_cls=stream_cls,
- retries_taken=retries_taken,
- )
-
- async def _request(
- self,
- cast_to: Type[ResponseT],
- options: FinalRequestOptions,
- *,
- stream: bool,
- stream_cls: type[_AsyncStreamT] | None,
- retries_taken: int,
) -> ResponseT | _AsyncStreamT:
if self._platform is None:
# `get_platform` can make blocking IO calls so we
# execute it earlier while we are in an async context
self._platform = await asyncify(get_platform)()
+ cast_to = self._maybe_override_cast_to(cast_to, options)
+
# create a copy of the options we were given so that if the
# options are mutated later & we then retry, the retries are
# given the original options
input_options = model_copy(options)
+ if input_options.idempotency_key is None and input_options.method.lower() != "get":
+ # ensure the idempotency key is reused between requests
+ input_options.idempotency_key = self._idempotency_key()
- cast_to = self._maybe_override_cast_to(cast_to, options)
- options = await self._prepare_options(options)
+ response: httpx.Response | None = None
+ max_retries = input_options.get_max_retries(self.max_retries)
- remaining_retries = options.get_max_retries(self.max_retries) - retries_taken
- request = self._build_request(options, retries_taken=retries_taken)
- await self._prepare_request(request)
+ retries_taken = 0
+ for retries_taken in range(max_retries + 1):
+ options = model_copy(input_options)
+ options = await self._prepare_options(options)
- kwargs: HttpxSendArgs = {}
- if self.custom_auth is not None:
- kwargs["auth"] = self.custom_auth
+ remaining_retries = max_retries - retries_taken
+ request = self._build_request(options, retries_taken=retries_taken)
+ await self._prepare_request(request)
- try:
- response = await self._client.send(
- request,
- stream=stream or self._should_stream_response_body(request=request),
- **kwargs,
- )
- except httpx.TimeoutException as err:
- log.debug("Encountered httpx.TimeoutException", exc_info=True)
+ kwargs: HttpxSendArgs = {}
+ if self.custom_auth is not None:
+ kwargs["auth"] = self.custom_auth
- if remaining_retries > 0:
- return await self._retry_request(
- input_options,
- cast_to,
- retries_taken=retries_taken,
- stream=stream,
- stream_cls=stream_cls,
- response_headers=None,
- )
+ log.debug("Sending HTTP Request: %s %s", request.method, request.url)
- log.debug("Raising timeout error")
- raise APITimeoutError(request=request) from err
- except Exception as err:
- log.debug("Encountered Exception", exc_info=True)
-
- if remaining_retries > 0:
- return await self._retry_request(
- input_options,
- cast_to,
- retries_taken=retries_taken,
- stream=stream,
- stream_cls=stream_cls,
- response_headers=None,
+ response = None
+ try:
+ response = await self._client.send(
+ request,
+ stream=stream or self._should_stream_response_body(request=request),
+ **kwargs,
)
+ except httpx.TimeoutException as err:
+ log.debug("Encountered httpx.TimeoutException", exc_info=True)
+
+ if remaining_retries > 0:
+ await self._sleep_for_retry(
+ retries_taken=retries_taken,
+ max_retries=max_retries,
+ options=input_options,
+ response=None,
+ )
+ continue
+
+ log.debug("Raising timeout error")
+ raise APITimeoutError(request=request) from err
+ except Exception as err:
+ log.debug("Encountered Exception", exc_info=True)
+
+ if remaining_retries > 0:
+ await self._sleep_for_retry(
+ retries_taken=retries_taken,
+ max_retries=max_retries,
+ options=input_options,
+ response=None,
+ )
+ continue
+
+ log.debug("Raising connection error")
+ raise APIConnectionError(request=request) from err
+
+ log.debug(
+ 'HTTP Response: %s %s "%i %s" %s',
+ request.method,
+ request.url,
+ response.status_code,
+ response.reason_phrase,
+ response.headers,
+ )
- log.debug("Raising connection error")
- raise APIConnectionError(request=request) from err
+ try:
+ response.raise_for_status()
+ except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code
+ log.debug("Encountered httpx.HTTPStatusError", exc_info=True)
+
+ if remaining_retries > 0 and self._should_retry(err.response):
+ await err.response.aclose()
+ await self._sleep_for_retry(
+ retries_taken=retries_taken,
+ max_retries=max_retries,
+ options=input_options,
+ response=response,
+ )
+ continue
- log.debug(
- 'HTTP Request: %s %s "%i %s"', request.method, request.url, response.status_code, response.reason_phrase
- )
+ # If the response is streamed then we need to explicitly read the response
+ # to completion before attempting to access the response text.
+ if not err.response.is_closed:
+ await err.response.aread()
- try:
- response.raise_for_status()
- except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code
- log.debug("Encountered httpx.HTTPStatusError", exc_info=True)
-
- if remaining_retries > 0 and self._should_retry(err.response):
- await err.response.aclose()
- return await self._retry_request(
- input_options,
- cast_to,
- retries_taken=retries_taken,
- response_headers=err.response.headers,
- stream=stream,
- stream_cls=stream_cls,
- )
+ log.debug("Re-raising status error")
+ raise self._make_status_error_from_response(err.response) from None
- # If the response is streamed then we need to explicitly read the response
- # to completion before attempting to access the response text.
- if not err.response.is_closed:
- await err.response.aread()
-
- log.debug("Re-raising status error")
- raise self._make_status_error_from_response(err.response) from None
+ break
+ assert response is not None, "could not resolve response (should never happen)"
return await self._process_response(
cast_to=cast_to,
options=options,
@@ -1629,35 +1542,20 @@ async def _request(
retries_taken=retries_taken,
)
- async def _retry_request(
- self,
- options: FinalRequestOptions,
- cast_to: Type[ResponseT],
- *,
- retries_taken: int,
- response_headers: httpx.Headers | None,
- stream: bool,
- stream_cls: type[_AsyncStreamT] | None,
- ) -> ResponseT | _AsyncStreamT:
- remaining_retries = options.get_max_retries(self.max_retries) - retries_taken
+ async def _sleep_for_retry(
+ self, *, retries_taken: int, max_retries: int, options: FinalRequestOptions, response: httpx.Response | None
+ ) -> None:
+ remaining_retries = max_retries - retries_taken
if remaining_retries == 1:
log.debug("1 retry left")
else:
log.debug("%i retries left", remaining_retries)
- timeout = self._calculate_retry_timeout(remaining_retries, options, response_headers)
+ timeout = self._calculate_retry_timeout(remaining_retries, options, response.headers if response else None)
log.info("Retrying request to %s in %f seconds", options.url, timeout)
await anyio.sleep(timeout)
- return await self._request(
- options=options,
- cast_to=cast_to,
- retries_taken=retries_taken + 1,
- stream=stream,
- stream_cls=stream_cls,
- )
-
async def _process_response(
self,
*,
diff --git a/src/braintrust_api/_client.py b/src/braintrust_api/_client.py
index 23c65e8d..9c0c05af 100755
--- a/src/braintrust_api/_client.py
+++ b/src/braintrust_api/_client.py
@@ -8,7 +8,7 @@
import httpx
-from . import resources, _exceptions
+from . import _exceptions
from ._qs import Querystring
from ._types import (
NOT_GIVEN,
@@ -19,11 +19,27 @@
ProxiesTypes,
RequestOptions,
)
-from ._utils import (
- is_given,
- get_async_library,
-)
+from ._utils import is_given, get_async_library
from ._version import __version__
+from .resources import (
+ acls,
+ evals,
+ roles,
+ users,
+ views,
+ groups,
+ prompts,
+ api_keys,
+ datasets,
+ env_vars,
+ functions,
+ top_level,
+ ai_secrets,
+ experiments,
+ project_tags,
+ span_iframes,
+ project_scores,
+)
from ._streaming import Stream as Stream, AsyncStream as AsyncStream
from ._exceptions import APIStatusError
from ._base_client import (
@@ -31,13 +47,14 @@
SyncAPIClient,
AsyncAPIClient,
)
+from .resources.projects import projects
+from .resources.organizations import organizations
__all__ = [
"Timeout",
"Transport",
"ProxiesTypes",
"RequestOptions",
- "resources",
"Braintrust",
"AsyncBraintrust",
"Client",
@@ -46,25 +63,25 @@
class Braintrust(SyncAPIClient):
- top_level: resources.TopLevelResource
- projects: resources.ProjectsResource
- experiments: resources.ExperimentsResource
- datasets: resources.DatasetsResource
- prompts: resources.PromptsResource
- roles: resources.RolesResource
- groups: resources.GroupsResource
- acls: resources.ACLsResource
- users: resources.UsersResource
- project_scores: resources.ProjectScoresResource
- project_tags: resources.ProjectTagsResource
- span_iframes: resources.SpanIframesResource
- functions: resources.FunctionsResource
- views: resources.ViewsResource
- organizations: resources.OrganizationsResource
- api_keys: resources.APIKeysResource
- ai_secrets: resources.AISecretsResource
- env_vars: resources.EnvVarsResource
- evals: resources.EvalsResource
+ top_level: top_level.TopLevelResource
+ projects: projects.ProjectsResource
+ experiments: experiments.ExperimentsResource
+ datasets: datasets.DatasetsResource
+ prompts: prompts.PromptsResource
+ roles: roles.RolesResource
+ groups: groups.GroupsResource
+ acls: acls.ACLsResource
+ users: users.UsersResource
+ project_scores: project_scores.ProjectScoresResource
+ project_tags: project_tags.ProjectTagsResource
+ span_iframes: span_iframes.SpanIframesResource
+ functions: functions.FunctionsResource
+ views: views.ViewsResource
+ organizations: organizations.OrganizationsResource
+ api_keys: api_keys.APIKeysResource
+ ai_secrets: ai_secrets.AISecretsResource
+ env_vars: env_vars.EnvVarsResource
+ evals: evals.EvalsResource
with_raw_response: BraintrustWithRawResponse
with_streaming_response: BraintrustWithStreamedResponse
@@ -94,7 +111,7 @@ def __init__(
# part of our public interface in the future.
_strict_response_validation: bool = False,
) -> None:
- """Construct a new synchronous braintrust client instance.
+ """Construct a new synchronous Braintrust client instance.
This automatically infers the `api_key` argument from the `BRAINTRUST_API_KEY` environment variable if it is not provided.
"""
@@ -118,25 +135,25 @@ def __init__(
_strict_response_validation=_strict_response_validation,
)
- self.top_level = resources.TopLevelResource(self)
- self.projects = resources.ProjectsResource(self)
- self.experiments = resources.ExperimentsResource(self)
- self.datasets = resources.DatasetsResource(self)
- self.prompts = resources.PromptsResource(self)
- self.roles = resources.RolesResource(self)
- self.groups = resources.GroupsResource(self)
- self.acls = resources.ACLsResource(self)
- self.users = resources.UsersResource(self)
- self.project_scores = resources.ProjectScoresResource(self)
- self.project_tags = resources.ProjectTagsResource(self)
- self.span_iframes = resources.SpanIframesResource(self)
- self.functions = resources.FunctionsResource(self)
- self.views = resources.ViewsResource(self)
- self.organizations = resources.OrganizationsResource(self)
- self.api_keys = resources.APIKeysResource(self)
- self.ai_secrets = resources.AISecretsResource(self)
- self.env_vars = resources.EnvVarsResource(self)
- self.evals = resources.EvalsResource(self)
+ self.top_level = top_level.TopLevelResource(self)
+ self.projects = projects.ProjectsResource(self)
+ self.experiments = experiments.ExperimentsResource(self)
+ self.datasets = datasets.DatasetsResource(self)
+ self.prompts = prompts.PromptsResource(self)
+ self.roles = roles.RolesResource(self)
+ self.groups = groups.GroupsResource(self)
+ self.acls = acls.ACLsResource(self)
+ self.users = users.UsersResource(self)
+ self.project_scores = project_scores.ProjectScoresResource(self)
+ self.project_tags = project_tags.ProjectTagsResource(self)
+ self.span_iframes = span_iframes.SpanIframesResource(self)
+ self.functions = functions.FunctionsResource(self)
+ self.views = views.ViewsResource(self)
+ self.organizations = organizations.OrganizationsResource(self)
+ self.api_keys = api_keys.APIKeysResource(self)
+ self.ai_secrets = ai_secrets.AISecretsResource(self)
+ self.env_vars = env_vars.EnvVarsResource(self)
+ self.evals = evals.EvalsResource(self)
self.with_raw_response = BraintrustWithRawResponse(self)
self.with_streaming_response = BraintrustWithStreamedResponse(self)
@@ -248,25 +265,25 @@ def _make_status_error(
class AsyncBraintrust(AsyncAPIClient):
- top_level: resources.AsyncTopLevelResource
- projects: resources.AsyncProjectsResource
- experiments: resources.AsyncExperimentsResource
- datasets: resources.AsyncDatasetsResource
- prompts: resources.AsyncPromptsResource
- roles: resources.AsyncRolesResource
- groups: resources.AsyncGroupsResource
- acls: resources.AsyncACLsResource
- users: resources.AsyncUsersResource
- project_scores: resources.AsyncProjectScoresResource
- project_tags: resources.AsyncProjectTagsResource
- span_iframes: resources.AsyncSpanIframesResource
- functions: resources.AsyncFunctionsResource
- views: resources.AsyncViewsResource
- organizations: resources.AsyncOrganizationsResource
- api_keys: resources.AsyncAPIKeysResource
- ai_secrets: resources.AsyncAISecretsResource
- env_vars: resources.AsyncEnvVarsResource
- evals: resources.AsyncEvalsResource
+ top_level: top_level.AsyncTopLevelResource
+ projects: projects.AsyncProjectsResource
+ experiments: experiments.AsyncExperimentsResource
+ datasets: datasets.AsyncDatasetsResource
+ prompts: prompts.AsyncPromptsResource
+ roles: roles.AsyncRolesResource
+ groups: groups.AsyncGroupsResource
+ acls: acls.AsyncACLsResource
+ users: users.AsyncUsersResource
+ project_scores: project_scores.AsyncProjectScoresResource
+ project_tags: project_tags.AsyncProjectTagsResource
+ span_iframes: span_iframes.AsyncSpanIframesResource
+ functions: functions.AsyncFunctionsResource
+ views: views.AsyncViewsResource
+ organizations: organizations.AsyncOrganizationsResource
+ api_keys: api_keys.AsyncAPIKeysResource
+ ai_secrets: ai_secrets.AsyncAISecretsResource
+ env_vars: env_vars.AsyncEnvVarsResource
+ evals: evals.AsyncEvalsResource
with_raw_response: AsyncBraintrustWithRawResponse
with_streaming_response: AsyncBraintrustWithStreamedResponse
@@ -296,7 +313,7 @@ def __init__(
# part of our public interface in the future.
_strict_response_validation: bool = False,
) -> None:
- """Construct a new async braintrust client instance.
+ """Construct a new async AsyncBraintrust client instance.
This automatically infers the `api_key` argument from the `BRAINTRUST_API_KEY` environment variable if it is not provided.
"""
@@ -320,25 +337,25 @@ def __init__(
_strict_response_validation=_strict_response_validation,
)
- self.top_level = resources.AsyncTopLevelResource(self)
- self.projects = resources.AsyncProjectsResource(self)
- self.experiments = resources.AsyncExperimentsResource(self)
- self.datasets = resources.AsyncDatasetsResource(self)
- self.prompts = resources.AsyncPromptsResource(self)
- self.roles = resources.AsyncRolesResource(self)
- self.groups = resources.AsyncGroupsResource(self)
- self.acls = resources.AsyncACLsResource(self)
- self.users = resources.AsyncUsersResource(self)
- self.project_scores = resources.AsyncProjectScoresResource(self)
- self.project_tags = resources.AsyncProjectTagsResource(self)
- self.span_iframes = resources.AsyncSpanIframesResource(self)
- self.functions = resources.AsyncFunctionsResource(self)
- self.views = resources.AsyncViewsResource(self)
- self.organizations = resources.AsyncOrganizationsResource(self)
- self.api_keys = resources.AsyncAPIKeysResource(self)
- self.ai_secrets = resources.AsyncAISecretsResource(self)
- self.env_vars = resources.AsyncEnvVarsResource(self)
- self.evals = resources.AsyncEvalsResource(self)
+ self.top_level = top_level.AsyncTopLevelResource(self)
+ self.projects = projects.AsyncProjectsResource(self)
+ self.experiments = experiments.AsyncExperimentsResource(self)
+ self.datasets = datasets.AsyncDatasetsResource(self)
+ self.prompts = prompts.AsyncPromptsResource(self)
+ self.roles = roles.AsyncRolesResource(self)
+ self.groups = groups.AsyncGroupsResource(self)
+ self.acls = acls.AsyncACLsResource(self)
+ self.users = users.AsyncUsersResource(self)
+ self.project_scores = project_scores.AsyncProjectScoresResource(self)
+ self.project_tags = project_tags.AsyncProjectTagsResource(self)
+ self.span_iframes = span_iframes.AsyncSpanIframesResource(self)
+ self.functions = functions.AsyncFunctionsResource(self)
+ self.views = views.AsyncViewsResource(self)
+ self.organizations = organizations.AsyncOrganizationsResource(self)
+ self.api_keys = api_keys.AsyncAPIKeysResource(self)
+ self.ai_secrets = ai_secrets.AsyncAISecretsResource(self)
+ self.env_vars = env_vars.AsyncEnvVarsResource(self)
+ self.evals = evals.AsyncEvalsResource(self)
self.with_raw_response = AsyncBraintrustWithRawResponse(self)
self.with_streaming_response = AsyncBraintrustWithStreamedResponse(self)
@@ -451,94 +468,94 @@ def _make_status_error(
class BraintrustWithRawResponse:
def __init__(self, client: Braintrust) -> None:
- self.top_level = resources.TopLevelResourceWithRawResponse(client.top_level)
- self.projects = resources.ProjectsResourceWithRawResponse(client.projects)
- self.experiments = resources.ExperimentsResourceWithRawResponse(client.experiments)
- self.datasets = resources.DatasetsResourceWithRawResponse(client.datasets)
- self.prompts = resources.PromptsResourceWithRawResponse(client.prompts)
- self.roles = resources.RolesResourceWithRawResponse(client.roles)
- self.groups = resources.GroupsResourceWithRawResponse(client.groups)
- self.acls = resources.ACLsResourceWithRawResponse(client.acls)
- self.users = resources.UsersResourceWithRawResponse(client.users)
- self.project_scores = resources.ProjectScoresResourceWithRawResponse(client.project_scores)
- self.project_tags = resources.ProjectTagsResourceWithRawResponse(client.project_tags)
- self.span_iframes = resources.SpanIframesResourceWithRawResponse(client.span_iframes)
- self.functions = resources.FunctionsResourceWithRawResponse(client.functions)
- self.views = resources.ViewsResourceWithRawResponse(client.views)
- self.organizations = resources.OrganizationsResourceWithRawResponse(client.organizations)
- self.api_keys = resources.APIKeysResourceWithRawResponse(client.api_keys)
- self.ai_secrets = resources.AISecretsResourceWithRawResponse(client.ai_secrets)
- self.env_vars = resources.EnvVarsResourceWithRawResponse(client.env_vars)
- self.evals = resources.EvalsResourceWithRawResponse(client.evals)
+ self.top_level = top_level.TopLevelResourceWithRawResponse(client.top_level)
+ self.projects = projects.ProjectsResourceWithRawResponse(client.projects)
+ self.experiments = experiments.ExperimentsResourceWithRawResponse(client.experiments)
+ self.datasets = datasets.DatasetsResourceWithRawResponse(client.datasets)
+ self.prompts = prompts.PromptsResourceWithRawResponse(client.prompts)
+ self.roles = roles.RolesResourceWithRawResponse(client.roles)
+ self.groups = groups.GroupsResourceWithRawResponse(client.groups)
+ self.acls = acls.ACLsResourceWithRawResponse(client.acls)
+ self.users = users.UsersResourceWithRawResponse(client.users)
+ self.project_scores = project_scores.ProjectScoresResourceWithRawResponse(client.project_scores)
+ self.project_tags = project_tags.ProjectTagsResourceWithRawResponse(client.project_tags)
+ self.span_iframes = span_iframes.SpanIframesResourceWithRawResponse(client.span_iframes)
+ self.functions = functions.FunctionsResourceWithRawResponse(client.functions)
+ self.views = views.ViewsResourceWithRawResponse(client.views)
+ self.organizations = organizations.OrganizationsResourceWithRawResponse(client.organizations)
+ self.api_keys = api_keys.APIKeysResourceWithRawResponse(client.api_keys)
+ self.ai_secrets = ai_secrets.AISecretsResourceWithRawResponse(client.ai_secrets)
+ self.env_vars = env_vars.EnvVarsResourceWithRawResponse(client.env_vars)
+ self.evals = evals.EvalsResourceWithRawResponse(client.evals)
class AsyncBraintrustWithRawResponse:
def __init__(self, client: AsyncBraintrust) -> None:
- self.top_level = resources.AsyncTopLevelResourceWithRawResponse(client.top_level)
- self.projects = resources.AsyncProjectsResourceWithRawResponse(client.projects)
- self.experiments = resources.AsyncExperimentsResourceWithRawResponse(client.experiments)
- self.datasets = resources.AsyncDatasetsResourceWithRawResponse(client.datasets)
- self.prompts = resources.AsyncPromptsResourceWithRawResponse(client.prompts)
- self.roles = resources.AsyncRolesResourceWithRawResponse(client.roles)
- self.groups = resources.AsyncGroupsResourceWithRawResponse(client.groups)
- self.acls = resources.AsyncACLsResourceWithRawResponse(client.acls)
- self.users = resources.AsyncUsersResourceWithRawResponse(client.users)
- self.project_scores = resources.AsyncProjectScoresResourceWithRawResponse(client.project_scores)
- self.project_tags = resources.AsyncProjectTagsResourceWithRawResponse(client.project_tags)
- self.span_iframes = resources.AsyncSpanIframesResourceWithRawResponse(client.span_iframes)
- self.functions = resources.AsyncFunctionsResourceWithRawResponse(client.functions)
- self.views = resources.AsyncViewsResourceWithRawResponse(client.views)
- self.organizations = resources.AsyncOrganizationsResourceWithRawResponse(client.organizations)
- self.api_keys = resources.AsyncAPIKeysResourceWithRawResponse(client.api_keys)
- self.ai_secrets = resources.AsyncAISecretsResourceWithRawResponse(client.ai_secrets)
- self.env_vars = resources.AsyncEnvVarsResourceWithRawResponse(client.env_vars)
- self.evals = resources.AsyncEvalsResourceWithRawResponse(client.evals)
+ self.top_level = top_level.AsyncTopLevelResourceWithRawResponse(client.top_level)
+ self.projects = projects.AsyncProjectsResourceWithRawResponse(client.projects)
+ self.experiments = experiments.AsyncExperimentsResourceWithRawResponse(client.experiments)
+ self.datasets = datasets.AsyncDatasetsResourceWithRawResponse(client.datasets)
+ self.prompts = prompts.AsyncPromptsResourceWithRawResponse(client.prompts)
+ self.roles = roles.AsyncRolesResourceWithRawResponse(client.roles)
+ self.groups = groups.AsyncGroupsResourceWithRawResponse(client.groups)
+ self.acls = acls.AsyncACLsResourceWithRawResponse(client.acls)
+ self.users = users.AsyncUsersResourceWithRawResponse(client.users)
+ self.project_scores = project_scores.AsyncProjectScoresResourceWithRawResponse(client.project_scores)
+ self.project_tags = project_tags.AsyncProjectTagsResourceWithRawResponse(client.project_tags)
+ self.span_iframes = span_iframes.AsyncSpanIframesResourceWithRawResponse(client.span_iframes)
+ self.functions = functions.AsyncFunctionsResourceWithRawResponse(client.functions)
+ self.views = views.AsyncViewsResourceWithRawResponse(client.views)
+ self.organizations = organizations.AsyncOrganizationsResourceWithRawResponse(client.organizations)
+ self.api_keys = api_keys.AsyncAPIKeysResourceWithRawResponse(client.api_keys)
+ self.ai_secrets = ai_secrets.AsyncAISecretsResourceWithRawResponse(client.ai_secrets)
+ self.env_vars = env_vars.AsyncEnvVarsResourceWithRawResponse(client.env_vars)
+ self.evals = evals.AsyncEvalsResourceWithRawResponse(client.evals)
class BraintrustWithStreamedResponse:
def __init__(self, client: Braintrust) -> None:
- self.top_level = resources.TopLevelResourceWithStreamingResponse(client.top_level)
- self.projects = resources.ProjectsResourceWithStreamingResponse(client.projects)
- self.experiments = resources.ExperimentsResourceWithStreamingResponse(client.experiments)
- self.datasets = resources.DatasetsResourceWithStreamingResponse(client.datasets)
- self.prompts = resources.PromptsResourceWithStreamingResponse(client.prompts)
- self.roles = resources.RolesResourceWithStreamingResponse(client.roles)
- self.groups = resources.GroupsResourceWithStreamingResponse(client.groups)
- self.acls = resources.ACLsResourceWithStreamingResponse(client.acls)
- self.users = resources.UsersResourceWithStreamingResponse(client.users)
- self.project_scores = resources.ProjectScoresResourceWithStreamingResponse(client.project_scores)
- self.project_tags = resources.ProjectTagsResourceWithStreamingResponse(client.project_tags)
- self.span_iframes = resources.SpanIframesResourceWithStreamingResponse(client.span_iframes)
- self.functions = resources.FunctionsResourceWithStreamingResponse(client.functions)
- self.views = resources.ViewsResourceWithStreamingResponse(client.views)
- self.organizations = resources.OrganizationsResourceWithStreamingResponse(client.organizations)
- self.api_keys = resources.APIKeysResourceWithStreamingResponse(client.api_keys)
- self.ai_secrets = resources.AISecretsResourceWithStreamingResponse(client.ai_secrets)
- self.env_vars = resources.EnvVarsResourceWithStreamingResponse(client.env_vars)
- self.evals = resources.EvalsResourceWithStreamingResponse(client.evals)
+ self.top_level = top_level.TopLevelResourceWithStreamingResponse(client.top_level)
+ self.projects = projects.ProjectsResourceWithStreamingResponse(client.projects)
+ self.experiments = experiments.ExperimentsResourceWithStreamingResponse(client.experiments)
+ self.datasets = datasets.DatasetsResourceWithStreamingResponse(client.datasets)
+ self.prompts = prompts.PromptsResourceWithStreamingResponse(client.prompts)
+ self.roles = roles.RolesResourceWithStreamingResponse(client.roles)
+ self.groups = groups.GroupsResourceWithStreamingResponse(client.groups)
+ self.acls = acls.ACLsResourceWithStreamingResponse(client.acls)
+ self.users = users.UsersResourceWithStreamingResponse(client.users)
+ self.project_scores = project_scores.ProjectScoresResourceWithStreamingResponse(client.project_scores)
+ self.project_tags = project_tags.ProjectTagsResourceWithStreamingResponse(client.project_tags)
+ self.span_iframes = span_iframes.SpanIframesResourceWithStreamingResponse(client.span_iframes)
+ self.functions = functions.FunctionsResourceWithStreamingResponse(client.functions)
+ self.views = views.ViewsResourceWithStreamingResponse(client.views)
+ self.organizations = organizations.OrganizationsResourceWithStreamingResponse(client.organizations)
+ self.api_keys = api_keys.APIKeysResourceWithStreamingResponse(client.api_keys)
+ self.ai_secrets = ai_secrets.AISecretsResourceWithStreamingResponse(client.ai_secrets)
+ self.env_vars = env_vars.EnvVarsResourceWithStreamingResponse(client.env_vars)
+ self.evals = evals.EvalsResourceWithStreamingResponse(client.evals)
class AsyncBraintrustWithStreamedResponse:
def __init__(self, client: AsyncBraintrust) -> None:
- self.top_level = resources.AsyncTopLevelResourceWithStreamingResponse(client.top_level)
- self.projects = resources.AsyncProjectsResourceWithStreamingResponse(client.projects)
- self.experiments = resources.AsyncExperimentsResourceWithStreamingResponse(client.experiments)
- self.datasets = resources.AsyncDatasetsResourceWithStreamingResponse(client.datasets)
- self.prompts = resources.AsyncPromptsResourceWithStreamingResponse(client.prompts)
- self.roles = resources.AsyncRolesResourceWithStreamingResponse(client.roles)
- self.groups = resources.AsyncGroupsResourceWithStreamingResponse(client.groups)
- self.acls = resources.AsyncACLsResourceWithStreamingResponse(client.acls)
- self.users = resources.AsyncUsersResourceWithStreamingResponse(client.users)
- self.project_scores = resources.AsyncProjectScoresResourceWithStreamingResponse(client.project_scores)
- self.project_tags = resources.AsyncProjectTagsResourceWithStreamingResponse(client.project_tags)
- self.span_iframes = resources.AsyncSpanIframesResourceWithStreamingResponse(client.span_iframes)
- self.functions = resources.AsyncFunctionsResourceWithStreamingResponse(client.functions)
- self.views = resources.AsyncViewsResourceWithStreamingResponse(client.views)
- self.organizations = resources.AsyncOrganizationsResourceWithStreamingResponse(client.organizations)
- self.api_keys = resources.AsyncAPIKeysResourceWithStreamingResponse(client.api_keys)
- self.ai_secrets = resources.AsyncAISecretsResourceWithStreamingResponse(client.ai_secrets)
- self.env_vars = resources.AsyncEnvVarsResourceWithStreamingResponse(client.env_vars)
- self.evals = resources.AsyncEvalsResourceWithStreamingResponse(client.evals)
+ self.top_level = top_level.AsyncTopLevelResourceWithStreamingResponse(client.top_level)
+ self.projects = projects.AsyncProjectsResourceWithStreamingResponse(client.projects)
+ self.experiments = experiments.AsyncExperimentsResourceWithStreamingResponse(client.experiments)
+ self.datasets = datasets.AsyncDatasetsResourceWithStreamingResponse(client.datasets)
+ self.prompts = prompts.AsyncPromptsResourceWithStreamingResponse(client.prompts)
+ self.roles = roles.AsyncRolesResourceWithStreamingResponse(client.roles)
+ self.groups = groups.AsyncGroupsResourceWithStreamingResponse(client.groups)
+ self.acls = acls.AsyncACLsResourceWithStreamingResponse(client.acls)
+ self.users = users.AsyncUsersResourceWithStreamingResponse(client.users)
+ self.project_scores = project_scores.AsyncProjectScoresResourceWithStreamingResponse(client.project_scores)
+ self.project_tags = project_tags.AsyncProjectTagsResourceWithStreamingResponse(client.project_tags)
+ self.span_iframes = span_iframes.AsyncSpanIframesResourceWithStreamingResponse(client.span_iframes)
+ self.functions = functions.AsyncFunctionsResourceWithStreamingResponse(client.functions)
+ self.views = views.AsyncViewsResourceWithStreamingResponse(client.views)
+ self.organizations = organizations.AsyncOrganizationsResourceWithStreamingResponse(client.organizations)
+ self.api_keys = api_keys.AsyncAPIKeysResourceWithStreamingResponse(client.api_keys)
+ self.ai_secrets = ai_secrets.AsyncAISecretsResourceWithStreamingResponse(client.ai_secrets)
+ self.env_vars = env_vars.AsyncEnvVarsResourceWithStreamingResponse(client.env_vars)
+ self.evals = evals.AsyncEvalsResourceWithStreamingResponse(client.evals)
Client = Braintrust
diff --git a/src/braintrust_api/_constants.py b/src/braintrust_api/_constants.py
index a2ac3b6f..6ddf2c71 100755
--- a/src/braintrust_api/_constants.py
+++ b/src/braintrust_api/_constants.py
@@ -6,7 +6,7 @@
OVERRIDE_CAST_TO_HEADER = "____stainless_override_cast_to"
# default timeout is 1 minute
-DEFAULT_TIMEOUT = httpx.Timeout(timeout=60.0, connect=5.0)
+DEFAULT_TIMEOUT = httpx.Timeout(timeout=60, connect=5.0)
DEFAULT_MAX_RETRIES = 2
DEFAULT_CONNECTION_LIMITS = httpx.Limits(max_connections=100, max_keepalive_connections=20)
diff --git a/src/braintrust_api/_models.py b/src/braintrust_api/_models.py
index 6cb469e2..798956f1 100755
--- a/src/braintrust_api/_models.py
+++ b/src/braintrust_api/_models.py
@@ -19,7 +19,6 @@
)
import pydantic
-import pydantic.generics
from pydantic.fields import FieldInfo
from ._types import (
@@ -46,6 +45,7 @@
strip_not_given,
extract_type_arg,
is_annotated_type,
+ is_type_alias_type,
strip_annotated_type,
)
from ._compat import (
@@ -64,7 +64,7 @@
from ._constants import RAW_RESPONSE_HEADER
if TYPE_CHECKING:
- from pydantic_core.core_schema import ModelField, LiteralSchema, ModelFieldsSchema
+ from pydantic_core.core_schema import ModelField, ModelSchema, LiteralSchema, ModelFieldsSchema
__all__ = ["BaseModel", "GenericModel"]
@@ -171,21 +171,21 @@ def to_json(
@override
def __str__(self) -> str:
# mypy complains about an invalid self arg
- return f'{self.__repr_name__()}({self.__repr_str__(", ")})' # type: ignore[misc]
+ return f"{self.__repr_name__()}({self.__repr_str__(', ')})" # type: ignore[misc]
# Override the 'construct' method in a way that supports recursive parsing without validation.
# Based on https://github.com/samuelcolvin/pydantic/issues/1168#issuecomment-817742836.
@classmethod
@override
def construct( # pyright: ignore[reportIncompatibleMethodOverride]
- cls: Type[ModelT],
+ __cls: Type[ModelT],
_fields_set: set[str] | None = None,
**values: object,
) -> ModelT:
- m = cls.__new__(cls)
+ m = __cls.__new__(__cls)
fields_values: dict[str, object] = {}
- config = get_model_config(cls)
+ config = get_model_config(__cls)
populate_by_name = (
config.allow_population_by_field_name
if isinstance(config, _ConfigProtocol)
@@ -195,7 +195,7 @@ def construct( # pyright: ignore[reportIncompatibleMethodOverride]
if _fields_set is None:
_fields_set = set()
- model_fields = get_model_fields(cls)
+ model_fields = get_model_fields(__cls)
for name, field in model_fields.items():
key = field.alias
if key is None or (key not in values and populate_by_name):
@@ -425,9 +425,17 @@ def construct_type(*, value: object, type_: object) -> object:
If the given value does not match the expected type then it is returned as-is.
"""
+
+ # store a reference to the original type we were given before we extract any inner
+ # types so that we can properly resolve forward references in `TypeAliasType` annotations
+ original_type = None
+
# we allow `object` as the input type because otherwise, passing things like
# `Literal['value']` will be reported as a type error by type checkers
type_ = cast("type[object]", type_)
+ if is_type_alias_type(type_):
+ original_type = type_ # type: ignore[unreachable]
+ type_ = type_.__value__ # type: ignore[unreachable]
# unwrap `Annotated[T, ...]` -> `T`
if is_annotated_type(type_):
@@ -443,7 +451,7 @@ def construct_type(*, value: object, type_: object) -> object:
if is_union(origin):
try:
- return validate_type(type_=cast("type[object]", type_), value=value)
+ return validate_type(type_=cast("type[object]", original_type or type_), value=value)
except Exception:
pass
@@ -485,7 +493,11 @@ def construct_type(*, value: object, type_: object) -> object:
_, items_type = get_args(type_) # Dict[_, items_type]
return {key: construct_type(value=item, type_=items_type) for key, item in value.items()}
- if not is_literal_type(type_) and (issubclass(origin, BaseModel) or issubclass(origin, GenericModel)):
+ if (
+ not is_literal_type(type_)
+ and inspect.isclass(origin)
+ and (issubclass(origin, BaseModel) or issubclass(origin, GenericModel))
+ ):
if is_list(value):
return [cast(Any, type_).construct(**entry) if is_mapping(entry) else entry for entry in value]
@@ -614,8 +626,8 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any,
# Note: if one variant defines an alias then they all should
discriminator_alias = field_info.alias
- if field_info.annotation and is_literal_type(field_info.annotation):
- for entry in get_args(field_info.annotation):
+ if (annotation := getattr(field_info, "annotation", None)) and is_literal_type(annotation):
+ for entry in get_args(annotation):
if isinstance(entry, str):
mapping[entry] = variant
@@ -633,15 +645,18 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any,
def _extract_field_schema_pv2(model: type[BaseModel], field_name: str) -> ModelField | None:
schema = model.__pydantic_core_schema__
+ if schema["type"] == "definitions":
+ schema = schema["schema"]
+
if schema["type"] != "model":
return None
+ schema = cast("ModelSchema", schema)
fields_schema = schema["schema"]
if fields_schema["type"] != "model-fields":
return None
fields_schema = cast("ModelFieldsSchema", fields_schema)
-
field = fields_schema["fields"].get(field_name)
if not field:
return None
@@ -665,7 +680,7 @@ def set_pydantic_config(typ: Any, config: pydantic.ConfigDict) -> None:
setattr(typ, "__pydantic_config__", config) # noqa: B010
-# our use of subclasssing here causes weirdness for type checkers,
+# our use of subclassing here causes weirdness for type checkers,
# so we just pretend that we don't subclass
if TYPE_CHECKING:
GenericModel = BaseModel
diff --git a/src/braintrust_api/_response.py b/src/braintrust_api/_response.py
index 1658de82..8553aac9 100755
--- a/src/braintrust_api/_response.py
+++ b/src/braintrust_api/_response.py
@@ -25,7 +25,7 @@
import pydantic
from ._types import NoneType
-from ._utils import is_given, extract_type_arg, is_annotated_type, extract_type_var_from_base
+from ._utils import is_given, extract_type_arg, is_annotated_type, is_type_alias_type, extract_type_var_from_base
from ._models import BaseModel, is_basemodel
from ._constants import RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER
from ._streaming import Stream, AsyncStream, is_stream_class_type, extract_stream_chunk_type
@@ -126,9 +126,17 @@ def __repr__(self) -> str:
)
def _parse(self, *, to: type[_T] | None = None) -> R | _T:
+ cast_to = to if to is not None else self._cast_to
+
+ # unwrap `TypeAlias('Name', T)` -> `T`
+ if is_type_alias_type(cast_to):
+ cast_to = cast_to.__value__ # type: ignore[unreachable]
+
# unwrap `Annotated[T, ...]` -> `T`
- if to and is_annotated_type(to):
- to = extract_type_arg(to, 0)
+ if cast_to and is_annotated_type(cast_to):
+ cast_to = extract_type_arg(cast_to, 0)
+
+ origin = get_origin(cast_to) or cast_to
if self._is_sse_stream:
if to:
@@ -164,18 +172,12 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
return cast(
R,
stream_cls(
- cast_to=self._cast_to,
+ cast_to=cast_to,
response=self.http_response,
client=cast(Any, self._client),
),
)
- cast_to = to if to is not None else self._cast_to
-
- # unwrap `Annotated[T, ...]` -> `T`
- if is_annotated_type(cast_to):
- cast_to = extract_type_arg(cast_to, 0)
-
if cast_to is NoneType:
return cast(R, None)
@@ -195,8 +197,6 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
if cast_to == bool:
return cast(R, response.text.lower() == "true")
- origin = get_origin(cast_to) or cast_to
-
if origin == APIResponse:
raise RuntimeError("Unexpected state - cast_to is `APIResponse`")
@@ -210,7 +210,13 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
raise ValueError(f"Subclasses of httpx.Response cannot be passed to `cast_to`")
return cast(R, response)
- if inspect.isclass(origin) and not issubclass(origin, BaseModel) and issubclass(origin, pydantic.BaseModel):
+ if (
+ inspect.isclass(
+ origin # pyright: ignore[reportUnknownArgumentType]
+ )
+ and not issubclass(origin, BaseModel)
+ and issubclass(origin, pydantic.BaseModel)
+ ):
raise TypeError(
"Pydantic models must subclass our base model type, e.g. `from braintrust_api import BaseModel`"
)
@@ -229,7 +235,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
# split is required to handle cases where additional information is included
# in the response, e.g. application/json; charset=utf-8
content_type, *_ = response.headers.get("content-type", "*").split(";")
- if content_type != "application/json":
+ if not content_type.endswith("json"):
if is_basemodel(cast_to):
try:
data = response.json()
diff --git a/src/braintrust_api/_types.py b/src/braintrust_api/_types.py
index 41e40751..5e530610 100755
--- a/src/braintrust_api/_types.py
+++ b/src/braintrust_api/_types.py
@@ -192,10 +192,8 @@ def get(self, __key: str) -> str | None: ...
StrBytesIntFloat = Union[str, bytes, int, float]
# Note: copied from Pydantic
-# https://github.com/pydantic/pydantic/blob/32ea570bf96e84234d2992e1ddf40ab8a565925a/pydantic/main.py#L49
-IncEx: TypeAlias = Union[
- Set[int], Set[str], Mapping[int, Union["IncEx", Literal[True]]], Mapping[str, Union["IncEx", Literal[True]]]
-]
+# https://github.com/pydantic/pydantic/blob/6f31f8f68ef011f84357330186f603ff295312fd/pydantic/main.py#L79
+IncEx: TypeAlias = Union[Set[int], Set[str], Mapping[int, Union["IncEx", bool]], Mapping[str, Union["IncEx", bool]]]
PostParser = Callable[[Any], Any]
diff --git a/src/braintrust_api/_utils/__init__.py b/src/braintrust_api/_utils/__init__.py
index a7cff3c0..d4fda26f 100755
--- a/src/braintrust_api/_utils/__init__.py
+++ b/src/braintrust_api/_utils/__init__.py
@@ -39,6 +39,7 @@
is_iterable_type as is_iterable_type,
is_required_type as is_required_type,
is_annotated_type as is_annotated_type,
+ is_type_alias_type as is_type_alias_type,
strip_annotated_type as strip_annotated_type,
extract_type_var_from_base as extract_type_var_from_base,
)
diff --git a/src/braintrust_api/_utils/_proxy.py b/src/braintrust_api/_utils/_proxy.py
index ffd883e9..0f239a33 100755
--- a/src/braintrust_api/_utils/_proxy.py
+++ b/src/braintrust_api/_utils/_proxy.py
@@ -46,7 +46,10 @@ def __dir__(self) -> Iterable[str]:
@property # type: ignore
@override
def __class__(self) -> type: # pyright: ignore
- proxied = self.__get_proxied__()
+ try:
+ proxied = self.__get_proxied__()
+ except Exception:
+ return type(self)
if issubclass(type(proxied), LazyProxy):
return type(proxied)
return proxied.__class__
diff --git a/src/braintrust_api/_utils/_resources_proxy.py b/src/braintrust_api/_utils/_resources_proxy.py
new file mode 100644
index 00000000..3befc3ce
--- /dev/null
+++ b/src/braintrust_api/_utils/_resources_proxy.py
@@ -0,0 +1,24 @@
+from __future__ import annotations
+
+from typing import Any
+from typing_extensions import override
+
+from ._proxy import LazyProxy
+
+
+class ResourcesProxy(LazyProxy[Any]):
+ """A proxy for the `braintrust_api.resources` module.
+
+ This is used so that we can lazily import `braintrust_api.resources` only when
+ needed *and* so that users can just import `braintrust_api` and reference `braintrust_api.resources`
+ """
+
+ @override
+ def __load__(self) -> Any:
+ import importlib
+
+ mod = importlib.import_module("braintrust_api.resources")
+ return mod
+
+
+resources = ResourcesProxy().__as_proxied__()
diff --git a/src/braintrust_api/_utils/_sync.py b/src/braintrust_api/_utils/_sync.py
index 8b3aaf2b..ad7ec71b 100755
--- a/src/braintrust_api/_utils/_sync.py
+++ b/src/braintrust_api/_utils/_sync.py
@@ -7,16 +7,20 @@
from typing import Any, TypeVar, Callable, Awaitable
from typing_extensions import ParamSpec
+import anyio
+import sniffio
+import anyio.to_thread
+
T_Retval = TypeVar("T_Retval")
T_ParamSpec = ParamSpec("T_ParamSpec")
if sys.version_info >= (3, 9):
- to_thread = asyncio.to_thread
+ _asyncio_to_thread = asyncio.to_thread
else:
# backport of https://docs.python.org/3/library/asyncio-task.html#asyncio.to_thread
# for Python 3.8 support
- async def to_thread(
+ async def _asyncio_to_thread(
func: Callable[T_ParamSpec, T_Retval], /, *args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs
) -> Any:
"""Asynchronously run function *func* in a separate thread.
@@ -34,6 +38,17 @@ async def to_thread(
return await loop.run_in_executor(None, func_call)
+async def to_thread(
+ func: Callable[T_ParamSpec, T_Retval], /, *args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs
+) -> T_Retval:
+ if sniffio.current_async_library() == "asyncio":
+ return await _asyncio_to_thread(func, *args, **kwargs)
+
+ return await anyio.to_thread.run_sync(
+ functools.partial(func, *args, **kwargs),
+ )
+
+
# inspired by `asyncer`, https://github.com/tiangolo/asyncer
def asyncify(function: Callable[T_ParamSpec, T_Retval]) -> Callable[T_ParamSpec, Awaitable[T_Retval]]:
"""
diff --git a/src/braintrust_api/_utils/_transform.py b/src/braintrust_api/_utils/_transform.py
index a6b62cad..b0cc20a7 100755
--- a/src/braintrust_api/_utils/_transform.py
+++ b/src/braintrust_api/_utils/_transform.py
@@ -5,13 +5,15 @@
import pathlib
from typing import Any, Mapping, TypeVar, cast
from datetime import date, datetime
-from typing_extensions import Literal, get_args, override, get_type_hints
+from typing_extensions import Literal, get_args, override, get_type_hints as _get_type_hints
import anyio
import pydantic
from ._utils import (
is_list,
+ is_given,
+ lru_cache,
is_mapping,
is_iterable,
)
@@ -25,7 +27,7 @@
is_annotated_type,
strip_annotated_type,
)
-from .._compat import model_dump, is_typeddict
+from .._compat import get_origin, model_dump, is_typeddict
_T = TypeVar("_T")
@@ -108,6 +110,7 @@ class Params(TypedDict, total=False):
return cast(_T, transformed)
+@lru_cache(maxsize=8096)
def _get_annotated_type(type_: type) -> type | None:
"""If the given type is an `Annotated` type then it is returned, if not `None` is returned.
@@ -126,7 +129,7 @@ def _get_annotated_type(type_: type) -> type | None:
def _maybe_transform_key(key: str, type_: type) -> str:
"""Transform the given `data` based on the annotations provided in `type_`.
- Note: this function only looks at `Annotated` types that contain `PropertInfo` metadata.
+ Note: this function only looks at `Annotated` types that contain `PropertyInfo` metadata.
"""
annotated_type = _get_annotated_type(type_)
if annotated_type is None:
@@ -142,6 +145,10 @@ def _maybe_transform_key(key: str, type_: type) -> str:
return key
+def _no_transform_needed(annotation: type) -> bool:
+ return annotation == float or annotation == int
+
+
def _transform_recursive(
data: object,
*,
@@ -164,9 +171,14 @@ def _transform_recursive(
inner_type = annotation
stripped_type = strip_annotated_type(inner_type)
+ origin = get_origin(stripped_type) or stripped_type
if is_typeddict(stripped_type) and is_mapping(data):
return _transform_typeddict(data, stripped_type)
+ if origin == dict and is_mapping(data):
+ items_type = get_args(stripped_type)[1]
+ return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()}
+
if (
# List[T]
(is_list_type(stripped_type) and is_list(data))
@@ -179,6 +191,15 @@ def _transform_recursive(
return cast(object, data)
inner_type = extract_type_arg(stripped_type, 0)
+ if _no_transform_needed(inner_type):
+ # for some types there is no need to transform anything, so we can get a small
+ # perf boost from skipping that work.
+ #
+ # but we still need to convert to a list to ensure the data is json-serializable
+ if is_list(data):
+ return data
+ return list(data)
+
return [_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data]
if is_union_type(stripped_type):
@@ -240,6 +261,11 @@ def _transform_typeddict(
result: dict[str, object] = {}
annotations = get_type_hints(expected_type, include_extras=True)
for key, value in data.items():
+ if not is_given(value):
+ # we don't need to include `NotGiven` values here as they'll
+ # be stripped out before the request is sent anyway
+ continue
+
type_ = annotations.get(key)
if type_ is None:
# we do not have a type annotation for this field, leave it as is
@@ -307,9 +333,14 @@ async def _async_transform_recursive(
inner_type = annotation
stripped_type = strip_annotated_type(inner_type)
+ origin = get_origin(stripped_type) or stripped_type
if is_typeddict(stripped_type) and is_mapping(data):
return await _async_transform_typeddict(data, stripped_type)
+ if origin == dict and is_mapping(data):
+ items_type = get_args(stripped_type)[1]
+ return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()}
+
if (
# List[T]
(is_list_type(stripped_type) and is_list(data))
@@ -322,6 +353,15 @@ async def _async_transform_recursive(
return cast(object, data)
inner_type = extract_type_arg(stripped_type, 0)
+ if _no_transform_needed(inner_type):
+ # for some types there is no need to transform anything, so we can get a small
+ # perf boost from skipping that work.
+ #
+ # but we still need to convert to a list to ensure the data is json-serializable
+ if is_list(data):
+ return data
+ return list(data)
+
return [await _async_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data]
if is_union_type(stripped_type):
@@ -383,6 +423,11 @@ async def _async_transform_typeddict(
result: dict[str, object] = {}
annotations = get_type_hints(expected_type, include_extras=True)
for key, value in data.items():
+ if not is_given(value):
+ # we don't need to include `NotGiven` values here as they'll
+ # be stripped out before the request is sent anyway
+ continue
+
type_ = annotations.get(key)
if type_ is None:
# we do not have a type annotation for this field, leave it as is
@@ -390,3 +435,13 @@ async def _async_transform_typeddict(
else:
result[_maybe_transform_key(key, type_)] = await _async_transform_recursive(value, annotation=type_)
return result
+
+
+@lru_cache(maxsize=8096)
+def get_type_hints(
+ obj: Any,
+ globalns: dict[str, Any] | None = None,
+ localns: Mapping[str, Any] | None = None,
+ include_extras: bool = False,
+) -> dict[str, Any]:
+ return _get_type_hints(obj, globalns=globalns, localns=localns, include_extras=include_extras)
diff --git a/src/braintrust_api/_utils/_typing.py b/src/braintrust_api/_utils/_typing.py
index c036991f..1bac9542 100755
--- a/src/braintrust_api/_utils/_typing.py
+++ b/src/braintrust_api/_utils/_typing.py
@@ -1,9 +1,19 @@
from __future__ import annotations
+import sys
+import typing
+import typing_extensions
from typing import Any, TypeVar, Iterable, cast
from collections import abc as _c_abc
-from typing_extensions import Required, Annotated, get_args, get_origin
-
+from typing_extensions import (
+ TypeIs,
+ Required,
+ Annotated,
+ get_args,
+ get_origin,
+)
+
+from ._utils import lru_cache
from .._types import InheritsGeneric
from .._compat import is_union as _is_union
@@ -36,7 +46,28 @@ def is_typevar(typ: type) -> bool:
return type(typ) == TypeVar # type: ignore
+_TYPE_ALIAS_TYPES: tuple[type[typing_extensions.TypeAliasType], ...] = (typing_extensions.TypeAliasType,)
+if sys.version_info >= (3, 12):
+ _TYPE_ALIAS_TYPES = (*_TYPE_ALIAS_TYPES, typing.TypeAliasType)
+
+
+def is_type_alias_type(tp: Any, /) -> TypeIs[typing_extensions.TypeAliasType]:
+ """Return whether the provided argument is an instance of `TypeAliasType`.
+
+ ```python
+ type Int = int
+ is_type_alias_type(Int)
+ # > True
+ Str = TypeAliasType("Str", str)
+ is_type_alias_type(Str)
+ # > True
+ ```
+ """
+ return isinstance(tp, _TYPE_ALIAS_TYPES)
+
+
# Extracts T from Annotated[T, ...] or from Required[Annotated[T, ...]]
+@lru_cache(maxsize=8096)
def strip_annotated_type(typ: type) -> type:
if is_required_type(typ) or is_annotated_type(typ):
return strip_annotated_type(cast(type, get_args(typ)[0]))
@@ -79,7 +110,7 @@ class MyResponse(Foo[_T]):
```
"""
cls = cast(object, get_origin(typ) or typ)
- if cls in generic_bases:
+ if cls in generic_bases: # pyright: ignore[reportUnnecessaryContains]
# we're given the class directly
return extract_type_arg(typ, index)
diff --git a/src/braintrust_api/_utils/_utils.py b/src/braintrust_api/_utils/_utils.py
index e5811bba..ea3cf3f2 100755
--- a/src/braintrust_api/_utils/_utils.py
+++ b/src/braintrust_api/_utils/_utils.py
@@ -72,8 +72,16 @@ def _extract_items(
from .._files import assert_is_file_content
# We have exhausted the path, return the entry we found.
- assert_is_file_content(obj, key=flattened_key)
assert flattened_key is not None
+
+ if is_list(obj):
+ files: list[tuple[str, FileTypes]] = []
+ for entry in obj:
+ assert_is_file_content(entry, key=flattened_key + "[]" if flattened_key else "")
+ files.append((flattened_key + "[]", cast(FileTypes, entry)))
+ return files
+
+ assert_is_file_content(obj, key=flattened_key)
return [(flattened_key, cast(FileTypes, obj))]
index += 1
diff --git a/src/braintrust_api/_version.py b/src/braintrust_api/_version.py
index 39415709..363fcd46 100755
--- a/src/braintrust_api/_version.py
+++ b/src/braintrust_api/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "braintrust_api"
-__version__ = "0.6.0" # x-release-please-version
+__version__ = "0.7.0" # x-release-please-version
diff --git a/src/braintrust_api/resources/acls.py b/src/braintrust_api/resources/acls.py
index 60af5e9f..b171c650 100644
--- a/src/braintrust_api/resources/acls.py
+++ b/src/braintrust_api/resources/acls.py
@@ -3,21 +3,12 @@
from __future__ import annotations
from typing import List, Union, Iterable, Optional
-from typing_extensions import Literal
import httpx
-from ..types import (
- acl_list_params,
- acl_create_params,
- acl_batch_update_params,
- acl_find_and_delete_params,
-)
+from ..types import acl_list_params, acl_create_params, acl_batch_update_params, acl_find_and_delete_params
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -29,6 +20,8 @@
from ..pagination import SyncListObjects, AsyncListObjects
from .._base_client import AsyncPaginator, make_request_options
from ..types.shared.acl import ACL
+from ..types.shared.permission import Permission
+from ..types.shared.acl_object_type import ACLObjectType
from ..types.shared.acl_batch_update_response import ACLBatchUpdateResponse
__all__ = ["ACLsResource", "AsyncACLsResource"]
@@ -38,7 +31,7 @@ class ACLsResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> ACLsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -58,40 +51,10 @@ def create(
self,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
group_id: Optional[str] | NotGiven = NOT_GIVEN,
- permission: Optional[
- Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
- ]
- | NotGiven = NOT_GIVEN,
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
- | NotGiven = NOT_GIVEN,
+ permission: Optional[Permission] | NotGiven = NOT_GIVEN,
+ restrict_object_type: Optional[ACLObjectType] | NotGiven = NOT_GIVEN,
role_id: Optional[str] | NotGiven = NOT_GIVEN,
user_id: Optional[str] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -193,19 +156,7 @@ def list(
self,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
ending_before: str | NotGiven = NOT_GIVEN,
ids: Union[str, List[str]] | NotGiven = NOT_GIVEN,
limit: Optional[int] | NotGiven = NOT_GIVEN,
@@ -360,7 +311,7 @@ def batch_update(
timeout: Override the client-level default timeout for this request, in seconds
"""
return self._post(
- "/v1/acl/batch-update",
+ "/v1/acl/batch_update",
body=maybe_transform(
{
"add_acls": add_acls,
@@ -378,40 +329,10 @@ def find_and_delete(
self,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
group_id: Optional[str] | NotGiven = NOT_GIVEN,
- permission: Optional[
- Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
- ]
- | NotGiven = NOT_GIVEN,
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
- | NotGiven = NOT_GIVEN,
+ permission: Optional[Permission] | NotGiven = NOT_GIVEN,
+ restrict_object_type: Optional[ACLObjectType] | NotGiven = NOT_GIVEN,
role_id: Optional[str] | NotGiven = NOT_GIVEN,
user_id: Optional[str] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -477,7 +398,7 @@ class AsyncACLsResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncACLsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -497,40 +418,10 @@ async def create(
self,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
group_id: Optional[str] | NotGiven = NOT_GIVEN,
- permission: Optional[
- Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
- ]
- | NotGiven = NOT_GIVEN,
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
- | NotGiven = NOT_GIVEN,
+ permission: Optional[Permission] | NotGiven = NOT_GIVEN,
+ restrict_object_type: Optional[ACLObjectType] | NotGiven = NOT_GIVEN,
role_id: Optional[str] | NotGiven = NOT_GIVEN,
user_id: Optional[str] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -632,19 +523,7 @@ def list(
self,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
ending_before: str | NotGiven = NOT_GIVEN,
ids: Union[str, List[str]] | NotGiven = NOT_GIVEN,
limit: Optional[int] | NotGiven = NOT_GIVEN,
@@ -799,7 +678,7 @@ async def batch_update(
timeout: Override the client-level default timeout for this request, in seconds
"""
return await self._post(
- "/v1/acl/batch-update",
+ "/v1/acl/batch_update",
body=await async_maybe_transform(
{
"add_acls": add_acls,
@@ -817,40 +696,10 @@ async def find_and_delete(
self,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
group_id: Optional[str] | NotGiven = NOT_GIVEN,
- permission: Optional[
- Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
- ]
- | NotGiven = NOT_GIVEN,
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
- | NotGiven = NOT_GIVEN,
+ permission: Optional[Permission] | NotGiven = NOT_GIVEN,
+ restrict_object_type: Optional[ACLObjectType] | NotGiven = NOT_GIVEN,
role_id: Optional[str] | NotGiven = NOT_GIVEN,
user_id: Optional[str] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
diff --git a/src/braintrust_api/resources/ai_secrets.py b/src/braintrust_api/resources/ai_secrets.py
index 2d8a3f73..d95b5e9e 100644
--- a/src/braintrust_api/resources/ai_secrets.py
+++ b/src/braintrust_api/resources/ai_secrets.py
@@ -14,10 +14,7 @@
ai_secret_find_and_delete_params,
)
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -37,7 +34,7 @@ class AISecretsResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> AISecretsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -415,7 +412,7 @@ class AsyncAISecretsResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncAISecretsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/api_keys.py b/src/braintrust_api/resources/api_keys.py
index 1b40f611..3c4307a1 100644
--- a/src/braintrust_api/resources/api_keys.py
+++ b/src/braintrust_api/resources/api_keys.py
@@ -8,10 +8,7 @@
from ..types import api_key_list_params, api_key_create_params
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -32,7 +29,7 @@ class APIKeysResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> APIKeysResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -244,7 +241,7 @@ class AsyncAPIKeysResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncAPIKeysResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/datasets.py b/src/braintrust_api/resources/datasets.py
index b835e563..e8993dde 100644
--- a/src/braintrust_api/resources/datasets.py
+++ b/src/braintrust_api/resources/datasets.py
@@ -17,10 +17,7 @@
dataset_fetch_post_params,
)
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -46,7 +43,7 @@ class DatasetsResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> DatasetsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -650,7 +647,7 @@ class AsyncDatasetsResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncDatasetsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/env_vars.py b/src/braintrust_api/resources/env_vars.py
index cdab08e3..1a44fe62 100644
--- a/src/braintrust_api/resources/env_vars.py
+++ b/src/braintrust_api/resources/env_vars.py
@@ -7,17 +7,9 @@
import httpx
-from ..types import (
- env_var_list_params,
- env_var_create_params,
- env_var_update_params,
- env_var_replace_params,
-)
+from ..types import env_var_list_params, env_var_create_params, env_var_update_params, env_var_replace_params
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -29,6 +21,7 @@
from .._base_client import make_request_options
from ..types.shared.env_var import EnvVar
from ..types.env_var_list_response import EnvVarListResponse
+from ..types.shared.env_var_object_type import EnvVarObjectType
__all__ = ["EnvVarsResource", "AsyncEnvVarsResource"]
@@ -37,7 +30,7 @@ class EnvVarsResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> EnvVarsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -199,7 +192,7 @@ def list(
ids: Union[str, List[str]] | NotGiven = NOT_GIVEN,
limit: Optional[int] | NotGiven = NOT_GIVEN,
object_id: str | NotGiven = NOT_GIVEN,
- object_type: Literal["organization", "project", "function"] | NotGiven = NOT_GIVEN,
+ object_type: EnvVarObjectType | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -347,7 +340,7 @@ class AsyncEnvVarsResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncEnvVarsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -509,7 +502,7 @@ async def list(
ids: Union[str, List[str]] | NotGiven = NOT_GIVEN,
limit: Optional[int] | NotGiven = NOT_GIVEN,
object_id: str | NotGiven = NOT_GIVEN,
- object_type: Literal["organization", "project", "function"] | NotGiven = NOT_GIVEN,
+ object_type: EnvVarObjectType | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
diff --git a/src/braintrust_api/resources/evals.py b/src/braintrust_api/resources/evals.py
index 2e8c382e..1e387b97 100644
--- a/src/braintrust_api/resources/evals.py
+++ b/src/braintrust_api/resources/evals.py
@@ -8,10 +8,7 @@
from ..types import eval_create_params
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -31,7 +28,7 @@ class EvalsResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> EvalsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -61,6 +58,7 @@ def create(
is_public: Optional[bool] | NotGiven = NOT_GIVEN,
max_concurrency: Optional[float] | NotGiven = NOT_GIVEN,
metadata: Dict[str, Optional[object]] | NotGiven = NOT_GIVEN,
+ parent: eval_create_params.Parent | NotGiven = NOT_GIVEN,
repo_info: Optional[RepoInfo] | NotGiven = NOT_GIVEN,
stream: bool | NotGiven = NOT_GIVEN,
api_timeout: Optional[float] | NotGiven = NOT_GIVEN,
@@ -110,6 +108,8 @@ def create(
metadata: Optional experiment-level metadata to store about the evaluation. You can later
use this to slice & dice across experiments.
+ parent: Options for tracing the evaluation
+
repo_info: Metadata about the state of the repo when the experiment was created
stream: Whether to stream the results of the eval. If true, the request will return two
@@ -146,6 +146,7 @@ def create(
"is_public": is_public,
"max_concurrency": max_concurrency,
"metadata": metadata,
+ "parent": parent,
"repo_info": repo_info,
"stream": stream,
"api_timeout": api_timeout,
@@ -164,7 +165,7 @@ class AsyncEvalsResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncEvalsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -194,6 +195,7 @@ async def create(
is_public: Optional[bool] | NotGiven = NOT_GIVEN,
max_concurrency: Optional[float] | NotGiven = NOT_GIVEN,
metadata: Dict[str, Optional[object]] | NotGiven = NOT_GIVEN,
+ parent: eval_create_params.Parent | NotGiven = NOT_GIVEN,
repo_info: Optional[RepoInfo] | NotGiven = NOT_GIVEN,
stream: bool | NotGiven = NOT_GIVEN,
api_timeout: Optional[float] | NotGiven = NOT_GIVEN,
@@ -243,6 +245,8 @@ async def create(
metadata: Optional experiment-level metadata to store about the evaluation. You can later
use this to slice & dice across experiments.
+ parent: Options for tracing the evaluation
+
repo_info: Metadata about the state of the repo when the experiment was created
stream: Whether to stream the results of the eval. If true, the request will return two
@@ -279,6 +283,7 @@ async def create(
"is_public": is_public,
"max_concurrency": max_concurrency,
"metadata": metadata,
+ "parent": parent,
"repo_info": repo_info,
"stream": stream,
"api_timeout": api_timeout,
diff --git a/src/braintrust_api/resources/experiments.py b/src/braintrust_api/resources/experiments.py
index e5afec3b..2f627528 100644
--- a/src/braintrust_api/resources/experiments.py
+++ b/src/braintrust_api/resources/experiments.py
@@ -17,10 +17,7 @@
experiment_fetch_post_params,
)
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -47,7 +44,7 @@ class ExperimentsResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> ExperimentsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -714,7 +711,7 @@ class AsyncExperimentsResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncExperimentsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/functions.py b/src/braintrust_api/resources/functions.py
index 2d5b333b..5190101e 100644
--- a/src/braintrust_api/resources/functions.py
+++ b/src/braintrust_api/resources/functions.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import List, Union, Iterable, Optional
+from typing import Dict, List, Union, Iterable, Optional
from typing_extensions import Literal
import httpx
@@ -15,10 +15,7 @@
function_replace_params,
)
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -39,7 +36,7 @@ class FunctionsResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> FunctionsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -167,7 +164,7 @@ def update(
function_id: str,
*,
description: Optional[str] | NotGiven = NOT_GIVEN,
- function_data: function_update_params.FunctionData | NotGiven = NOT_GIVEN,
+ function_data: Optional[function_update_params.FunctionData] | NotGiven = NOT_GIVEN,
name: Optional[str] | NotGiven = NOT_GIVEN,
prompt_data: Optional[PromptData] | NotGiven = NOT_GIVEN,
tags: Optional[List[str]] | NotGiven = NOT_GIVEN,
@@ -355,8 +352,10 @@ def invoke(
self,
function_id: str,
*,
- input: Optional[object] | NotGiven = NOT_GIVEN,
+ expected: object | NotGiven = NOT_GIVEN,
+ input: object | NotGiven = NOT_GIVEN,
messages: Iterable[function_invoke_params.Message] | NotGiven = NOT_GIVEN,
+ metadata: Optional[Dict[str, Optional[object]]] | NotGiven = NOT_GIVEN,
mode: Optional[Literal["auto", "parallel"]] | NotGiven = NOT_GIVEN,
parent: function_invoke_params.Parent | NotGiven = NOT_GIVEN,
stream: Optional[bool] | NotGiven = NOT_GIVEN,
@@ -374,10 +373,14 @@ def invoke(
Args:
function_id: Function id
+ expected: The expected output of the function
+
input: Argument to the function, which can be any JSON serializable value
messages: If the function is an LLM, additional messages to pass along to it
+ metadata: Any relevant metadata
+
mode: The mode format of the returned value (defaults to 'auto')
parent: Options for tracing the function call
@@ -401,8 +404,10 @@ def invoke(
f"/v1/function/{function_id}/invoke",
body=maybe_transform(
{
+ "expected": expected,
"input": input,
"messages": messages,
+ "metadata": metadata,
"mode": mode,
"parent": parent,
"stream": stream,
@@ -493,7 +498,7 @@ class AsyncFunctionsResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncFunctionsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -621,7 +626,7 @@ async def update(
function_id: str,
*,
description: Optional[str] | NotGiven = NOT_GIVEN,
- function_data: function_update_params.FunctionData | NotGiven = NOT_GIVEN,
+ function_data: Optional[function_update_params.FunctionData] | NotGiven = NOT_GIVEN,
name: Optional[str] | NotGiven = NOT_GIVEN,
prompt_data: Optional[PromptData] | NotGiven = NOT_GIVEN,
tags: Optional[List[str]] | NotGiven = NOT_GIVEN,
@@ -809,8 +814,10 @@ async def invoke(
self,
function_id: str,
*,
- input: Optional[object] | NotGiven = NOT_GIVEN,
+ expected: object | NotGiven = NOT_GIVEN,
+ input: object | NotGiven = NOT_GIVEN,
messages: Iterable[function_invoke_params.Message] | NotGiven = NOT_GIVEN,
+ metadata: Optional[Dict[str, Optional[object]]] | NotGiven = NOT_GIVEN,
mode: Optional[Literal["auto", "parallel"]] | NotGiven = NOT_GIVEN,
parent: function_invoke_params.Parent | NotGiven = NOT_GIVEN,
stream: Optional[bool] | NotGiven = NOT_GIVEN,
@@ -828,10 +835,14 @@ async def invoke(
Args:
function_id: Function id
+ expected: The expected output of the function
+
input: Argument to the function, which can be any JSON serializable value
messages: If the function is an LLM, additional messages to pass along to it
+ metadata: Any relevant metadata
+
mode: The mode format of the returned value (defaults to 'auto')
parent: Options for tracing the function call
@@ -855,8 +866,10 @@ async def invoke(
f"/v1/function/{function_id}/invoke",
body=await async_maybe_transform(
{
+ "expected": expected,
"input": input,
"messages": messages,
+ "metadata": metadata,
"mode": mode,
"parent": parent,
"stream": stream,
diff --git a/src/braintrust_api/resources/groups.py b/src/braintrust_api/resources/groups.py
index e61e0a45..8b0b35c0 100644
--- a/src/braintrust_api/resources/groups.py
+++ b/src/braintrust_api/resources/groups.py
@@ -8,10 +8,7 @@
from ..types import group_list_params, group_create_params, group_update_params, group_replace_params
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -31,7 +28,7 @@ class GroupsResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> GroupsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -388,7 +385,7 @@ class AsyncGroupsResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncGroupsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/organizations/members.py b/src/braintrust_api/resources/organizations/members.py
index f5df5dc7..89be89e2 100644
--- a/src/braintrust_api/resources/organizations/members.py
+++ b/src/braintrust_api/resources/organizations/members.py
@@ -7,10 +7,7 @@
import httpx
from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from ..._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from ..._utils import maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -30,7 +27,7 @@ class MembersResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> MembersResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -108,7 +105,7 @@ class AsyncMembersResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncMembersResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/organizations/organizations.py b/src/braintrust_api/resources/organizations/organizations.py
index 19323792..05ffe3b4 100644
--- a/src/braintrust_api/resources/organizations/organizations.py
+++ b/src/braintrust_api/resources/organizations/organizations.py
@@ -16,10 +16,7 @@
AsyncMembersResourceWithStreamingResponse,
)
from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from ..._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from ..._utils import maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -43,7 +40,7 @@ def members(self) -> MembersResource:
@cached_property
def with_raw_response(self) -> OrganizationsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -263,7 +260,7 @@ def members(self) -> AsyncMembersResource:
@cached_property
def with_raw_response(self) -> AsyncOrganizationsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/project_scores.py b/src/braintrust_api/resources/project_scores.py
index 9c67d1ac..3495e6a3 100644
--- a/src/braintrust_api/resources/project_scores.py
+++ b/src/braintrust_api/resources/project_scores.py
@@ -2,8 +2,7 @@
from __future__ import annotations
-from typing import List, Union, Optional
-from typing_extensions import Literal
+from typing import Dict, List, Union, Iterable, Optional
import httpx
@@ -14,10 +13,7 @@
project_score_replace_params,
)
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -29,7 +25,9 @@
from ..pagination import SyncListObjects, AsyncListObjects
from .._base_client import AsyncPaginator, make_request_options
from ..types.shared.project_score import ProjectScore
+from ..types.shared.project_score_type import ProjectScoreType
from ..types.shared_params.project_score_config import ProjectScoreConfig
+from ..types.shared_params.project_score_category import ProjectScoreCategory
__all__ = ["ProjectScoresResource", "AsyncProjectScoresResource"]
@@ -38,7 +36,7 @@ class ProjectScoresResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> ProjectScoresResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -59,8 +57,8 @@ def create(
*,
name: str,
project_id: str,
- score_type: Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"],
- categories: project_score_create_params.Categories | NotGiven = NOT_GIVEN,
+ score_type: ProjectScoreType,
+ categories: Union[Iterable[ProjectScoreCategory], Dict[str, float], List[str], None] | NotGiven = NOT_GIVEN,
config: Optional[ProjectScoreConfig] | NotGiven = NOT_GIVEN,
description: Optional[str] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -153,12 +151,11 @@ def update(
self,
project_score_id: str,
*,
- categories: project_score_update_params.Categories | NotGiven = NOT_GIVEN,
+ categories: Union[Iterable[ProjectScoreCategory], Dict[str, float], List[str], None] | NotGiven = NOT_GIVEN,
config: Optional[ProjectScoreConfig] | NotGiven = NOT_GIVEN,
description: Optional[str] | NotGiven = NOT_GIVEN,
name: Optional[str] | NotGiven = NOT_GIVEN,
- score_type: Optional[Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"]]
- | NotGiven = NOT_GIVEN,
+ score_type: Optional[ProjectScoreType] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -221,11 +218,7 @@ def list(
project_id: str | NotGiven = NOT_GIVEN,
project_name: str | NotGiven = NOT_GIVEN,
project_score_name: str | NotGiven = NOT_GIVEN,
- score_type: Union[
- Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"],
- List[Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"]],
- ]
- | NotGiven = NOT_GIVEN,
+ score_type: Union[ProjectScoreType, List[ProjectScoreType]] | NotGiven = NOT_GIVEN,
starting_after: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -341,8 +334,8 @@ def replace(
*,
name: str,
project_id: str,
- score_type: Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"],
- categories: project_score_replace_params.Categories | NotGiven = NOT_GIVEN,
+ score_type: ProjectScoreType,
+ categories: Union[Iterable[ProjectScoreCategory], Dict[str, float], List[str], None] | NotGiven = NOT_GIVEN,
config: Optional[ProjectScoreConfig] | NotGiven = NOT_GIVEN,
description: Optional[str] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -401,7 +394,7 @@ class AsyncProjectScoresResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncProjectScoresResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -422,8 +415,8 @@ async def create(
*,
name: str,
project_id: str,
- score_type: Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"],
- categories: project_score_create_params.Categories | NotGiven = NOT_GIVEN,
+ score_type: ProjectScoreType,
+ categories: Union[Iterable[ProjectScoreCategory], Dict[str, float], List[str], None] | NotGiven = NOT_GIVEN,
config: Optional[ProjectScoreConfig] | NotGiven = NOT_GIVEN,
description: Optional[str] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -516,12 +509,11 @@ async def update(
self,
project_score_id: str,
*,
- categories: project_score_update_params.Categories | NotGiven = NOT_GIVEN,
+ categories: Union[Iterable[ProjectScoreCategory], Dict[str, float], List[str], None] | NotGiven = NOT_GIVEN,
config: Optional[ProjectScoreConfig] | NotGiven = NOT_GIVEN,
description: Optional[str] | NotGiven = NOT_GIVEN,
name: Optional[str] | NotGiven = NOT_GIVEN,
- score_type: Optional[Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"]]
- | NotGiven = NOT_GIVEN,
+ score_type: Optional[ProjectScoreType] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -584,11 +576,7 @@ def list(
project_id: str | NotGiven = NOT_GIVEN,
project_name: str | NotGiven = NOT_GIVEN,
project_score_name: str | NotGiven = NOT_GIVEN,
- score_type: Union[
- Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"],
- List[Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"]],
- ]
- | NotGiven = NOT_GIVEN,
+ score_type: Union[ProjectScoreType, List[ProjectScoreType]] | NotGiven = NOT_GIVEN,
starting_after: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -704,8 +692,8 @@ async def replace(
*,
name: str,
project_id: str,
- score_type: Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"],
- categories: project_score_replace_params.Categories | NotGiven = NOT_GIVEN,
+ score_type: ProjectScoreType,
+ categories: Union[Iterable[ProjectScoreCategory], Dict[str, float], List[str], None] | NotGiven = NOT_GIVEN,
config: Optional[ProjectScoreConfig] | NotGiven = NOT_GIVEN,
description: Optional[str] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
diff --git a/src/braintrust_api/resources/project_tags.py b/src/braintrust_api/resources/project_tags.py
index 66c2f93d..83d24ad0 100644
--- a/src/braintrust_api/resources/project_tags.py
+++ b/src/braintrust_api/resources/project_tags.py
@@ -13,10 +13,7 @@
project_tag_replace_params,
)
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -36,7 +33,7 @@ class ProjectTagsResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> ProjectTagsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -372,7 +369,7 @@ class AsyncProjectTagsResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncProjectTagsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/projects/logs.py b/src/braintrust_api/resources/projects/logs.py
index 71550e24..2bd5ae6a 100644
--- a/src/braintrust_api/resources/projects/logs.py
+++ b/src/braintrust_api/resources/projects/logs.py
@@ -7,10 +7,7 @@
import httpx
from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from ..._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from ..._utils import maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -34,7 +31,7 @@ class LogsResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> LogsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -332,7 +329,7 @@ class AsyncLogsResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncLogsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/projects/projects.py b/src/braintrust_api/resources/projects/projects.py
index 92d2c3ad..0bf1b0ec 100644
--- a/src/braintrust_api/resources/projects/projects.py
+++ b/src/braintrust_api/resources/projects/projects.py
@@ -16,10 +16,7 @@
)
from ...types import project_list_params, project_create_params, project_update_params
from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from ..._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from ..._utils import maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -44,7 +41,7 @@ def logs(self) -> LogsResource:
@cached_property
def with_raw_response(self) -> ProjectsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -312,7 +309,7 @@ def logs(self) -> AsyncLogsResource:
@cached_property
def with_raw_response(self) -> AsyncProjectsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/prompts.py b/src/braintrust_api/resources/prompts.py
index 2de45baa..65a92512 100644
--- a/src/braintrust_api/resources/prompts.py
+++ b/src/braintrust_api/resources/prompts.py
@@ -7,17 +7,9 @@
import httpx
-from ..types import (
- prompt_list_params,
- prompt_create_params,
- prompt_update_params,
- prompt_replace_params,
-)
+from ..types import prompt_list_params, prompt_create_params, prompt_update_params, prompt_replace_params
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -38,7 +30,7 @@ class PromptsResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> PromptsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -413,7 +405,7 @@ class AsyncPromptsResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncPromptsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/roles.py b/src/braintrust_api/resources/roles.py
index ac5deb22..aa2401ec 100644
--- a/src/braintrust_api/resources/roles.py
+++ b/src/braintrust_api/resources/roles.py
@@ -8,10 +8,7 @@
from ..types import role_list_params, role_create_params, role_update_params, role_replace_params
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -31,7 +28,7 @@ class RolesResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> RolesResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -388,7 +385,7 @@ class AsyncRolesResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncRolesResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/span_iframes.py b/src/braintrust_api/resources/span_iframes.py
index 66ac16a4..b904d6fc 100644
--- a/src/braintrust_api/resources/span_iframes.py
+++ b/src/braintrust_api/resources/span_iframes.py
@@ -13,10 +13,7 @@
span_iframe_replace_params,
)
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -36,7 +33,7 @@ class SpanIframesResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> SpanIframesResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -150,6 +147,7 @@ def update(
self,
span_iframe_id: str,
*,
+ description: Optional[str] | NotGiven = NOT_GIVEN,
name: Optional[str] | NotGiven = NOT_GIVEN,
post_message: Optional[bool] | NotGiven = NOT_GIVEN,
url: Optional[str] | NotGiven = NOT_GIVEN,
@@ -169,6 +167,8 @@ def update(
Args:
span_iframe_id: SpanIframe id
+ description: Textual description of the span iframe
+
name: Name of the span iframe
post_message: Whether to post messages to the iframe containing the span's data. This is
@@ -190,6 +190,7 @@ def update(
f"/v1/span_iframe/{span_iframe_id}",
body=maybe_transform(
{
+ "description": description,
"name": name,
"post_message": post_message,
"url": url,
@@ -375,7 +376,7 @@ class AsyncSpanIframesResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncSpanIframesResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -489,6 +490,7 @@ async def update(
self,
span_iframe_id: str,
*,
+ description: Optional[str] | NotGiven = NOT_GIVEN,
name: Optional[str] | NotGiven = NOT_GIVEN,
post_message: Optional[bool] | NotGiven = NOT_GIVEN,
url: Optional[str] | NotGiven = NOT_GIVEN,
@@ -508,6 +510,8 @@ async def update(
Args:
span_iframe_id: SpanIframe id
+ description: Textual description of the span iframe
+
name: Name of the span iframe
post_message: Whether to post messages to the iframe containing the span's data. This is
@@ -529,6 +533,7 @@ async def update(
f"/v1/span_iframe/{span_iframe_id}",
body=await async_maybe_transform(
{
+ "description": description,
"name": name,
"post_message": post_message,
"url": url,
diff --git a/src/braintrust_api/resources/top_level.py b/src/braintrust_api/resources/top_level.py
index c0fc77e5..2215d150 100755
--- a/src/braintrust_api/resources/top_level.py
+++ b/src/braintrust_api/resources/top_level.py
@@ -22,7 +22,7 @@ class TopLevelResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> TopLevelResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -67,7 +67,7 @@ class AsyncTopLevelResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncTopLevelResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/users.py b/src/braintrust_api/resources/users.py
index 87018a4d..8165d73a 100644
--- a/src/braintrust_api/resources/users.py
+++ b/src/braintrust_api/resources/users.py
@@ -28,7 +28,7 @@ class UsersResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> UsersResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -169,7 +169,7 @@ class AsyncUsersResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncUsersResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
diff --git a/src/braintrust_api/resources/views.py b/src/braintrust_api/resources/views.py
index 35718a39..f960d142 100644
--- a/src/braintrust_api/resources/views.py
+++ b/src/braintrust_api/resources/views.py
@@ -17,10 +17,7 @@
view_retrieve_params,
)
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
-from .._utils import (
- maybe_transform,
- async_maybe_transform,
-)
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -32,6 +29,8 @@
from ..pagination import SyncListObjects, AsyncListObjects
from .._base_client import AsyncPaginator, make_request_options
from ..types.shared.view import View
+from ..types.shared.view_type import ViewType
+from ..types.shared.acl_object_type import ACLObjectType
from ..types.shared_params.view_data import ViewData
from ..types.shared_params.view_options import ViewOptions
@@ -42,7 +41,7 @@ class ViewsResource(SyncAPIResource):
@cached_property
def with_raw_response(self) -> ViewsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -63,21 +62,21 @@ def create(
*,
name: str,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
view_type: Optional[
- Literal["projects", "logs", "experiments", "datasets", "prompts", "playgrounds", "experiment", "dataset"]
+ Literal[
+ "projects",
+ "experiments",
+ "experiment",
+ "playgrounds",
+ "playground",
+ "datasets",
+ "dataset",
+ "prompts",
+ "tools",
+ "scorers",
+ "logs",
+ ]
],
deleted_at: Union[str, datetime, None] | NotGiven = NOT_GIVEN,
options: Optional[ViewOptions] | NotGiven = NOT_GIVEN,
@@ -146,19 +145,7 @@ def retrieve(
view_id: str,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -209,25 +196,25 @@ def update(
view_id: str,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
name: Optional[str] | NotGiven = NOT_GIVEN,
options: Optional[ViewOptions] | NotGiven = NOT_GIVEN,
user_id: Optional[str] | NotGiven = NOT_GIVEN,
view_data: Optional[ViewData] | NotGiven = NOT_GIVEN,
view_type: Optional[
- Literal["projects", "logs", "experiments", "datasets", "prompts", "playgrounds", "experiment", "dataset"]
+ Literal[
+ "projects",
+ "experiments",
+ "experiment",
+ "playgrounds",
+ "playground",
+ "datasets",
+ "dataset",
+ "prompts",
+ "tools",
+ "scorers",
+ "logs",
+ ]
]
| NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -294,28 +281,13 @@ def list(
self,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
ending_before: str | NotGiven = NOT_GIVEN,
ids: Union[str, List[str]] | NotGiven = NOT_GIVEN,
limit: Optional[int] | NotGiven = NOT_GIVEN,
starting_after: str | NotGiven = NOT_GIVEN,
view_name: str | NotGiven = NOT_GIVEN,
- view_type: Optional[
- Literal["projects", "logs", "experiments", "datasets", "prompts", "playgrounds", "experiment", "dataset"]
- ]
- | NotGiven = NOT_GIVEN,
+ view_type: Optional[ViewType] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -392,19 +364,7 @@ def delete(
view_id: str,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -452,21 +412,21 @@ def replace(
*,
name: str,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
view_type: Optional[
- Literal["projects", "logs", "experiments", "datasets", "prompts", "playgrounds", "experiment", "dataset"]
+ Literal[
+ "projects",
+ "experiments",
+ "experiment",
+ "playgrounds",
+ "playground",
+ "datasets",
+ "dataset",
+ "prompts",
+ "tools",
+ "scorers",
+ "logs",
+ ]
],
deleted_at: Union[str, datetime, None] | NotGiven = NOT_GIVEN,
options: Optional[ViewOptions] | NotGiven = NOT_GIVEN,
@@ -536,7 +496,7 @@ class AsyncViewsResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncViewsResourceWithRawResponse:
"""
- This property can be used as a prefix for any HTTP method call to return the
+ This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
For more information, see https://www.github.com/braintrustdata/braintrust-api-py#accessing-raw-response-data-eg-headers
@@ -557,21 +517,21 @@ async def create(
*,
name: str,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
view_type: Optional[
- Literal["projects", "logs", "experiments", "datasets", "prompts", "playgrounds", "experiment", "dataset"]
+ Literal[
+ "projects",
+ "experiments",
+ "experiment",
+ "playgrounds",
+ "playground",
+ "datasets",
+ "dataset",
+ "prompts",
+ "tools",
+ "scorers",
+ "logs",
+ ]
],
deleted_at: Union[str, datetime, None] | NotGiven = NOT_GIVEN,
options: Optional[ViewOptions] | NotGiven = NOT_GIVEN,
@@ -640,19 +600,7 @@ async def retrieve(
view_id: str,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -703,25 +651,25 @@ async def update(
view_id: str,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
name: Optional[str] | NotGiven = NOT_GIVEN,
options: Optional[ViewOptions] | NotGiven = NOT_GIVEN,
user_id: Optional[str] | NotGiven = NOT_GIVEN,
view_data: Optional[ViewData] | NotGiven = NOT_GIVEN,
view_type: Optional[
- Literal["projects", "logs", "experiments", "datasets", "prompts", "playgrounds", "experiment", "dataset"]
+ Literal[
+ "projects",
+ "experiments",
+ "experiment",
+ "playgrounds",
+ "playground",
+ "datasets",
+ "dataset",
+ "prompts",
+ "tools",
+ "scorers",
+ "logs",
+ ]
]
| NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -788,28 +736,13 @@ def list(
self,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
ending_before: str | NotGiven = NOT_GIVEN,
ids: Union[str, List[str]] | NotGiven = NOT_GIVEN,
limit: Optional[int] | NotGiven = NOT_GIVEN,
starting_after: str | NotGiven = NOT_GIVEN,
view_name: str | NotGiven = NOT_GIVEN,
- view_type: Optional[
- Literal["projects", "logs", "experiments", "datasets", "prompts", "playgrounds", "experiment", "dataset"]
- ]
- | NotGiven = NOT_GIVEN,
+ view_type: Optional[ViewType] | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -886,19 +819,7 @@ async def delete(
view_id: str,
*,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -946,21 +867,21 @@ async def replace(
*,
name: str,
object_id: str,
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ],
+ object_type: ACLObjectType,
view_type: Optional[
- Literal["projects", "logs", "experiments", "datasets", "prompts", "playgrounds", "experiment", "dataset"]
+ Literal[
+ "projects",
+ "experiments",
+ "experiment",
+ "playgrounds",
+ "playground",
+ "datasets",
+ "dataset",
+ "prompts",
+ "tools",
+ "scorers",
+ "logs",
+ ]
],
deleted_at: Union[str, datetime, None] | NotGiven = NOT_GIVEN,
options: Optional[ViewOptions] | NotGiven = NOT_GIVEN,
diff --git a/src/braintrust_api/types/__init__.py b/src/braintrust_api/types/__init__.py
index e2421c29..25f722ae 100755
--- a/src/braintrust_api/types/__init__.py
+++ b/src/braintrust_api/types/__init__.py
@@ -16,9 +16,12 @@
AISecret as AISecret,
Function as Function,
RepoInfo as RepoInfo,
+ SpanType as SpanType,
ViewData as ViewData,
+ ViewType as ViewType,
CodeBundle as CodeBundle,
Experiment as Experiment,
+ Permission as Permission,
ProjectTag as ProjectTag,
PromptData as PromptData,
SpanIFrame as SpanIFrame,
@@ -28,13 +31,17 @@
Organization as Organization,
ProjectScore as ProjectScore,
ScoreSummary as ScoreSummary,
+ ACLObjectType as ACLObjectType,
MetricSummary as MetricSummary,
PromptOptions as PromptOptions,
SpanAttributes as SpanAttributes,
ViewDataSearch as ViewDataSearch,
ExperimentEvent as ExperimentEvent,
+ ObjectReference as ObjectReference,
ProjectSettings as ProjectSettings,
+ EnvVarObjectType as EnvVarObjectType,
ProjectLogsEvent as ProjectLogsEvent,
+ ProjectScoreType as ProjectScoreType,
OnlineScoreConfig as OnlineScoreConfig,
CreateAPIKeyOutput as CreateAPIKeyOutput,
InsertDatasetEvent as InsertDatasetEvent,
diff --git a/src/braintrust_api/types/acl_batch_update_params.py b/src/braintrust_api/types/acl_batch_update_params.py
index 80a552f6..31810440 100644
--- a/src/braintrust_api/types/acl_batch_update_params.py
+++ b/src/braintrust_api/types/acl_batch_update_params.py
@@ -3,7 +3,10 @@
from __future__ import annotations
from typing import Iterable, Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Required, TypedDict
+
+from .shared.permission import Permission
+from .shared.acl_object_type import ACLObjectType
__all__ = ["ACLBatchUpdateParams", "AddACL", "RemoveACL"]
@@ -42,21 +45,7 @@ class AddACL(TypedDict, total=False):
object_id: Required[str]
"""The id of the object the ACL applies to"""
- object_type: Required[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ object_type: Required[ACLObjectType]
"""The object type that the ACL applies to"""
group_id: Optional[str]
@@ -65,29 +54,13 @@ class AddACL(TypedDict, total=False):
Exactly one of `user_id` and `group_id` will be provided
"""
- permission: Optional[
- Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
- ]
+ permission: Optional[Permission]
"""Permission the ACL grants.
Exactly one of `permission` and `role_id` will be provided
"""
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ restrict_object_type: Optional[ACLObjectType]
"""
When setting a permission directly, optionally restricts the permission grant to
just the specified object type. Cannot be set alongside a `role_id`.
@@ -110,21 +83,7 @@ class RemoveACL(TypedDict, total=False):
object_id: Required[str]
"""The id of the object the ACL applies to"""
- object_type: Required[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ object_type: Required[ACLObjectType]
"""The object type that the ACL applies to"""
group_id: Optional[str]
@@ -133,29 +92,13 @@ class RemoveACL(TypedDict, total=False):
Exactly one of `user_id` and `group_id` will be provided
"""
- permission: Optional[
- Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
- ]
+ permission: Optional[Permission]
"""Permission the ACL grants.
Exactly one of `permission` and `role_id` will be provided
"""
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ restrict_object_type: Optional[ACLObjectType]
"""
When setting a permission directly, optionally restricts the permission grant to
just the specified object type. Cannot be set alongside a `role_id`.
diff --git a/src/braintrust_api/types/acl_create_params.py b/src/braintrust_api/types/acl_create_params.py
index 6b089072..9f46d447 100755
--- a/src/braintrust_api/types/acl_create_params.py
+++ b/src/braintrust_api/types/acl_create_params.py
@@ -3,7 +3,10 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Required, TypedDict
+
+from .shared.permission import Permission
+from .shared.acl_object_type import ACLObjectType
__all__ = ["ACLCreateParams"]
@@ -12,21 +15,7 @@ class ACLCreateParams(TypedDict, total=False):
object_id: Required[str]
"""The id of the object the ACL applies to"""
- object_type: Required[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ object_type: Required[ACLObjectType]
"""The object type that the ACL applies to"""
group_id: Optional[str]
@@ -35,29 +24,13 @@ class ACLCreateParams(TypedDict, total=False):
Exactly one of `user_id` and `group_id` will be provided
"""
- permission: Optional[
- Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
- ]
+ permission: Optional[Permission]
"""Permission the ACL grants.
Exactly one of `permission` and `role_id` will be provided
"""
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ restrict_object_type: Optional[ACLObjectType]
"""
When setting a permission directly, optionally restricts the permission grant to
just the specified object type. Cannot be set alongside a `role_id`.
diff --git a/src/braintrust_api/types/acl_find_and_delete_params.py b/src/braintrust_api/types/acl_find_and_delete_params.py
index f751880f..a8d092dc 100644
--- a/src/braintrust_api/types/acl_find_and_delete_params.py
+++ b/src/braintrust_api/types/acl_find_and_delete_params.py
@@ -3,7 +3,10 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Required, TypedDict
+
+from .shared.permission import Permission
+from .shared.acl_object_type import ACLObjectType
__all__ = ["ACLFindAndDeleteParams"]
@@ -12,21 +15,7 @@ class ACLFindAndDeleteParams(TypedDict, total=False):
object_id: Required[str]
"""The id of the object the ACL applies to"""
- object_type: Required[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ object_type: Required[ACLObjectType]
"""The object type that the ACL applies to"""
group_id: Optional[str]
@@ -35,29 +24,13 @@ class ACLFindAndDeleteParams(TypedDict, total=False):
Exactly one of `user_id` and `group_id` will be provided
"""
- permission: Optional[
- Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
- ]
+ permission: Optional[Permission]
"""Permission the ACL grants.
Exactly one of `permission` and `role_id` will be provided
"""
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ restrict_object_type: Optional[ACLObjectType]
"""
When setting a permission directly, optionally restricts the permission grant to
just the specified object type. Cannot be set alongside a `role_id`.
diff --git a/src/braintrust_api/types/acl_list_params.py b/src/braintrust_api/types/acl_list_params.py
index 74c365a0..4c3bacd0 100755
--- a/src/braintrust_api/types/acl_list_params.py
+++ b/src/braintrust_api/types/acl_list_params.py
@@ -3,7 +3,9 @@
from __future__ import annotations
from typing import List, Union, Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Required, TypedDict
+
+from .shared.acl_object_type import ACLObjectType
__all__ = ["ACLListParams"]
@@ -12,21 +14,7 @@ class ACLListParams(TypedDict, total=False):
object_id: Required[str]
"""The id of the object the ACL applies to"""
- object_type: Required[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ object_type: Required[ACLObjectType]
"""The object type that the ACL applies to"""
ending_before: str
diff --git a/src/braintrust_api/types/env_var_list_params.py b/src/braintrust_api/types/env_var_list_params.py
index 4924c7bc..8826c7d7 100644
--- a/src/braintrust_api/types/env_var_list_params.py
+++ b/src/braintrust_api/types/env_var_list_params.py
@@ -3,7 +3,9 @@
from __future__ import annotations
from typing import List, Union, Optional
-from typing_extensions import Literal, TypedDict
+from typing_extensions import TypedDict
+
+from .shared.env_var_object_type import EnvVarObjectType
__all__ = ["EnvVarListParams"]
@@ -24,5 +26,5 @@ class EnvVarListParams(TypedDict, total=False):
object_id: str
"""The id of the object the environment variable is scoped for"""
- object_type: Literal["organization", "project", "function"]
+ object_type: EnvVarObjectType
"""The type of the object the environment variable is scoped for"""
diff --git a/src/braintrust_api/types/eval_create_params.py b/src/braintrust_api/types/eval_create_params.py
index aec9c8a7..6b0275bc 100644
--- a/src/braintrust_api/types/eval_create_params.py
+++ b/src/braintrust_api/types/eval_create_params.py
@@ -14,6 +14,7 @@
"Data",
"DataDatasetID",
"DataProjectDatasetName",
+ "DataDatasetRows",
"Score",
"ScoreFunctionID",
"ScoreProjectSlug",
@@ -31,6 +32,9 @@
"TaskInlineCodeInlineContext",
"TaskInlinePrompt",
"GitMetadataSettings",
+ "Parent",
+ "ParentSpanParentStruct",
+ "ParentSpanParentStructRowIDs",
]
@@ -89,6 +93,9 @@ class EvalCreateParams(TypedDict, total=False):
You can later use this to slice & dice across experiments.
"""
+ parent: Parent
+ """Options for tracing the evaluation"""
+
repo_info: Optional[RepoInfo]
"""Metadata about the state of the repo when the experiment was created"""
@@ -118,14 +125,22 @@ class EvalCreateParams(TypedDict, total=False):
class DataDatasetID(TypedDict, total=False):
dataset_id: Required[str]
+ _internal_btql: Optional[Dict[str, Optional[object]]]
+
class DataProjectDatasetName(TypedDict, total=False):
dataset_name: Required[str]
project_name: Required[str]
+ _internal_btql: Optional[Dict[str, Optional[object]]]
+
+
+class DataDatasetRows(TypedDict, total=False):
+ data: Required[Iterable[Optional[object]]]
-Data: TypeAlias = Union[DataDatasetID, DataProjectDatasetName]
+
+Data: TypeAlias = Union[DataDatasetID, DataProjectDatasetName, DataDatasetRows]
class ScoreFunctionID(TypedDict, total=False):
@@ -278,3 +293,30 @@ class GitMetadataSettings(TypedDict, total=False):
"git_diff",
]
]
+
+
+class ParentSpanParentStructRowIDs(TypedDict, total=False):
+ id: Required[str]
+ """The id of the row"""
+
+ root_span_id: Required[str]
+ """The root_span_id of the row"""
+
+ span_id: Required[str]
+ """The span_id of the row"""
+
+
+class ParentSpanParentStruct(TypedDict, total=False):
+ object_id: Required[str]
+ """The id of the container object you are logging to"""
+
+ object_type: Required[Literal["project_logs", "experiment", "playground_logs"]]
+
+ propagated_event: Optional[Dict[str, Optional[object]]]
+ """Include these properties in every span created under this parent"""
+
+ row_ids: Optional[ParentSpanParentStructRowIDs]
+ """Identifiers for the row to to log a subspan under"""
+
+
+Parent: TypeAlias = Union[ParentSpanParentStruct, str]
diff --git a/src/braintrust_api/types/function_create_params.py b/src/braintrust_api/types/function_create_params.py
index 0547166c..339fc4de 100755
--- a/src/braintrust_api/types/function_create_params.py
+++ b/src/braintrust_api/types/function_create_params.py
@@ -5,7 +5,8 @@
from typing import List, Union, Optional
from typing_extensions import Literal, Required, TypeAlias, TypedDict
-from ..types.shared import CodeBundle
+from .shared.acl_object_type import ACLObjectType
+from .shared_params.code_bundle import CodeBundle
from .shared_params.prompt_data import PromptData
__all__ = [
@@ -14,6 +15,7 @@
"FunctionDataPrompt",
"FunctionDataCode",
"FunctionDataCodeData",
+ "FunctionDataCodeDataBundle",
"FunctionDataCodeDataInline",
"FunctionDataCodeDataInlineRuntimeContext",
"FunctionDataGlobal",
@@ -55,6 +57,10 @@ class FunctionDataPrompt(TypedDict, total=False):
type: Required[Literal["prompt"]]
+class FunctionDataCodeDataBundle(CodeBundle, total=False):
+ type: Required[Literal["bundle"]]
+
+
class FunctionDataCodeDataInlineRuntimeContext(TypedDict, total=False):
runtime: Required[Literal["node", "python"]]
@@ -69,7 +75,7 @@ class FunctionDataCodeDataInline(TypedDict, total=False):
type: Required[Literal["inline"]]
-FunctionDataCodeData: TypeAlias = Union[CodeBundle, FunctionDataCodeDataInline]
+FunctionDataCodeData: TypeAlias = Union[FunctionDataCodeDataBundle, FunctionDataCodeDataInline]
class FunctionDataCode(TypedDict, total=False):
@@ -88,30 +94,16 @@ class FunctionDataGlobal(TypedDict, total=False):
class FunctionSchema(TypedDict, total=False):
- parameters: Optional[object]
+ parameters: object
- returns: Optional[object]
+ returns: object
class Origin(TypedDict, total=False):
object_id: Required[str]
"""Id of the object the function is originating from"""
- object_type: Required[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ object_type: Required[ACLObjectType]
"""The object type that the ACL applies to"""
internal: Optional[bool]
diff --git a/src/braintrust_api/types/function_invoke_params.py b/src/braintrust_api/types/function_invoke_params.py
index 443a4784..2906108e 100644
--- a/src/braintrust_api/types/function_invoke_params.py
+++ b/src/braintrust_api/types/function_invoke_params.py
@@ -27,12 +27,18 @@
class FunctionInvokeParams(TypedDict, total=False):
- input: Optional[object]
+ expected: object
+ """The expected output of the function"""
+
+ input: object
"""Argument to the function, which can be any JSON serializable value"""
messages: Iterable[Message]
"""If the function is an LLM, additional messages to pass along to it"""
+ metadata: Optional[Dict[str, Optional[object]]]
+ """Any relevant metadata"""
+
mode: Optional[Literal["auto", "parallel"]]
"""The mode format of the returned value (defaults to 'auto')"""
@@ -126,7 +132,7 @@ class ParentSpanParentStruct(TypedDict, total=False):
object_id: Required[str]
"""The id of the container object you are logging to"""
- object_type: Required[Literal["project_logs", "experiment"]]
+ object_type: Required[Literal["project_logs", "experiment", "playground_logs"]]
propagated_event: Optional[Dict[str, Optional[object]]]
"""Include these properties in every span created under this parent"""
diff --git a/src/braintrust_api/types/function_replace_params.py b/src/braintrust_api/types/function_replace_params.py
index 647bb35e..d52bfa42 100755
--- a/src/braintrust_api/types/function_replace_params.py
+++ b/src/braintrust_api/types/function_replace_params.py
@@ -5,7 +5,8 @@
from typing import List, Union, Optional
from typing_extensions import Literal, Required, TypeAlias, TypedDict
-from ..types.shared import CodeBundle
+from .shared.acl_object_type import ACLObjectType
+from .shared_params.code_bundle import CodeBundle
from .shared_params.prompt_data import PromptData
__all__ = [
@@ -14,6 +15,7 @@
"FunctionDataPrompt",
"FunctionDataCode",
"FunctionDataCodeData",
+ "FunctionDataCodeDataBundle",
"FunctionDataCodeDataInline",
"FunctionDataCodeDataInlineRuntimeContext",
"FunctionDataGlobal",
@@ -55,6 +57,10 @@ class FunctionDataPrompt(TypedDict, total=False):
type: Required[Literal["prompt"]]
+class FunctionDataCodeDataBundle(CodeBundle, total=False):
+ type: Required[Literal["bundle"]]
+
+
class FunctionDataCodeDataInlineRuntimeContext(TypedDict, total=False):
runtime: Required[Literal["node", "python"]]
@@ -69,7 +75,7 @@ class FunctionDataCodeDataInline(TypedDict, total=False):
type: Required[Literal["inline"]]
-FunctionDataCodeData: TypeAlias = Union[CodeBundle, FunctionDataCodeDataInline]
+FunctionDataCodeData: TypeAlias = Union[FunctionDataCodeDataBundle, FunctionDataCodeDataInline]
class FunctionDataCode(TypedDict, total=False):
@@ -88,30 +94,16 @@ class FunctionDataGlobal(TypedDict, total=False):
class FunctionSchema(TypedDict, total=False):
- parameters: Optional[object]
+ parameters: object
- returns: Optional[object]
+ returns: object
class Origin(TypedDict, total=False):
object_id: Required[str]
"""Id of the object the function is originating from"""
- object_type: Required[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ object_type: Required[ACLObjectType]
"""The object type that the ACL applies to"""
internal: Optional[bool]
diff --git a/src/braintrust_api/types/function_update_params.py b/src/braintrust_api/types/function_update_params.py
index 9ff8001a..fd5e26c3 100755
--- a/src/braintrust_api/types/function_update_params.py
+++ b/src/braintrust_api/types/function_update_params.py
@@ -5,7 +5,7 @@
from typing import List, Union, Optional
from typing_extensions import Literal, Required, TypeAlias, TypedDict
-from ..types.shared import CodeBundle
+from .shared_params.code_bundle import CodeBundle
from .shared_params.prompt_data import PromptData
__all__ = [
@@ -14,10 +14,10 @@
"FunctionDataPrompt",
"FunctionDataCode",
"FunctionDataCodeData",
+ "FunctionDataCodeDataBundle",
"FunctionDataCodeDataInline",
"FunctionDataCodeDataInlineRuntimeContext",
"FunctionDataGlobal",
- "FunctionDataNullableVariant",
]
@@ -25,7 +25,7 @@ class FunctionUpdateParams(TypedDict, total=False):
description: Optional[str]
"""Textual description of the prompt"""
- function_data: FunctionData
+ function_data: Optional[FunctionData]
name: Optional[str]
"""Name of the prompt"""
@@ -41,6 +41,10 @@ class FunctionDataPrompt(TypedDict, total=False):
type: Required[Literal["prompt"]]
+class FunctionDataCodeDataBundle(CodeBundle, total=False):
+ type: Required[Literal["bundle"]]
+
+
class FunctionDataCodeDataInlineRuntimeContext(TypedDict, total=False):
runtime: Required[Literal["node", "python"]]
@@ -55,7 +59,7 @@ class FunctionDataCodeDataInline(TypedDict, total=False):
type: Required[Literal["inline"]]
-FunctionDataCodeData: TypeAlias = Union[CodeBundle, FunctionDataCodeDataInline]
+FunctionDataCodeData: TypeAlias = Union[FunctionDataCodeDataBundle, FunctionDataCodeDataInline]
class FunctionDataCode(TypedDict, total=False):
@@ -70,10 +74,4 @@ class FunctionDataGlobal(TypedDict, total=False):
type: Required[Literal["global"]]
-class FunctionDataNullableVariant(TypedDict, total=False):
- pass
-
-
-FunctionData: TypeAlias = Union[
- FunctionDataPrompt, FunctionDataCode, FunctionDataGlobal, Optional[FunctionDataNullableVariant]
-]
+FunctionData: TypeAlias = Union[FunctionDataPrompt, FunctionDataCode, FunctionDataGlobal]
diff --git a/src/braintrust_api/types/project_score_create_params.py b/src/braintrust_api/types/project_score_create_params.py
index c2342cca..2337d2c2 100755
--- a/src/braintrust_api/types/project_score_create_params.py
+++ b/src/braintrust_api/types/project_score_create_params.py
@@ -3,12 +3,13 @@
from __future__ import annotations
from typing import Dict, List, Union, Iterable, Optional
-from typing_extensions import Literal, Required, TypeAlias, TypedDict
+from typing_extensions import Required, TypedDict
+from .shared.project_score_type import ProjectScoreType
from .shared_params.project_score_config import ProjectScoreConfig
from .shared_params.project_score_category import ProjectScoreCategory
-__all__ = ["ProjectScoreCreateParams", "Categories", "CategoriesNullableVariant"]
+__all__ = ["ProjectScoreCreateParams"]
class ProjectScoreCreateParams(TypedDict, total=False):
@@ -18,22 +19,13 @@ class ProjectScoreCreateParams(TypedDict, total=False):
project_id: Required[str]
"""Unique identifier for the project that the project score belongs under"""
- score_type: Required[Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"]]
+ score_type: Required[ProjectScoreType]
"""The type of the configured score"""
- categories: Categories
+ categories: Union[Iterable[ProjectScoreCategory], Dict[str, float], List[str], None]
"""For categorical-type project scores, the list of all categories"""
config: Optional[ProjectScoreConfig]
description: Optional[str]
"""Textual description of the project score"""
-
-
-class CategoriesNullableVariant(TypedDict, total=False):
- pass
-
-
-Categories: TypeAlias = Union[
- Iterable[ProjectScoreCategory], Dict[str, float], List[str], Optional[CategoriesNullableVariant]
-]
diff --git a/src/braintrust_api/types/project_score_list_params.py b/src/braintrust_api/types/project_score_list_params.py
index 55fcdc68..c9871b94 100755
--- a/src/braintrust_api/types/project_score_list_params.py
+++ b/src/braintrust_api/types/project_score_list_params.py
@@ -3,7 +3,9 @@
from __future__ import annotations
from typing import List, Union, Optional
-from typing_extensions import Literal, TypedDict
+from typing_extensions import TypedDict
+
+from .shared.project_score_type import ProjectScoreType
__all__ = ["ProjectScoreListParams"]
@@ -38,10 +40,7 @@ class ProjectScoreListParams(TypedDict, total=False):
project_score_name: str
"""Name of the project_score to search for"""
- score_type: Union[
- Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"],
- List[Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"]],
- ]
+ score_type: Union[ProjectScoreType, List[ProjectScoreType]]
"""The type of the configured score"""
starting_after: str
diff --git a/src/braintrust_api/types/project_score_replace_params.py b/src/braintrust_api/types/project_score_replace_params.py
index d9176115..c0c0a8ae 100755
--- a/src/braintrust_api/types/project_score_replace_params.py
+++ b/src/braintrust_api/types/project_score_replace_params.py
@@ -3,12 +3,13 @@
from __future__ import annotations
from typing import Dict, List, Union, Iterable, Optional
-from typing_extensions import Literal, Required, TypeAlias, TypedDict
+from typing_extensions import Required, TypedDict
+from .shared.project_score_type import ProjectScoreType
from .shared_params.project_score_config import ProjectScoreConfig
from .shared_params.project_score_category import ProjectScoreCategory
-__all__ = ["ProjectScoreReplaceParams", "Categories", "CategoriesNullableVariant"]
+__all__ = ["ProjectScoreReplaceParams"]
class ProjectScoreReplaceParams(TypedDict, total=False):
@@ -18,22 +19,13 @@ class ProjectScoreReplaceParams(TypedDict, total=False):
project_id: Required[str]
"""Unique identifier for the project that the project score belongs under"""
- score_type: Required[Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"]]
+ score_type: Required[ProjectScoreType]
"""The type of the configured score"""
- categories: Categories
+ categories: Union[Iterable[ProjectScoreCategory], Dict[str, float], List[str], None]
"""For categorical-type project scores, the list of all categories"""
config: Optional[ProjectScoreConfig]
description: Optional[str]
"""Textual description of the project score"""
-
-
-class CategoriesNullableVariant(TypedDict, total=False):
- pass
-
-
-Categories: TypeAlias = Union[
- Iterable[ProjectScoreCategory], Dict[str, float], List[str], Optional[CategoriesNullableVariant]
-]
diff --git a/src/braintrust_api/types/project_score_update_params.py b/src/braintrust_api/types/project_score_update_params.py
index e5cdcf11..69325908 100755
--- a/src/braintrust_api/types/project_score_update_params.py
+++ b/src/braintrust_api/types/project_score_update_params.py
@@ -3,16 +3,17 @@
from __future__ import annotations
from typing import Dict, List, Union, Iterable, Optional
-from typing_extensions import Literal, TypeAlias, TypedDict
+from typing_extensions import TypedDict
+from .shared.project_score_type import ProjectScoreType
from .shared_params.project_score_config import ProjectScoreConfig
from .shared_params.project_score_category import ProjectScoreCategory
-__all__ = ["ProjectScoreUpdateParams", "Categories", "CategoriesNullableVariant"]
+__all__ = ["ProjectScoreUpdateParams"]
class ProjectScoreUpdateParams(TypedDict, total=False):
- categories: Categories
+ categories: Union[Iterable[ProjectScoreCategory], Dict[str, float], List[str], None]
"""For categorical-type project scores, the list of all categories"""
config: Optional[ProjectScoreConfig]
@@ -23,14 +24,5 @@ class ProjectScoreUpdateParams(TypedDict, total=False):
name: Optional[str]
"""Name of the project score"""
- score_type: Optional[Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"]]
+ score_type: Optional[ProjectScoreType]
"""The type of the configured score"""
-
-
-class CategoriesNullableVariant(TypedDict, total=False):
- pass
-
-
-Categories: TypeAlias = Union[
- Iterable[ProjectScoreCategory], Dict[str, float], List[str], Optional[CategoriesNullableVariant]
-]
diff --git a/src/braintrust_api/types/role_create_params.py b/src/braintrust_api/types/role_create_params.py
index 8e472058..8b1f7c98 100755
--- a/src/braintrust_api/types/role_create_params.py
+++ b/src/braintrust_api/types/role_create_params.py
@@ -3,7 +3,10 @@
from __future__ import annotations
from typing import List, Iterable, Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Required, TypedDict
+
+from .shared.permission import Permission
+from .shared.acl_object_type import ACLObjectType
__all__ = ["RoleCreateParams", "MemberPermission"]
@@ -34,28 +37,12 @@ class RoleCreateParams(TypedDict, total=False):
class MemberPermission(TypedDict, total=False):
- permission: Required[
- Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
- ]
+ permission: Required[Permission]
"""Each permission permits a certain type of operation on an object in the system
Permissions can be assigned to to objects on an individual basis, or grouped
into roles
"""
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ restrict_object_type: Optional[ACLObjectType]
"""The object type that the ACL applies to"""
diff --git a/src/braintrust_api/types/role_replace_params.py b/src/braintrust_api/types/role_replace_params.py
index 8113bcad..26d16e27 100755
--- a/src/braintrust_api/types/role_replace_params.py
+++ b/src/braintrust_api/types/role_replace_params.py
@@ -3,7 +3,10 @@
from __future__ import annotations
from typing import List, Iterable, Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Required, TypedDict
+
+from .shared.permission import Permission
+from .shared.acl_object_type import ACLObjectType
__all__ = ["RoleReplaceParams", "MemberPermission"]
@@ -34,28 +37,12 @@ class RoleReplaceParams(TypedDict, total=False):
class MemberPermission(TypedDict, total=False):
- permission: Required[
- Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
- ]
+ permission: Required[Permission]
"""Each permission permits a certain type of operation on an object in the system
Permissions can be assigned to to objects on an individual basis, or grouped
into roles
"""
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ restrict_object_type: Optional[ACLObjectType]
"""The object type that the ACL applies to"""
diff --git a/src/braintrust_api/types/role_update_params.py b/src/braintrust_api/types/role_update_params.py
index 7705eccf..30841be3 100755
--- a/src/braintrust_api/types/role_update_params.py
+++ b/src/braintrust_api/types/role_update_params.py
@@ -3,7 +3,10 @@
from __future__ import annotations
from typing import List, Iterable, Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Required, TypedDict
+
+from .shared.permission import Permission
+from .shared.acl_object_type import ACLObjectType
__all__ = ["RoleUpdateParams", "AddMemberPermission", "RemoveMemberPermission"]
@@ -29,56 +32,24 @@ class RoleUpdateParams(TypedDict, total=False):
class AddMemberPermission(TypedDict, total=False):
- permission: Required[
- Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
- ]
+ permission: Required[Permission]
"""Each permission permits a certain type of operation on an object in the system
Permissions can be assigned to to objects on an individual basis, or grouped
into roles
"""
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ restrict_object_type: Optional[ACLObjectType]
"""The object type that the ACL applies to"""
class RemoveMemberPermission(TypedDict, total=False):
- permission: Required[
- Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
- ]
+ permission: Required[Permission]
"""Each permission permits a certain type of operation on an object in the system
Permissions can be assigned to to objects on an individual basis, or grouped
into roles
"""
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ restrict_object_type: Optional[ACLObjectType]
"""The object type that the ACL applies to"""
diff --git a/src/braintrust_api/types/shared/__init__.py b/src/braintrust_api/types/shared/__init__.py
index 39dda8de..38344496 100755
--- a/src/braintrust_api/types/shared/__init__.py
+++ b/src/braintrust_api/types/shared/__init__.py
@@ -12,9 +12,12 @@
from .project import Project as Project
from .function import Function as Function
from .repo_info import RepoInfo as RepoInfo
+from .span_type import SpanType as SpanType
from .view_data import ViewData as ViewData
+from .view_type import ViewType as ViewType
from .a_i_secret import AISecret as AISecret
from .experiment import Experiment as Experiment
+from .permission import Permission as Permission
from .code_bundle import CodeBundle as CodeBundle
from .project_tag import ProjectTag as ProjectTag
from .prompt_data import PromptData as PromptData
@@ -27,11 +30,15 @@
from .score_summary import ScoreSummary as ScoreSummary
from .metric_summary import MetricSummary as MetricSummary
from .prompt_options import PromptOptions as PromptOptions
+from .acl_object_type import ACLObjectType as ACLObjectType
from .span_attributes import SpanAttributes as SpanAttributes
from .experiment_event import ExperimentEvent as ExperimentEvent
+from .object_reference import ObjectReference as ObjectReference
from .project_settings import ProjectSettings as ProjectSettings
from .view_data_search import ViewDataSearch as ViewDataSearch
from .project_logs_event import ProjectLogsEvent as ProjectLogsEvent
+from .project_score_type import ProjectScoreType as ProjectScoreType
+from .env_var_object_type import EnvVarObjectType as EnvVarObjectType
from .online_score_config import OnlineScoreConfig as OnlineScoreConfig
from .insert_dataset_event import InsertDatasetEvent as InsertDatasetEvent
from .project_score_config import ProjectScoreConfig as ProjectScoreConfig
diff --git a/src/braintrust_api/types/shared/a_i_secret.py b/src/braintrust_api/types/shared/a_i_secret.py
index 24706df9..3ddb45db 100644
--- a/src/braintrust_api/types/shared/a_i_secret.py
+++ b/src/braintrust_api/types/shared/a_i_secret.py
@@ -26,3 +26,6 @@ class AISecret(BaseModel):
preview_secret: Optional[str] = None
type: Optional[str] = None
+
+ updated_at: Optional[datetime] = None
+ """Date of last AI secret update"""
diff --git a/src/braintrust_api/types/shared/acl.py b/src/braintrust_api/types/shared/acl.py
index 8a8262e5..1d7f961e 100755
--- a/src/braintrust_api/types/shared/acl.py
+++ b/src/braintrust_api/types/shared/acl.py
@@ -2,11 +2,12 @@
from typing import Optional
from datetime import datetime
-from typing_extensions import Literal
from pydantic import Field as FieldInfo
from ..._models import BaseModel
+from .permission import Permission
+from .acl_object_type import ACLObjectType
__all__ = ["ACL"]
@@ -21,19 +22,7 @@ class ACL(BaseModel):
object_id: str
"""The id of the object the ACL applies to"""
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
+ object_type: ACLObjectType
"""The object type that the ACL applies to"""
created: Optional[datetime] = None
@@ -45,29 +34,13 @@ class ACL(BaseModel):
Exactly one of `user_id` and `group_id` will be provided
"""
- permission: Optional[
- Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
- ] = None
+ permission: Optional[Permission] = None
"""Permission the ACL grants.
Exactly one of `permission` and `role_id` will be provided
"""
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ] = None
+ restrict_object_type: Optional[ACLObjectType] = None
"""
When setting a permission directly, optionally restricts the permission grant to
just the specified object type. Cannot be set alongside a `role_id`.
diff --git a/src/braintrust_api/types/shared/acl_object_type.py b/src/braintrust_api/types/shared/acl_object_type.py
new file mode 100644
index 00000000..a2e5dafc
--- /dev/null
+++ b/src/braintrust_api/types/shared/acl_object_type.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["ACLObjectType"]
+
+ACLObjectType: TypeAlias = Literal[
+ "organization",
+ "project",
+ "experiment",
+ "dataset",
+ "prompt",
+ "prompt_session",
+ "group",
+ "role",
+ "org_member",
+ "project_log",
+ "org_project",
+]
diff --git a/src/braintrust_api/types/shared/data_summary.py b/src/braintrust_api/types/shared/data_summary.py
index 7f3ba7bc..20444ddb 100755
--- a/src/braintrust_api/types/shared/data_summary.py
+++ b/src/braintrust_api/types/shared/data_summary.py
@@ -1,6 +1,5 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
from ..._models import BaseModel
__all__ = ["DataSummary"]
diff --git a/src/braintrust_api/types/shared/dataset_event.py b/src/braintrust_api/types/shared/dataset_event.py
index a7d10684..85712caa 100755
--- a/src/braintrust_api/types/shared/dataset_event.py
+++ b/src/braintrust_api/types/shared/dataset_event.py
@@ -1,28 +1,25 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Dict, List, Optional
+from typing import TYPE_CHECKING, List, Optional
from datetime import datetime
-from typing_extensions import Literal
from pydantic import Field as FieldInfo
from ..._models import BaseModel
+from .object_reference import ObjectReference
-__all__ = ["DatasetEvent", "Origin"]
+__all__ = ["DatasetEvent", "Metadata"]
-class Origin(BaseModel):
- id: str
- """ID of the original event."""
-
- xact_id: str = FieldInfo(alias="_xact_id")
- """Transaction ID of the original event."""
-
- object_id: str
- """ID of the object the event is originating from."""
+class Metadata(BaseModel):
+ model: Optional[str] = None
+ """The model used for this example"""
- object_type: Literal["experiment", "dataset", "prompt", "function", "prompt_session", "project_logs"]
- """Type of the object the event is originating from."""
+ if TYPE_CHECKING:
+ # Stub to indicate that arbitrary properties are accepted.
+ # To access properties that are not valid identifiers you can use `getattr`, e.g.
+ # `getattr(obj, '$type')`
+ def __getattr__(self, attr: str) -> Optional[object]: ...
class DatasetEvent(BaseModel):
@@ -75,7 +72,7 @@ class DatasetEvent(BaseModel):
is_root: Optional[bool] = None
"""Whether this span is a root span"""
- metadata: Optional[Dict[str, Optional[object]]] = None
+ metadata: Optional[Metadata] = None
"""
A dictionary with additional data about the test example, model outputs, or just
about anything else that's relevant, that you can use to help find and analyze
@@ -84,7 +81,7 @@ class DatasetEvent(BaseModel):
can be any JSON-serializable type, but its keys must be strings
"""
- origin: Optional[Origin] = None
+ origin: Optional[ObjectReference] = None
"""Indicates the event was copied from another object."""
tags: Optional[List[str]] = None
diff --git a/src/braintrust_api/types/shared/env_var_object_type.py b/src/braintrust_api/types/shared/env_var_object_type.py
new file mode 100644
index 00000000..24ea83dc
--- /dev/null
+++ b/src/braintrust_api/types/shared/env_var_object_type.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["EnvVarObjectType"]
+
+EnvVarObjectType: TypeAlias = Literal["organization", "project", "function"]
diff --git a/src/braintrust_api/types/shared/experiment_event.py b/src/braintrust_api/types/shared/experiment_event.py
index aa35a51f..00c7511f 100755
--- a/src/braintrust_api/types/shared/experiment_event.py
+++ b/src/braintrust_api/types/shared/experiment_event.py
@@ -2,14 +2,14 @@
from typing import TYPE_CHECKING, Dict, List, Optional
from datetime import datetime
-from typing_extensions import Literal
from pydantic import Field as FieldInfo
from ..._models import BaseModel
from .span_attributes import SpanAttributes
+from .object_reference import ObjectReference
-__all__ = ["ExperimentEvent", "Context", "Metrics", "Origin"]
+__all__ = ["ExperimentEvent", "Context", "Metadata", "Metrics"]
class Context(BaseModel):
@@ -29,6 +29,17 @@ class Context(BaseModel):
def __getattr__(self, attr: str) -> Optional[object]: ...
+class Metadata(BaseModel):
+ model: Optional[str] = None
+ """The model used for this example"""
+
+ if TYPE_CHECKING:
+ # Stub to indicate that arbitrary properties are accepted.
+ # To access properties that are not valid identifiers you can use `getattr`, e.g.
+ # `getattr(obj, '$type')`
+ def __getattr__(self, attr: str) -> Optional[object]: ...
+
+
class Metrics(BaseModel):
caller_filename: Optional[object] = None
"""This metric is deprecated"""
@@ -73,20 +84,6 @@ class Metrics(BaseModel):
def __getattr__(self, attr: str) -> float: ...
-class Origin(BaseModel):
- id: str
- """ID of the original event."""
-
- xact_id: str = FieldInfo(alias="_xact_id")
- """Transaction ID of the original event."""
-
- object_id: str
- """ID of the object the event is originating from."""
-
- object_type: Literal["experiment", "dataset", "prompt", "function", "prompt_session", "project_logs"]
- """Type of the object the event is originating from."""
-
-
class ExperimentEvent(BaseModel):
id: str
"""A unique identifier for the experiment event.
@@ -130,12 +127,6 @@ class ExperimentEvent(BaseModel):
experiment event
"""
- dataset_record_id: Optional[str] = None
- """
- If the experiment is associated to a dataset, this is the event-level dataset id
- this experiment event is tied to
- """
-
error: Optional[object] = None
"""The error that occurred, if any."""
@@ -162,7 +153,7 @@ class ExperimentEvent(BaseModel):
is_root: Optional[bool] = None
"""Whether this span is a root span"""
- metadata: Optional[Dict[str, Optional[object]]] = None
+ metadata: Optional[Metadata] = None
"""
A dictionary with additional data about the test example, model outputs, or just
about anything else that's relevant, that you can use to help find and analyze
@@ -178,7 +169,7 @@ class ExperimentEvent(BaseModel):
which the experiment event was produced
"""
- origin: Optional[Origin] = None
+ origin: Optional[ObjectReference] = None
"""Indicates the event was copied from another object."""
output: Optional[object] = None
diff --git a/src/braintrust_api/types/shared/function.py b/src/braintrust_api/types/shared/function.py
index 6d7a1dbc..70ef9bf9 100755
--- a/src/braintrust_api/types/shared/function.py
+++ b/src/braintrust_api/types/shared/function.py
@@ -9,6 +9,7 @@
from ..._models import BaseModel
from .code_bundle import CodeBundle
from .prompt_data import PromptData
+from .acl_object_type import ACLObjectType
__all__ = [
"Function",
@@ -75,19 +76,7 @@ class Origin(BaseModel):
object_id: str
"""Id of the object the function is originating from"""
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
+ object_type: ACLObjectType
"""The object type that the ACL applies to"""
internal: Optional[bool] = None
diff --git a/src/braintrust_api/types/shared/insert_dataset_event.py b/src/braintrust_api/types/shared/insert_dataset_event.py
index bdbc8058..fffb9cc4 100644
--- a/src/braintrust_api/types/shared/insert_dataset_event.py
+++ b/src/braintrust_api/types/shared/insert_dataset_event.py
@@ -1,13 +1,25 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Dict, List, Optional
+from typing import TYPE_CHECKING, List, Optional
from datetime import datetime
from pydantic import Field as FieldInfo
from ..._models import BaseModel
+from .object_reference import ObjectReference
-__all__ = ["InsertDatasetEvent"]
+__all__ = ["InsertDatasetEvent", "Metadata"]
+
+
+class Metadata(BaseModel):
+ model: Optional[str] = None
+ """The model used for this example"""
+
+ if TYPE_CHECKING:
+ # Stub to indicate that arbitrary properties are accepted.
+ # To access properties that are not valid identifiers you can use `getattr`, e.g.
+ # `getattr(obj, '$type')`
+ def __getattr__(self, attr: str) -> Optional[object]: ...
class InsertDatasetEvent(BaseModel):
@@ -57,8 +69,12 @@ class InsertDatasetEvent(BaseModel):
"""
parent_id: Optional[str] = FieldInfo(alias="_parent_id", default=None)
- """Use the `_parent_id` field to create this row as a subspan of an existing row.
+ """DEPRECATED: The `_parent_id` field is deprecated and should not be used.
+ Support for `_parent_id` will be dropped in a future version of Braintrust. Log
+ `span_id`, `root_span_id`, and `span_parents` explicitly instead.
+
+ Use the `_parent_id` field to create this row as a subspan of an existing row.
Tracking hierarchical relationships are important for tracing (see the
[guide](https://www.braintrust.dev/docs/guides/tracing) for full details).
@@ -88,7 +104,7 @@ class InsertDatasetEvent(BaseModel):
object)
"""
- metadata: Optional[Dict[str, Optional[object]]] = None
+ metadata: Optional[Metadata] = None
"""
A dictionary with additional data about the test example, model outputs, or just
about anything else that's relevant, that you can use to help find and analyze
@@ -97,11 +113,14 @@ class InsertDatasetEvent(BaseModel):
can be any JSON-serializable type, but its keys must be strings
"""
+ origin: Optional[ObjectReference] = None
+ """Indicates the event was copied from another object."""
+
root_span_id: Optional[str] = None
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
@@ -118,9 +137,9 @@ class InsertDatasetEvent(BaseModel):
span_id: Optional[str] = None
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
@@ -137,9 +156,9 @@ class InsertDatasetEvent(BaseModel):
span_parents: Optional[List[str]] = None
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
diff --git a/src/braintrust_api/types/shared/insert_experiment_event.py b/src/braintrust_api/types/shared/insert_experiment_event.py
index 78dbe1db..4840614f 100644
--- a/src/braintrust_api/types/shared/insert_experiment_event.py
+++ b/src/braintrust_api/types/shared/insert_experiment_event.py
@@ -7,8 +7,9 @@
from ..._models import BaseModel
from .span_attributes import SpanAttributes
+from .object_reference import ObjectReference
-__all__ = ["InsertExperimentEvent", "Context", "Metrics"]
+__all__ = ["InsertExperimentEvent", "Context", "Metadata", "Metrics"]
class Context(BaseModel):
@@ -28,6 +29,17 @@ class Context(BaseModel):
def __getattr__(self, attr: str) -> Optional[object]: ...
+class Metadata(BaseModel):
+ model: Optional[str] = None
+ """The model used for this example"""
+
+ if TYPE_CHECKING:
+ # Stub to indicate that arbitrary properties are accepted.
+ # To access properties that are not valid identifiers you can use `getattr`, e.g.
+ # `getattr(obj, '$type')`
+ def __getattr__(self, attr: str) -> Optional[object]: ...
+
+
class Metrics(BaseModel):
caller_filename: Optional[object] = None
"""This metric is deprecated"""
@@ -119,8 +131,12 @@ class InsertExperimentEvent(BaseModel):
"""
parent_id: Optional[str] = FieldInfo(alias="_parent_id", default=None)
- """Use the `_parent_id` field to create this row as a subspan of an existing row.
+ """DEPRECATED: The `_parent_id` field is deprecated and should not be used.
+
+ Support for `_parent_id` will be dropped in a future version of Braintrust. Log
+ `span_id`, `root_span_id`, and `span_parents` explicitly instead.
+ Use the `_parent_id` field to create this row as a subspan of an existing row.
Tracking hierarchical relationships are important for tracing (see the
[guide](https://www.braintrust.dev/docs/guides/tracing) for full details).
@@ -146,12 +162,6 @@ class InsertExperimentEvent(BaseModel):
created: Optional[datetime] = None
"""The timestamp the experiment event was created"""
- dataset_record_id: Optional[str] = None
- """
- If the experiment is associated to a dataset, this is the event-level dataset id
- this experiment event is tied to
- """
-
error: Optional[object] = None
"""The error that occurred, if any."""
@@ -175,7 +185,7 @@ class InsertExperimentEvent(BaseModel):
experiment twice, the `input` should be identical
"""
- metadata: Optional[Dict[str, Optional[object]]] = None
+ metadata: Optional[Metadata] = None
"""
A dictionary with additional data about the test example, model outputs, or just
about anything else that's relevant, that you can use to help find and analyze
@@ -191,6 +201,9 @@ class InsertExperimentEvent(BaseModel):
which the experiment event was produced
"""
+ origin: Optional[ObjectReference] = None
+ """Indicates the event was copied from another object."""
+
output: Optional[object] = None
"""
The output of your application, including post-processing (an arbitrary, JSON
@@ -202,9 +215,9 @@ class InsertExperimentEvent(BaseModel):
root_span_id: Optional[str] = None
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
@@ -236,9 +249,9 @@ class InsertExperimentEvent(BaseModel):
span_id: Optional[str] = None
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
@@ -255,9 +268,9 @@ class InsertExperimentEvent(BaseModel):
span_parents: Optional[List[str]] = None
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
diff --git a/src/braintrust_api/types/shared/insert_project_logs_event.py b/src/braintrust_api/types/shared/insert_project_logs_event.py
index c6f95570..7ff2b3d0 100644
--- a/src/braintrust_api/types/shared/insert_project_logs_event.py
+++ b/src/braintrust_api/types/shared/insert_project_logs_event.py
@@ -7,8 +7,9 @@
from ..._models import BaseModel
from .span_attributes import SpanAttributes
+from .object_reference import ObjectReference
-__all__ = ["InsertProjectLogsEvent", "Context", "Metrics"]
+__all__ = ["InsertProjectLogsEvent", "Context", "Metadata", "Metrics"]
class Context(BaseModel):
@@ -28,6 +29,17 @@ class Context(BaseModel):
def __getattr__(self, attr: str) -> Optional[object]: ...
+class Metadata(BaseModel):
+ model: Optional[str] = None
+ """The model used for this example"""
+
+ if TYPE_CHECKING:
+ # Stub to indicate that arbitrary properties are accepted.
+ # To access properties that are not valid identifiers you can use `getattr`, e.g.
+ # `getattr(obj, '$type')`
+ def __getattr__(self, attr: str) -> Optional[object]: ...
+
+
class Metrics(BaseModel):
caller_filename: Optional[object] = None
"""This metric is deprecated"""
@@ -119,8 +131,12 @@ class InsertProjectLogsEvent(BaseModel):
"""
parent_id: Optional[str] = FieldInfo(alias="_parent_id", default=None)
- """Use the `_parent_id` field to create this row as a subspan of an existing row.
+ """DEPRECATED: The `_parent_id` field is deprecated and should not be used.
+ Support for `_parent_id` will be dropped in a future version of Braintrust. Log
+ `span_id`, `root_span_id`, and `span_parents` explicitly instead.
+
+ Use the `_parent_id` field to create this row as a subspan of an existing row.
Tracking hierarchical relationships are important for tracing (see the
[guide](https://www.braintrust.dev/docs/guides/tracing) for full details).
@@ -165,7 +181,7 @@ class InsertProjectLogsEvent(BaseModel):
object).
"""
- metadata: Optional[Dict[str, Optional[object]]] = None
+ metadata: Optional[Metadata] = None
"""
A dictionary with additional data about the test example, model outputs, or just
about anything else that's relevant, that you can use to help find and analyze
@@ -181,6 +197,9 @@ class InsertProjectLogsEvent(BaseModel):
over which the project logs event was produced
"""
+ origin: Optional[ObjectReference] = None
+ """Indicates the event was copied from another object."""
+
output: Optional[object] = None
"""
The output of your application, including post-processing (an arbitrary, JSON
@@ -192,9 +211,9 @@ class InsertProjectLogsEvent(BaseModel):
root_span_id: Optional[str] = None
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
@@ -226,9 +245,9 @@ class InsertProjectLogsEvent(BaseModel):
span_id: Optional[str] = None
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
@@ -245,9 +264,9 @@ class InsertProjectLogsEvent(BaseModel):
span_parents: Optional[List[str]] = None
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
diff --git a/src/braintrust_api/types/shared/object_reference.py b/src/braintrust_api/types/shared/object_reference.py
new file mode 100644
index 00000000..96493ed6
--- /dev/null
+++ b/src/braintrust_api/types/shared/object_reference.py
@@ -0,0 +1,27 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["ObjectReference"]
+
+
+class ObjectReference(BaseModel):
+ id: str
+ """ID of the original event."""
+
+ xact_id: str = FieldInfo(alias="_xact_id")
+ """Transaction ID of the original event."""
+
+ object_id: str
+ """ID of the object the event is originating from."""
+
+ object_type: Literal["experiment", "dataset", "prompt", "function", "prompt_session", "project_logs"]
+ """Type of the object the event is originating from."""
+
+ created: Optional[str] = None
+ """Created timestamp of the original event. Used to help sort in the UI"""
diff --git a/src/braintrust_api/types/shared/permission.py b/src/braintrust_api/types/shared/permission.py
new file mode 100644
index 00000000..33bf98f8
--- /dev/null
+++ b/src/braintrust_api/types/shared/permission.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["Permission"]
+
+Permission: TypeAlias = Literal[
+ "create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"
+]
diff --git a/src/braintrust_api/types/shared/project_logs_event.py b/src/braintrust_api/types/shared/project_logs_event.py
index 2483c3cc..d692a144 100755
--- a/src/braintrust_api/types/shared/project_logs_event.py
+++ b/src/braintrust_api/types/shared/project_logs_event.py
@@ -8,8 +8,9 @@
from ..._models import BaseModel
from .span_attributes import SpanAttributes
+from .object_reference import ObjectReference
-__all__ = ["ProjectLogsEvent", "Context", "Metrics", "Origin"]
+__all__ = ["ProjectLogsEvent", "Context", "Metadata", "Metrics"]
class Context(BaseModel):
@@ -29,6 +30,17 @@ class Context(BaseModel):
def __getattr__(self, attr: str) -> Optional[object]: ...
+class Metadata(BaseModel):
+ model: Optional[str] = None
+ """The model used for this example"""
+
+ if TYPE_CHECKING:
+ # Stub to indicate that arbitrary properties are accepted.
+ # To access properties that are not valid identifiers you can use `getattr`, e.g.
+ # `getattr(obj, '$type')`
+ def __getattr__(self, attr: str) -> Optional[object]: ...
+
+
class Metrics(BaseModel):
caller_filename: Optional[object] = None
"""This metric is deprecated"""
@@ -73,20 +85,6 @@ class Metrics(BaseModel):
def __getattr__(self, attr: str) -> float: ...
-class Origin(BaseModel):
- id: str
- """ID of the original event."""
-
- xact_id: str = FieldInfo(alias="_xact_id")
- """Transaction ID of the original event."""
-
- object_id: str
- """ID of the object the event is originating from."""
-
- object_type: Literal["experiment", "dataset", "prompt", "function", "prompt_session", "project_logs"]
- """Type of the object the event is originating from."""
-
-
class ProjectLogsEvent(BaseModel):
id: str
"""A unique identifier for the project logs event.
@@ -155,7 +153,7 @@ class ProjectLogsEvent(BaseModel):
is_root: Optional[bool] = None
"""Whether this span is a root span"""
- metadata: Optional[Dict[str, Optional[object]]] = None
+ metadata: Optional[Metadata] = None
"""
A dictionary with additional data about the test example, model outputs, or just
about anything else that's relevant, that you can use to help find and analyze
@@ -171,7 +169,7 @@ class ProjectLogsEvent(BaseModel):
over which the project logs event was produced
"""
- origin: Optional[Origin] = None
+ origin: Optional[ObjectReference] = None
"""Indicates the event was copied from another object."""
output: Optional[object] = None
diff --git a/src/braintrust_api/types/shared/project_score.py b/src/braintrust_api/types/shared/project_score.py
index 7b852d06..25138826 100755
--- a/src/braintrust_api/types/shared/project_score.py
+++ b/src/braintrust_api/types/shared/project_score.py
@@ -2,22 +2,13 @@
from typing import Dict, List, Union, Optional
from datetime import datetime
-from typing_extensions import Literal, TypeAlias
from ..._models import BaseModel
+from .project_score_type import ProjectScoreType
from .project_score_config import ProjectScoreConfig
from .project_score_category import ProjectScoreCategory
-__all__ = ["ProjectScore", "Categories", "CategoriesNullableVariant"]
-
-
-class CategoriesNullableVariant(BaseModel):
- pass
-
-
-Categories: TypeAlias = Union[
- List[ProjectScoreCategory], Dict[str, float], List[str], Optional[CategoriesNullableVariant]
-]
+__all__ = ["ProjectScore"]
class ProjectScore(BaseModel):
@@ -30,12 +21,12 @@ class ProjectScore(BaseModel):
project_id: str
"""Unique identifier for the project that the project score belongs under"""
- score_type: Literal["slider", "categorical", "weighted", "minimum", "maximum", "online"]
+ score_type: ProjectScoreType
"""The type of the configured score"""
user_id: str
- categories: Optional[Categories] = None
+ categories: Union[List[ProjectScoreCategory], Dict[str, float], List[str], None] = None
"""For categorical-type project scores, the list of all categories"""
config: Optional[ProjectScoreConfig] = None
diff --git a/src/braintrust_api/types/shared/project_score_category.py b/src/braintrust_api/types/shared/project_score_category.py
index 06034cdc..5501c2bf 100755
--- a/src/braintrust_api/types/shared/project_score_category.py
+++ b/src/braintrust_api/types/shared/project_score_category.py
@@ -1,6 +1,5 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
from ..._models import BaseModel
__all__ = ["ProjectScoreCategory"]
diff --git a/src/braintrust_api/types/shared/project_score_config.py b/src/braintrust_api/types/shared/project_score_config.py
index 1fe7d6f2..e6ce35ea 100644
--- a/src/braintrust_api/types/shared/project_score_config.py
+++ b/src/braintrust_api/types/shared/project_score_config.py
@@ -1,7 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import Optional
-from typing_extensions import Literal
from ..._models import BaseModel
from .online_score_config import OnlineScoreConfig
@@ -10,7 +9,7 @@
class ProjectScoreConfig(BaseModel):
- destination: Optional[Literal["expected"]] = None
+ destination: Optional[str] = None
multi_select: Optional[bool] = None
diff --git a/src/braintrust_api/types/shared/project_score_type.py b/src/braintrust_api/types/shared/project_score_type.py
new file mode 100644
index 00000000..6acc2391
--- /dev/null
+++ b/src/braintrust_api/types/shared/project_score_type.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["ProjectScoreType"]
+
+ProjectScoreType: TypeAlias = Literal["slider", "categorical", "weighted", "minimum", "maximum", "online", "free-form"]
diff --git a/src/braintrust_api/types/shared/project_settings.py b/src/braintrust_api/types/shared/project_settings.py
index 666288e4..bffe6bd5 100644
--- a/src/braintrust_api/types/shared/project_settings.py
+++ b/src/braintrust_api/types/shared/project_settings.py
@@ -1,12 +1,31 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
+from typing import List, Optional
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
from ..._models import BaseModel
-__all__ = ["ProjectSettings"]
+__all__ = ["ProjectSettings", "SpanFieldOrder"]
+
+
+class SpanFieldOrder(BaseModel):
+ column_id: str
+
+ object_type: str
+
+ position: str
+
+ layout: Optional[Literal["full", "two_column"]] = None
class ProjectSettings(BaseModel):
+ baseline_experiment_id: Optional[str] = None
+ """The id of the experiment to use as the default baseline for comparisons"""
+
comparison_key: Optional[str] = None
- """The key used to join two experiments (defaults to `input`)."""
+ """The key used to join two experiments (defaults to `input`)"""
+
+ span_field_order: Optional[List[SpanFieldOrder]] = FieldInfo(alias="spanFieldOrder", default=None)
+ """The order of the fields to display in the trace view"""
diff --git a/src/braintrust_api/types/shared/prompt_data.py b/src/braintrust_api/types/shared/prompt_data.py
index 74b02bc7..5b3350cc 100755
--- a/src/braintrust_api/types/shared/prompt_data.py
+++ b/src/braintrust_api/types/shared/prompt_data.py
@@ -25,7 +25,6 @@
"PromptChatMessageTool",
"PromptChatMessageFunction",
"PromptChatMessageFallback",
- "PromptNullableVariant",
"ToolFunction",
"ToolFunctionFunction",
"ToolFunctionGlobal",
@@ -131,11 +130,7 @@ class PromptChat(BaseModel):
tools: Optional[str] = None
-class PromptNullableVariant(BaseModel):
- pass
-
-
-Prompt: TypeAlias = Union[PromptCompletion, PromptChat, Optional[PromptNullableVariant]]
+Prompt: TypeAlias = Union[PromptCompletion, PromptChat, None]
class ToolFunctionFunction(BaseModel):
diff --git a/src/braintrust_api/types/shared/prompt_options.py b/src/braintrust_api/types/shared/prompt_options.py
index 66f68e2a..03efebe2 100644
--- a/src/braintrust_api/types/shared/prompt_options.py
+++ b/src/braintrust_api/types/shared/prompt_options.py
@@ -18,7 +18,6 @@
"ParamsOpenAIModelParamsResponseFormatJsonSchema",
"ParamsOpenAIModelParamsResponseFormatJsonSchemaJsonSchema",
"ParamsOpenAIModelParamsResponseFormatText",
- "ParamsOpenAIModelParamsResponseFormatNullableVariant",
"ParamsOpenAIModelParamsToolChoice",
"ParamsOpenAIModelParamsToolChoiceFunction",
"ParamsOpenAIModelParamsToolChoiceFunctionFunction",
@@ -34,7 +33,7 @@ class ParamsOpenAIModelParamsFunctionCallFunction(BaseModel):
ParamsOpenAIModelParamsFunctionCall: TypeAlias = Union[
- Literal["auto"], Literal["none"], ParamsOpenAIModelParamsFunctionCallFunction
+ Literal["auto", "none"], ParamsOpenAIModelParamsFunctionCallFunction
]
@@ -47,7 +46,7 @@ class ParamsOpenAIModelParamsResponseFormatJsonSchemaJsonSchema(BaseModel):
description: Optional[str] = None
- schema_: Optional[Dict[str, Optional[object]]] = FieldInfo(alias="schema", default=None)
+ schema_: Union[Dict[str, Optional[object]], str, None] = FieldInfo(alias="schema", default=None)
strict: Optional[bool] = None
@@ -62,15 +61,11 @@ class ParamsOpenAIModelParamsResponseFormatText(BaseModel):
type: Literal["text"]
-class ParamsOpenAIModelParamsResponseFormatNullableVariant(BaseModel):
- pass
-
-
ParamsOpenAIModelParamsResponseFormat: TypeAlias = Union[
ParamsOpenAIModelParamsResponseFormatJsonObject,
ParamsOpenAIModelParamsResponseFormatJsonSchema,
ParamsOpenAIModelParamsResponseFormatText,
- Optional[ParamsOpenAIModelParamsResponseFormatNullableVariant],
+ None,
]
@@ -85,7 +80,7 @@ class ParamsOpenAIModelParamsToolChoiceFunction(BaseModel):
ParamsOpenAIModelParamsToolChoice: TypeAlias = Union[
- Literal["auto"], Literal["none"], Literal["required"], ParamsOpenAIModelParamsToolChoiceFunction
+ Literal["auto", "none", "required"], ParamsOpenAIModelParamsToolChoiceFunction
]
@@ -94,12 +89,17 @@ class ParamsOpenAIModelParams(BaseModel):
function_call: Optional[ParamsOpenAIModelParamsFunctionCall] = None
+ max_completion_tokens: Optional[float] = None
+ """The successor to max_tokens"""
+
max_tokens: Optional[float] = None
n: Optional[float] = None
presence_penalty: Optional[float] = None
+ reasoning_effort: Optional[Literal["low", "medium", "high"]] = None
+
response_format: Optional[ParamsOpenAIModelParamsResponseFormat] = None
stop: Optional[List[str]] = None
diff --git a/src/braintrust_api/types/shared/role.py b/src/braintrust_api/types/shared/role.py
index c94cd569..61530af5 100755
--- a/src/braintrust_api/types/shared/role.py
+++ b/src/braintrust_api/types/shared/role.py
@@ -2,36 +2,23 @@
from typing import List, Optional
from datetime import datetime
-from typing_extensions import Literal
from ..._models import BaseModel
+from .permission import Permission
+from .acl_object_type import ACLObjectType
__all__ = ["Role", "MemberPermission"]
class MemberPermission(BaseModel):
- permission: Literal["create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"]
+ permission: Permission
"""Each permission permits a certain type of operation on an object in the system
Permissions can be assigned to to objects on an individual basis, or grouped
into roles
"""
- restrict_object_type: Optional[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ] = None
+ restrict_object_type: Optional[ACLObjectType] = None
"""The object type that the ACL applies to"""
diff --git a/src/braintrust_api/types/shared/span_attributes.py b/src/braintrust_api/types/shared/span_attributes.py
index 18eec021..f39cff98 100644
--- a/src/braintrust_api/types/shared/span_attributes.py
+++ b/src/braintrust_api/types/shared/span_attributes.py
@@ -1,9 +1,9 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import TYPE_CHECKING, Optional
-from typing_extensions import Literal
from ..._models import BaseModel
+from .span_type import SpanType
__all__ = ["SpanAttributes"]
@@ -12,7 +12,7 @@ class SpanAttributes(BaseModel):
name: Optional[str] = None
"""Name of the span, for display purposes only"""
- type: Optional[Literal["llm", "score", "function", "eval", "task", "tool"]] = None
+ type: Optional[SpanType] = None
"""Type of the span, for display purposes only"""
if TYPE_CHECKING:
diff --git a/src/braintrust_api/types/shared/span_type.py b/src/braintrust_api/types/shared/span_type.py
new file mode 100644
index 00000000..8cf820bf
--- /dev/null
+++ b/src/braintrust_api/types/shared/span_type.py
@@ -0,0 +1,8 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["SpanType"]
+
+SpanType: TypeAlias = Optional[Literal["llm", "score", "function", "eval", "task", "tool"]]
diff --git a/src/braintrust_api/types/shared/view.py b/src/braintrust_api/types/shared/view.py
index 6c9b5d7a..ba4fe766 100755
--- a/src/braintrust_api/types/shared/view.py
+++ b/src/braintrust_api/types/shared/view.py
@@ -7,6 +7,7 @@
from ..._models import BaseModel
from .view_data import ViewData
from .view_options import ViewOptions
+from .acl_object_type import ACLObjectType
__all__ = ["View"]
@@ -21,23 +22,23 @@ class View(BaseModel):
object_id: str
"""The id of the object the view applies to"""
- object_type: Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
+ object_type: ACLObjectType
"""The object type that the ACL applies to"""
view_type: Optional[
- Literal["projects", "logs", "experiments", "datasets", "prompts", "playgrounds", "experiment", "dataset"]
+ Literal[
+ "projects",
+ "experiments",
+ "experiment",
+ "playgrounds",
+ "playground",
+ "datasets",
+ "dataset",
+ "prompts",
+ "tools",
+ "scorers",
+ "logs",
+ ]
] = None
"""Type of table that the view corresponds to."""
diff --git a/src/braintrust_api/types/shared/view_options.py b/src/braintrust_api/types/shared/view_options.py
index 567cfe2d..2f333be0 100755
--- a/src/braintrust_api/types/shared/view_options.py
+++ b/src/braintrust_api/types/shared/view_options.py
@@ -15,3 +15,9 @@ class ViewOptions(BaseModel):
column_sizing: Optional[Dict[str, float]] = FieldInfo(alias="columnSizing", default=None)
column_visibility: Optional[Dict[str, bool]] = FieldInfo(alias="columnVisibility", default=None)
+
+ grouping: Optional[str] = None
+
+ layout: Optional[str] = None
+
+ row_height: Optional[str] = FieldInfo(alias="rowHeight", default=None)
diff --git a/src/braintrust_api/types/shared/view_type.py b/src/braintrust_api/types/shared/view_type.py
new file mode 100644
index 00000000..66d8618a
--- /dev/null
+++ b/src/braintrust_api/types/shared/view_type.py
@@ -0,0 +1,22 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["ViewType"]
+
+ViewType: TypeAlias = Optional[
+ Literal[
+ "projects",
+ "experiments",
+ "experiment",
+ "playgrounds",
+ "playground",
+ "datasets",
+ "dataset",
+ "prompts",
+ "tools",
+ "scorers",
+ "logs",
+ ]
+]
diff --git a/src/braintrust_api/types/shared_params/__init__.py b/src/braintrust_api/types/shared_params/__init__.py
index b2649298..611f0a87 100755
--- a/src/braintrust_api/types/shared_params/__init__.py
+++ b/src/braintrust_api/types/shared_params/__init__.py
@@ -1,14 +1,21 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from .repo_info import RepoInfo as RepoInfo
+from .span_type import SpanType as SpanType
from .view_data import ViewData as ViewData
+from .view_type import ViewType as ViewType
+from .permission import Permission as Permission
from .code_bundle import CodeBundle as CodeBundle
from .prompt_data import PromptData as PromptData
from .view_options import ViewOptions as ViewOptions
from .prompt_options import PromptOptions as PromptOptions
+from .acl_object_type import ACLObjectType as ACLObjectType
from .span_attributes import SpanAttributes as SpanAttributes
+from .object_reference import ObjectReference as ObjectReference
from .project_settings import ProjectSettings as ProjectSettings
from .view_data_search import ViewDataSearch as ViewDataSearch
+from .project_score_type import ProjectScoreType as ProjectScoreType
+from .env_var_object_type import EnvVarObjectType as EnvVarObjectType
from .online_score_config import OnlineScoreConfig as OnlineScoreConfig
from .insert_dataset_event import InsertDatasetEvent as InsertDatasetEvent
from .project_score_config import ProjectScoreConfig as ProjectScoreConfig
diff --git a/src/braintrust_api/types/shared_params/acl_object_type.py b/src/braintrust_api/types/shared_params/acl_object_type.py
new file mode 100644
index 00000000..6d307f11
--- /dev/null
+++ b/src/braintrust_api/types/shared_params/acl_object_type.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["ACLObjectType"]
+
+ACLObjectType: TypeAlias = Literal[
+ "organization",
+ "project",
+ "experiment",
+ "dataset",
+ "prompt",
+ "prompt_session",
+ "group",
+ "role",
+ "org_member",
+ "project_log",
+ "org_project",
+]
diff --git a/src/braintrust_api/types/shared_params/env_var_object_type.py b/src/braintrust_api/types/shared_params/env_var_object_type.py
new file mode 100644
index 00000000..edc830cf
--- /dev/null
+++ b/src/braintrust_api/types/shared_params/env_var_object_type.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["EnvVarObjectType"]
+
+EnvVarObjectType: TypeAlias = Literal["organization", "project", "function"]
diff --git a/src/braintrust_api/types/shared_params/feedback_experiment_item.py b/src/braintrust_api/types/shared_params/feedback_experiment_item.py
index 2da1919f..f817b360 100755
--- a/src/braintrust_api/types/shared_params/feedback_experiment_item.py
+++ b/src/braintrust_api/types/shared_params/feedback_experiment_item.py
@@ -18,7 +18,7 @@ class FeedbackExperimentItem(TypedDict, total=False):
comment: Optional[str]
"""An optional comment string to log about the experiment event"""
- expected: Optional[object]
+ expected: object
"""
The ground truth value (an arbitrary, JSON serializable object) that you'd
compare to `output` to determine if your `output` value is correct or not
diff --git a/src/braintrust_api/types/shared_params/feedback_project_logs_item.py b/src/braintrust_api/types/shared_params/feedback_project_logs_item.py
index b14a0374..47351871 100755
--- a/src/braintrust_api/types/shared_params/feedback_project_logs_item.py
+++ b/src/braintrust_api/types/shared_params/feedback_project_logs_item.py
@@ -18,7 +18,7 @@ class FeedbackProjectLogsItem(TypedDict, total=False):
comment: Optional[str]
"""An optional comment string to log about the project logs event"""
- expected: Optional[object]
+ expected: object
"""
The ground truth value (an arbitrary, JSON serializable object) that you'd
compare to `output` to determine if your `output` value is correct or not
diff --git a/src/braintrust_api/types/shared_params/insert_dataset_event.py b/src/braintrust_api/types/shared_params/insert_dataset_event.py
index 9ba14549..fdc67ac5 100644
--- a/src/braintrust_api/types/shared_params/insert_dataset_event.py
+++ b/src/braintrust_api/types/shared_params/insert_dataset_event.py
@@ -4,11 +4,20 @@
from typing import Dict, List, Union, Iterable, Optional
from datetime import datetime
-from typing_extensions import Annotated, TypedDict
+from typing_extensions import Annotated, TypeAlias, TypedDict
from ..._utils import PropertyInfo
+from .object_reference import ObjectReference
-__all__ = ["InsertDatasetEvent"]
+__all__ = ["InsertDatasetEvent", "Metadata"]
+
+
+class MetadataTyped(TypedDict, total=False):
+ model: Optional[str]
+ """The model used for this example"""
+
+
+Metadata: TypeAlias = Union[MetadataTyped, Dict[str, Optional[object]]]
class InsertDatasetEvent(TypedDict, total=False):
@@ -58,8 +67,12 @@ class InsertDatasetEvent(TypedDict, total=False):
"""
_parent_id: Optional[str]
- """Use the `_parent_id` field to create this row as a subspan of an existing row.
+ """DEPRECATED: The `_parent_id` field is deprecated and should not be used.
+
+ Support for `_parent_id` will be dropped in a future version of Braintrust. Log
+ `span_id`, `root_span_id`, and `span_parents` explicitly instead.
+ Use the `_parent_id` field to create this row as a subspan of an existing row.
Tracking hierarchical relationships are important for tracing (see the
[guide](https://www.braintrust.dev/docs/guides/tracing) for full details).
@@ -77,19 +90,19 @@ class InsertDatasetEvent(TypedDict, total=False):
created: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
"""The timestamp the dataset event was created"""
- expected: Optional[object]
+ expected: object
"""
The output of your application, including post-processing (an arbitrary, JSON
serializable object)
"""
- input: Optional[object]
+ input: object
"""
The argument that uniquely define an input case (an arbitrary, JSON serializable
object)
"""
- metadata: Optional[Dict[str, Optional[object]]]
+ metadata: Optional[Metadata]
"""
A dictionary with additional data about the test example, model outputs, or just
about anything else that's relevant, that you can use to help find and analyze
@@ -98,11 +111,14 @@ class InsertDatasetEvent(TypedDict, total=False):
can be any JSON-serializable type, but its keys must be strings
"""
+ origin: Optional[ObjectReference]
+ """Indicates the event was copied from another object."""
+
root_span_id: Optional[str]
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
@@ -119,9 +135,9 @@ class InsertDatasetEvent(TypedDict, total=False):
span_id: Optional[str]
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
@@ -138,9 +154,9 @@ class InsertDatasetEvent(TypedDict, total=False):
span_parents: Optional[List[str]]
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
diff --git a/src/braintrust_api/types/shared_params/insert_experiment_event.py b/src/braintrust_api/types/shared_params/insert_experiment_event.py
index de55f41a..64716022 100644
--- a/src/braintrust_api/types/shared_params/insert_experiment_event.py
+++ b/src/braintrust_api/types/shared_params/insert_experiment_event.py
@@ -8,8 +8,9 @@
from ..._utils import PropertyInfo
from .span_attributes import SpanAttributes
+from .object_reference import ObjectReference
-__all__ = ["InsertExperimentEvent", "Context", "Metrics"]
+__all__ = ["InsertExperimentEvent", "Context", "Metadata", "Metrics"]
class ContextTyped(TypedDict, total=False):
@@ -26,14 +27,22 @@ class ContextTyped(TypedDict, total=False):
Context: TypeAlias = Union[ContextTyped, Dict[str, Optional[object]]]
+class MetadataTyped(TypedDict, total=False):
+ model: Optional[str]
+ """The model used for this example"""
+
+
+Metadata: TypeAlias = Union[MetadataTyped, Dict[str, Optional[object]]]
+
+
class MetricsTyped(TypedDict, total=False):
- caller_filename: Optional[object]
+ caller_filename: object
"""This metric is deprecated"""
- caller_functionname: Optional[object]
+ caller_functionname: object
"""This metric is deprecated"""
- caller_lineno: Optional[object]
+ caller_lineno: object
"""This metric is deprecated"""
completion_tokens: Optional[int]
@@ -114,8 +123,12 @@ class InsertExperimentEvent(TypedDict, total=False):
"""
_parent_id: Optional[str]
- """Use the `_parent_id` field to create this row as a subspan of an existing row.
+ """DEPRECATED: The `_parent_id` field is deprecated and should not be used.
+
+ Support for `_parent_id` will be dropped in a future version of Braintrust. Log
+ `span_id`, `root_span_id`, and `span_parents` explicitly instead.
+ Use the `_parent_id` field to create this row as a subspan of an existing row.
Tracking hierarchical relationships are important for tracing (see the
[guide](https://www.braintrust.dev/docs/guides/tracing) for full details).
@@ -141,16 +154,10 @@ class InsertExperimentEvent(TypedDict, total=False):
created: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
"""The timestamp the experiment event was created"""
- dataset_record_id: Optional[str]
- """
- If the experiment is associated to a dataset, this is the event-level dataset id
- this experiment event is tied to
- """
-
- error: Optional[object]
+ error: object
"""The error that occurred, if any."""
- expected: Optional[object]
+ expected: object
"""
The ground truth value (an arbitrary, JSON serializable object) that you'd
compare to `output` to determine if your `output` value is correct or not.
@@ -161,7 +168,7 @@ class InsertExperimentEvent(TypedDict, total=False):
models
"""
- input: Optional[object]
+ input: object
"""
The arguments that uniquely define a test case (an arbitrary, JSON serializable
object). Later on, Braintrust will use the `input` to know whether two test
@@ -170,7 +177,7 @@ class InsertExperimentEvent(TypedDict, total=False):
experiment twice, the `input` should be identical
"""
- metadata: Optional[Dict[str, Optional[object]]]
+ metadata: Optional[Metadata]
"""
A dictionary with additional data about the test example, model outputs, or just
about anything else that's relevant, that you can use to help find and analyze
@@ -186,7 +193,10 @@ class InsertExperimentEvent(TypedDict, total=False):
which the experiment event was produced
"""
- output: Optional[object]
+ origin: Optional[ObjectReference]
+ """Indicates the event was copied from another object."""
+
+ output: object
"""
The output of your application, including post-processing (an arbitrary, JSON
serializable object), that allows you to determine whether the result is correct
@@ -197,9 +207,9 @@ class InsertExperimentEvent(TypedDict, total=False):
root_span_id: Optional[str]
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
@@ -231,9 +241,9 @@ class InsertExperimentEvent(TypedDict, total=False):
span_id: Optional[str]
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
@@ -250,9 +260,9 @@ class InsertExperimentEvent(TypedDict, total=False):
span_parents: Optional[List[str]]
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
diff --git a/src/braintrust_api/types/shared_params/insert_project_logs_event.py b/src/braintrust_api/types/shared_params/insert_project_logs_event.py
index ae5d681e..d03cbe43 100644
--- a/src/braintrust_api/types/shared_params/insert_project_logs_event.py
+++ b/src/braintrust_api/types/shared_params/insert_project_logs_event.py
@@ -8,8 +8,9 @@
from ..._utils import PropertyInfo
from .span_attributes import SpanAttributes
+from .object_reference import ObjectReference
-__all__ = ["InsertProjectLogsEvent", "Context", "Metrics"]
+__all__ = ["InsertProjectLogsEvent", "Context", "Metadata", "Metrics"]
class ContextTyped(TypedDict, total=False):
@@ -26,14 +27,22 @@ class ContextTyped(TypedDict, total=False):
Context: TypeAlias = Union[ContextTyped, Dict[str, Optional[object]]]
+class MetadataTyped(TypedDict, total=False):
+ model: Optional[str]
+ """The model used for this example"""
+
+
+Metadata: TypeAlias = Union[MetadataTyped, Dict[str, Optional[object]]]
+
+
class MetricsTyped(TypedDict, total=False):
- caller_filename: Optional[object]
+ caller_filename: object
"""This metric is deprecated"""
- caller_functionname: Optional[object]
+ caller_functionname: object
"""This metric is deprecated"""
- caller_lineno: Optional[object]
+ caller_lineno: object
"""This metric is deprecated"""
completion_tokens: Optional[int]
@@ -114,8 +123,12 @@ class InsertProjectLogsEvent(TypedDict, total=False):
"""
_parent_id: Optional[str]
- """Use the `_parent_id` field to create this row as a subspan of an existing row.
+ """DEPRECATED: The `_parent_id` field is deprecated and should not be used.
+
+ Support for `_parent_id` will be dropped in a future version of Braintrust. Log
+ `span_id`, `root_span_id`, and `span_parents` explicitly instead.
+ Use the `_parent_id` field to create this row as a subspan of an existing row.
Tracking hierarchical relationships are important for tracing (see the
[guide](https://www.braintrust.dev/docs/guides/tracing) for full details).
@@ -141,10 +154,10 @@ class InsertProjectLogsEvent(TypedDict, total=False):
created: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
"""The timestamp the project logs event was created"""
- error: Optional[object]
+ error: object
"""The error that occurred, if any."""
- expected: Optional[object]
+ expected: object
"""
The ground truth value (an arbitrary, JSON serializable object) that you'd
compare to `output` to determine if your `output` value is correct or not.
@@ -154,13 +167,13 @@ class InsertProjectLogsEvent(TypedDict, total=False):
later use these values to re-score outputs or fine-tune your models.
"""
- input: Optional[object]
+ input: object
"""
The arguments that uniquely define a user input (an arbitrary, JSON serializable
object).
"""
- metadata: Optional[Dict[str, Optional[object]]]
+ metadata: Optional[Metadata]
"""
A dictionary with additional data about the test example, model outputs, or just
about anything else that's relevant, that you can use to help find and analyze
@@ -176,7 +189,10 @@ class InsertProjectLogsEvent(TypedDict, total=False):
over which the project logs event was produced
"""
- output: Optional[object]
+ origin: Optional[ObjectReference]
+ """Indicates the event was copied from another object."""
+
+ output: object
"""
The output of your application, including post-processing (an arbitrary, JSON
serializable object), that allows you to determine whether the result is correct
@@ -187,9 +203,9 @@ class InsertProjectLogsEvent(TypedDict, total=False):
root_span_id: Optional[str]
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
@@ -221,9 +237,9 @@ class InsertProjectLogsEvent(TypedDict, total=False):
span_id: Optional[str]
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
@@ -240,9 +256,9 @@ class InsertProjectLogsEvent(TypedDict, total=False):
span_parents: Optional[List[str]]
"""
- Use span_id, root_span_id, and span_parents as a more explicit alternative to
- \\__parent_id. The span_id is a unique identifier describing the row's place in
- the a trace, and the root_span_id is a unique identifier for the whole trace.
+ Use `span_id`, `root_span_id`, and `span_parents` instead of `_parent_id`, which
+ is now deprecated. The span_id is a unique identifier describing the row's place
+ in the a trace, and the root_span_id is a unique identifier for the whole trace.
See the [guide](https://www.braintrust.dev/docs/guides/tracing) for full
details.
diff --git a/src/braintrust_api/types/shared_params/object_reference.py b/src/braintrust_api/types/shared_params/object_reference.py
new file mode 100644
index 00000000..8b6e78c7
--- /dev/null
+++ b/src/braintrust_api/types/shared_params/object_reference.py
@@ -0,0 +1,25 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["ObjectReference"]
+
+
+class ObjectReference(TypedDict, total=False):
+ id: Required[str]
+ """ID of the original event."""
+
+ _xact_id: Required[str]
+ """Transaction ID of the original event."""
+
+ object_id: Required[str]
+ """ID of the object the event is originating from."""
+
+ object_type: Required[Literal["experiment", "dataset", "prompt", "function", "prompt_session", "project_logs"]]
+ """Type of the object the event is originating from."""
+
+ created: Optional[str]
+ """Created timestamp of the original event. Used to help sort in the UI"""
diff --git a/src/braintrust_api/types/shared_params/permission.py b/src/braintrust_api/types/shared_params/permission.py
new file mode 100644
index 00000000..8ef46e18
--- /dev/null
+++ b/src/braintrust_api/types/shared_params/permission.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["Permission"]
+
+Permission: TypeAlias = Literal[
+ "create", "read", "update", "delete", "create_acls", "read_acls", "update_acls", "delete_acls"
+]
diff --git a/src/braintrust_api/types/shared_params/project_score_config.py b/src/braintrust_api/types/shared_params/project_score_config.py
index dadadc82..fdf6b38d 100644
--- a/src/braintrust_api/types/shared_params/project_score_config.py
+++ b/src/braintrust_api/types/shared_params/project_score_config.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Literal, TypedDict
+from typing_extensions import TypedDict
from .online_score_config import OnlineScoreConfig
@@ -11,7 +11,7 @@
class ProjectScoreConfig(TypedDict, total=False):
- destination: Optional[Literal["expected"]]
+ destination: Optional[str]
multi_select: Optional[bool]
diff --git a/src/braintrust_api/types/shared_params/project_score_type.py b/src/braintrust_api/types/shared_params/project_score_type.py
new file mode 100644
index 00000000..9605616f
--- /dev/null
+++ b/src/braintrust_api/types/shared_params/project_score_type.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["ProjectScoreType"]
+
+ProjectScoreType: TypeAlias = Literal["slider", "categorical", "weighted", "minimum", "maximum", "online", "free-form"]
diff --git a/src/braintrust_api/types/shared_params/project_settings.py b/src/braintrust_api/types/shared_params/project_settings.py
index 09d03b10..1d7299ba 100644
--- a/src/braintrust_api/types/shared_params/project_settings.py
+++ b/src/braintrust_api/types/shared_params/project_settings.py
@@ -2,12 +2,30 @@
from __future__ import annotations
-from typing import Optional
-from typing_extensions import TypedDict
+from typing import Iterable, Optional
+from typing_extensions import Literal, Required, Annotated, TypedDict
-__all__ = ["ProjectSettings"]
+from ..._utils import PropertyInfo
+
+__all__ = ["ProjectSettings", "SpanFieldOrder"]
+
+
+class SpanFieldOrder(TypedDict, total=False):
+ column_id: Required[str]
+
+ object_type: Required[str]
+
+ position: Required[str]
+
+ layout: Optional[Literal["full", "two_column"]]
class ProjectSettings(TypedDict, total=False):
+ baseline_experiment_id: Optional[str]
+ """The id of the experiment to use as the default baseline for comparisons"""
+
comparison_key: Optional[str]
- """The key used to join two experiments (defaults to `input`)."""
+ """The key used to join two experiments (defaults to `input`)"""
+
+ span_field_order: Annotated[Optional[Iterable[SpanFieldOrder]], PropertyInfo(alias="spanFieldOrder")]
+ """The order of the fields to display in the trace view"""
diff --git a/src/braintrust_api/types/shared_params/prompt_data.py b/src/braintrust_api/types/shared_params/prompt_data.py
index 160551ea..0043be7e 100755
--- a/src/braintrust_api/types/shared_params/prompt_data.py
+++ b/src/braintrust_api/types/shared_params/prompt_data.py
@@ -26,7 +26,6 @@
"PromptChatMessageTool",
"PromptChatMessageFunction",
"PromptChatMessageFallback",
- "PromptNullableVariant",
"ToolFunction",
"ToolFunctionFunction",
"ToolFunctionGlobal",
@@ -132,11 +131,7 @@ class PromptChat(TypedDict, total=False):
tools: str
-class PromptNullableVariant(TypedDict, total=False):
- pass
-
-
-Prompt: TypeAlias = Union[PromptCompletion, PromptChat, Optional[PromptNullableVariant]]
+Prompt: TypeAlias = Union[PromptCompletion, PromptChat]
class ToolFunctionFunction(TypedDict, total=False):
@@ -161,6 +156,6 @@ class PromptData(TypedDict, total=False):
parser: Optional[Parser]
- prompt: Prompt
+ prompt: Optional[Prompt]
tool_functions: Optional[Iterable[ToolFunction]]
diff --git a/src/braintrust_api/types/shared_params/prompt_options.py b/src/braintrust_api/types/shared_params/prompt_options.py
index cdfb1ad0..938e31d1 100644
--- a/src/braintrust_api/types/shared_params/prompt_options.py
+++ b/src/braintrust_api/types/shared_params/prompt_options.py
@@ -18,7 +18,6 @@
"ParamsOpenAIModelParamsResponseFormatJsonSchema",
"ParamsOpenAIModelParamsResponseFormatJsonSchemaJsonSchema",
"ParamsOpenAIModelParamsResponseFormatText",
- "ParamsOpenAIModelParamsResponseFormatNullableVariant",
"ParamsOpenAIModelParamsToolChoice",
"ParamsOpenAIModelParamsToolChoiceFunction",
"ParamsOpenAIModelParamsToolChoiceFunctionFunction",
@@ -34,7 +33,7 @@ class ParamsOpenAIModelParamsFunctionCallFunction(TypedDict, total=False):
ParamsOpenAIModelParamsFunctionCall: TypeAlias = Union[
- Literal["auto"], Literal["none"], ParamsOpenAIModelParamsFunctionCallFunction
+ Literal["auto", "none"], ParamsOpenAIModelParamsFunctionCallFunction
]
@@ -47,7 +46,7 @@ class ParamsOpenAIModelParamsResponseFormatJsonSchemaJsonSchema(TypedDict, total
description: str
- schema: Dict[str, Optional[object]]
+ schema: Union[Dict[str, Optional[object]], str]
strict: Optional[bool]
@@ -62,15 +61,10 @@ class ParamsOpenAIModelParamsResponseFormatText(TypedDict, total=False):
type: Required[Literal["text"]]
-class ParamsOpenAIModelParamsResponseFormatNullableVariant(TypedDict, total=False):
- pass
-
-
ParamsOpenAIModelParamsResponseFormat: TypeAlias = Union[
ParamsOpenAIModelParamsResponseFormatJsonObject,
ParamsOpenAIModelParamsResponseFormatJsonSchema,
ParamsOpenAIModelParamsResponseFormatText,
- Optional[ParamsOpenAIModelParamsResponseFormatNullableVariant],
]
@@ -85,7 +79,7 @@ class ParamsOpenAIModelParamsToolChoiceFunction(TypedDict, total=False):
ParamsOpenAIModelParamsToolChoice: TypeAlias = Union[
- Literal["auto"], Literal["none"], Literal["required"], ParamsOpenAIModelParamsToolChoiceFunction
+ Literal["auto", "none", "required"], ParamsOpenAIModelParamsToolChoiceFunction
]
@@ -94,13 +88,18 @@ class ParamsOpenAIModelParams(TypedDict, total=False):
function_call: ParamsOpenAIModelParamsFunctionCall
+ max_completion_tokens: float
+ """The successor to max_tokens"""
+
max_tokens: float
n: float
presence_penalty: float
- response_format: ParamsOpenAIModelParamsResponseFormat
+ reasoning_effort: Literal["low", "medium", "high"]
+
+ response_format: Optional[ParamsOpenAIModelParamsResponseFormat]
stop: List[str]
diff --git a/src/braintrust_api/types/shared_params/span_attributes.py b/src/braintrust_api/types/shared_params/span_attributes.py
index 9b3930b8..64e7b31b 100644
--- a/src/braintrust_api/types/shared_params/span_attributes.py
+++ b/src/braintrust_api/types/shared_params/span_attributes.py
@@ -3,7 +3,9 @@
from __future__ import annotations
from typing import Dict, Union, Optional
-from typing_extensions import Literal, TypeAlias, TypedDict
+from typing_extensions import TypeAlias, TypedDict
+
+from ..shared.span_type import SpanType
__all__ = ["SpanAttributes"]
@@ -12,7 +14,7 @@ class SpanAttributesTyped(TypedDict, total=False):
name: Optional[str]
"""Name of the span, for display purposes only"""
- type: Optional[Literal["llm", "score", "function", "eval", "task", "tool"]]
+ type: Optional[SpanType]
"""Type of the span, for display purposes only"""
diff --git a/src/braintrust_api/types/shared_params/span_type.py b/src/braintrust_api/types/shared_params/span_type.py
new file mode 100644
index 00000000..fd0e866a
--- /dev/null
+++ b/src/braintrust_api/types/shared_params/span_type.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["SpanType"]
+
+SpanType: TypeAlias = Optional[Literal["llm", "score", "function", "eval", "task", "tool"]]
diff --git a/src/braintrust_api/types/shared_params/view_options.py b/src/braintrust_api/types/shared_params/view_options.py
index 4e042a0b..d1a98e0a 100755
--- a/src/braintrust_api/types/shared_params/view_options.py
+++ b/src/braintrust_api/types/shared_params/view_options.py
@@ -16,3 +16,9 @@ class ViewOptions(TypedDict, total=False):
column_sizing: Annotated[Optional[Dict[str, float]], PropertyInfo(alias="columnSizing")]
column_visibility: Annotated[Optional[Dict[str, bool]], PropertyInfo(alias="columnVisibility")]
+
+ grouping: Optional[str]
+
+ layout: Optional[str]
+
+ row_height: Annotated[Optional[str], PropertyInfo(alias="rowHeight")]
diff --git a/src/braintrust_api/types/shared_params/view_type.py b/src/braintrust_api/types/shared_params/view_type.py
new file mode 100644
index 00000000..286458f7
--- /dev/null
+++ b/src/braintrust_api/types/shared_params/view_type.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["ViewType"]
+
+ViewType: TypeAlias = Optional[
+ Literal[
+ "projects",
+ "experiments",
+ "experiment",
+ "playgrounds",
+ "playground",
+ "datasets",
+ "dataset",
+ "prompts",
+ "tools",
+ "scorers",
+ "logs",
+ ]
+]
diff --git a/src/braintrust_api/types/span_iframe_update_params.py b/src/braintrust_api/types/span_iframe_update_params.py
index 6915af63..255f93b8 100644
--- a/src/braintrust_api/types/span_iframe_update_params.py
+++ b/src/braintrust_api/types/span_iframe_update_params.py
@@ -9,6 +9,9 @@
class SpanIframeUpdateParams(TypedDict, total=False):
+ description: Optional[str]
+ """Textual description of the span iframe"""
+
name: Optional[str]
"""Name of the span iframe"""
diff --git a/src/braintrust_api/types/view_create_params.py b/src/braintrust_api/types/view_create_params.py
index 2b0c1e67..07f8adbb 100755
--- a/src/braintrust_api/types/view_create_params.py
+++ b/src/braintrust_api/types/view_create_params.py
@@ -7,6 +7,7 @@
from typing_extensions import Literal, Required, Annotated, TypedDict
from .._utils import PropertyInfo
+from .shared.acl_object_type import ACLObjectType
from .shared_params.view_data import ViewData
from .shared_params.view_options import ViewOptions
@@ -20,26 +21,24 @@ class ViewCreateParams(TypedDict, total=False):
object_id: Required[str]
"""The id of the object the view applies to"""
- object_type: Required[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ object_type: Required[ACLObjectType]
"""The object type that the ACL applies to"""
view_type: Required[
Optional[
- Literal["projects", "logs", "experiments", "datasets", "prompts", "playgrounds", "experiment", "dataset"]
+ Literal[
+ "projects",
+ "experiments",
+ "experiment",
+ "playgrounds",
+ "playground",
+ "datasets",
+ "dataset",
+ "prompts",
+ "tools",
+ "scorers",
+ "logs",
+ ]
]
]
"""Type of table that the view corresponds to."""
diff --git a/src/braintrust_api/types/view_delete_params.py b/src/braintrust_api/types/view_delete_params.py
index b06d6ee2..4e1f4fde 100755
--- a/src/braintrust_api/types/view_delete_params.py
+++ b/src/braintrust_api/types/view_delete_params.py
@@ -2,7 +2,9 @@
from __future__ import annotations
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Required, TypedDict
+
+from .shared.acl_object_type import ACLObjectType
__all__ = ["ViewDeleteParams"]
@@ -11,19 +13,5 @@ class ViewDeleteParams(TypedDict, total=False):
object_id: Required[str]
"""The id of the object the view applies to"""
- object_type: Required[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ object_type: Required[ACLObjectType]
"""The object type that the ACL applies to"""
diff --git a/src/braintrust_api/types/view_list_params.py b/src/braintrust_api/types/view_list_params.py
index 37c5b712..802ae569 100755
--- a/src/braintrust_api/types/view_list_params.py
+++ b/src/braintrust_api/types/view_list_params.py
@@ -3,7 +3,10 @@
from __future__ import annotations
from typing import List, Union, Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Required, TypedDict
+
+from .shared.view_type import ViewType
+from .shared.acl_object_type import ACLObjectType
__all__ = ["ViewListParams"]
@@ -12,21 +15,7 @@ class ViewListParams(TypedDict, total=False):
object_id: Required[str]
"""The id of the object the ACL applies to"""
- object_type: Required[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ object_type: Required[ACLObjectType]
"""The object type that the ACL applies to"""
ending_before: str
@@ -57,7 +46,5 @@ class ViewListParams(TypedDict, total=False):
view_name: str
"""Name of the view to search for"""
- view_type: Optional[
- Literal["projects", "logs", "experiments", "datasets", "prompts", "playgrounds", "experiment", "dataset"]
- ]
+ view_type: Optional[ViewType]
"""Type of table that the view corresponds to."""
diff --git a/src/braintrust_api/types/view_replace_params.py b/src/braintrust_api/types/view_replace_params.py
index acd3071f..d6cfe513 100755
--- a/src/braintrust_api/types/view_replace_params.py
+++ b/src/braintrust_api/types/view_replace_params.py
@@ -7,6 +7,7 @@
from typing_extensions import Literal, Required, Annotated, TypedDict
from .._utils import PropertyInfo
+from .shared.acl_object_type import ACLObjectType
from .shared_params.view_data import ViewData
from .shared_params.view_options import ViewOptions
@@ -20,26 +21,24 @@ class ViewReplaceParams(TypedDict, total=False):
object_id: Required[str]
"""The id of the object the view applies to"""
- object_type: Required[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ object_type: Required[ACLObjectType]
"""The object type that the ACL applies to"""
view_type: Required[
Optional[
- Literal["projects", "logs", "experiments", "datasets", "prompts", "playgrounds", "experiment", "dataset"]
+ Literal[
+ "projects",
+ "experiments",
+ "experiment",
+ "playgrounds",
+ "playground",
+ "datasets",
+ "dataset",
+ "prompts",
+ "tools",
+ "scorers",
+ "logs",
+ ]
]
]
"""Type of table that the view corresponds to."""
diff --git a/src/braintrust_api/types/view_retrieve_params.py b/src/braintrust_api/types/view_retrieve_params.py
index e9087fc4..2b1d47d6 100755
--- a/src/braintrust_api/types/view_retrieve_params.py
+++ b/src/braintrust_api/types/view_retrieve_params.py
@@ -2,7 +2,9 @@
from __future__ import annotations
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Required, TypedDict
+
+from .shared.acl_object_type import ACLObjectType
__all__ = ["ViewRetrieveParams"]
@@ -11,19 +13,5 @@ class ViewRetrieveParams(TypedDict, total=False):
object_id: Required[str]
"""The id of the object the ACL applies to"""
- object_type: Required[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ object_type: Required[ACLObjectType]
"""The object type that the ACL applies to"""
diff --git a/src/braintrust_api/types/view_update_params.py b/src/braintrust_api/types/view_update_params.py
index c148ef75..1ff88aa3 100755
--- a/src/braintrust_api/types/view_update_params.py
+++ b/src/braintrust_api/types/view_update_params.py
@@ -5,6 +5,7 @@
from typing import Optional
from typing_extensions import Literal, Required, TypedDict
+from .shared.acl_object_type import ACLObjectType
from .shared_params.view_data import ViewData
from .shared_params.view_options import ViewOptions
@@ -15,21 +16,7 @@ class ViewUpdateParams(TypedDict, total=False):
object_id: Required[str]
"""The id of the object the view applies to"""
- object_type: Required[
- Literal[
- "organization",
- "project",
- "experiment",
- "dataset",
- "prompt",
- "prompt_session",
- "group",
- "role",
- "org_member",
- "project_log",
- "org_project",
- ]
- ]
+ object_type: Required[ACLObjectType]
"""The object type that the ACL applies to"""
name: Optional[str]
@@ -45,6 +32,18 @@ class ViewUpdateParams(TypedDict, total=False):
"""The view definition"""
view_type: Optional[
- Literal["projects", "logs", "experiments", "datasets", "prompts", "playgrounds", "experiment", "dataset"]
+ Literal[
+ "projects",
+ "experiments",
+ "experiment",
+ "playgrounds",
+ "playground",
+ "datasets",
+ "dataset",
+ "prompts",
+ "tools",
+ "scorers",
+ "logs",
+ ]
]
"""Type of table that the view corresponds to."""
diff --git a/tests/api_resources/test_evals.py b/tests/api_resources/test_evals.py
index 674dc0a7..2c100576 100644
--- a/tests/api_resources/test_evals.py
+++ b/tests/api_resources/test_evals.py
@@ -30,7 +30,10 @@ def test_method_create(self, client: Braintrust) -> None:
@parametrize
def test_method_create_with_all_params(self, client: Braintrust) -> None:
eval = client.evals.create(
- data={"dataset_id": "dataset_id"},
+ data={
+ "dataset_id": "dataset_id",
+ "_internal_btql": {"foo": "bar"},
+ },
project_id="project_id",
scores=[
{
@@ -52,6 +55,16 @@ def test_method_create_with_all_params(self, client: Braintrust) -> None:
is_public=True,
max_concurrency=0,
metadata={"foo": "bar"},
+ parent={
+ "object_id": "object_id",
+ "object_type": "project_logs",
+ "propagated_event": {"foo": "bar"},
+ "row_ids": {
+ "id": "id",
+ "root_span_id": "root_span_id",
+ "span_id": "span_id",
+ },
+ },
repo_info={
"author_email": "author_email",
"author_name": "author_name",
@@ -116,7 +129,10 @@ async def test_method_create(self, async_client: AsyncBraintrust) -> None:
@parametrize
async def test_method_create_with_all_params(self, async_client: AsyncBraintrust) -> None:
eval = await async_client.evals.create(
- data={"dataset_id": "dataset_id"},
+ data={
+ "dataset_id": "dataset_id",
+ "_internal_btql": {"foo": "bar"},
+ },
project_id="project_id",
scores=[
{
@@ -138,6 +154,16 @@ async def test_method_create_with_all_params(self, async_client: AsyncBraintrust
is_public=True,
max_concurrency=0,
metadata={"foo": "bar"},
+ parent={
+ "object_id": "object_id",
+ "object_type": "project_logs",
+ "propagated_event": {"foo": "bar"},
+ "row_ids": {
+ "id": "id",
+ "root_span_id": "root_span_id",
+ "span_id": "span_id",
+ },
+ },
repo_info={
"author_email": "author_email",
"author_name": "author_name",
diff --git a/tests/api_resources/test_functions.py b/tests/api_resources/test_functions.py
index dfd435b1..2526bb1d 100644
--- a/tests/api_resources/test_functions.py
+++ b/tests/api_resources/test_functions.py
@@ -52,9 +52,11 @@ def test_method_create_with_all_params(self, client: Braintrust) -> None:
"params": {
"frequency_penalty": 0,
"function_call": "auto",
+ "max_completion_tokens": 0,
"max_tokens": 0,
"n": 0,
"presence_penalty": 0,
+ "reasoning_effort": "low",
"response_format": {"type": "json_object"},
"stop": ["string"],
"temperature": 0,
@@ -177,9 +179,11 @@ def test_method_update_with_all_params(self, client: Braintrust) -> None:
"params": {
"frequency_penalty": 0,
"function_call": "auto",
+ "max_completion_tokens": 0,
"max_tokens": 0,
"n": 0,
"presence_penalty": 0,
+ "reasoning_effort": "low",
"response_format": {"type": "json_object"},
"stop": ["string"],
"temperature": 0,
@@ -335,6 +339,7 @@ def test_method_invoke(self, client: Braintrust) -> None:
def test_method_invoke_with_all_params(self, client: Braintrust) -> None:
function = client.functions.invoke(
function_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ expected={},
input={},
messages=[
{
@@ -343,6 +348,7 @@ def test_method_invoke_with_all_params(self, client: Braintrust) -> None:
"name": "name",
}
],
+ metadata={"foo": "bar"},
mode="auto",
parent={
"object_id": "object_id",
@@ -424,9 +430,11 @@ def test_method_replace_with_all_params(self, client: Braintrust) -> None:
"params": {
"frequency_penalty": 0,
"function_call": "auto",
+ "max_completion_tokens": 0,
"max_tokens": 0,
"n": 0,
"presence_penalty": 0,
+ "reasoning_effort": "low",
"response_format": {"type": "json_object"},
"stop": ["string"],
"temperature": 0,
@@ -529,9 +537,11 @@ async def test_method_create_with_all_params(self, async_client: AsyncBraintrust
"params": {
"frequency_penalty": 0,
"function_call": "auto",
+ "max_completion_tokens": 0,
"max_tokens": 0,
"n": 0,
"presence_penalty": 0,
+ "reasoning_effort": "low",
"response_format": {"type": "json_object"},
"stop": ["string"],
"temperature": 0,
@@ -654,9 +664,11 @@ async def test_method_update_with_all_params(self, async_client: AsyncBraintrust
"params": {
"frequency_penalty": 0,
"function_call": "auto",
+ "max_completion_tokens": 0,
"max_tokens": 0,
"n": 0,
"presence_penalty": 0,
+ "reasoning_effort": "low",
"response_format": {"type": "json_object"},
"stop": ["string"],
"temperature": 0,
@@ -812,6 +824,7 @@ async def test_method_invoke(self, async_client: AsyncBraintrust) -> None:
async def test_method_invoke_with_all_params(self, async_client: AsyncBraintrust) -> None:
function = await async_client.functions.invoke(
function_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ expected={},
input={},
messages=[
{
@@ -820,6 +833,7 @@ async def test_method_invoke_with_all_params(self, async_client: AsyncBraintrust
"name": "name",
}
],
+ metadata={"foo": "bar"},
mode="auto",
parent={
"object_id": "object_id",
@@ -901,9 +915,11 @@ async def test_method_replace_with_all_params(self, async_client: AsyncBraintrus
"params": {
"frequency_penalty": 0,
"function_call": "auto",
+ "max_completion_tokens": 0,
"max_tokens": 0,
"n": 0,
"presence_penalty": 0,
+ "reasoning_effort": "low",
"response_format": {"type": "json_object"},
"stop": ["string"],
"temperature": 0,
diff --git a/tests/api_resources/test_project_scores.py b/tests/api_resources/test_project_scores.py
index 1d1aea47..fd720f57 100644
--- a/tests/api_resources/test_project_scores.py
+++ b/tests/api_resources/test_project_scores.py
@@ -40,7 +40,7 @@ def test_method_create_with_all_params(self, client: Braintrust) -> None:
}
],
config={
- "destination": "expected",
+ "destination": "destination",
"multi_select": True,
"online": {
"sampling_rate": 0,
@@ -142,7 +142,7 @@ def test_method_update_with_all_params(self, client: Braintrust) -> None:
}
],
config={
- "destination": "expected",
+ "destination": "destination",
"multi_select": True,
"online": {
"sampling_rate": 0,
@@ -293,7 +293,7 @@ def test_method_replace_with_all_params(self, client: Braintrust) -> None:
}
],
config={
- "destination": "expected",
+ "destination": "destination",
"multi_select": True,
"online": {
"sampling_rate": 0,
@@ -365,7 +365,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncBraintrust
}
],
config={
- "destination": "expected",
+ "destination": "destination",
"multi_select": True,
"online": {
"sampling_rate": 0,
@@ -467,7 +467,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncBraintrust
}
],
config={
- "destination": "expected",
+ "destination": "destination",
"multi_select": True,
"online": {
"sampling_rate": 0,
@@ -618,7 +618,7 @@ async def test_method_replace_with_all_params(self, async_client: AsyncBraintrus
}
],
config={
- "destination": "expected",
+ "destination": "destination",
"multi_select": True,
"online": {
"sampling_rate": 0,
diff --git a/tests/api_resources/test_projects.py b/tests/api_resources/test_projects.py
index 48be7f80..14d8cb3f 100644
--- a/tests/api_resources/test_projects.py
+++ b/tests/api_resources/test_projects.py
@@ -107,7 +107,18 @@ def test_method_update_with_all_params(self, client: Braintrust) -> None:
project = client.projects.update(
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
name="name",
- settings={"comparison_key": "comparison_key"},
+ settings={
+ "baseline_experiment_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "comparison_key": "comparison_key",
+ "span_field_order": [
+ {
+ "column_id": "column_id",
+ "object_type": "object_type",
+ "position": "position",
+ "layout": "full",
+ }
+ ],
+ },
)
assert_matches_type(Project, project, path=["response"])
@@ -310,7 +321,18 @@ async def test_method_update_with_all_params(self, async_client: AsyncBraintrust
project = await async_client.projects.update(
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
name="name",
- settings={"comparison_key": "comparison_key"},
+ settings={
+ "baseline_experiment_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "comparison_key": "comparison_key",
+ "span_field_order": [
+ {
+ "column_id": "column_id",
+ "object_type": "object_type",
+ "position": "position",
+ "layout": "full",
+ }
+ ],
+ },
)
assert_matches_type(Project, project, path=["response"])
diff --git a/tests/api_resources/test_prompts.py b/tests/api_resources/test_prompts.py
index a682924c..596d9e76 100644
--- a/tests/api_resources/test_prompts.py
+++ b/tests/api_resources/test_prompts.py
@@ -41,9 +41,11 @@ def test_method_create_with_all_params(self, client: Braintrust) -> None:
"params": {
"frequency_penalty": 0,
"function_call": "auto",
+ "max_completion_tokens": 0,
"max_tokens": 0,
"n": 0,
"presence_penalty": 0,
+ "reasoning_effort": "low",
"response_format": {"type": "json_object"},
"stop": ["string"],
"temperature": 0,
@@ -163,9 +165,11 @@ def test_method_update_with_all_params(self, client: Braintrust) -> None:
"params": {
"frequency_penalty": 0,
"function_call": "auto",
+ "max_completion_tokens": 0,
"max_tokens": 0,
"n": 0,
"presence_penalty": 0,
+ "reasoning_effort": "low",
"response_format": {"type": "json_object"},
"stop": ["string"],
"temperature": 0,
@@ -334,9 +338,11 @@ def test_method_replace_with_all_params(self, client: Braintrust) -> None:
"params": {
"frequency_penalty": 0,
"function_call": "auto",
+ "max_completion_tokens": 0,
"max_tokens": 0,
"n": 0,
"presence_penalty": 0,
+ "reasoning_effort": "low",
"response_format": {"type": "json_object"},
"stop": ["string"],
"temperature": 0,
@@ -426,9 +432,11 @@ async def test_method_create_with_all_params(self, async_client: AsyncBraintrust
"params": {
"frequency_penalty": 0,
"function_call": "auto",
+ "max_completion_tokens": 0,
"max_tokens": 0,
"n": 0,
"presence_penalty": 0,
+ "reasoning_effort": "low",
"response_format": {"type": "json_object"},
"stop": ["string"],
"temperature": 0,
@@ -548,9 +556,11 @@ async def test_method_update_with_all_params(self, async_client: AsyncBraintrust
"params": {
"frequency_penalty": 0,
"function_call": "auto",
+ "max_completion_tokens": 0,
"max_tokens": 0,
"n": 0,
"presence_penalty": 0,
+ "reasoning_effort": "low",
"response_format": {"type": "json_object"},
"stop": ["string"],
"temperature": 0,
@@ -719,9 +729,11 @@ async def test_method_replace_with_all_params(self, async_client: AsyncBraintrus
"params": {
"frequency_penalty": 0,
"function_call": "auto",
+ "max_completion_tokens": 0,
"max_tokens": 0,
"n": 0,
"presence_penalty": 0,
+ "reasoning_effort": "low",
"response_format": {"type": "json_object"},
"stop": ["string"],
"temperature": 0,
diff --git a/tests/api_resources/test_span_iframes.py b/tests/api_resources/test_span_iframes.py
index 4c6098da..1ccc8585 100644
--- a/tests/api_resources/test_span_iframes.py
+++ b/tests/api_resources/test_span_iframes.py
@@ -115,6 +115,7 @@ def test_method_update(self, client: Braintrust) -> None:
def test_method_update_with_all_params(self, client: Braintrust) -> None:
span_iframe = client.span_iframes.update(
span_iframe_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ description="description",
name="name",
post_message=True,
url="url",
@@ -376,6 +377,7 @@ async def test_method_update(self, async_client: AsyncBraintrust) -> None:
async def test_method_update_with_all_params(self, async_client: AsyncBraintrust) -> None:
span_iframe = await async_client.span_iframes.update(
span_iframe_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ description="description",
name="name",
post_message=True,
url="url",
diff --git a/tests/api_resources/test_views.py b/tests/api_resources/test_views.py
index 734c87df..bfa1a2e0 100644
--- a/tests/api_resources/test_views.py
+++ b/tests/api_resources/test_views.py
@@ -41,6 +41,9 @@ def test_method_create_with_all_params(self, client: Braintrust) -> None:
"column_order": ["string"],
"column_sizing": {"foo": 0},
"column_visibility": {"foo": True},
+ "grouping": "grouping",
+ "layout": "layout",
+ "row_height": "rowHeight",
},
user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
view_data={
@@ -150,6 +153,9 @@ def test_method_update_with_all_params(self, client: Braintrust) -> None:
"column_order": ["string"],
"column_sizing": {"foo": 0},
"column_visibility": {"foo": True},
+ "grouping": "grouping",
+ "layout": "layout",
+ "row_height": "rowHeight",
},
user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
view_data={
@@ -317,6 +323,9 @@ def test_method_replace_with_all_params(self, client: Braintrust) -> None:
"column_order": ["string"],
"column_sizing": {"foo": 0},
"column_visibility": {"foo": True},
+ "grouping": "grouping",
+ "layout": "layout",
+ "row_height": "rowHeight",
},
user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
view_data={
@@ -386,6 +395,9 @@ async def test_method_create_with_all_params(self, async_client: AsyncBraintrust
"column_order": ["string"],
"column_sizing": {"foo": 0},
"column_visibility": {"foo": True},
+ "grouping": "grouping",
+ "layout": "layout",
+ "row_height": "rowHeight",
},
user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
view_data={
@@ -495,6 +507,9 @@ async def test_method_update_with_all_params(self, async_client: AsyncBraintrust
"column_order": ["string"],
"column_sizing": {"foo": 0},
"column_visibility": {"foo": True},
+ "grouping": "grouping",
+ "layout": "layout",
+ "row_height": "rowHeight",
},
user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
view_data={
@@ -662,6 +677,9 @@ async def test_method_replace_with_all_params(self, async_client: AsyncBraintrus
"column_order": ["string"],
"column_sizing": {"foo": 0},
"column_visibility": {"foo": True},
+ "grouping": "grouping",
+ "layout": "layout",
+ "row_height": "rowHeight",
},
user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
view_data={
diff --git a/tests/conftest.py b/tests/conftest.py
index abe496fc..6b67d412 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -10,7 +10,7 @@
from braintrust_api import Braintrust, AsyncBraintrust
if TYPE_CHECKING:
- from _pytest.fixtures import FixtureRequest
+ from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage]
pytest.register_assert_rewrite("tests.utils")
diff --git a/tests/test_client.py b/tests/test_client.py
index a0d792d6..6007cdd7 100755
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -6,6 +6,7 @@
import os
import sys
import json
+import time
import asyncio
import inspect
import subprocess
@@ -22,6 +23,7 @@
from braintrust_api import Braintrust, AsyncBraintrust, APIResponseValidationError
from braintrust_api._types import Omit
+from braintrust_api._utils import maybe_transform
from braintrust_api._models import BaseModel, FinalRequestOptions
from braintrust_api._constants import RAW_RESPONSE_HEADER
from braintrust_api._exceptions import APIStatusError, APITimeoutError, APIResponseValidationError
@@ -31,6 +33,7 @@
BaseClient,
make_request_options,
)
+from braintrust_api.types.project_create_params import ProjectCreateParams
from .utils import update_env
@@ -355,11 +358,11 @@ def test_default_query_option(self) -> None:
FinalRequestOptions(
method="get",
url="/foo",
- params={"foo": "baz", "query_param": "overriden"},
+ params={"foo": "baz", "query_param": "overridden"},
)
)
url = httpx.URL(request.url)
- assert dict(url.params) == {"foo": "baz", "query_param": "overriden"}
+ assert dict(url.params) == {"foo": "baz", "query_param": "overridden"}
def test_request_extra_json(self) -> None:
request = self.client._build_request(
@@ -724,7 +727,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> No
with pytest.raises(APITimeoutError):
self.client.post(
"/v1/project",
- body=cast(object, dict(name="foobar")),
+ body=cast(object, maybe_transform(dict(name="foobar"), ProjectCreateParams)),
cast_to=httpx.Response,
options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
)
@@ -739,7 +742,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> Non
with pytest.raises(APIStatusError):
self.client.post(
"/v1/project",
- body=cast(object, dict(name="foobar")),
+ body=cast(object, maybe_transform(dict(name="foobar"), ProjectCreateParams)),
cast_to=httpx.Response,
options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
)
@@ -1125,11 +1128,11 @@ def test_default_query_option(self) -> None:
FinalRequestOptions(
method="get",
url="/foo",
- params={"foo": "baz", "query_param": "overriden"},
+ params={"foo": "baz", "query_param": "overridden"},
)
)
url = httpx.URL(request.url)
- assert dict(url.params) == {"foo": "baz", "query_param": "overriden"}
+ assert dict(url.params) == {"foo": "baz", "query_param": "overridden"}
def test_request_extra_json(self) -> None:
request = self.client._build_request(
@@ -1500,7 +1503,7 @@ async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter)
with pytest.raises(APITimeoutError):
await self.client.post(
"/v1/project",
- body=cast(object, dict(name="foobar")),
+ body=cast(object, maybe_transform(dict(name="foobar"), ProjectCreateParams)),
cast_to=httpx.Response,
options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
)
@@ -1515,7 +1518,7 @@ async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter)
with pytest.raises(APIStatusError):
await self.client.post(
"/v1/project",
- body=cast(object, dict(name="foobar")),
+ body=cast(object, maybe_transform(dict(name="foobar"), ProjectCreateParams)),
cast_to=httpx.Response,
options={"headers": {RAW_RESPONSE_HEADER: "stream"}},
)
@@ -1618,7 +1621,7 @@ def test_get_platform(self) -> None:
import threading
from braintrust_api._utils import asyncify
- from braintrust_api._base_client import get_platform
+ from braintrust_api._base_client import get_platform
async def test_main() -> None:
result = await asyncify(get_platform)()
@@ -1633,10 +1636,20 @@ async def test_main() -> None:
[sys.executable, "-c", test_code],
text=True,
) as process:
- try:
- process.wait(2)
- if process.returncode:
- raise AssertionError("calling get_platform using asyncify resulted in a non-zero exit code")
- except subprocess.TimeoutExpired as e:
- process.kill()
- raise AssertionError("calling get_platform using asyncify resulted in a hung process") from e
+ timeout = 10 # seconds
+
+ start_time = time.monotonic()
+ while True:
+ return_code = process.poll()
+ if return_code is not None:
+ if return_code != 0:
+ raise AssertionError("calling get_platform using asyncify resulted in a non-zero exit code")
+
+ # success
+ break
+
+ if time.monotonic() - start_time > timeout:
+ process.kill()
+ raise AssertionError("calling get_platform using asyncify resulted in a hung process")
+
+ time.sleep(0.1)
diff --git a/tests/test_models.py b/tests/test_models.py
index a2d58a87..fb862a56 100644
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -1,7 +1,7 @@
import json
from typing import Any, Dict, List, Union, Optional, cast
from datetime import datetime, timezone
-from typing_extensions import Literal, Annotated
+from typing_extensions import Literal, Annotated, TypeAliasType
import pytest
import pydantic
@@ -492,12 +492,15 @@ class Model(BaseModel):
resource_id: Optional[str] = None
m = Model.construct()
+ assert m.resource_id is None
assert "resource_id" not in m.model_fields_set
m = Model.construct(resource_id=None)
+ assert m.resource_id is None
assert "resource_id" in m.model_fields_set
m = Model.construct(resource_id="foo")
+ assert m.resource_id == "foo"
assert "resource_id" in m.model_fields_set
@@ -828,3 +831,61 @@ class B(BaseModel):
# if the discriminator details object stays the same between invocations then
# we hit the cache
assert UnionType.__discriminator__ is discriminator
+
+
+@pytest.mark.skipif(not PYDANTIC_V2, reason="TypeAliasType is not supported in Pydantic v1")
+def test_type_alias_type() -> None:
+ Alias = TypeAliasType("Alias", str) # pyright: ignore
+
+ class Model(BaseModel):
+ alias: Alias
+ union: Union[int, Alias]
+
+ m = construct_type(value={"alias": "foo", "union": "bar"}, type_=Model)
+ assert isinstance(m, Model)
+ assert isinstance(m.alias, str)
+ assert m.alias == "foo"
+ assert isinstance(m.union, str)
+ assert m.union == "bar"
+
+
+@pytest.mark.skipif(not PYDANTIC_V2, reason="TypeAliasType is not supported in Pydantic v1")
+def test_field_named_cls() -> None:
+ class Model(BaseModel):
+ cls: str
+
+ m = construct_type(value={"cls": "foo"}, type_=Model)
+ assert isinstance(m, Model)
+ assert isinstance(m.cls, str)
+
+
+def test_discriminated_union_case() -> None:
+ class A(BaseModel):
+ type: Literal["a"]
+
+ data: bool
+
+ class B(BaseModel):
+ type: Literal["b"]
+
+ data: List[Union[A, object]]
+
+ class ModelA(BaseModel):
+ type: Literal["modelA"]
+
+ data: int
+
+ class ModelB(BaseModel):
+ type: Literal["modelB"]
+
+ required: str
+
+ data: Union[A, B]
+
+ # when constructing ModelA | ModelB, value data doesn't match ModelB exactly - missing `required`
+ m = construct_type(
+ value={"type": "modelB", "data": {"type": "a", "data": True}},
+ type_=cast(Any, Annotated[Union[ModelA, ModelB], PropertyInfo(discriminator="type")]),
+ )
+
+ assert isinstance(m, ModelB)
diff --git a/tests/test_transform.py b/tests/test_transform.py
index d57c2a7e..ebf53ed8 100644
--- a/tests/test_transform.py
+++ b/tests/test_transform.py
@@ -2,13 +2,13 @@
import io
import pathlib
-from typing import Any, List, Union, TypeVar, Iterable, Optional, cast
+from typing import Any, Dict, List, Union, TypeVar, Iterable, Optional, cast
from datetime import date, datetime
from typing_extensions import Required, Annotated, TypedDict
import pytest
-from braintrust_api._types import Base64FileInput
+from braintrust_api._types import NOT_GIVEN, Base64FileInput
from braintrust_api._utils import (
PropertyInfo,
transform as _transform,
@@ -388,6 +388,15 @@ def my_iter() -> Iterable[Baz8]:
}
+@parametrize
+@pytest.mark.asyncio
+async def test_dictionary_items(use_async: bool) -> None:
+ class DictItems(TypedDict):
+ foo_baz: Annotated[str, PropertyInfo(alias="fooBaz")]
+
+ assert await transform({"foo": {"foo_baz": "bar"}}, Dict[str, DictItems], use_async) == {"foo": {"fooBaz": "bar"}}
+
+
class TypedDictIterableUnionStr(TypedDict):
foo: Annotated[Union[str, Iterable[Baz8]], PropertyInfo(alias="FOO")]
@@ -423,3 +432,22 @@ async def test_base64_file_input(use_async: bool) -> None:
assert await transform({"foo": io.BytesIO(b"Hello, world!")}, TypedDictBase64Input, use_async) == {
"foo": "SGVsbG8sIHdvcmxkIQ=="
} # type: ignore[comparison-overlap]
+
+
+@parametrize
+@pytest.mark.asyncio
+async def test_transform_skipping(use_async: bool) -> None:
+ # lists of ints are left as-is
+ data = [1, 2, 3]
+ assert await transform(data, List[int], use_async) is data
+
+ # iterables of ints are converted to a list
+ data = iter([1, 2, 3])
+ assert await transform(data, Iterable[int], use_async) == [1, 2, 3]
+
+
+@parametrize
+@pytest.mark.asyncio
+async def test_strips_notgiven(use_async: bool) -> None:
+ assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"}
+ assert await transform({"foo_bar": NOT_GIVEN}, Foo1, use_async) == {}
diff --git a/tests/test_utils/test_proxy.py b/tests/test_utils/test_proxy.py
index b429bdaf..8a8e94e9 100644
--- a/tests/test_utils/test_proxy.py
+++ b/tests/test_utils/test_proxy.py
@@ -21,3 +21,14 @@ def test_recursive_proxy() -> None:
assert dir(proxy) == []
assert type(proxy).__name__ == "RecursiveLazyProxy"
assert type(operator.attrgetter("name.foo.bar.baz")(proxy)).__name__ == "RecursiveLazyProxy"
+
+
+def test_isinstance_does_not_error() -> None:
+ class AlwaysErrorProxy(LazyProxy[Any]):
+ @override
+ def __load__(self) -> Any:
+ raise RuntimeError("Mocking missing dependency")
+
+ proxy = AlwaysErrorProxy()
+ assert not isinstance(proxy, dict)
+ assert isinstance(proxy, LazyProxy)
diff --git a/tests/utils.py b/tests/utils.py
index 56273e52..5e1b1872 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -16,6 +16,7 @@
is_union_type,
extract_type_arg,
is_annotated_type,
+ is_type_alias_type,
)
from braintrust_api._compat import PYDANTIC_V2, field_outer_type, get_model_fields
from braintrust_api._models import BaseModel
@@ -51,6 +52,9 @@ def assert_matches_type(
path: list[str],
allow_none: bool = False,
) -> None:
+ if is_type_alias_type(type_):
+ type_ = type_.__value__
+
# unwrap `Annotated[T, ...]` -> `T`
if is_annotated_type(type_):
type_ = extract_type_arg(type_, 0)