From f9b35f6d04184131168dde207f7d8dac47a7ecd7 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 20 Mar 2026 03:02:11 +0000
Subject: [PATCH 1/6] fix: sanitize endpoint path params
---
src/formalize/_utils/__init__.py | 1 +
src/formalize/_utils/_path.py | 127 ++++++++++++++++++
.../resources/api/contracts/contracts.py | 6 +-
.../api/contracts/optimization_results.py | 5 +-
.../resources/api/v1/contracts/audit.py | 10 +-
tests/test_utils/test_path.py | 89 ++++++++++++
6 files changed, 228 insertions(+), 10 deletions(-)
create mode 100644 src/formalize/_utils/_path.py
create mode 100644 tests/test_utils/test_path.py
diff --git a/src/formalize/_utils/__init__.py b/src/formalize/_utils/__init__.py
index dc64e29..10cb66d 100644
--- a/src/formalize/_utils/__init__.py
+++ b/src/formalize/_utils/__init__.py
@@ -1,3 +1,4 @@
+from ._path import path_template as path_template
from ._sync import asyncify as asyncify
from ._proxy import LazyProxy as LazyProxy
from ._utils import (
diff --git a/src/formalize/_utils/_path.py b/src/formalize/_utils/_path.py
new file mode 100644
index 0000000..4d6e1e4
--- /dev/null
+++ b/src/formalize/_utils/_path.py
@@ -0,0 +1,127 @@
+from __future__ import annotations
+
+import re
+from typing import (
+ Any,
+ Mapping,
+ Callable,
+)
+from urllib.parse import quote
+
+# Matches '.' or '..' where each dot is either literal or percent-encoded (%2e / %2E).
+_DOT_SEGMENT_RE = re.compile(r"^(?:\.|%2[eE]){1,2}$")
+
+_PLACEHOLDER_RE = re.compile(r"\{(\w+)\}")
+
+
+def _quote_path_segment_part(value: str) -> str:
+ """Percent-encode `value` for use in a URI path segment.
+
+ Considers characters not in `pchar` set from RFC 3986 §3.3 to be unsafe.
+ https://datatracker.ietf.org/doc/html/rfc3986#section-3.3
+ """
+ # quote() already treats unreserved characters (letters, digits, and -._~)
+ # as safe, so we only need to add sub-delims, ':', and '@'.
+ # Notably, unlike the default `safe` for quote(), / is unsafe and must be quoted.
+ return quote(value, safe="!$&'()*+,;=:@")
+
+
+def _quote_query_part(value: str) -> str:
+ """Percent-encode `value` for use in a URI query string.
+
+ Considers &, = and characters not in `query` set from RFC 3986 §3.4 to be unsafe.
+ https://datatracker.ietf.org/doc/html/rfc3986#section-3.4
+ """
+ return quote(value, safe="!$'()*+,;:@/?")
+
+
+def _quote_fragment_part(value: str) -> str:
+ """Percent-encode `value` for use in a URI fragment.
+
+ Considers characters not in `fragment` set from RFC 3986 §3.5 to be unsafe.
+ https://datatracker.ietf.org/doc/html/rfc3986#section-3.5
+ """
+ return quote(value, safe="!$&'()*+,;=:@/?")
+
+
+def _interpolate(
+ template: str,
+ values: Mapping[str, Any],
+ quoter: Callable[[str], str],
+) -> str:
+ """Replace {name} placeholders in `template`, quoting each value with `quoter`.
+
+ Placeholder names are looked up in `values`.
+
+ Raises:
+ KeyError: If a placeholder is not found in `values`.
+ """
+ # re.split with a capturing group returns alternating
+ # [text, name, text, name, ..., text] elements.
+ parts = _PLACEHOLDER_RE.split(template)
+
+ for i in range(1, len(parts), 2):
+ name = parts[i]
+ if name not in values:
+ raise KeyError(f"a value for placeholder {{{name}}} was not provided")
+ val = values[name]
+ if val is None:
+ parts[i] = "null"
+ elif isinstance(val, bool):
+ parts[i] = "true" if val else "false"
+ else:
+ parts[i] = quoter(str(values[name]))
+
+ return "".join(parts)
+
+
+def path_template(template: str, /, **kwargs: Any) -> str:
+ """Interpolate {name} placeholders in `template` from keyword arguments.
+
+ Args:
+ template: The template string containing {name} placeholders.
+ **kwargs: Keyword arguments to interpolate into the template.
+
+ Returns:
+ The template with placeholders interpolated and percent-encoded.
+
+ Safe characters for percent-encoding are dependent on the URI component.
+ Placeholders in path and fragment portions are percent-encoded where the `segment`
+ and `fragment` sets from RFC 3986 respectively are considered safe.
+ Placeholders in the query portion are percent-encoded where the `query` set from
+ RFC 3986 §3.3 is considered safe except for = and & characters.
+
+ Raises:
+ KeyError: If a placeholder is not found in `kwargs`.
+ ValueError: If resulting path contains /./ or /../ segments (including percent-encoded dot-segments).
+ """
+ # Split the template into path, query, and fragment portions.
+ fragment_template: str | None = None
+ query_template: str | None = None
+
+ rest = template
+ if "#" in rest:
+ rest, fragment_template = rest.split("#", 1)
+ if "?" in rest:
+ rest, query_template = rest.split("?", 1)
+ path_template = rest
+
+ # Interpolate each portion with the appropriate quoting rules.
+ path_result = _interpolate(path_template, kwargs, _quote_path_segment_part)
+
+ # Reject dot-segments (. and ..) in the final assembled path. The check
+ # runs after interpolation so that adjacent placeholders or a mix of static
+ # text and placeholders that together form a dot-segment are caught.
+ # Also reject percent-encoded dot-segments to protect against incorrectly
+ # implemented normalization in servers/proxies.
+ for segment in path_result.split("/"):
+ if _DOT_SEGMENT_RE.match(segment):
+ raise ValueError(f"Constructed path {path_result!r} contains dot-segment {segment!r} which is not allowed")
+
+ result = path_result
+ if query_template is not None:
+ result += "?" + _interpolate(query_template, kwargs, _quote_query_part)
+ if fragment_template is not None:
+ result += "#" + _interpolate(fragment_template, kwargs, _quote_fragment_part)
+
+ return result
diff --git a/src/formalize/resources/api/contracts/contracts.py b/src/formalize/resources/api/contracts/contracts.py
index 7b5075c..4f21d0c 100644
--- a/src/formalize/resources/api/contracts/contracts.py
+++ b/src/formalize/resources/api/contracts/contracts.py
@@ -7,7 +7,7 @@
import httpx
from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ...._utils import maybe_transform, async_maybe_transform
+from ...._utils import path_template, maybe_transform, async_maybe_transform
from ...._compat import cached_property
from ...._resource import SyncAPIResource, AsyncAPIResource
from ...._response import (
@@ -88,7 +88,7 @@ def optimize(
if not contract_id:
raise ValueError(f"Expected a non-empty value for `contract_id` but received {contract_id!r}")
return self._post(
- f"/api/contracts/{contract_id}/optimize",
+ path_template("/api/contracts/{contract_id}/optimize", contract_id=contract_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -167,7 +167,7 @@ async def optimize(
if not contract_id:
raise ValueError(f"Expected a non-empty value for `contract_id` but received {contract_id!r}")
return await self._post(
- f"/api/contracts/{contract_id}/optimize",
+ path_template("/api/contracts/{contract_id}/optimize", contract_id=contract_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
diff --git a/src/formalize/resources/api/contracts/optimization_results.py b/src/formalize/resources/api/contracts/optimization_results.py
index 3ac3d8d..85ebd71 100644
--- a/src/formalize/resources/api/contracts/optimization_results.py
+++ b/src/formalize/resources/api/contracts/optimization_results.py
@@ -5,6 +5,7 @@
import httpx
from ...._types import Body, Query, Headers, NotGiven, not_given
+from ...._utils import path_template
from ...._compat import cached_property
from ...._resource import SyncAPIResource, AsyncAPIResource
from ...._response import (
@@ -66,7 +67,7 @@ def retrieve_optimization_results(
if not contract_id:
raise ValueError(f"Expected a non-empty value for `contract_id` but received {contract_id!r}")
return self._get(
- f"/api/contracts/{contract_id}/optimization-results",
+ path_template("/api/contracts/{contract_id}/optimization-results", contract_id=contract_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -122,7 +123,7 @@ async def retrieve_optimization_results(
if not contract_id:
raise ValueError(f"Expected a non-empty value for `contract_id` but received {contract_id!r}")
return await self._get(
- f"/api/contracts/{contract_id}/optimization-results",
+ path_template("/api/contracts/{contract_id}/optimization-results", contract_id=contract_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/src/formalize/resources/api/v1/contracts/audit.py b/src/formalize/resources/api/v1/contracts/audit.py
index c058d61..af2cc00 100644
--- a/src/formalize/resources/api/v1/contracts/audit.py
+++ b/src/formalize/resources/api/v1/contracts/audit.py
@@ -7,7 +7,7 @@
import httpx
from ....._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ....._utils import maybe_transform, async_maybe_transform
+from ....._utils import path_template, maybe_transform, async_maybe_transform
from ....._compat import cached_property
from ....._resource import SyncAPIResource, AsyncAPIResource
from ....._response import (
@@ -81,7 +81,7 @@ def create(
if not contract_id:
raise ValueError(f"Expected a non-empty value for `contract_id` but received {contract_id!r}")
return self._post(
- f"/api/v1/contracts/{contract_id}/audit",
+ path_template("/api/v1/contracts/{contract_id}/audit", contract_id=contract_id),
body=maybe_transform(
{
"inputs": inputs,
@@ -127,7 +127,7 @@ def batch(
if not contract_id:
raise ValueError(f"Expected a non-empty value for `contract_id` but received {contract_id!r}")
return self._post(
- f"/api/v1/contracts/{contract_id}/audit/batch",
+ path_template("/api/v1/contracts/{contract_id}/audit/batch", contract_id=contract_id),
body=maybe_transform(
{
"scenarios": scenarios,
@@ -199,7 +199,7 @@ async def create(
if not contract_id:
raise ValueError(f"Expected a non-empty value for `contract_id` but received {contract_id!r}")
return await self._post(
- f"/api/v1/contracts/{contract_id}/audit",
+ path_template("/api/v1/contracts/{contract_id}/audit", contract_id=contract_id),
body=await async_maybe_transform(
{
"inputs": inputs,
@@ -245,7 +245,7 @@ async def batch(
if not contract_id:
raise ValueError(f"Expected a non-empty value for `contract_id` but received {contract_id!r}")
return await self._post(
- f"/api/v1/contracts/{contract_id}/audit/batch",
+ path_template("/api/v1/contracts/{contract_id}/audit/batch", contract_id=contract_id),
body=await async_maybe_transform(
{
"scenarios": scenarios,
diff --git a/tests/test_utils/test_path.py b/tests/test_utils/test_path.py
new file mode 100644
index 0000000..238e309
--- /dev/null
+++ b/tests/test_utils/test_path.py
@@ -0,0 +1,89 @@
+from __future__ import annotations
+
+from typing import Any
+
+import pytest
+
+from formalize._utils._path import path_template
+
+
+@pytest.mark.parametrize(
+ "template, kwargs, expected",
+ [
+ ("/v1/{id}", dict(id="abc"), "/v1/abc"),
+ ("/v1/{a}/{b}", dict(a="x", b="y"), "/v1/x/y"),
+ ("/v1/{a}{b}/path/{c}?val={d}#{e}", dict(a="x", b="y", c="z", d="u", e="v"), "/v1/xy/path/z?val=u#v"),
+ ("/{w}/{w}", dict(w="echo"), "/echo/echo"),
+ ("/v1/static", {}, "/v1/static"),
+ ("", {}, ""),
+ ("/v1/?q={n}&count=10", dict(n=42), "/v1/?q=42&count=10"),
+ ("/v1/{v}", dict(v=None), "/v1/null"),
+ ("/v1/{v}", dict(v=True), "/v1/true"),
+ ("/v1/{v}", dict(v=False), "/v1/false"),
+ ("/v1/{v}", dict(v=".hidden"), "/v1/.hidden"), # dot prefix ok
+ ("/v1/{v}", dict(v="file.txt"), "/v1/file.txt"), # dot in middle ok
+ ("/v1/{v}", dict(v="..."), "/v1/..."), # triple dot ok
+ ("/v1/{a}{b}", dict(a=".", b="txt"), "/v1/.txt"), # dot var combining with adjacent to be ok
+ ("/items?q={v}#{f}", dict(v=".", f=".."), "/items?q=.#.."), # dots in query/fragment are fine
+ (
+ "/v1/{a}?query={b}",
+ dict(a="../../other/endpoint", b="a&bad=true"),
+ "/v1/..%2F..%2Fother%2Fendpoint?query=a%26bad%3Dtrue",
+ ),
+ ("/v1/{val}", dict(val="a/b/c"), "/v1/a%2Fb%2Fc"),
+ ("/v1/{val}", dict(val="a/b/c?query=value"), "/v1/a%2Fb%2Fc%3Fquery=value"),
+ ("/v1/{val}", dict(val="a/b/c?query=value&bad=true"), "/v1/a%2Fb%2Fc%3Fquery=value&bad=true"),
+ ("/v1/{val}", dict(val="%20"), "/v1/%2520"), # escapes escape sequences in input
+ # Query: slash and ? are safe, # is not
+ ("/items?q={v}", dict(v="a/b"), "/items?q=a/b"),
+ ("/items?q={v}", dict(v="a?b"), "/items?q=a?b"),
+ ("/items?q={v}", dict(v="a#b"), "/items?q=a%23b"),
+ ("/items?q={v}", dict(v="a b"), "/items?q=a%20b"),
+ # Fragment: slash and ? are safe
+ ("/docs#{v}", dict(v="a/b"), "/docs#a/b"),
+ ("/docs#{v}", dict(v="a?b"), "/docs#a?b"),
+ # Path: slash, ? and # are all encoded
+ ("/v1/{v}", dict(v="a/b"), "/v1/a%2Fb"),
+ ("/v1/{v}", dict(v="a?b"), "/v1/a%3Fb"),
+ ("/v1/{v}", dict(v="a#b"), "/v1/a%23b"),
+ # same var encoded differently by component
+ (
+ "/v1/{v}?q={v}#{v}",
+ dict(v="a/b?c#d"),
+ "/v1/a%2Fb%3Fc%23d?q=a/b?c%23d#a/b?c%23d",
+ ),
+ ("/v1/{val}", dict(val="x?admin=true"), "/v1/x%3Fadmin=true"), # query injection
+ ("/v1/{val}", dict(val="x#admin"), "/v1/x%23admin"), # fragment injection
+ ],
+)
+def test_interpolation(template: str, kwargs: dict[str, Any], expected: str) -> None:
+ assert path_template(template, **kwargs) == expected
+
+
+def test_missing_kwarg_raises_key_error() -> None:
+ with pytest.raises(KeyError, match="org_id"):
+ path_template("/v1/{org_id}")
+
+
+@pytest.mark.parametrize(
+ "template, kwargs",
+ [
+ ("{a}/path", dict(a=".")),
+ ("{a}/path", dict(a="..")),
+ ("/v1/{a}", dict(a=".")),
+ ("/v1/{a}", dict(a="..")),
+ ("/v1/{a}/path", dict(a=".")),
+ ("/v1/{a}/path", dict(a="..")),
+ ("/v1/{a}{b}", dict(a=".", b=".")), # adjacent vars → ".."
+ ("/v1/{a}.", dict(a=".")), # var + static → ".."
+ ("/v1/{a}{b}", dict(a="", b=".")), # empty + dot → "."
+ ("/v1/%2e/{x}", dict(x="ok")), # encoded dot in static text
+ ("/v1/%2e./{x}", dict(x="ok")), # mixed encoded ".." in static
+ ("/v1/.%2E/{x}", dict(x="ok")), # mixed encoded ".." in static
+ ("/v1/{v}?q=1", dict(v="..")),
+ ("/v1/{v}#frag", dict(v="..")),
+ ],
+)
+def test_dot_segment_rejected(template: str, kwargs: dict[str, Any]) -> None:
+ with pytest.raises(ValueError, match="dot-segment"):
+ path_template(template, **kwargs)
From 05eef18b272c2be5047fa6c51504fc1e49aca1cb Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 24 Mar 2026 03:43:59 +0000
Subject: [PATCH 2/6] chore(internal): update gitignore
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 95ceb18..3824f4c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
.prism.log
+.stdy.log
_dev
__pycache__
From f3ad8e3e3f5a4f4a49bad8f60ff3202d5e487152 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 25 Mar 2026 02:48:03 +0000
Subject: [PATCH 3/6] chore(ci): skip lint on metadata-only changes
Note that we still want to run tests, as these depend on the metadata.
---
.github/workflows/ci.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c9bf3b9..cb8e282 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -19,7 +19,7 @@ jobs:
timeout-minutes: 10
name: lint
runs-on: ${{ github.repository == 'stainless-sdks/formalize-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
- if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
+ if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata')
steps:
- uses: actions/checkout@v6
@@ -35,7 +35,7 @@ jobs:
run: ./scripts/lint
build:
- if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
+ if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata')
timeout-minutes: 10
name: build
permissions:
From 563c58cb935ec2baf52614b9a2b8f7f2ac4178e7 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 27 Mar 2026 04:47:59 +0000
Subject: [PATCH 4/6] feat(internal): implement indices array format for query
and form serialization
---
src/formalize/_qs.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/formalize/_qs.py b/src/formalize/_qs.py
index ada6fd3..de8c99b 100644
--- a/src/formalize/_qs.py
+++ b/src/formalize/_qs.py
@@ -101,7 +101,10 @@ def _stringify_item(
items.extend(self._stringify_item(key, item, opts))
return items
elif array_format == "indices":
- raise NotImplementedError("The array indices format is not supported yet")
+ items = []
+ for i, item in enumerate(value):
+ items.extend(self._stringify_item(f"{key}[{i}]", item, opts))
+ return items
elif array_format == "brackets":
items = []
key = key + "[]"
From 5da527973b1d2d994bf3dfeccd5e69bc65aa12f5 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 31 Mar 2026 16:47:43 +0000
Subject: [PATCH 5/6] feat: get rid of legacy routes
---
.stats.yml | 6 +-
api.md | 12 -
src/formalize/resources/api/__init__.py | 14 -
src/formalize/resources/api/api.py | 38 ---
.../resources/api/contracts/__init__.py | 33 ---
.../resources/api/contracts/contracts.py | 244 ------------------
.../api/contracts/optimization_results.py | 167 ------------
src/formalize/types/api/__init__.py | 2 -
.../types/api/contract_optimize_params.py | 20 --
tests/api_resources/api/contracts/__init__.py | 1 -
.../contracts/test_optimization_results.py | 111 --------
tests/api_resources/api/test_contracts.py | 133 ----------
12 files changed, 3 insertions(+), 778 deletions(-)
delete mode 100644 src/formalize/resources/api/contracts/__init__.py
delete mode 100644 src/formalize/resources/api/contracts/contracts.py
delete mode 100644 src/formalize/resources/api/contracts/optimization_results.py
delete mode 100644 src/formalize/types/api/contract_optimize_params.py
delete mode 100644 tests/api_resources/api/contracts/__init__.py
delete mode 100644 tests/api_resources/api/contracts/test_optimization_results.py
delete mode 100644 tests/api_resources/api/test_contracts.py
diff --git a/.stats.yml b/.stats.yml
index 0ca8a82..4a1d032 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 4
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/benchify%2Fformalize-68622707ed43c0c2934d378d9c87b746a95967ca3d2764b0889889f771317611.yml
-openapi_spec_hash: e46e13174b96c49dbca07afd1a97c2ed
+configured_endpoints: 2
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/benchify%2Fformalize-f6e0e485f1191c10775d87291f7a76776c2af882ad6a9e32af17e676dde8521e.yml
+openapi_spec_hash: b09b4f07b4f2796145d9a607d6dfa2e5
config_hash: 63fdaff946185aaff06e9fd59a007649
diff --git a/api.md b/api.md
index 2377f5b..c1b78b6 100644
--- a/api.md
+++ b/api.md
@@ -16,15 +16,3 @@ Methods:
- client.api.v1.contracts.audit.create(contract_id, \*\*params) -> AuditCreateResponse
- client.api.v1.contracts.audit.batch(contract_id, \*\*params) -> AuditBatchResponse
-
-## Contracts
-
-Methods:
-
-- client.api.contracts.optimize(contract_id, \*\*params) -> object
-
-### OptimizationResults
-
-Methods:
-
-- client.api.contracts.optimization_results.retrieve_optimization_results(contract_id) -> object
diff --git a/src/formalize/resources/api/__init__.py b/src/formalize/resources/api/__init__.py
index e241e77..c0c6efa 100644
--- a/src/formalize/resources/api/__init__.py
+++ b/src/formalize/resources/api/__init__.py
@@ -16,14 +16,6 @@
APIResourceWithStreamingResponse,
AsyncAPIResourceWithStreamingResponse,
)
-from .contracts import (
- ContractsResource,
- AsyncContractsResource,
- ContractsResourceWithRawResponse,
- AsyncContractsResourceWithRawResponse,
- ContractsResourceWithStreamingResponse,
- AsyncContractsResourceWithStreamingResponse,
-)
__all__ = [
"V1Resource",
@@ -32,12 +24,6 @@
"AsyncV1ResourceWithRawResponse",
"V1ResourceWithStreamingResponse",
"AsyncV1ResourceWithStreamingResponse",
- "ContractsResource",
- "AsyncContractsResource",
- "ContractsResourceWithRawResponse",
- "AsyncContractsResourceWithRawResponse",
- "ContractsResourceWithStreamingResponse",
- "AsyncContractsResourceWithStreamingResponse",
"APIResource",
"AsyncAPIResource",
"APIResourceWithRawResponse",
diff --git a/src/formalize/resources/api/api.py b/src/formalize/resources/api/api.py
index cde3740..8dff72a 100644
--- a/src/formalize/resources/api/api.py
+++ b/src/formalize/resources/api/api.py
@@ -12,14 +12,6 @@
AsyncV1ResourceWithStreamingResponse,
)
from ..._compat import cached_property
-from .contracts.contracts import (
- ContractsResource,
- AsyncContractsResource,
- ContractsResourceWithRawResponse,
- AsyncContractsResourceWithRawResponse,
- ContractsResourceWithStreamingResponse,
- AsyncContractsResourceWithStreamingResponse,
-)
__all__ = ["APIResource", "AsyncAPIResource"]
@@ -29,11 +21,6 @@ class APIResource(_resource.SyncAPIResource):
def v1(self) -> V1Resource:
return V1Resource(self._client)
- @cached_property
- def contracts(self) -> ContractsResource:
- """Contract optimization and AI-powered redline generation"""
- return ContractsResource(self._client)
-
@cached_property
def with_raw_response(self) -> APIResourceWithRawResponse:
"""
@@ -59,11 +46,6 @@ class AsyncAPIResource(_resource.AsyncAPIResource):
def v1(self) -> AsyncV1Resource:
return AsyncV1Resource(self._client)
- @cached_property
- def contracts(self) -> AsyncContractsResource:
- """Contract optimization and AI-powered redline generation"""
- return AsyncContractsResource(self._client)
-
@cached_property
def with_raw_response(self) -> AsyncAPIResourceWithRawResponse:
"""
@@ -92,11 +74,6 @@ def __init__(self, api: APIResource) -> None:
def v1(self) -> V1ResourceWithRawResponse:
return V1ResourceWithRawResponse(self._api.v1)
- @cached_property
- def contracts(self) -> ContractsResourceWithRawResponse:
- """Contract optimization and AI-powered redline generation"""
- return ContractsResourceWithRawResponse(self._api.contracts)
-
class AsyncAPIResourceWithRawResponse:
def __init__(self, api: AsyncAPIResource) -> None:
@@ -106,11 +83,6 @@ def __init__(self, api: AsyncAPIResource) -> None:
def v1(self) -> AsyncV1ResourceWithRawResponse:
return AsyncV1ResourceWithRawResponse(self._api.v1)
- @cached_property
- def contracts(self) -> AsyncContractsResourceWithRawResponse:
- """Contract optimization and AI-powered redline generation"""
- return AsyncContractsResourceWithRawResponse(self._api.contracts)
-
class APIResourceWithStreamingResponse:
def __init__(self, api: APIResource) -> None:
@@ -120,11 +92,6 @@ def __init__(self, api: APIResource) -> None:
def v1(self) -> V1ResourceWithStreamingResponse:
return V1ResourceWithStreamingResponse(self._api.v1)
- @cached_property
- def contracts(self) -> ContractsResourceWithStreamingResponse:
- """Contract optimization and AI-powered redline generation"""
- return ContractsResourceWithStreamingResponse(self._api.contracts)
-
class AsyncAPIResourceWithStreamingResponse:
def __init__(self, api: AsyncAPIResource) -> None:
@@ -133,8 +100,3 @@ def __init__(self, api: AsyncAPIResource) -> None:
@cached_property
def v1(self) -> AsyncV1ResourceWithStreamingResponse:
return AsyncV1ResourceWithStreamingResponse(self._api.v1)
-
- @cached_property
- def contracts(self) -> AsyncContractsResourceWithStreamingResponse:
- """Contract optimization and AI-powered redline generation"""
- return AsyncContractsResourceWithStreamingResponse(self._api.contracts)
diff --git a/src/formalize/resources/api/contracts/__init__.py b/src/formalize/resources/api/contracts/__init__.py
deleted file mode 100644
index 5c20686..0000000
--- a/src/formalize/resources/api/contracts/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .contracts import (
- ContractsResource,
- AsyncContractsResource,
- ContractsResourceWithRawResponse,
- AsyncContractsResourceWithRawResponse,
- ContractsResourceWithStreamingResponse,
- AsyncContractsResourceWithStreamingResponse,
-)
-from .optimization_results import (
- OptimizationResultsResource,
- AsyncOptimizationResultsResource,
- OptimizationResultsResourceWithRawResponse,
- AsyncOptimizationResultsResourceWithRawResponse,
- OptimizationResultsResourceWithStreamingResponse,
- AsyncOptimizationResultsResourceWithStreamingResponse,
-)
-
-__all__ = [
- "OptimizationResultsResource",
- "AsyncOptimizationResultsResource",
- "OptimizationResultsResourceWithRawResponse",
- "AsyncOptimizationResultsResourceWithRawResponse",
- "OptimizationResultsResourceWithStreamingResponse",
- "AsyncOptimizationResultsResourceWithStreamingResponse",
- "ContractsResource",
- "AsyncContractsResource",
- "ContractsResourceWithRawResponse",
- "AsyncContractsResourceWithRawResponse",
- "ContractsResourceWithStreamingResponse",
- "AsyncContractsResourceWithStreamingResponse",
-]
diff --git a/src/formalize/resources/api/contracts/contracts.py b/src/formalize/resources/api/contracts/contracts.py
deleted file mode 100644
index 4f21d0c..0000000
--- a/src/formalize/resources/api/contracts/contracts.py
+++ /dev/null
@@ -1,244 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Optional
-
-import httpx
-
-from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ...._utils import path_template, maybe_transform, async_maybe_transform
-from ...._compat import cached_property
-from ...._resource import SyncAPIResource, AsyncAPIResource
-from ...._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ....types.api import contract_optimize_params
-from ...._base_client import make_request_options
-from .optimization_results import (
- OptimizationResultsResource,
- AsyncOptimizationResultsResource,
- OptimizationResultsResourceWithRawResponse,
- AsyncOptimizationResultsResourceWithRawResponse,
- OptimizationResultsResourceWithStreamingResponse,
- AsyncOptimizationResultsResourceWithStreamingResponse,
-)
-
-__all__ = ["ContractsResource", "AsyncContractsResource"]
-
-
-class ContractsResource(SyncAPIResource):
- """Contract optimization and AI-powered redline generation"""
-
- @cached_property
- def optimization_results(self) -> OptimizationResultsResource:
- """Contract optimization and AI-powered redline generation"""
- return OptimizationResultsResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> ContractsResourceWithRawResponse:
- """
- 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/Benchify/formalize-python#accessing-raw-response-data-eg-headers
- """
- return ContractsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ContractsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/Benchify/formalize-python#with_streaming_response
- """
- return ContractsResourceWithStreamingResponse(self)
-
- def optimize(
- self,
- contract_id: str,
- *,
- analysis_concurrency: int | Omit = omit,
- num_test_inputs: int | Omit = omit,
- output_var: Optional[str] | Omit = omit,
- party_position: str | Omit = omit,
- scope_name: Optional[str] | Omit = omit,
- # 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,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> object:
- """
- Run Optimization
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not contract_id:
- raise ValueError(f"Expected a non-empty value for `contract_id` but received {contract_id!r}")
- return self._post(
- path_template("/api/contracts/{contract_id}/optimize", contract_id=contract_id),
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "analysis_concurrency": analysis_concurrency,
- "num_test_inputs": num_test_inputs,
- "output_var": output_var,
- "party_position": party_position,
- "scope_name": scope_name,
- },
- contract_optimize_params.ContractOptimizeParams,
- ),
- ),
- cast_to=object,
- )
-
-
-class AsyncContractsResource(AsyncAPIResource):
- """Contract optimization and AI-powered redline generation"""
-
- @cached_property
- def optimization_results(self) -> AsyncOptimizationResultsResource:
- """Contract optimization and AI-powered redline generation"""
- return AsyncOptimizationResultsResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> AsyncContractsResourceWithRawResponse:
- """
- 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/Benchify/formalize-python#accessing-raw-response-data-eg-headers
- """
- return AsyncContractsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncContractsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/Benchify/formalize-python#with_streaming_response
- """
- return AsyncContractsResourceWithStreamingResponse(self)
-
- async def optimize(
- self,
- contract_id: str,
- *,
- analysis_concurrency: int | Omit = omit,
- num_test_inputs: int | Omit = omit,
- output_var: Optional[str] | Omit = omit,
- party_position: str | Omit = omit,
- scope_name: Optional[str] | Omit = omit,
- # 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,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> object:
- """
- Run Optimization
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not contract_id:
- raise ValueError(f"Expected a non-empty value for `contract_id` but received {contract_id!r}")
- return await self._post(
- path_template("/api/contracts/{contract_id}/optimize", contract_id=contract_id),
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform(
- {
- "analysis_concurrency": analysis_concurrency,
- "num_test_inputs": num_test_inputs,
- "output_var": output_var,
- "party_position": party_position,
- "scope_name": scope_name,
- },
- contract_optimize_params.ContractOptimizeParams,
- ),
- ),
- cast_to=object,
- )
-
-
-class ContractsResourceWithRawResponse:
- def __init__(self, contracts: ContractsResource) -> None:
- self._contracts = contracts
-
- self.optimize = to_raw_response_wrapper(
- contracts.optimize,
- )
-
- @cached_property
- def optimization_results(self) -> OptimizationResultsResourceWithRawResponse:
- """Contract optimization and AI-powered redline generation"""
- return OptimizationResultsResourceWithRawResponse(self._contracts.optimization_results)
-
-
-class AsyncContractsResourceWithRawResponse:
- def __init__(self, contracts: AsyncContractsResource) -> None:
- self._contracts = contracts
-
- self.optimize = async_to_raw_response_wrapper(
- contracts.optimize,
- )
-
- @cached_property
- def optimization_results(self) -> AsyncOptimizationResultsResourceWithRawResponse:
- """Contract optimization and AI-powered redline generation"""
- return AsyncOptimizationResultsResourceWithRawResponse(self._contracts.optimization_results)
-
-
-class ContractsResourceWithStreamingResponse:
- def __init__(self, contracts: ContractsResource) -> None:
- self._contracts = contracts
-
- self.optimize = to_streamed_response_wrapper(
- contracts.optimize,
- )
-
- @cached_property
- def optimization_results(self) -> OptimizationResultsResourceWithStreamingResponse:
- """Contract optimization and AI-powered redline generation"""
- return OptimizationResultsResourceWithStreamingResponse(self._contracts.optimization_results)
-
-
-class AsyncContractsResourceWithStreamingResponse:
- def __init__(self, contracts: AsyncContractsResource) -> None:
- self._contracts = contracts
-
- self.optimize = async_to_streamed_response_wrapper(
- contracts.optimize,
- )
-
- @cached_property
- def optimization_results(self) -> AsyncOptimizationResultsResourceWithStreamingResponse:
- """Contract optimization and AI-powered redline generation"""
- return AsyncOptimizationResultsResourceWithStreamingResponse(self._contracts.optimization_results)
diff --git a/src/formalize/resources/api/contracts/optimization_results.py b/src/formalize/resources/api/contracts/optimization_results.py
deleted file mode 100644
index 85ebd71..0000000
--- a/src/formalize/resources/api/contracts/optimization_results.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import httpx
-
-from ...._types import Body, Query, Headers, NotGiven, not_given
-from ...._utils import path_template
-from ...._compat import cached_property
-from ...._resource import SyncAPIResource, AsyncAPIResource
-from ...._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ...._base_client import make_request_options
-
-__all__ = ["OptimizationResultsResource", "AsyncOptimizationResultsResource"]
-
-
-class OptimizationResultsResource(SyncAPIResource):
- """Contract optimization and AI-powered redline generation"""
-
- @cached_property
- def with_raw_response(self) -> OptimizationResultsResourceWithRawResponse:
- """
- 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/Benchify/formalize-python#accessing-raw-response-data-eg-headers
- """
- return OptimizationResultsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> OptimizationResultsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/Benchify/formalize-python#with_streaming_response
- """
- return OptimizationResultsResourceWithStreamingResponse(self)
-
- def retrieve_optimization_results(
- self,
- contract_id: str,
- *,
- # 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,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> object:
- """
- Get Optimization Results
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not contract_id:
- raise ValueError(f"Expected a non-empty value for `contract_id` but received {contract_id!r}")
- return self._get(
- path_template("/api/contracts/{contract_id}/optimization-results", contract_id=contract_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=object,
- )
-
-
-class AsyncOptimizationResultsResource(AsyncAPIResource):
- """Contract optimization and AI-powered redline generation"""
-
- @cached_property
- def with_raw_response(self) -> AsyncOptimizationResultsResourceWithRawResponse:
- """
- 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/Benchify/formalize-python#accessing-raw-response-data-eg-headers
- """
- return AsyncOptimizationResultsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncOptimizationResultsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/Benchify/formalize-python#with_streaming_response
- """
- return AsyncOptimizationResultsResourceWithStreamingResponse(self)
-
- async def retrieve_optimization_results(
- self,
- contract_id: str,
- *,
- # 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,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> object:
- """
- Get Optimization Results
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not contract_id:
- raise ValueError(f"Expected a non-empty value for `contract_id` but received {contract_id!r}")
- return await self._get(
- path_template("/api/contracts/{contract_id}/optimization-results", contract_id=contract_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=object,
- )
-
-
-class OptimizationResultsResourceWithRawResponse:
- def __init__(self, optimization_results: OptimizationResultsResource) -> None:
- self._optimization_results = optimization_results
-
- self.retrieve_optimization_results = to_raw_response_wrapper(
- optimization_results.retrieve_optimization_results,
- )
-
-
-class AsyncOptimizationResultsResourceWithRawResponse:
- def __init__(self, optimization_results: AsyncOptimizationResultsResource) -> None:
- self._optimization_results = optimization_results
-
- self.retrieve_optimization_results = async_to_raw_response_wrapper(
- optimization_results.retrieve_optimization_results,
- )
-
-
-class OptimizationResultsResourceWithStreamingResponse:
- def __init__(self, optimization_results: OptimizationResultsResource) -> None:
- self._optimization_results = optimization_results
-
- self.retrieve_optimization_results = to_streamed_response_wrapper(
- optimization_results.retrieve_optimization_results,
- )
-
-
-class AsyncOptimizationResultsResourceWithStreamingResponse:
- def __init__(self, optimization_results: AsyncOptimizationResultsResource) -> None:
- self._optimization_results = optimization_results
-
- self.retrieve_optimization_results = async_to_streamed_response_wrapper(
- optimization_results.retrieve_optimization_results,
- )
diff --git a/src/formalize/types/api/__init__.py b/src/formalize/types/api/__init__.py
index 46d0ef7..f8ee8b1 100644
--- a/src/formalize/types/api/__init__.py
+++ b/src/formalize/types/api/__init__.py
@@ -1,5 +1,3 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from __future__ import annotations
-
-from .contract_optimize_params import ContractOptimizeParams as ContractOptimizeParams
diff --git a/src/formalize/types/api/contract_optimize_params.py b/src/formalize/types/api/contract_optimize_params.py
deleted file mode 100644
index bcce01f..0000000
--- a/src/formalize/types/api/contract_optimize_params.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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 TypedDict
-
-__all__ = ["ContractOptimizeParams"]
-
-
-class ContractOptimizeParams(TypedDict, total=False):
- analysis_concurrency: int
-
- num_test_inputs: int
-
- output_var: Optional[str]
-
- party_position: str
-
- scope_name: Optional[str]
diff --git a/tests/api_resources/api/contracts/__init__.py b/tests/api_resources/api/contracts/__init__.py
deleted file mode 100644
index fd8019a..0000000
--- a/tests/api_resources/api/contracts/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/api/contracts/test_optimization_results.py b/tests/api_resources/api/contracts/test_optimization_results.py
deleted file mode 100644
index 1eaa60d..0000000
--- a/tests/api_resources/api/contracts/test_optimization_results.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from formalize import Formalize, AsyncFormalize
-from tests.utils import assert_matches_type
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestOptimizationResults:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_retrieve_optimization_results(self, client: Formalize) -> None:
- optimization_result = client.api.contracts.optimization_results.retrieve_optimization_results(
- "contract_id",
- )
- assert_matches_type(object, optimization_result, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_retrieve_optimization_results(self, client: Formalize) -> None:
- response = client.api.contracts.optimization_results.with_raw_response.retrieve_optimization_results(
- "contract_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- optimization_result = response.parse()
- assert_matches_type(object, optimization_result, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_retrieve_optimization_results(self, client: Formalize) -> None:
- with client.api.contracts.optimization_results.with_streaming_response.retrieve_optimization_results(
- "contract_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- optimization_result = response.parse()
- assert_matches_type(object, optimization_result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_retrieve_optimization_results(self, client: Formalize) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `contract_id` but received ''"):
- client.api.contracts.optimization_results.with_raw_response.retrieve_optimization_results(
- "",
- )
-
-
-class TestAsyncOptimizationResults:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_retrieve_optimization_results(self, async_client: AsyncFormalize) -> None:
- optimization_result = await async_client.api.contracts.optimization_results.retrieve_optimization_results(
- "contract_id",
- )
- assert_matches_type(object, optimization_result, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_retrieve_optimization_results(self, async_client: AsyncFormalize) -> None:
- response = (
- await async_client.api.contracts.optimization_results.with_raw_response.retrieve_optimization_results(
- "contract_id",
- )
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- optimization_result = await response.parse()
- assert_matches_type(object, optimization_result, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_retrieve_optimization_results(self, async_client: AsyncFormalize) -> None:
- async with (
- async_client.api.contracts.optimization_results.with_streaming_response.retrieve_optimization_results(
- "contract_id",
- )
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- optimization_result = await response.parse()
- assert_matches_type(object, optimization_result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_path_params_retrieve_optimization_results(self, async_client: AsyncFormalize) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `contract_id` but received ''"):
- await async_client.api.contracts.optimization_results.with_raw_response.retrieve_optimization_results(
- "",
- )
diff --git a/tests/api_resources/api/test_contracts.py b/tests/api_resources/api/test_contracts.py
deleted file mode 100644
index 1871abd..0000000
--- a/tests/api_resources/api/test_contracts.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from formalize import Formalize, AsyncFormalize
-from tests.utils import assert_matches_type
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestContracts:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_optimize(self, client: Formalize) -> None:
- contract = client.api.contracts.optimize(
- contract_id="contract_id",
- )
- assert_matches_type(object, contract, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_optimize_with_all_params(self, client: Formalize) -> None:
- contract = client.api.contracts.optimize(
- contract_id="contract_id",
- analysis_concurrency=0,
- num_test_inputs=0,
- output_var="output_var",
- party_position="party_position",
- scope_name="scope_name",
- )
- assert_matches_type(object, contract, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_optimize(self, client: Formalize) -> None:
- response = client.api.contracts.with_raw_response.optimize(
- contract_id="contract_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- contract = response.parse()
- assert_matches_type(object, contract, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_optimize(self, client: Formalize) -> None:
- with client.api.contracts.with_streaming_response.optimize(
- contract_id="contract_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- contract = response.parse()
- assert_matches_type(object, contract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_optimize(self, client: Formalize) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `contract_id` but received ''"):
- client.api.contracts.with_raw_response.optimize(
- contract_id="",
- )
-
-
-class TestAsyncContracts:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_optimize(self, async_client: AsyncFormalize) -> None:
- contract = await async_client.api.contracts.optimize(
- contract_id="contract_id",
- )
- assert_matches_type(object, contract, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_optimize_with_all_params(self, async_client: AsyncFormalize) -> None:
- contract = await async_client.api.contracts.optimize(
- contract_id="contract_id",
- analysis_concurrency=0,
- num_test_inputs=0,
- output_var="output_var",
- party_position="party_position",
- scope_name="scope_name",
- )
- assert_matches_type(object, contract, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_optimize(self, async_client: AsyncFormalize) -> None:
- response = await async_client.api.contracts.with_raw_response.optimize(
- contract_id="contract_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- contract = await response.parse()
- assert_matches_type(object, contract, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_optimize(self, async_client: AsyncFormalize) -> None:
- async with async_client.api.contracts.with_streaming_response.optimize(
- contract_id="contract_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- contract = await response.parse()
- assert_matches_type(object, contract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_path_params_optimize(self, async_client: AsyncFormalize) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `contract_id` but received ''"):
- await async_client.api.contracts.with_raw_response.optimize(
- contract_id="",
- )
From d6084da4b5f5b33867ec2f40a8071f808d21c61e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 31 Mar 2026 16:48:04 +0000
Subject: [PATCH 6/6] release: 1.4.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 20 ++++++++++++++++++++
pyproject.toml | 2 +-
src/formalize/_version.py | 2 +-
4 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 2a8f4ff..3e9af1b 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "1.3.0"
+ ".": "1.4.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 18f9952..6aeb69b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,25 @@
# Changelog
+## 1.4.0 (2026-03-31)
+
+Full Changelog: [v1.3.0...v1.4.0](https://github.com/Benchify/formalize-python/compare/v1.3.0...v1.4.0)
+
+### Features
+
+* get rid of legacy routes ([5da5279](https://github.com/Benchify/formalize-python/commit/5da527973b1d2d994bf3dfeccd5e69bc65aa12f5))
+* **internal:** implement indices array format for query and form serialization ([563c58c](https://github.com/Benchify/formalize-python/commit/563c58cb935ec2baf52614b9a2b8f7f2ac4178e7))
+
+
+### Bug Fixes
+
+* sanitize endpoint path params ([f9b35f6](https://github.com/Benchify/formalize-python/commit/f9b35f6d04184131168dde207f7d8dac47a7ecd7))
+
+
+### Chores
+
+* **ci:** skip lint on metadata-only changes ([f3ad8e3](https://github.com/Benchify/formalize-python/commit/f3ad8e3e3f5a4f4a49bad8f60ff3202d5e487152))
+* **internal:** update gitignore ([05eef18](https://github.com/Benchify/formalize-python/commit/05eef18b272c2be5047fa6c51504fc1e49aca1cb))
+
## 1.3.0 (2026-03-17)
Full Changelog: [v1.2.0...v1.3.0](https://github.com/Benchify/formalize-python/compare/v1.2.0...v1.3.0)
diff --git a/pyproject.toml b/pyproject.toml
index aca0d37..6cf6728 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "benchify"
-version = "1.3.0"
+version = "1.4.0"
description = "The official Python library for the formalize API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/formalize/_version.py b/src/formalize/_version.py
index 7bc1e96..a03222b 100644
--- a/src/formalize/_version.py
+++ b/src/formalize/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "formalize"
-__version__ = "1.3.0" # x-release-please-version
+__version__ = "1.4.0" # x-release-please-version