diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b5898d5..ceb048fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,14 @@ name: CI on: push: - branches-ignore: - - 'generated' - - 'codegen/**' - - 'integrated/**' - - 'stl-preview-head/**' - - 'stl-preview-base/**' + branches: + - '**' + - '!integrated/**' + - '!stl-preview-head/**' + - '!stl-preview-base/**' + - '!generated' + - '!codegen/**' + - 'codegen/stl/**' pull_request: branches-ignore: - 'stl-preview-head/**' @@ -16,10 +18,10 @@ jobs: lint: timeout-minutes: 10 name: lint - runs-on: ${{ github.repository == 'stainless-sdks/m3ter-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + 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 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | @@ -36,15 +38,15 @@ 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: contents: read id-token: write - runs-on: ${{ github.repository == 'stainless-sdks/m3ter-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | @@ -65,7 +67,7 @@ jobs: github.repository == 'stainless-sdks/m3ter-sdk-python' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -82,10 +84,10 @@ jobs: test: timeout-minutes: 10 name: test - runs-on: ${{ github.repository == 'stainless-sdks/m3ter-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 9da16f4f..7d178272 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 727f0501..b0b0dbd8 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'm3ter-com/m3ter-sdk-python' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check release environment run: | diff --git a/.gitignore b/.gitignore index 95ceb189..3824f4c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .prism.log +.stdy.log _dev __pycache__ diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6d78745c..091cfb12 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.9.0" + ".": "0.10.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 4af5e39d..ba1032d6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 286 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/rg%2Fm3ter-sdk-da8df9ce0e1464799f3b9feea8f957a3ca4c016fcba753ec71deb0ee2caf6536.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/rg/m3ter-sdk-8ed00aff39e19053e35301d739d96ff2bafb352273d647c86073ca879a1dad3f.yml openapi_spec_hash: 3e75a21276e7cd06944188f512a7a4e3 -config_hash: 10410ec7acfbc33ee5116775c6714440 +config_hash: 5de7039a6202fb360a3970934cffb50e diff --git a/CHANGELOG.md b/CHANGELOG.md index 099e7e9f..38fbd977 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,54 @@ # Changelog +## 0.10.0 (2026-07-17) + +Full Changelog: [v0.9.0...v0.10.0](https://github.com/m3ter-com/m3ter-sdk-python/compare/v0.9.0...v0.10.0) + +### Features + +* **api:** switch to TypeScript SDK ([57c1e3c](https://github.com/m3ter-com/m3ter-sdk-python/commit/57c1e3c32584a63fbf443ad0ee9826cec6c57948)) +* **internal/types:** support eagerly validating pydantic iterators ([3bc5e23](https://github.com/m3ter-com/m3ter-sdk-python/commit/3bc5e2308d9c72883e96030e5772f1aa2b284fd7)) +* **internal:** implement indices array format for query and form serialization ([3cd118a](https://github.com/m3ter-com/m3ter-sdk-python/commit/3cd118a9bc21161240103b20c337543971085869)) +* **stlc:** configurable CI runner and private-production-repo support in workflow templates ([75e6694](https://github.com/m3ter-com/m3ter-sdk-python/commit/75e6694bd74dd1c17aa1b91831c30fd88721e91c)) +* support setting headers via env ([7abe70c](https://github.com/m3ter-com/m3ter-sdk-python/commit/7abe70c78c984efc97fdf2bdef561b3b4b121a01)) + + +### Bug Fixes + +* **client:** add missing f-string prefix in file type error message ([1189baf](https://github.com/m3ter-com/m3ter-sdk-python/commit/1189baf65f73248e66dadb15c009efd8088893ed)) +* **client:** preserve hardcoded query params when merging with user params ([9a0e3e1](https://github.com/m3ter-com/m3ter-sdk-python/commit/9a0e3e1b22996f808cdb22d4c3758c447d2bbd01)) +* **deps:** bump minimum typing-extensions version ([f4e0bf7](https://github.com/m3ter-com/m3ter-sdk-python/commit/f4e0bf765ad9b9ac52fd1b20961502b0ffb4c5ab)) +* ensure file data are only sent as 1 parameter ([1b3db7b](https://github.com/m3ter-com/m3ter-sdk-python/commit/1b3db7bf3a779a3880b5c1dfef4b0a2d6b0eb8a3)) +* **pydantic:** do not pass `by_alias` unless set ([d1effd7](https://github.com/m3ter-com/m3ter-sdk-python/commit/d1effd76e6d5a03fad1a5d8419ca8b52816b39e9)) +* sanitize endpoint path params ([5e98894](https://github.com/m3ter-com/m3ter-sdk-python/commit/5e988949139bf65480de9f9d2c698fee6e075439)) +* use correct field name format for multipart file arrays ([5688176](https://github.com/m3ter-com/m3ter-sdk-python/commit/56881765eb3db683d4b8f01ecae568d1cc8edd47)) + + +### Performance Improvements + +* **client:** optimize file structure copying in multipart requests ([3e53f72](https://github.com/m3ter-com/m3ter-sdk-python/commit/3e53f729f671160b65b4694a35c3c42501701d91)) + + +### Chores + +* **ci:** skip lint on metadata-only changes ([edf0807](https://github.com/m3ter-com/m3ter-sdk-python/commit/edf08074926089e25f642074a80c5af93cdafc79)) +* **internal:** more robust bootstrap script ([e6be626](https://github.com/m3ter-com/m3ter-sdk-python/commit/e6be6268f7194886718d8aaf4cadf23762ea6bb4)) +* **internal:** reformat pyproject.toml ([b94f0ed](https://github.com/m3ter-com/m3ter-sdk-python/commit/b94f0ed6582d97df147e15a60c94cb07c3e8ca2f)) +* **internal:** tweak CI branches ([8b957b0](https://github.com/m3ter-com/m3ter-sdk-python/commit/8b957b0f1ae1fa8319ef24fc46b53a02f1c1a7e5)) +* **internal:** update gitignore ([82b4984](https://github.com/m3ter-com/m3ter-sdk-python/commit/82b49845738e8adde71e3e754f88a908d038a07e)) +* **tests:** bump steady to v0.19.4 ([d0ef767](https://github.com/m3ter-com/m3ter-sdk-python/commit/d0ef76766537a414720512f10fb4373194cfaf44)) +* **tests:** bump steady to v0.19.5 ([6d6fcb3](https://github.com/m3ter-com/m3ter-sdk-python/commit/6d6fcb3631dbbbe79fdd7761ad9ed71be313b40b)) +* **tests:** bump steady to v0.19.6 ([3d0a67c](https://github.com/m3ter-com/m3ter-sdk-python/commit/3d0a67c9d8f2d14fc1597617cae17f049538bb3b)) +* **tests:** bump steady to v0.19.7 ([12eed8a](https://github.com/m3ter-com/m3ter-sdk-python/commit/12eed8a0fa281e595cbe7d89e25ff45a4eb5268d)) +* **tests:** bump steady to v0.20.1 ([b1f6263](https://github.com/m3ter-com/m3ter-sdk-python/commit/b1f62634a84d9c9caa18728cfe11feffdb406cfa)) +* **tests:** bump steady to v0.20.2 ([2311bd8](https://github.com/m3ter-com/m3ter-sdk-python/commit/2311bd8d4338a46ebef3d47110d078a84479d960)) +* **tests:** bump steady to v0.22.1 ([afb0d6c](https://github.com/m3ter-com/m3ter-sdk-python/commit/afb0d6cc0f6b17f386ba162ffe5dbab68ccd10e2)) + + +### Refactors + +* **tests:** switch from prism to steady ([65a1e47](https://github.com/m3ter-com/m3ter-sdk-python/commit/65a1e47911b86486a1f6b8bd5bc8ae5feb520d15)) + ## 0.9.0 (2026-03-07) Full Changelog: [v0.8.0...v0.9.0](https://github.com/m3ter-com/m3ter-sdk-python/compare/v0.8.0...v0.9.0) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a6013309..7f324c76 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -85,7 +85,7 @@ $ pip install ./path-to-wheel-file.whl ## Running tests -Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. +Most tests require you to [set up a mock server](https://github.com/dgellow/steady) against the OpenAPI spec to run the tests. ```sh $ ./scripts/mock diff --git a/README.md b/README.md index 9180b52b..71b4b7cc 100644 --- a/README.md +++ b/README.md @@ -9,15 +9,6 @@ and offers both synchronous and asynchronous clients powered by [httpx](https:// It is generated with [Stainless](https://www.stainless.com/). -## MCP Server - -Use the M3ter MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application. - -[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=m3ter-sdk-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm0zdGVyLXNkay1tY3AiXSwiZW52Ijp7Ik0zVEVSX0FQSV9LRVkiOiJNeSBBUEkgS2V5IiwiTTNURVJfQVBJX1NFQ1JFVCI6Ik15IEFQSSBTZWNyZXQiLCJNM1RFUl9BUElfVE9LRU4iOiJNeSBUb2tlbiIsIk0zVEVSX09SR19JRCI6Ik15IE9yZyBJRCJ9fQ) -[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22m3ter-sdk-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22m3ter-sdk-mcp%22%5D%2C%22env%22%3A%7B%22M3TER_API_KEY%22%3A%22My%20API%20Key%22%2C%22M3TER_API_SECRET%22%3A%22My%20API%20Secret%22%2C%22M3TER_API_TOKEN%22%3A%22My%20Token%22%2C%22M3TER_ORG_ID%22%3A%22My%20Org%20ID%22%7D%7D) - -> Note: You may need to set environment variables in your MCP client. - ## Documentation The REST API documentation can be found on [www.m3ter.com](https://www.m3ter.com). The full API of this library can be found in [api.md](api.md). diff --git a/pyproject.toml b/pyproject.toml index 7fad8c4c..f677bf61 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "m3ter" -version = "0.9.0" +version = "0.10.0" description = "The official Python library for the m3ter API" dynamic = ["readme"] license = "Apache-2.0" @@ -11,7 +11,7 @@ authors = [ dependencies = [ "httpx>=0.23.0, <1", "pydantic>=1.9.0, <3", - "typing-extensions>=4.10, <5", + "typing-extensions>=4.14, <5", "anyio>=3.5.0, <5", "distro>=1.7.0, <2", "sniffio", @@ -168,7 +168,7 @@ show_error_codes = true # # We also exclude our `tests` as mypy doesn't always infer # types correctly and Pyright will still catch any type errors. -exclude = ['src/m3ter/_files.py', '_dev/.*.py', 'tests/.*'] +exclude = ["src/m3ter/_files.py", "_dev/.*.py", "tests/.*"] strict_equality = true implicit_reexport = true diff --git a/scripts/bootstrap b/scripts/bootstrap index b430fee3..fe8451e4 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,7 +4,7 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { echo -n "==> Install Homebrew dependencies? (y/N): " read -r response diff --git a/scripts/mock b/scripts/mock index bcf3b392..feebe5ed 100755 --- a/scripts/mock +++ b/scripts/mock @@ -19,34 +19,34 @@ fi echo "==> Starting mock server with URL ${URL}" -# Run prism mock on the given spec +# Run steady mock on the given spec if [ "$1" == "--daemon" ]; then # Pre-install the package so the download doesn't eat into the startup timeout - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism --version + npm exec --package=@stdy/cli@0.22.1 -- steady --version - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & + npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log & - # Wait for server to come online (max 30s) + # Wait for server to come online via health endpoint (max 30s) echo -n "Waiting for server" attempts=0 - while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + while ! curl --silent --fail "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1; do + if ! kill -0 $! 2>/dev/null; then + echo + cat .stdy.log + exit 1 + fi attempts=$((attempts + 1)) if [ "$attempts" -ge 300 ]; then echo - echo "Timed out waiting for Prism server to start" - cat .prism.log + echo "Timed out waiting for Steady server to start" + cat .stdy.log exit 1 fi echo -n "." sleep 0.1 done - if grep -q "✖ fatal" ".prism.log"; then - cat .prism.log - exit 1 - fi - echo else - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" + npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" fi diff --git a/scripts/test b/scripts/test index dbeda2d2..19acc916 100755 --- a/scripts/test +++ b/scripts/test @@ -9,8 +9,8 @@ GREEN='\033[0;32m' YELLOW='\033[0;33m' NC='\033[0m' # No Color -function prism_is_running() { - curl --silent "http://localhost:4010" >/dev/null 2>&1 +function steady_is_running() { + curl --silent "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1 } kill_server_on_port() { @@ -25,7 +25,7 @@ function is_overriding_api_base_url() { [ -n "$TEST_API_BASE_URL" ] } -if ! is_overriding_api_base_url && ! prism_is_running ; then +if ! is_overriding_api_base_url && ! steady_is_running ; then # When we exit this script, make sure to kill the background mock server process trap 'kill_server_on_port 4010' EXIT @@ -36,19 +36,19 @@ fi if is_overriding_api_base_url ; then echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" echo -elif ! prism_is_running ; then - echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" +elif ! steady_is_running ; then + echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Steady server" echo -e "running against your OpenAPI spec." echo echo -e "To run the server, pass in the path or url of your OpenAPI" - echo -e "spec to the prism command:" + echo -e "spec to the steady command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.22.1 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}" echo exit 1 else - echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" + echo -e "${GREEN}✔ Mock steady server is running with your OpenAPI spec${NC}" echo fi diff --git a/src/m3ter/_base_client.py b/src/m3ter/_base_client.py index b35740ac..27b87549 100644 --- a/src/m3ter/_base_client.py +++ b/src/m3ter/_base_client.py @@ -540,6 +540,10 @@ def _build_request( files = cast(HttpxRequestFiles, ForceMultipartDict()) prepared_url = self._prepare_url(options.url) + # preserve hard-coded query params from the url + if params and prepared_url.query: + params = {**dict(prepared_url.params.items()), **params} + prepared_url = prepared_url.copy_with(raw_path=prepared_url.raw_path.split(b"?", 1)[0]) if "_" in prepared_url.host: # work around https://github.com/encode/httpx/discussions/2880 kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")} diff --git a/src/m3ter/_client.py b/src/m3ter/_client.py index 39c034d6..1a372a17 100644 --- a/src/m3ter/_client.py +++ b/src/m3ter/_client.py @@ -22,7 +22,11 @@ RequestOptions, not_given, ) -from ._utils import is_given, get_async_library +from ._utils import ( + is_given, + is_mapping_t, + get_async_library, +) from ._compat import cached_property from ._models import FinalRequestOptions from ._version import __version__ @@ -212,6 +216,15 @@ def __init__( if base_url is None: base_url = f"https://api.m3ter.com" + custom_headers_env = os.environ.get("M3TER_CUSTOM_HEADERS") + if custom_headers_env is not None: + parsed: dict[str, str] = {} + for line in custom_headers_env.split("\n"): + colon = line.find(":") + if colon >= 0: + parsed[line[:colon].strip()] = line[colon + 1 :].strip() + default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} + super().__init__( version=__version__, base_url=base_url, @@ -1214,6 +1227,15 @@ def __init__( if base_url is None: base_url = f"https://api.m3ter.com" + custom_headers_env = os.environ.get("M3TER_CUSTOM_HEADERS") + if custom_headers_env is not None: + parsed: dict[str, str] = {} + for line in custom_headers_env.split("\n"): + colon = line.find(":") + if colon >= 0: + parsed[line[:colon].strip()] = line[colon + 1 :].strip() + default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} + super().__init__( version=__version__, base_url=base_url, diff --git a/src/m3ter/_compat.py b/src/m3ter/_compat.py index 786ff42a..e6690a4f 100644 --- a/src/m3ter/_compat.py +++ b/src/m3ter/_compat.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Any, Union, Generic, TypeVar, Callable, cast, overload from datetime import date, datetime -from typing_extensions import Self, Literal +from typing_extensions import Self, Literal, TypedDict import pydantic from pydantic.fields import FieldInfo @@ -131,6 +131,10 @@ def model_json(model: pydantic.BaseModel, *, indent: int | None = None) -> str: return model.model_dump_json(indent=indent) +class _ModelDumpKwargs(TypedDict, total=False): + by_alias: bool + + def model_dump( model: pydantic.BaseModel, *, @@ -142,6 +146,9 @@ def model_dump( by_alias: bool | None = None, ) -> dict[str, Any]: if (not PYDANTIC_V1) or hasattr(model, "model_dump"): + kwargs: _ModelDumpKwargs = {} + if by_alias is not None: + kwargs["by_alias"] = by_alias return model.model_dump( mode=mode, exclude=exclude, @@ -149,7 +156,7 @@ def model_dump( exclude_defaults=exclude_defaults, # warnings are not supported in Pydantic v1 warnings=True if PYDANTIC_V1 else warnings, - by_alias=by_alias, + **kwargs, ) return cast( "dict[str, Any]", diff --git a/src/m3ter/_files.py b/src/m3ter/_files.py index cc14c14f..76da9e08 100644 --- a/src/m3ter/_files.py +++ b/src/m3ter/_files.py @@ -3,8 +3,8 @@ import io import os import pathlib -from typing import overload -from typing_extensions import TypeGuard +from typing import Sequence, cast, overload +from typing_extensions import TypeVar, TypeGuard import anyio @@ -17,7 +17,9 @@ HttpxFileContent, HttpxRequestFiles, ) -from ._utils import is_tuple_t, is_mapping_t, is_sequence_t +from ._utils import is_list, is_mapping, is_tuple_t, is_mapping_t, is_sequence_t + +_T = TypeVar("_T") def is_base64_file_input(obj: object) -> TypeGuard[Base64FileInput]: @@ -97,7 +99,7 @@ async def async_to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles elif is_sequence_t(files): files = [(key, await _async_transform_file(file)) for key, file in files] else: - raise TypeError("Unexpected file type input {type(files)}, expected mapping or sequence") + raise TypeError(f"Unexpected file type input {type(files)}, expected mapping or sequence") return files @@ -121,3 +123,51 @@ async def async_read_file_content(file: FileContent) -> HttpxFileContent: return await anyio.Path(file).read_bytes() return file + + +def deepcopy_with_paths(item: _T, paths: Sequence[Sequence[str]]) -> _T: + """Copy only the containers along the given paths. + + Used to guard against mutation by extract_files without copying the entire structure. + Only dicts and lists that lie on a path are copied; everything else + is returned by reference. + + For example, given paths=[["foo", "files", "file"]] and the structure: + { + "foo": { + "bar": {"baz": {}}, + "files": {"file": } + } + } + The root dict, "foo", and "files" are copied (they lie on the path). + "bar" and "baz" are returned by reference (off the path). + """ + return _deepcopy_with_paths(item, paths, 0) + + +def _deepcopy_with_paths(item: _T, paths: Sequence[Sequence[str]], index: int) -> _T: + if not paths: + return item + if is_mapping(item): + key_to_paths: dict[str, list[Sequence[str]]] = {} + for path in paths: + if index < len(path): + key_to_paths.setdefault(path[index], []).append(path) + + # if no path continues through this mapping, it won't be mutated and copying it is redundant + if not key_to_paths: + return item + + result = dict(item) + for key, subpaths in key_to_paths.items(): + if key in result: + result[key] = _deepcopy_with_paths(result[key], subpaths, index + 1) + return cast(_T, result) + if is_list(item): + array_paths = [path for path in paths if index < len(path) and path[index] == ""] + + # if no path expects a list here, nothing will be mutated inside it - return by reference + if not array_paths: + return cast(_T, item) + return cast(_T, [_deepcopy_with_paths(entry, array_paths, index + 1) for entry in item]) + return item diff --git a/src/m3ter/_models.py b/src/m3ter/_models.py index 29070e05..8c5ab260 100644 --- a/src/m3ter/_models.py +++ b/src/m3ter/_models.py @@ -25,7 +25,9 @@ ClassVar, Protocol, Required, + Annotated, ParamSpec, + TypeAlias, TypedDict, TypeGuard, final, @@ -79,7 +81,15 @@ from ._constants import RAW_RESPONSE_HEADER if TYPE_CHECKING: + from pydantic import GetCoreSchemaHandler, ValidatorFunctionWrapHandler + from pydantic_core import CoreSchema, core_schema from pydantic_core.core_schema import ModelField, ModelSchema, LiteralSchema, ModelFieldsSchema +else: + try: + from pydantic_core import CoreSchema, core_schema + except ImportError: + CoreSchema = None + core_schema = None __all__ = ["BaseModel", "GenericModel"] @@ -396,6 +406,76 @@ def model_dump_json( ) +class _EagerIterable(list[_T], Generic[_T]): + """ + Accepts any Iterable[T] input (including generators), consumes it + eagerly, and validates all items upfront. + + Validation preserves the original container type where possible + (e.g. a set[T] stays a set[T]). Serialization (model_dump / JSON) + always emits a list — round-tripping through model_dump() will not + restore the original container type. + """ + + @classmethod + def __get_pydantic_core_schema__( + cls, + source_type: Any, + handler: GetCoreSchemaHandler, + ) -> CoreSchema: + (item_type,) = get_args(source_type) or (Any,) + item_schema: CoreSchema = handler.generate_schema(item_type) + list_of_items_schema: CoreSchema = core_schema.list_schema(item_schema) + + return core_schema.no_info_wrap_validator_function( + cls._validate, + list_of_items_schema, + serialization=core_schema.plain_serializer_function_ser_schema( + cls._serialize, + info_arg=False, + ), + ) + + @staticmethod + def _validate(v: Iterable[_T], handler: "ValidatorFunctionWrapHandler") -> Any: + original_type: type[Any] = type(v) + + # Normalize to list so list_schema can validate each item + if isinstance(v, list): + items: list[_T] = v + else: + try: + items = list(v) + except TypeError as e: + raise TypeError("Value is not iterable") from e + + # Validate items against the inner schema + validated: list[_T] = handler(items) + + # Reconstruct original container type + if original_type is list: + return validated + # str(list) produces the list's repr, not a string built from items, + # so skip reconstruction for str and its subclasses. + if issubclass(original_type, str): + return validated + try: + return original_type(validated) + except (TypeError, ValueError): + # If the type cannot be reconstructed, just return the validated list + return validated + + @staticmethod + def _serialize(v: Iterable[_T]) -> list[_T]: + """Always serialize as a list so Pydantic's JSON encoder is happy.""" + if isinstance(v, list): + return v + return list(v) + + +EagerIterable: TypeAlias = Annotated[Iterable[_T], _EagerIterable] + + def _construct_field(value: object, field: FieldInfo, key: str) -> object: if value is None: return field_get_default(field) diff --git a/src/m3ter/_qs.py b/src/m3ter/_qs.py index ada6fd3f..4127c19c 100644 --- a/src/m3ter/_qs.py +++ b/src/m3ter/_qs.py @@ -2,17 +2,13 @@ from typing import Any, List, Tuple, Union, Mapping, TypeVar from urllib.parse import parse_qs, urlencode -from typing_extensions import Literal, get_args +from typing_extensions import get_args -from ._types import NotGiven, not_given +from ._types import NotGiven, ArrayFormat, NestedFormat, not_given from ._utils import flatten _T = TypeVar("_T") - -ArrayFormat = Literal["comma", "repeat", "indices", "brackets"] -NestedFormat = Literal["dots", "brackets"] - PrimitiveData = Union[str, int, float, bool, None] # this should be Data = Union[PrimitiveData, "List[Data]", "Tuple[Data]", "Mapping[str, Data]"] # https://github.com/microsoft/pyright/issues/3555 @@ -101,7 +97,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 + "[]" diff --git a/src/m3ter/_types.py b/src/m3ter/_types.py index 5eee9613..9fa7c4ce 100644 --- a/src/m3ter/_types.py +++ b/src/m3ter/_types.py @@ -47,6 +47,9 @@ ModelT = TypeVar("ModelT", bound=pydantic.BaseModel) _T = TypeVar("_T") +ArrayFormat = Literal["comma", "repeat", "indices", "brackets"] +NestedFormat = Literal["dots", "brackets"] + # Approximates httpx internal ProxiesTypes and RequestFiles types # while adding support for `PathLike` instances diff --git a/src/m3ter/_utils/__init__.py b/src/m3ter/_utils/__init__.py index dc64e29a..1c090e51 100644 --- a/src/m3ter/_utils/__init__.py +++ b/src/m3ter/_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 ( @@ -23,7 +24,6 @@ coerce_integer as coerce_integer, file_from_path as file_from_path, strip_not_given as strip_not_given, - deepcopy_minimal as deepcopy_minimal, get_async_library as get_async_library, maybe_coerce_float as maybe_coerce_float, get_required_header as get_required_header, diff --git a/src/m3ter/_utils/_path.py b/src/m3ter/_utils/_path.py new file mode 100644 index 00000000..4d6e1e4c --- /dev/null +++ b/src/m3ter/_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/m3ter/_utils/_utils.py b/src/m3ter/_utils/_utils.py index eec7f4a1..199cd231 100644 --- a/src/m3ter/_utils/_utils.py +++ b/src/m3ter/_utils/_utils.py @@ -17,11 +17,11 @@ ) from pathlib import Path from datetime import date, datetime -from typing_extensions import TypeGuard +from typing_extensions import TypeGuard, get_args import sniffio -from .._types import Omit, NotGiven, FileTypes, HeadersLike +from .._types import Omit, NotGiven, FileTypes, ArrayFormat, HeadersLike _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) @@ -40,25 +40,45 @@ def extract_files( query: Mapping[str, object], *, paths: Sequence[Sequence[str]], + array_format: ArrayFormat = "brackets", ) -> list[tuple[str, FileTypes]]: """Recursively extract files from the given dictionary based on specified paths. A path may look like this ['foo', 'files', '', 'data']. + ``array_format`` controls how ```` segments contribute to the emitted + field name. Supported values: ``"brackets"`` (``foo[]``), ``"repeat"`` and + ``"comma"`` (``foo``), ``"indices"`` (``foo[0]``, ``foo[1]``). + Note: this mutates the given dictionary. """ files: list[tuple[str, FileTypes]] = [] for path in paths: - files.extend(_extract_items(query, path, index=0, flattened_key=None)) + files.extend(_extract_items(query, path, index=0, flattened_key=None, array_format=array_format)) return files +def _array_suffix(array_format: ArrayFormat, array_index: int) -> str: + if array_format == "brackets": + return "[]" + if array_format == "indices": + return f"[{array_index}]" + if array_format == "repeat" or array_format == "comma": + # Both repeat the bare field name for each file part; there is no + # meaningful way to comma-join binary parts. + return "" + raise NotImplementedError( + f"Unknown array_format value: {array_format}, choose from {', '.join(get_args(ArrayFormat))}" + ) + + def _extract_items( obj: object, path: Sequence[str], *, index: int, flattened_key: str | None, + array_format: ArrayFormat, ) -> list[tuple[str, FileTypes]]: try: key = path[index] @@ -75,9 +95,11 @@ def _extract_items( 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))) + for array_index, entry in enumerate(obj): + suffix = _array_suffix(array_format, array_index) + emitted_key = (flattened_key + suffix) if flattened_key else suffix + assert_is_file_content(entry, key=emitted_key) + files.append((emitted_key, cast(FileTypes, entry))) return files assert_is_file_content(obj, key=flattened_key) @@ -86,8 +108,9 @@ def _extract_items( index += 1 if is_dict(obj): try: - # We are at the last entry in the path so we must remove the field - if (len(path)) == index: + # Remove the field if there are no more dict keys in the path, + # only "" traversal markers or end. + if all(p == "" for p in path[index:]): item = obj.pop(key) else: item = obj[key] @@ -105,6 +128,7 @@ def _extract_items( path, index=index, flattened_key=flattened_key, + array_format=array_format, ) elif is_list(obj): if key != "": @@ -116,9 +140,12 @@ def _extract_items( item, path, index=index, - flattened_key=flattened_key + "[]" if flattened_key is not None else "[]", + flattened_key=( + (flattened_key if flattened_key is not None else "") + _array_suffix(array_format, array_index) + ), + array_format=array_format, ) - for item in obj + for array_index, item in enumerate(obj) ] ) @@ -176,21 +203,6 @@ def is_iterable(obj: object) -> TypeGuard[Iterable[object]]: return isinstance(obj, Iterable) -def deepcopy_minimal(item: _T) -> _T: - """Minimal reimplementation of copy.deepcopy() that will only copy certain object types: - - - mappings, e.g. `dict` - - list - - This is done for performance reasons. - """ - if is_mapping(item): - return cast(_T, {k: deepcopy_minimal(v) for k, v in item.items()}) - if is_list(item): - return cast(_T, [deepcopy_minimal(entry) for entry in item]) - return item - - # copied from https://github.com/Rapptz/RoboDanny def human_join(seq: Sequence[str], *, delim: str = ", ", final: str = "or") -> str: size = len(seq) diff --git a/src/m3ter/_version.py b/src/m3ter/_version.py index 1ca1465b..5fb7059d 100644 --- a/src/m3ter/_version.py +++ b/src/m3ter/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "m3ter" -__version__ = "0.9.0" # x-release-please-version +__version__ = "0.10.0" # x-release-please-version diff --git a/src/m3ter/resources/account_plans.py b/src/m3ter/resources/account_plans.py index 06aafe27..b554a4a8 100644 --- a/src/m3ter/resources/account_plans.py +++ b/src/m3ter/resources/account_plans.py @@ -10,7 +10,7 @@ from ..types import account_plan_list_params, account_plan_create_params, account_plan_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -194,7 +194,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/accountplans", + path_template("/organizations/{org_id}/accountplans", org_id=org_id), body=maybe_transform( { "account_id": account_id, @@ -249,7 +249,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/accountplans/{id}", + path_template("/organizations/{org_id}/accountplans/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -384,7 +384,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/accountplans/{id}", + path_template("/organizations/{org_id}/accountplans/{id}", org_id=org_id, id=id), body=maybe_transform( { "account_id": account_id, @@ -497,7 +497,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/accountplans", + path_template("/organizations/{org_id}/accountplans", org_id=org_id), page=SyncCursor[AccountPlanResponse], options=make_request_options( extra_headers=extra_headers, @@ -556,7 +556,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/accountplans/{id}", + path_template("/organizations/{org_id}/accountplans/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -732,7 +732,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/accountplans", + path_template("/organizations/{org_id}/accountplans", org_id=org_id), body=await async_maybe_transform( { "account_id": account_id, @@ -787,7 +787,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/accountplans/{id}", + path_template("/organizations/{org_id}/accountplans/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -922,7 +922,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/accountplans/{id}", + path_template("/organizations/{org_id}/accountplans/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "account_id": account_id, @@ -1035,7 +1035,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/accountplans", + path_template("/organizations/{org_id}/accountplans", org_id=org_id), page=AsyncCursor[AccountPlanResponse], options=make_request_options( extra_headers=extra_headers, @@ -1094,7 +1094,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/accountplans/{id}", + path_template("/organizations/{org_id}/accountplans/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/accounts.py b/src/m3ter/resources/accounts.py index 275e73af..7a0d1e07 100644 --- a/src/m3ter/resources/accounts.py +++ b/src/m3ter/resources/accounts.py @@ -17,7 +17,7 @@ account_end_date_billing_entities_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -224,7 +224,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/accounts", + path_template("/organizations/{org_id}/accounts", org_id=org_id), body=maybe_transform( { "code": code, @@ -281,7 +281,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/accounts/{id}", + path_template("/organizations/{org_id}/accounts/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -448,7 +448,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/accounts/{id}", + path_template("/organizations/{org_id}/accounts/{id}", org_id=org_id, id=id), body=maybe_transform( { "code": code, @@ -515,7 +515,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/accounts", + path_template("/organizations/{org_id}/accounts", org_id=org_id), page=SyncCursor[AccountResponse], options=make_request_options( extra_headers=extra_headers, @@ -568,7 +568,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/accounts/{id}", + path_template("/organizations/{org_id}/accounts/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -626,7 +626,7 @@ def end_date_billing_entities( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/accounts/{id}/enddatebillingentities", + path_template("/organizations/{org_id}/accounts/{id}/enddatebillingentities", org_id=org_id, id=id), body=maybe_transform( { "billing_entities": billing_entities, @@ -674,7 +674,7 @@ def list_children( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get_api_list( - f"/organizations/{org_id}/accounts/{id}/children", + path_template("/organizations/{org_id}/accounts/{id}/children", org_id=org_id, id=id), page=SyncCursor[AccountResponse], options=make_request_options( extra_headers=extra_headers, @@ -765,7 +765,7 @@ def search( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get( - f"/organizations/{org_id}/accounts/search", + path_template("/organizations/{org_id}/accounts/search", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -975,7 +975,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/accounts", + path_template("/organizations/{org_id}/accounts", org_id=org_id), body=await async_maybe_transform( { "code": code, @@ -1032,7 +1032,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/accounts/{id}", + path_template("/organizations/{org_id}/accounts/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1199,7 +1199,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/accounts/{id}", + path_template("/organizations/{org_id}/accounts/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "code": code, @@ -1266,7 +1266,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/accounts", + path_template("/organizations/{org_id}/accounts", org_id=org_id), page=AsyncCursor[AccountResponse], options=make_request_options( extra_headers=extra_headers, @@ -1319,7 +1319,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/accounts/{id}", + path_template("/organizations/{org_id}/accounts/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1377,7 +1377,7 @@ async def end_date_billing_entities( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/accounts/{id}/enddatebillingentities", + path_template("/organizations/{org_id}/accounts/{id}/enddatebillingentities", org_id=org_id, id=id), body=await async_maybe_transform( { "billing_entities": billing_entities, @@ -1425,7 +1425,7 @@ def list_children( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get_api_list( - f"/organizations/{org_id}/accounts/{id}/children", + path_template("/organizations/{org_id}/accounts/{id}/children", org_id=org_id, id=id), page=AsyncCursor[AccountResponse], options=make_request_options( extra_headers=extra_headers, @@ -1516,7 +1516,7 @@ async def search( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._get( - f"/organizations/{org_id}/accounts/search", + path_template("/organizations/{org_id}/accounts/search", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, diff --git a/src/m3ter/resources/aggregations.py b/src/m3ter/resources/aggregations.py index 641f891f..dc4872ec 100644 --- a/src/m3ter/resources/aggregations.py +++ b/src/m3ter/resources/aggregations.py @@ -9,7 +9,7 @@ from ..types import aggregation_list_params, aggregation_create_params, aggregation_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -220,7 +220,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/aggregations", + path_template("/organizations/{org_id}/aggregations", org_id=org_id), body=maybe_transform( { "aggregation": aggregation, @@ -278,7 +278,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/aggregations/{id}", + path_template("/organizations/{org_id}/aggregations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -457,7 +457,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/aggregations/{id}", + path_template("/organizations/{org_id}/aggregations/{id}", org_id=org_id, id=id), body=maybe_transform( { "aggregation": aggregation, @@ -529,7 +529,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/aggregations", + path_template("/organizations/{org_id}/aggregations", org_id=org_id), page=SyncCursor[AggregationResponse], options=make_request_options( extra_headers=extra_headers, @@ -581,7 +581,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/aggregations/{id}", + path_template("/organizations/{org_id}/aggregations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -784,7 +784,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/aggregations", + path_template("/organizations/{org_id}/aggregations", org_id=org_id), body=await async_maybe_transform( { "aggregation": aggregation, @@ -842,7 +842,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/aggregations/{id}", + path_template("/organizations/{org_id}/aggregations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1021,7 +1021,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/aggregations/{id}", + path_template("/organizations/{org_id}/aggregations/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "aggregation": aggregation, @@ -1093,7 +1093,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/aggregations", + path_template("/organizations/{org_id}/aggregations", org_id=org_id), page=AsyncCursor[AggregationResponse], options=make_request_options( extra_headers=extra_headers, @@ -1145,7 +1145,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/aggregations/{id}", + path_template("/organizations/{org_id}/aggregations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/balances/balances.py b/src/m3ter/resources/balances/balances.py index e5158d44..79359464 100644 --- a/src/m3ter/resources/balances/balances.py +++ b/src/m3ter/resources/balances/balances.py @@ -10,7 +10,7 @@ from ...types import balance_list_params, balance_create_params, balance_update_params from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -312,7 +312,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/balances", + path_template("/organizations/{org_id}/balances", org_id=org_id), body=maybe_transform( { "account_id": account_id, @@ -377,7 +377,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/balances/{id}", + path_template("/organizations/{org_id}/balances/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -554,7 +554,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/balances/{id}", + path_template("/organizations/{org_id}/balances/{id}", org_id=org_id, id=id), body=maybe_transform( { "account_id": account_id, @@ -650,7 +650,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/balances", + path_template("/organizations/{org_id}/balances", org_id=org_id), page=SyncCursor[Balance], options=make_request_options( extra_headers=extra_headers, @@ -707,7 +707,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/balances/{id}", + path_template("/organizations/{org_id}/balances/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -977,7 +977,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/balances", + path_template("/organizations/{org_id}/balances", org_id=org_id), body=await async_maybe_transform( { "account_id": account_id, @@ -1042,7 +1042,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/balances/{id}", + path_template("/organizations/{org_id}/balances/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1219,7 +1219,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/balances/{id}", + path_template("/organizations/{org_id}/balances/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "account_id": account_id, @@ -1315,7 +1315,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/balances", + path_template("/organizations/{org_id}/balances", org_id=org_id), page=AsyncCursor[Balance], options=make_request_options( extra_headers=extra_headers, @@ -1372,7 +1372,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/balances/{id}", + path_template("/organizations/{org_id}/balances/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/balances/charge_schedules.py b/src/m3ter/resources/balances/charge_schedules.py index a26d2461..55c22d1c 100644 --- a/src/m3ter/resources/balances/charge_schedules.py +++ b/src/m3ter/resources/balances/charge_schedules.py @@ -9,7 +9,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -169,7 +169,11 @@ def create( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return self._post( - f"/organizations/{org_id}/balances/{balance_id}/balancechargeschedules", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancechargeschedules", + org_id=org_id, + balance_id=balance_id, + ), body=maybe_transform( { "bill_frequency": bill_frequency, @@ -230,7 +234,12 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/{id}", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/{id}", + org_id=org_id, + balance_id=balance_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -348,7 +357,12 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/{id}", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/{id}", + org_id=org_id, + balance_id=balance_id, + id=id, + ), body=maybe_transform( { "bill_frequency": bill_frequency, @@ -413,7 +427,11 @@ def list( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return self._get_api_list( - f"/organizations/{org_id}/balances/{balance_id}/balancechargeschedules", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancechargeschedules", + org_id=org_id, + balance_id=balance_id, + ), page=SyncCursor[ChargeScheduleListResponse], options=make_request_options( extra_headers=extra_headers, @@ -466,7 +484,12 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/{id}", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/{id}", + org_id=org_id, + balance_id=balance_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -590,7 +613,11 @@ def preview( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return self._post( - f"/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/preview", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/preview", + org_id=org_id, + balance_id=balance_id, + ), body=maybe_transform( { "bill_frequency": bill_frequency, @@ -761,7 +788,11 @@ async def create( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return await self._post( - f"/organizations/{org_id}/balances/{balance_id}/balancechargeschedules", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancechargeschedules", + org_id=org_id, + balance_id=balance_id, + ), body=await async_maybe_transform( { "bill_frequency": bill_frequency, @@ -822,7 +853,12 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/{id}", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/{id}", + org_id=org_id, + balance_id=balance_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -940,7 +976,12 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/{id}", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/{id}", + org_id=org_id, + balance_id=balance_id, + id=id, + ), body=await async_maybe_transform( { "bill_frequency": bill_frequency, @@ -1005,7 +1046,11 @@ def list( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return self._get_api_list( - f"/organizations/{org_id}/balances/{balance_id}/balancechargeschedules", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancechargeschedules", + org_id=org_id, + balance_id=balance_id, + ), page=AsyncCursor[ChargeScheduleListResponse], options=make_request_options( extra_headers=extra_headers, @@ -1058,7 +1103,12 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/{id}", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/{id}", + org_id=org_id, + balance_id=balance_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1182,7 +1232,11 @@ async def preview( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return await self._post( - f"/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/preview", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancechargeschedules/preview", + org_id=org_id, + balance_id=balance_id, + ), body=await async_maybe_transform( { "bill_frequency": bill_frequency, diff --git a/src/m3ter/resources/balances/transaction_schedules.py b/src/m3ter/resources/balances/transaction_schedules.py index 9fe6636b..10593354 100644 --- a/src/m3ter/resources/balances/transaction_schedules.py +++ b/src/m3ter/resources/balances/transaction_schedules.py @@ -9,7 +9,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -154,7 +154,11 @@ def create( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return self._post( - f"/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules", + org_id=org_id, + balance_id=balance_id, + ), body=maybe_transform( { "amount": amount, @@ -213,7 +217,12 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/{id}", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/{id}", + org_id=org_id, + balance_id=balance_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -321,7 +330,12 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/{id}", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/{id}", + org_id=org_id, + balance_id=balance_id, + id=id, + ), body=maybe_transform( { "amount": amount, @@ -384,7 +398,11 @@ def list( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return self._get_api_list( - f"/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules", + org_id=org_id, + balance_id=balance_id, + ), page=SyncCursor[ScheduleResponse], options=make_request_options( extra_headers=extra_headers, @@ -437,7 +455,12 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/{id}", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/{id}", + org_id=org_id, + balance_id=balance_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -550,7 +573,11 @@ def preview( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return self._post( - f"/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/preview", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/preview", + org_id=org_id, + balance_id=balance_id, + ), body=maybe_transform( { "amount": amount, @@ -709,7 +736,11 @@ async def create( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return await self._post( - f"/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules", + org_id=org_id, + balance_id=balance_id, + ), body=await async_maybe_transform( { "amount": amount, @@ -768,7 +799,12 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/{id}", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/{id}", + org_id=org_id, + balance_id=balance_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -876,7 +912,12 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/{id}", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/{id}", + org_id=org_id, + balance_id=balance_id, + id=id, + ), body=await async_maybe_transform( { "amount": amount, @@ -939,7 +980,11 @@ def list( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return self._get_api_list( - f"/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules", + org_id=org_id, + balance_id=balance_id, + ), page=AsyncCursor[ScheduleResponse], options=make_request_options( extra_headers=extra_headers, @@ -992,7 +1037,12 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/{id}", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/{id}", + org_id=org_id, + balance_id=balance_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1105,7 +1155,11 @@ async def preview( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return await self._post( - f"/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/preview", + path_template( + "/organizations/{org_id}/balances/{balance_id}/balancetransactionschedules/preview", + org_id=org_id, + balance_id=balance_id, + ), body=await async_maybe_transform( { "amount": amount, diff --git a/src/m3ter/resources/balances/transactions.py b/src/m3ter/resources/balances/transactions.py index 292a131b..27fea589 100644 --- a/src/m3ter/resources/balances/transactions.py +++ b/src/m3ter/resources/balances/transactions.py @@ -9,7 +9,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 ( @@ -156,7 +156,9 @@ def create( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return self._post( - f"/organizations/{org_id}/balances/{balance_id}/transactions", + path_template( + "/organizations/{org_id}/balances/{balance_id}/transactions", org_id=org_id, balance_id=balance_id + ), body=maybe_transform( { "amount": amount, @@ -223,7 +225,9 @@ def list( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return self._get_api_list( - f"/organizations/{org_id}/balances/{balance_id}/transactions", + path_template( + "/organizations/{org_id}/balances/{balance_id}/transactions", org_id=org_id, balance_id=balance_id + ), page=SyncCursor[TransactionResponse], options=make_request_options( extra_headers=extra_headers, @@ -297,7 +301,11 @@ def summary( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return self._get( - f"/organizations/{org_id}/balances/{balance_id}/transactions/summary", + path_template( + "/organizations/{org_id}/balances/{balance_id}/transactions/summary", + org_id=org_id, + balance_id=balance_id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -434,7 +442,9 @@ async def create( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return await self._post( - f"/organizations/{org_id}/balances/{balance_id}/transactions", + path_template( + "/organizations/{org_id}/balances/{balance_id}/transactions", org_id=org_id, balance_id=balance_id + ), body=await async_maybe_transform( { "amount": amount, @@ -501,7 +511,9 @@ def list( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return self._get_api_list( - f"/organizations/{org_id}/balances/{balance_id}/transactions", + path_template( + "/organizations/{org_id}/balances/{balance_id}/transactions", org_id=org_id, balance_id=balance_id + ), page=AsyncCursor[TransactionResponse], options=make_request_options( extra_headers=extra_headers, @@ -575,7 +587,11 @@ async def summary( if not balance_id: raise ValueError(f"Expected a non-empty value for `balance_id` but received {balance_id!r}") return await self._get( - f"/organizations/{org_id}/balances/{balance_id}/transactions/summary", + path_template( + "/organizations/{org_id}/balances/{balance_id}/transactions/summary", + org_id=org_id, + balance_id=balance_id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/bill_config.py b/src/m3ter/resources/bill_config.py index 8d9c4c0f..c3efb90b 100644 --- a/src/m3ter/resources/bill_config.py +++ b/src/m3ter/resources/bill_config.py @@ -9,7 +9,7 @@ from ..types import bill_config_update_params 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 ( @@ -82,7 +82,7 @@ def retrieve( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get( - f"/organizations/{org_id}/billconfig", + path_template("/organizations/{org_id}/billconfig", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -135,7 +135,7 @@ def update( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._put( - f"/organizations/{org_id}/billconfig", + path_template("/organizations/{org_id}/billconfig", org_id=org_id), body=maybe_transform( { "bill_lock_date": bill_lock_date, @@ -208,7 +208,7 @@ async def retrieve( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._get( - f"/organizations/{org_id}/billconfig", + path_template("/organizations/{org_id}/billconfig", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -261,7 +261,7 @@ async def update( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._put( - f"/organizations/{org_id}/billconfig", + path_template("/organizations/{org_id}/billconfig", org_id=org_id), body=await async_maybe_transform( { "bill_lock_date": bill_lock_date, diff --git a/src/m3ter/resources/bill_jobs.py b/src/m3ter/resources/bill_jobs.py index c28010a4..ee8e2c55 100644 --- a/src/m3ter/resources/bill_jobs.py +++ b/src/m3ter/resources/bill_jobs.py @@ -10,7 +10,7 @@ from ..types import bill_job_list_params, bill_job_create_params, bill_job_recalculate_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -214,7 +214,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/billjobs", + path_template("/organizations/{org_id}/billjobs", org_id=org_id), body=maybe_transform( { "account_ids": account_ids, @@ -272,7 +272,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/billjobs/{id}", + path_template("/organizations/{org_id}/billjobs/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -338,7 +338,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/billjobs", + path_template("/organizations/{org_id}/billjobs", org_id=org_id), page=SyncCursor[BillJobResponse], options=make_request_options( extra_headers=extra_headers, @@ -393,7 +393,7 @@ def cancel( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/organizations/{org_id}/billjobs/{id}/cancel", + path_template("/organizations/{org_id}/billjobs/{id}/cancel", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -457,7 +457,7 @@ def recalculate( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/billjobs/recalculate", + path_template("/organizations/{org_id}/billjobs/recalculate", org_id=org_id), body=maybe_transform( { "bill_ids": bill_ids, @@ -659,7 +659,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/billjobs", + path_template("/organizations/{org_id}/billjobs", org_id=org_id), body=await async_maybe_transform( { "account_ids": account_ids, @@ -717,7 +717,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/billjobs/{id}", + path_template("/organizations/{org_id}/billjobs/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -783,7 +783,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/billjobs", + path_template("/organizations/{org_id}/billjobs", org_id=org_id), page=AsyncCursor[BillJobResponse], options=make_request_options( extra_headers=extra_headers, @@ -838,7 +838,7 @@ async def cancel( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/organizations/{org_id}/billjobs/{id}/cancel", + path_template("/organizations/{org_id}/billjobs/{id}/cancel", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -902,7 +902,7 @@ async def recalculate( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/billjobs/recalculate", + path_template("/organizations/{org_id}/billjobs/recalculate", org_id=org_id), body=await async_maybe_transform( { "bill_ids": bill_ids, diff --git a/src/m3ter/resources/bills/bills.py b/src/m3ter/resources/bills/bills.py index b3c4fe3d..2fd0187a 100644 --- a/src/m3ter/resources/bills/bills.py +++ b/src/m3ter/resources/bills/bills.py @@ -16,7 +16,7 @@ bill_latest_by_account_params, ) from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 .line_items import ( LineItemsResource, @@ -148,7 +148,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/bills/{id}", + path_template("/organizations/{org_id}/bills/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -243,7 +243,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/bills", + path_template("/organizations/{org_id}/bills", org_id=org_id), page=SyncCursor[BillResponse], options=make_request_options( extra_headers=extra_headers, @@ -312,7 +312,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/bills/{id}", + path_template("/organizations/{org_id}/bills/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -377,7 +377,7 @@ def approve( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/bills/approve", + path_template("/organizations/{org_id}/bills/approve", org_id=org_id), body=maybe_transform({"bill_ids": bill_ids}, bill_approve_params.BillApproveParams), options=make_request_options( extra_headers=extra_headers, @@ -434,7 +434,7 @@ def latest_by_account( if not account_id: raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") return self._get( - f"/organizations/{org_id}/bills/latest/{account_id}", + path_template("/organizations/{org_id}/bills/latest/{account_id}", org_id=org_id, account_id=account_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -485,7 +485,7 @@ def lock( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/bills/{id}/lock", + path_template("/organizations/{org_id}/bills/{id}/lock", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -565,7 +565,7 @@ def search( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get( - f"/organizations/{org_id}/bills/search", + path_template("/organizations/{org_id}/bills/search", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -624,7 +624,7 @@ def update_status( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/bills/{id}/status", + path_template("/organizations/{org_id}/bills/{id}/status", org_id=org_id, id=id), body=maybe_transform({"status": status}, bill_update_status_params.BillUpdateStatusParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -723,7 +723,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/bills/{id}", + path_template("/organizations/{org_id}/bills/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -818,7 +818,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/bills", + path_template("/organizations/{org_id}/bills", org_id=org_id), page=AsyncCursor[BillResponse], options=make_request_options( extra_headers=extra_headers, @@ -887,7 +887,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/bills/{id}", + path_template("/organizations/{org_id}/bills/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -952,7 +952,7 @@ async def approve( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/bills/approve", + path_template("/organizations/{org_id}/bills/approve", org_id=org_id), body=await async_maybe_transform({"bill_ids": bill_ids}, bill_approve_params.BillApproveParams), options=make_request_options( extra_headers=extra_headers, @@ -1009,7 +1009,7 @@ async def latest_by_account( if not account_id: raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}") return await self._get( - f"/organizations/{org_id}/bills/latest/{account_id}", + path_template("/organizations/{org_id}/bills/latest/{account_id}", org_id=org_id, account_id=account_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -1060,7 +1060,7 @@ async def lock( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/bills/{id}/lock", + path_template("/organizations/{org_id}/bills/{id}/lock", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1140,7 +1140,7 @@ async def search( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._get( - f"/organizations/{org_id}/bills/search", + path_template("/organizations/{org_id}/bills/search", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -1199,7 +1199,7 @@ async def update_status( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/bills/{id}/status", + path_template("/organizations/{org_id}/bills/{id}/status", org_id=org_id, id=id), body=await async_maybe_transform({"status": status}, bill_update_status_params.BillUpdateStatusParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout diff --git a/src/m3ter/resources/bills/credit_line_items.py b/src/m3ter/resources/bills/credit_line_items.py index 6d79612f..13184766 100644 --- a/src/m3ter/resources/bills/credit_line_items.py +++ b/src/m3ter/resources/bills/credit_line_items.py @@ -9,7 +9,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 ( @@ -156,7 +156,7 @@ def create( if not bill_id: raise ValueError(f"Expected a non-empty value for `bill_id` but received {bill_id!r}") return self._post( - f"/organizations/{org_id}/bills/{bill_id}/creditlineitems", + path_template("/organizations/{org_id}/bills/{bill_id}/creditlineitems", org_id=org_id, bill_id=bill_id), body=maybe_transform( { "accounting_product_id": accounting_product_id, @@ -215,7 +215,9 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/bills/{bill_id}/creditlineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/creditlineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -325,7 +327,9 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/bills/{bill_id}/creditlineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/creditlineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), body=maybe_transform( { "accounting_product_id": accounting_product_id, @@ -387,7 +391,7 @@ def list( if not bill_id: raise ValueError(f"Expected a non-empty value for `bill_id` but received {bill_id!r}") return self._get_api_list( - f"/organizations/{org_id}/bills/{bill_id}/creditlineitems", + path_template("/organizations/{org_id}/bills/{bill_id}/creditlineitems", org_id=org_id, bill_id=bill_id), page=SyncCursor[CreditLineItemResponse], options=make_request_options( extra_headers=extra_headers, @@ -439,7 +443,9 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/bills/{bill_id}/creditlineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/creditlineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -577,7 +583,7 @@ async def create( if not bill_id: raise ValueError(f"Expected a non-empty value for `bill_id` but received {bill_id!r}") return await self._post( - f"/organizations/{org_id}/bills/{bill_id}/creditlineitems", + path_template("/organizations/{org_id}/bills/{bill_id}/creditlineitems", org_id=org_id, bill_id=bill_id), body=await async_maybe_transform( { "accounting_product_id": accounting_product_id, @@ -636,7 +642,9 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/bills/{bill_id}/creditlineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/creditlineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -746,7 +754,9 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/bills/{bill_id}/creditlineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/creditlineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), body=await async_maybe_transform( { "accounting_product_id": accounting_product_id, @@ -808,7 +818,7 @@ def list( if not bill_id: raise ValueError(f"Expected a non-empty value for `bill_id` but received {bill_id!r}") return self._get_api_list( - f"/organizations/{org_id}/bills/{bill_id}/creditlineitems", + path_template("/organizations/{org_id}/bills/{bill_id}/creditlineitems", org_id=org_id, bill_id=bill_id), page=AsyncCursor[CreditLineItemResponse], options=make_request_options( extra_headers=extra_headers, @@ -860,7 +870,9 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/bills/{bill_id}/creditlineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/creditlineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/bills/debit_line_items.py b/src/m3ter/resources/bills/debit_line_items.py index 6b762de7..f0b37102 100644 --- a/src/m3ter/resources/bills/debit_line_items.py +++ b/src/m3ter/resources/bills/debit_line_items.py @@ -9,7 +9,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 ( @@ -155,7 +155,7 @@ def create( if not bill_id: raise ValueError(f"Expected a non-empty value for `bill_id` but received {bill_id!r}") return self._post( - f"/organizations/{org_id}/bills/{bill_id}/debitlineitems", + path_template("/organizations/{org_id}/bills/{bill_id}/debitlineitems", org_id=org_id, bill_id=bill_id), body=maybe_transform( { "accounting_product_id": accounting_product_id, @@ -214,7 +214,9 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/bills/{bill_id}/debitlineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/debitlineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -324,7 +326,9 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/bills/{bill_id}/debitlineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/debitlineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), body=maybe_transform( { "accounting_product_id": accounting_product_id, @@ -386,7 +390,7 @@ def list( if not bill_id: raise ValueError(f"Expected a non-empty value for `bill_id` but received {bill_id!r}") return self._get_api_list( - f"/organizations/{org_id}/bills/{bill_id}/debitlineitems", + path_template("/organizations/{org_id}/bills/{bill_id}/debitlineitems", org_id=org_id, bill_id=bill_id), page=SyncCursor[DebitLineItemResponse], options=make_request_options( extra_headers=extra_headers, @@ -438,7 +442,9 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/bills/{bill_id}/debitlineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/debitlineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -575,7 +581,7 @@ async def create( if not bill_id: raise ValueError(f"Expected a non-empty value for `bill_id` but received {bill_id!r}") return await self._post( - f"/organizations/{org_id}/bills/{bill_id}/debitlineitems", + path_template("/organizations/{org_id}/bills/{bill_id}/debitlineitems", org_id=org_id, bill_id=bill_id), body=await async_maybe_transform( { "accounting_product_id": accounting_product_id, @@ -634,7 +640,9 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/bills/{bill_id}/debitlineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/debitlineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -744,7 +752,9 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/bills/{bill_id}/debitlineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/debitlineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), body=await async_maybe_transform( { "accounting_product_id": accounting_product_id, @@ -806,7 +816,7 @@ def list( if not bill_id: raise ValueError(f"Expected a non-empty value for `bill_id` but received {bill_id!r}") return self._get_api_list( - f"/organizations/{org_id}/bills/{bill_id}/debitlineitems", + path_template("/organizations/{org_id}/bills/{bill_id}/debitlineitems", org_id=org_id, bill_id=bill_id), page=AsyncCursor[DebitLineItemResponse], options=make_request_options( extra_headers=extra_headers, @@ -858,7 +868,9 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/bills/{bill_id}/debitlineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/debitlineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/bills/line_items.py b/src/m3ter/resources/bills/line_items.py index 2585fd24..4a8b39b9 100644 --- a/src/m3ter/resources/bills/line_items.py +++ b/src/m3ter/resources/bills/line_items.py @@ -5,7 +5,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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,9 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/bills/{bill_id}/lineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/lineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -145,7 +147,7 @@ def list( if not bill_id: raise ValueError(f"Expected a non-empty value for `bill_id` but received {bill_id!r}") return self._get_api_list( - f"/organizations/{org_id}/bills/{bill_id}/lineitems", + path_template("/organizations/{org_id}/bills/{bill_id}/lineitems", org_id=org_id, bill_id=bill_id), page=SyncCursor[LineItemResponse], options=make_request_options( extra_headers=extra_headers, @@ -231,7 +233,9 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/bills/{bill_id}/lineitems/{id}", + path_template( + "/organizations/{org_id}/bills/{bill_id}/lineitems/{id}", org_id=org_id, bill_id=bill_id, id=id + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -290,7 +294,7 @@ def list( if not bill_id: raise ValueError(f"Expected a non-empty value for `bill_id` but received {bill_id!r}") return self._get_api_list( - f"/organizations/{org_id}/bills/{bill_id}/lineitems", + path_template("/organizations/{org_id}/bills/{bill_id}/lineitems", org_id=org_id, bill_id=bill_id), page=AsyncCursor[LineItemResponse], options=make_request_options( extra_headers=extra_headers, diff --git a/src/m3ter/resources/charges.py b/src/m3ter/resources/charges.py index 7c18df42..95b8c67f 100644 --- a/src/m3ter/resources/charges.py +++ b/src/m3ter/resources/charges.py @@ -10,7 +10,7 @@ from ..types import charge_list_params, charge_create_params, charge_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -176,7 +176,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/charges", + path_template("/organizations/{org_id}/charges", org_id=org_id), body=maybe_transform( { "account_id": account_id, @@ -237,7 +237,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/charges/{id}", + path_template("/organizations/{org_id}/charges/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -351,7 +351,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/charges/{id}", + path_template("/organizations/{org_id}/charges/{id}", org_id=org_id, id=id), body=maybe_transform( { "account_id": account_id, @@ -433,7 +433,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/charges", + path_template("/organizations/{org_id}/charges", org_id=org_id), page=SyncCursor[ChargeListResponse], options=make_request_options( extra_headers=extra_headers, @@ -488,7 +488,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/charges/{id}", + path_template("/organizations/{org_id}/charges/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -642,7 +642,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/charges", + path_template("/organizations/{org_id}/charges", org_id=org_id), body=await async_maybe_transform( { "account_id": account_id, @@ -703,7 +703,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/charges/{id}", + path_template("/organizations/{org_id}/charges/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -817,7 +817,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/charges/{id}", + path_template("/organizations/{org_id}/charges/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "account_id": account_id, @@ -899,7 +899,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/charges", + path_template("/organizations/{org_id}/charges", org_id=org_id), page=AsyncCursor[ChargeListResponse], options=make_request_options( extra_headers=extra_headers, @@ -954,7 +954,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/charges/{id}", + path_template("/organizations/{org_id}/charges/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/commitments.py b/src/m3ter/resources/commitments.py index 28069384..8e0c552f 100644 --- a/src/m3ter/resources/commitments.py +++ b/src/m3ter/resources/commitments.py @@ -10,7 +10,7 @@ from ..types import commitment_list_params, commitment_create_params, commitment_search_params, commitment_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -305,7 +305,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/commitments", + path_template("/organizations/{org_id}/commitments", org_id=org_id), body=maybe_transform( { "account_id": account_id, @@ -378,7 +378,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/commitments/{id}", + path_template("/organizations/{org_id}/commitments/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -610,7 +610,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/commitments/{id}", + path_template("/organizations/{org_id}/commitments/{id}", org_id=org_id, id=id), body=maybe_transform( { "account_id": account_id, @@ -712,7 +712,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/commitments", + path_template("/organizations/{org_id}/commitments", org_id=org_id), page=SyncCursor[CommitmentResponse], options=make_request_options( extra_headers=extra_headers, @@ -772,7 +772,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/commitments/{id}", + path_template("/organizations/{org_id}/commitments/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -853,7 +853,7 @@ def search( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get( - f"/organizations/{org_id}/commitments/search", + path_template("/organizations/{org_id}/commitments/search", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -1152,7 +1152,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/commitments", + path_template("/organizations/{org_id}/commitments", org_id=org_id), body=await async_maybe_transform( { "account_id": account_id, @@ -1225,7 +1225,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/commitments/{id}", + path_template("/organizations/{org_id}/commitments/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1457,7 +1457,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/commitments/{id}", + path_template("/organizations/{org_id}/commitments/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "account_id": account_id, @@ -1559,7 +1559,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/commitments", + path_template("/organizations/{org_id}/commitments", org_id=org_id), page=AsyncCursor[CommitmentResponse], options=make_request_options( extra_headers=extra_headers, @@ -1619,7 +1619,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/commitments/{id}", + path_template("/organizations/{org_id}/commitments/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1700,7 +1700,7 @@ async def search( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._get( - f"/organizations/{org_id}/commitments/search", + path_template("/organizations/{org_id}/commitments/search", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, diff --git a/src/m3ter/resources/compound_aggregations.py b/src/m3ter/resources/compound_aggregations.py index 8e92270b..7ac490b8 100644 --- a/src/m3ter/resources/compound_aggregations.py +++ b/src/m3ter/resources/compound_aggregations.py @@ -13,7 +13,7 @@ compound_aggregation_update_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -189,7 +189,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/compoundaggregations", + path_template("/organizations/{org_id}/compoundaggregations", org_id=org_id), body=maybe_transform( { "calculation": calculation, @@ -246,7 +246,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/compoundaggregations/{id}", + path_template("/organizations/{org_id}/compoundaggregations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -380,7 +380,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/compoundaggregations/{id}", + path_template("/organizations/{org_id}/compoundaggregations/{id}", org_id=org_id, id=id), body=maybe_transform( { "calculation": calculation, @@ -456,7 +456,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/compoundaggregations", + path_template("/organizations/{org_id}/compoundaggregations", org_id=org_id), page=SyncCursor[CompoundAggregationResponse], options=make_request_options( extra_headers=extra_headers, @@ -513,7 +513,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/compoundaggregations/{id}", + path_template("/organizations/{org_id}/compoundaggregations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -680,7 +680,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/compoundaggregations", + path_template("/organizations/{org_id}/compoundaggregations", org_id=org_id), body=await async_maybe_transform( { "calculation": calculation, @@ -737,7 +737,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/compoundaggregations/{id}", + path_template("/organizations/{org_id}/compoundaggregations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -871,7 +871,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/compoundaggregations/{id}", + path_template("/organizations/{org_id}/compoundaggregations/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "calculation": calculation, @@ -947,7 +947,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/compoundaggregations", + path_template("/organizations/{org_id}/compoundaggregations", org_id=org_id), page=AsyncCursor[CompoundAggregationResponse], options=make_request_options( extra_headers=extra_headers, @@ -1004,7 +1004,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/compoundaggregations/{id}", + path_template("/organizations/{org_id}/compoundaggregations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/contracts.py b/src/m3ter/resources/contracts.py index 5eb1c28c..a647d0da 100644 --- a/src/m3ter/resources/contracts.py +++ b/src/m3ter/resources/contracts.py @@ -15,7 +15,7 @@ contract_end_date_billing_entities_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -172,7 +172,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/contracts", + path_template("/organizations/{org_id}/contracts", org_id=org_id), body=maybe_transform( { "account_id": account_id, @@ -229,7 +229,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/contracts/{id}", + path_template("/organizations/{org_id}/contracts/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -353,7 +353,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/contracts/{id}", + path_template("/organizations/{org_id}/contracts/{id}", org_id=org_id, id=id), body=maybe_transform( { "account_id": account_id, @@ -423,7 +423,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/contracts", + path_template("/organizations/{org_id}/contracts", org_id=org_id), page=SyncCursor[ContractResponse], options=make_request_options( extra_headers=extra_headers, @@ -481,7 +481,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/contracts/{id}", + path_template("/organizations/{org_id}/contracts/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -546,7 +546,7 @@ def end_date_billing_entities( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/contracts/{id}/enddatebillingentities", + path_template("/organizations/{org_id}/contracts/{id}/enddatebillingentities", org_id=org_id, id=id), body=maybe_transform( { "billing_entities": billing_entities, @@ -702,7 +702,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/contracts", + path_template("/organizations/{org_id}/contracts", org_id=org_id), body=await async_maybe_transform( { "account_id": account_id, @@ -759,7 +759,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/contracts/{id}", + path_template("/organizations/{org_id}/contracts/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -883,7 +883,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/contracts/{id}", + path_template("/organizations/{org_id}/contracts/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "account_id": account_id, @@ -953,7 +953,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/contracts", + path_template("/organizations/{org_id}/contracts", org_id=org_id), page=AsyncCursor[ContractResponse], options=make_request_options( extra_headers=extra_headers, @@ -1011,7 +1011,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/contracts/{id}", + path_template("/organizations/{org_id}/contracts/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1076,7 +1076,7 @@ async def end_date_billing_entities( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/contracts/{id}/enddatebillingentities", + path_template("/organizations/{org_id}/contracts/{id}/enddatebillingentities", org_id=org_id, id=id), body=await async_maybe_transform( { "billing_entities": billing_entities, diff --git a/src/m3ter/resources/counter_adjustments.py b/src/m3ter/resources/counter_adjustments.py index 92bbb889..a30a17d1 100644 --- a/src/m3ter/resources/counter_adjustments.py +++ b/src/m3ter/resources/counter_adjustments.py @@ -8,7 +8,7 @@ from ..types import counter_adjustment_list_params, counter_adjustment_create_params, counter_adjustment_update_params 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 ( @@ -126,7 +126,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/counteradjustments", + path_template("/organizations/{org_id}/counteradjustments", org_id=org_id), body=maybe_transform( { "account_id": account_id, @@ -175,7 +175,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/counteradjustments/{id}", + path_template("/organizations/{org_id}/counteradjustments/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -249,7 +249,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/counteradjustments/{id}", + path_template("/organizations/{org_id}/counteradjustments/{id}", org_id=org_id, id=id), body=maybe_transform( { "account_id": account_id, @@ -330,7 +330,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/counteradjustments", + path_template("/organizations/{org_id}/counteradjustments", org_id=org_id), page=SyncCursor[CounterAdjustmentResponse], options=make_request_options( extra_headers=extra_headers, @@ -387,7 +387,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/counteradjustments/{id}", + path_template("/organizations/{org_id}/counteradjustments/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -497,7 +497,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/counteradjustments", + path_template("/organizations/{org_id}/counteradjustments", org_id=org_id), body=await async_maybe_transform( { "account_id": account_id, @@ -546,7 +546,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/counteradjustments/{id}", + path_template("/organizations/{org_id}/counteradjustments/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -620,7 +620,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/counteradjustments/{id}", + path_template("/organizations/{org_id}/counteradjustments/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "account_id": account_id, @@ -701,7 +701,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/counteradjustments", + path_template("/organizations/{org_id}/counteradjustments", org_id=org_id), page=AsyncCursor[CounterAdjustmentResponse], options=make_request_options( extra_headers=extra_headers, @@ -758,7 +758,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/counteradjustments/{id}", + path_template("/organizations/{org_id}/counteradjustments/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/counter_pricings.py b/src/m3ter/resources/counter_pricings.py index 6e7fe8f4..0b813613 100644 --- a/src/m3ter/resources/counter_pricings.py +++ b/src/m3ter/resources/counter_pricings.py @@ -9,7 +9,7 @@ from ..types import counter_pricing_list_params, counter_pricing_create_params, counter_pricing_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -187,7 +187,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/counterpricings", + path_template("/organizations/{org_id}/counterpricings", org_id=org_id), body=maybe_transform( { "counter_id": counter_id, @@ -245,7 +245,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/counterpricings/{id}", + path_template("/organizations/{org_id}/counterpricings/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -388,7 +388,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/counterpricings/{id}", + path_template("/organizations/{org_id}/counterpricings/{id}", org_id=org_id, id=id), body=maybe_transform( { "counter_id": counter_id, @@ -462,7 +462,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/counterpricings", + path_template("/organizations/{org_id}/counterpricings", org_id=org_id), page=SyncCursor[CounterPricingResponse], options=make_request_options( extra_headers=extra_headers, @@ -515,7 +515,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/counterpricings/{id}", + path_template("/organizations/{org_id}/counterpricings/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -684,7 +684,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/counterpricings", + path_template("/organizations/{org_id}/counterpricings", org_id=org_id), body=await async_maybe_transform( { "counter_id": counter_id, @@ -742,7 +742,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/counterpricings/{id}", + path_template("/organizations/{org_id}/counterpricings/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -885,7 +885,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/counterpricings/{id}", + path_template("/organizations/{org_id}/counterpricings/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "counter_id": counter_id, @@ -959,7 +959,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/counterpricings", + path_template("/organizations/{org_id}/counterpricings", org_id=org_id), page=AsyncCursor[CounterPricingResponse], options=make_request_options( extra_headers=extra_headers, @@ -1012,7 +1012,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/counterpricings/{id}", + path_template("/organizations/{org_id}/counterpricings/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/counters.py b/src/m3ter/resources/counters.py index 50eb8777..dbe2dbd2 100644 --- a/src/m3ter/resources/counters.py +++ b/src/m3ter/resources/counters.py @@ -6,7 +6,7 @@ from ..types import counter_list_params, counter_create_params, counter_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -105,7 +105,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/counters", + path_template("/organizations/{org_id}/counters", org_id=org_id), body=maybe_transform( { "name": name, @@ -153,7 +153,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/counters/{id}", + path_template("/organizations/{org_id}/counters/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -217,7 +217,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/counters/{id}", + path_template("/organizations/{org_id}/counters/{id}", org_id=org_id, id=id), body=maybe_transform( { "name": name, @@ -279,7 +279,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/counters", + path_template("/organizations/{org_id}/counters", org_id=org_id), page=SyncCursor[CounterResponse], options=make_request_options( extra_headers=extra_headers, @@ -331,7 +331,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/counters/{id}", + path_template("/organizations/{org_id}/counters/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -422,7 +422,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/counters", + path_template("/organizations/{org_id}/counters", org_id=org_id), body=await async_maybe_transform( { "name": name, @@ -470,7 +470,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/counters/{id}", + path_template("/organizations/{org_id}/counters/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -534,7 +534,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/counters/{id}", + path_template("/organizations/{org_id}/counters/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "name": name, @@ -596,7 +596,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/counters", + path_template("/organizations/{org_id}/counters", org_id=org_id), page=AsyncCursor[CounterResponse], options=make_request_options( extra_headers=extra_headers, @@ -648,7 +648,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/counters/{id}", + path_template("/organizations/{org_id}/counters/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/credit_reasons.py b/src/m3ter/resources/credit_reasons.py index 8efc3b55..51014bd4 100644 --- a/src/m3ter/resources/credit_reasons.py +++ b/src/m3ter/resources/credit_reasons.py @@ -6,7 +6,7 @@ from ..types import credit_reason_list_params, credit_reason_create_params, credit_reason_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -104,7 +104,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/picklists/creditreasons", + path_template("/organizations/{org_id}/picklists/creditreasons", org_id=org_id), body=maybe_transform( { "name": name, @@ -151,7 +151,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/picklists/creditreasons/{id}", + path_template("/organizations/{org_id}/picklists/creditreasons/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -213,7 +213,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/picklists/creditreasons/{id}", + path_template("/organizations/{org_id}/picklists/creditreasons/{id}", org_id=org_id, id=id), body=maybe_transform( { "name": name, @@ -279,7 +279,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/picklists/creditreasons", + path_template("/organizations/{org_id}/picklists/creditreasons", org_id=org_id), page=SyncCursor[CreditReasonResponse], options=make_request_options( extra_headers=extra_headers, @@ -331,7 +331,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/picklists/creditreasons/{id}", + path_template("/organizations/{org_id}/picklists/creditreasons/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -421,7 +421,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/picklists/creditreasons", + path_template("/organizations/{org_id}/picklists/creditreasons", org_id=org_id), body=await async_maybe_transform( { "name": name, @@ -468,7 +468,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/picklists/creditreasons/{id}", + path_template("/organizations/{org_id}/picklists/creditreasons/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -530,7 +530,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/picklists/creditreasons/{id}", + path_template("/organizations/{org_id}/picklists/creditreasons/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "name": name, @@ -596,7 +596,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/picklists/creditreasons", + path_template("/organizations/{org_id}/picklists/creditreasons", org_id=org_id), page=AsyncCursor[CreditReasonResponse], options=make_request_options( extra_headers=extra_headers, @@ -648,7 +648,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/picklists/creditreasons/{id}", + path_template("/organizations/{org_id}/picklists/creditreasons/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/currencies.py b/src/m3ter/resources/currencies.py index 5585f443..b2a67f5d 100644 --- a/src/m3ter/resources/currencies.py +++ b/src/m3ter/resources/currencies.py @@ -8,7 +8,7 @@ from ..types import currency_list_params, currency_create_params, currency_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -118,7 +118,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/picklists/currency", + path_template("/organizations/{org_id}/picklists/currency", org_id=org_id), body=maybe_transform( { "name": name, @@ -169,7 +169,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/picklists/currency/{id}", + path_template("/organizations/{org_id}/picklists/currency/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -241,7 +241,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/picklists/currency/{id}", + path_template("/organizations/{org_id}/picklists/currency/{id}", org_id=org_id, id=id), body=maybe_transform( { "name": name, @@ -313,7 +313,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/picklists/currency", + path_template("/organizations/{org_id}/picklists/currency", org_id=org_id), page=SyncCursor[CurrencyResponse], options=make_request_options( extra_headers=extra_headers, @@ -368,7 +368,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/picklists/currency/{id}", + path_template("/organizations/{org_id}/picklists/currency/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -470,7 +470,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/picklists/currency", + path_template("/organizations/{org_id}/picklists/currency", org_id=org_id), body=await async_maybe_transform( { "name": name, @@ -521,7 +521,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/picklists/currency/{id}", + path_template("/organizations/{org_id}/picklists/currency/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -593,7 +593,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/picklists/currency/{id}", + path_template("/organizations/{org_id}/picklists/currency/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "name": name, @@ -665,7 +665,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/picklists/currency", + path_template("/organizations/{org_id}/picklists/currency", org_id=org_id), page=AsyncCursor[CurrencyResponse], options=make_request_options( extra_headers=extra_headers, @@ -720,7 +720,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/picklists/currency/{id}", + path_template("/organizations/{org_id}/picklists/currency/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/custom_fields.py b/src/m3ter/resources/custom_fields.py index 6615e2f9..ca12cd1e 100644 --- a/src/m3ter/resources/custom_fields.py +++ b/src/m3ter/resources/custom_fields.py @@ -8,7 +8,7 @@ from ..types import custom_field_update_params 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 ( @@ -127,7 +127,7 @@ def retrieve( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get( - f"/organizations/{org_id}/customfields", + path_template("/organizations/{org_id}/customfields", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -203,7 +203,7 @@ def update( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._put( - f"/organizations/{org_id}/customfields", + path_template("/organizations/{org_id}/customfields", org_id=org_id), body=maybe_transform( { "account": account, @@ -331,7 +331,7 @@ async def retrieve( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._get( - f"/organizations/{org_id}/customfields", + path_template("/organizations/{org_id}/customfields", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -407,7 +407,7 @@ async def update( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._put( - f"/organizations/{org_id}/customfields", + path_template("/organizations/{org_id}/customfields", org_id=org_id), body=await async_maybe_transform( { "account": account, diff --git a/src/m3ter/resources/data_exports/data_exports.py b/src/m3ter/resources/data_exports/data_exports.py index 7c56bd89..2c84ace4 100644 --- a/src/m3ter/resources/data_exports/data_exports.py +++ b/src/m3ter/resources/data_exports/data_exports.py @@ -18,7 +18,7 @@ ) from ...types import data_export_create_adhoc_params from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from ..._utils import required_args, maybe_transform, async_maybe_transform +from ..._utils import path_template, required_args, maybe_transform, async_maybe_transform from ..._compat import cached_property from .schedules import ( SchedulesResource, @@ -396,7 +396,7 @@ def create_adhoc( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/dataexports/adhoc", + path_template("/organizations/{org_id}/dataexports/adhoc", org_id=org_id), body=maybe_transform( { "operational_data_types": operational_data_types, @@ -764,7 +764,7 @@ async def create_adhoc( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/dataexports/adhoc", + path_template("/organizations/{org_id}/dataexports/adhoc", org_id=org_id), body=await async_maybe_transform( { "operational_data_types": operational_data_types, diff --git a/src/m3ter/resources/data_exports/destinations.py b/src/m3ter/resources/data_exports/destinations.py index 98ed7ed7..a59fa2cb 100644 --- a/src/m3ter/resources/data_exports/destinations.py +++ b/src/m3ter/resources/data_exports/destinations.py @@ -8,7 +8,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from ..._utils import required_args, maybe_transform, async_maybe_transform +from ..._utils import path_template, required_args, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -280,7 +280,7 @@ def create( return cast( DestinationCreateResponse, self._post( - f"/organizations/{org_id}/dataexports/destinations", + path_template("/organizations/{org_id}/dataexports/destinations", org_id=org_id), body=maybe_transform( { "bucket_name": bucket_name, @@ -338,7 +338,7 @@ def retrieve( return cast( DestinationRetrieveResponse, self._get( - f"/organizations/{org_id}/dataexports/destinations/{id}", + path_template("/organizations/{org_id}/dataexports/destinations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -570,7 +570,7 @@ def update( return cast( DestinationUpdateResponse, self._put( - f"/organizations/{org_id}/dataexports/destinations/{id}", + path_template("/organizations/{org_id}/dataexports/destinations/{id}", org_id=org_id, id=id), body=maybe_transform( { "bucket_name": bucket_name, @@ -634,7 +634,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/dataexports/destinations", + path_template("/organizations/{org_id}/dataexports/destinations", org_id=org_id), page=SyncCursor[DataExportDestinationResponse], options=make_request_options( extra_headers=extra_headers, @@ -690,7 +690,7 @@ def delete( return cast( DestinationDeleteResponse, self._delete( - f"/organizations/{org_id}/dataexports/destinations/{id}", + path_template("/organizations/{org_id}/dataexports/destinations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -952,7 +952,7 @@ async def create( return cast( DestinationCreateResponse, await self._post( - f"/organizations/{org_id}/dataexports/destinations", + path_template("/organizations/{org_id}/dataexports/destinations", org_id=org_id), body=await async_maybe_transform( { "bucket_name": bucket_name, @@ -1010,7 +1010,7 @@ async def retrieve( return cast( DestinationRetrieveResponse, await self._get( - f"/organizations/{org_id}/dataexports/destinations/{id}", + path_template("/organizations/{org_id}/dataexports/destinations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1242,7 +1242,7 @@ async def update( return cast( DestinationUpdateResponse, await self._put( - f"/organizations/{org_id}/dataexports/destinations/{id}", + path_template("/organizations/{org_id}/dataexports/destinations/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "bucket_name": bucket_name, @@ -1306,7 +1306,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/dataexports/destinations", + path_template("/organizations/{org_id}/dataexports/destinations", org_id=org_id), page=AsyncCursor[DataExportDestinationResponse], options=make_request_options( extra_headers=extra_headers, @@ -1362,7 +1362,7 @@ async def delete( return cast( DestinationDeleteResponse, await self._delete( - f"/organizations/{org_id}/dataexports/destinations/{id}", + path_template("/organizations/{org_id}/dataexports/destinations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/data_exports/jobs.py b/src/m3ter/resources/data_exports/jobs.py index 9e23ee0c..c080e75a 100644 --- a/src/m3ter/resources/data_exports/jobs.py +++ b/src/m3ter/resources/data_exports/jobs.py @@ -7,7 +7,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from ..._utils import maybe_transform +from ..._utils import path_template, maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -82,7 +82,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/dataexports/jobs/{id}", + path_template("/organizations/{org_id}/dataexports/jobs/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -142,7 +142,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/dataexports/jobs", + path_template("/organizations/{org_id}/dataexports/jobs", org_id=org_id), page=SyncCursor[DataExportJobResponse], options=make_request_options( extra_headers=extra_headers, @@ -213,7 +213,9 @@ def get_download_url( if not job_id: raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}") return self._get( - f"/organizations/{org_id}/dataexports/jobs/{job_id}/getdownloadurl", + path_template( + "/organizations/{org_id}/dataexports/jobs/{job_id}/getdownloadurl", org_id=org_id, job_id=job_id + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -278,7 +280,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/dataexports/jobs/{id}", + path_template("/organizations/{org_id}/dataexports/jobs/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -338,7 +340,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/dataexports/jobs", + path_template("/organizations/{org_id}/dataexports/jobs", org_id=org_id), page=AsyncCursor[DataExportJobResponse], options=make_request_options( extra_headers=extra_headers, @@ -409,7 +411,9 @@ async def get_download_url( if not job_id: raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}") return await self._get( - f"/organizations/{org_id}/dataexports/jobs/{job_id}/getdownloadurl", + path_template( + "/organizations/{org_id}/dataexports/jobs/{job_id}/getdownloadurl", org_id=org_id, job_id=job_id + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/data_exports/schedules.py b/src/m3ter/resources/data_exports/schedules.py index 441951ef..ee41968f 100644 --- a/src/m3ter/resources/data_exports/schedules.py +++ b/src/m3ter/resources/data_exports/schedules.py @@ -8,7 +8,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from ..._utils import required_args, maybe_transform, async_maybe_transform +from ..._utils import path_template, required_args, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -388,7 +388,7 @@ def create( return cast( ScheduleCreateResponse, self._post( - f"/organizations/{org_id}/dataexports/schedules", + path_template("/organizations/{org_id}/dataexports/schedules", org_id=org_id), body=maybe_transform( { "operational_data_types": operational_data_types, @@ -447,7 +447,7 @@ def retrieve( return cast( ScheduleRetrieveResponse, self._get( - f"/organizations/{org_id}/dataexports/schedules/{id}", + path_template("/organizations/{org_id}/dataexports/schedules/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -766,7 +766,7 @@ def update( return cast( ScheduleUpdateResponse, self._put( - f"/organizations/{org_id}/dataexports/schedules/{id}", + path_template("/organizations/{org_id}/dataexports/schedules/{id}", org_id=org_id, id=id), body=maybe_transform( { "operational_data_types": operational_data_types, @@ -832,7 +832,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/dataexports/schedules", + path_template("/organizations/{org_id}/dataexports/schedules", org_id=org_id), page=SyncCursor[ScheduleListResponse], options=make_request_options( extra_headers=extra_headers, @@ -886,7 +886,7 @@ def delete( return cast( ScheduleDeleteResponse, self._delete( - f"/organizations/{org_id}/dataexports/schedules/{id}", + path_template("/organizations/{org_id}/dataexports/schedules/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1255,7 +1255,7 @@ async def create( return cast( ScheduleCreateResponse, await self._post( - f"/organizations/{org_id}/dataexports/schedules", + path_template("/organizations/{org_id}/dataexports/schedules", org_id=org_id), body=await async_maybe_transform( { "operational_data_types": operational_data_types, @@ -1314,7 +1314,7 @@ async def retrieve( return cast( ScheduleRetrieveResponse, await self._get( - f"/organizations/{org_id}/dataexports/schedules/{id}", + path_template("/organizations/{org_id}/dataexports/schedules/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1633,7 +1633,7 @@ async def update( return cast( ScheduleUpdateResponse, await self._put( - f"/organizations/{org_id}/dataexports/schedules/{id}", + path_template("/organizations/{org_id}/dataexports/schedules/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "operational_data_types": operational_data_types, @@ -1699,7 +1699,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/dataexports/schedules", + path_template("/organizations/{org_id}/dataexports/schedules", org_id=org_id), page=AsyncCursor[ScheduleListResponse], options=make_request_options( extra_headers=extra_headers, @@ -1753,7 +1753,7 @@ async def delete( return cast( ScheduleDeleteResponse, await self._delete( - f"/organizations/{org_id}/dataexports/schedules/{id}", + path_template("/organizations/{org_id}/dataexports/schedules/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/debit_reasons.py b/src/m3ter/resources/debit_reasons.py index 6e286b3d..e128d1ff 100644 --- a/src/m3ter/resources/debit_reasons.py +++ b/src/m3ter/resources/debit_reasons.py @@ -6,7 +6,7 @@ from ..types import debit_reason_list_params, debit_reason_create_params, debit_reason_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -104,7 +104,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/picklists/debitreasons", + path_template("/organizations/{org_id}/picklists/debitreasons", org_id=org_id), body=maybe_transform( { "name": name, @@ -151,7 +151,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/picklists/debitreasons/{id}", + path_template("/organizations/{org_id}/picklists/debitreasons/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -213,7 +213,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/picklists/debitreasons/{id}", + path_template("/organizations/{org_id}/picklists/debitreasons/{id}", org_id=org_id, id=id), body=maybe_transform( { "name": name, @@ -279,7 +279,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/picklists/debitreasons", + path_template("/organizations/{org_id}/picklists/debitreasons", org_id=org_id), page=SyncCursor[DebitReasonResponse], options=make_request_options( extra_headers=extra_headers, @@ -331,7 +331,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/picklists/debitreasons/{id}", + path_template("/organizations/{org_id}/picklists/debitreasons/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -421,7 +421,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/picklists/debitreasons", + path_template("/organizations/{org_id}/picklists/debitreasons", org_id=org_id), body=await async_maybe_transform( { "name": name, @@ -468,7 +468,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/picklists/debitreasons/{id}", + path_template("/organizations/{org_id}/picklists/debitreasons/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -530,7 +530,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/picklists/debitreasons/{id}", + path_template("/organizations/{org_id}/picklists/debitreasons/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "name": name, @@ -596,7 +596,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/picklists/debitreasons", + path_template("/organizations/{org_id}/picklists/debitreasons", org_id=org_id), page=AsyncCursor[DebitReasonResponse], options=make_request_options( extra_headers=extra_headers, @@ -648,7 +648,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/picklists/debitreasons/{id}", + path_template("/organizations/{org_id}/picklists/debitreasons/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/events.py b/src/m3ter/resources/events.py index 3716f38a..85425e8a 100644 --- a/src/m3ter/resources/events.py +++ b/src/m3ter/resources/events.py @@ -8,7 +8,7 @@ from ..types import event_list_params, event_get_fields_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -137,7 +137,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/events/{id}", + path_template("/organizations/{org_id}/events/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -226,7 +226,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/events", + path_template("/organizations/{org_id}/events", org_id=org_id), page=SyncCursor[EventResponse], options=make_request_options( extra_headers=extra_headers, @@ -309,7 +309,7 @@ def get_fields( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get( - f"/organizations/{org_id}/events/fields", + path_template("/organizations/{org_id}/events/fields", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -351,7 +351,7 @@ def get_types( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get( - f"/organizations/{org_id}/events/types", + path_template("/organizations/{org_id}/events/types", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -470,7 +470,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/events/{id}", + path_template("/organizations/{org_id}/events/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -559,7 +559,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/events", + path_template("/organizations/{org_id}/events", org_id=org_id), page=AsyncCursor[EventResponse], options=make_request_options( extra_headers=extra_headers, @@ -642,7 +642,7 @@ async def get_fields( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._get( - f"/organizations/{org_id}/events/fields", + path_template("/organizations/{org_id}/events/fields", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -686,7 +686,7 @@ async def get_types( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._get( - f"/organizations/{org_id}/events/types", + path_template("/organizations/{org_id}/events/types", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/external_mappings.py b/src/m3ter/resources/external_mappings.py index a1f3541e..135cc723 100644 --- a/src/m3ter/resources/external_mappings.py +++ b/src/m3ter/resources/external_mappings.py @@ -12,7 +12,7 @@ external_mapping_list_by_external_entity_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -119,7 +119,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/externalmappings", + path_template("/organizations/{org_id}/externalmappings", org_id=org_id), body=maybe_transform( { "external_id": external_id, @@ -172,7 +172,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/externalmappings/{id}", + path_template("/organizations/{org_id}/externalmappings/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -245,7 +245,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/externalmappings/{id}", + path_template("/organizations/{org_id}/externalmappings/{id}", org_id=org_id, id=id), body=maybe_transform( { "external_id": external_id, @@ -317,7 +317,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/externalmappings", + path_template("/organizations/{org_id}/externalmappings", org_id=org_id), page=SyncCursor[ExternalMappingResponse], options=make_request_options( extra_headers=extra_headers, @@ -369,7 +369,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/externalmappings/{id}", + path_template("/organizations/{org_id}/externalmappings/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -425,7 +425,13 @@ def list_by_external_entity( if not external_id: raise ValueError(f"Expected a non-empty value for `external_id` but received {external_id!r}") return self._get_api_list( - f"/organizations/{org_id}/externalmappings/externalid/{system}/{external_table}/{external_id}", + path_template( + "/organizations/{org_id}/externalmappings/externalid/{system}/{external_table}/{external_id}", + org_id=org_id, + system=system, + external_table=external_table, + external_id=external_id, + ), page=SyncCursor[ExternalMappingResponse], options=make_request_options( extra_headers=extra_headers, @@ -487,7 +493,12 @@ def list_by_m3ter_entity( if not m3ter_id: raise ValueError(f"Expected a non-empty value for `m3ter_id` but received {m3ter_id!r}") return self._get_api_list( - f"/organizations/{org_id}/externalmappings/external/{entity}/{m3ter_id}", + path_template( + "/organizations/{org_id}/externalmappings/external/{entity}/{m3ter_id}", + org_id=org_id, + entity=entity, + m3ter_id=m3ter_id, + ), page=SyncCursor[ExternalMappingResponse], options=make_request_options( extra_headers=extra_headers, @@ -597,7 +608,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/externalmappings", + path_template("/organizations/{org_id}/externalmappings", org_id=org_id), body=await async_maybe_transform( { "external_id": external_id, @@ -650,7 +661,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/externalmappings/{id}", + path_template("/organizations/{org_id}/externalmappings/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -723,7 +734,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/externalmappings/{id}", + path_template("/organizations/{org_id}/externalmappings/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "external_id": external_id, @@ -795,7 +806,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/externalmappings", + path_template("/organizations/{org_id}/externalmappings", org_id=org_id), page=AsyncCursor[ExternalMappingResponse], options=make_request_options( extra_headers=extra_headers, @@ -847,7 +858,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/externalmappings/{id}", + path_template("/organizations/{org_id}/externalmappings/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -903,7 +914,13 @@ def list_by_external_entity( if not external_id: raise ValueError(f"Expected a non-empty value for `external_id` but received {external_id!r}") return self._get_api_list( - f"/organizations/{org_id}/externalmappings/externalid/{system}/{external_table}/{external_id}", + path_template( + "/organizations/{org_id}/externalmappings/externalid/{system}/{external_table}/{external_id}", + org_id=org_id, + system=system, + external_table=external_table, + external_id=external_id, + ), page=AsyncCursor[ExternalMappingResponse], options=make_request_options( extra_headers=extra_headers, @@ -965,7 +982,12 @@ def list_by_m3ter_entity( if not m3ter_id: raise ValueError(f"Expected a non-empty value for `m3ter_id` but received {m3ter_id!r}") return self._get_api_list( - f"/organizations/{org_id}/externalmappings/external/{entity}/{m3ter_id}", + path_template( + "/organizations/{org_id}/externalmappings/external/{entity}/{m3ter_id}", + org_id=org_id, + entity=entity, + m3ter_id=m3ter_id, + ), page=AsyncCursor[ExternalMappingResponse], options=make_request_options( extra_headers=extra_headers, diff --git a/src/m3ter/resources/integration_configurations.py b/src/m3ter/resources/integration_configurations.py index 534a043c..7feca42c 100644 --- a/src/m3ter/resources/integration_configurations.py +++ b/src/m3ter/resources/integration_configurations.py @@ -13,7 +13,7 @@ integration_configuration_get_by_entity_params, ) 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 ( @@ -137,7 +137,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/integrationconfigs", + path_template("/organizations/{org_id}/integrationconfigs", org_id=org_id), body=maybe_transform( { "destination": destination, @@ -193,7 +193,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/integrationconfigs/{id}", + path_template("/organizations/{org_id}/integrationconfigs/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -275,7 +275,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/integrationconfigs/{id}", + path_template("/organizations/{org_id}/integrationconfigs/{id}", org_id=org_id, id=id), body=maybe_transform( { "destination": destination, @@ -337,7 +337,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/integrationconfigs", + path_template("/organizations/{org_id}/integrationconfigs", org_id=org_id), page=SyncCursor[IntegrationConfigurationListResponse], options=make_request_options( extra_headers=extra_headers, @@ -391,7 +391,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/integrationconfigs/{id}", + path_template("/organizations/{org_id}/integrationconfigs/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -430,7 +430,7 @@ def enable( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/organizations/{org_id}/integrationconfigs/{id}/enable", + path_template("/organizations/{org_id}/integrationconfigs/{id}/enable", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -483,7 +483,11 @@ def get_by_entity( if not entity_type: raise ValueError(f"Expected a non-empty value for `entity_type` but received {entity_type!r}") return self._get( - f"/organizations/{org_id}/integrationconfigs/entity/{entity_type}", + path_template( + "/organizations/{org_id}/integrationconfigs/entity/{entity_type}", + org_id=org_id, + entity_type=entity_type, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -607,7 +611,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/integrationconfigs", + path_template("/organizations/{org_id}/integrationconfigs", org_id=org_id), body=await async_maybe_transform( { "destination": destination, @@ -663,7 +667,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/integrationconfigs/{id}", + path_template("/organizations/{org_id}/integrationconfigs/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -745,7 +749,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/integrationconfigs/{id}", + path_template("/organizations/{org_id}/integrationconfigs/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "destination": destination, @@ -807,7 +811,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/integrationconfigs", + path_template("/organizations/{org_id}/integrationconfigs", org_id=org_id), page=AsyncCursor[IntegrationConfigurationListResponse], options=make_request_options( extra_headers=extra_headers, @@ -861,7 +865,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/integrationconfigs/{id}", + path_template("/organizations/{org_id}/integrationconfigs/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -900,7 +904,7 @@ async def enable( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/organizations/{org_id}/integrationconfigs/{id}/enable", + path_template("/organizations/{org_id}/integrationconfigs/{id}/enable", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -953,7 +957,11 @@ async def get_by_entity( if not entity_type: raise ValueError(f"Expected a non-empty value for `entity_type` but received {entity_type!r}") return await self._get( - f"/organizations/{org_id}/integrationconfigs/entity/{entity_type}", + path_template( + "/organizations/{org_id}/integrationconfigs/entity/{entity_type}", + org_id=org_id, + entity_type=entity_type, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, diff --git a/src/m3ter/resources/lookup_tables/lookup_table_revision_data/lookup_table_revision_data.py b/src/m3ter/resources/lookup_tables/lookup_table_revision_data/lookup_table_revision_data.py index 69e88ace..5a26c483 100644 --- a/src/m3ter/resources/lookup_tables/lookup_table_revision_data/lookup_table_revision_data.py +++ b/src/m3ter/resources/lookup_tables/lookup_table_revision_data/lookup_table_revision_data.py @@ -8,7 +8,7 @@ import httpx from ...._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -157,7 +157,12 @@ def retrieve( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return self._get( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -222,7 +227,12 @@ def update( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return self._put( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), body=maybe_transform( { "items": items, @@ -279,7 +289,12 @@ def delete( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return self._delete( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -332,7 +347,12 @@ def archieve( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return self._post( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/archived", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/archived", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), body=maybe_transform( {"content_type": content_type}, lookup_table_revision_data_archieve_params.LookupTableRevisionDataArchieveParams, @@ -391,7 +411,12 @@ def copy( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return self._post( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/copy", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/copy", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), body=maybe_transform( {"revision_id": revision_id}, lookup_table_revision_data_copy_params.LookupTableRevisionDataCopyParams ), @@ -453,7 +478,13 @@ def delete_key( if not lookup_key: raise ValueError(f"Expected a non-empty value for `lookup_key` but received {lookup_key!r}") return self._delete( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/{lookup_key}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/{lookup_key}", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + lookup_key=lookup_key, + ), body=maybe_transform( {"version": version}, lookup_table_revision_data_delete_key_params.LookupTableRevisionDataDeleteKeyParams, @@ -530,7 +561,12 @@ def generate_download_url( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return self._post( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/generateuploadurl", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/generateuploadurl", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), body=maybe_transform( { "content_length": content_length, @@ -595,7 +631,13 @@ def retrieve_key( if not lookup_key: raise ValueError(f"Expected a non-empty value for `lookup_key` but received {lookup_key!r}") return self._get( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/{lookup_key}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/{lookup_key}", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + lookup_key=lookup_key, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -661,7 +703,13 @@ def update_key( if not lookup_key: raise ValueError(f"Expected a non-empty value for `lookup_key` but received {lookup_key!r}") return self._put( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/{lookup_key}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/{lookup_key}", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + lookup_key=lookup_key, + ), body=maybe_transform( { "item": item, @@ -784,7 +832,12 @@ async def retrieve( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return await self._get( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -849,7 +902,12 @@ async def update( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return await self._put( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), body=await async_maybe_transform( { "items": items, @@ -906,7 +964,12 @@ async def delete( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return await self._delete( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -959,7 +1022,12 @@ async def archieve( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return await self._post( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/archived", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/archived", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), body=await async_maybe_transform( {"content_type": content_type}, lookup_table_revision_data_archieve_params.LookupTableRevisionDataArchieveParams, @@ -1018,7 +1086,12 @@ async def copy( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return await self._post( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/copy", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/copy", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), body=await async_maybe_transform( {"revision_id": revision_id}, lookup_table_revision_data_copy_params.LookupTableRevisionDataCopyParams ), @@ -1080,7 +1153,13 @@ async def delete_key( if not lookup_key: raise ValueError(f"Expected a non-empty value for `lookup_key` but received {lookup_key!r}") return await self._delete( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/{lookup_key}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/{lookup_key}", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + lookup_key=lookup_key, + ), body=await async_maybe_transform( {"version": version}, lookup_table_revision_data_delete_key_params.LookupTableRevisionDataDeleteKeyParams, @@ -1157,7 +1236,12 @@ async def generate_download_url( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return await self._post( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/generateuploadurl", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/generateuploadurl", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), body=await async_maybe_transform( { "content_length": content_length, @@ -1222,7 +1306,13 @@ async def retrieve_key( if not lookup_key: raise ValueError(f"Expected a non-empty value for `lookup_key` but received {lookup_key!r}") return await self._get( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/{lookup_key}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/{lookup_key}", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + lookup_key=lookup_key, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1288,7 +1378,13 @@ async def update_key( if not lookup_key: raise ValueError(f"Expected a non-empty value for `lookup_key` but received {lookup_key!r}") return await self._put( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/{lookup_key}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/{lookup_key}", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + lookup_key=lookup_key, + ), body=await async_maybe_transform( { "item": item, diff --git a/src/m3ter/resources/lookup_tables/lookup_table_revision_data/lookup_table_revision_data_jobs.py b/src/m3ter/resources/lookup_tables/lookup_table_revision_data/lookup_table_revision_data_jobs.py index 84f1c68e..ab1839c3 100644 --- a/src/m3ter/resources/lookup_tables/lookup_table_revision_data/lookup_table_revision_data_jobs.py +++ b/src/m3ter/resources/lookup_tables/lookup_table_revision_data/lookup_table_revision_data_jobs.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 ( @@ -115,7 +115,13 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs/{id}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs/{id}", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -191,7 +197,12 @@ def list( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return self._get_api_list( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), page=SyncCursor[LookupTableRevisionDataJobListResponse], options=make_request_options( extra_headers=extra_headers, @@ -252,7 +263,13 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs/{id}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs/{id}", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -304,7 +321,12 @@ def download( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return self._post( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs/download", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs/download", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), body=maybe_transform( {"content_type": content_type}, lookup_table_revision_data_job_download_params.LookupTableRevisionDataJobDownloadParams, @@ -393,7 +415,13 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs/{id}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs/{id}", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -469,7 +497,12 @@ def list( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return self._get_api_list( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), page=AsyncCursor[LookupTableRevisionDataJobListResponse], options=make_request_options( extra_headers=extra_headers, @@ -530,7 +563,13 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs/{id}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs/{id}", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -582,7 +621,12 @@ async def download( f"Expected a non-empty value for `lookup_table_revision_id` but received {lookup_table_revision_id!r}" ) return await self._post( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs/download", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{lookup_table_revision_id}/data/jobs/download", + org_id=org_id, + lookup_table_id=lookup_table_id, + lookup_table_revision_id=lookup_table_revision_id, + ), body=await async_maybe_transform( {"content_type": content_type}, lookup_table_revision_data_job_download_params.LookupTableRevisionDataJobDownloadParams, diff --git a/src/m3ter/resources/lookup_tables/lookup_table_revisions.py b/src/m3ter/resources/lookup_tables/lookup_table_revisions.py index d23d9936..e6642c44 100644 --- a/src/m3ter/resources/lookup_tables/lookup_table_revisions.py +++ b/src/m3ter/resources/lookup_tables/lookup_table_revisions.py @@ -9,7 +9,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -145,7 +145,11 @@ def create( if not lookup_table_id: raise ValueError(f"Expected a non-empty value for `lookup_table_id` but received {lookup_table_id!r}") return self._post( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions", + org_id=org_id, + lookup_table_id=lookup_table_id, + ), body=maybe_transform( { "fields": fields, @@ -197,7 +201,12 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}", + org_id=org_id, + lookup_table_id=lookup_table_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -280,7 +289,12 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}", + org_id=org_id, + lookup_table_id=lookup_table_id, + id=id, + ), body=maybe_transform( { "fields": fields, @@ -338,7 +352,11 @@ def list( if not lookup_table_id: raise ValueError(f"Expected a non-empty value for `lookup_table_id` but received {lookup_table_id!r}") return self._get_api_list( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions", + org_id=org_id, + lookup_table_id=lookup_table_id, + ), page=SyncCursor[LookupTableRevisionResponse], options=make_request_options( extra_headers=extra_headers, @@ -391,7 +409,12 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}", + org_id=org_id, + lookup_table_id=lookup_table_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -438,7 +461,12 @@ def update_status( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}/status", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}/status", + org_id=org_id, + lookup_table_id=lookup_table_id, + id=id, + ), body=maybe_transform( { "status": status, @@ -567,7 +595,11 @@ async def create( if not lookup_table_id: raise ValueError(f"Expected a non-empty value for `lookup_table_id` but received {lookup_table_id!r}") return await self._post( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions", + org_id=org_id, + lookup_table_id=lookup_table_id, + ), body=await async_maybe_transform( { "fields": fields, @@ -619,7 +651,12 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}", + org_id=org_id, + lookup_table_id=lookup_table_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -702,7 +739,12 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}", + org_id=org_id, + lookup_table_id=lookup_table_id, + id=id, + ), body=await async_maybe_transform( { "fields": fields, @@ -760,7 +802,11 @@ def list( if not lookup_table_id: raise ValueError(f"Expected a non-empty value for `lookup_table_id` but received {lookup_table_id!r}") return self._get_api_list( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions", + org_id=org_id, + lookup_table_id=lookup_table_id, + ), page=AsyncCursor[LookupTableRevisionResponse], options=make_request_options( extra_headers=extra_headers, @@ -813,7 +859,12 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}", + org_id=org_id, + lookup_table_id=lookup_table_id, + id=id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -860,7 +911,12 @@ async def update_status( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}/status", + path_template( + "/organizations/{org_id}/lookuptables/{lookup_table_id}/revisions/{id}/status", + org_id=org_id, + lookup_table_id=lookup_table_id, + id=id, + ), body=await async_maybe_transform( { "status": status, diff --git a/src/m3ter/resources/lookup_tables/lookup_tables.py b/src/m3ter/resources/lookup_tables/lookup_tables.py index 8b9a6fc9..a8c9d7b4 100644 --- a/src/m3ter/resources/lookup_tables/lookup_tables.py +++ b/src/m3ter/resources/lookup_tables/lookup_tables.py @@ -13,7 +13,7 @@ lookup_table_retrieve_params, ) from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -164,7 +164,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/lookuptables", + path_template("/organizations/{org_id}/lookuptables", org_id=org_id), body=maybe_transform( { "code": code, @@ -216,7 +216,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/lookuptables/{id}", + path_template("/organizations/{org_id}/lookuptables/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -293,7 +293,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/lookuptables/{id}", + path_template("/organizations/{org_id}/lookuptables/{id}", org_id=org_id, id=id), body=maybe_transform( { "code": code, @@ -356,7 +356,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/lookuptables", + path_template("/organizations/{org_id}/lookuptables", org_id=org_id), page=SyncCursor[LookupTableResponse], options=make_request_options( extra_headers=extra_headers, @@ -407,7 +407,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/lookuptables/{id}", + path_template("/organizations/{org_id}/lookuptables/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -534,7 +534,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/lookuptables", + path_template("/organizations/{org_id}/lookuptables", org_id=org_id), body=await async_maybe_transform( { "code": code, @@ -586,7 +586,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/lookuptables/{id}", + path_template("/organizations/{org_id}/lookuptables/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -663,7 +663,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/lookuptables/{id}", + path_template("/organizations/{org_id}/lookuptables/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "code": code, @@ -726,7 +726,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/lookuptables", + path_template("/organizations/{org_id}/lookuptables", org_id=org_id), page=AsyncCursor[LookupTableResponse], options=make_request_options( extra_headers=extra_headers, @@ -777,7 +777,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/lookuptables/{id}", + path_template("/organizations/{org_id}/lookuptables/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/meters.py b/src/m3ter/resources/meters.py index 7919cd6e..c4fdffc4 100644 --- a/src/m3ter/resources/meters.py +++ b/src/m3ter/resources/meters.py @@ -8,7 +8,7 @@ from ..types import meter_list_params, meter_create_params, meter_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -178,7 +178,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/meters", + path_template("/organizations/{org_id}/meters", org_id=org_id), body=maybe_transform( { "code": code, @@ -229,7 +229,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/meters/{id}", + path_template("/organizations/{org_id}/meters/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -325,7 +325,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/meters/{id}", + path_template("/organizations/{org_id}/meters/{id}", org_id=org_id, id=id), body=maybe_transform( { "code": code, @@ -390,7 +390,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/meters", + path_template("/organizations/{org_id}/meters", org_id=org_id), page=SyncCursor[MeterResponse], options=make_request_options( extra_headers=extra_headers, @@ -442,7 +442,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/meters/{id}", + path_template("/organizations/{org_id}/meters/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -602,7 +602,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/meters", + path_template("/organizations/{org_id}/meters", org_id=org_id), body=await async_maybe_transform( { "code": code, @@ -653,7 +653,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/meters/{id}", + path_template("/organizations/{org_id}/meters/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -749,7 +749,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/meters/{id}", + path_template("/organizations/{org_id}/meters/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "code": code, @@ -814,7 +814,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/meters", + path_template("/organizations/{org_id}/meters", org_id=org_id), page=AsyncCursor[MeterResponse], options=make_request_options( extra_headers=extra_headers, @@ -866,7 +866,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/meters/{id}", + path_template("/organizations/{org_id}/meters/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/notification_configurations.py b/src/m3ter/resources/notification_configurations.py index 4da7e503..eb5cc5bc 100644 --- a/src/m3ter/resources/notification_configurations.py +++ b/src/m3ter/resources/notification_configurations.py @@ -10,7 +10,7 @@ notification_configuration_update_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -149,7 +149,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/notifications/configurations", + path_template("/organizations/{org_id}/notifications/configurations", org_id=org_id), body=maybe_transform( { "code": code, @@ -204,7 +204,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/notifications/configurations/{id}", + path_template("/organizations/{org_id}/notifications/configurations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -306,7 +306,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/notifications/configurations/{id}", + path_template("/organizations/{org_id}/notifications/configurations/{id}", org_id=org_id, id=id), body=maybe_transform( { "code": code, @@ -379,7 +379,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/notifications/configurations", + path_template("/organizations/{org_id}/notifications/configurations", org_id=org_id), page=SyncCursor[NotificationConfigurationResponse], options=make_request_options( extra_headers=extra_headers, @@ -434,7 +434,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/notifications/configurations/{id}", + path_template("/organizations/{org_id}/notifications/configurations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -565,7 +565,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/notifications/configurations", + path_template("/organizations/{org_id}/notifications/configurations", org_id=org_id), body=await async_maybe_transform( { "code": code, @@ -620,7 +620,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/notifications/configurations/{id}", + path_template("/organizations/{org_id}/notifications/configurations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -722,7 +722,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/notifications/configurations/{id}", + path_template("/organizations/{org_id}/notifications/configurations/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "code": code, @@ -795,7 +795,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/notifications/configurations", + path_template("/organizations/{org_id}/notifications/configurations", org_id=org_id), page=AsyncCursor[NotificationConfigurationResponse], options=make_request_options( extra_headers=extra_headers, @@ -850,7 +850,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/notifications/configurations/{id}", + path_template("/organizations/{org_id}/notifications/configurations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/organization_config.py b/src/m3ter/resources/organization_config.py index 7791a6be..80102519 100644 --- a/src/m3ter/resources/organization_config.py +++ b/src/m3ter/resources/organization_config.py @@ -9,7 +9,7 @@ from ..types import organization_config_update_params 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 ( @@ -93,7 +93,7 @@ def retrieve( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get( - f"/organizations/{org_id}/organizationconfig", + path_template("/organizations/{org_id}/organizationconfig", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -378,7 +378,7 @@ def update( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._put( - f"/organizations/{org_id}/organizationconfig", + path_template("/organizations/{org_id}/organizationconfig", org_id=org_id), body=maybe_transform( { "currency": currency, @@ -485,7 +485,7 @@ async def retrieve( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._get( - f"/organizations/{org_id}/organizationconfig", + path_template("/organizations/{org_id}/organizationconfig", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -770,7 +770,7 @@ async def update( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._put( - f"/organizations/{org_id}/organizationconfig", + path_template("/organizations/{org_id}/organizationconfig", org_id=org_id), body=await async_maybe_transform( { "currency": currency, diff --git a/src/m3ter/resources/permission_policies.py b/src/m3ter/resources/permission_policies.py index 3e7172ca..f183cb64 100644 --- a/src/m3ter/resources/permission_policies.py +++ b/src/m3ter/resources/permission_policies.py @@ -19,7 +19,7 @@ permission_policy_remove_from_service_user_params, ) 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 ( @@ -142,7 +142,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/permissionpolicies", + path_template("/organizations/{org_id}/permissionpolicies", org_id=org_id), body=maybe_transform( { "name": name, @@ -188,7 +188,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/permissionpolicies/{id}", + path_template("/organizations/{org_id}/permissionpolicies/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -268,7 +268,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/permissionpolicies/{id}", + path_template("/organizations/{org_id}/permissionpolicies/{id}", org_id=org_id, id=id), body=maybe_transform( { "name": name, @@ -317,7 +317,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/permissionpolicies", + path_template("/organizations/{org_id}/permissionpolicies", org_id=org_id), page=SyncCursor[PermissionPolicyResponse], options=make_request_options( extra_headers=extra_headers, @@ -366,7 +366,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/permissionpolicies/{id}", + path_template("/organizations/{org_id}/permissionpolicies/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -420,7 +420,11 @@ def add_to_service_user( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtoserviceuser", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtoserviceuser", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=maybe_transform( { "principal_id": principal_id, @@ -478,7 +482,11 @@ def add_to_support_user( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtosupportusers", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtosupportusers", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=maybe_transform( {"version": version}, permission_policy_add_to_support_user_params.PermissionPolicyAddToSupportUserParams, @@ -536,7 +544,11 @@ def add_to_user( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtouser", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtouser", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=maybe_transform( { "principal_id": principal_id, @@ -597,7 +609,11 @@ def add_to_user_group( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtousergroup", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtousergroup", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=maybe_transform( { "principal_id": principal_id, @@ -658,7 +674,11 @@ def remove_from_service_user( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromserviceuser", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromserviceuser", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=maybe_transform( { "principal_id": principal_id, @@ -705,7 +725,11 @@ def remove_from_support_user( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromsupportusers", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromsupportusers", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -759,7 +783,11 @@ def remove_from_user( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromuser", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromuser", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=maybe_transform( { "principal_id": principal_id, @@ -820,7 +848,11 @@ def remove_from_user_group( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromusergroup", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromusergroup", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=maybe_transform( { "principal_id": principal_id, @@ -933,7 +965,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/permissionpolicies", + path_template("/organizations/{org_id}/permissionpolicies", org_id=org_id), body=await async_maybe_transform( { "name": name, @@ -979,7 +1011,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/permissionpolicies/{id}", + path_template("/organizations/{org_id}/permissionpolicies/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1059,7 +1091,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/permissionpolicies/{id}", + path_template("/organizations/{org_id}/permissionpolicies/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "name": name, @@ -1108,7 +1140,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/permissionpolicies", + path_template("/organizations/{org_id}/permissionpolicies", org_id=org_id), page=AsyncCursor[PermissionPolicyResponse], options=make_request_options( extra_headers=extra_headers, @@ -1157,7 +1189,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/permissionpolicies/{id}", + path_template("/organizations/{org_id}/permissionpolicies/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1211,7 +1243,11 @@ async def add_to_service_user( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return await self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtoserviceuser", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtoserviceuser", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=await async_maybe_transform( { "principal_id": principal_id, @@ -1269,7 +1305,11 @@ async def add_to_support_user( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return await self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtosupportusers", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtosupportusers", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=await async_maybe_transform( {"version": version}, permission_policy_add_to_support_user_params.PermissionPolicyAddToSupportUserParams, @@ -1327,7 +1367,11 @@ async def add_to_user( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return await self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtouser", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtouser", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=await async_maybe_transform( { "principal_id": principal_id, @@ -1388,7 +1432,11 @@ async def add_to_user_group( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return await self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtousergroup", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/addtousergroup", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=await async_maybe_transform( { "principal_id": principal_id, @@ -1449,7 +1497,11 @@ async def remove_from_service_user( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return await self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromserviceuser", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromserviceuser", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=await async_maybe_transform( { "principal_id": principal_id, @@ -1496,7 +1548,11 @@ async def remove_from_support_user( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return await self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromsupportusers", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromsupportusers", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1550,7 +1606,11 @@ async def remove_from_user( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return await self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromuser", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromuser", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=await async_maybe_transform( { "principal_id": principal_id, @@ -1611,7 +1671,11 @@ async def remove_from_user_group( f"Expected a non-empty value for `permission_policy_id` but received {permission_policy_id!r}" ) return await self._post( - f"/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromusergroup", + path_template( + "/organizations/{org_id}/permissionpolicies/{permission_policy_id}/removefromusergroup", + org_id=org_id, + permission_policy_id=permission_policy_id, + ), body=await async_maybe_transform( { "principal_id": principal_id, diff --git a/src/m3ter/resources/plan_group_links.py b/src/m3ter/resources/plan_group_links.py index 60f77fb3..41c38de3 100644 --- a/src/m3ter/resources/plan_group_links.py +++ b/src/m3ter/resources/plan_group_links.py @@ -6,7 +6,7 @@ from ..types import plan_group_link_list_params, plan_group_link_create_params, plan_group_link_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -93,7 +93,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/plangrouplinks", + path_template("/organizations/{org_id}/plangrouplinks", org_id=org_id), body=maybe_transform( { "plan_group_id": plan_group_id, @@ -139,7 +139,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/plangrouplinks/{id}", + path_template("/organizations/{org_id}/plangrouplinks/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -194,7 +194,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/plangrouplinks/{id}", + path_template("/organizations/{org_id}/plangrouplinks/{id}", org_id=org_id, id=id), body=maybe_transform( { "plan_group_id": plan_group_id, @@ -252,7 +252,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/plangrouplinks", + path_template("/organizations/{org_id}/plangrouplinks", org_id=org_id), page=SyncCursor[PlanGroupLinkResponse], options=make_request_options( extra_headers=extra_headers, @@ -304,7 +304,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/plangrouplinks/{id}", + path_template("/organizations/{org_id}/plangrouplinks/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -383,7 +383,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/plangrouplinks", + path_template("/organizations/{org_id}/plangrouplinks", org_id=org_id), body=await async_maybe_transform( { "plan_group_id": plan_group_id, @@ -429,7 +429,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/plangrouplinks/{id}", + path_template("/organizations/{org_id}/plangrouplinks/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -484,7 +484,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/plangrouplinks/{id}", + path_template("/organizations/{org_id}/plangrouplinks/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "plan_group_id": plan_group_id, @@ -542,7 +542,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/plangrouplinks", + path_template("/organizations/{org_id}/plangrouplinks", org_id=org_id), page=AsyncCursor[PlanGroupLinkResponse], options=make_request_options( extra_headers=extra_headers, @@ -594,7 +594,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/plangrouplinks/{id}", + path_template("/organizations/{org_id}/plangrouplinks/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/plan_groups.py b/src/m3ter/resources/plan_groups.py index 58809394..9e1e8bf3 100644 --- a/src/m3ter/resources/plan_groups.py +++ b/src/m3ter/resources/plan_groups.py @@ -8,7 +8,7 @@ from ..types import plan_group_list_params, plan_group_create_params, plan_group_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -152,7 +152,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/plangroups", + path_template("/organizations/{org_id}/plangroups", org_id=org_id), body=maybe_transform( { "currency": currency, @@ -212,7 +212,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/plangroups/{id}", + path_template("/organizations/{org_id}/plangroups/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -331,7 +331,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/plangroups/{id}", + path_template("/organizations/{org_id}/plangroups/{id}", org_id=org_id, id=id), body=maybe_transform( { "currency": currency, @@ -402,7 +402,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/plangroups", + path_template("/organizations/{org_id}/plangroups", org_id=org_id), page=SyncCursor[PlanGroupResponse], options=make_request_options( extra_headers=extra_headers, @@ -457,7 +457,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/plangroups/{id}", + path_template("/organizations/{org_id}/plangroups/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -593,7 +593,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/plangroups", + path_template("/organizations/{org_id}/plangroups", org_id=org_id), body=await async_maybe_transform( { "currency": currency, @@ -653,7 +653,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/plangroups/{id}", + path_template("/organizations/{org_id}/plangroups/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -772,7 +772,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/plangroups/{id}", + path_template("/organizations/{org_id}/plangroups/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "currency": currency, @@ -843,7 +843,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/plangroups", + path_template("/organizations/{org_id}/plangroups", org_id=org_id), page=AsyncCursor[PlanGroupResponse], options=make_request_options( extra_headers=extra_headers, @@ -898,7 +898,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/plangroups/{id}", + path_template("/organizations/{org_id}/plangroups/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/plan_templates.py b/src/m3ter/resources/plan_templates.py index 027e1723..66b7d921 100644 --- a/src/m3ter/resources/plan_templates.py +++ b/src/m3ter/resources/plan_templates.py @@ -9,7 +9,7 @@ from ..types import plan_template_list_params, plan_template_create_params, plan_template_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -206,7 +206,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/plantemplates", + path_template("/organizations/{org_id}/plantemplates", org_id=org_id), body=maybe_transform( { "bill_frequency": bill_frequency, @@ -269,7 +269,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/plantemplates/{id}", + path_template("/organizations/{org_id}/plantemplates/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -437,7 +437,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/plantemplates/{id}", + path_template("/organizations/{org_id}/plantemplates/{id}", org_id=org_id, id=id), body=maybe_transform( { "bill_frequency": bill_frequency, @@ -512,7 +512,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/plantemplates", + path_template("/organizations/{org_id}/plantemplates", org_id=org_id), page=SyncCursor[PlanTemplateResponse], options=make_request_options( extra_headers=extra_headers, @@ -566,7 +566,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/plantemplates/{id}", + path_template("/organizations/{org_id}/plantemplates/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -755,7 +755,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/plantemplates", + path_template("/organizations/{org_id}/plantemplates", org_id=org_id), body=await async_maybe_transform( { "bill_frequency": bill_frequency, @@ -818,7 +818,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/plantemplates/{id}", + path_template("/organizations/{org_id}/plantemplates/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -986,7 +986,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/plantemplates/{id}", + path_template("/organizations/{org_id}/plantemplates/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "bill_frequency": bill_frequency, @@ -1061,7 +1061,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/plantemplates", + path_template("/organizations/{org_id}/plantemplates", org_id=org_id), page=AsyncCursor[PlanTemplateResponse], options=make_request_options( extra_headers=extra_headers, @@ -1115,7 +1115,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/plantemplates/{id}", + path_template("/organizations/{org_id}/plantemplates/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/plans.py b/src/m3ter/resources/plans.py index e0e55b45..527cf5e5 100644 --- a/src/m3ter/resources/plans.py +++ b/src/m3ter/resources/plans.py @@ -8,7 +8,7 @@ from ..types import plan_list_params, plan_create_params, plan_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -183,7 +183,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/plans", + path_template("/organizations/{org_id}/plans", org_id=org_id), body=maybe_transform( { "code": code, @@ -242,7 +242,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/plans/{id}", + path_template("/organizations/{org_id}/plans/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -383,7 +383,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/plans/{id}", + path_template("/organizations/{org_id}/plans/{id}", org_id=org_id, id=id), body=maybe_transform( { "code": code, @@ -454,7 +454,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/plans", + path_template("/organizations/{org_id}/plans", org_id=org_id), page=SyncCursor[PlanResponse], options=make_request_options( extra_headers=extra_headers, @@ -506,7 +506,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/plans/{id}", + path_template("/organizations/{org_id}/plans/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -673,7 +673,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/plans", + path_template("/organizations/{org_id}/plans", org_id=org_id), body=await async_maybe_transform( { "code": code, @@ -732,7 +732,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/plans/{id}", + path_template("/organizations/{org_id}/plans/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -873,7 +873,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/plans/{id}", + path_template("/organizations/{org_id}/plans/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "code": code, @@ -944,7 +944,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/plans", + path_template("/organizations/{org_id}/plans", org_id=org_id), page=AsyncCursor[PlanResponse], options=make_request_options( extra_headers=extra_headers, @@ -996,7 +996,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/plans/{id}", + path_template("/organizations/{org_id}/plans/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/pricings.py b/src/m3ter/resources/pricings.py index 59fa992d..7b88563f 100644 --- a/src/m3ter/resources/pricings.py +++ b/src/m3ter/resources/pricings.py @@ -10,7 +10,7 @@ from ..types import pricing_list_params, pricing_create_params, pricing_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -228,7 +228,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/pricings", + path_template("/organizations/{org_id}/pricings", org_id=org_id), body=maybe_transform( { "pricing_bands": pricing_bands, @@ -290,7 +290,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/pricings/{id}", + path_template("/organizations/{org_id}/pricings/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -474,7 +474,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/pricings/{id}", + path_template("/organizations/{org_id}/pricings/{id}", org_id=org_id, id=id), body=maybe_transform( { "pricing_bands": pricing_bands, @@ -555,7 +555,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/pricings", + path_template("/organizations/{org_id}/pricings", org_id=org_id), page=SyncCursor[PricingResponse], options=make_request_options( extra_headers=extra_headers, @@ -609,7 +609,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/pricings/{id}", + path_template("/organizations/{org_id}/pricings/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -818,7 +818,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/pricings", + path_template("/organizations/{org_id}/pricings", org_id=org_id), body=await async_maybe_transform( { "pricing_bands": pricing_bands, @@ -880,7 +880,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/pricings/{id}", + path_template("/organizations/{org_id}/pricings/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1064,7 +1064,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/pricings/{id}", + path_template("/organizations/{org_id}/pricings/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "pricing_bands": pricing_bands, @@ -1145,7 +1145,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/pricings", + path_template("/organizations/{org_id}/pricings", org_id=org_id), page=AsyncCursor[PricingResponse], options=make_request_options( extra_headers=extra_headers, @@ -1199,7 +1199,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/pricings/{id}", + path_template("/organizations/{org_id}/pricings/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/products.py b/src/m3ter/resources/products.py index 221859d8..5ccf8964 100644 --- a/src/m3ter/resources/products.py +++ b/src/m3ter/resources/products.py @@ -8,7 +8,7 @@ from ..types import product_list_params, product_create_params, product_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -110,7 +110,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/products", + path_template("/organizations/{org_id}/products", org_id=org_id), body=maybe_transform( { "code": code, @@ -160,7 +160,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/products/{id}", + path_template("/organizations/{org_id}/products/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -237,7 +237,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/products/{id}", + path_template("/organizations/{org_id}/products/{id}", org_id=org_id, id=id), body=maybe_transform( { "code": code, @@ -295,7 +295,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/products", + path_template("/organizations/{org_id}/products", org_id=org_id), page=SyncCursor[ProductResponse], options=make_request_options( extra_headers=extra_headers, @@ -348,7 +348,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/products/{id}", + path_template("/organizations/{org_id}/products/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -442,7 +442,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/products", + path_template("/organizations/{org_id}/products", org_id=org_id), body=await async_maybe_transform( { "code": code, @@ -492,7 +492,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/products/{id}", + path_template("/organizations/{org_id}/products/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -569,7 +569,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/products/{id}", + path_template("/organizations/{org_id}/products/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "code": code, @@ -627,7 +627,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/products", + path_template("/organizations/{org_id}/products", org_id=org_id), page=AsyncCursor[ProductResponse], options=make_request_options( extra_headers=extra_headers, @@ -680,7 +680,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/products/{id}", + path_template("/organizations/{org_id}/products/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/resource_groups.py b/src/m3ter/resources/resource_groups.py index d494d042..277d8f12 100644 --- a/src/m3ter/resources/resource_groups.py +++ b/src/m3ter/resources/resource_groups.py @@ -16,7 +16,7 @@ resource_group_list_permissions_params, ) 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 ( @@ -125,7 +125,7 @@ def create( if not type: raise ValueError(f"Expected a non-empty value for `type` but received {type!r}") return self._post( - f"/organizations/{org_id}/resourcegroups/{type}", + path_template("/organizations/{org_id}/resourcegroups/{type}", org_id=org_id, type=type), body=maybe_transform( { "name": name, @@ -173,7 +173,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/resourcegroups/{type}/{id}", + path_template("/organizations/{org_id}/resourcegroups/{type}/{id}", org_id=org_id, type=type, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -220,7 +220,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/resourcegroups/{type}/{id}", + path_template("/organizations/{org_id}/resourcegroups/{type}/{id}", org_id=org_id, type=type, id=id), body=maybe_transform( { "name": name, @@ -271,7 +271,7 @@ def list( if not type: raise ValueError(f"Expected a non-empty value for `type` but received {type!r}") return self._get_api_list( - f"/organizations/{org_id}/resourcegroups/{type}", + path_template("/organizations/{org_id}/resourcegroups/{type}", org_id=org_id, type=type), page=SyncCursor[ResourceGroupResponse], options=make_request_options( extra_headers=extra_headers, @@ -323,7 +323,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/resourcegroups/{type}/{id}", + path_template("/organizations/{org_id}/resourcegroups/{type}/{id}", org_id=org_id, type=type, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -387,7 +387,12 @@ def add_resource( if not resource_group_id: raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}") return self._post( - f"/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/addresource", + path_template( + "/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/addresource", + org_id=org_id, + type=type, + resource_group_id=resource_group_id, + ), body=maybe_transform( { "target_id": target_id, @@ -442,7 +447,12 @@ def list_contents( if not resource_group_id: raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}") return self._get_api_list( - f"/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/contents", + path_template( + "/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/contents", + org_id=org_id, + type=type, + resource_group_id=resource_group_id, + ), page=SyncCursor[ResourceGroupListContentsResponse], options=make_request_options( extra_headers=extra_headers, @@ -501,7 +511,12 @@ def list_permissions( if not resource_group_id: raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}") return self._get_api_list( - f"/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/permissions", + path_template( + "/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/permissions", + org_id=org_id, + type=type, + resource_group_id=resource_group_id, + ), page=SyncCursor[PermissionPolicyResponse], options=make_request_options( extra_headers=extra_headers, @@ -576,7 +591,12 @@ def remove_resource( if not resource_group_id: raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}") return self._post( - f"/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/removeresource", + path_template( + "/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/removeresource", + org_id=org_id, + type=type, + resource_group_id=resource_group_id, + ), body=maybe_transform( { "target_id": target_id, @@ -683,7 +703,7 @@ async def create( if not type: raise ValueError(f"Expected a non-empty value for `type` but received {type!r}") return await self._post( - f"/organizations/{org_id}/resourcegroups/{type}", + path_template("/organizations/{org_id}/resourcegroups/{type}", org_id=org_id, type=type), body=await async_maybe_transform( { "name": name, @@ -731,7 +751,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/resourcegroups/{type}/{id}", + path_template("/organizations/{org_id}/resourcegroups/{type}/{id}", org_id=org_id, type=type, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -778,7 +798,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/resourcegroups/{type}/{id}", + path_template("/organizations/{org_id}/resourcegroups/{type}/{id}", org_id=org_id, type=type, id=id), body=await async_maybe_transform( { "name": name, @@ -829,7 +849,7 @@ def list( if not type: raise ValueError(f"Expected a non-empty value for `type` but received {type!r}") return self._get_api_list( - f"/organizations/{org_id}/resourcegroups/{type}", + path_template("/organizations/{org_id}/resourcegroups/{type}", org_id=org_id, type=type), page=AsyncCursor[ResourceGroupResponse], options=make_request_options( extra_headers=extra_headers, @@ -881,7 +901,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/resourcegroups/{type}/{id}", + path_template("/organizations/{org_id}/resourcegroups/{type}/{id}", org_id=org_id, type=type, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -945,7 +965,12 @@ async def add_resource( if not resource_group_id: raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}") return await self._post( - f"/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/addresource", + path_template( + "/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/addresource", + org_id=org_id, + type=type, + resource_group_id=resource_group_id, + ), body=await async_maybe_transform( { "target_id": target_id, @@ -1000,7 +1025,12 @@ def list_contents( if not resource_group_id: raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}") return self._get_api_list( - f"/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/contents", + path_template( + "/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/contents", + org_id=org_id, + type=type, + resource_group_id=resource_group_id, + ), page=AsyncCursor[ResourceGroupListContentsResponse], options=make_request_options( extra_headers=extra_headers, @@ -1059,7 +1089,12 @@ def list_permissions( if not resource_group_id: raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}") return self._get_api_list( - f"/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/permissions", + path_template( + "/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/permissions", + org_id=org_id, + type=type, + resource_group_id=resource_group_id, + ), page=AsyncCursor[PermissionPolicyResponse], options=make_request_options( extra_headers=extra_headers, @@ -1134,7 +1169,12 @@ async def remove_resource( if not resource_group_id: raise ValueError(f"Expected a non-empty value for `resource_group_id` but received {resource_group_id!r}") return await self._post( - f"/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/removeresource", + path_template( + "/organizations/{org_id}/resourcegroups/{type}/{resource_group_id}/removeresource", + org_id=org_id, + type=type, + resource_group_id=resource_group_id, + ), body=await async_maybe_transform( { "target_id": target_id, diff --git a/src/m3ter/resources/scheduled_event_configurations.py b/src/m3ter/resources/scheduled_event_configurations.py index a66aeb48..b4c0c1fb 100644 --- a/src/m3ter/resources/scheduled_event_configurations.py +++ b/src/m3ter/resources/scheduled_event_configurations.py @@ -10,7 +10,7 @@ scheduled_event_configuration_update_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -115,7 +115,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/scheduledevents/configurations", + path_template("/organizations/{org_id}/scheduledevents/configurations", org_id=org_id), body=maybe_transform( { "entity": entity, @@ -163,7 +163,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/scheduledevents/configurations/{id}", + path_template("/organizations/{org_id}/scheduledevents/configurations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -235,7 +235,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/scheduledevents/configurations/{id}", + path_template("/organizations/{org_id}/scheduledevents/configurations/{id}", org_id=org_id, id=id), body=maybe_transform( { "entity": entity, @@ -289,7 +289,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/scheduledevents/configurations", + path_template("/organizations/{org_id}/scheduledevents/configurations", org_id=org_id), page=SyncCursor[ScheduledEventConfigurationResponse], options=make_request_options( extra_headers=extra_headers, @@ -339,7 +339,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/scheduledevents/configurations/{id}", + path_template("/organizations/{org_id}/scheduledevents/configurations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -436,7 +436,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/scheduledevents/configurations", + path_template("/organizations/{org_id}/scheduledevents/configurations", org_id=org_id), body=await async_maybe_transform( { "entity": entity, @@ -484,7 +484,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/scheduledevents/configurations/{id}", + path_template("/organizations/{org_id}/scheduledevents/configurations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -556,7 +556,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/scheduledevents/configurations/{id}", + path_template("/organizations/{org_id}/scheduledevents/configurations/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "entity": entity, @@ -610,7 +610,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/scheduledevents/configurations", + path_template("/organizations/{org_id}/scheduledevents/configurations", org_id=org_id), page=AsyncCursor[ScheduledEventConfigurationResponse], options=make_request_options( extra_headers=extra_headers, @@ -660,7 +660,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/scheduledevents/configurations/{id}", + path_template("/organizations/{org_id}/scheduledevents/configurations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/statements/statement_definitions.py b/src/m3ter/resources/statements/statement_definitions.py index a2f9219b..ddf41982 100644 --- a/src/m3ter/resources/statements/statement_definitions.py +++ b/src/m3ter/resources/statements/statement_definitions.py @@ -8,7 +8,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 ( @@ -122,7 +122,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/statementdefinitions", + path_template("/organizations/{org_id}/statementdefinitions", org_id=org_id), body=maybe_transform( { "aggregation_frequency": aggregation_frequency, @@ -176,7 +176,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/statementdefinitions/{id}", + path_template("/organizations/{org_id}/statementdefinitions/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -251,7 +251,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/statementdefinitions/{id}", + path_template("/organizations/{org_id}/statementdefinitions/{id}", org_id=org_id, id=id), body=maybe_transform( { "aggregation_frequency": aggregation_frequency, @@ -308,7 +308,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/statementdefinitions", + path_template("/organizations/{org_id}/statementdefinitions", org_id=org_id), page=SyncCursor[StatementDefinitionResponse], options=make_request_options( extra_headers=extra_headers, @@ -360,7 +360,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/statementdefinitions/{id}", + path_template("/organizations/{org_id}/statementdefinitions/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -461,7 +461,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/statementdefinitions", + path_template("/organizations/{org_id}/statementdefinitions", org_id=org_id), body=await async_maybe_transform( { "aggregation_frequency": aggregation_frequency, @@ -515,7 +515,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/statementdefinitions/{id}", + path_template("/organizations/{org_id}/statementdefinitions/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -590,7 +590,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/statementdefinitions/{id}", + path_template("/organizations/{org_id}/statementdefinitions/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "aggregation_frequency": aggregation_frequency, @@ -647,7 +647,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/statementdefinitions", + path_template("/organizations/{org_id}/statementdefinitions", org_id=org_id), page=AsyncCursor[StatementDefinitionResponse], options=make_request_options( extra_headers=extra_headers, @@ -699,7 +699,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/statementdefinitions/{id}", + path_template("/organizations/{org_id}/statementdefinitions/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/statements/statement_jobs.py b/src/m3ter/resources/statements/statement_jobs.py index 80340116..9bcdb640 100644 --- a/src/m3ter/resources/statements/statement_jobs.py +++ b/src/m3ter/resources/statements/statement_jobs.py @@ -5,7 +5,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -139,7 +139,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/statementjobs", + path_template("/organizations/{org_id}/statementjobs", org_id=org_id), body=maybe_transform( { "bill_id": bill_id, @@ -198,7 +198,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/statementjobs/{id}", + path_template("/organizations/{org_id}/statementjobs/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -275,7 +275,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/statementjobs", + path_template("/organizations/{org_id}/statementjobs", org_id=org_id), page=SyncCursor[StatementJobResponse], options=make_request_options( extra_headers=extra_headers, @@ -331,7 +331,7 @@ def cancel( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/organizations/{org_id}/statementjobs/{id}/cancel", + path_template("/organizations/{org_id}/statementjobs/{id}/cancel", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -424,7 +424,7 @@ def create_batch( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/statementjobs/batch", + path_template("/organizations/{org_id}/statementjobs/batch", org_id=org_id), body=maybe_transform( { "bill_ids": bill_ids, @@ -553,7 +553,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/statementjobs", + path_template("/organizations/{org_id}/statementjobs", org_id=org_id), body=await async_maybe_transform( { "bill_id": bill_id, @@ -612,7 +612,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/statementjobs/{id}", + path_template("/organizations/{org_id}/statementjobs/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -689,7 +689,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/statementjobs", + path_template("/organizations/{org_id}/statementjobs", org_id=org_id), page=AsyncCursor[StatementJobResponse], options=make_request_options( extra_headers=extra_headers, @@ -745,7 +745,7 @@ async def cancel( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/organizations/{org_id}/statementjobs/{id}/cancel", + path_template("/organizations/{org_id}/statementjobs/{id}/cancel", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -838,7 +838,7 @@ async def create_batch( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/statementjobs/batch", + path_template("/organizations/{org_id}/statementjobs/batch", org_id=org_id), body=await async_maybe_transform( { "bill_ids": bill_ids, diff --git a/src/m3ter/resources/statements/statements.py b/src/m3ter/resources/statements/statements.py index c948f327..c881bc9d 100644 --- a/src/m3ter/resources/statements/statements.py +++ b/src/m3ter/resources/statements/statements.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 ( @@ -120,7 +121,7 @@ def create_csv( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._post( - f"/organizations/{org_id}/bills/{id}/statement/csv", + path_template("/organizations/{org_id}/bills/{id}/statement/csv", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -166,7 +167,7 @@ def get_csv( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/bills/{id}/statement/csv", + path_template("/organizations/{org_id}/bills/{id}/statement/csv", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -211,7 +212,7 @@ def get_json( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/bills/{id}/statement/json", + path_template("/organizations/{org_id}/bills/{id}/statement/json", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -304,7 +305,7 @@ async def create_csv( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._post( - f"/organizations/{org_id}/bills/{id}/statement/csv", + path_template("/organizations/{org_id}/bills/{id}/statement/csv", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -350,7 +351,7 @@ async def get_csv( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/bills/{id}/statement/csv", + path_template("/organizations/{org_id}/bills/{id}/statement/csv", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -395,7 +396,7 @@ async def get_json( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/bills/{id}/statement/json", + path_template("/organizations/{org_id}/bills/{id}/statement/json", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/transaction_types.py b/src/m3ter/resources/transaction_types.py index 3e025d1b..7b6acf44 100644 --- a/src/m3ter/resources/transaction_types.py +++ b/src/m3ter/resources/transaction_types.py @@ -6,7 +6,7 @@ from ..types import transaction_type_list_params, transaction_type_create_params, transaction_type_update_params from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -104,7 +104,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/picklists/transactiontypes", + path_template("/organizations/{org_id}/picklists/transactiontypes", org_id=org_id), body=maybe_transform( { "name": name, @@ -152,7 +152,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/picklists/transactiontypes/{id}", + path_template("/organizations/{org_id}/picklists/transactiontypes/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -216,7 +216,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/picklists/transactiontypes/{id}", + path_template("/organizations/{org_id}/picklists/transactiontypes/{id}", org_id=org_id, id=id), body=maybe_transform( { "name": name, @@ -283,7 +283,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/picklists/transactiontypes", + path_template("/organizations/{org_id}/picklists/transactiontypes", org_id=org_id), page=SyncCursor[TransactionTypeResponse], options=make_request_options( extra_headers=extra_headers, @@ -335,7 +335,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/picklists/transactiontypes/{id}", + path_template("/organizations/{org_id}/picklists/transactiontypes/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -425,7 +425,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/picklists/transactiontypes", + path_template("/organizations/{org_id}/picklists/transactiontypes", org_id=org_id), body=await async_maybe_transform( { "name": name, @@ -473,7 +473,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/picklists/transactiontypes/{id}", + path_template("/organizations/{org_id}/picklists/transactiontypes/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -537,7 +537,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/picklists/transactiontypes/{id}", + path_template("/organizations/{org_id}/picklists/transactiontypes/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "name": name, @@ -604,7 +604,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/picklists/transactiontypes", + path_template("/organizations/{org_id}/picklists/transactiontypes", org_id=org_id), page=AsyncCursor[TransactionTypeResponse], options=make_request_options( extra_headers=extra_headers, @@ -656,7 +656,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/picklists/transactiontypes/{id}", + path_template("/organizations/{org_id}/picklists/transactiontypes/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/usage/file_uploads/file_uploads.py b/src/m3ter/resources/usage/file_uploads/file_uploads.py index 43d0e370..18f72202 100644 --- a/src/m3ter/resources/usage/file_uploads/file_uploads.py +++ b/src/m3ter/resources/usage/file_uploads/file_uploads.py @@ -15,7 +15,7 @@ AsyncJobsResourceWithStreamingResponse, ) from ...._types import Body, Query, Headers, NotGiven, 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 ( @@ -149,7 +149,7 @@ def generate_upload_url( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/fileuploads/measurements/generateUploadUrl", + path_template("/organizations/{org_id}/fileuploads/measurements/generateUploadUrl", org_id=org_id), body=maybe_transform( { "content_length": content_length, @@ -283,7 +283,7 @@ async def generate_upload_url( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/fileuploads/measurements/generateUploadUrl", + path_template("/organizations/{org_id}/fileuploads/measurements/generateUploadUrl", org_id=org_id), body=await async_maybe_transform( { "content_length": content_length, diff --git a/src/m3ter/resources/usage/file_uploads/jobs.py b/src/m3ter/resources/usage/file_uploads/jobs.py index 4ef56b03..f507b809 100644 --- a/src/m3ter/resources/usage/file_uploads/jobs.py +++ b/src/m3ter/resources/usage/file_uploads/jobs.py @@ -7,7 +7,7 @@ import httpx from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ...._utils import maybe_transform +from ...._utils import path_template, maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import ( @@ -96,7 +96,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/fileuploads/measurements/jobs/{id}", + path_template("/organizations/{org_id}/fileuploads/measurements/jobs/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -156,7 +156,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/fileuploads/measurements/jobs", + path_template("/organizations/{org_id}/fileuploads/measurements/jobs", org_id=org_id), page=SyncCursor[FileUploadJobResponse], options=make_request_options( extra_headers=extra_headers, @@ -215,7 +215,7 @@ def get_original_download_url( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/fileuploads/measurements/jobs/{id}/original", + path_template("/organizations/{org_id}/fileuploads/measurements/jobs/{id}/original", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -294,7 +294,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/fileuploads/measurements/jobs/{id}", + path_template("/organizations/{org_id}/fileuploads/measurements/jobs/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -354,7 +354,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/fileuploads/measurements/jobs", + path_template("/organizations/{org_id}/fileuploads/measurements/jobs", org_id=org_id), page=AsyncCursor[FileUploadJobResponse], options=make_request_options( extra_headers=extra_headers, @@ -413,7 +413,7 @@ async def get_original_download_url( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/fileuploads/measurements/jobs/{id}/original", + path_template("/organizations/{org_id}/fileuploads/measurements/jobs/{id}/original", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/usage/usage.py b/src/m3ter/resources/usage/usage.py index ff91bb59..f94e4d94 100644 --- a/src/m3ter/resources/usage/usage.py +++ b/src/m3ter/resources/usage/usage.py @@ -9,7 +9,7 @@ from ...types import usage_query_params, usage_submit_params, usage_get_failed_ingest_download_url_params from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -148,7 +148,7 @@ def get_failed_ingest_download_url( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get( - f"/organizations/{org_id}/measurements/failedIngest/getDownloadUrl", + path_template("/organizations/{org_id}/measurements/failedIngest/getDownloadUrl", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -264,7 +264,7 @@ def query( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/usage/query", + path_template("/organizations/{org_id}/usage/query", org_id=org_id), body=maybe_transform( { "account_ids": account_ids, @@ -353,9 +353,8 @@ def submit( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/measurements" - if self._client._base_url_overridden - else f"https://ingest.m3ter.com/organizations/{org_id}/measurements", + ("https://ingest.m3ter.com" if not self._client._base_url_overridden else "") + + path_template("/organizations/{org_id}/measurements", org_id=org_id), body=maybe_transform({"measurements": measurements}, usage_submit_params.UsageSubmitParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -545,7 +544,7 @@ async def get_failed_ingest_download_url( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._get( - f"/organizations/{org_id}/measurements/failedIngest/getDownloadUrl", + path_template("/organizations/{org_id}/measurements/failedIngest/getDownloadUrl", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -661,7 +660,7 @@ async def query( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/usage/query", + path_template("/organizations/{org_id}/usage/query", org_id=org_id), body=await async_maybe_transform( { "account_ids": account_ids, @@ -750,9 +749,8 @@ async def submit( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/measurements" - if self._client._base_url_overridden - else f"https://ingest.m3ter.com/organizations/{org_id}/measurements", + ("https://ingest.m3ter.com" if not self._client._base_url_overridden else "") + + path_template("/organizations/{org_id}/measurements", org_id=org_id), body=await async_maybe_transform({"measurements": measurements}, usage_submit_params.UsageSubmitParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout diff --git a/src/m3ter/resources/users/invitations.py b/src/m3ter/resources/users/invitations.py index 4abb900f..47512ecb 100644 --- a/src/m3ter/resources/users/invitations.py +++ b/src/m3ter/resources/users/invitations.py @@ -8,7 +8,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -123,7 +123,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/invitations", + path_template("/organizations/{org_id}/invitations", org_id=org_id), body=maybe_transform( { "email": email, @@ -175,7 +175,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/invitations/{id}", + path_template("/organizations/{org_id}/invitations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -216,7 +216,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/invitations", + path_template("/organizations/{org_id}/invitations", org_id=org_id), page=SyncCursor[InvitationResponse], options=make_request_options( extra_headers=extra_headers, @@ -333,7 +333,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/invitations", + path_template("/organizations/{org_id}/invitations", org_id=org_id), body=await async_maybe_transform( { "email": email, @@ -385,7 +385,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/invitations/{id}", + path_template("/organizations/{org_id}/invitations/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -426,7 +426,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/invitations", + path_template("/organizations/{org_id}/invitations", org_id=org_id), page=AsyncCursor[InvitationResponse], options=make_request_options( extra_headers=extra_headers, diff --git a/src/m3ter/resources/users/users.py b/src/m3ter/resources/users/users.py index 595808f1..4e84704d 100644 --- a/src/m3ter/resources/users/users.py +++ b/src/m3ter/resources/users/users.py @@ -9,7 +9,7 @@ from ...types import user_list_params, user_update_params, user_get_permissions_params, user_get_user_groups_params from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, 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 ( @@ -110,7 +110,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/users/{id}", + path_template("/organizations/{org_id}/users/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -174,7 +174,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/users/{id}", + path_template("/organizations/{org_id}/users/{id}", org_id=org_id, id=id), body=maybe_transform( { "dt_end_access": dt_end_access, @@ -231,7 +231,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/users", + path_template("/organizations/{org_id}/users", org_id=org_id), page=SyncCursor[UserResponse], options=make_request_options( extra_headers=extra_headers, @@ -291,7 +291,7 @@ def get_permissions( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/users/{id}/permissions", + path_template("/organizations/{org_id}/users/{id}/permissions", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -370,7 +370,7 @@ def get_user_groups( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/users/{id}/usergroups", + path_template("/organizations/{org_id}/users/{id}/usergroups", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -415,7 +415,7 @@ def me( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get( - f"/organizations/{org_id}/users/me", + path_template("/organizations/{org_id}/users/me", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -454,7 +454,7 @@ def resend_password( raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._put( - f"/organizations/{org_id}/users/{id}/password/resend", + path_template("/organizations/{org_id}/users/{id}/password/resend", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -535,7 +535,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/users/{id}", + path_template("/organizations/{org_id}/users/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -599,7 +599,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/users/{id}", + path_template("/organizations/{org_id}/users/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "dt_end_access": dt_end_access, @@ -656,7 +656,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/users", + path_template("/organizations/{org_id}/users", org_id=org_id), page=AsyncCursor[UserResponse], options=make_request_options( extra_headers=extra_headers, @@ -716,7 +716,7 @@ async def get_permissions( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/users/{id}/permissions", + path_template("/organizations/{org_id}/users/{id}/permissions", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -795,7 +795,7 @@ async def get_user_groups( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/users/{id}/usergroups", + path_template("/organizations/{org_id}/users/{id}/usergroups", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -840,7 +840,7 @@ async def me( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._get( - f"/organizations/{org_id}/users/me", + path_template("/organizations/{org_id}/users/me", org_id=org_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -879,7 +879,7 @@ async def resend_password( raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._put( - f"/organizations/{org_id}/users/{id}/password/resend", + path_template("/organizations/{org_id}/users/{id}/password/resend", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/m3ter/resources/webhooks.py b/src/m3ter/resources/webhooks.py index 141621bf..5629ca2b 100644 --- a/src/m3ter/resources/webhooks.py +++ b/src/m3ter/resources/webhooks.py @@ -11,7 +11,7 @@ webhook_set_active_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, 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 ( @@ -122,7 +122,7 @@ def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._post( - f"/organizations/{org_id}/integrationdestinations/webhooks", + path_template("/organizations/{org_id}/integrationdestinations/webhooks", org_id=org_id), body=maybe_transform( { "credentials": credentials, @@ -172,7 +172,7 @@ def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._get( - f"/organizations/{org_id}/integrationdestinations/webhooks/{id}", + path_template("/organizations/{org_id}/integrationdestinations/webhooks/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -239,7 +239,7 @@ def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/integrationdestinations/webhooks/{id}", + path_template("/organizations/{org_id}/integrationdestinations/webhooks/{id}", org_id=org_id, id=id), body=maybe_transform( { "credentials": credentials, @@ -293,7 +293,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/integrationdestinations/webhooks", + path_template("/organizations/{org_id}/integrationdestinations/webhooks", org_id=org_id), page=SyncCursor[Webhook], options=make_request_options( extra_headers=extra_headers, @@ -343,7 +343,7 @@ def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._delete( - f"/organizations/{org_id}/integrationdestinations/webhooks/{id}", + path_template("/organizations/{org_id}/integrationdestinations/webhooks/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -388,7 +388,7 @@ def set_active( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return self._put( - f"/organizations/{org_id}/integrationdestinations/webhooks/{id}/active", + path_template("/organizations/{org_id}/integrationdestinations/webhooks/{id}/active", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -494,7 +494,7 @@ async def create( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return await self._post( - f"/organizations/{org_id}/integrationdestinations/webhooks", + path_template("/organizations/{org_id}/integrationdestinations/webhooks", org_id=org_id), body=await async_maybe_transform( { "credentials": credentials, @@ -544,7 +544,7 @@ async def retrieve( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._get( - f"/organizations/{org_id}/integrationdestinations/webhooks/{id}", + path_template("/organizations/{org_id}/integrationdestinations/webhooks/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -611,7 +611,7 @@ async def update( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/integrationdestinations/webhooks/{id}", + path_template("/organizations/{org_id}/integrationdestinations/webhooks/{id}", org_id=org_id, id=id), body=await async_maybe_transform( { "credentials": credentials, @@ -665,7 +665,7 @@ def list( if not org_id: raise ValueError(f"Expected a non-empty value for `org_id` but received {org_id!r}") return self._get_api_list( - f"/organizations/{org_id}/integrationdestinations/webhooks", + path_template("/organizations/{org_id}/integrationdestinations/webhooks", org_id=org_id), page=AsyncCursor[Webhook], options=make_request_options( extra_headers=extra_headers, @@ -715,7 +715,7 @@ async def delete( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._delete( - f"/organizations/{org_id}/integrationdestinations/webhooks/{id}", + path_template("/organizations/{org_id}/integrationdestinations/webhooks/{id}", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -760,7 +760,7 @@ async def set_active( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") return await self._put( - f"/organizations/{org_id}/integrationdestinations/webhooks/{id}/active", + path_template("/organizations/{org_id}/integrationdestinations/webhooks/{id}/active", org_id=org_id, id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, diff --git a/tests/test_client.py b/tests/test_client.py index 59ac85dc..6e1106cd 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -552,6 +552,30 @@ def test_default_query_option(self) -> None: client.close() + def test_hardcoded_query_params_in_url(self, client: M3ter) -> None: + request = client._build_request(FinalRequestOptions(method="get", url="/foo?beta=true")) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true"} + + request = client._build_request( + FinalRequestOptions( + method="get", + url="/foo?beta=true", + params={"limit": "10", "page": "abc"}, + ) + ) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true", "limit": "10", "page": "abc"} + + request = client._build_request( + FinalRequestOptions( + method="get", + url="/files/a%2Fb?beta=true", + params={"limit": "10"}, + ) + ) + assert request.url.raw_path == b"/files/a%2Fb?beta=true&limit=10" + def test_request_extra_json(self, client: M3ter) -> None: request = client._build_request( FinalRequestOptions( @@ -1589,6 +1613,30 @@ async def test_default_query_option(self) -> None: await client.close() + async def test_hardcoded_query_params_in_url(self, async_client: AsyncM3ter) -> None: + request = async_client._build_request(FinalRequestOptions(method="get", url="/foo?beta=true")) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true"} + + request = async_client._build_request( + FinalRequestOptions( + method="get", + url="/foo?beta=true", + params={"limit": "10", "page": "abc"}, + ) + ) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true", "limit": "10", "page": "abc"} + + request = async_client._build_request( + FinalRequestOptions( + method="get", + url="/files/a%2Fb?beta=true", + params={"limit": "10"}, + ) + ) + assert request.url.raw_path == b"/files/a%2Fb?beta=true&limit=10" + def test_request_extra_json(self, client: M3ter) -> None: request = client._build_request( FinalRequestOptions( diff --git a/tests/test_deepcopy.py b/tests/test_deepcopy.py deleted file mode 100644 index d0a2c748..00000000 --- a/tests/test_deepcopy.py +++ /dev/null @@ -1,58 +0,0 @@ -from m3ter._utils import deepcopy_minimal - - -def assert_different_identities(obj1: object, obj2: object) -> None: - assert obj1 == obj2 - assert id(obj1) != id(obj2) - - -def test_simple_dict() -> None: - obj1 = {"foo": "bar"} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - - -def test_nested_dict() -> None: - obj1 = {"foo": {"bar": True}} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert_different_identities(obj1["foo"], obj2["foo"]) - - -def test_complex_nested_dict() -> None: - obj1 = {"foo": {"bar": [{"hello": "world"}]}} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert_different_identities(obj1["foo"], obj2["foo"]) - assert_different_identities(obj1["foo"]["bar"], obj2["foo"]["bar"]) - assert_different_identities(obj1["foo"]["bar"][0], obj2["foo"]["bar"][0]) - - -def test_simple_list() -> None: - obj1 = ["a", "b", "c"] - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - - -def test_nested_list() -> None: - obj1 = ["a", [1, 2, 3]] - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert_different_identities(obj1[1], obj2[1]) - - -class MyObject: ... - - -def test_ignores_other_types() -> None: - # custom classes - my_obj = MyObject() - obj1 = {"foo": my_obj} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert obj1["foo"] is my_obj - - # tuples - obj3 = ("a", "b") - obj4 = deepcopy_minimal(obj3) - assert obj3 is obj4 diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index e4a1155a..605a2bb8 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -4,7 +4,7 @@ import pytest -from m3ter._types import FileTypes +from m3ter._types import FileTypes, ArrayFormat from m3ter._utils import extract_files @@ -35,6 +35,12 @@ def test_multiple_files() -> None: assert query == {"documents": [{}, {}]} +def test_top_level_file_array() -> None: + query = {"files": [b"file one", b"file two"], "title": "hello"} + assert extract_files(query, paths=[["files", ""]]) == [("files[]", b"file one"), ("files[]", b"file two")] + assert query == {"title": "hello"} + + @pytest.mark.parametrize( "query,paths,expected", [ @@ -62,3 +68,24 @@ def test_ignores_incorrect_paths( expected: list[tuple[str, FileTypes]], ) -> None: assert extract_files(query, paths=paths) == expected + + +@pytest.mark.parametrize( + "array_format,expected_top_level,expected_nested", + [ + ("brackets", [("files[]", b"a"), ("files[]", b"b")], [("items[][file]", b"a"), ("items[][file]", b"b")]), + ("repeat", [("files", b"a"), ("files", b"b")], [("items[file]", b"a"), ("items[file]", b"b")]), + ("comma", [("files", b"a"), ("files", b"b")], [("items[file]", b"a"), ("items[file]", b"b")]), + ("indices", [("files[0]", b"a"), ("files[1]", b"b")], [("items[0][file]", b"a"), ("items[1][file]", b"b")]), + ], +) +def test_array_format_controls_file_field_names( + array_format: ArrayFormat, + expected_top_level: list[tuple[str, FileTypes]], + expected_nested: list[tuple[str, FileTypes]], +) -> None: + top_level = {"files": [b"a", b"b"]} + assert extract_files(top_level, paths=[["files", ""]], array_format=array_format) == expected_top_level + + nested = {"items": [{"file": b"a"}, {"file": b"b"}]} + assert extract_files(nested, paths=[["items", "", "file"]], array_format=array_format) == expected_nested diff --git a/tests/test_files.py b/tests/test_files.py index 890bfc7f..a3d84e23 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -4,7 +4,8 @@ import pytest from dirty_equals import IsDict, IsList, IsBytes, IsTuple -from m3ter._files import to_httpx_files, async_to_httpx_files +from m3ter._files import to_httpx_files, deepcopy_with_paths, async_to_httpx_files +from m3ter._utils import extract_files readme_path = Path(__file__).parent.parent.joinpath("README.md") @@ -49,3 +50,99 @@ def test_string_not_allowed() -> None: "file": "foo", # type: ignore } ) + + +def assert_different_identities(obj1: object, obj2: object) -> None: + assert obj1 == obj2 + assert obj1 is not obj2 + + +class TestDeepcopyWithPaths: + def test_copies_top_level_dict(self) -> None: + original = {"file": b"data", "other": "value"} + result = deepcopy_with_paths(original, [["file"]]) + assert_different_identities(result, original) + + def test_file_value_is_same_reference(self) -> None: + file_bytes = b"contents" + original = {"file": file_bytes} + result = deepcopy_with_paths(original, [["file"]]) + assert_different_identities(result, original) + assert result["file"] is file_bytes + + def test_list_popped_wholesale(self) -> None: + files = [b"f1", b"f2"] + original = {"files": files, "title": "t"} + result = deepcopy_with_paths(original, [["files", ""]]) + assert_different_identities(result, original) + result_files = result["files"] + assert isinstance(result_files, list) + assert_different_identities(result_files, files) + + def test_nested_array_path_copies_list_and_elements(self) -> None: + elem1 = {"file": b"f1", "extra": 1} + elem2 = {"file": b"f2", "extra": 2} + original = {"items": [elem1, elem2]} + result = deepcopy_with_paths(original, [["items", "", "file"]]) + assert_different_identities(result, original) + result_items = result["items"] + assert isinstance(result_items, list) + assert_different_identities(result_items, original["items"]) + assert_different_identities(result_items[0], elem1) + assert_different_identities(result_items[1], elem2) + + def test_empty_paths_returns_same_object(self) -> None: + original = {"foo": "bar"} + result = deepcopy_with_paths(original, []) + assert result is original + + def test_multiple_paths(self) -> None: + f1 = b"file1" + f2 = b"file2" + original = {"a": f1, "b": f2, "c": "unchanged"} + result = deepcopy_with_paths(original, [["a"], ["b"]]) + assert_different_identities(result, original) + assert result["a"] is f1 + assert result["b"] is f2 + assert result["c"] is original["c"] + + def test_extract_files_does_not_mutate_original_top_level(self) -> None: + file_bytes = b"contents" + original = {"file": file_bytes, "other": "value"} + + copied = deepcopy_with_paths(original, [["file"]]) + extracted = extract_files(copied, paths=[["file"]]) + + assert extracted == [("file", file_bytes)] + assert original == {"file": file_bytes, "other": "value"} + assert copied == {"other": "value"} + + def test_extract_files_does_not_mutate_original_nested_array_path(self) -> None: + file1 = b"f1" + file2 = b"f2" + original = { + "items": [ + {"file": file1, "extra": 1}, + {"file": file2, "extra": 2}, + ], + "title": "example", + } + + copied = deepcopy_with_paths(original, [["items", "", "file"]]) + extracted = extract_files(copied, paths=[["items", "", "file"]]) + + assert [entry for _, entry in extracted] == [file1, file2] + assert original == { + "items": [ + {"file": file1, "extra": 1}, + {"file": file2, "extra": 2}, + ], + "title": "example", + } + assert copied == { + "items": [ + {"extra": 1}, + {"extra": 2}, + ], + "title": "example", + } diff --git a/tests/test_models.py b/tests/test_models.py index 615448f8..7c0d6501 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,7 +1,8 @@ import json -from typing import TYPE_CHECKING, Any, Dict, List, Union, Optional, cast +from typing import TYPE_CHECKING, Any, Dict, List, Union, Iterable, Optional, cast from datetime import datetime, timezone -from typing_extensions import Literal, Annotated, TypeAliasType +from collections import deque +from typing_extensions import Literal, Annotated, TypedDict, TypeAliasType import pytest import pydantic @@ -9,7 +10,7 @@ from m3ter._utils import PropertyInfo from m3ter._compat import PYDANTIC_V1, parse_obj, model_dump, model_json -from m3ter._models import DISCRIMINATOR_CACHE, BaseModel, construct_type +from m3ter._models import DISCRIMINATOR_CACHE, BaseModel, EagerIterable, construct_type class BasicModel(BaseModel): @@ -961,3 +962,56 @@ def __getattr__(self, attr: str) -> Item: ... assert model.a.prop == 1 assert isinstance(model.a, Item) assert model.other == "foo" + + +# NOTE: Workaround for Pydantic Iterable behavior. +# Iterable fields are replaced with a ValidatorIterator and may be consumed +# during serialization, which can cause subsequent dumps to return empty data. +# See: https://github.com/pydantic/pydantic/issues/9541 +@pytest.mark.parametrize( + "data, expected_validated", + [ + ([1, 2, 3], [1, 2, 3]), + ((1, 2, 3), (1, 2, 3)), + (set([1, 2, 3]), set([1, 2, 3])), + (iter([1, 2, 3]), [1, 2, 3]), + ([], []), + ((x for x in [1, 2, 3]), [1, 2, 3]), + (map(lambda x: x, [1, 2, 3]), [1, 2, 3]), + (frozenset([1, 2, 3]), frozenset([1, 2, 3])), + (deque([1, 2, 3]), deque([1, 2, 3])), + ], + ids=["list", "tuple", "set", "iterator", "empty", "generator", "map", "frozenset", "deque"], +) +@pytest.mark.skipif(PYDANTIC_V1, reason="this is only supported in pydantic v2") +def test_iterable_construction(data: Iterable[int], expected_validated: Iterable[int]) -> None: + class TypeWithIterable(TypedDict): + items: EagerIterable[int] + + class Model(BaseModel): + data: TypeWithIterable + + m = Model.model_validate({"data": {"items": data}}) + assert m.data["items"] == expected_validated + + # Verify repeated dumps don't lose data (the original bug) + assert m.model_dump()["data"]["items"] == list(expected_validated) + assert m.model_dump()["data"]["items"] == list(expected_validated) + + +@pytest.mark.skipif(PYDANTIC_V1, reason="this is only supported in pydantic v2") +def test_iterable_construction_str_falls_back_to_list() -> None: + # str is iterable (over chars), but str(list_of_chars) produces the list's repr + # rather than reconstructing a string from items. We special-case str to fall + # back to list instead of attempting reconstruction. + class TypeWithIterable(TypedDict): + items: EagerIterable[str] + + class Model(BaseModel): + data: TypeWithIterable + + m = Model.model_validate({"data": {"items": "hello"}}) + + # falls back to list of chars rather than calling str(["h", "e", "l", "l", "o"]) + assert m.data["items"] == ["h", "e", "l", "l", "o"] + assert m.model_dump()["data"]["items"] == ["h", "e", "l", "l", "o"] diff --git a/tests/test_utils/test_path.py b/tests/test_utils/test_path.py new file mode 100644 index 00000000..15c2363c --- /dev/null +++ b/tests/test_utils/test_path.py @@ -0,0 +1,89 @@ +from __future__ import annotations + +from typing import Any + +import pytest + +from m3ter._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)