diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..73f1b9f2 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,27 @@ +# syntax=docker/dockerfile:1 +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y \ + libxkbcommon0 \ + ca-certificates \ + make \ + curl \ + git \ + unzip \ + libc++1 \ + vim \ + termcap \ + && apt-get clean autoclean + +RUN curl -sSf https://rye-up.com/get | RYE_VERSION="0.15.2" RYE_INSTALL_OPTION="--yes" bash +ENV PATH=/root/.rye/shims:$PATH + +WORKDIR /workspace + +COPY README.md .python-version pyproject.toml requirements.lock requirements-dev.lock /workspace/ + +RUN rye sync --all-features + +COPY . /workspace + +CMD ["rye", "shell"] diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..d55fc4d6 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,20 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/debian +{ + "name": "Debian", + "build": { + "dockerfile": "Dockerfile" + } + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b842a19d..6ff0071b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,10 @@ jobs: run: | rye sync --all-features + - name: Run ruff + run: | + rye run check:ruff + - name: Run type checking run: | rye run typecheck diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 86b0e83d..cb9d2541 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.21.0" + ".": "0.22.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ecdda56..1777444c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 0.22.0 (2023-11-03) + +Full Changelog: [v0.21.0...v0.22.0](https://github.com/lithic-com/lithic-python/compare/v0.21.0...v0.22.0) + +### Features + +* **api:** add verification_attempts response property ([#223](https://github.com/lithic-com/lithic-python/issues/223)) ([84446d7](https://github.com/lithic-com/lithic-python/commit/84446d7a9e69bfe2bc4b22dca2b15ba4cfd053d5)) +* **client:** allow binary returns ([#224](https://github.com/lithic-com/lithic-python/issues/224)) ([78c7e86](https://github.com/lithic-com/lithic-python/commit/78c7e86a3930f9174e23363734499ff9b6fd1417)) +* **client:** support accessing raw response objects ([#218](https://github.com/lithic-com/lithic-python/issues/218)) ([8540bba](https://github.com/lithic-com/lithic-python/commit/8540bbac962b5241d01aee47e518033e0dfa6c5e)) +* **client:** support passing BaseModels to request params at runtime ([#225](https://github.com/lithic-com/lithic-python/issues/225)) ([ab37ce8](https://github.com/lithic-com/lithic-python/commit/ab37ce804c856b42f2964e5fc882a96199b2554d)) +* **github:** include a devcontainer setup ([#222](https://github.com/lithic-com/lithic-python/issues/222)) ([1256ea0](https://github.com/lithic-com/lithic-python/commit/1256ea00c91a566685741806c0611f32fa74a89c)) +* **package:** add classifiers ([#221](https://github.com/lithic-com/lithic-python/issues/221)) ([a1d9641](https://github.com/lithic-com/lithic-python/commit/a1d9641c633db15dff8306d45a555dcbb561a75a)) + + +### Chores + +* **internal:** minor restructuring of base client ([#220](https://github.com/lithic-com/lithic-python/issues/220)) ([2c36aa7](https://github.com/lithic-com/lithic-python/commit/2c36aa7f52575c37a7152bdfa00bc2fa5c37de92)) +* **internal:** require explicit overrides ([#217](https://github.com/lithic-com/lithic-python/issues/217)) ([c85bd62](https://github.com/lithic-com/lithic-python/commit/c85bd6213a6d8a3bbceccc700ed9004ce4d3f0cd)) + ## 0.21.0 (2023-10-26) Full Changelog: [v0.20.0...v0.21.0](https://github.com/lithic-com/lithic-python/compare/v0.20.0...v0.21.0) diff --git a/README.md b/README.md index c283910d..72f053ef 100644 --- a/README.md +++ b/README.md @@ -309,6 +309,26 @@ if response.my_field is None: print('Got json like {"my_field": null}.') ``` +### Accessing raw response data (e.g. headers) + +The "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call. + +```py +from lithic import Lithic + +client = Lithic() +response = client.cards.with_raw_response.create( + type="VIRTUAL", +) + +print(response.headers.get('X-My-Header')) + +card = response.parse() # get the object that `cards.create()` would have returned +print(card.token) +``` + +These methods return an [`APIResponse`](https://github.com/lithic-com/lithic-python/src/lithic/_response.py) object. + ### Configuring the HTTP client You can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including: diff --git a/pyproject.toml b/pyproject.toml index 47eb9e97..795aa6a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lithic" -version = "0.21.0" +version = "0.22.0" description = "Client library for the lithic API" readme = "README.md" license = "Apache-2.0" @@ -13,9 +13,25 @@ dependencies = [ "typing-extensions>=4.5, <5", "anyio>=3.5.0, <4", "distro>=1.7.0, <2", - + ] requires-python = ">= 3.7" +classifiers = [ + "Typing :: Typed", + "Intended Audience :: Developers", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Operating System :: OS Independent", + "Operating System :: POSIX", + "Operating System :: MacOS", + "Operating System :: POSIX :: Linux", + "Operating System :: Microsoft :: Windows", + "Topic :: Software Development :: Libraries :: Python Modules", +] @@ -39,7 +55,7 @@ dev-dependencies = [ "time-machine==2.9.0", "nox==2023.4.22", "dirty-equals>=0.6.0", - + ] [tool.rye.scripts] @@ -54,9 +70,10 @@ format = { chain = [ "format:ruff" = "ruff --fix ." "format:isort" = "isort ." +"check:ruff" = "ruff ." + typecheck = { chain = [ "typecheck:pyright", - "typecheck:verify-types", "typecheck:mypy" ]} "typecheck:pyright" = "pyright" @@ -100,6 +117,9 @@ exclude = [ ".venv", ".nox", ] + +reportImplicitOverride = true + reportImportCycles = false reportPrivateUsage = false diff --git a/src/lithic/_base_client.py b/src/lithic/_base_client.py index f061e668..5354c488 100644 --- a/src/lithic/_base_client.py +++ b/src/lithic/_base_client.py @@ -1,5 +1,6 @@ from __future__ import annotations +import os import json import time import uuid @@ -29,7 +30,7 @@ overload, ) from functools import lru_cache -from typing_extensions import Literal, get_args, get_origin +from typing_extensions import Literal, override import anyio import httpx @@ -49,34 +50,31 @@ ModelT, Headers, Timeout, - NoneType, NotGiven, ResponseT, Transport, AnyMapping, + PostParser, ProxiesTypes, RequestFiles, AsyncTransport, RequestOptions, UnknownResponse, ModelBuilderProtocol, + BinaryResponseContent, ) from ._utils import is_dict, is_given, is_mapping from ._compat import model_copy, model_dump -from ._models import ( - BaseModel, - GenericModel, - FinalRequestOptions, - validate_type, - construct_type, +from ._models import GenericModel, FinalRequestOptions, validate_type, construct_type +from ._response import APIResponse +from ._constants import ( + DEFAULT_LIMITS, + DEFAULT_TIMEOUT, + DEFAULT_MAX_RETRIES, + RAW_RESPONSE_HEADER, ) from ._streaming import Stream, AsyncStream -from ._exceptions import ( - APIStatusError, - APITimeoutError, - APIConnectionError, - APIResponseValidationError, -) +from ._exceptions import APIStatusError, APITimeoutError, APIConnectionError log: logging.Logger = logging.getLogger(__name__) @@ -101,19 +99,6 @@ HTTPX_DEFAULT_TIMEOUT = Timeout(5.0) -# default timeout is 1 minute -DEFAULT_TIMEOUT = Timeout(timeout=60.0, connect=5.0) -DEFAULT_MAX_RETRIES = 2 -DEFAULT_LIMITS = Limits(max_connections=100, max_keepalive_connections=20) - - -class MissingStreamClassError(TypeError): - def __init__(self) -> None: - super().__init__( - "The `stream` argument was set to `True` but the `stream_cls` argument was not given. See `lithic._streaming` for reference", - ) - - class PageInfo: """Stores the necesary information to build the request to retrieve the next page. @@ -182,6 +167,7 @@ def _params_from_url(self, url: URL) -> httpx.QueryParams: def _info_to_options(self, info: PageInfo) -> FinalRequestOptions: options = model_copy(self._options) + options._strip_raw_response_header() if not isinstance(info.params, NotGiven): options.params = {**options.params, **info.params} @@ -260,13 +246,17 @@ def __await__(self) -> Generator[Any, None, AsyncPageT]: return self._get_page().__await__() async def _get_page(self) -> AsyncPageT: - page = await self._client.request(self._page_cls, self._options) - page._set_private_attributes( # pyright: ignore[reportPrivateUsage] - model=self._model, - options=self._options, - client=self._client, - ) - return page + def _parser(resp: AsyncPageT) -> AsyncPageT: + resp._set_private_attributes( + model=self._model, + options=self._options, + client=self._client, + ) + return resp + + self._options.post_parser = _parser + + return await self._client.request(self._page_cls, self._options) async def __aiter__(self) -> AsyncIterator[ModelT]: # https://github.com/microsoft/pyright/issues/3464 @@ -317,9 +307,10 @@ async def get_next_page(self: AsyncPageT) -> AsyncPageT: _HttpxClientT = TypeVar("_HttpxClientT", bound=Union[httpx.Client, httpx.AsyncClient]) +_DefaultStreamT = TypeVar("_DefaultStreamT", bound=Union[Stream[Any], AsyncStream[Any]]) -class BaseClient(Generic[_HttpxClientT]): +class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]): _client: _HttpxClientT _version: str _base_url: URL @@ -330,6 +321,7 @@ class BaseClient(Generic[_HttpxClientT]): _transport: Transport | AsyncTransport | None _strict_response_validation: bool _idempotency_header: str | None + _default_stream_cls: type[_DefaultStreamT] | None = None def __init__( self, @@ -409,18 +401,6 @@ def _build_headers(self, options: FinalRequestOptions) -> httpx.Headers: return headers - def _prepare_request( - self, - request: httpx.Request, # noqa: ARG002 - ) -> None: - """This method is used as a callback for mutating the `Request` object - after it has been constructed. - - This is useful for cases where you want to add certain headers based off of - the request properties, e.g. `url`, `method` etc. - """ - return None - def _prepare_url(self, url: str) -> URL: """ Merge a URL argument together with any 'base_url' on the client, @@ -473,7 +453,7 @@ def _build_request( kwargs["data"] = self._serialize_multipartform(json_data) # TODO: report this error to httpx - request = self._client.build_request( # pyright: ignore[reportUnknownMemberType] + return self._client.build_request( # pyright: ignore[reportUnknownMemberType] headers=headers, timeout=self.timeout if isinstance(options.timeout, NotGiven) else options.timeout, method=options.method, @@ -487,8 +467,6 @@ def _build_request( files=options.files, **kwargs, ) - self._prepare_request(request) - return request def _serialize_multipartform(self, data: Mapping[object, object]) -> dict[str, object]: items = self.qs.stringify_items( @@ -504,80 +482,28 @@ def _serialize_multipartform(self, data: Mapping[object, object]) -> dict[str, o serialized[key] = value return serialized - def _extract_stream_chunk_type(self, stream_cls: type) -> type: - args = get_args(stream_cls) - if not args: - raise TypeError( - f"Expected stream_cls to have been given a generic type argument, e.g. Stream[Foo] but received {stream_cls}", - ) - return cast(type, args[0]) - def _process_response( self, *, cast_to: Type[ResponseT], - options: FinalRequestOptions, # noqa: ARG002 + options: FinalRequestOptions, response: httpx.Response, + stream: bool, + stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, ) -> ResponseT: - if cast_to is NoneType: - return cast(ResponseT, None) - - if cast_to == str: - return cast(ResponseT, response.text) - - origin = get_origin(cast_to) or cast_to - - if inspect.isclass(origin) and issubclass(origin, httpx.Response): - # Because of the invariance of our ResponseT TypeVar, users can subclass httpx.Response - # and pass that class to our request functions. We cannot change the variance to be either - # covariant or contravariant as that makes our usage of ResponseT illegal. We could construct - # the response class ourselves but that is something that should be supported directly in httpx - # as it would be easy to incorrectly construct the Response object due to the multitude of arguments. - if cast_to != httpx.Response: - raise ValueError(f"Subclasses of httpx.Response cannot be passed to `cast_to`") - return cast(ResponseT, response) - - # The check here is necessary as we are subverting the the type system - # with casts as the relationship between TypeVars and Types are very strict - # which means we must return *exactly* what was input or transform it in a - # way that retains the TypeVar state. As we cannot do that in this function - # then we have to resort to using `cast`. At the time of writing, we know this - # to be safe as we have handled all the types that could be bound to the - # `ResponseT` TypeVar, however if that TypeVar is ever updated in the future, then - # this function would become unsafe but a type checker would not report an error. - if ( - cast_to is not UnknownResponse - and not origin is list - and not origin is dict - and not origin is Union - and not issubclass(origin, BaseModel) - ): - raise RuntimeError( - f"Invalid state, expected {cast_to} to be a subclass type of {BaseModel}, {dict}, {list} or {Union}." - ) - - # split is required to handle cases where additional information is included - # in the response, e.g. application/json; charset=utf-8 - content_type, *_ = response.headers.get("content-type").split(";") - if content_type != "application/json": - if self._strict_response_validation: - raise APIResponseValidationError( - response=response, - message=f"Expected Content-Type response header to be `application/json` but received `{content_type}` instead.", - body=response.text, - ) - - # If the API responds with content that isn't JSON then we just return - # the (decoded) text without performing any parsing so that you can still - # handle the response however you need to. - return response.text # type: ignore + api_response = APIResponse( + raw=response, + client=self, + cast_to=cast_to, + stream=stream, + stream_cls=stream_cls, + options=options, + ) - data = response.json() + if response.request.headers.get(RAW_RESPONSE_HEADER) == "true": + return cast(ResponseT, api_response) - try: - return self._process_response_data(data=data, cast_to=cast_to, response=response) - except pydantic.ValidationError as err: - raise APIResponseValidationError(response=response, body=data) from err + return api_response.parse() def _process_response_data( self, @@ -734,7 +660,7 @@ def _idempotency_key(self) -> str: return f"stainless-python-retry-{uuid.uuid4()}" -class SyncAPIClient(BaseClient[httpx.Client]): +class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]): _client: httpx.Client _has_custom_http_client: bool _default_stream_cls: type[Stream[Any]] | None = None @@ -843,6 +769,24 @@ def __exit__( ) -> None: self.close() + def _prepare_options( + self, + options: FinalRequestOptions, # noqa: ARG002 + ) -> None: + """Hook for mutating the given options""" + return None + + def _prepare_request( + self, + request: httpx.Request, # noqa: ARG002 + ) -> None: + """This method is used as a callback for mutating the `Request` object + after it has been constructed. + This is useful for cases where you want to add certain headers based off of + the request properties, e.g. `url`, `method` etc. + """ + return None + @overload def request( self, @@ -904,8 +848,11 @@ def _request( stream: bool, stream_cls: type[_StreamT] | None, ) -> ResponseT | _StreamT: + self._prepare_options(options) + retries = self._remaining_retries(remaining_retries, options) request = self._build_request(options) + self._prepare_request(request) try: response = self._client.send(request, auth=self.custom_auth, stream=stream) @@ -930,23 +877,32 @@ def _request( raise self._make_status_error_from_response(err.response) from None except httpx.TimeoutException as err: if retries > 0: - return self._retry_request(options, cast_to, retries, stream=stream, stream_cls=stream_cls) + return self._retry_request( + options, + cast_to, + retries, + stream=stream, + stream_cls=stream_cls, + ) raise APITimeoutError(request=request) from err except Exception as err: if retries > 0: - return self._retry_request(options, cast_to, retries, stream=stream, stream_cls=stream_cls) + return self._retry_request( + options, + cast_to, + retries, + stream=stream, + stream_cls=stream_cls, + ) raise APIConnectionError(request=request) from err - if stream: - if stream_cls: - return stream_cls(cast_to=self._extract_stream_chunk_type(stream_cls), response=response, client=self) - - stream_cls = cast("type[_StreamT] | None", self._default_stream_cls) - if stream_cls is None: - raise MissingStreamClassError() - return stream_cls(cast_to=cast_to, response=response, client=self) - - return self._process_response(cast_to=cast_to, options=options, response=response) + return self._process_response( + cast_to=cast_to, + options=options, + response=response, + stream=stream, + stream_cls=stream_cls, + ) def _retry_request( self, @@ -980,13 +936,17 @@ def _request_api_list( page: Type[SyncPageT], options: FinalRequestOptions, ) -> SyncPageT: - resp = self.request(page, options, stream=False) - resp._set_private_attributes( # pyright: ignore[reportPrivateUsage] - client=self, - model=model, - options=options, - ) - return resp + def _parser(resp: SyncPageT) -> SyncPageT: + resp._set_private_attributes( + client=self, + model=model, + options=options, + ) + return resp + + options.post_parser = _parser + + return self.request(page, options, stream=False) @overload def get( @@ -1144,7 +1104,7 @@ def get_api_list( return self._request_api_list(model, page, opts) -class AsyncAPIClient(BaseClient[httpx.AsyncClient]): +class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]): _client: httpx.AsyncClient _has_custom_http_client: bool _default_stream_cls: type[AsyncStream[Any]] | None = None @@ -1250,6 +1210,24 @@ async def __aexit__( ) -> None: await self.close() + async def _prepare_options( + self, + options: FinalRequestOptions, # noqa: ARG002 + ) -> None: + """Hook for mutating the given options""" + return None + + async def _prepare_request( + self, + request: httpx.Request, # noqa: ARG002 + ) -> None: + """This method is used as a callback for mutating the `Request` object + after it has been constructed. + This is useful for cases where you want to add certain headers based off of + the request properties, e.g. `url`, `method` etc. + """ + return None + @overload async def request( self, @@ -1311,8 +1289,11 @@ async def _request( stream_cls: type[_AsyncStreamT] | None, remaining_retries: int | None, ) -> ResponseT | _AsyncStreamT: + await self._prepare_options(options) + retries = self._remaining_retries(remaining_retries, options) request = self._build_request(options) + await self._prepare_request(request) try: response = await self._client.send(request, auth=self.custom_auth, stream=stream) @@ -1354,16 +1335,13 @@ async def _request( return await self._retry_request(options, cast_to, retries, stream=stream, stream_cls=stream_cls) raise APIConnectionError(request=request) from err - if stream: - if stream_cls: - return stream_cls(cast_to=self._extract_stream_chunk_type(stream_cls), response=response, client=self) - - stream_cls = cast("type[_AsyncStreamT] | None", self._default_stream_cls) - if stream_cls is None: - raise MissingStreamClassError() - return stream_cls(cast_to=cast_to, response=response, client=self) - - return self._process_response(cast_to=cast_to, options=options, response=response) + return self._process_response( + cast_to=cast_to, + options=options, + response=response, + stream=stream, + stream_cls=stream_cls, + ) async def _retry_request( self, @@ -1560,6 +1538,7 @@ def make_request_options( extra_body: Body | None = None, idempotency_key: str | None = None, timeout: float | None | NotGiven = NOT_GIVEN, + post_parser: PostParser | NotGiven = NOT_GIVEN, ) -> RequestOptions: """Create a dict of type RequestOptions without keys of NotGiven values.""" options: RequestOptions = {} @@ -1581,6 +1560,10 @@ def make_request_options( if idempotency_key is not None: options["idempotency_key"] = idempotency_key + if is_given(post_parser): + # internal + options["post_parser"] = post_parser # type: ignore + return options @@ -1588,6 +1571,7 @@ class OtherPlatform: def __init__(self, name: str) -> None: self.name = name + @override def __str__(self) -> str: return f"Other:{self.name}" @@ -1649,6 +1633,7 @@ class OtherArch: def __init__(self, name: str) -> None: self.name = name + @override def __str__(self) -> str: return f"other:{self.name}" @@ -1689,3 +1674,94 @@ def _merge_mappings( """ merged = {**obj1, **obj2} return {key: value for key, value in merged.items() if not isinstance(value, Omit)} + + +class HttpxBinaryResponseContent(BinaryResponseContent): + response: httpx.Response + + def __init__(self, response: httpx.Response) -> None: + self.response = response + + @property + @override + def content(self) -> bytes: + return self.response.content + + @property + @override + def text(self) -> str: + return self.response.text + + @property + @override + def encoding(self) -> Optional[str]: + return self.response.encoding + + @property + @override + def charset_encoding(self) -> Optional[str]: + return self.response.charset_encoding + + @override + def json(self, **kwargs: Any) -> Any: + return self.response.json(**kwargs) + + @override + def read(self) -> bytes: + return self.response.read() + + @override + def iter_bytes(self, chunk_size: Optional[int] = None) -> Iterator[bytes]: + return self.response.iter_bytes(chunk_size) + + @override + def iter_text(self, chunk_size: Optional[int] = None) -> Iterator[str]: + return self.response.iter_text(chunk_size) + + @override + def iter_lines(self) -> Iterator[str]: + return self.response.iter_lines() + + @override + def iter_raw(self, chunk_size: Optional[int] = None) -> Iterator[bytes]: + return self.response.iter_raw(chunk_size) + + @override + def stream_to_file(self, file: str | os.PathLike[str]) -> None: + with open(file, mode="wb") as f: + for data in self.response.iter_bytes(): + f.write(data) + + @override + def close(self) -> None: + return self.response.close() + + @override + async def aread(self) -> bytes: + return await self.response.aread() + + @override + async def aiter_bytes(self, chunk_size: Optional[int] = None) -> AsyncIterator[bytes]: + return self.response.aiter_bytes(chunk_size) + + @override + async def aiter_text(self, chunk_size: Optional[int] = None) -> AsyncIterator[str]: + return self.response.aiter_text(chunk_size) + + @override + async def aiter_lines(self) -> AsyncIterator[str]: + return self.response.aiter_lines() + + @override + async def aiter_raw(self, chunk_size: Optional[int] = None) -> AsyncIterator[bytes]: + return self.response.aiter_raw(chunk_size) + + @override + async def astream_to_file(self, file: str | os.PathLike[str]) -> None: + with open(file, mode="wb") as f: + async for data in self.response.aiter_bytes(): + f.write(data) + + @override + async def aclose(self) -> None: + return await self.response.aclose() diff --git a/src/lithic/_client.py b/src/lithic/_client.py index f449a0a6..be7fc379 100644 --- a/src/lithic/_client.py +++ b/src/lithic/_client.py @@ -5,7 +5,7 @@ import os import asyncio from typing import Dict, Union, Mapping -from typing_extensions import Literal +from typing_extensions import Literal, override import httpx @@ -27,6 +27,7 @@ ) from ._utils import is_given from ._version import __version__ +from ._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ._streaming import Stream as Stream from ._streaming import AsyncStream as AsyncStream from ._exceptions import LithicError, APIStatusError @@ -80,6 +81,7 @@ class Lithic(SyncAPIClient): card_product: resources.CardProduct card_programs: resources.CardPrograms digital_card_art: resources.DigitalCardArtResource + with_raw_response: LithicWithRawResponse # client options api_key: str @@ -180,17 +182,21 @@ def __init__( self.card_product = resources.CardProduct(self) self.card_programs = resources.CardPrograms(self) self.digital_card_art = resources.DigitalCardArtResource(self) + self.with_raw_response = LithicWithRawResponse(self) @property + @override def qs(self) -> Querystring: return Querystring(array_format="comma") @property + @override def auth_headers(self) -> dict[str, str]: api_key = self.api_key return {"Authorization": api_key} @property + @override def default_headers(self) -> dict[str, str | Omit]: return { **super().default_headers, @@ -302,6 +308,7 @@ def api_status( cast_to=APIStatus, ) + @override def _make_status_error( self, err_msg: str, @@ -358,6 +365,7 @@ class AsyncLithic(AsyncAPIClient): card_product: resources.AsyncCardProduct card_programs: resources.AsyncCardPrograms digital_card_art: resources.AsyncDigitalCardArtResource + with_raw_response: AsyncLithicWithRawResponse # client options api_key: str @@ -458,17 +466,21 @@ def __init__( self.card_product = resources.AsyncCardProduct(self) self.card_programs = resources.AsyncCardPrograms(self) self.digital_card_art = resources.AsyncDigitalCardArtResource(self) + self.with_raw_response = AsyncLithicWithRawResponse(self) @property + @override def qs(self) -> Querystring: return Querystring(array_format="comma") @property + @override def auth_headers(self) -> dict[str, str]: api_key = self.api_key return {"Authorization": api_key} @property + @override def default_headers(self) -> dict[str, str | Omit]: return { **super().default_headers, @@ -583,6 +595,7 @@ async def api_status( cast_to=APIStatus, ) + @override def _make_status_error( self, err_msg: str, @@ -616,6 +629,72 @@ def _make_status_error( return APIStatusError(err_msg, response=response, body=body) +class LithicWithRawResponse: + def __init__(self, client: Lithic) -> None: + self.accounts = resources.AccountsWithRawResponse(client.accounts) + self.account_holders = resources.AccountHoldersWithRawResponse(client.account_holders) + self.auth_rules = resources.AuthRulesWithRawResponse(client.auth_rules) + self.auth_stream_enrollment = resources.AuthStreamEnrollmentResourceWithRawResponse( + client.auth_stream_enrollment + ) + self.tokenization_decisioning = resources.TokenizationDecisioningWithRawResponse( + client.tokenization_decisioning + ) + self.tokenizations = resources.TokenizationsWithRawResponse(client.tokenizations) + self.cards = resources.CardsWithRawResponse(client.cards) + self.balances = resources.BalancesWithRawResponse(client.balances) + self.aggregate_balances = resources.AggregateBalancesWithRawResponse(client.aggregate_balances) + self.disputes = resources.DisputesWithRawResponse(client.disputes) + self.events = resources.EventsWithRawResponse(client.events) + self.financial_accounts = resources.FinancialAccountsWithRawResponse(client.financial_accounts) + self.transactions = resources.TransactionsWithRawResponse(client.transactions) + self.responder_endpoints = resources.ResponderEndpointsWithRawResponse(client.responder_endpoints) + self.external_bank_accounts = resources.ExternalBankAccountsWithRawResponse(client.external_bank_accounts) + self.payments = resources.PaymentsWithRawResponse(client.payments) + self.three_ds = resources.ThreeDSWithRawResponse(client.three_ds) + self.reports = resources.ReportsWithRawResponse(client.reports) + self.card_product = resources.CardProductWithRawResponse(client.card_product) + self.card_programs = resources.CardProgramsWithRawResponse(client.card_programs) + self.digital_card_art = resources.DigitalCardArtResourceWithRawResponse(client.digital_card_art) + + self.api_status = to_raw_response_wrapper( + client.api_status, + ) + + +class AsyncLithicWithRawResponse: + def __init__(self, client: AsyncLithic) -> None: + self.accounts = resources.AsyncAccountsWithRawResponse(client.accounts) + self.account_holders = resources.AsyncAccountHoldersWithRawResponse(client.account_holders) + self.auth_rules = resources.AsyncAuthRulesWithRawResponse(client.auth_rules) + self.auth_stream_enrollment = resources.AsyncAuthStreamEnrollmentResourceWithRawResponse( + client.auth_stream_enrollment + ) + self.tokenization_decisioning = resources.AsyncTokenizationDecisioningWithRawResponse( + client.tokenization_decisioning + ) + self.tokenizations = resources.AsyncTokenizationsWithRawResponse(client.tokenizations) + self.cards = resources.AsyncCardsWithRawResponse(client.cards) + self.balances = resources.AsyncBalancesWithRawResponse(client.balances) + self.aggregate_balances = resources.AsyncAggregateBalancesWithRawResponse(client.aggregate_balances) + self.disputes = resources.AsyncDisputesWithRawResponse(client.disputes) + self.events = resources.AsyncEventsWithRawResponse(client.events) + self.financial_accounts = resources.AsyncFinancialAccountsWithRawResponse(client.financial_accounts) + self.transactions = resources.AsyncTransactionsWithRawResponse(client.transactions) + self.responder_endpoints = resources.AsyncResponderEndpointsWithRawResponse(client.responder_endpoints) + self.external_bank_accounts = resources.AsyncExternalBankAccountsWithRawResponse(client.external_bank_accounts) + self.payments = resources.AsyncPaymentsWithRawResponse(client.payments) + self.three_ds = resources.AsyncThreeDSWithRawResponse(client.three_ds) + self.reports = resources.AsyncReportsWithRawResponse(client.reports) + self.card_product = resources.AsyncCardProductWithRawResponse(client.card_product) + self.card_programs = resources.AsyncCardProgramsWithRawResponse(client.card_programs) + self.digital_card_art = resources.AsyncDigitalCardArtResourceWithRawResponse(client.digital_card_art) + + self.api_status = async_to_raw_response_wrapper( + client.api_status, + ) + + Client = Lithic AsyncClient = AsyncLithic diff --git a/src/lithic/_constants.py b/src/lithic/_constants.py new file mode 100644 index 00000000..0c3f31df --- /dev/null +++ b/src/lithic/_constants.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. + +import httpx + +RAW_RESPONSE_HEADER = "X-Stainless-Raw-Response" + +# default timeout is 1 minute +DEFAULT_TIMEOUT = httpx.Timeout(timeout=60.0, connect=5.0) +DEFAULT_MAX_RETRIES = 2 +DEFAULT_LIMITS = httpx.Limits(max_connections=100, max_keepalive_connections=20) diff --git a/src/lithic/_models.py b/src/lithic/_models.py index 4e4107f5..40245ac9 100644 --- a/src/lithic/_models.py +++ b/src/lithic/_models.py @@ -1,7 +1,7 @@ from __future__ import annotations import inspect -from typing import TYPE_CHECKING, Any, Type, Union, Generic, TypeVar, cast +from typing import TYPE_CHECKING, Any, Type, Union, Generic, TypeVar, Callable, cast from datetime import date, datetime from typing_extensions import ( Unpack, @@ -11,6 +11,7 @@ Required, TypedDict, final, + override, runtime_checkable, ) @@ -29,7 +30,14 @@ AnyMapping, HttpxRequestFiles, ) -from ._utils import is_list, is_mapping, parse_date, parse_datetime, strip_not_given +from ._utils import ( + is_list, + is_given, + is_mapping, + parse_date, + parse_datetime, + strip_not_given, +) from ._compat import PYDANTIC_V2, ConfigDict from ._compat import GenericModel as BaseGenericModel from ._compat import ( @@ -42,6 +50,7 @@ get_model_fields, field_get_default, ) +from ._constants import RAW_RESPONSE_HEADER __all__ = ["BaseModel", "GenericModel"] @@ -59,6 +68,7 @@ class BaseModel(pydantic.BaseModel): else: @property + @override def model_fields_set(self) -> set[str]: # a forwards-compat shim for pydantic v2 return self.__fields_set__ # type: ignore @@ -66,6 +76,7 @@ def model_fields_set(self) -> set[str]: class Config(pydantic.BaseConfig): # pyright: ignore[reportDeprecated] extra: Any = pydantic.Extra.allow # type: ignore + @override def __str__(self) -> str: # mypy complains about an invalid self arg return f'{self.__repr_name__()}({self.__repr_str__(", ")})' # type: ignore[misc] @@ -73,6 +84,7 @@ def __str__(self) -> str: # Override the 'construct' method in a way that supports recursive parsing without validation. # Based on https://github.com/samuelcolvin/pydantic/issues/1168#issuecomment-817742836. @classmethod + @override def construct( cls: Type[ModelT], _fields_set: set[str] | None = None, @@ -139,6 +151,7 @@ def construct( # a specifc pydantic version as some users may not know which # pydantic version they are currently using + @override def model_dump( self, *, @@ -187,6 +200,7 @@ def model_dump( exclude_none=exclude_none, ) + @override def model_dump_json( self, *, @@ -395,6 +409,7 @@ class FinalRequestOptions(pydantic.BaseModel): timeout: Union[float, Timeout, None, NotGiven] = NotGiven() files: Union[HttpxRequestFiles, None] = None idempotency_key: Union[str, None] = None + post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven() # It should be noted that we cannot use `json` here as that would override # a BaseModel method in an incompatible fashion. @@ -413,6 +428,14 @@ def get_max_retries(self, max_retries: int) -> int: return max_retries return self.max_retries + def _strip_raw_response_header(self) -> None: + if not is_given(self.headers): + return + + if self.headers.get(RAW_RESPONSE_HEADER): + self.headers = {**self.headers} + self.headers.pop(RAW_RESPONSE_HEADER) + # override the `construct` method so that we can run custom transformations. # this is necessary as we don't want to do any actual runtime type checking # (which means we can't use validators) but we do want to ensure that `NotGiven` diff --git a/src/lithic/_response.py b/src/lithic/_response.py new file mode 100644 index 00000000..3c4c4637 --- /dev/null +++ b/src/lithic/_response.py @@ -0,0 +1,252 @@ +from __future__ import annotations + +import inspect +import datetime +import functools +from typing import TYPE_CHECKING, Any, Union, Generic, TypeVar, Callable, cast +from typing_extensions import Awaitable, ParamSpec, get_args, override, get_origin + +import httpx +import pydantic + +from ._types import NoneType, UnknownResponse, BinaryResponseContent +from ._utils import is_given +from ._models import BaseModel +from ._constants import RAW_RESPONSE_HEADER +from ._exceptions import APIResponseValidationError + +if TYPE_CHECKING: + from ._models import FinalRequestOptions + from ._base_client import Stream, BaseClient, AsyncStream + + +P = ParamSpec("P") +R = TypeVar("R") + + +class APIResponse(Generic[R]): + _cast_to: type[R] + _client: BaseClient[Any, Any] + _parsed: R | None + _stream: bool + _stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None + _options: FinalRequestOptions + + http_response: httpx.Response + + def __init__( + self, + *, + raw: httpx.Response, + cast_to: type[R], + client: BaseClient[Any, Any], + stream: bool, + stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, + options: FinalRequestOptions, + ) -> None: + self._cast_to = cast_to + self._client = client + self._parsed = None + self._stream = stream + self._stream_cls = stream_cls + self._options = options + self.http_response = raw + + def parse(self) -> R: + if self._parsed is not None: + return self._parsed + + parsed = self._parse() + if is_given(self._options.post_parser): + parsed = self._options.post_parser(parsed) + + self._parsed = parsed + return parsed + + @property + def headers(self) -> httpx.Headers: + return self.http_response.headers + + @property + def http_request(self) -> httpx.Request: + return self.http_response.request + + @property + def status_code(self) -> int: + return self.http_response.status_code + + @property + def url(self) -> httpx.URL: + return self.http_response.url + + @property + def method(self) -> str: + return self.http_request.method + + @property + def content(self) -> bytes: + return self.http_response.content + + @property + def text(self) -> str: + return self.http_response.text + + @property + def http_version(self) -> str: + return self.http_response.http_version + + @property + def elapsed(self) -> datetime.timedelta: + """The time taken for the complete request/response cycle to complete.""" + return self.http_response.elapsed + + def _parse(self) -> R: + if self._stream: + if self._stream_cls: + return cast( + R, + self._stream_cls( + cast_to=_extract_stream_chunk_type(self._stream_cls), + response=self.http_response, + client=cast(Any, self._client), + ), + ) + + stream_cls = cast("type[Stream[Any]] | type[AsyncStream[Any]] | None", self._client._default_stream_cls) + if stream_cls is None: + raise MissingStreamClassError() + + return cast( + R, + stream_cls( + cast_to=self._cast_to, + response=self.http_response, + client=cast(Any, self._client), + ), + ) + + cast_to = self._cast_to + if cast_to is NoneType: + return cast(R, None) + + response = self.http_response + if cast_to == str: + return cast(R, response.text) + + origin = get_origin(cast_to) or cast_to + + if inspect.isclass(origin) and issubclass(origin, BinaryResponseContent): + return cast(R, cast_to(response)) # type: ignore + + if origin == APIResponse: + raise RuntimeError("Unexpected state - cast_to is `APIResponse`") + + if inspect.isclass(origin) and issubclass(origin, httpx.Response): + # Because of the invariance of our ResponseT TypeVar, users can subclass httpx.Response + # and pass that class to our request functions. We cannot change the variance to be either + # covariant or contravariant as that makes our usage of ResponseT illegal. We could construct + # the response class ourselves but that is something that should be supported directly in httpx + # as it would be easy to incorrectly construct the Response object due to the multitude of arguments. + if cast_to != httpx.Response: + raise ValueError(f"Subclasses of httpx.Response cannot be passed to `cast_to`") + return cast(R, response) + + # The check here is necessary as we are subverting the the type system + # with casts as the relationship between TypeVars and Types are very strict + # which means we must return *exactly* what was input or transform it in a + # way that retains the TypeVar state. As we cannot do that in this function + # then we have to resort to using `cast`. At the time of writing, we know this + # to be safe as we have handled all the types that could be bound to the + # `ResponseT` TypeVar, however if that TypeVar is ever updated in the future, then + # this function would become unsafe but a type checker would not report an error. + if ( + cast_to is not UnknownResponse + and not origin is list + and not origin is dict + and not origin is Union + and not issubclass(origin, BaseModel) + ): + raise RuntimeError( + f"Invalid state, expected {cast_to} to be a subclass type of {BaseModel}, {dict}, {list} or {Union}." + ) + + # split is required to handle cases where additional information is included + # in the response, e.g. application/json; charset=utf-8 + content_type, *_ = response.headers.get("content-type").split(";") + if content_type != "application/json": + if self._client._strict_response_validation: + raise APIResponseValidationError( + response=response, + message=f"Expected Content-Type response header to be `application/json` but received `{content_type}` instead.", + body=response.text, + ) + + # If the API responds with content that isn't JSON then we just return + # the (decoded) text without performing any parsing so that you can still + # handle the response however you need to. + return response.text # type: ignore + + data = response.json() + + try: + return self._client._process_response_data( + data=data, + cast_to=cast_to, # type: ignore + response=response, + ) + except pydantic.ValidationError as err: + raise APIResponseValidationError(response=response, body=data) from err + + @override + def __repr__(self) -> str: + return f"" + + +class MissingStreamClassError(TypeError): + def __init__(self) -> None: + super().__init__( + "The `stream` argument was set to `True` but the `stream_cls` argument was not given. See `lithic._streaming` for reference", + ) + + +def _extract_stream_chunk_type(stream_cls: type) -> type: + args = get_args(stream_cls) + if not args: + raise TypeError( + f"Expected stream_cls to have been given a generic type argument, e.g. Stream[Foo] but received {stream_cls}", + ) + return cast(type, args[0]) + + +def to_raw_response_wrapper(func: Callable[P, R]) -> Callable[P, APIResponse[R]]: + """Higher order function that takes one of our bound API methods and wraps it + to support returning the raw `APIResponse` object directly. + """ + + @functools.wraps(func) + def wrapped(*args: P.args, **kwargs: P.kwargs) -> APIResponse[R]: + extra_headers = {**(cast(Any, kwargs.get("extra_headers")) or {})} + extra_headers[RAW_RESPONSE_HEADER] = "true" + + kwargs["extra_headers"] = extra_headers + + return cast(APIResponse[R], func(*args, **kwargs)) + + return wrapped + + +def async_to_raw_response_wrapper(func: Callable[P, Awaitable[R]]) -> Callable[P, Awaitable[APIResponse[R]]]: + """Higher order function that takes one of our bound API methods and wraps it + to support returning the raw `APIResponse` object directly. + """ + + @functools.wraps(func) + async def wrapped(*args: P.args, **kwargs: P.kwargs) -> APIResponse[R]: + extra_headers = {**(cast(Any, kwargs.get("extra_headers")) or {})} + extra_headers[RAW_RESPONSE_HEADER] = "true" + + kwargs["extra_headers"] = extra_headers + + return cast(APIResponse[R], await func(*args, **kwargs)) + + return wrapped diff --git a/src/lithic/_streaming.py b/src/lithic/_streaming.py index 18749b53..b0600fc9 100644 --- a/src/lithic/_streaming.py +++ b/src/lithic/_streaming.py @@ -3,6 +3,7 @@ import json from typing import TYPE_CHECKING, Any, Generic, Iterator, AsyncIterator +from typing_extensions import override import httpx @@ -123,6 +124,7 @@ def data(self) -> str: def json(self) -> Any: return json.loads(self.data) + @override def __repr__(self) -> str: return f"ServerSentEvent(event={self.event}, data={self.data}, id={self.id}, retry={self.retry})" diff --git a/src/lithic/_types.py b/src/lithic/_types.py index 54e6b0d9..0f250077 100644 --- a/src/lithic/_types.py +++ b/src/lithic/_types.py @@ -1,6 +1,7 @@ from __future__ import annotations from os import PathLike +from abc import ABC, abstractmethod from typing import ( IO, TYPE_CHECKING, @@ -12,12 +13,21 @@ Union, Mapping, TypeVar, + Callable, + Iterator, Optional, Sequence, + AsyncIterator, +) +from typing_extensions import ( + Literal, + Protocol, + TypeAlias, + TypedDict, + override, + runtime_checkable, ) -from typing_extensions import Literal, Protocol, TypeAlias, TypedDict, runtime_checkable -import httpx import pydantic from httpx import URL, Proxy, Timeout, Response, BaseTransport, AsyncBaseTransport @@ -32,6 +42,151 @@ ModelT = TypeVar("ModelT", bound=pydantic.BaseModel) _T = TypeVar("_T") + +class BinaryResponseContent(ABC): + def __init__( + self, + response: Any, + ) -> None: + ... + + @property + @abstractmethod + def content(self) -> bytes: + pass + + @property + @abstractmethod + def text(self) -> str: + pass + + @property + @abstractmethod + def encoding(self) -> Optional[str]: + """ + Return an encoding to use for decoding the byte content into text. + The priority for determining this is given by... + + * `.encoding = <>` has been set explicitly. + * The encoding as specified by the charset parameter in the Content-Type header. + * The encoding as determined by `default_encoding`, which may either be + a string like "utf-8" indicating the encoding to use, or may be a callable + which enables charset autodetection. + """ + pass + + @property + @abstractmethod + def charset_encoding(self) -> Optional[str]: + """ + Return the encoding, as specified by the Content-Type header. + """ + pass + + @abstractmethod + def json(self, **kwargs: Any) -> Any: + pass + + @abstractmethod + def read(self) -> bytes: + """ + Read and return the response content. + """ + pass + + @abstractmethod + def iter_bytes(self, chunk_size: Optional[int] = None) -> Iterator[bytes]: + """ + A byte-iterator over the decoded response content. + This allows us to handle gzip, deflate, and brotli encoded responses. + """ + pass + + @abstractmethod + def iter_text(self, chunk_size: Optional[int] = None) -> Iterator[str]: + """ + A str-iterator over the decoded response content + that handles both gzip, deflate, etc but also detects the content's + string encoding. + """ + pass + + @abstractmethod + def iter_lines(self) -> Iterator[str]: + pass + + @abstractmethod + def iter_raw(self, chunk_size: Optional[int] = None) -> Iterator[bytes]: + """ + A byte-iterator over the raw response content. + """ + pass + + @abstractmethod + def stream_to_file(self, file: str | PathLike[str]) -> None: + """ + Stream the output to the given file. + """ + pass + + @abstractmethod + def close(self) -> None: + """ + Close the response and release the connection. + Automatically called if the response body is read to completion. + """ + pass + + @abstractmethod + async def aread(self) -> bytes: + """ + Read and return the response content. + """ + pass + + @abstractmethod + async def aiter_bytes(self, chunk_size: Optional[int] = None) -> AsyncIterator[bytes]: + """ + A byte-iterator over the decoded response content. + This allows us to handle gzip, deflate, and brotli encoded responses. + """ + pass + + @abstractmethod + async def aiter_text(self, chunk_size: Optional[int] = None) -> AsyncIterator[str]: + """ + A str-iterator over the decoded response content + that handles both gzip, deflate, etc but also detects the content's + string encoding. + """ + pass + + @abstractmethod + async def aiter_lines(self) -> AsyncIterator[str]: + pass + + @abstractmethod + async def aiter_raw(self, chunk_size: Optional[int] = None) -> AsyncIterator[bytes]: + """ + A byte-iterator over the raw response content. + """ + pass + + async def astream_to_file(self, file: str | PathLike[str]) -> None: + """ + Stream the output to the given file. + """ + pass + + @abstractmethod + async def aclose(self) -> None: + """ + Close the response and release the connection. + Automatically called if the response body is read to completion. + """ + pass + + # Approximates httpx internal ProxiesTypes and RequestFiles types # while adding support for `PathLike` instances ProxiesDict = Dict["str | URL", Union[None, str, URL, Proxy]] @@ -119,6 +274,7 @@ def get(timeout: Union[int, NotGiven, None] = NotGiven()) -> Response: ... def __bool__(self) -> Literal[False]: return False + @override def __repr__(self) -> str: return "NOT_GIVEN" @@ -172,7 +328,7 @@ def get(self, __key: str) -> str | None: ResponseT = TypeVar( "ResponseT", - bound="Union[str, None, BaseModel, List[Any], Dict[str, Any], httpx.Response, UnknownResponse, ModelBuilderProtocol]", + bound="Union[str, None, BaseModel, List[Any], Dict[str, Any], Response, UnknownResponse, ModelBuilderProtocol, BinaryResponseContent]", ) StrBytesIntFloat = Union[str, bytes, int, float] @@ -180,3 +336,5 @@ def get(self, __key: str) -> str | None: # Note: copied from Pydantic # https://github.com/pydantic/pydantic/blob/32ea570bf96e84234d2992e1ddf40ab8a565925a/pydantic/main.py#L49 IncEx: TypeAlias = "set[int] | set[str] | dict[int, Any] | dict[str, Any] | None" + +PostParser = Callable[[Any], Any] diff --git a/src/lithic/_utils/_proxy.py b/src/lithic/_utils/_proxy.py index fd85ebd5..aa934a3f 100644 --- a/src/lithic/_utils/_proxy.py +++ b/src/lithic/_utils/_proxy.py @@ -2,7 +2,7 @@ from abc import ABC, abstractmethod from typing import Generic, TypeVar, Iterable, cast -from typing_extensions import ClassVar +from typing_extensions import ClassVar, override T = TypeVar("T") @@ -21,16 +21,20 @@ def __init__(self) -> None: def __getattr__(self, attr: str) -> object: return getattr(self.__get_proxied__(), attr) + @override def __repr__(self) -> str: return repr(self.__get_proxied__()) + @override def __str__(self) -> str: return str(self.__get_proxied__()) + @override def __dir__(self) -> Iterable[str]: return self.__get_proxied__().__dir__() @property # type: ignore + @override def __class__(self) -> type: return self.__get_proxied__().__class__ diff --git a/src/lithic/_utils/_transform.py b/src/lithic/_utils/_transform.py index c007d8b0..db40bff2 100644 --- a/src/lithic/_utils/_transform.py +++ b/src/lithic/_utils/_transform.py @@ -2,7 +2,9 @@ from typing import Any, List, Mapping, TypeVar, cast from datetime import date, datetime -from typing_extensions import Literal, get_args, get_type_hints +from typing_extensions import Literal, get_args, override, get_type_hints + +import pydantic from ._utils import ( is_list, @@ -14,7 +16,7 @@ is_annotated_type, strip_annotated_type, ) -from .._compat import is_typeddict +from .._compat import model_dump, is_typeddict _T = TypeVar("_T") @@ -52,6 +54,7 @@ def __init__( self.format = format self.format_template = format_template + @override def __repr__(self) -> str: return f"{self.__class__.__name__}(alias='{self.alias}', format={self.format}, format_template='{self.format_template}')" @@ -164,6 +167,9 @@ def _transform_recursive( data = _transform_recursive(data, annotation=annotation, inner_type=subtype) return data + if isinstance(data, pydantic.BaseModel): + return model_dump(data, exclude_unset=True, exclude_defaults=True) + return _transform_value(data, annotation) diff --git a/src/lithic/_version.py b/src/lithic/_version.py index af10ebb3..785b5738 100644 --- a/src/lithic/_version.py +++ b/src/lithic/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. __title__ = "lithic" -__version__ = "0.21.0" # x-release-please-version +__version__ = "0.22.0" # x-release-please-version diff --git a/src/lithic/pagination.py b/src/lithic/pagination.py index a847b2eb..0ed0e749 100644 --- a/src/lithic/pagination.py +++ b/src/lithic/pagination.py @@ -1,7 +1,7 @@ # File generated from our OpenAPI spec by Stainless. from typing import Any, List, Generic, TypeVar, Optional, cast -from typing_extensions import Protocol, runtime_checkable +from typing_extensions import Protocol, override, runtime_checkable from ._types import ModelT from ._models import BaseModel @@ -21,9 +21,11 @@ class SyncCursorPage(BaseSyncPage[ModelT], BasePage[ModelT], Generic[ModelT]): data: List[ModelT] has_more: bool + @override def _get_page_items(self) -> List[ModelT]: return self.data + @override def next_page_info(self) -> Optional[PageInfo]: is_forwards = not self._options.params.get("ending_before", False) @@ -48,9 +50,11 @@ class AsyncCursorPage(BaseAsyncPage[ModelT], BasePage[ModelT], Generic[ModelT]): data: List[ModelT] has_more: bool + @override def _get_page_items(self) -> List[ModelT]: return self.data + @override def next_page_info(self) -> Optional[PageInfo]: is_forwards = not self._options.params.get("ending_before", False) @@ -75,9 +79,11 @@ class SyncSinglePage(BaseSyncPage[ModelT], BasePage[ModelT], Generic[ModelT]): data: List[ModelT] has_more: bool + @override def _get_page_items(self) -> List[ModelT]: return self.data + @override def next_page_info(self) -> None: """ This page represents a response that isn't actually paginated at the API level @@ -90,9 +96,11 @@ class AsyncSinglePage(BaseAsyncPage[ModelT], BasePage[ModelT], Generic[ModelT]): data: List[ModelT] has_more: bool + @override def _get_page_items(self) -> List[ModelT]: return self.data + @override def next_page_info(self) -> None: """ This page represents a response that isn't actually paginated at the API level diff --git a/src/lithic/resources/__init__.py b/src/lithic/resources/__init__.py index eda8b518..56d93715 100644 --- a/src/lithic/resources/__init__.py +++ b/src/lithic/resources/__init__.py @@ -1,77 +1,213 @@ # File generated from our OpenAPI spec by Stainless. -from .cards import Cards, AsyncCards -from .events import Events, AsyncEvents -from .reports import Reports, AsyncReports -from .accounts import Accounts, AsyncAccounts -from .balances import Balances, AsyncBalances -from .disputes import Disputes, AsyncDisputes -from .payments import Payments, AsyncPayments -from .three_ds import ThreeDS, AsyncThreeDS +from .cards import Cards, AsyncCards, CardsWithRawResponse, AsyncCardsWithRawResponse +from .events import ( + Events, + AsyncEvents, + EventsWithRawResponse, + AsyncEventsWithRawResponse, +) +from .reports import ( + Reports, + AsyncReports, + ReportsWithRawResponse, + AsyncReportsWithRawResponse, +) +from .accounts import ( + Accounts, + AsyncAccounts, + AccountsWithRawResponse, + AsyncAccountsWithRawResponse, +) +from .balances import ( + Balances, + AsyncBalances, + BalancesWithRawResponse, + AsyncBalancesWithRawResponse, +) +from .disputes import ( + Disputes, + AsyncDisputes, + DisputesWithRawResponse, + AsyncDisputesWithRawResponse, +) +from .payments import ( + Payments, + AsyncPayments, + PaymentsWithRawResponse, + AsyncPaymentsWithRawResponse, +) +from .three_ds import ( + ThreeDS, + AsyncThreeDS, + ThreeDSWithRawResponse, + AsyncThreeDSWithRawResponse, +) from .webhooks import Webhooks, AsyncWebhooks -from .auth_rules import AuthRules, AsyncAuthRules -from .card_product import CardProduct, AsyncCardProduct -from .transactions import Transactions, AsyncTransactions -from .card_programs import CardPrograms, AsyncCardPrograms -from .tokenizations import Tokenizations, AsyncTokenizations -from .account_holders import AccountHolders, AsyncAccountHolders -from .digital_card_art import DigitalCardArtResource, AsyncDigitalCardArtResource -from .aggregate_balances import AggregateBalances, AsyncAggregateBalances -from .financial_accounts import FinancialAccounts, AsyncFinancialAccounts -from .responder_endpoints import ResponderEndpoints, AsyncResponderEndpoints +from .auth_rules import ( + AuthRules, + AsyncAuthRules, + AuthRulesWithRawResponse, + AsyncAuthRulesWithRawResponse, +) +from .card_product import ( + CardProduct, + AsyncCardProduct, + CardProductWithRawResponse, + AsyncCardProductWithRawResponse, +) +from .transactions import ( + Transactions, + AsyncTransactions, + TransactionsWithRawResponse, + AsyncTransactionsWithRawResponse, +) +from .card_programs import ( + CardPrograms, + AsyncCardPrograms, + CardProgramsWithRawResponse, + AsyncCardProgramsWithRawResponse, +) +from .tokenizations import ( + Tokenizations, + AsyncTokenizations, + TokenizationsWithRawResponse, + AsyncTokenizationsWithRawResponse, +) +from .account_holders import ( + AccountHolders, + AsyncAccountHolders, + AccountHoldersWithRawResponse, + AsyncAccountHoldersWithRawResponse, +) +from .digital_card_art import ( + DigitalCardArtResource, + AsyncDigitalCardArtResource, + DigitalCardArtResourceWithRawResponse, + AsyncDigitalCardArtResourceWithRawResponse, +) +from .aggregate_balances import ( + AggregateBalances, + AsyncAggregateBalances, + AggregateBalancesWithRawResponse, + AsyncAggregateBalancesWithRawResponse, +) +from .financial_accounts import ( + FinancialAccounts, + AsyncFinancialAccounts, + FinancialAccountsWithRawResponse, + AsyncFinancialAccountsWithRawResponse, +) +from .responder_endpoints import ( + ResponderEndpoints, + AsyncResponderEndpoints, + ResponderEndpointsWithRawResponse, + AsyncResponderEndpointsWithRawResponse, +) from .auth_stream_enrollment import ( AuthStreamEnrollmentResource, AsyncAuthStreamEnrollmentResource, + AuthStreamEnrollmentResourceWithRawResponse, + AsyncAuthStreamEnrollmentResourceWithRawResponse, +) +from .external_bank_accounts import ( + ExternalBankAccounts, + AsyncExternalBankAccounts, + ExternalBankAccountsWithRawResponse, + AsyncExternalBankAccountsWithRawResponse, ) -from .external_bank_accounts import ExternalBankAccounts, AsyncExternalBankAccounts from .tokenization_decisioning import ( TokenizationDecisioning, AsyncTokenizationDecisioning, + TokenizationDecisioningWithRawResponse, + AsyncTokenizationDecisioningWithRawResponse, ) __all__ = [ "Accounts", "AsyncAccounts", + "AccountsWithRawResponse", + "AsyncAccountsWithRawResponse", "AccountHolders", "AsyncAccountHolders", + "AccountHoldersWithRawResponse", + "AsyncAccountHoldersWithRawResponse", "AuthRules", "AsyncAuthRules", + "AuthRulesWithRawResponse", + "AsyncAuthRulesWithRawResponse", "AuthStreamEnrollmentResource", "AsyncAuthStreamEnrollmentResource", + "AuthStreamEnrollmentResourceWithRawResponse", + "AsyncAuthStreamEnrollmentResourceWithRawResponse", "TokenizationDecisioning", "AsyncTokenizationDecisioning", + "TokenizationDecisioningWithRawResponse", + "AsyncTokenizationDecisioningWithRawResponse", "Tokenizations", "AsyncTokenizations", + "TokenizationsWithRawResponse", + "AsyncTokenizationsWithRawResponse", "Cards", "AsyncCards", + "CardsWithRawResponse", + "AsyncCardsWithRawResponse", "Balances", "AsyncBalances", + "BalancesWithRawResponse", + "AsyncBalancesWithRawResponse", "AggregateBalances", "AsyncAggregateBalances", + "AggregateBalancesWithRawResponse", + "AsyncAggregateBalancesWithRawResponse", "Disputes", "AsyncDisputes", + "DisputesWithRawResponse", + "AsyncDisputesWithRawResponse", "Events", "AsyncEvents", + "EventsWithRawResponse", + "AsyncEventsWithRawResponse", "FinancialAccounts", "AsyncFinancialAccounts", + "FinancialAccountsWithRawResponse", + "AsyncFinancialAccountsWithRawResponse", "Transactions", "AsyncTransactions", + "TransactionsWithRawResponse", + "AsyncTransactionsWithRawResponse", "ResponderEndpoints", "AsyncResponderEndpoints", + "ResponderEndpointsWithRawResponse", + "AsyncResponderEndpointsWithRawResponse", "Webhooks", "AsyncWebhooks", "ExternalBankAccounts", "AsyncExternalBankAccounts", + "ExternalBankAccountsWithRawResponse", + "AsyncExternalBankAccountsWithRawResponse", "Payments", "AsyncPayments", + "PaymentsWithRawResponse", + "AsyncPaymentsWithRawResponse", "ThreeDS", "AsyncThreeDS", + "ThreeDSWithRawResponse", + "AsyncThreeDSWithRawResponse", "Reports", "AsyncReports", + "ReportsWithRawResponse", + "AsyncReportsWithRawResponse", "CardProduct", "AsyncCardProduct", + "CardProductWithRawResponse", + "AsyncCardProductWithRawResponse", "CardPrograms", "AsyncCardPrograms", + "CardProgramsWithRawResponse", + "AsyncCardProgramsWithRawResponse", "DigitalCardArtResource", "AsyncDigitalCardArtResource", + "DigitalCardArtResourceWithRawResponse", + "AsyncDigitalCardArtResourceWithRawResponse", ] diff --git a/src/lithic/resources/account_holders.py b/src/lithic/resources/account_holders.py index cb0a655f..ec717a4b 100644 --- a/src/lithic/resources/account_holders.py +++ b/src/lithic/resources/account_holders.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, overload +from typing import TYPE_CHECKING, List, overload from typing_extensions import Literal from ..types import ( @@ -19,12 +19,22 @@ from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._utils import required_args, maybe_transform from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from .._base_client import make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["AccountHolders", "AsyncAccountHolders"] class AccountHolders(SyncAPIResource): + with_raw_response: AccountHoldersWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = AccountHoldersWithRawResponse(self) + @overload def create( self, @@ -616,6 +626,12 @@ def upload_document( class AsyncAccountHolders(AsyncAPIResource): + with_raw_response: AsyncAccountHoldersWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncAccountHoldersWithRawResponse(self) + @overload async def create( self, @@ -1204,3 +1220,53 @@ async def upload_document( ), cast_to=AccountHolderDocument, ) + + +class AccountHoldersWithRawResponse: + def __init__(self, account_holders: AccountHolders) -> None: + self.create = to_raw_response_wrapper( + account_holders.create, + ) + self.retrieve = to_raw_response_wrapper( + account_holders.retrieve, + ) + self.update = to_raw_response_wrapper( + account_holders.update, + ) + self.list_documents = to_raw_response_wrapper( + account_holders.list_documents, + ) + self.resubmit = to_raw_response_wrapper( + account_holders.resubmit, + ) + self.retrieve_document = to_raw_response_wrapper( + account_holders.retrieve_document, + ) + self.upload_document = to_raw_response_wrapper( + account_holders.upload_document, + ) + + +class AsyncAccountHoldersWithRawResponse: + def __init__(self, account_holders: AsyncAccountHolders) -> None: + self.create = async_to_raw_response_wrapper( + account_holders.create, + ) + self.retrieve = async_to_raw_response_wrapper( + account_holders.retrieve, + ) + self.update = async_to_raw_response_wrapper( + account_holders.update, + ) + self.list_documents = async_to_raw_response_wrapper( + account_holders.list_documents, + ) + self.resubmit = async_to_raw_response_wrapper( + account_holders.resubmit, + ) + self.retrieve_document = async_to_raw_response_wrapper( + account_holders.retrieve_document, + ) + self.upload_document = async_to_raw_response_wrapper( + account_holders.upload_document, + ) diff --git a/src/lithic/resources/accounts/__init__.py b/src/lithic/resources/accounts/__init__.py index 5e9482cf..407c9e2f 100644 --- a/src/lithic/resources/accounts/__init__.py +++ b/src/lithic/resources/accounts/__init__.py @@ -1,6 +1,25 @@ # File generated from our OpenAPI spec by Stainless. -from .accounts import Accounts, AsyncAccounts -from .credit_configurations import CreditConfigurations, AsyncCreditConfigurations +from .accounts import ( + Accounts, + AsyncAccounts, + AccountsWithRawResponse, + AsyncAccountsWithRawResponse, +) +from .credit_configurations import ( + CreditConfigurations, + AsyncCreditConfigurations, + CreditConfigurationsWithRawResponse, + AsyncCreditConfigurationsWithRawResponse, +) -__all__ = ["CreditConfigurations", "AsyncCreditConfigurations", "Accounts", "AsyncAccounts"] +__all__ = [ + "CreditConfigurations", + "AsyncCreditConfigurations", + "CreditConfigurationsWithRawResponse", + "AsyncCreditConfigurationsWithRawResponse", + "Accounts", + "AsyncAccounts", + "AccountsWithRawResponse", + "AsyncAccountsWithRawResponse", +] diff --git a/src/lithic/resources/accounts/accounts.py b/src/lithic/resources/accounts/accounts.py index 72abf957..c6d032a3 100644 --- a/src/lithic/resources/accounts/accounts.py +++ b/src/lithic/resources/accounts/accounts.py @@ -10,9 +10,15 @@ from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ...pagination import SyncCursorPage, AsyncCursorPage from ..._base_client import AsyncPaginator, make_request_options -from .credit_configurations import CreditConfigurations, AsyncCreditConfigurations +from .credit_configurations import ( + CreditConfigurations, + AsyncCreditConfigurations, + CreditConfigurationsWithRawResponse, + AsyncCreditConfigurationsWithRawResponse, +) if TYPE_CHECKING: from ..._client import Lithic, AsyncLithic @@ -22,10 +28,12 @@ class Accounts(SyncAPIResource): credit_configurations: CreditConfigurations + with_raw_response: AccountsWithRawResponse def __init__(self, client: Lithic) -> None: super().__init__(client) self.credit_configurations = CreditConfigurations(client) + self.with_raw_response = AccountsWithRawResponse(self) def retrieve( self, @@ -202,10 +210,12 @@ def list( class AsyncAccounts(AsyncAPIResource): credit_configurations: AsyncCreditConfigurations + with_raw_response: AsyncAccountsWithRawResponse def __init__(self, client: AsyncLithic) -> None: super().__init__(client) self.credit_configurations = AsyncCreditConfigurations(client) + self.with_raw_response = AsyncAccountsWithRawResponse(self) async def retrieve( self, @@ -378,3 +388,33 @@ def list( ), model=Account, ) + + +class AccountsWithRawResponse: + def __init__(self, accounts: Accounts) -> None: + self.credit_configurations = CreditConfigurationsWithRawResponse(accounts.credit_configurations) + + self.retrieve = to_raw_response_wrapper( + accounts.retrieve, + ) + self.update = to_raw_response_wrapper( + accounts.update, + ) + self.list = to_raw_response_wrapper( + accounts.list, + ) + + +class AsyncAccountsWithRawResponse: + def __init__(self, accounts: AsyncAccounts) -> None: + self.credit_configurations = AsyncCreditConfigurationsWithRawResponse(accounts.credit_configurations) + + self.retrieve = async_to_raw_response_wrapper( + accounts.retrieve, + ) + self.update = async_to_raw_response_wrapper( + accounts.update, + ) + self.list = async_to_raw_response_wrapper( + accounts.list, + ) diff --git a/src/lithic/resources/accounts/credit_configurations.py b/src/lithic/resources/accounts/credit_configurations.py index b9973b91..f9d5f34a 100644 --- a/src/lithic/resources/accounts/credit_configurations.py +++ b/src/lithic/resources/accounts/credit_configurations.py @@ -2,17 +2,29 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from ...types import BusinessAccount from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ..._base_client import make_request_options from ...types.accounts import credit_configuration_update_params +if TYPE_CHECKING: + from ..._client import Lithic, AsyncLithic + __all__ = ["CreditConfigurations", "AsyncCreditConfigurations"] class CreditConfigurations(SyncAPIResource): + with_raw_response: CreditConfigurationsWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = CreditConfigurationsWithRawResponse(self) + def retrieve( self, account_token: str, @@ -105,6 +117,12 @@ def update( class AsyncCreditConfigurations(AsyncAPIResource): + with_raw_response: AsyncCreditConfigurationsWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncCreditConfigurationsWithRawResponse(self) + async def retrieve( self, account_token: str, @@ -194,3 +212,23 @@ async def update( ), cast_to=BusinessAccount, ) + + +class CreditConfigurationsWithRawResponse: + def __init__(self, credit_configurations: CreditConfigurations) -> None: + self.retrieve = to_raw_response_wrapper( + credit_configurations.retrieve, + ) + self.update = to_raw_response_wrapper( + credit_configurations.update, + ) + + +class AsyncCreditConfigurationsWithRawResponse: + def __init__(self, credit_configurations: AsyncCreditConfigurations) -> None: + self.retrieve = async_to_raw_response_wrapper( + credit_configurations.retrieve, + ) + self.update = async_to_raw_response_wrapper( + credit_configurations.update, + ) diff --git a/src/lithic/resources/aggregate_balances.py b/src/lithic/resources/aggregate_balances.py index 545972f6..42d45e54 100644 --- a/src/lithic/resources/aggregate_balances.py +++ b/src/lithic/resources/aggregate_balances.py @@ -2,19 +2,30 @@ from __future__ import annotations +from typing import TYPE_CHECKING from typing_extensions import Literal from ..types import AggregateBalance, aggregate_balance_list_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._utils import maybe_transform from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ..pagination import SyncSinglePage, AsyncSinglePage from .._base_client import AsyncPaginator, make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["AggregateBalances", "AsyncAggregateBalances"] class AggregateBalances(SyncAPIResource): + with_raw_response: AggregateBalancesWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = AggregateBalancesWithRawResponse(self) + def list( self, *, @@ -59,6 +70,12 @@ def list( class AsyncAggregateBalances(AsyncAPIResource): + with_raw_response: AsyncAggregateBalancesWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncAggregateBalancesWithRawResponse(self) + def list( self, *, @@ -100,3 +117,17 @@ def list( ), model=AggregateBalance, ) + + +class AggregateBalancesWithRawResponse: + def __init__(self, aggregate_balances: AggregateBalances) -> None: + self.list = to_raw_response_wrapper( + aggregate_balances.list, + ) + + +class AsyncAggregateBalancesWithRawResponse: + def __init__(self, aggregate_balances: AsyncAggregateBalances) -> None: + self.list = async_to_raw_response_wrapper( + aggregate_balances.list, + ) diff --git a/src/lithic/resources/auth_rules.py b/src/lithic/resources/auth_rules.py index e6707d51..bd4b5ac6 100644 --- a/src/lithic/resources/auth_rules.py +++ b/src/lithic/resources/auth_rules.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List +from typing import TYPE_CHECKING, List from ..types import ( AuthRule, @@ -17,13 +17,23 @@ from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._utils import maybe_transform from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ..pagination import SyncCursorPage, AsyncCursorPage from .._base_client import AsyncPaginator, make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["AuthRules", "AsyncAuthRules"] class AuthRules(SyncAPIResource): + with_raw_response: AuthRulesWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = AuthRulesWithRawResponse(self) + def create( self, *, @@ -372,6 +382,12 @@ def remove( class AsyncAuthRules(AsyncAPIResource): + with_raw_response: AsyncAuthRulesWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncAuthRulesWithRawResponse(self) + async def create( self, *, @@ -717,3 +733,47 @@ async def remove( ), cast_to=AuthRuleRemoveResponse, ) + + +class AuthRulesWithRawResponse: + def __init__(self, auth_rules: AuthRules) -> None: + self.create = to_raw_response_wrapper( + auth_rules.create, + ) + self.retrieve = to_raw_response_wrapper( + auth_rules.retrieve, + ) + self.update = to_raw_response_wrapper( + auth_rules.update, + ) + self.list = to_raw_response_wrapper( + auth_rules.list, + ) + self.apply = to_raw_response_wrapper( + auth_rules.apply, + ) + self.remove = to_raw_response_wrapper( + auth_rules.remove, + ) + + +class AsyncAuthRulesWithRawResponse: + def __init__(self, auth_rules: AsyncAuthRules) -> None: + self.create = async_to_raw_response_wrapper( + auth_rules.create, + ) + self.retrieve = async_to_raw_response_wrapper( + auth_rules.retrieve, + ) + self.update = async_to_raw_response_wrapper( + auth_rules.update, + ) + self.list = async_to_raw_response_wrapper( + auth_rules.list, + ) + self.apply = async_to_raw_response_wrapper( + auth_rules.apply, + ) + self.remove = async_to_raw_response_wrapper( + auth_rules.remove, + ) diff --git a/src/lithic/resources/auth_stream_enrollment.py b/src/lithic/resources/auth_stream_enrollment.py index ffab6b1c..227b3ac7 100644 --- a/src/lithic/resources/auth_stream_enrollment.py +++ b/src/lithic/resources/auth_stream_enrollment.py @@ -2,6 +2,8 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from ..types import ( AuthStreamSecret, AuthStreamEnrollment, @@ -10,12 +12,22 @@ from .._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven from .._utils import maybe_transform from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from .._base_client import make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["AuthStreamEnrollmentResource", "AsyncAuthStreamEnrollmentResource"] class AuthStreamEnrollmentResource(SyncAPIResource): + with_raw_response: AuthStreamEnrollmentResourceWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = AuthStreamEnrollmentResourceWithRawResponse(self) + def retrieve( self, *, @@ -175,6 +187,12 @@ def rotate_secret( class AsyncAuthStreamEnrollmentResource(AsyncAPIResource): + with_raw_response: AsyncAuthStreamEnrollmentResourceWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncAuthStreamEnrollmentResourceWithRawResponse(self) + async def retrieve( self, *, @@ -331,3 +349,41 @@ async def rotate_secret( ), cast_to=NoneType, ) + + +class AuthStreamEnrollmentResourceWithRawResponse: + def __init__(self, auth_stream_enrollment: AuthStreamEnrollmentResource) -> None: + self.retrieve = to_raw_response_wrapper( + auth_stream_enrollment.retrieve, + ) + self.disenroll = to_raw_response_wrapper( + auth_stream_enrollment.disenroll, + ) + self.enroll = to_raw_response_wrapper( + auth_stream_enrollment.enroll, + ) + self.retrieve_secret = to_raw_response_wrapper( + auth_stream_enrollment.retrieve_secret, + ) + self.rotate_secret = to_raw_response_wrapper( + auth_stream_enrollment.rotate_secret, + ) + + +class AsyncAuthStreamEnrollmentResourceWithRawResponse: + def __init__(self, auth_stream_enrollment: AsyncAuthStreamEnrollmentResource) -> None: + self.retrieve = async_to_raw_response_wrapper( + auth_stream_enrollment.retrieve, + ) + self.disenroll = async_to_raw_response_wrapper( + auth_stream_enrollment.disenroll, + ) + self.enroll = async_to_raw_response_wrapper( + auth_stream_enrollment.enroll, + ) + self.retrieve_secret = async_to_raw_response_wrapper( + auth_stream_enrollment.retrieve_secret, + ) + self.rotate_secret = async_to_raw_response_wrapper( + auth_stream_enrollment.rotate_secret, + ) diff --git a/src/lithic/resources/balances.py b/src/lithic/resources/balances.py index 378e45c2..7beca31e 100644 --- a/src/lithic/resources/balances.py +++ b/src/lithic/resources/balances.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Union +from typing import TYPE_CHECKING, Union from datetime import datetime from typing_extensions import Literal @@ -10,13 +10,23 @@ from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._utils import maybe_transform from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ..pagination import SyncSinglePage, AsyncSinglePage from .._base_client import AsyncPaginator, make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["Balances", "AsyncBalances"] class Balances(SyncAPIResource): + with_raw_response: BalancesWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = BalancesWithRawResponse(self) + def list( self, *, @@ -71,6 +81,12 @@ def list( class AsyncBalances(AsyncAPIResource): + with_raw_response: AsyncBalancesWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncBalancesWithRawResponse(self) + def list( self, *, @@ -122,3 +138,17 @@ def list( ), model=Balance, ) + + +class BalancesWithRawResponse: + def __init__(self, balances: Balances) -> None: + self.list = to_raw_response_wrapper( + balances.list, + ) + + +class AsyncBalancesWithRawResponse: + def __init__(self, balances: AsyncBalances) -> None: + self.list = async_to_raw_response_wrapper( + balances.list, + ) diff --git a/src/lithic/resources/card_product.py b/src/lithic/resources/card_product.py index 6d472464..612acc4c 100644 --- a/src/lithic/resources/card_product.py +++ b/src/lithic/resources/card_product.py @@ -2,15 +2,27 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from ..types import CardProductCreditDetailResponse from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from .._base_client import make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["CardProduct", "AsyncCardProduct"] class CardProduct(SyncAPIResource): + with_raw_response: CardProductWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = CardProductWithRawResponse(self) + def credit_detail( self, *, @@ -32,6 +44,12 @@ def credit_detail( class AsyncCardProduct(AsyncAPIResource): + with_raw_response: AsyncCardProductWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncCardProductWithRawResponse(self) + async def credit_detail( self, *, @@ -50,3 +68,17 @@ async def credit_detail( ), cast_to=CardProductCreditDetailResponse, ) + + +class CardProductWithRawResponse: + def __init__(self, card_product: CardProduct) -> None: + self.credit_detail = to_raw_response_wrapper( + card_product.credit_detail, + ) + + +class AsyncCardProductWithRawResponse: + def __init__(self, card_product: AsyncCardProduct) -> None: + self.credit_detail = async_to_raw_response_wrapper( + card_product.credit_detail, + ) diff --git a/src/lithic/resources/card_programs.py b/src/lithic/resources/card_programs.py index 6e8800fc..57424f36 100644 --- a/src/lithic/resources/card_programs.py +++ b/src/lithic/resources/card_programs.py @@ -2,17 +2,29 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from ..types import CardProgram, card_program_list_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._utils import maybe_transform from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ..pagination import SyncCursorPage, AsyncCursorPage from .._base_client import AsyncPaginator, make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["CardPrograms", "AsyncCardPrograms"] class CardPrograms(SyncAPIResource): + with_raw_response: CardProgramsWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = CardProgramsWithRawResponse(self) + def retrieve( self, card_program_token: str, @@ -99,6 +111,12 @@ def list( class AsyncCardPrograms(AsyncAPIResource): + with_raw_response: AsyncCardProgramsWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncCardProgramsWithRawResponse(self) + async def retrieve( self, card_program_token: str, @@ -182,3 +200,23 @@ def list( ), model=CardProgram, ) + + +class CardProgramsWithRawResponse: + def __init__(self, card_programs: CardPrograms) -> None: + self.retrieve = to_raw_response_wrapper( + card_programs.retrieve, + ) + self.list = to_raw_response_wrapper( + card_programs.list, + ) + + +class AsyncCardProgramsWithRawResponse: + def __init__(self, card_programs: AsyncCardPrograms) -> None: + self.retrieve = async_to_raw_response_wrapper( + card_programs.retrieve, + ) + self.list = async_to_raw_response_wrapper( + card_programs.list, + ) diff --git a/src/lithic/resources/cards/__init__.py b/src/lithic/resources/cards/__init__.py index 2e4ce107..392a8fc3 100644 --- a/src/lithic/resources/cards/__init__.py +++ b/src/lithic/resources/cards/__init__.py @@ -1,17 +1,40 @@ # File generated from our OpenAPI spec by Stainless. -from .cards import Cards, AsyncCards -from .balances import Balances, AsyncBalances -from .aggregate_balances import AggregateBalances, AsyncAggregateBalances -from .financial_transactions import FinancialTransactions, AsyncFinancialTransactions +from .cards import Cards, AsyncCards, CardsWithRawResponse, AsyncCardsWithRawResponse +from .balances import ( + Balances, + AsyncBalances, + BalancesWithRawResponse, + AsyncBalancesWithRawResponse, +) +from .aggregate_balances import ( + AggregateBalances, + AsyncAggregateBalances, + AggregateBalancesWithRawResponse, + AsyncAggregateBalancesWithRawResponse, +) +from .financial_transactions import ( + FinancialTransactions, + AsyncFinancialTransactions, + FinancialTransactionsWithRawResponse, + AsyncFinancialTransactionsWithRawResponse, +) __all__ = [ "AggregateBalances", "AsyncAggregateBalances", + "AggregateBalancesWithRawResponse", + "AsyncAggregateBalancesWithRawResponse", "Balances", "AsyncBalances", + "BalancesWithRawResponse", + "AsyncBalancesWithRawResponse", "FinancialTransactions", "AsyncFinancialTransactions", + "FinancialTransactionsWithRawResponse", + "AsyncFinancialTransactionsWithRawResponse", "Cards", "AsyncCards", + "CardsWithRawResponse", + "AsyncCardsWithRawResponse", ] diff --git a/src/lithic/resources/cards/aggregate_balances.py b/src/lithic/resources/cards/aggregate_balances.py index 0d60423e..329b4a8c 100644 --- a/src/lithic/resources/cards/aggregate_balances.py +++ b/src/lithic/resources/cards/aggregate_balances.py @@ -2,17 +2,29 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ...pagination import SyncSinglePage, AsyncSinglePage from ...types.cards import AggregateBalanceListResponse, aggregate_balance_list_params from ..._base_client import AsyncPaginator, make_request_options +if TYPE_CHECKING: + from ..._client import Lithic, AsyncLithic + __all__ = ["AggregateBalances", "AsyncAggregateBalances"] class AggregateBalances(SyncAPIResource): + with_raw_response: AggregateBalancesWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = AggregateBalancesWithRawResponse(self) + def list( self, *, @@ -62,6 +74,12 @@ def list( class AsyncAggregateBalances(AsyncAPIResource): + with_raw_response: AsyncAggregateBalancesWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncAggregateBalancesWithRawResponse(self) + def list( self, *, @@ -108,3 +126,17 @@ def list( ), model=AggregateBalanceListResponse, ) + + +class AggregateBalancesWithRawResponse: + def __init__(self, aggregate_balances: AggregateBalances) -> None: + self.list = to_raw_response_wrapper( + aggregate_balances.list, + ) + + +class AsyncAggregateBalancesWithRawResponse: + def __init__(self, aggregate_balances: AsyncAggregateBalances) -> None: + self.list = async_to_raw_response_wrapper( + aggregate_balances.list, + ) diff --git a/src/lithic/resources/cards/balances.py b/src/lithic/resources/cards/balances.py index 613fa296..0a985b41 100644 --- a/src/lithic/resources/cards/balances.py +++ b/src/lithic/resources/cards/balances.py @@ -2,21 +2,31 @@ from __future__ import annotations -from typing import Union +from typing import TYPE_CHECKING, Union from datetime import datetime from ...types import Balance from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ...pagination import SyncSinglePage, AsyncSinglePage from ...types.cards import balance_list_params from ..._base_client import AsyncPaginator, make_request_options +if TYPE_CHECKING: + from ..._client import Lithic, AsyncLithic + __all__ = ["Balances", "AsyncBalances"] class Balances(SyncAPIResource): + with_raw_response: BalancesWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = BalancesWithRawResponse(self) + def list( self, card_token: str, @@ -69,6 +79,12 @@ def list( class AsyncBalances(AsyncAPIResource): + with_raw_response: AsyncBalancesWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncBalancesWithRawResponse(self) + def list( self, card_token: str, @@ -118,3 +134,17 @@ def list( ), model=Balance, ) + + +class BalancesWithRawResponse: + def __init__(self, balances: Balances) -> None: + self.list = to_raw_response_wrapper( + balances.list, + ) + + +class AsyncBalancesWithRawResponse: + def __init__(self, balances: AsyncBalances) -> None: + self.list = async_to_raw_response_wrapper( + balances.list, + ) diff --git a/src/lithic/resources/cards/cards.py b/src/lithic/resources/cards/cards.py index db83f8da..f4388d51 100644 --- a/src/lithic/resources/cards/cards.py +++ b/src/lithic/resources/cards/cards.py @@ -27,12 +27,28 @@ ) from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform, strip_not_given -from .balances import Balances, AsyncBalances +from .balances import ( + Balances, + AsyncBalances, + BalancesWithRawResponse, + AsyncBalancesWithRawResponse, +) from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ...pagination import SyncCursorPage, AsyncCursorPage from ..._base_client import AsyncPaginator, _merge_mappings, make_request_options -from .aggregate_balances import AggregateBalances, AsyncAggregateBalances -from .financial_transactions import FinancialTransactions, AsyncFinancialTransactions +from .aggregate_balances import ( + AggregateBalances, + AsyncAggregateBalances, + AggregateBalancesWithRawResponse, + AsyncAggregateBalancesWithRawResponse, +) +from .financial_transactions import ( + FinancialTransactions, + AsyncFinancialTransactions, + FinancialTransactionsWithRawResponse, + AsyncFinancialTransactionsWithRawResponse, +) if TYPE_CHECKING: from ..._client import Lithic, AsyncLithic @@ -44,12 +60,14 @@ class Cards(SyncAPIResource): aggregate_balances: AggregateBalances balances: Balances financial_transactions: FinancialTransactions + with_raw_response: CardsWithRawResponse def __init__(self, client: Lithic) -> None: super().__init__(client) self.aggregate_balances = AggregateBalances(client) self.balances = Balances(client) self.financial_transactions = FinancialTransactions(client) + self.with_raw_response = CardsWithRawResponse(self) def create( self, @@ -756,12 +774,14 @@ class AsyncCards(AsyncAPIResource): aggregate_balances: AsyncAggregateBalances balances: AsyncBalances financial_transactions: AsyncFinancialTransactions + with_raw_response: AsyncCardsWithRawResponse def __init__(self, client: AsyncLithic) -> None: super().__init__(client) self.aggregate_balances = AsyncAggregateBalances(client) self.balances = AsyncBalances(client) self.financial_transactions = AsyncFinancialTransactions(client) + self.with_raw_response = AsyncCardsWithRawResponse(self) async def create( self, @@ -1462,3 +1482,61 @@ async def reissue( ), cast_to=Card, ) + + +class CardsWithRawResponse: + def __init__(self, cards: Cards) -> None: + self.aggregate_balances = AggregateBalancesWithRawResponse(cards.aggregate_balances) + self.balances = BalancesWithRawResponse(cards.balances) + self.financial_transactions = FinancialTransactionsWithRawResponse(cards.financial_transactions) + + self.create = to_raw_response_wrapper( + cards.create, + ) + self.retrieve = to_raw_response_wrapper( + cards.retrieve, + ) + self.update = to_raw_response_wrapper( + cards.update, + ) + self.list = to_raw_response_wrapper( + cards.list, + ) + self.embed = to_raw_response_wrapper( + cards.embed, + ) + self.provision = to_raw_response_wrapper( + cards.provision, + ) + self.reissue = to_raw_response_wrapper( + cards.reissue, + ) + + +class AsyncCardsWithRawResponse: + def __init__(self, cards: AsyncCards) -> None: + self.aggregate_balances = AsyncAggregateBalancesWithRawResponse(cards.aggregate_balances) + self.balances = AsyncBalancesWithRawResponse(cards.balances) + self.financial_transactions = AsyncFinancialTransactionsWithRawResponse(cards.financial_transactions) + + self.create = async_to_raw_response_wrapper( + cards.create, + ) + self.retrieve = async_to_raw_response_wrapper( + cards.retrieve, + ) + self.update = async_to_raw_response_wrapper( + cards.update, + ) + self.list = async_to_raw_response_wrapper( + cards.list, + ) + self.embed = async_to_raw_response_wrapper( + cards.embed, + ) + self.provision = async_to_raw_response_wrapper( + cards.provision, + ) + self.reissue = async_to_raw_response_wrapper( + cards.reissue, + ) diff --git a/src/lithic/resources/cards/financial_transactions.py b/src/lithic/resources/cards/financial_transactions.py index 8cad4848..0e8698de 100644 --- a/src/lithic/resources/cards/financial_transactions.py +++ b/src/lithic/resources/cards/financial_transactions.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Union +from typing import TYPE_CHECKING, Union from datetime import datetime from typing_extensions import Literal @@ -10,14 +10,24 @@ from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ...pagination import SyncSinglePage, AsyncSinglePage from ...types.cards import financial_transaction_list_params from ..._base_client import AsyncPaginator, make_request_options +if TYPE_CHECKING: + from ..._client import Lithic, AsyncLithic + __all__ = ["FinancialTransactions", "AsyncFinancialTransactions"] class FinancialTransactions(SyncAPIResource): + with_raw_response: FinancialTransactionsWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = FinancialTransactionsWithRawResponse(self) + def retrieve( self, financial_transaction_token: str, @@ -124,6 +134,12 @@ def list( class AsyncFinancialTransactions(AsyncAPIResource): + with_raw_response: AsyncFinancialTransactionsWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncFinancialTransactionsWithRawResponse(self) + async def retrieve( self, financial_transaction_token: str, @@ -227,3 +243,23 @@ def list( ), model=FinancialTransaction, ) + + +class FinancialTransactionsWithRawResponse: + def __init__(self, financial_transactions: FinancialTransactions) -> None: + self.retrieve = to_raw_response_wrapper( + financial_transactions.retrieve, + ) + self.list = to_raw_response_wrapper( + financial_transactions.list, + ) + + +class AsyncFinancialTransactionsWithRawResponse: + def __init__(self, financial_transactions: AsyncFinancialTransactions) -> None: + self.retrieve = async_to_raw_response_wrapper( + financial_transactions.retrieve, + ) + self.list = async_to_raw_response_wrapper( + financial_transactions.list, + ) diff --git a/src/lithic/resources/digital_card_art.py b/src/lithic/resources/digital_card_art.py index b5d9d742..3a8b614c 100644 --- a/src/lithic/resources/digital_card_art.py +++ b/src/lithic/resources/digital_card_art.py @@ -2,17 +2,29 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from ..types import DigitalCardArt, digital_card_art_list_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._utils import maybe_transform from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ..pagination import SyncCursorPage, AsyncCursorPage from .._base_client import AsyncPaginator, make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["DigitalCardArtResource", "AsyncDigitalCardArtResource"] class DigitalCardArtResource(SyncAPIResource): + with_raw_response: DigitalCardArtResourceWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = DigitalCardArtResourceWithRawResponse(self) + def list( self, *, @@ -68,6 +80,12 @@ def list( class AsyncDigitalCardArtResource(AsyncAPIResource): + with_raw_response: AsyncDigitalCardArtResourceWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncDigitalCardArtResourceWithRawResponse(self) + def list( self, *, @@ -120,3 +138,17 @@ def list( ), model=DigitalCardArt, ) + + +class DigitalCardArtResourceWithRawResponse: + def __init__(self, digital_card_art: DigitalCardArtResource) -> None: + self.list = to_raw_response_wrapper( + digital_card_art.list, + ) + + +class AsyncDigitalCardArtResourceWithRawResponse: + def __init__(self, digital_card_art: AsyncDigitalCardArtResource) -> None: + self.list = async_to_raw_response_wrapper( + digital_card_art.list, + ) diff --git a/src/lithic/resources/disputes.py b/src/lithic/resources/disputes.py index 5227d41f..b44e134b 100644 --- a/src/lithic/resources/disputes.py +++ b/src/lithic/resources/disputes.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Union +from typing import TYPE_CHECKING, List, Union from datetime import datetime from typing_extensions import Literal @@ -27,13 +27,23 @@ ) from .._utils import maybe_transform from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ..pagination import SyncCursorPage, AsyncCursorPage from .._base_client import AsyncPaginator, make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["Disputes", "AsyncDisputes"] class Disputes(SyncAPIResource): + with_raw_response: DisputesWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = DisputesWithRawResponse(self) + def create( self, *, @@ -548,6 +558,12 @@ def upload_evidence( class AsyncDisputes(AsyncAPIResource): + with_raw_response: AsyncDisputesWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncDisputesWithRawResponse(self) + async def create( self, *, @@ -1059,3 +1075,65 @@ async def upload_evidence( files = {"file": file} options = make_request_options(extra_headers={"Authorization": Omit()}) await self._put(payload.upload_url, cast_to=NoneType, body=None, files=files, options=options) + + +class DisputesWithRawResponse: + def __init__(self, disputes: Disputes) -> None: + self.create = to_raw_response_wrapper( + disputes.create, + ) + self.retrieve = to_raw_response_wrapper( + disputes.retrieve, + ) + self.update = to_raw_response_wrapper( + disputes.update, + ) + self.list = to_raw_response_wrapper( + disputes.list, + ) + self.delete = to_raw_response_wrapper( + disputes.delete, + ) + self.delete_evidence = to_raw_response_wrapper( + disputes.delete_evidence, + ) + self.initiate_evidence_upload = to_raw_response_wrapper( + disputes.initiate_evidence_upload, + ) + self.list_evidences = to_raw_response_wrapper( + disputes.list_evidences, + ) + self.retrieve_evidence = to_raw_response_wrapper( + disputes.retrieve_evidence, + ) + + +class AsyncDisputesWithRawResponse: + def __init__(self, disputes: AsyncDisputes) -> None: + self.create = async_to_raw_response_wrapper( + disputes.create, + ) + self.retrieve = async_to_raw_response_wrapper( + disputes.retrieve, + ) + self.update = async_to_raw_response_wrapper( + disputes.update, + ) + self.list = async_to_raw_response_wrapper( + disputes.list, + ) + self.delete = async_to_raw_response_wrapper( + disputes.delete, + ) + self.delete_evidence = async_to_raw_response_wrapper( + disputes.delete_evidence, + ) + self.initiate_evidence_upload = async_to_raw_response_wrapper( + disputes.initiate_evidence_upload, + ) + self.list_evidences = async_to_raw_response_wrapper( + disputes.list_evidences, + ) + self.retrieve_evidence = async_to_raw_response_wrapper( + disputes.retrieve_evidence, + ) diff --git a/src/lithic/resources/events/__init__.py b/src/lithic/resources/events/__init__.py index fb54a8e5..f1c77d9e 100644 --- a/src/lithic/resources/events/__init__.py +++ b/src/lithic/resources/events/__init__.py @@ -1,6 +1,25 @@ # File generated from our OpenAPI spec by Stainless. -from .events import Events, AsyncEvents -from .subscriptions import Subscriptions, AsyncSubscriptions +from .events import ( + Events, + AsyncEvents, + EventsWithRawResponse, + AsyncEventsWithRawResponse, +) +from .subscriptions import ( + Subscriptions, + AsyncSubscriptions, + SubscriptionsWithRawResponse, + AsyncSubscriptionsWithRawResponse, +) -__all__ = ["Subscriptions", "AsyncSubscriptions", "Events", "AsyncEvents"] +__all__ = [ + "Subscriptions", + "AsyncSubscriptions", + "SubscriptionsWithRawResponse", + "AsyncSubscriptionsWithRawResponse", + "Events", + "AsyncEvents", + "EventsWithRawResponse", + "AsyncEventsWithRawResponse", +] diff --git a/src/lithic/resources/events/events.py b/src/lithic/resources/events/events.py index 2e0b3aea..dd30d1d5 100644 --- a/src/lithic/resources/events/events.py +++ b/src/lithic/resources/events/events.py @@ -15,8 +15,14 @@ from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ...pagination import SyncCursorPage, AsyncCursorPage -from .subscriptions import Subscriptions, AsyncSubscriptions +from .subscriptions import ( + Subscriptions, + AsyncSubscriptions, + SubscriptionsWithRawResponse, + AsyncSubscriptionsWithRawResponse, +) from ..._base_client import AsyncPaginator, make_request_options if TYPE_CHECKING: @@ -27,10 +33,12 @@ class Events(SyncAPIResource): subscriptions: Subscriptions + with_raw_response: EventsWithRawResponse def __init__(self, client: Lithic) -> None: super().__init__(client) self.subscriptions = Subscriptions(client) + self.with_raw_response = EventsWithRawResponse(self) def retrieve( self, @@ -239,10 +247,12 @@ def resend( class AsyncEvents(AsyncAPIResource): subscriptions: AsyncSubscriptions + with_raw_response: AsyncEventsWithRawResponse def __init__(self, client: AsyncLithic) -> None: super().__init__(client) self.subscriptions = AsyncSubscriptions(client) + self.with_raw_response = AsyncEventsWithRawResponse(self) async def retrieve( self, @@ -447,3 +457,33 @@ async def resend( options=make_request_options(extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body), cast_to=NoneType, ) + + +class EventsWithRawResponse: + def __init__(self, events: Events) -> None: + self.subscriptions = SubscriptionsWithRawResponse(events.subscriptions) + + self.retrieve = to_raw_response_wrapper( + events.retrieve, + ) + self.list = to_raw_response_wrapper( + events.list, + ) + self.list_attempts = to_raw_response_wrapper( + events.list_attempts, + ) + + +class AsyncEventsWithRawResponse: + def __init__(self, events: AsyncEvents) -> None: + self.subscriptions = AsyncSubscriptionsWithRawResponse(events.subscriptions) + + self.retrieve = async_to_raw_response_wrapper( + events.retrieve, + ) + self.list = async_to_raw_response_wrapper( + events.list, + ) + self.list_attempts = async_to_raw_response_wrapper( + events.list_attempts, + ) diff --git a/src/lithic/resources/events/subscriptions.py b/src/lithic/resources/events/subscriptions.py index 1b337b8b..cd9b962d 100644 --- a/src/lithic/resources/events/subscriptions.py +++ b/src/lithic/resources/events/subscriptions.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Union +from typing import TYPE_CHECKING, List, Union from datetime import datetime from typing_extensions import Literal @@ -10,6 +10,7 @@ from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ...pagination import SyncCursorPage, AsyncCursorPage from ..._base_client import AsyncPaginator, make_request_options from ...types.events import ( @@ -23,10 +24,19 @@ subscription_send_simulated_example_params, ) +if TYPE_CHECKING: + from ..._client import Lithic, AsyncLithic + __all__ = ["Subscriptions", "AsyncSubscriptions"] class Subscriptions(SyncAPIResource): + with_raw_response: SubscriptionsWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = SubscriptionsWithRawResponse(self) + def create( self, *, @@ -618,6 +628,12 @@ def send_simulated_example( class AsyncSubscriptions(AsyncAPIResource): + with_raw_response: AsyncSubscriptionsWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncSubscriptionsWithRawResponse(self) + async def create( self, *, @@ -1206,3 +1222,77 @@ async def send_simulated_example( ), cast_to=NoneType, ) + + +class SubscriptionsWithRawResponse: + def __init__(self, subscriptions: Subscriptions) -> None: + self.create = to_raw_response_wrapper( + subscriptions.create, + ) + self.retrieve = to_raw_response_wrapper( + subscriptions.retrieve, + ) + self.update = to_raw_response_wrapper( + subscriptions.update, + ) + self.list = to_raw_response_wrapper( + subscriptions.list, + ) + self.delete = to_raw_response_wrapper( + subscriptions.delete, + ) + self.list_attempts = to_raw_response_wrapper( + subscriptions.list_attempts, + ) + self.recover = to_raw_response_wrapper( + subscriptions.recover, + ) + self.replay_missing = to_raw_response_wrapper( + subscriptions.replay_missing, + ) + self.retrieve_secret = to_raw_response_wrapper( + subscriptions.retrieve_secret, + ) + self.rotate_secret = to_raw_response_wrapper( + subscriptions.rotate_secret, + ) + self.send_simulated_example = to_raw_response_wrapper( + subscriptions.send_simulated_example, + ) + + +class AsyncSubscriptionsWithRawResponse: + def __init__(self, subscriptions: AsyncSubscriptions) -> None: + self.create = async_to_raw_response_wrapper( + subscriptions.create, + ) + self.retrieve = async_to_raw_response_wrapper( + subscriptions.retrieve, + ) + self.update = async_to_raw_response_wrapper( + subscriptions.update, + ) + self.list = async_to_raw_response_wrapper( + subscriptions.list, + ) + self.delete = async_to_raw_response_wrapper( + subscriptions.delete, + ) + self.list_attempts = async_to_raw_response_wrapper( + subscriptions.list_attempts, + ) + self.recover = async_to_raw_response_wrapper( + subscriptions.recover, + ) + self.replay_missing = async_to_raw_response_wrapper( + subscriptions.replay_missing, + ) + self.retrieve_secret = async_to_raw_response_wrapper( + subscriptions.retrieve_secret, + ) + self.rotate_secret = async_to_raw_response_wrapper( + subscriptions.rotate_secret, + ) + self.send_simulated_example = async_to_raw_response_wrapper( + subscriptions.send_simulated_example, + ) diff --git a/src/lithic/resources/external_bank_accounts/__init__.py b/src/lithic/resources/external_bank_accounts/__init__.py index b5d454a6..8e45db27 100644 --- a/src/lithic/resources/external_bank_accounts/__init__.py +++ b/src/lithic/resources/external_bank_accounts/__init__.py @@ -1,6 +1,25 @@ # File generated from our OpenAPI spec by Stainless. -from .micro_deposits import MicroDeposits, AsyncMicroDeposits -from .external_bank_accounts import ExternalBankAccounts, AsyncExternalBankAccounts +from .micro_deposits import ( + MicroDeposits, + AsyncMicroDeposits, + MicroDepositsWithRawResponse, + AsyncMicroDepositsWithRawResponse, +) +from .external_bank_accounts import ( + ExternalBankAccounts, + AsyncExternalBankAccounts, + ExternalBankAccountsWithRawResponse, + AsyncExternalBankAccountsWithRawResponse, +) -__all__ = ["MicroDeposits", "AsyncMicroDeposits", "ExternalBankAccounts", "AsyncExternalBankAccounts"] +__all__ = [ + "MicroDeposits", + "AsyncMicroDeposits", + "MicroDepositsWithRawResponse", + "AsyncMicroDepositsWithRawResponse", + "ExternalBankAccounts", + "AsyncExternalBankAccounts", + "ExternalBankAccountsWithRawResponse", + "AsyncExternalBankAccountsWithRawResponse", +] diff --git a/src/lithic/resources/external_bank_accounts/external_bank_accounts.py b/src/lithic/resources/external_bank_accounts/external_bank_accounts.py index 2ef3879f..64411797 100644 --- a/src/lithic/resources/external_bank_accounts/external_bank_accounts.py +++ b/src/lithic/resources/external_bank_accounts/external_bank_accounts.py @@ -21,9 +21,15 @@ from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import required_args, maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ...pagination import SyncCursorPage, AsyncCursorPage from ..._base_client import AsyncPaginator, make_request_options -from .micro_deposits import MicroDeposits, AsyncMicroDeposits +from .micro_deposits import ( + MicroDeposits, + AsyncMicroDeposits, + MicroDepositsWithRawResponse, + AsyncMicroDepositsWithRawResponse, +) if TYPE_CHECKING: from ..._client import Lithic, AsyncLithic @@ -33,10 +39,12 @@ class ExternalBankAccounts(SyncAPIResource): micro_deposits: MicroDeposits + with_raw_response: ExternalBankAccountsWithRawResponse def __init__(self, client: Lithic) -> None: super().__init__(client) self.micro_deposits = MicroDeposits(client) + self.with_raw_response = ExternalBankAccountsWithRawResponse(self) @overload def create( @@ -369,10 +377,12 @@ def list( class AsyncExternalBankAccounts(AsyncAPIResource): micro_deposits: AsyncMicroDeposits + with_raw_response: AsyncExternalBankAccountsWithRawResponse def __init__(self, client: AsyncLithic) -> None: super().__init__(client) self.micro_deposits = AsyncMicroDeposits(client) + self.with_raw_response = AsyncExternalBankAccountsWithRawResponse(self) @overload async def create( @@ -701,3 +711,39 @@ def list( ), model=ExternalBankAccountListResponse, ) + + +class ExternalBankAccountsWithRawResponse: + def __init__(self, external_bank_accounts: ExternalBankAccounts) -> None: + self.micro_deposits = MicroDepositsWithRawResponse(external_bank_accounts.micro_deposits) + + self.create = to_raw_response_wrapper( + external_bank_accounts.create, + ) + self.retrieve = to_raw_response_wrapper( + external_bank_accounts.retrieve, + ) + self.update = to_raw_response_wrapper( + external_bank_accounts.update, + ) + self.list = to_raw_response_wrapper( + external_bank_accounts.list, + ) + + +class AsyncExternalBankAccountsWithRawResponse: + def __init__(self, external_bank_accounts: AsyncExternalBankAccounts) -> None: + self.micro_deposits = AsyncMicroDepositsWithRawResponse(external_bank_accounts.micro_deposits) + + self.create = async_to_raw_response_wrapper( + external_bank_accounts.create, + ) + self.retrieve = async_to_raw_response_wrapper( + external_bank_accounts.retrieve, + ) + self.update = async_to_raw_response_wrapper( + external_bank_accounts.update, + ) + self.list = async_to_raw_response_wrapper( + external_bank_accounts.list, + ) diff --git a/src/lithic/resources/external_bank_accounts/micro_deposits.py b/src/lithic/resources/external_bank_accounts/micro_deposits.py index 5ea79649..7153b28f 100644 --- a/src/lithic/resources/external_bank_accounts/micro_deposits.py +++ b/src/lithic/resources/external_bank_accounts/micro_deposits.py @@ -2,21 +2,31 @@ from __future__ import annotations -from typing import List +from typing import TYPE_CHECKING, List from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ..._base_client import make_request_options from ...types.external_bank_accounts import ( MicroDepositCreateResponse, micro_deposit_create_params, ) +if TYPE_CHECKING: + from ..._client import Lithic, AsyncLithic + __all__ = ["MicroDeposits", "AsyncMicroDeposits"] class MicroDeposits(SyncAPIResource): + with_raw_response: MicroDepositsWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = MicroDepositsWithRawResponse(self) + def create( self, external_bank_account_token: str, @@ -61,6 +71,12 @@ def create( class AsyncMicroDeposits(AsyncAPIResource): + with_raw_response: AsyncMicroDepositsWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncMicroDepositsWithRawResponse(self) + async def create( self, external_bank_account_token: str, @@ -102,3 +118,17 @@ async def create( ), cast_to=MicroDepositCreateResponse, ) + + +class MicroDepositsWithRawResponse: + def __init__(self, micro_deposits: MicroDeposits) -> None: + self.create = to_raw_response_wrapper( + micro_deposits.create, + ) + + +class AsyncMicroDepositsWithRawResponse: + def __init__(self, micro_deposits: AsyncMicroDeposits) -> None: + self.create = async_to_raw_response_wrapper( + micro_deposits.create, + ) diff --git a/src/lithic/resources/financial_accounts/__init__.py b/src/lithic/resources/financial_accounts/__init__.py index baffc09a..61de020b 100644 --- a/src/lithic/resources/financial_accounts/__init__.py +++ b/src/lithic/resources/financial_accounts/__init__.py @@ -1,17 +1,45 @@ # File generated from our OpenAPI spec by Stainless. -from .balances import Balances, AsyncBalances -from .statements import Statements, AsyncStatements -from .financial_accounts import FinancialAccounts, AsyncFinancialAccounts -from .financial_transactions import FinancialTransactions, AsyncFinancialTransactions +from .balances import ( + Balances, + AsyncBalances, + BalancesWithRawResponse, + AsyncBalancesWithRawResponse, +) +from .statements import ( + Statements, + AsyncStatements, + StatementsWithRawResponse, + AsyncStatementsWithRawResponse, +) +from .financial_accounts import ( + FinancialAccounts, + AsyncFinancialAccounts, + FinancialAccountsWithRawResponse, + AsyncFinancialAccountsWithRawResponse, +) +from .financial_transactions import ( + FinancialTransactions, + AsyncFinancialTransactions, + FinancialTransactionsWithRawResponse, + AsyncFinancialTransactionsWithRawResponse, +) __all__ = [ "Balances", "AsyncBalances", + "BalancesWithRawResponse", + "AsyncBalancesWithRawResponse", "FinancialTransactions", "AsyncFinancialTransactions", + "FinancialTransactionsWithRawResponse", + "AsyncFinancialTransactionsWithRawResponse", "Statements", "AsyncStatements", + "StatementsWithRawResponse", + "AsyncStatementsWithRawResponse", "FinancialAccounts", "AsyncFinancialAccounts", + "FinancialAccountsWithRawResponse", + "AsyncFinancialAccountsWithRawResponse", ] diff --git a/src/lithic/resources/financial_accounts/balances.py b/src/lithic/resources/financial_accounts/balances.py index 07ab0d51..ca900afd 100644 --- a/src/lithic/resources/financial_accounts/balances.py +++ b/src/lithic/resources/financial_accounts/balances.py @@ -2,21 +2,31 @@ from __future__ import annotations -from typing import Union +from typing import TYPE_CHECKING, Union from datetime import datetime from ...types import Balance from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ...pagination import SyncSinglePage, AsyncSinglePage from ..._base_client import AsyncPaginator, make_request_options from ...types.financial_accounts import balance_list_params +if TYPE_CHECKING: + from ..._client import Lithic, AsyncLithic + __all__ = ["Balances", "AsyncBalances"] class Balances(SyncAPIResource): + with_raw_response: BalancesWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = BalancesWithRawResponse(self) + def list( self, financial_account_token: str, @@ -69,6 +79,12 @@ def list( class AsyncBalances(AsyncAPIResource): + with_raw_response: AsyncBalancesWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncBalancesWithRawResponse(self) + def list( self, financial_account_token: str, @@ -118,3 +134,17 @@ def list( ), model=Balance, ) + + +class BalancesWithRawResponse: + def __init__(self, balances: Balances) -> None: + self.list = to_raw_response_wrapper( + balances.list, + ) + + +class AsyncBalancesWithRawResponse: + def __init__(self, balances: AsyncBalances) -> None: + self.list = async_to_raw_response_wrapper( + balances.list, + ) diff --git a/src/lithic/resources/financial_accounts/financial_accounts.py b/src/lithic/resources/financial_accounts/financial_accounts.py index 2353822f..2773f0f9 100644 --- a/src/lithic/resources/financial_accounts/financial_accounts.py +++ b/src/lithic/resources/financial_accounts/financial_accounts.py @@ -8,12 +8,28 @@ from ...types import FinancialAccount, financial_account_list_params from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform -from .balances import Balances, AsyncBalances -from .statements import Statements, AsyncStatements +from .balances import ( + Balances, + AsyncBalances, + BalancesWithRawResponse, + AsyncBalancesWithRawResponse, +) +from .statements import ( + Statements, + AsyncStatements, + StatementsWithRawResponse, + AsyncStatementsWithRawResponse, +) from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ...pagination import SyncSinglePage, AsyncSinglePage from ..._base_client import AsyncPaginator, make_request_options -from .financial_transactions import FinancialTransactions, AsyncFinancialTransactions +from .financial_transactions import ( + FinancialTransactions, + AsyncFinancialTransactions, + FinancialTransactionsWithRawResponse, + AsyncFinancialTransactionsWithRawResponse, +) if TYPE_CHECKING: from ..._client import Lithic, AsyncLithic @@ -25,12 +41,14 @@ class FinancialAccounts(SyncAPIResource): balances: Balances financial_transactions: FinancialTransactions statements: Statements + with_raw_response: FinancialAccountsWithRawResponse def __init__(self, client: Lithic) -> None: super().__init__(client) self.balances = Balances(client) self.financial_transactions = FinancialTransactions(client) self.statements = Statements(client) + self.with_raw_response = FinancialAccountsWithRawResponse(self) def list( self, @@ -85,12 +103,14 @@ class AsyncFinancialAccounts(AsyncAPIResource): balances: AsyncBalances financial_transactions: AsyncFinancialTransactions statements: AsyncStatements + with_raw_response: AsyncFinancialAccountsWithRawResponse def __init__(self, client: AsyncLithic) -> None: super().__init__(client) self.balances = AsyncBalances(client) self.financial_transactions = AsyncFinancialTransactions(client) self.statements = AsyncStatements(client) + self.with_raw_response = AsyncFinancialAccountsWithRawResponse(self) def list( self, @@ -139,3 +159,27 @@ def list( ), model=FinancialAccount, ) + + +class FinancialAccountsWithRawResponse: + def __init__(self, financial_accounts: FinancialAccounts) -> None: + self.balances = BalancesWithRawResponse(financial_accounts.balances) + self.financial_transactions = FinancialTransactionsWithRawResponse(financial_accounts.financial_transactions) + self.statements = StatementsWithRawResponse(financial_accounts.statements) + + self.list = to_raw_response_wrapper( + financial_accounts.list, + ) + + +class AsyncFinancialAccountsWithRawResponse: + def __init__(self, financial_accounts: AsyncFinancialAccounts) -> None: + self.balances = AsyncBalancesWithRawResponse(financial_accounts.balances) + self.financial_transactions = AsyncFinancialTransactionsWithRawResponse( + financial_accounts.financial_transactions + ) + self.statements = AsyncStatementsWithRawResponse(financial_accounts.statements) + + self.list = async_to_raw_response_wrapper( + financial_accounts.list, + ) diff --git a/src/lithic/resources/financial_accounts/financial_transactions.py b/src/lithic/resources/financial_accounts/financial_transactions.py index bdad5b19..6b939908 100644 --- a/src/lithic/resources/financial_accounts/financial_transactions.py +++ b/src/lithic/resources/financial_accounts/financial_transactions.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Union +from typing import TYPE_CHECKING, Union from datetime import datetime from typing_extensions import Literal @@ -10,14 +10,24 @@ from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ...pagination import SyncSinglePage, AsyncSinglePage from ..._base_client import AsyncPaginator, make_request_options from ...types.financial_accounts import financial_transaction_list_params +if TYPE_CHECKING: + from ..._client import Lithic, AsyncLithic + __all__ = ["FinancialTransactions", "AsyncFinancialTransactions"] class FinancialTransactions(SyncAPIResource): + with_raw_response: FinancialTransactionsWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = FinancialTransactionsWithRawResponse(self) + def retrieve( self, financial_transaction_token: str, @@ -124,6 +134,12 @@ def list( class AsyncFinancialTransactions(AsyncAPIResource): + with_raw_response: AsyncFinancialTransactionsWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncFinancialTransactionsWithRawResponse(self) + async def retrieve( self, financial_transaction_token: str, @@ -227,3 +243,23 @@ def list( ), model=FinancialTransaction, ) + + +class FinancialTransactionsWithRawResponse: + def __init__(self, financial_transactions: FinancialTransactions) -> None: + self.retrieve = to_raw_response_wrapper( + financial_transactions.retrieve, + ) + self.list = to_raw_response_wrapper( + financial_transactions.list, + ) + + +class AsyncFinancialTransactionsWithRawResponse: + def __init__(self, financial_transactions: AsyncFinancialTransactions) -> None: + self.retrieve = async_to_raw_response_wrapper( + financial_transactions.retrieve, + ) + self.list = async_to_raw_response_wrapper( + financial_transactions.list, + ) diff --git a/src/lithic/resources/financial_accounts/statements/__init__.py b/src/lithic/resources/financial_accounts/statements/__init__.py index e6262088..9998a7d3 100644 --- a/src/lithic/resources/financial_accounts/statements/__init__.py +++ b/src/lithic/resources/financial_accounts/statements/__init__.py @@ -1,6 +1,25 @@ # File generated from our OpenAPI spec by Stainless. -from .line_items import LineItems, AsyncLineItems -from .statements import Statements, AsyncStatements +from .line_items import ( + LineItems, + AsyncLineItems, + LineItemsWithRawResponse, + AsyncLineItemsWithRawResponse, +) +from .statements import ( + Statements, + AsyncStatements, + StatementsWithRawResponse, + AsyncStatementsWithRawResponse, +) -__all__ = ["LineItems", "AsyncLineItems", "Statements", "AsyncStatements"] +__all__ = [ + "LineItems", + "AsyncLineItems", + "LineItemsWithRawResponse", + "AsyncLineItemsWithRawResponse", + "Statements", + "AsyncStatements", + "StatementsWithRawResponse", + "AsyncStatementsWithRawResponse", +] diff --git a/src/lithic/resources/financial_accounts/statements/line_items.py b/src/lithic/resources/financial_accounts/statements/line_items.py index 4b7f236b..a97b7811 100644 --- a/src/lithic/resources/financial_accounts/statements/line_items.py +++ b/src/lithic/resources/financial_accounts/statements/line_items.py @@ -2,9 +2,12 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ...._utils import maybe_transform from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ....pagination import SyncCursorPage, AsyncCursorPage from ...._base_client import AsyncPaginator, make_request_options from ....types.financial_accounts.statements import ( @@ -12,10 +15,19 @@ line_item_list_params, ) +if TYPE_CHECKING: + from ...._client import Lithic, AsyncLithic + __all__ = ["LineItems", "AsyncLineItems"] class LineItems(SyncAPIResource): + with_raw_response: LineItemsWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = LineItemsWithRawResponse(self) + def list( self, statement_token: str, @@ -73,6 +85,12 @@ def list( class AsyncLineItems(AsyncAPIResource): + with_raw_response: AsyncLineItemsWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncLineItemsWithRawResponse(self) + def list( self, statement_token: str, @@ -127,3 +145,17 @@ def list( ), model=LineItemListResponse, ) + + +class LineItemsWithRawResponse: + def __init__(self, line_items: LineItems) -> None: + self.list = to_raw_response_wrapper( + line_items.list, + ) + + +class AsyncLineItemsWithRawResponse: + def __init__(self, line_items: AsyncLineItems) -> None: + self.list = async_to_raw_response_wrapper( + line_items.list, + ) diff --git a/src/lithic/resources/financial_accounts/statements/statements.py b/src/lithic/resources/financial_accounts/statements/statements.py index 63db399d..9086e7d0 100644 --- a/src/lithic/resources/financial_accounts/statements/statements.py +++ b/src/lithic/resources/financial_accounts/statements/statements.py @@ -7,8 +7,14 @@ from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ...._utils import maybe_transform -from .line_items import LineItems, AsyncLineItems +from .line_items import ( + LineItems, + AsyncLineItems, + LineItemsWithRawResponse, + AsyncLineItemsWithRawResponse, +) from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ....pagination import SyncCursorPage, AsyncCursorPage from ...._base_client import AsyncPaginator, make_request_options from ....types.financial_accounts import Statement, statement_list_params @@ -21,10 +27,12 @@ class Statements(SyncAPIResource): line_items: LineItems + with_raw_response: StatementsWithRawResponse def __init__(self, client: Lithic) -> None: super().__init__(client) self.line_items = LineItems(client) + self.with_raw_response = StatementsWithRawResponse(self) def retrieve( self, @@ -125,10 +133,12 @@ def list( class AsyncStatements(AsyncAPIResource): line_items: AsyncLineItems + with_raw_response: AsyncStatementsWithRawResponse def __init__(self, client: AsyncLithic) -> None: super().__init__(client) self.line_items = AsyncLineItems(client) + self.with_raw_response = AsyncStatementsWithRawResponse(self) async def retrieve( self, @@ -225,3 +235,27 @@ def list( ), model=Statement, ) + + +class StatementsWithRawResponse: + def __init__(self, statements: Statements) -> None: + self.line_items = LineItemsWithRawResponse(statements.line_items) + + self.retrieve = to_raw_response_wrapper( + statements.retrieve, + ) + self.list = to_raw_response_wrapper( + statements.list, + ) + + +class AsyncStatementsWithRawResponse: + def __init__(self, statements: AsyncStatements) -> None: + self.line_items = AsyncLineItemsWithRawResponse(statements.line_items) + + self.retrieve = async_to_raw_response_wrapper( + statements.retrieve, + ) + self.list = async_to_raw_response_wrapper( + statements.list, + ) diff --git a/src/lithic/resources/payments.py b/src/lithic/resources/payments.py index 2548a817..47ebf656 100644 --- a/src/lithic/resources/payments.py +++ b/src/lithic/resources/payments.py @@ -2,6 +2,7 @@ from __future__ import annotations +from typing import TYPE_CHECKING from typing_extensions import Literal from ..types import ( @@ -18,13 +19,23 @@ from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._utils import maybe_transform from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ..pagination import SyncCursorPage, AsyncCursorPage from .._base_client import AsyncPaginator, make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["Payments", "AsyncPayments"] class Payments(SyncAPIResource): + with_raw_response: PaymentsWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = PaymentsWithRawResponse(self) + def create( self, *, @@ -302,6 +313,12 @@ def simulate_return( class AsyncPayments(AsyncAPIResource): + with_raw_response: AsyncPaymentsWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncPaymentsWithRawResponse(self) + async def create( self, *, @@ -576,3 +593,47 @@ async def simulate_return( ), cast_to=PaymentSimulateReturnResponse, ) + + +class PaymentsWithRawResponse: + def __init__(self, payments: Payments) -> None: + self.create = to_raw_response_wrapper( + payments.create, + ) + self.retrieve = to_raw_response_wrapper( + payments.retrieve, + ) + self.list = to_raw_response_wrapper( + payments.list, + ) + self.retry = to_raw_response_wrapper( + payments.retry, + ) + self.simulate_release = to_raw_response_wrapper( + payments.simulate_release, + ) + self.simulate_return = to_raw_response_wrapper( + payments.simulate_return, + ) + + +class AsyncPaymentsWithRawResponse: + def __init__(self, payments: AsyncPayments) -> None: + self.create = async_to_raw_response_wrapper( + payments.create, + ) + self.retrieve = async_to_raw_response_wrapper( + payments.retrieve, + ) + self.list = async_to_raw_response_wrapper( + payments.list, + ) + self.retry = async_to_raw_response_wrapper( + payments.retry, + ) + self.simulate_release = async_to_raw_response_wrapper( + payments.simulate_release, + ) + self.simulate_return = async_to_raw_response_wrapper( + payments.simulate_return, + ) diff --git a/src/lithic/resources/reports/__init__.py b/src/lithic/resources/reports/__init__.py index d1907022..b9d41ef2 100644 --- a/src/lithic/resources/reports/__init__.py +++ b/src/lithic/resources/reports/__init__.py @@ -1,6 +1,25 @@ # File generated from our OpenAPI spec by Stainless. -from .reports import Reports, AsyncReports -from .settlement import Settlement, AsyncSettlement +from .reports import ( + Reports, + AsyncReports, + ReportsWithRawResponse, + AsyncReportsWithRawResponse, +) +from .settlement import ( + Settlement, + AsyncSettlement, + SettlementWithRawResponse, + AsyncSettlementWithRawResponse, +) -__all__ = ["Settlement", "AsyncSettlement", "Reports", "AsyncReports"] +__all__ = [ + "Settlement", + "AsyncSettlement", + "SettlementWithRawResponse", + "AsyncSettlementWithRawResponse", + "Reports", + "AsyncReports", + "ReportsWithRawResponse", + "AsyncReportsWithRawResponse", +] diff --git a/src/lithic/resources/reports/reports.py b/src/lithic/resources/reports/reports.py index 3bd04af4..4e37fc82 100644 --- a/src/lithic/resources/reports/reports.py +++ b/src/lithic/resources/reports/reports.py @@ -4,7 +4,12 @@ from typing import TYPE_CHECKING -from .settlement import Settlement, AsyncSettlement +from .settlement import ( + Settlement, + AsyncSettlement, + SettlementWithRawResponse, + AsyncSettlementWithRawResponse, +) from ..._resource import SyncAPIResource, AsyncAPIResource if TYPE_CHECKING: @@ -15,15 +20,29 @@ class Reports(SyncAPIResource): settlement: Settlement + with_raw_response: ReportsWithRawResponse def __init__(self, client: Lithic) -> None: super().__init__(client) self.settlement = Settlement(client) + self.with_raw_response = ReportsWithRawResponse(self) class AsyncReports(AsyncAPIResource): settlement: AsyncSettlement + with_raw_response: AsyncReportsWithRawResponse def __init__(self, client: AsyncLithic) -> None: super().__init__(client) self.settlement = AsyncSettlement(client) + self.with_raw_response = AsyncReportsWithRawResponse(self) + + +class ReportsWithRawResponse: + def __init__(self, reports: Reports) -> None: + self.settlement = SettlementWithRawResponse(reports.settlement) + + +class AsyncReportsWithRawResponse: + def __init__(self, reports: AsyncReports) -> None: + self.settlement = AsyncSettlementWithRawResponse(reports.settlement) diff --git a/src/lithic/resources/reports/settlement.py b/src/lithic/resources/reports/settlement.py index 0ca4ec76..0dfbbeb3 100644 --- a/src/lithic/resources/reports/settlement.py +++ b/src/lithic/resources/reports/settlement.py @@ -2,21 +2,31 @@ from __future__ import annotations -from typing import Union +from typing import TYPE_CHECKING, Union from datetime import date from ...types import SettlementDetail from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ...pagination import SyncCursorPage, AsyncCursorPage from ..._base_client import AsyncPaginator, make_request_options from ...types.reports import SettlementSummaryResponse, settlement_list_details_params +if TYPE_CHECKING: + from ..._client import Lithic, AsyncLithic + __all__ = ["Settlement", "AsyncSettlement"] class Settlement(SyncAPIResource): + with_raw_response: SettlementWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = SettlementWithRawResponse(self) + def list_details( self, report_date: Union[str, date], @@ -104,6 +114,12 @@ def summary( class AsyncSettlement(AsyncAPIResource): + with_raw_response: AsyncSettlementWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncSettlementWithRawResponse(self) + def list_details( self, report_date: Union[str, date], @@ -188,3 +204,23 @@ async def summary( ), cast_to=SettlementSummaryResponse, ) + + +class SettlementWithRawResponse: + def __init__(self, settlement: Settlement) -> None: + self.list_details = to_raw_response_wrapper( + settlement.list_details, + ) + self.summary = to_raw_response_wrapper( + settlement.summary, + ) + + +class AsyncSettlementWithRawResponse: + def __init__(self, settlement: AsyncSettlement) -> None: + self.list_details = async_to_raw_response_wrapper( + settlement.list_details, + ) + self.summary = async_to_raw_response_wrapper( + settlement.summary, + ) diff --git a/src/lithic/resources/responder_endpoints.py b/src/lithic/resources/responder_endpoints.py index 3ad29d69..3ea19b9d 100644 --- a/src/lithic/resources/responder_endpoints.py +++ b/src/lithic/resources/responder_endpoints.py @@ -2,6 +2,7 @@ from __future__ import annotations +from typing import TYPE_CHECKING from typing_extensions import Literal from ..types import ( @@ -14,12 +15,22 @@ from .._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven from .._utils import maybe_transform from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from .._base_client import make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["ResponderEndpoints", "AsyncResponderEndpoints"] class ResponderEndpoints(SyncAPIResource): + with_raw_response: ResponderEndpointsWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = ResponderEndpointsWithRawResponse(self) + def create( self, *, @@ -152,6 +163,12 @@ def check_status( class AsyncResponderEndpoints(AsyncAPIResource): + with_raw_response: AsyncResponderEndpointsWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncResponderEndpointsWithRawResponse(self) + async def create( self, *, @@ -281,3 +298,29 @@ async def check_status( ), cast_to=ResponderEndpointStatus, ) + + +class ResponderEndpointsWithRawResponse: + def __init__(self, responder_endpoints: ResponderEndpoints) -> None: + self.create = to_raw_response_wrapper( + responder_endpoints.create, + ) + self.delete = to_raw_response_wrapper( + responder_endpoints.delete, + ) + self.check_status = to_raw_response_wrapper( + responder_endpoints.check_status, + ) + + +class AsyncResponderEndpointsWithRawResponse: + def __init__(self, responder_endpoints: AsyncResponderEndpoints) -> None: + self.create = async_to_raw_response_wrapper( + responder_endpoints.create, + ) + self.delete = async_to_raw_response_wrapper( + responder_endpoints.delete, + ) + self.check_status = async_to_raw_response_wrapper( + responder_endpoints.check_status, + ) diff --git a/src/lithic/resources/three_ds/__init__.py b/src/lithic/resources/three_ds/__init__.py index 45385d53..d8ce7c60 100644 --- a/src/lithic/resources/three_ds/__init__.py +++ b/src/lithic/resources/three_ds/__init__.py @@ -1,7 +1,35 @@ # File generated from our OpenAPI spec by Stainless. -from .three_ds import ThreeDS, AsyncThreeDS -from .decisioning import Decisioning, AsyncDecisioning -from .authentication import Authentication, AsyncAuthentication +from .three_ds import ( + ThreeDS, + AsyncThreeDS, + ThreeDSWithRawResponse, + AsyncThreeDSWithRawResponse, +) +from .decisioning import ( + Decisioning, + AsyncDecisioning, + DecisioningWithRawResponse, + AsyncDecisioningWithRawResponse, +) +from .authentication import ( + Authentication, + AsyncAuthentication, + AuthenticationWithRawResponse, + AsyncAuthenticationWithRawResponse, +) -__all__ = ["Authentication", "AsyncAuthentication", "Decisioning", "AsyncDecisioning", "ThreeDS", "AsyncThreeDS"] +__all__ = [ + "Authentication", + "AsyncAuthentication", + "AuthenticationWithRawResponse", + "AsyncAuthenticationWithRawResponse", + "Decisioning", + "AsyncDecisioning", + "DecisioningWithRawResponse", + "AsyncDecisioningWithRawResponse", + "ThreeDS", + "AsyncThreeDS", + "ThreeDSWithRawResponse", + "AsyncThreeDSWithRawResponse", +] diff --git a/src/lithic/resources/three_ds/authentication.py b/src/lithic/resources/three_ds/authentication.py index 3495ccfb..576b2a41 100644 --- a/src/lithic/resources/three_ds/authentication.py +++ b/src/lithic/resources/three_ds/authentication.py @@ -2,9 +2,12 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ..._base_client import make_request_options from ...types.three_ds import ( AuthenticationRetrieveResponse, @@ -12,10 +15,19 @@ authentication_simulate_params, ) +if TYPE_CHECKING: + from ..._client import Lithic, AsyncLithic + __all__ = ["Authentication", "AsyncAuthentication"] class Authentication(SyncAPIResource): + with_raw_response: AuthenticationWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = AuthenticationWithRawResponse(self) + def retrieve( self, three_ds_authentication_token: str, @@ -102,6 +114,12 @@ def simulate( class AsyncAuthentication(AsyncAPIResource): + with_raw_response: AsyncAuthenticationWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncAuthenticationWithRawResponse(self) + async def retrieve( self, three_ds_authentication_token: str, @@ -185,3 +203,23 @@ async def simulate( ), cast_to=AuthenticationSimulateResponse, ) + + +class AuthenticationWithRawResponse: + def __init__(self, authentication: Authentication) -> None: + self.retrieve = to_raw_response_wrapper( + authentication.retrieve, + ) + self.simulate = to_raw_response_wrapper( + authentication.simulate, + ) + + +class AsyncAuthenticationWithRawResponse: + def __init__(self, authentication: AsyncAuthentication) -> None: + self.retrieve = async_to_raw_response_wrapper( + authentication.retrieve, + ) + self.simulate = async_to_raw_response_wrapper( + authentication.simulate, + ) diff --git a/src/lithic/resources/three_ds/decisioning.py b/src/lithic/resources/three_ds/decisioning.py index 2b3e3646..0190c97d 100644 --- a/src/lithic/resources/three_ds/decisioning.py +++ b/src/lithic/resources/three_ds/decisioning.py @@ -2,15 +2,27 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ..._base_client import make_request_options from ...types.three_ds import DecisioningRetrieveSecretResponse +if TYPE_CHECKING: + from ..._client import Lithic, AsyncLithic + __all__ = ["Decisioning", "AsyncDecisioning"] class Decisioning(SyncAPIResource): + with_raw_response: DecisioningWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = DecisioningWithRawResponse(self) + def retrieve_secret( self, *, @@ -70,6 +82,12 @@ def rotate_secret( class AsyncDecisioning(AsyncAPIResource): + with_raw_response: AsyncDecisioningWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncDecisioningWithRawResponse(self) + async def retrieve_secret( self, *, @@ -126,3 +144,23 @@ async def rotate_secret( ), cast_to=NoneType, ) + + +class DecisioningWithRawResponse: + def __init__(self, decisioning: Decisioning) -> None: + self.retrieve_secret = to_raw_response_wrapper( + decisioning.retrieve_secret, + ) + self.rotate_secret = to_raw_response_wrapper( + decisioning.rotate_secret, + ) + + +class AsyncDecisioningWithRawResponse: + def __init__(self, decisioning: AsyncDecisioning) -> None: + self.retrieve_secret = async_to_raw_response_wrapper( + decisioning.retrieve_secret, + ) + self.rotate_secret = async_to_raw_response_wrapper( + decisioning.rotate_secret, + ) diff --git a/src/lithic/resources/three_ds/three_ds.py b/src/lithic/resources/three_ds/three_ds.py index d5db638b..3c5fabf8 100644 --- a/src/lithic/resources/three_ds/three_ds.py +++ b/src/lithic/resources/three_ds/three_ds.py @@ -5,8 +5,18 @@ from typing import TYPE_CHECKING from ..._resource import SyncAPIResource, AsyncAPIResource -from .decisioning import Decisioning, AsyncDecisioning -from .authentication import Authentication, AsyncAuthentication +from .decisioning import ( + Decisioning, + AsyncDecisioning, + DecisioningWithRawResponse, + AsyncDecisioningWithRawResponse, +) +from .authentication import ( + Authentication, + AsyncAuthentication, + AuthenticationWithRawResponse, + AsyncAuthenticationWithRawResponse, +) if TYPE_CHECKING: from ..._client import Lithic, AsyncLithic @@ -17,18 +27,34 @@ class ThreeDS(SyncAPIResource): authentication: Authentication decisioning: Decisioning + with_raw_response: ThreeDSWithRawResponse def __init__(self, client: Lithic) -> None: super().__init__(client) self.authentication = Authentication(client) self.decisioning = Decisioning(client) + self.with_raw_response = ThreeDSWithRawResponse(self) class AsyncThreeDS(AsyncAPIResource): authentication: AsyncAuthentication decisioning: AsyncDecisioning + with_raw_response: AsyncThreeDSWithRawResponse def __init__(self, client: AsyncLithic) -> None: super().__init__(client) self.authentication = AsyncAuthentication(client) self.decisioning = AsyncDecisioning(client) + self.with_raw_response = AsyncThreeDSWithRawResponse(self) + + +class ThreeDSWithRawResponse: + def __init__(self, three_ds: ThreeDS) -> None: + self.authentication = AuthenticationWithRawResponse(three_ds.authentication) + self.decisioning = DecisioningWithRawResponse(three_ds.decisioning) + + +class AsyncThreeDSWithRawResponse: + def __init__(self, three_ds: AsyncThreeDS) -> None: + self.authentication = AsyncAuthenticationWithRawResponse(three_ds.authentication) + self.decisioning = AsyncDecisioningWithRawResponse(three_ds.decisioning) diff --git a/src/lithic/resources/tokenization_decisioning.py b/src/lithic/resources/tokenization_decisioning.py index 0d34e28b..c7c97c74 100644 --- a/src/lithic/resources/tokenization_decisioning.py +++ b/src/lithic/resources/tokenization_decisioning.py @@ -2,15 +2,27 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from ..types import TokenizationSecret, TokenizationDecisioningRotateSecretResponse from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from .._base_client import make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["TokenizationDecisioning", "AsyncTokenizationDecisioning"] class TokenizationDecisioning(SyncAPIResource): + with_raw_response: TokenizationDecisioningWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = TokenizationDecisioningWithRawResponse(self) + def retrieve_secret( self, *, @@ -69,6 +81,12 @@ def rotate_secret( class AsyncTokenizationDecisioning(AsyncAPIResource): + with_raw_response: AsyncTokenizationDecisioningWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncTokenizationDecisioningWithRawResponse(self) + async def retrieve_secret( self, *, @@ -124,3 +142,23 @@ async def rotate_secret( ), cast_to=TokenizationDecisioningRotateSecretResponse, ) + + +class TokenizationDecisioningWithRawResponse: + def __init__(self, tokenization_decisioning: TokenizationDecisioning) -> None: + self.retrieve_secret = to_raw_response_wrapper( + tokenization_decisioning.retrieve_secret, + ) + self.rotate_secret = to_raw_response_wrapper( + tokenization_decisioning.rotate_secret, + ) + + +class AsyncTokenizationDecisioningWithRawResponse: + def __init__(self, tokenization_decisioning: AsyncTokenizationDecisioning) -> None: + self.retrieve_secret = async_to_raw_response_wrapper( + tokenization_decisioning.retrieve_secret, + ) + self.rotate_secret = async_to_raw_response_wrapper( + tokenization_decisioning.rotate_secret, + ) diff --git a/src/lithic/resources/tokenizations.py b/src/lithic/resources/tokenizations.py index 03e1b25f..f185a2ef 100644 --- a/src/lithic/resources/tokenizations.py +++ b/src/lithic/resources/tokenizations.py @@ -2,18 +2,29 @@ from __future__ import annotations +from typing import TYPE_CHECKING from typing_extensions import Literal from ..types import TokenizationSimulateResponse, tokenization_simulate_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._utils import maybe_transform from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from .._base_client import make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["Tokenizations", "AsyncTokenizations"] class Tokenizations(SyncAPIResource): + with_raw_response: TokenizationsWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = TokenizationsWithRawResponse(self) + def simulate( self, *, @@ -90,6 +101,12 @@ def simulate( class AsyncTokenizations(AsyncAPIResource): + with_raw_response: AsyncTokenizationsWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncTokenizationsWithRawResponse(self) + async def simulate( self, *, @@ -163,3 +180,17 @@ async def simulate( ), cast_to=TokenizationSimulateResponse, ) + + +class TokenizationsWithRawResponse: + def __init__(self, tokenizations: Tokenizations) -> None: + self.simulate = to_raw_response_wrapper( + tokenizations.simulate, + ) + + +class AsyncTokenizationsWithRawResponse: + def __init__(self, tokenizations: AsyncTokenizations) -> None: + self.simulate = async_to_raw_response_wrapper( + tokenizations.simulate, + ) diff --git a/src/lithic/resources/transactions.py b/src/lithic/resources/transactions.py index 88defa5c..e633192f 100644 --- a/src/lithic/resources/transactions.py +++ b/src/lithic/resources/transactions.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Union +from typing import TYPE_CHECKING, Union from datetime import datetime from typing_extensions import Literal @@ -27,13 +27,23 @@ from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._utils import maybe_transform from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper from ..pagination import SyncCursorPage, AsyncCursorPage from .._base_client import AsyncPaginator, make_request_options +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["Transactions", "AsyncTransactions"] class Transactions(SyncAPIResource): + with_raw_response: TransactionsWithRawResponse + + def __init__(self, client: Lithic) -> None: + super().__init__(client) + self.with_raw_response = TransactionsWithRawResponse(self) + def retrieve( self, transaction_token: str, @@ -606,6 +616,12 @@ def simulate_void( class AsyncTransactions(AsyncAPIResource): + with_raw_response: AsyncTransactionsWithRawResponse + + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + self.with_raw_response = AsyncTransactionsWithRawResponse(self) + async def retrieve( self, transaction_token: str, @@ -1175,3 +1191,65 @@ async def simulate_void( ), cast_to=TransactionSimulateVoidResponse, ) + + +class TransactionsWithRawResponse: + def __init__(self, transactions: Transactions) -> None: + self.retrieve = to_raw_response_wrapper( + transactions.retrieve, + ) + self.list = to_raw_response_wrapper( + transactions.list, + ) + self.simulate_authorization = to_raw_response_wrapper( + transactions.simulate_authorization, + ) + self.simulate_authorization_advice = to_raw_response_wrapper( + transactions.simulate_authorization_advice, + ) + self.simulate_clearing = to_raw_response_wrapper( + transactions.simulate_clearing, + ) + self.simulate_credit_authorization = to_raw_response_wrapper( + transactions.simulate_credit_authorization, + ) + self.simulate_return = to_raw_response_wrapper( + transactions.simulate_return, + ) + self.simulate_return_reversal = to_raw_response_wrapper( + transactions.simulate_return_reversal, + ) + self.simulate_void = to_raw_response_wrapper( + transactions.simulate_void, + ) + + +class AsyncTransactionsWithRawResponse: + def __init__(self, transactions: AsyncTransactions) -> None: + self.retrieve = async_to_raw_response_wrapper( + transactions.retrieve, + ) + self.list = async_to_raw_response_wrapper( + transactions.list, + ) + self.simulate_authorization = async_to_raw_response_wrapper( + transactions.simulate_authorization, + ) + self.simulate_authorization_advice = async_to_raw_response_wrapper( + transactions.simulate_authorization_advice, + ) + self.simulate_clearing = async_to_raw_response_wrapper( + transactions.simulate_clearing, + ) + self.simulate_credit_authorization = async_to_raw_response_wrapper( + transactions.simulate_credit_authorization, + ) + self.simulate_return = async_to_raw_response_wrapper( + transactions.simulate_return, + ) + self.simulate_return_reversal = async_to_raw_response_wrapper( + transactions.simulate_return_reversal, + ) + self.simulate_void = async_to_raw_response_wrapper( + transactions.simulate_void, + ) diff --git a/src/lithic/resources/webhooks.py b/src/lithic/resources/webhooks.py index f98a37ba..f643cfd5 100644 --- a/src/lithic/resources/webhooks.py +++ b/src/lithic/resources/webhooks.py @@ -7,16 +7,23 @@ import math import base64 import hashlib +from typing import TYPE_CHECKING from datetime import datetime, timezone, timedelta from .._types import HeadersLike from .._utils import removeprefix, get_required_header from .._resource import SyncAPIResource, AsyncAPIResource +if TYPE_CHECKING: + from .._client import Lithic, AsyncLithic + __all__ = ["Webhooks", "AsyncWebhooks"] class Webhooks(SyncAPIResource): + def __init__(self, client: Lithic) -> None: + super().__init__(client) + def unwrap( self, payload: str | bytes, @@ -110,6 +117,9 @@ def verify_signature( class AsyncWebhooks(AsyncAPIResource): + def __init__(self, client: AsyncLithic) -> None: + super().__init__(client) + def unwrap( self, payload: str | bytes, diff --git a/src/lithic/types/external_bank_account_create_response.py b/src/lithic/types/external_bank_account_create_response.py index bb17dc55..16ef9b39 100644 --- a/src/lithic/types/external_bank_account_create_response.py +++ b/src/lithic/types/external_bank_account_create_response.py @@ -54,6 +54,9 @@ class ExternalBankAccountCreateResponse(BaseModel): type: Literal["CHECKING", "SAVINGS"] + verification_attempts: int + """The number of attempts at verification""" + verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID"] verification_state: Literal["PENDING", "ENABLED", "FAILED_VERIFICATION"] diff --git a/src/lithic/types/external_bank_account_list_response.py b/src/lithic/types/external_bank_account_list_response.py index b3ca4352..3f7f67e1 100644 --- a/src/lithic/types/external_bank_account_list_response.py +++ b/src/lithic/types/external_bank_account_list_response.py @@ -54,6 +54,9 @@ class ExternalBankAccountListResponse(BaseModel): type: Literal["CHECKING", "SAVINGS"] + verification_attempts: int + """The number of attempts at verification""" + verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID"] verification_state: Literal["PENDING", "ENABLED", "FAILED_VERIFICATION"] diff --git a/src/lithic/types/external_bank_account_retrieve_response.py b/src/lithic/types/external_bank_account_retrieve_response.py index d4bcd4a8..2207b7d0 100644 --- a/src/lithic/types/external_bank_account_retrieve_response.py +++ b/src/lithic/types/external_bank_account_retrieve_response.py @@ -54,6 +54,9 @@ class ExternalBankAccountRetrieveResponse(BaseModel): type: Literal["CHECKING", "SAVINGS"] + verification_attempts: int + """The number of attempts at verification""" + verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID"] verification_state: Literal["PENDING", "ENABLED", "FAILED_VERIFICATION"] diff --git a/src/lithic/types/external_bank_account_update_response.py b/src/lithic/types/external_bank_account_update_response.py index 30a57166..d495debb 100644 --- a/src/lithic/types/external_bank_account_update_response.py +++ b/src/lithic/types/external_bank_account_update_response.py @@ -54,6 +54,9 @@ class ExternalBankAccountUpdateResponse(BaseModel): type: Literal["CHECKING", "SAVINGS"] + verification_attempts: int + """The number of attempts at verification""" + verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID"] verification_state: Literal["PENDING", "ENABLED", "FAILED_VERIFICATION"] diff --git a/src/lithic/types/external_bank_accounts/micro_deposit_create_response.py b/src/lithic/types/external_bank_accounts/micro_deposit_create_response.py index 4fc3e3e0..cbabf911 100644 --- a/src/lithic/types/external_bank_accounts/micro_deposit_create_response.py +++ b/src/lithic/types/external_bank_accounts/micro_deposit_create_response.py @@ -54,6 +54,9 @@ class MicroDepositCreateResponse(BaseModel): type: Literal["CHECKING", "SAVINGS"] + verification_attempts: int + """The number of attempts at verification""" + verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID"] verification_state: Literal["PENDING", "ENABLED", "FAILED_VERIFICATION"] diff --git a/tests/api_resources/accounts/test_credit_configurations.py b/tests/api_resources/accounts/test_credit_configurations.py index dc12c185..d9eaa8cb 100644 --- a/tests/api_resources/accounts/test_credit_configurations.py +++ b/tests/api_resources/accounts/test_credit_configurations.py @@ -9,6 +9,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type from lithic.types import BusinessAccount +from lithic._client import Lithic, AsyncLithic base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My Lithic API Key" @@ -26,6 +27,15 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(BusinessAccount, credit_configuration, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.accounts.credit_configurations.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credit_configuration = response.parse() + assert_matches_type(BusinessAccount, credit_configuration, path=["response"]) + @parametrize def test_method_update(self, client: Lithic) -> None: credit_configuration = client.accounts.credit_configurations.update( @@ -44,6 +54,15 @@ def test_method_update_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(BusinessAccount, credit_configuration, path=["response"]) + @parametrize + def test_raw_response_update(self, client: Lithic) -> None: + response = client.accounts.credit_configurations.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credit_configuration = response.parse() + assert_matches_type(BusinessAccount, credit_configuration, path=["response"]) + class TestAsyncCreditConfigurations: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -57,6 +76,15 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(BusinessAccount, credit_configuration, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.accounts.credit_configurations.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credit_configuration = response.parse() + assert_matches_type(BusinessAccount, credit_configuration, path=["response"]) + @parametrize async def test_method_update(self, client: AsyncLithic) -> None: credit_configuration = await client.accounts.credit_configurations.update( @@ -74,3 +102,12 @@ async def test_method_update_with_all_params(self, client: AsyncLithic) -> None: payment_period=0, ) assert_matches_type(BusinessAccount, credit_configuration, path=["response"]) + + @parametrize + async def test_raw_response_update(self, client: AsyncLithic) -> None: + response = await client.accounts.credit_configurations.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credit_configuration = response.parse() + assert_matches_type(BusinessAccount, credit_configuration, path=["response"]) diff --git a/tests/api_resources/cards/test_aggregate_balances.py b/tests/api_resources/cards/test_aggregate_balances.py index 5da335ed..636549df 100644 --- a/tests/api_resources/cards/test_aggregate_balances.py +++ b/tests/api_resources/cards/test_aggregate_balances.py @@ -8,6 +8,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncSinglePage, AsyncSinglePage from lithic.types.cards import AggregateBalanceListResponse @@ -33,6 +34,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncSinglePage[AggregateBalanceListResponse], aggregate_balance, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.cards.aggregate_balances.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + aggregate_balance = response.parse() + assert_matches_type(SyncSinglePage[AggregateBalanceListResponse], aggregate_balance, path=["response"]) + class TestAsyncAggregateBalances: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -51,3 +59,10 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: business_account_token="string", ) assert_matches_type(AsyncSinglePage[AggregateBalanceListResponse], aggregate_balance, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.cards.aggregate_balances.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + aggregate_balance = response.parse() + assert_matches_type(AsyncSinglePage[AggregateBalanceListResponse], aggregate_balance, path=["response"]) diff --git a/tests/api_resources/cards/test_balances.py b/tests/api_resources/cards/test_balances.py index 40a05529..e536c225 100644 --- a/tests/api_resources/cards/test_balances.py +++ b/tests/api_resources/cards/test_balances.py @@ -10,6 +10,7 @@ from tests.utils import assert_matches_type from lithic.types import Balance from lithic._utils import parse_datetime +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncSinglePage, AsyncSinglePage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -37,6 +38,15 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncSinglePage[Balance], balance, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.cards.balances.with_raw_response.list( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + balance = response.parse() + assert_matches_type(SyncSinglePage[Balance], balance, path=["response"]) + class TestAsyncBalances: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -58,3 +68,12 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: last_transaction_event_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert_matches_type(AsyncSinglePage[Balance], balance, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.cards.balances.with_raw_response.list( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + balance = response.parse() + assert_matches_type(AsyncSinglePage[Balance], balance, path=["response"]) diff --git a/tests/api_resources/cards/test_financial_transactions.py b/tests/api_resources/cards/test_financial_transactions.py index 64dfc5eb..11b7ad69 100644 --- a/tests/api_resources/cards/test_financial_transactions.py +++ b/tests/api_resources/cards/test_financial_transactions.py @@ -10,6 +10,7 @@ from tests.utils import assert_matches_type from lithic.types import FinancialTransaction from lithic._utils import parse_datetime +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncSinglePage, AsyncSinglePage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -29,6 +30,16 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(FinancialTransaction, financial_transaction, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.cards.financial_transactions.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + financial_transaction = response.parse() + assert_matches_type(FinancialTransaction, financial_transaction, path=["response"]) + @parametrize def test_method_list(self, client: Lithic) -> None: financial_transaction = client.cards.financial_transactions.list( @@ -50,6 +61,15 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncSinglePage[FinancialTransaction], financial_transaction, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.cards.financial_transactions.with_raw_response.list( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + financial_transaction = response.parse() + assert_matches_type(SyncSinglePage[FinancialTransaction], financial_transaction, path=["response"]) + class TestAsyncFinancialTransactions: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -64,6 +84,16 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(FinancialTransaction, financial_transaction, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.cards.financial_transactions.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + financial_transaction = response.parse() + assert_matches_type(FinancialTransaction, financial_transaction, path=["response"]) + @parametrize async def test_method_list(self, client: AsyncLithic) -> None: financial_transaction = await client.cards.financial_transactions.list( @@ -84,3 +114,12 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: status="DECLINED", ) assert_matches_type(AsyncSinglePage[FinancialTransaction], financial_transaction, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.cards.financial_transactions.with_raw_response.list( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + financial_transaction = response.parse() + assert_matches_type(AsyncSinglePage[FinancialTransaction], financial_transaction, path=["response"]) diff --git a/tests/api_resources/events/test_subscriptions.py b/tests/api_resources/events/test_subscriptions.py index 4d8a912f..ca5a38e2 100644 --- a/tests/api_resources/events/test_subscriptions.py +++ b/tests/api_resources/events/test_subscriptions.py @@ -10,6 +10,7 @@ from tests.utils import assert_matches_type from lithic.types import MessageAttempt, EventSubscription from lithic._utils import parse_datetime +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage from lithic.types.events import SubscriptionRetrieveSecretResponse @@ -39,6 +40,15 @@ def test_method_create_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(EventSubscription, subscription, path=["response"]) + @parametrize + def test_raw_response_create(self, client: Lithic) -> None: + response = client.events.subscriptions.with_raw_response.create( + url="https://example.com", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert_matches_type(EventSubscription, subscription, path=["response"]) + @parametrize def test_method_retrieve(self, client: Lithic) -> None: subscription = client.events.subscriptions.retrieve( @@ -46,6 +56,15 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(EventSubscription, subscription, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.events.subscriptions.with_raw_response.retrieve( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert_matches_type(EventSubscription, subscription, path=["response"]) + @parametrize def test_method_update(self, client: Lithic) -> None: subscription = client.events.subscriptions.update( @@ -65,6 +84,16 @@ def test_method_update_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(EventSubscription, subscription, path=["response"]) + @parametrize + def test_raw_response_update(self, client: Lithic) -> None: + response = client.events.subscriptions.with_raw_response.update( + "string", + url="https://example.com", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert_matches_type(EventSubscription, subscription, path=["response"]) + @parametrize def test_method_list(self, client: Lithic) -> None: subscription = client.events.subscriptions.list() @@ -79,6 +108,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[EventSubscription], subscription, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.events.subscriptions.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert_matches_type(SyncCursorPage[EventSubscription], subscription, path=["response"]) + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") @parametrize def test_method_delete(self, client: Lithic) -> None: @@ -87,6 +123,16 @@ def test_method_delete(self, client: Lithic) -> None: ) assert subscription is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") + @parametrize + def test_raw_response_delete(self, client: Lithic) -> None: + response = client.events.subscriptions.with_raw_response.delete( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert subscription is None + @parametrize def test_method_list_attempts(self, client: Lithic) -> None: subscription = client.events.subscriptions.list_attempts( @@ -107,6 +153,15 @@ def test_method_list_attempts_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[MessageAttempt], subscription, path=["response"]) + @parametrize + def test_raw_response_list_attempts(self, client: Lithic) -> None: + response = client.events.subscriptions.with_raw_response.list_attempts( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert_matches_type(SyncCursorPage[MessageAttempt], subscription, path=["response"]) + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") @parametrize def test_method_recover(self, client: Lithic) -> None: @@ -125,6 +180,16 @@ def test_method_recover_with_all_params(self, client: Lithic) -> None: ) assert subscription is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") + @parametrize + def test_raw_response_recover(self, client: Lithic) -> None: + response = client.events.subscriptions.with_raw_response.recover( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert subscription is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") @parametrize def test_method_replay_missing(self, client: Lithic) -> None: @@ -143,6 +208,16 @@ def test_method_replay_missing_with_all_params(self, client: Lithic) -> None: ) assert subscription is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") + @parametrize + def test_raw_response_replay_missing(self, client: Lithic) -> None: + response = client.events.subscriptions.with_raw_response.replay_missing( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert subscription is None + @parametrize def test_method_retrieve_secret(self, client: Lithic) -> None: subscription = client.events.subscriptions.retrieve_secret( @@ -150,6 +225,15 @@ def test_method_retrieve_secret(self, client: Lithic) -> None: ) assert_matches_type(SubscriptionRetrieveSecretResponse, subscription, path=["response"]) + @parametrize + def test_raw_response_retrieve_secret(self, client: Lithic) -> None: + response = client.events.subscriptions.with_raw_response.retrieve_secret( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert_matches_type(SubscriptionRetrieveSecretResponse, subscription, path=["response"]) + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") @parametrize def test_method_rotate_secret(self, client: Lithic) -> None: @@ -158,6 +242,16 @@ def test_method_rotate_secret(self, client: Lithic) -> None: ) assert subscription is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") + @parametrize + def test_raw_response_rotate_secret(self, client: Lithic) -> None: + response = client.events.subscriptions.with_raw_response.rotate_secret( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert subscription is None + @parametrize def test_method_send_simulated_example(self, client: Lithic) -> None: subscription = client.events.subscriptions.send_simulated_example( @@ -173,6 +267,15 @@ def test_method_send_simulated_example_with_all_params(self, client: Lithic) -> ) assert subscription is None + @parametrize + def test_raw_response_send_simulated_example(self, client: Lithic) -> None: + response = client.events.subscriptions.with_raw_response.send_simulated_example( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert subscription is None + class TestAsyncSubscriptions: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -196,6 +299,15 @@ async def test_method_create_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(EventSubscription, subscription, path=["response"]) + @parametrize + async def test_raw_response_create(self, client: AsyncLithic) -> None: + response = await client.events.subscriptions.with_raw_response.create( + url="https://example.com", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert_matches_type(EventSubscription, subscription, path=["response"]) + @parametrize async def test_method_retrieve(self, client: AsyncLithic) -> None: subscription = await client.events.subscriptions.retrieve( @@ -203,6 +315,15 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(EventSubscription, subscription, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.events.subscriptions.with_raw_response.retrieve( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert_matches_type(EventSubscription, subscription, path=["response"]) + @parametrize async def test_method_update(self, client: AsyncLithic) -> None: subscription = await client.events.subscriptions.update( @@ -222,6 +343,16 @@ async def test_method_update_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(EventSubscription, subscription, path=["response"]) + @parametrize + async def test_raw_response_update(self, client: AsyncLithic) -> None: + response = await client.events.subscriptions.with_raw_response.update( + "string", + url="https://example.com", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert_matches_type(EventSubscription, subscription, path=["response"]) + @parametrize async def test_method_list(self, client: AsyncLithic) -> None: subscription = await client.events.subscriptions.list() @@ -236,6 +367,13 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(AsyncCursorPage[EventSubscription], subscription, path=["response"]) + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.events.subscriptions.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert_matches_type(AsyncCursorPage[EventSubscription], subscription, path=["response"]) + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") @parametrize async def test_method_delete(self, client: AsyncLithic) -> None: @@ -244,6 +382,16 @@ async def test_method_delete(self, client: AsyncLithic) -> None: ) assert subscription is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") + @parametrize + async def test_raw_response_delete(self, client: AsyncLithic) -> None: + response = await client.events.subscriptions.with_raw_response.delete( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert subscription is None + @parametrize async def test_method_list_attempts(self, client: AsyncLithic) -> None: subscription = await client.events.subscriptions.list_attempts( @@ -264,6 +412,15 @@ async def test_method_list_attempts_with_all_params(self, client: AsyncLithic) - ) assert_matches_type(AsyncCursorPage[MessageAttempt], subscription, path=["response"]) + @parametrize + async def test_raw_response_list_attempts(self, client: AsyncLithic) -> None: + response = await client.events.subscriptions.with_raw_response.list_attempts( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert_matches_type(AsyncCursorPage[MessageAttempt], subscription, path=["response"]) + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") @parametrize async def test_method_recover(self, client: AsyncLithic) -> None: @@ -282,6 +439,16 @@ async def test_method_recover_with_all_params(self, client: AsyncLithic) -> None ) assert subscription is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") + @parametrize + async def test_raw_response_recover(self, client: AsyncLithic) -> None: + response = await client.events.subscriptions.with_raw_response.recover( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert subscription is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") @parametrize async def test_method_replay_missing(self, client: AsyncLithic) -> None: @@ -300,6 +467,16 @@ async def test_method_replay_missing_with_all_params(self, client: AsyncLithic) ) assert subscription is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") + @parametrize + async def test_raw_response_replay_missing(self, client: AsyncLithic) -> None: + response = await client.events.subscriptions.with_raw_response.replay_missing( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert subscription is None + @parametrize async def test_method_retrieve_secret(self, client: AsyncLithic) -> None: subscription = await client.events.subscriptions.retrieve_secret( @@ -307,6 +484,15 @@ async def test_method_retrieve_secret(self, client: AsyncLithic) -> None: ) assert_matches_type(SubscriptionRetrieveSecretResponse, subscription, path=["response"]) + @parametrize + async def test_raw_response_retrieve_secret(self, client: AsyncLithic) -> None: + response = await client.events.subscriptions.with_raw_response.retrieve_secret( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert_matches_type(SubscriptionRetrieveSecretResponse, subscription, path=["response"]) + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") @parametrize async def test_method_rotate_secret(self, client: AsyncLithic) -> None: @@ -315,6 +501,16 @@ async def test_method_rotate_secret(self, client: AsyncLithic) -> None: ) assert subscription is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") + @parametrize + async def test_raw_response_rotate_secret(self, client: AsyncLithic) -> None: + response = await client.events.subscriptions.with_raw_response.rotate_secret( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert subscription is None + @parametrize async def test_method_send_simulated_example(self, client: AsyncLithic) -> None: subscription = await client.events.subscriptions.send_simulated_example( @@ -329,3 +525,12 @@ async def test_method_send_simulated_example_with_all_params(self, client: Async event_type="account_holder.created", ) assert subscription is None + + @parametrize + async def test_raw_response_send_simulated_example(self, client: AsyncLithic) -> None: + response = await client.events.subscriptions.with_raw_response.send_simulated_example( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + subscription = response.parse() + assert subscription is None diff --git a/tests/api_resources/external_bank_accounts/test_micro_deposits.py b/tests/api_resources/external_bank_accounts/test_micro_deposits.py index 7253ab72..1a8b2d0b 100644 --- a/tests/api_resources/external_bank_accounts/test_micro_deposits.py +++ b/tests/api_resources/external_bank_accounts/test_micro_deposits.py @@ -8,6 +8,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type +from lithic._client import Lithic, AsyncLithic from lithic.types.external_bank_accounts import MicroDepositCreateResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -27,6 +28,16 @@ def test_method_create(self, client: Lithic) -> None: ) assert_matches_type(MicroDepositCreateResponse, micro_deposit, path=["response"]) + @parametrize + def test_raw_response_create(self, client: Lithic) -> None: + response = client.external_bank_accounts.micro_deposits.with_raw_response.create( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + micro_deposits=[0, 0, 0], + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + micro_deposit = response.parse() + assert_matches_type(MicroDepositCreateResponse, micro_deposit, path=["response"]) + class TestAsyncMicroDeposits: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -40,3 +51,13 @@ async def test_method_create(self, client: AsyncLithic) -> None: micro_deposits=[0, 0, 0], ) assert_matches_type(MicroDepositCreateResponse, micro_deposit, path=["response"]) + + @parametrize + async def test_raw_response_create(self, client: AsyncLithic) -> None: + response = await client.external_bank_accounts.micro_deposits.with_raw_response.create( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + micro_deposits=[0, 0, 0], + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + micro_deposit = response.parse() + assert_matches_type(MicroDepositCreateResponse, micro_deposit, path=["response"]) diff --git a/tests/api_resources/financial_accounts/statements/test_line_items.py b/tests/api_resources/financial_accounts/statements/test_line_items.py index 6595c764..faadb48b 100644 --- a/tests/api_resources/financial_accounts/statements/test_line_items.py +++ b/tests/api_resources/financial_accounts/statements/test_line_items.py @@ -8,6 +8,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage from lithic.types.financial_accounts.statements import LineItemListResponse @@ -39,6 +40,16 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[LineItemListResponse], line_item, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.financial_accounts.statements.line_items.with_raw_response.list( + "string", + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + line_item = response.parse() + assert_matches_type(SyncCursorPage[LineItemListResponse], line_item, path=["response"]) + class TestAsyncLineItems: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -63,3 +74,13 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: starting_after="string", ) assert_matches_type(AsyncCursorPage[LineItemListResponse], line_item, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.financial_accounts.statements.line_items.with_raw_response.list( + "string", + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + line_item = response.parse() + assert_matches_type(AsyncCursorPage[LineItemListResponse], line_item, path=["response"]) diff --git a/tests/api_resources/financial_accounts/test_balances.py b/tests/api_resources/financial_accounts/test_balances.py index d01cb4e4..cb054f03 100644 --- a/tests/api_resources/financial_accounts/test_balances.py +++ b/tests/api_resources/financial_accounts/test_balances.py @@ -10,6 +10,7 @@ from tests.utils import assert_matches_type from lithic.types import Balance from lithic._utils import parse_datetime +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncSinglePage, AsyncSinglePage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -37,6 +38,15 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncSinglePage[Balance], balance, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.financial_accounts.balances.with_raw_response.list( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + balance = response.parse() + assert_matches_type(SyncSinglePage[Balance], balance, path=["response"]) + class TestAsyncBalances: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -58,3 +68,12 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: last_transaction_event_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert_matches_type(AsyncSinglePage[Balance], balance, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.financial_accounts.balances.with_raw_response.list( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + balance = response.parse() + assert_matches_type(AsyncSinglePage[Balance], balance, path=["response"]) diff --git a/tests/api_resources/financial_accounts/test_financial_transactions.py b/tests/api_resources/financial_accounts/test_financial_transactions.py index 48d6de55..61576fbf 100644 --- a/tests/api_resources/financial_accounts/test_financial_transactions.py +++ b/tests/api_resources/financial_accounts/test_financial_transactions.py @@ -10,6 +10,7 @@ from tests.utils import assert_matches_type from lithic.types import FinancialTransaction from lithic._utils import parse_datetime +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncSinglePage, AsyncSinglePage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -29,6 +30,16 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(FinancialTransaction, financial_transaction, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.financial_accounts.financial_transactions.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + financial_transaction = response.parse() + assert_matches_type(FinancialTransaction, financial_transaction, path=["response"]) + @parametrize def test_method_list(self, client: Lithic) -> None: financial_transaction = client.financial_accounts.financial_transactions.list( @@ -50,6 +61,15 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncSinglePage[FinancialTransaction], financial_transaction, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.financial_accounts.financial_transactions.with_raw_response.list( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + financial_transaction = response.parse() + assert_matches_type(SyncSinglePage[FinancialTransaction], financial_transaction, path=["response"]) + class TestAsyncFinancialTransactions: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -64,6 +84,16 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(FinancialTransaction, financial_transaction, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.financial_accounts.financial_transactions.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + financial_transaction = response.parse() + assert_matches_type(FinancialTransaction, financial_transaction, path=["response"]) + @parametrize async def test_method_list(self, client: AsyncLithic) -> None: financial_transaction = await client.financial_accounts.financial_transactions.list( @@ -84,3 +114,12 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: status="DECLINED", ) assert_matches_type(AsyncSinglePage[FinancialTransaction], financial_transaction, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.financial_accounts.financial_transactions.with_raw_response.list( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + financial_transaction = response.parse() + assert_matches_type(AsyncSinglePage[FinancialTransaction], financial_transaction, path=["response"]) diff --git a/tests/api_resources/financial_accounts/test_statements.py b/tests/api_resources/financial_accounts/test_statements.py index 06841bdb..0b03a628 100644 --- a/tests/api_resources/financial_accounts/test_statements.py +++ b/tests/api_resources/financial_accounts/test_statements.py @@ -9,6 +9,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type from lithic._utils import parse_date +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage from lithic.types.financial_accounts import Statement @@ -29,6 +30,16 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(Statement, statement, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.financial_accounts.statements.with_raw_response.retrieve( + "string", + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + statement = response.parse() + assert_matches_type(Statement, statement, path=["response"]) + @parametrize def test_method_list(self, client: Lithic) -> None: statement = client.financial_accounts.statements.list( @@ -48,6 +59,15 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[Statement], statement, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.financial_accounts.statements.with_raw_response.list( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + statement = response.parse() + assert_matches_type(SyncCursorPage[Statement], statement, path=["response"]) + class TestAsyncStatements: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -62,6 +82,16 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(Statement, statement, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.financial_accounts.statements.with_raw_response.retrieve( + "string", + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + statement = response.parse() + assert_matches_type(Statement, statement, path=["response"]) + @parametrize async def test_method_list(self, client: AsyncLithic) -> None: statement = await client.financial_accounts.statements.list( @@ -80,3 +110,12 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: starting_after="string", ) assert_matches_type(AsyncCursorPage[Statement], statement, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.financial_accounts.statements.with_raw_response.list( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + statement = response.parse() + assert_matches_type(AsyncCursorPage[Statement], statement, path=["response"]) diff --git a/tests/api_resources/reports/test_settlement.py b/tests/api_resources/reports/test_settlement.py index 51879577..4e4a93fb 100644 --- a/tests/api_resources/reports/test_settlement.py +++ b/tests/api_resources/reports/test_settlement.py @@ -10,6 +10,7 @@ from tests.utils import assert_matches_type from lithic.types import SettlementDetail from lithic._utils import parse_date +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage from lithic.types.reports import SettlementSummaryResponse @@ -39,6 +40,15 @@ def test_method_list_details_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[SettlementDetail], settlement, path=["response"]) + @parametrize + def test_raw_response_list_details(self, client: Lithic) -> None: + response = client.reports.settlement.with_raw_response.list_details( + parse_date("2019-12-27"), + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + settlement = response.parse() + assert_matches_type(SyncCursorPage[SettlementDetail], settlement, path=["response"]) + @parametrize def test_method_summary(self, client: Lithic) -> None: settlement = client.reports.settlement.summary( @@ -46,6 +56,15 @@ def test_method_summary(self, client: Lithic) -> None: ) assert_matches_type(SettlementSummaryResponse, settlement, path=["response"]) + @parametrize + def test_raw_response_summary(self, client: Lithic) -> None: + response = client.reports.settlement.with_raw_response.summary( + parse_date("2019-12-27"), + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + settlement = response.parse() + assert_matches_type(SettlementSummaryResponse, settlement, path=["response"]) + class TestAsyncSettlement: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -69,9 +88,27 @@ async def test_method_list_details_with_all_params(self, client: AsyncLithic) -> ) assert_matches_type(AsyncCursorPage[SettlementDetail], settlement, path=["response"]) + @parametrize + async def test_raw_response_list_details(self, client: AsyncLithic) -> None: + response = await client.reports.settlement.with_raw_response.list_details( + parse_date("2019-12-27"), + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + settlement = response.parse() + assert_matches_type(AsyncCursorPage[SettlementDetail], settlement, path=["response"]) + @parametrize async def test_method_summary(self, client: AsyncLithic) -> None: settlement = await client.reports.settlement.summary( parse_date("2019-12-27"), ) assert_matches_type(SettlementSummaryResponse, settlement, path=["response"]) + + @parametrize + async def test_raw_response_summary(self, client: AsyncLithic) -> None: + response = await client.reports.settlement.with_raw_response.summary( + parse_date("2019-12-27"), + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + settlement = response.parse() + assert_matches_type(SettlementSummaryResponse, settlement, path=["response"]) diff --git a/tests/api_resources/test_account_holders.py b/tests/api_resources/test_account_holders.py index 703b7a40..2b4d18fc 100644 --- a/tests/api_resources/test_account_holders.py +++ b/tests/api_resources/test_account_holders.py @@ -14,6 +14,7 @@ AccountHolderUpdateResponse, AccountHolderListDocumentsResponse, ) +from lithic._client import Lithic, AsyncLithic base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My Lithic API Key" @@ -284,6 +285,129 @@ def test_method_create_with_all_params_overload_1(self, client: Lithic) -> None: ) assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize + def test_raw_response_create_overload_1(self, client: Lithic) -> None: + response = client.account_holders.with_raw_response.create( + beneficial_owner_entities=[ + { + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "government_id": "114-123-1513", + "legal_business_name": "Acme, Inc.", + "phone_numbers": ["+12124007676"], + }, + { + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "government_id": "114-123-1513", + "legal_business_name": "Acme, Inc.", + "phone_numbers": ["+12124007676"], + }, + { + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "government_id": "114-123-1513", + "legal_business_name": "Acme, Inc.", + "phone_numbers": ["+12124007676"], + }, + ], + beneficial_owner_individuals=[ + { + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "dob": "1991-03-08 08:00:00", + "email": "tom@middle-earth.com", + "first_name": "Tom", + "government_id": "111-23-1412", + "last_name": "Bombadil", + "phone_number": "+12124007676", + }, + { + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "dob": "1991-03-08 08:00:00", + "email": "tom@middle-earth.com", + "first_name": "Tom", + "government_id": "111-23-1412", + "last_name": "Bombadil", + "phone_number": "+12124007676", + }, + { + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "dob": "1991-03-08 08:00:00", + "email": "tom@middle-earth.com", + "first_name": "Tom", + "government_id": "111-23-1412", + "last_name": "Bombadil", + "phone_number": "+12124007676", + }, + ], + business_entity={ + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "government_id": "114-123-1513", + "legal_business_name": "Acme, Inc.", + "phone_numbers": ["+12124007676"], + }, + control_person={ + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "dob": "1991-03-08 08:00:00", + "email": "tom@middle-earth.com", + "first_name": "Tom", + "government_id": "111-23-1412", + "last_name": "Bombadil", + "phone_number": "+12124007676", + }, + nature_of_business="Software company selling solutions to the restaurant industry", + tos_timestamp="2018-05-29T21:16:05Z", + workflow="KYB_BASIC", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize def test_method_create_overload_2(self, client: Lithic) -> None: account_holder = client.account_holders.create( @@ -332,6 +456,31 @@ def test_method_create_with_all_params_overload_2(self, client: Lithic) -> None: ) assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize + def test_raw_response_create_overload_2(self, client: Lithic) -> None: + response = client.account_holders.with_raw_response.create( + individual={ + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "dob": "1991-03-08 08:00:00", + "email": "tom@middle-earth.com", + "first_name": "Tom", + "government_id": "111-23-1412", + "last_name": "Bombadil", + "phone_number": "+12124007676", + }, + tos_timestamp="string", + workflow="KYC_ADVANCED", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize def test_method_create_overload_3(self, client: Lithic) -> None: account_holder = client.account_holders.create( @@ -365,6 +514,20 @@ def test_method_create_with_all_params_overload_3(self, client: Lithic) -> None: ) assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize + def test_raw_response_create_overload_3(self, client: Lithic) -> None: + response = client.account_holders.with_raw_response.create( + email="string", + first_name="string", + kyc_exemption_type="AUTHORIZED_USER", + last_name="string", + phone_number="string", + workflow="KYC_EXEMPT", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize def test_method_retrieve(self, client: Lithic) -> None: account_holder = client.account_holders.retrieve( @@ -372,6 +535,15 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.account_holders.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize def test_method_update(self, client: Lithic) -> None: account_holder = client.account_holders.update( @@ -389,6 +561,15 @@ def test_method_update_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(AccountHolderUpdateResponse, account_holder, path=["response"]) + @parametrize + def test_raw_response_update(self, client: Lithic) -> None: + response = client.account_holders.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolderUpdateResponse, account_holder, path=["response"]) + @parametrize def test_method_list_documents(self, client: Lithic) -> None: account_holder = client.account_holders.list_documents( @@ -396,6 +577,15 @@ def test_method_list_documents(self, client: Lithic) -> None: ) assert_matches_type(AccountHolderListDocumentsResponse, account_holder, path=["response"]) + @parametrize + def test_raw_response_list_documents(self, client: Lithic) -> None: + response = client.account_holders.with_raw_response.list_documents( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolderListDocumentsResponse, account_holder, path=["response"]) + @parametrize def test_method_resubmit(self, client: Lithic) -> None: account_holder = client.account_holders.resubmit( @@ -420,6 +610,32 @@ def test_method_resubmit(self, client: Lithic) -> None: ) assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize + def test_raw_response_resubmit(self, client: Lithic) -> None: + response = client.account_holders.with_raw_response.resubmit( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + individual={ + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "dob": "1991-03-08 08:00:00", + "email": "tom@middle-earth.com", + "first_name": "Tom", + "government_id": "111-23-1412", + "last_name": "Bombadil", + "phone_number": "+12124007676", + }, + tos_timestamp="2018-05-29T21:16:05Z", + workflow="KYC_ADVANCED", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize def test_method_retrieve_document(self, client: Lithic) -> None: account_holder = client.account_holders.retrieve_document( @@ -428,6 +644,16 @@ def test_method_retrieve_document(self, client: Lithic) -> None: ) assert_matches_type(AccountHolderDocument, account_holder, path=["response"]) + @parametrize + def test_raw_response_retrieve_document(self, client: Lithic) -> None: + response = client.account_holders.with_raw_response.retrieve_document( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + account_holder_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolderDocument, account_holder, path=["response"]) + @parametrize def test_method_upload_document(self, client: Lithic) -> None: account_holder = client.account_holders.upload_document( @@ -436,6 +662,16 @@ def test_method_upload_document(self, client: Lithic) -> None: ) assert_matches_type(AccountHolderDocument, account_holder, path=["response"]) + @parametrize + def test_raw_response_upload_document(self, client: Lithic) -> None: + response = client.account_holders.with_raw_response.upload_document( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + document_type="drivers_license", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolderDocument, account_holder, path=["response"]) + class TestAsyncAccountHolders: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -702,6 +938,129 @@ async def test_method_create_with_all_params_overload_1(self, client: AsyncLithi ) assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize + async def test_raw_response_create_overload_1(self, client: AsyncLithic) -> None: + response = await client.account_holders.with_raw_response.create( + beneficial_owner_entities=[ + { + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "government_id": "114-123-1513", + "legal_business_name": "Acme, Inc.", + "phone_numbers": ["+12124007676"], + }, + { + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "government_id": "114-123-1513", + "legal_business_name": "Acme, Inc.", + "phone_numbers": ["+12124007676"], + }, + { + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "government_id": "114-123-1513", + "legal_business_name": "Acme, Inc.", + "phone_numbers": ["+12124007676"], + }, + ], + beneficial_owner_individuals=[ + { + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "dob": "1991-03-08 08:00:00", + "email": "tom@middle-earth.com", + "first_name": "Tom", + "government_id": "111-23-1412", + "last_name": "Bombadil", + "phone_number": "+12124007676", + }, + { + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "dob": "1991-03-08 08:00:00", + "email": "tom@middle-earth.com", + "first_name": "Tom", + "government_id": "111-23-1412", + "last_name": "Bombadil", + "phone_number": "+12124007676", + }, + { + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "dob": "1991-03-08 08:00:00", + "email": "tom@middle-earth.com", + "first_name": "Tom", + "government_id": "111-23-1412", + "last_name": "Bombadil", + "phone_number": "+12124007676", + }, + ], + business_entity={ + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "government_id": "114-123-1513", + "legal_business_name": "Acme, Inc.", + "phone_numbers": ["+12124007676"], + }, + control_person={ + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "dob": "1991-03-08 08:00:00", + "email": "tom@middle-earth.com", + "first_name": "Tom", + "government_id": "111-23-1412", + "last_name": "Bombadil", + "phone_number": "+12124007676", + }, + nature_of_business="Software company selling solutions to the restaurant industry", + tos_timestamp="2018-05-29T21:16:05Z", + workflow="KYB_BASIC", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize async def test_method_create_overload_2(self, client: AsyncLithic) -> None: account_holder = await client.account_holders.create( @@ -750,6 +1109,31 @@ async def test_method_create_with_all_params_overload_2(self, client: AsyncLithi ) assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize + async def test_raw_response_create_overload_2(self, client: AsyncLithic) -> None: + response = await client.account_holders.with_raw_response.create( + individual={ + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "dob": "1991-03-08 08:00:00", + "email": "tom@middle-earth.com", + "first_name": "Tom", + "government_id": "111-23-1412", + "last_name": "Bombadil", + "phone_number": "+12124007676", + }, + tos_timestamp="string", + workflow="KYC_ADVANCED", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize async def test_method_create_overload_3(self, client: AsyncLithic) -> None: account_holder = await client.account_holders.create( @@ -783,6 +1167,20 @@ async def test_method_create_with_all_params_overload_3(self, client: AsyncLithi ) assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize + async def test_raw_response_create_overload_3(self, client: AsyncLithic) -> None: + response = await client.account_holders.with_raw_response.create( + email="string", + first_name="string", + kyc_exemption_type="AUTHORIZED_USER", + last_name="string", + phone_number="string", + workflow="KYC_EXEMPT", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize async def test_method_retrieve(self, client: AsyncLithic) -> None: account_holder = await client.account_holders.retrieve( @@ -790,6 +1188,15 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.account_holders.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize async def test_method_update(self, client: AsyncLithic) -> None: account_holder = await client.account_holders.update( @@ -807,6 +1214,15 @@ async def test_method_update_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(AccountHolderUpdateResponse, account_holder, path=["response"]) + @parametrize + async def test_raw_response_update(self, client: AsyncLithic) -> None: + response = await client.account_holders.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolderUpdateResponse, account_holder, path=["response"]) + @parametrize async def test_method_list_documents(self, client: AsyncLithic) -> None: account_holder = await client.account_holders.list_documents( @@ -814,6 +1230,15 @@ async def test_method_list_documents(self, client: AsyncLithic) -> None: ) assert_matches_type(AccountHolderListDocumentsResponse, account_holder, path=["response"]) + @parametrize + async def test_raw_response_list_documents(self, client: AsyncLithic) -> None: + response = await client.account_holders.with_raw_response.list_documents( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolderListDocumentsResponse, account_holder, path=["response"]) + @parametrize async def test_method_resubmit(self, client: AsyncLithic) -> None: account_holder = await client.account_holders.resubmit( @@ -838,6 +1263,32 @@ async def test_method_resubmit(self, client: AsyncLithic) -> None: ) assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize + async def test_raw_response_resubmit(self, client: AsyncLithic) -> None: + response = await client.account_holders.with_raw_response.resubmit( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + individual={ + "address": { + "address1": "123 Old Forest Way", + "city": "Omaha", + "country": "USA", + "postal_code": "68022", + "state": "NE", + }, + "dob": "1991-03-08 08:00:00", + "email": "tom@middle-earth.com", + "first_name": "Tom", + "government_id": "111-23-1412", + "last_name": "Bombadil", + "phone_number": "+12124007676", + }, + tos_timestamp="2018-05-29T21:16:05Z", + workflow="KYC_ADVANCED", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolder, account_holder, path=["response"]) + @parametrize async def test_method_retrieve_document(self, client: AsyncLithic) -> None: account_holder = await client.account_holders.retrieve_document( @@ -846,6 +1297,16 @@ async def test_method_retrieve_document(self, client: AsyncLithic) -> None: ) assert_matches_type(AccountHolderDocument, account_holder, path=["response"]) + @parametrize + async def test_raw_response_retrieve_document(self, client: AsyncLithic) -> None: + response = await client.account_holders.with_raw_response.retrieve_document( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + account_holder_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolderDocument, account_holder, path=["response"]) + @parametrize async def test_method_upload_document(self, client: AsyncLithic) -> None: account_holder = await client.account_holders.upload_document( @@ -853,3 +1314,13 @@ async def test_method_upload_document(self, client: AsyncLithic) -> None: document_type="drivers_license", ) assert_matches_type(AccountHolderDocument, account_holder, path=["response"]) + + @parametrize + async def test_raw_response_upload_document(self, client: AsyncLithic) -> None: + response = await client.account_holders.with_raw_response.upload_document( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + document_type="drivers_license", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account_holder = response.parse() + assert_matches_type(AccountHolderDocument, account_holder, path=["response"]) diff --git a/tests/api_resources/test_accounts.py b/tests/api_resources/test_accounts.py index f1ba0738..099c12c1 100644 --- a/tests/api_resources/test_accounts.py +++ b/tests/api_resources/test_accounts.py @@ -10,6 +10,7 @@ from tests.utils import assert_matches_type from lithic.types import Account from lithic._utils import parse_datetime +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -28,6 +29,15 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(Account, account, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.accounts.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account = response.parse() + assert_matches_type(Account, account, path=["response"]) + @pytest.mark.skip(reason="Prism returns invalid data") @parametrize def test_method_update(self, client: Lithic) -> None: @@ -56,6 +66,16 @@ def test_method_update_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(Account, account, path=["response"]) + @pytest.mark.skip(reason="Prism returns invalid data") + @parametrize + def test_raw_response_update(self, client: Lithic) -> None: + response = client.accounts.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account = response.parse() + assert_matches_type(Account, account, path=["response"]) + @parametrize def test_method_list(self, client: Lithic) -> None: account = client.accounts.list() @@ -72,6 +92,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[Account], account, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.accounts.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account = response.parse() + assert_matches_type(SyncCursorPage[Account], account, path=["response"]) + class TestAsyncAccounts: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -85,6 +112,15 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(Account, account, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.accounts.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account = response.parse() + assert_matches_type(Account, account, path=["response"]) + @pytest.mark.skip(reason="Prism returns invalid data") @parametrize async def test_method_update(self, client: AsyncLithic) -> None: @@ -113,6 +149,16 @@ async def test_method_update_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(Account, account, path=["response"]) + @pytest.mark.skip(reason="Prism returns invalid data") + @parametrize + async def test_raw_response_update(self, client: AsyncLithic) -> None: + response = await client.accounts.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account = response.parse() + assert_matches_type(Account, account, path=["response"]) + @parametrize async def test_method_list(self, client: AsyncLithic) -> None: account = await client.accounts.list() @@ -128,3 +174,10 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: starting_after="string", ) assert_matches_type(AsyncCursorPage[Account], account, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.accounts.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + account = response.parse() + assert_matches_type(AsyncCursorPage[Account], account, path=["response"]) diff --git a/tests/api_resources/test_aggregate_balances.py b/tests/api_resources/test_aggregate_balances.py index 647e3202..79d4e87a 100644 --- a/tests/api_resources/test_aggregate_balances.py +++ b/tests/api_resources/test_aggregate_balances.py @@ -9,6 +9,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type from lithic.types import AggregateBalance +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncSinglePage, AsyncSinglePage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -32,6 +33,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncSinglePage[AggregateBalance], aggregate_balance, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.aggregate_balances.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + aggregate_balance = response.parse() + assert_matches_type(SyncSinglePage[AggregateBalance], aggregate_balance, path=["response"]) + class TestAsyncAggregateBalances: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -49,3 +57,10 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: financial_account_type="ISSUING", ) assert_matches_type(AsyncSinglePage[AggregateBalance], aggregate_balance, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.aggregate_balances.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + aggregate_balance = response.parse() + assert_matches_type(AsyncSinglePage[AggregateBalance], aggregate_balance, path=["response"]) diff --git a/tests/api_resources/test_auth_rules.py b/tests/api_resources/test_auth_rules.py index bcf65874..bcccbee7 100644 --- a/tests/api_resources/test_auth_rules.py +++ b/tests/api_resources/test_auth_rules.py @@ -9,6 +9,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type from lithic.types import AuthRule, AuthRuleRemoveResponse, AuthRuleRetrieveResponse +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -38,6 +39,13 @@ def test_method_create_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(AuthRule, auth_rule, path=["response"]) + @parametrize + def test_raw_response_create(self, client: Lithic) -> None: + response = client.auth_rules.with_raw_response.create() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_rule = response.parse() + assert_matches_type(AuthRule, auth_rule, path=["response"]) + @parametrize def test_method_retrieve(self, client: Lithic) -> None: auth_rule = client.auth_rules.retrieve( @@ -45,6 +53,15 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(AuthRuleRetrieveResponse, auth_rule, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.auth_rules.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_rule = response.parse() + assert_matches_type(AuthRuleRetrieveResponse, auth_rule, path=["response"]) + @parametrize def test_method_update(self, client: Lithic) -> None: auth_rule = client.auth_rules.update( @@ -63,6 +80,15 @@ def test_method_update_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(AuthRule, auth_rule, path=["response"]) + @parametrize + def test_raw_response_update(self, client: Lithic) -> None: + response = client.auth_rules.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_rule = response.parse() + assert_matches_type(AuthRule, auth_rule, path=["response"]) + @parametrize def test_method_list(self, client: Lithic) -> None: auth_rule = client.auth_rules.list() @@ -77,6 +103,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[AuthRule], auth_rule, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.auth_rules.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_rule = response.parse() + assert_matches_type(SyncCursorPage[AuthRule], auth_rule, path=["response"]) + @parametrize def test_method_apply(self, client: Lithic) -> None: auth_rule = client.auth_rules.apply( @@ -94,6 +127,15 @@ def test_method_apply_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(AuthRule, auth_rule, path=["response"]) + @parametrize + def test_raw_response_apply(self, client: Lithic) -> None: + response = client.auth_rules.with_raw_response.apply( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_rule = response.parse() + assert_matches_type(AuthRule, auth_rule, path=["response"]) + @parametrize def test_method_remove(self, client: Lithic) -> None: auth_rule = client.auth_rules.remove() @@ -108,6 +150,13 @@ def test_method_remove_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(AuthRuleRemoveResponse, auth_rule, path=["response"]) + @parametrize + def test_raw_response_remove(self, client: Lithic) -> None: + response = client.auth_rules.with_raw_response.remove() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_rule = response.parse() + assert_matches_type(AuthRuleRemoveResponse, auth_rule, path=["response"]) + class TestAsyncAuthRules: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -132,6 +181,13 @@ async def test_method_create_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(AuthRule, auth_rule, path=["response"]) + @parametrize + async def test_raw_response_create(self, client: AsyncLithic) -> None: + response = await client.auth_rules.with_raw_response.create() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_rule = response.parse() + assert_matches_type(AuthRule, auth_rule, path=["response"]) + @parametrize async def test_method_retrieve(self, client: AsyncLithic) -> None: auth_rule = await client.auth_rules.retrieve( @@ -139,6 +195,15 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(AuthRuleRetrieveResponse, auth_rule, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.auth_rules.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_rule = response.parse() + assert_matches_type(AuthRuleRetrieveResponse, auth_rule, path=["response"]) + @parametrize async def test_method_update(self, client: AsyncLithic) -> None: auth_rule = await client.auth_rules.update( @@ -157,6 +222,15 @@ async def test_method_update_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(AuthRule, auth_rule, path=["response"]) + @parametrize + async def test_raw_response_update(self, client: AsyncLithic) -> None: + response = await client.auth_rules.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_rule = response.parse() + assert_matches_type(AuthRule, auth_rule, path=["response"]) + @parametrize async def test_method_list(self, client: AsyncLithic) -> None: auth_rule = await client.auth_rules.list() @@ -171,6 +245,13 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(AsyncCursorPage[AuthRule], auth_rule, path=["response"]) + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.auth_rules.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_rule = response.parse() + assert_matches_type(AsyncCursorPage[AuthRule], auth_rule, path=["response"]) + @parametrize async def test_method_apply(self, client: AsyncLithic) -> None: auth_rule = await client.auth_rules.apply( @@ -188,6 +269,15 @@ async def test_method_apply_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(AuthRule, auth_rule, path=["response"]) + @parametrize + async def test_raw_response_apply(self, client: AsyncLithic) -> None: + response = await client.auth_rules.with_raw_response.apply( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_rule = response.parse() + assert_matches_type(AuthRule, auth_rule, path=["response"]) + @parametrize async def test_method_remove(self, client: AsyncLithic) -> None: auth_rule = await client.auth_rules.remove() @@ -201,3 +291,10 @@ async def test_method_remove_with_all_params(self, client: AsyncLithic) -> None: program_level=False, ) assert_matches_type(AuthRuleRemoveResponse, auth_rule, path=["response"]) + + @parametrize + async def test_raw_response_remove(self, client: AsyncLithic) -> None: + response = await client.auth_rules.with_raw_response.remove() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_rule = response.parse() + assert_matches_type(AuthRuleRemoveResponse, auth_rule, path=["response"]) diff --git a/tests/api_resources/test_auth_stream_enrollment.py b/tests/api_resources/test_auth_stream_enrollment.py index 33ed639a..2ba14bdc 100644 --- a/tests/api_resources/test_auth_stream_enrollment.py +++ b/tests/api_resources/test_auth_stream_enrollment.py @@ -9,6 +9,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type from lithic.types import AuthStreamSecret, AuthStreamEnrollment +from lithic._client import Lithic, AsyncLithic base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My Lithic API Key" @@ -24,12 +25,27 @@ def test_method_retrieve(self, client: Lithic) -> None: auth_stream_enrollment = client.auth_stream_enrollment.retrieve() assert_matches_type(AuthStreamEnrollment, auth_stream_enrollment, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.auth_stream_enrollment.with_raw_response.retrieve() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_stream_enrollment = response.parse() + assert_matches_type(AuthStreamEnrollment, auth_stream_enrollment, path=["response"]) + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") @parametrize def test_method_disenroll(self, client: Lithic) -> None: auth_stream_enrollment = client.auth_stream_enrollment.disenroll() assert auth_stream_enrollment is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") + @parametrize + def test_raw_response_disenroll(self, client: Lithic) -> None: + response = client.auth_stream_enrollment.with_raw_response.disenroll() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_stream_enrollment = response.parse() + assert auth_stream_enrollment is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") @parametrize def test_method_enroll(self, client: Lithic) -> None: @@ -44,16 +60,38 @@ def test_method_enroll_with_all_params(self, client: Lithic) -> None: ) assert auth_stream_enrollment is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") + @parametrize + def test_raw_response_enroll(self, client: Lithic) -> None: + response = client.auth_stream_enrollment.with_raw_response.enroll() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_stream_enrollment = response.parse() + assert auth_stream_enrollment is None + @parametrize def test_method_retrieve_secret(self, client: Lithic) -> None: auth_stream_enrollment = client.auth_stream_enrollment.retrieve_secret() assert_matches_type(AuthStreamSecret, auth_stream_enrollment, path=["response"]) + @parametrize + def test_raw_response_retrieve_secret(self, client: Lithic) -> None: + response = client.auth_stream_enrollment.with_raw_response.retrieve_secret() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_stream_enrollment = response.parse() + assert_matches_type(AuthStreamSecret, auth_stream_enrollment, path=["response"]) + @parametrize def test_method_rotate_secret(self, client: Lithic) -> None: auth_stream_enrollment = client.auth_stream_enrollment.rotate_secret() assert auth_stream_enrollment is None + @parametrize + def test_raw_response_rotate_secret(self, client: Lithic) -> None: + response = client.auth_stream_enrollment.with_raw_response.rotate_secret() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_stream_enrollment = response.parse() + assert auth_stream_enrollment is None + class TestAsyncAuthStreamEnrollment: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -65,12 +103,27 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: auth_stream_enrollment = await client.auth_stream_enrollment.retrieve() assert_matches_type(AuthStreamEnrollment, auth_stream_enrollment, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.auth_stream_enrollment.with_raw_response.retrieve() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_stream_enrollment = response.parse() + assert_matches_type(AuthStreamEnrollment, auth_stream_enrollment, path=["response"]) + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") @parametrize async def test_method_disenroll(self, client: AsyncLithic) -> None: auth_stream_enrollment = await client.auth_stream_enrollment.disenroll() assert auth_stream_enrollment is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") + @parametrize + async def test_raw_response_disenroll(self, client: AsyncLithic) -> None: + response = await client.auth_stream_enrollment.with_raw_response.disenroll() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_stream_enrollment = response.parse() + assert auth_stream_enrollment is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") @parametrize async def test_method_enroll(self, client: AsyncLithic) -> None: @@ -85,12 +138,34 @@ async def test_method_enroll_with_all_params(self, client: AsyncLithic) -> None: ) assert auth_stream_enrollment is None + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") + @parametrize + async def test_raw_response_enroll(self, client: AsyncLithic) -> None: + response = await client.auth_stream_enrollment.with_raw_response.enroll() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_stream_enrollment = response.parse() + assert auth_stream_enrollment is None + @parametrize async def test_method_retrieve_secret(self, client: AsyncLithic) -> None: auth_stream_enrollment = await client.auth_stream_enrollment.retrieve_secret() assert_matches_type(AuthStreamSecret, auth_stream_enrollment, path=["response"]) + @parametrize + async def test_raw_response_retrieve_secret(self, client: AsyncLithic) -> None: + response = await client.auth_stream_enrollment.with_raw_response.retrieve_secret() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_stream_enrollment = response.parse() + assert_matches_type(AuthStreamSecret, auth_stream_enrollment, path=["response"]) + @parametrize async def test_method_rotate_secret(self, client: AsyncLithic) -> None: auth_stream_enrollment = await client.auth_stream_enrollment.rotate_secret() assert auth_stream_enrollment is None + + @parametrize + async def test_raw_response_rotate_secret(self, client: AsyncLithic) -> None: + response = await client.auth_stream_enrollment.with_raw_response.rotate_secret() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + auth_stream_enrollment = response.parse() + assert auth_stream_enrollment is None diff --git a/tests/api_resources/test_balances.py b/tests/api_resources/test_balances.py index 1d260776..dd4f1e34 100644 --- a/tests/api_resources/test_balances.py +++ b/tests/api_resources/test_balances.py @@ -10,6 +10,7 @@ from tests.utils import assert_matches_type from lithic.types import Balance from lithic._utils import parse_datetime +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncSinglePage, AsyncSinglePage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -35,6 +36,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncSinglePage[Balance], balance, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.balances.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + balance = response.parse() + assert_matches_type(SyncSinglePage[Balance], balance, path=["response"]) + class TestAsyncBalances: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -54,3 +62,10 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: financial_account_type="ISSUING", ) assert_matches_type(AsyncSinglePage[Balance], balance, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.balances.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + balance = response.parse() + assert_matches_type(AsyncSinglePage[Balance], balance, path=["response"]) diff --git a/tests/api_resources/test_card_product.py b/tests/api_resources/test_card_product.py index 151095e2..5df4e360 100644 --- a/tests/api_resources/test_card_product.py +++ b/tests/api_resources/test_card_product.py @@ -9,6 +9,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type from lithic.types import CardProductCreditDetailResponse +from lithic._client import Lithic, AsyncLithic base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My Lithic API Key" @@ -24,6 +25,13 @@ def test_method_credit_detail(self, client: Lithic) -> None: card_product = client.card_product.credit_detail() assert_matches_type(CardProductCreditDetailResponse, card_product, path=["response"]) + @parametrize + def test_raw_response_credit_detail(self, client: Lithic) -> None: + response = client.card_product.with_raw_response.credit_detail() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_product = response.parse() + assert_matches_type(CardProductCreditDetailResponse, card_product, path=["response"]) + class TestAsyncCardProduct: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -34,3 +42,10 @@ class TestAsyncCardProduct: async def test_method_credit_detail(self, client: AsyncLithic) -> None: card_product = await client.card_product.credit_detail() assert_matches_type(CardProductCreditDetailResponse, card_product, path=["response"]) + + @parametrize + async def test_raw_response_credit_detail(self, client: AsyncLithic) -> None: + response = await client.card_product.with_raw_response.credit_detail() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_product = response.parse() + assert_matches_type(CardProductCreditDetailResponse, card_product, path=["response"]) diff --git a/tests/api_resources/test_card_programs.py b/tests/api_resources/test_card_programs.py index 1db76469..ee36e334 100644 --- a/tests/api_resources/test_card_programs.py +++ b/tests/api_resources/test_card_programs.py @@ -9,6 +9,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type from lithic.types import CardProgram +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -27,6 +28,15 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(CardProgram, card_program, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.card_programs.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_program = response.parse() + assert_matches_type(CardProgram, card_program, path=["response"]) + @parametrize def test_method_list(self, client: Lithic) -> None: card_program = client.card_programs.list() @@ -41,6 +51,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[CardProgram], card_program, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.card_programs.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_program = response.parse() + assert_matches_type(SyncCursorPage[CardProgram], card_program, path=["response"]) + class TestAsyncCardPrograms: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -54,6 +71,15 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(CardProgram, card_program, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.card_programs.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_program = response.parse() + assert_matches_type(CardProgram, card_program, path=["response"]) + @parametrize async def test_method_list(self, client: AsyncLithic) -> None: card_program = await client.card_programs.list() @@ -67,3 +93,10 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: starting_after="string", ) assert_matches_type(AsyncCursorPage[CardProgram], card_program, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.card_programs.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_program = response.parse() + assert_matches_type(AsyncCursorPage[CardProgram], card_program, path=["response"]) diff --git a/tests/api_resources/test_cards.py b/tests/api_resources/test_cards.py index ea7b7ad6..9870e78e 100644 --- a/tests/api_resources/test_cards.py +++ b/tests/api_resources/test_cards.py @@ -10,6 +10,7 @@ from tests.utils import assert_matches_type from lithic.types import Card, CardProvisionResponse from lithic._utils import parse_datetime +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -61,6 +62,15 @@ def test_method_create_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(Card, card, path=["response"]) + @parametrize + def test_raw_response_create(self, client: Lithic) -> None: + response = client.cards.with_raw_response.create( + type="VIRTUAL", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(Card, card, path=["response"]) + @parametrize def test_method_retrieve(self, client: Lithic) -> None: card = client.cards.retrieve( @@ -68,6 +78,15 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(Card, card, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.cards.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(Card, card, path=["response"]) + @parametrize def test_method_update(self, client: Lithic) -> None: card = client.cards.update( @@ -89,6 +108,15 @@ def test_method_update_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(Card, card, path=["response"]) + @parametrize + def test_raw_response_update(self, client: Lithic) -> None: + response = client.cards.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(Card, card, path=["response"]) + @parametrize def test_method_list(self, client: Lithic) -> None: card = client.cards.list() @@ -107,6 +135,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[Card], card, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.cards.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(SyncCursorPage[Card], card, path=["response"]) + @parametrize def test_method_embed(self, client: Lithic) -> None: card = client.cards.embed( @@ -115,6 +150,16 @@ def test_method_embed(self, client: Lithic) -> None: ) assert_matches_type(str, card, path=["response"]) + @parametrize + def test_raw_response_embed(self, client: Lithic) -> None: + response = client.cards.with_raw_response.embed( + embed_request="string", + hmac="string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(str, card, path=["response"]) + def test_get_embed_html(self) -> None: html = self.strict_client.cards.get_embed_html(token="foo") assert "html" in html @@ -145,6 +190,15 @@ def test_method_provision_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(CardProvisionResponse, card, path=["response"]) + @parametrize + def test_raw_response_provision(self, client: Lithic) -> None: + response = client.cards.with_raw_response.provision( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(CardProvisionResponse, card, path=["response"]) + @parametrize def test_method_reissue(self, client: Lithic) -> None: card = client.cards.reissue( @@ -175,6 +229,15 @@ def test_method_reissue_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(Card, card, path=["response"]) + @parametrize + def test_raw_response_reissue(self, client: Lithic) -> None: + response = client.cards.with_raw_response.reissue( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(Card, card, path=["response"]) + class TestAsyncCards: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -221,6 +284,15 @@ async def test_method_create_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(Card, card, path=["response"]) + @parametrize + async def test_raw_response_create(self, client: AsyncLithic) -> None: + response = await client.cards.with_raw_response.create( + type="VIRTUAL", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(Card, card, path=["response"]) + @parametrize async def test_method_retrieve(self, client: AsyncLithic) -> None: card = await client.cards.retrieve( @@ -228,6 +300,15 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(Card, card, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.cards.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(Card, card, path=["response"]) + @parametrize async def test_method_update(self, client: AsyncLithic) -> None: card = await client.cards.update( @@ -249,6 +330,15 @@ async def test_method_update_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(Card, card, path=["response"]) + @parametrize + async def test_raw_response_update(self, client: AsyncLithic) -> None: + response = await client.cards.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(Card, card, path=["response"]) + @parametrize async def test_method_list(self, client: AsyncLithic) -> None: card = await client.cards.list() @@ -267,6 +357,13 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(AsyncCursorPage[Card], card, path=["response"]) + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.cards.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(AsyncCursorPage[Card], card, path=["response"]) + @parametrize async def test_method_embed(self, client: AsyncLithic) -> None: card = await client.cards.embed( @@ -275,6 +372,16 @@ async def test_method_embed(self, client: AsyncLithic) -> None: ) assert_matches_type(str, card, path=["response"]) + @parametrize + async def test_raw_response_embed(self, client: AsyncLithic) -> None: + response = await client.cards.with_raw_response.embed( + embed_request="string", + hmac="string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(str, card, path=["response"]) + async def test_get_embed_html(self) -> None: html = await self.strict_client.cards.get_embed_html(token="foo") assert "html" in html @@ -305,6 +412,15 @@ async def test_method_provision_with_all_params(self, client: AsyncLithic) -> No ) assert_matches_type(CardProvisionResponse, card, path=["response"]) + @parametrize + async def test_raw_response_provision(self, client: AsyncLithic) -> None: + response = await client.cards.with_raw_response.provision( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(CardProvisionResponse, card, path=["response"]) + @parametrize async def test_method_reissue(self, client: AsyncLithic) -> None: card = await client.cards.reissue( @@ -334,3 +450,12 @@ async def test_method_reissue_with_all_params(self, client: AsyncLithic) -> None shipping_method="STANDARD", ) assert_matches_type(Card, card, path=["response"]) + + @parametrize + async def test_raw_response_reissue(self, client: AsyncLithic) -> None: + response = await client.cards.with_raw_response.reissue( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(Card, card, path=["response"]) diff --git a/tests/api_resources/test_digital_card_art.py b/tests/api_resources/test_digital_card_art.py index f02dbafc..2200a834 100644 --- a/tests/api_resources/test_digital_card_art.py +++ b/tests/api_resources/test_digital_card_art.py @@ -9,6 +9,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type from lithic.types import DigitalCardArt +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -34,6 +35,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[DigitalCardArt], digital_card_art, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.digital_card_art.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + digital_card_art = response.parse() + assert_matches_type(SyncCursorPage[DigitalCardArt], digital_card_art, path=["response"]) + class TestAsyncDigitalCardArt: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -53,3 +61,10 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: starting_after="string", ) assert_matches_type(AsyncCursorPage[DigitalCardArt], digital_card_art, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.digital_card_art.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + digital_card_art = response.parse() + assert_matches_type(AsyncCursorPage[DigitalCardArt], digital_card_art, path=["response"]) diff --git a/tests/api_resources/test_disputes.py b/tests/api_resources/test_disputes.py index 519a9167..16d84a82 100644 --- a/tests/api_resources/test_disputes.py +++ b/tests/api_resources/test_disputes.py @@ -10,6 +10,7 @@ from tests.utils import assert_matches_type from lithic.types import Dispute, DisputeEvidence from lithic._utils import parse_datetime +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -41,6 +42,17 @@ def test_method_create_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize + def test_raw_response_create(self, client: Lithic) -> None: + response = client.disputes.with_raw_response.create( + amount=0, + reason="ATM_CASH_MISDISPENSE", + transaction_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize def test_method_retrieve(self, client: Lithic) -> None: dispute = client.disputes.retrieve( @@ -48,6 +60,15 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.disputes.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize def test_method_update(self, client: Lithic) -> None: dispute = client.disputes.update( @@ -66,6 +87,15 @@ def test_method_update_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize + def test_raw_response_update(self, client: Lithic) -> None: + response = client.disputes.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize def test_method_list(self, client: Lithic) -> None: dispute = client.disputes.list() @@ -88,6 +118,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[Dispute], dispute, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.disputes.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(SyncCursorPage[Dispute], dispute, path=["response"]) + @parametrize def test_method_delete(self, client: Lithic) -> None: dispute = client.disputes.delete( @@ -95,6 +132,15 @@ def test_method_delete(self, client: Lithic) -> None: ) assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize + def test_raw_response_delete(self, client: Lithic) -> None: + response = client.disputes.with_raw_response.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize def test_method_delete_evidence(self, client: Lithic) -> None: dispute = client.disputes.delete_evidence( @@ -103,6 +149,16 @@ def test_method_delete_evidence(self, client: Lithic) -> None: ) assert_matches_type(DisputeEvidence, dispute, path=["response"]) + @parametrize + def test_raw_response_delete_evidence(self, client: Lithic) -> None: + response = client.disputes.with_raw_response.delete_evidence( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + dispute_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(DisputeEvidence, dispute, path=["response"]) + @parametrize def test_method_initiate_evidence_upload(self, client: Lithic) -> None: dispute = client.disputes.initiate_evidence_upload( @@ -118,6 +174,15 @@ def test_method_initiate_evidence_upload_with_all_params(self, client: Lithic) - ) assert_matches_type(DisputeEvidence, dispute, path=["response"]) + @parametrize + def test_raw_response_initiate_evidence_upload(self, client: Lithic) -> None: + response = client.disputes.with_raw_response.initiate_evidence_upload( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(DisputeEvidence, dispute, path=["response"]) + @parametrize def test_method_list_evidences(self, client: Lithic) -> None: dispute = client.disputes.list_evidences( @@ -137,6 +202,15 @@ def test_method_list_evidences_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[DisputeEvidence], dispute, path=["response"]) + @parametrize + def test_raw_response_list_evidences(self, client: Lithic) -> None: + response = client.disputes.with_raw_response.list_evidences( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(SyncCursorPage[DisputeEvidence], dispute, path=["response"]) + @parametrize def test_method_retrieve_evidence(self, client: Lithic) -> None: dispute = client.disputes.retrieve_evidence( @@ -145,6 +219,16 @@ def test_method_retrieve_evidence(self, client: Lithic) -> None: ) assert_matches_type(DisputeEvidence, dispute, path=["response"]) + @parametrize + def test_raw_response_retrieve_evidence(self, client: Lithic) -> None: + response = client.disputes.with_raw_response.retrieve_evidence( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + dispute_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(DisputeEvidence, dispute, path=["response"]) + class TestAsyncDisputes: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -171,6 +255,17 @@ async def test_method_create_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize + async def test_raw_response_create(self, client: AsyncLithic) -> None: + response = await client.disputes.with_raw_response.create( + amount=0, + reason="ATM_CASH_MISDISPENSE", + transaction_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize async def test_method_retrieve(self, client: AsyncLithic) -> None: dispute = await client.disputes.retrieve( @@ -178,6 +273,15 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.disputes.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize async def test_method_update(self, client: AsyncLithic) -> None: dispute = await client.disputes.update( @@ -196,6 +300,15 @@ async def test_method_update_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize + async def test_raw_response_update(self, client: AsyncLithic) -> None: + response = await client.disputes.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize async def test_method_list(self, client: AsyncLithic) -> None: dispute = await client.disputes.list() @@ -218,6 +331,13 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(AsyncCursorPage[Dispute], dispute, path=["response"]) + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.disputes.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(AsyncCursorPage[Dispute], dispute, path=["response"]) + @parametrize async def test_method_delete(self, client: AsyncLithic) -> None: dispute = await client.disputes.delete( @@ -225,6 +345,15 @@ async def test_method_delete(self, client: AsyncLithic) -> None: ) assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize + async def test_raw_response_delete(self, client: AsyncLithic) -> None: + response = await client.disputes.with_raw_response.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(Dispute, dispute, path=["response"]) + @parametrize async def test_method_delete_evidence(self, client: AsyncLithic) -> None: dispute = await client.disputes.delete_evidence( @@ -233,6 +362,16 @@ async def test_method_delete_evidence(self, client: AsyncLithic) -> None: ) assert_matches_type(DisputeEvidence, dispute, path=["response"]) + @parametrize + async def test_raw_response_delete_evidence(self, client: AsyncLithic) -> None: + response = await client.disputes.with_raw_response.delete_evidence( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + dispute_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(DisputeEvidence, dispute, path=["response"]) + @parametrize async def test_method_initiate_evidence_upload(self, client: AsyncLithic) -> None: dispute = await client.disputes.initiate_evidence_upload( @@ -248,6 +387,15 @@ async def test_method_initiate_evidence_upload_with_all_params(self, client: Asy ) assert_matches_type(DisputeEvidence, dispute, path=["response"]) + @parametrize + async def test_raw_response_initiate_evidence_upload(self, client: AsyncLithic) -> None: + response = await client.disputes.with_raw_response.initiate_evidence_upload( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(DisputeEvidence, dispute, path=["response"]) + @parametrize async def test_method_list_evidences(self, client: AsyncLithic) -> None: dispute = await client.disputes.list_evidences( @@ -267,6 +415,15 @@ async def test_method_list_evidences_with_all_params(self, client: AsyncLithic) ) assert_matches_type(AsyncCursorPage[DisputeEvidence], dispute, path=["response"]) + @parametrize + async def test_raw_response_list_evidences(self, client: AsyncLithic) -> None: + response = await client.disputes.with_raw_response.list_evidences( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(AsyncCursorPage[DisputeEvidence], dispute, path=["response"]) + @parametrize async def test_method_retrieve_evidence(self, client: AsyncLithic) -> None: dispute = await client.disputes.retrieve_evidence( @@ -274,3 +431,13 @@ async def test_method_retrieve_evidence(self, client: AsyncLithic) -> None: dispute_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert_matches_type(DisputeEvidence, dispute, path=["response"]) + + @parametrize + async def test_raw_response_retrieve_evidence(self, client: AsyncLithic) -> None: + response = await client.disputes.with_raw_response.retrieve_evidence( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + dispute_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dispute = response.parse() + assert_matches_type(DisputeEvidence, dispute, path=["response"]) diff --git a/tests/api_resources/test_events.py b/tests/api_resources/test_events.py index 47a4a72d..550f22d6 100644 --- a/tests/api_resources/test_events.py +++ b/tests/api_resources/test_events.py @@ -10,6 +10,7 @@ from tests.utils import assert_matches_type from lithic.types import Event, MessageAttempt from lithic._utils import parse_datetime +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -28,6 +29,15 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(Event, event, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.events.with_raw_response.retrieve( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + event = response.parse() + assert_matches_type(Event, event, path=["response"]) + @parametrize def test_method_list(self, client: Lithic) -> None: event = client.events.list() @@ -46,6 +56,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[Event], event, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.events.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + event = response.parse() + assert_matches_type(SyncCursorPage[Event], event, path=["response"]) + @parametrize def test_method_list_attempts(self, client: Lithic) -> None: event = client.events.list_attempts( @@ -66,6 +83,15 @@ def test_method_list_attempts_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[MessageAttempt], event, path=["response"]) + @parametrize + def test_raw_response_list_attempts(self, client: Lithic) -> None: + response = client.events.with_raw_response.list_attempts( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + event = response.parse() + assert_matches_type(SyncCursorPage[MessageAttempt], event, path=["response"]) + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") def test_method_resend(self) -> None: self.strict_client.events.resend( @@ -86,6 +112,15 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(Event, event, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.events.with_raw_response.retrieve( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + event = response.parse() + assert_matches_type(Event, event, path=["response"]) + @parametrize async def test_method_list(self, client: AsyncLithic) -> None: event = await client.events.list() @@ -104,6 +139,13 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(AsyncCursorPage[Event], event, path=["response"]) + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.events.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + event = response.parse() + assert_matches_type(AsyncCursorPage[Event], event, path=["response"]) + @parametrize async def test_method_list_attempts(self, client: AsyncLithic) -> None: event = await client.events.list_attempts( @@ -124,6 +166,15 @@ async def test_method_list_attempts_with_all_params(self, client: AsyncLithic) - ) assert_matches_type(AsyncCursorPage[MessageAttempt], event, path=["response"]) + @parametrize + async def test_raw_response_list_attempts(self, client: AsyncLithic) -> None: + response = await client.events.with_raw_response.list_attempts( + "string", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + event = response.parse() + assert_matches_type(AsyncCursorPage[MessageAttempt], event, path=["response"]) + @pytest.mark.skip(reason="Prism Mock server doesnt want Accept header, but server requires it.") async def test_method_resend(self) -> None: await self.strict_client.events.resend( diff --git a/tests/api_resources/test_external_bank_accounts.py b/tests/api_resources/test_external_bank_accounts.py index 858c0177..b3c701a6 100644 --- a/tests/api_resources/test_external_bank_accounts.py +++ b/tests/api_resources/test_external_bank_accounts.py @@ -15,6 +15,7 @@ ExternalBankAccountRetrieveResponse, ) from lithic._utils import parse_date +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -51,6 +52,18 @@ def test_method_create_with_all_params_overload_1(self, client: Lithic) -> None: ) assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"]) + @parametrize + def test_raw_response_create_overload_1(self, client: Lithic) -> None: + response = client.external_bank_accounts.with_raw_response.create( + owner="x", + owner_type="INDIVIDUAL", + processor_token="x", + verification_method="MANUAL", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + external_bank_account = response.parse() + assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"]) + @parametrize def test_method_create_overload_2(self, client: Lithic) -> None: external_bank_account = client.external_bank_accounts.create( @@ -94,6 +107,22 @@ def test_method_create_with_all_params_overload_2(self, client: Lithic) -> None: ) assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"]) + @parametrize + def test_raw_response_create_overload_2(self, client: Lithic) -> None: + response = client.external_bank_accounts.with_raw_response.create( + account_number="string", + country="USD", + currency="USD", + owner="x", + owner_type="INDIVIDUAL", + routing_number="123456789", + type="CHECKING", + verification_method="MANUAL", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + external_bank_account = response.parse() + assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"]) + @parametrize def test_method_retrieve(self, client: Lithic) -> None: external_bank_account = client.external_bank_accounts.retrieve( @@ -101,6 +130,15 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(ExternalBankAccountRetrieveResponse, external_bank_account, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.external_bank_accounts.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + external_bank_account = response.parse() + assert_matches_type(ExternalBankAccountRetrieveResponse, external_bank_account, path=["response"]) + @parametrize def test_method_update(self, client: Lithic) -> None: external_bank_account = client.external_bank_accounts.update( @@ -130,6 +168,15 @@ def test_method_update_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(ExternalBankAccountUpdateResponse, external_bank_account, path=["response"]) + @parametrize + def test_raw_response_update(self, client: Lithic) -> None: + response = client.external_bank_accounts.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + external_bank_account = response.parse() + assert_matches_type(ExternalBankAccountUpdateResponse, external_bank_account, path=["response"]) + @parametrize def test_method_list(self, client: Lithic) -> None: external_bank_account = client.external_bank_accounts.list() @@ -150,6 +197,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[ExternalBankAccountListResponse], external_bank_account, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.external_bank_accounts.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + external_bank_account = response.parse() + assert_matches_type(SyncCursorPage[ExternalBankAccountListResponse], external_bank_account, path=["response"]) + class TestAsyncExternalBankAccounts: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -181,6 +235,18 @@ async def test_method_create_with_all_params_overload_1(self, client: AsyncLithi ) assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"]) + @parametrize + async def test_raw_response_create_overload_1(self, client: AsyncLithic) -> None: + response = await client.external_bank_accounts.with_raw_response.create( + owner="x", + owner_type="INDIVIDUAL", + processor_token="x", + verification_method="MANUAL", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + external_bank_account = response.parse() + assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"]) + @parametrize async def test_method_create_overload_2(self, client: AsyncLithic) -> None: external_bank_account = await client.external_bank_accounts.create( @@ -224,6 +290,22 @@ async def test_method_create_with_all_params_overload_2(self, client: AsyncLithi ) assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"]) + @parametrize + async def test_raw_response_create_overload_2(self, client: AsyncLithic) -> None: + response = await client.external_bank_accounts.with_raw_response.create( + account_number="string", + country="USD", + currency="USD", + owner="x", + owner_type="INDIVIDUAL", + routing_number="123456789", + type="CHECKING", + verification_method="MANUAL", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + external_bank_account = response.parse() + assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"]) + @parametrize async def test_method_retrieve(self, client: AsyncLithic) -> None: external_bank_account = await client.external_bank_accounts.retrieve( @@ -231,6 +313,15 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(ExternalBankAccountRetrieveResponse, external_bank_account, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.external_bank_accounts.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + external_bank_account = response.parse() + assert_matches_type(ExternalBankAccountRetrieveResponse, external_bank_account, path=["response"]) + @parametrize async def test_method_update(self, client: AsyncLithic) -> None: external_bank_account = await client.external_bank_accounts.update( @@ -260,6 +351,15 @@ async def test_method_update_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(ExternalBankAccountUpdateResponse, external_bank_account, path=["response"]) + @parametrize + async def test_raw_response_update(self, client: AsyncLithic) -> None: + response = await client.external_bank_accounts.with_raw_response.update( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + external_bank_account = response.parse() + assert_matches_type(ExternalBankAccountUpdateResponse, external_bank_account, path=["response"]) + @parametrize async def test_method_list(self, client: AsyncLithic) -> None: external_bank_account = await client.external_bank_accounts.list() @@ -279,3 +379,10 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: verification_states=["PENDING", "ENABLED", "FAILED_VERIFICATION"], ) assert_matches_type(AsyncCursorPage[ExternalBankAccountListResponse], external_bank_account, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.external_bank_accounts.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + external_bank_account = response.parse() + assert_matches_type(AsyncCursorPage[ExternalBankAccountListResponse], external_bank_account, path=["response"]) diff --git a/tests/api_resources/test_financial_accounts.py b/tests/api_resources/test_financial_accounts.py index 14e19859..dea55707 100644 --- a/tests/api_resources/test_financial_accounts.py +++ b/tests/api_resources/test_financial_accounts.py @@ -9,6 +9,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type from lithic.types import FinancialAccount +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncSinglePage, AsyncSinglePage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -33,6 +34,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncSinglePage[FinancialAccount], financial_account, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.financial_accounts.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + financial_account = response.parse() + assert_matches_type(SyncSinglePage[FinancialAccount], financial_account, path=["response"]) + class TestAsyncFinancialAccounts: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -51,3 +59,10 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: type="ISSUING", ) assert_matches_type(AsyncSinglePage[FinancialAccount], financial_account, path=["response"]) + + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.financial_accounts.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + financial_account = response.parse() + assert_matches_type(AsyncSinglePage[FinancialAccount], financial_account, path=["response"]) diff --git a/tests/api_resources/test_payments.py b/tests/api_resources/test_payments.py index 520b69d4..40a07784 100644 --- a/tests/api_resources/test_payments.py +++ b/tests/api_resources/test_payments.py @@ -15,6 +15,7 @@ PaymentSimulateReturnResponse, PaymentSimulateReleaseResponse, ) +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -57,6 +58,20 @@ def test_method_create_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(PaymentCreateResponse, payment, path=["response"]) + @parametrize + def test_raw_response_create(self, client: Lithic) -> None: + response = client.payments.with_raw_response.create( + amount=1, + external_bank_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + method="ACH_NEXT_DAY", + method_attributes={"sec_code": "PPD"}, + type="PAYMENT", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(PaymentCreateResponse, payment, path=["response"]) + @parametrize def test_method_retrieve(self, client: Lithic) -> None: payment = client.payments.retrieve( @@ -64,6 +79,15 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(Payment, payment, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.payments.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(Payment, payment, path=["response"]) + @parametrize def test_method_list(self, client: Lithic) -> None: payment = client.payments.list() @@ -81,6 +105,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[Payment], payment, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.payments.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(SyncCursorPage[Payment], payment, path=["response"]) + @parametrize def test_method_retry(self, client: Lithic) -> None: payment = client.payments.retry( @@ -88,6 +119,15 @@ def test_method_retry(self, client: Lithic) -> None: ) assert_matches_type(PaymentRetryResponse, payment, path=["response"]) + @parametrize + def test_raw_response_retry(self, client: Lithic) -> None: + response = client.payments.with_raw_response.retry( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(PaymentRetryResponse, payment, path=["response"]) + @parametrize def test_method_simulate_release(self, client: Lithic) -> None: payment = client.payments.simulate_release( @@ -95,6 +135,15 @@ def test_method_simulate_release(self, client: Lithic) -> None: ) assert_matches_type(PaymentSimulateReleaseResponse, payment, path=["response"]) + @parametrize + def test_raw_response_simulate_release(self, client: Lithic) -> None: + response = client.payments.with_raw_response.simulate_release( + payment_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(PaymentSimulateReleaseResponse, payment, path=["response"]) + @parametrize def test_method_simulate_return(self, client: Lithic) -> None: payment = client.payments.simulate_return( @@ -110,6 +159,15 @@ def test_method_simulate_return_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(PaymentSimulateReturnResponse, payment, path=["response"]) + @parametrize + def test_raw_response_simulate_return(self, client: Lithic) -> None: + response = client.payments.with_raw_response.simulate_return( + payment_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(PaymentSimulateReturnResponse, payment, path=["response"]) + class TestAsyncPayments: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -147,6 +205,20 @@ async def test_method_create_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(PaymentCreateResponse, payment, path=["response"]) + @parametrize + async def test_raw_response_create(self, client: AsyncLithic) -> None: + response = await client.payments.with_raw_response.create( + amount=1, + external_bank_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + method="ACH_NEXT_DAY", + method_attributes={"sec_code": "PPD"}, + type="PAYMENT", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(PaymentCreateResponse, payment, path=["response"]) + @parametrize async def test_method_retrieve(self, client: AsyncLithic) -> None: payment = await client.payments.retrieve( @@ -154,6 +226,15 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(Payment, payment, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.payments.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(Payment, payment, path=["response"]) + @parametrize async def test_method_list(self, client: AsyncLithic) -> None: payment = await client.payments.list() @@ -171,6 +252,13 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(AsyncCursorPage[Payment], payment, path=["response"]) + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.payments.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(AsyncCursorPage[Payment], payment, path=["response"]) + @parametrize async def test_method_retry(self, client: AsyncLithic) -> None: payment = await client.payments.retry( @@ -178,6 +266,15 @@ async def test_method_retry(self, client: AsyncLithic) -> None: ) assert_matches_type(PaymentRetryResponse, payment, path=["response"]) + @parametrize + async def test_raw_response_retry(self, client: AsyncLithic) -> None: + response = await client.payments.with_raw_response.retry( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(PaymentRetryResponse, payment, path=["response"]) + @parametrize async def test_method_simulate_release(self, client: AsyncLithic) -> None: payment = await client.payments.simulate_release( @@ -185,6 +282,15 @@ async def test_method_simulate_release(self, client: AsyncLithic) -> None: ) assert_matches_type(PaymentSimulateReleaseResponse, payment, path=["response"]) + @parametrize + async def test_raw_response_simulate_release(self, client: AsyncLithic) -> None: + response = await client.payments.with_raw_response.simulate_release( + payment_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(PaymentSimulateReleaseResponse, payment, path=["response"]) + @parametrize async def test_method_simulate_return(self, client: AsyncLithic) -> None: payment = await client.payments.simulate_return( @@ -199,3 +305,12 @@ async def test_method_simulate_return_with_all_params(self, client: AsyncLithic) return_reason_code="string", ) assert_matches_type(PaymentSimulateReturnResponse, payment, path=["response"]) + + @parametrize + async def test_raw_response_simulate_return(self, client: AsyncLithic) -> None: + response = await client.payments.with_raw_response.simulate_return( + payment_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(PaymentSimulateReturnResponse, payment, path=["response"]) diff --git a/tests/api_resources/test_responder_endpoints.py b/tests/api_resources/test_responder_endpoints.py index 0697b4fa..ab2c225b 100644 --- a/tests/api_resources/test_responder_endpoints.py +++ b/tests/api_resources/test_responder_endpoints.py @@ -9,6 +9,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type from lithic.types import ResponderEndpointStatus, ResponderEndpointCreateResponse +from lithic._client import Lithic, AsyncLithic base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My Lithic API Key" @@ -32,6 +33,13 @@ def test_method_create_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(ResponderEndpointCreateResponse, responder_endpoint, path=["response"]) + @parametrize + def test_raw_response_create(self, client: Lithic) -> None: + response = client.responder_endpoints.with_raw_response.create() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + responder_endpoint = response.parse() + assert_matches_type(ResponderEndpointCreateResponse, responder_endpoint, path=["response"]) + @pytest.mark.skip(reason="Prism errors when accept header set but no request body is defined") @parametrize def test_method_delete(self, client: Lithic) -> None: @@ -40,6 +48,16 @@ def test_method_delete(self, client: Lithic) -> None: ) assert responder_endpoint is None + @pytest.mark.skip(reason="Prism errors when accept header set but no request body is defined") + @parametrize + def test_raw_response_delete(self, client: Lithic) -> None: + response = client.responder_endpoints.with_raw_response.delete( + type="AUTH_STREAM_ACCESS", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + responder_endpoint = response.parse() + assert responder_endpoint is None + @parametrize def test_method_check_status(self, client: Lithic) -> None: responder_endpoint = client.responder_endpoints.check_status( @@ -47,6 +65,15 @@ def test_method_check_status(self, client: Lithic) -> None: ) assert_matches_type(ResponderEndpointStatus, responder_endpoint, path=["response"]) + @parametrize + def test_raw_response_check_status(self, client: Lithic) -> None: + response = client.responder_endpoints.with_raw_response.check_status( + type="AUTH_STREAM_ACCESS", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + responder_endpoint = response.parse() + assert_matches_type(ResponderEndpointStatus, responder_endpoint, path=["response"]) + class TestAsyncResponderEndpoints: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -66,6 +93,13 @@ async def test_method_create_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(ResponderEndpointCreateResponse, responder_endpoint, path=["response"]) + @parametrize + async def test_raw_response_create(self, client: AsyncLithic) -> None: + response = await client.responder_endpoints.with_raw_response.create() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + responder_endpoint = response.parse() + assert_matches_type(ResponderEndpointCreateResponse, responder_endpoint, path=["response"]) + @pytest.mark.skip(reason="Prism errors when accept header set but no request body is defined") @parametrize async def test_method_delete(self, client: AsyncLithic) -> None: @@ -74,9 +108,28 @@ async def test_method_delete(self, client: AsyncLithic) -> None: ) assert responder_endpoint is None + @pytest.mark.skip(reason="Prism errors when accept header set but no request body is defined") + @parametrize + async def test_raw_response_delete(self, client: AsyncLithic) -> None: + response = await client.responder_endpoints.with_raw_response.delete( + type="AUTH_STREAM_ACCESS", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + responder_endpoint = response.parse() + assert responder_endpoint is None + @parametrize async def test_method_check_status(self, client: AsyncLithic) -> None: responder_endpoint = await client.responder_endpoints.check_status( type="AUTH_STREAM_ACCESS", ) assert_matches_type(ResponderEndpointStatus, responder_endpoint, path=["response"]) + + @parametrize + async def test_raw_response_check_status(self, client: AsyncLithic) -> None: + response = await client.responder_endpoints.with_raw_response.check_status( + type="AUTH_STREAM_ACCESS", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + responder_endpoint = response.parse() + assert_matches_type(ResponderEndpointStatus, responder_endpoint, path=["response"]) diff --git a/tests/api_resources/test_tokenization_decisioning.py b/tests/api_resources/test_tokenization_decisioning.py index 74fdb60e..49b97c49 100644 --- a/tests/api_resources/test_tokenization_decisioning.py +++ b/tests/api_resources/test_tokenization_decisioning.py @@ -9,6 +9,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type from lithic.types import TokenizationSecret, TokenizationDecisioningRotateSecretResponse +from lithic._client import Lithic, AsyncLithic base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My Lithic API Key" @@ -24,11 +25,25 @@ def test_method_retrieve_secret(self, client: Lithic) -> None: tokenization_decisioning = client.tokenization_decisioning.retrieve_secret() assert_matches_type(TokenizationSecret, tokenization_decisioning, path=["response"]) + @parametrize + def test_raw_response_retrieve_secret(self, client: Lithic) -> None: + response = client.tokenization_decisioning.with_raw_response.retrieve_secret() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + tokenization_decisioning = response.parse() + assert_matches_type(TokenizationSecret, tokenization_decisioning, path=["response"]) + @parametrize def test_method_rotate_secret(self, client: Lithic) -> None: tokenization_decisioning = client.tokenization_decisioning.rotate_secret() assert_matches_type(TokenizationDecisioningRotateSecretResponse, tokenization_decisioning, path=["response"]) + @parametrize + def test_raw_response_rotate_secret(self, client: Lithic) -> None: + response = client.tokenization_decisioning.with_raw_response.rotate_secret() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + tokenization_decisioning = response.parse() + assert_matches_type(TokenizationDecisioningRotateSecretResponse, tokenization_decisioning, path=["response"]) + class TestAsyncTokenizationDecisioning: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -40,7 +55,21 @@ async def test_method_retrieve_secret(self, client: AsyncLithic) -> None: tokenization_decisioning = await client.tokenization_decisioning.retrieve_secret() assert_matches_type(TokenizationSecret, tokenization_decisioning, path=["response"]) + @parametrize + async def test_raw_response_retrieve_secret(self, client: AsyncLithic) -> None: + response = await client.tokenization_decisioning.with_raw_response.retrieve_secret() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + tokenization_decisioning = response.parse() + assert_matches_type(TokenizationSecret, tokenization_decisioning, path=["response"]) + @parametrize async def test_method_rotate_secret(self, client: AsyncLithic) -> None: tokenization_decisioning = await client.tokenization_decisioning.rotate_secret() assert_matches_type(TokenizationDecisioningRotateSecretResponse, tokenization_decisioning, path=["response"]) + + @parametrize + async def test_raw_response_rotate_secret(self, client: AsyncLithic) -> None: + response = await client.tokenization_decisioning.with_raw_response.rotate_secret() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + tokenization_decisioning = response.parse() + assert_matches_type(TokenizationDecisioningRotateSecretResponse, tokenization_decisioning, path=["response"]) diff --git a/tests/api_resources/test_tokenizations.py b/tests/api_resources/test_tokenizations.py index f6919ed2..a0053bbe 100644 --- a/tests/api_resources/test_tokenizations.py +++ b/tests/api_resources/test_tokenizations.py @@ -9,6 +9,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type from lithic.types import TokenizationSimulateResponse +from lithic._client import Lithic, AsyncLithic base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My Lithic API Key" @@ -42,6 +43,18 @@ def test_method_simulate_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(TokenizationSimulateResponse, tokenization, path=["response"]) + @parametrize + def test_raw_response_simulate(self, client: Lithic) -> None: + response = client.tokenizations.with_raw_response.simulate( + cvv="776", + expiration_date="08/29", + pan="4111111289144142", + tokenization_source="APPLE_PAY", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + tokenization = response.parse() + assert_matches_type(TokenizationSimulateResponse, tokenization, path=["response"]) + class TestAsyncTokenizations: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -70,3 +83,15 @@ async def test_method_simulate_with_all_params(self, client: AsyncLithic) -> Non wallet_recommended_decision="APPROVED", ) assert_matches_type(TokenizationSimulateResponse, tokenization, path=["response"]) + + @parametrize + async def test_raw_response_simulate(self, client: AsyncLithic) -> None: + response = await client.tokenizations.with_raw_response.simulate( + cvv="776", + expiration_date="08/29", + pan="4111111289144142", + tokenization_source="APPLE_PAY", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + tokenization = response.parse() + assert_matches_type(TokenizationSimulateResponse, tokenization, path=["response"]) diff --git a/tests/api_resources/test_top_level.py b/tests/api_resources/test_top_level.py index c1f6e6ee..790a80f3 100644 --- a/tests/api_resources/test_top_level.py +++ b/tests/api_resources/test_top_level.py @@ -9,6 +9,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type from lithic.types import APIStatus +from lithic._client import Lithic, AsyncLithic base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My Lithic API Key" @@ -24,6 +25,13 @@ def test_method_api_status(self, client: Lithic) -> None: top_level = client.api_status() assert_matches_type(APIStatus, top_level, path=["response"]) + @parametrize + def test_raw_response_api_status(self, client: Lithic) -> None: + response = client.with_raw_response.api_status() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + top_level = response.parse() + assert_matches_type(APIStatus, top_level, path=["response"]) + class TestAsyncTopLevel: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -34,3 +42,10 @@ class TestAsyncTopLevel: async def test_method_api_status(self, client: AsyncLithic) -> None: top_level = await client.api_status() assert_matches_type(APIStatus, top_level, path=["response"]) + + @parametrize + async def test_raw_response_api_status(self, client: AsyncLithic) -> None: + response = await client.with_raw_response.api_status() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + top_level = response.parse() + assert_matches_type(APIStatus, top_level, path=["response"]) diff --git a/tests/api_resources/test_transactions.py b/tests/api_resources/test_transactions.py index 232f17e3..0037d830 100644 --- a/tests/api_resources/test_transactions.py +++ b/tests/api_resources/test_transactions.py @@ -19,6 +19,7 @@ TransactionSimulateCreditAuthorizationResponse, ) from lithic._utils import parse_datetime +from lithic._client import Lithic, AsyncLithic from lithic.pagination import SyncCursorPage, AsyncCursorPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -37,6 +38,15 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(Transaction, transaction, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.transactions.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(Transaction, transaction, path=["response"]) + @parametrize def test_method_list(self, client: Lithic) -> None: transaction = client.transactions.list() @@ -56,6 +66,13 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(SyncCursorPage[Transaction], transaction, path=["response"]) + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.transactions.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(SyncCursorPage[Transaction], transaction, path=["response"]) + @parametrize def test_method_simulate_authorization(self, client: Lithic) -> None: transaction = client.transactions.simulate_authorization( @@ -80,6 +97,17 @@ def test_method_simulate_authorization_with_all_params(self, client: Lithic) -> ) assert_matches_type(TransactionSimulateAuthorizationResponse, transaction, path=["response"]) + @parametrize + def test_raw_response_simulate_authorization(self, client: Lithic) -> None: + response = client.transactions.with_raw_response.simulate_authorization( + amount=3831, + descriptor="COFFEE SHOP", + pan="4111111289144142", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateAuthorizationResponse, transaction, path=["response"]) + @parametrize def test_method_simulate_authorization_advice(self, client: Lithic) -> None: transaction = client.transactions.simulate_authorization_advice( @@ -88,6 +116,16 @@ def test_method_simulate_authorization_advice(self, client: Lithic) -> None: ) assert_matches_type(TransactionSimulateAuthorizationAdviceResponse, transaction, path=["response"]) + @parametrize + def test_raw_response_simulate_authorization_advice(self, client: Lithic) -> None: + response = client.transactions.with_raw_response.simulate_authorization_advice( + token="fabd829d-7f7b-4432-a8f2-07ea4889aaac", + amount=3831, + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateAuthorizationAdviceResponse, transaction, path=["response"]) + @parametrize def test_method_simulate_clearing(self, client: Lithic) -> None: transaction = client.transactions.simulate_clearing( @@ -103,6 +141,15 @@ def test_method_simulate_clearing_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(TransactionSimulateClearingResponse, transaction, path=["response"]) + @parametrize + def test_raw_response_simulate_clearing(self, client: Lithic) -> None: + response = client.transactions.with_raw_response.simulate_clearing( + token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateClearingResponse, transaction, path=["response"]) + @parametrize def test_method_simulate_credit_authorization(self, client: Lithic) -> None: transaction = client.transactions.simulate_credit_authorization( @@ -123,6 +170,17 @@ def test_method_simulate_credit_authorization_with_all_params(self, client: Lith ) assert_matches_type(TransactionSimulateCreditAuthorizationResponse, transaction, path=["response"]) + @parametrize + def test_raw_response_simulate_credit_authorization(self, client: Lithic) -> None: + response = client.transactions.with_raw_response.simulate_credit_authorization( + amount=3831, + descriptor="COFFEE SHOP", + pan="4111111289144142", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateCreditAuthorizationResponse, transaction, path=["response"]) + @parametrize def test_method_simulate_return(self, client: Lithic) -> None: transaction = client.transactions.simulate_return( @@ -132,6 +190,17 @@ def test_method_simulate_return(self, client: Lithic) -> None: ) assert_matches_type(TransactionSimulateReturnResponse, transaction, path=["response"]) + @parametrize + def test_raw_response_simulate_return(self, client: Lithic) -> None: + response = client.transactions.with_raw_response.simulate_return( + amount=3831, + descriptor="COFFEE SHOP", + pan="4111111289144142", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateReturnResponse, transaction, path=["response"]) + @parametrize def test_method_simulate_return_reversal(self, client: Lithic) -> None: transaction = client.transactions.simulate_return_reversal( @@ -139,6 +208,15 @@ def test_method_simulate_return_reversal(self, client: Lithic) -> None: ) assert_matches_type(TransactionSimulateReturnReversalResponse, transaction, path=["response"]) + @parametrize + def test_raw_response_simulate_return_reversal(self, client: Lithic) -> None: + response = client.transactions.with_raw_response.simulate_return_reversal( + token="fabd829d-7f7b-4432-a8f2-07ea4889aaac", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateReturnReversalResponse, transaction, path=["response"]) + @parametrize def test_method_simulate_void(self, client: Lithic) -> None: transaction = client.transactions.simulate_void( @@ -155,6 +233,15 @@ def test_method_simulate_void_with_all_params(self, client: Lithic) -> None: ) assert_matches_type(TransactionSimulateVoidResponse, transaction, path=["response"]) + @parametrize + def test_raw_response_simulate_void(self, client: Lithic) -> None: + response = client.transactions.with_raw_response.simulate_void( + token="fabd829d-7f7b-4432-a8f2-07ea4889aaac", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateVoidResponse, transaction, path=["response"]) + class TestAsyncTransactions: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -168,6 +255,15 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(Transaction, transaction, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.transactions.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(Transaction, transaction, path=["response"]) + @parametrize async def test_method_list(self, client: AsyncLithic) -> None: transaction = await client.transactions.list() @@ -187,6 +283,13 @@ async def test_method_list_with_all_params(self, client: AsyncLithic) -> None: ) assert_matches_type(AsyncCursorPage[Transaction], transaction, path=["response"]) + @parametrize + async def test_raw_response_list(self, client: AsyncLithic) -> None: + response = await client.transactions.with_raw_response.list() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(AsyncCursorPage[Transaction], transaction, path=["response"]) + @parametrize async def test_method_simulate_authorization(self, client: AsyncLithic) -> None: transaction = await client.transactions.simulate_authorization( @@ -211,6 +314,17 @@ async def test_method_simulate_authorization_with_all_params(self, client: Async ) assert_matches_type(TransactionSimulateAuthorizationResponse, transaction, path=["response"]) + @parametrize + async def test_raw_response_simulate_authorization(self, client: AsyncLithic) -> None: + response = await client.transactions.with_raw_response.simulate_authorization( + amount=3831, + descriptor="COFFEE SHOP", + pan="4111111289144142", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateAuthorizationResponse, transaction, path=["response"]) + @parametrize async def test_method_simulate_authorization_advice(self, client: AsyncLithic) -> None: transaction = await client.transactions.simulate_authorization_advice( @@ -219,6 +333,16 @@ async def test_method_simulate_authorization_advice(self, client: AsyncLithic) - ) assert_matches_type(TransactionSimulateAuthorizationAdviceResponse, transaction, path=["response"]) + @parametrize + async def test_raw_response_simulate_authorization_advice(self, client: AsyncLithic) -> None: + response = await client.transactions.with_raw_response.simulate_authorization_advice( + token="fabd829d-7f7b-4432-a8f2-07ea4889aaac", + amount=3831, + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateAuthorizationAdviceResponse, transaction, path=["response"]) + @parametrize async def test_method_simulate_clearing(self, client: AsyncLithic) -> None: transaction = await client.transactions.simulate_clearing( @@ -234,6 +358,15 @@ async def test_method_simulate_clearing_with_all_params(self, client: AsyncLithi ) assert_matches_type(TransactionSimulateClearingResponse, transaction, path=["response"]) + @parametrize + async def test_raw_response_simulate_clearing(self, client: AsyncLithic) -> None: + response = await client.transactions.with_raw_response.simulate_clearing( + token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateClearingResponse, transaction, path=["response"]) + @parametrize async def test_method_simulate_credit_authorization(self, client: AsyncLithic) -> None: transaction = await client.transactions.simulate_credit_authorization( @@ -254,6 +387,17 @@ async def test_method_simulate_credit_authorization_with_all_params(self, client ) assert_matches_type(TransactionSimulateCreditAuthorizationResponse, transaction, path=["response"]) + @parametrize + async def test_raw_response_simulate_credit_authorization(self, client: AsyncLithic) -> None: + response = await client.transactions.with_raw_response.simulate_credit_authorization( + amount=3831, + descriptor="COFFEE SHOP", + pan="4111111289144142", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateCreditAuthorizationResponse, transaction, path=["response"]) + @parametrize async def test_method_simulate_return(self, client: AsyncLithic) -> None: transaction = await client.transactions.simulate_return( @@ -263,6 +407,17 @@ async def test_method_simulate_return(self, client: AsyncLithic) -> None: ) assert_matches_type(TransactionSimulateReturnResponse, transaction, path=["response"]) + @parametrize + async def test_raw_response_simulate_return(self, client: AsyncLithic) -> None: + response = await client.transactions.with_raw_response.simulate_return( + amount=3831, + descriptor="COFFEE SHOP", + pan="4111111289144142", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateReturnResponse, transaction, path=["response"]) + @parametrize async def test_method_simulate_return_reversal(self, client: AsyncLithic) -> None: transaction = await client.transactions.simulate_return_reversal( @@ -270,6 +425,15 @@ async def test_method_simulate_return_reversal(self, client: AsyncLithic) -> Non ) assert_matches_type(TransactionSimulateReturnReversalResponse, transaction, path=["response"]) + @parametrize + async def test_raw_response_simulate_return_reversal(self, client: AsyncLithic) -> None: + response = await client.transactions.with_raw_response.simulate_return_reversal( + token="fabd829d-7f7b-4432-a8f2-07ea4889aaac", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateReturnReversalResponse, transaction, path=["response"]) + @parametrize async def test_method_simulate_void(self, client: AsyncLithic) -> None: transaction = await client.transactions.simulate_void( @@ -285,3 +449,12 @@ async def test_method_simulate_void_with_all_params(self, client: AsyncLithic) - type="AUTHORIZATION_EXPIRY", ) assert_matches_type(TransactionSimulateVoidResponse, transaction, path=["response"]) + + @parametrize + async def test_raw_response_simulate_void(self, client: AsyncLithic) -> None: + response = await client.transactions.with_raw_response.simulate_void( + token="fabd829d-7f7b-4432-a8f2-07ea4889aaac", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + transaction = response.parse() + assert_matches_type(TransactionSimulateVoidResponse, transaction, path=["response"]) diff --git a/tests/api_resources/test_webhooks.py b/tests/api_resources/test_webhooks.py index 40e8f89d..0d49df88 100644 --- a/tests/api_resources/test_webhooks.py +++ b/tests/api_resources/test_webhooks.py @@ -11,6 +11,7 @@ import time_machine from lithic import Lithic, AsyncLithic +from lithic._client import Lithic, AsyncLithic base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My Lithic API Key" diff --git a/tests/api_resources/three_ds/test_authentication.py b/tests/api_resources/three_ds/test_authentication.py index 683e9ccc..bf3313ff 100644 --- a/tests/api_resources/three_ds/test_authentication.py +++ b/tests/api_resources/three_ds/test_authentication.py @@ -8,6 +8,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type +from lithic._client import Lithic, AsyncLithic from lithic.types.three_ds import ( AuthenticationRetrieveResponse, AuthenticationSimulateResponse, @@ -29,6 +30,15 @@ def test_method_retrieve(self, client: Lithic) -> None: ) assert_matches_type(AuthenticationRetrieveResponse, authentication, path=["response"]) + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.three_ds.authentication.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + authentication = response.parse() + assert_matches_type(AuthenticationRetrieveResponse, authentication, path=["response"]) + @parametrize def test_method_simulate(self, client: Lithic) -> None: authentication = client.three_ds.authentication.simulate( @@ -46,6 +56,25 @@ def test_method_simulate(self, client: Lithic) -> None: ) assert_matches_type(AuthenticationSimulateResponse, authentication, path=["response"]) + @parametrize + def test_raw_response_simulate(self, client: Lithic) -> None: + response = client.three_ds.authentication.with_raw_response.simulate( + merchant={ + "country": "USA", + "mcc": "5812", + "id": "OODKZAPJVN4YS7O", + "name": "COFFEE SHOP", + }, + pan="4111111289144142", + transaction={ + "amount": 0, + "currency": "GBP", + }, + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + authentication = response.parse() + assert_matches_type(AuthenticationSimulateResponse, authentication, path=["response"]) + class TestAsyncAuthentication: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -59,6 +88,15 @@ async def test_method_retrieve(self, client: AsyncLithic) -> None: ) assert_matches_type(AuthenticationRetrieveResponse, authentication, path=["response"]) + @parametrize + async def test_raw_response_retrieve(self, client: AsyncLithic) -> None: + response = await client.three_ds.authentication.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + authentication = response.parse() + assert_matches_type(AuthenticationRetrieveResponse, authentication, path=["response"]) + @parametrize async def test_method_simulate(self, client: AsyncLithic) -> None: authentication = await client.three_ds.authentication.simulate( @@ -75,3 +113,22 @@ async def test_method_simulate(self, client: AsyncLithic) -> None: }, ) assert_matches_type(AuthenticationSimulateResponse, authentication, path=["response"]) + + @parametrize + async def test_raw_response_simulate(self, client: AsyncLithic) -> None: + response = await client.three_ds.authentication.with_raw_response.simulate( + merchant={ + "country": "USA", + "mcc": "5812", + "id": "OODKZAPJVN4YS7O", + "name": "COFFEE SHOP", + }, + pan="4111111289144142", + transaction={ + "amount": 0, + "currency": "GBP", + }, + ) + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + authentication = response.parse() + assert_matches_type(AuthenticationSimulateResponse, authentication, path=["response"]) diff --git a/tests/api_resources/three_ds/test_decisioning.py b/tests/api_resources/three_ds/test_decisioning.py index 570948aa..9c13c863 100644 --- a/tests/api_resources/three_ds/test_decisioning.py +++ b/tests/api_resources/three_ds/test_decisioning.py @@ -8,6 +8,7 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type +from lithic._client import Lithic, AsyncLithic from lithic.types.three_ds import DecisioningRetrieveSecretResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -24,11 +25,25 @@ def test_method_retrieve_secret(self, client: Lithic) -> None: decisioning = client.three_ds.decisioning.retrieve_secret() assert_matches_type(DecisioningRetrieveSecretResponse, decisioning, path=["response"]) + @parametrize + def test_raw_response_retrieve_secret(self, client: Lithic) -> None: + response = client.three_ds.decisioning.with_raw_response.retrieve_secret() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + decisioning = response.parse() + assert_matches_type(DecisioningRetrieveSecretResponse, decisioning, path=["response"]) + @parametrize def test_method_rotate_secret(self, client: Lithic) -> None: decisioning = client.three_ds.decisioning.rotate_secret() assert decisioning is None + @parametrize + def test_raw_response_rotate_secret(self, client: Lithic) -> None: + response = client.three_ds.decisioning.with_raw_response.rotate_secret() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + decisioning = response.parse() + assert decisioning is None + class TestAsyncDecisioning: strict_client = AsyncLithic(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -40,7 +55,21 @@ async def test_method_retrieve_secret(self, client: AsyncLithic) -> None: decisioning = await client.three_ds.decisioning.retrieve_secret() assert_matches_type(DecisioningRetrieveSecretResponse, decisioning, path=["response"]) + @parametrize + async def test_raw_response_retrieve_secret(self, client: AsyncLithic) -> None: + response = await client.three_ds.decisioning.with_raw_response.retrieve_secret() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + decisioning = response.parse() + assert_matches_type(DecisioningRetrieveSecretResponse, decisioning, path=["response"]) + @parametrize async def test_method_rotate_secret(self, client: AsyncLithic) -> None: decisioning = await client.three_ds.decisioning.rotate_secret() assert decisioning is None + + @parametrize + async def test_raw_response_rotate_secret(self, client: AsyncLithic) -> None: + response = await client.three_ds.decisioning.with_raw_response.rotate_secret() + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + decisioning = response.parse() + assert decisioning is None diff --git a/tests/test_client.py b/tests/test_client.py index 458af147..fe3a5c07 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -15,6 +15,7 @@ from pydantic import ValidationError from lithic import Lithic, AsyncLithic, APIResponseValidationError +from lithic._client import Lithic, AsyncLithic from lithic._models import BaseModel, FinalRequestOptions from lithic._exceptions import APIResponseValidationError from lithic._base_client import ( @@ -28,7 +29,7 @@ api_key = "My Lithic API Key" -def _get_params(client: BaseClient[Any]) -> dict[str, str]: +def _get_params(client: BaseClient[Any, Any]) -> dict[str, str]: request = client._build_request(FinalRequestOptions(method="get", url="/foo")) url = httpx.URL(request.url) return dict(url.params) @@ -39,12 +40,23 @@ class TestLithic: @pytest.mark.respx(base_url=base_url) def test_raw_response(self, respx_mock: MockRouter) -> None: - respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + respx_mock.post("/foo").mock(return_value=httpx.Response(200, json='{"foo": "bar"}')) response = self.client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) - assert response.json() == {"foo": "bar"} + assert response.json() == '{"foo": "bar"}' + + @pytest.mark.respx(base_url=base_url) + def test_raw_response_for_binary(self, respx_mock: MockRouter) -> None: + respx_mock.post("/foo").mock( + return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') + ) + + response = self.client.post("/foo", cast_to=httpx.Response) + assert response.status_code == 200 + assert isinstance(response, httpx.Response) + assert response.json() == '{"foo": "bar"}' def test_copy(self) -> None: copied = self.client.copy() @@ -666,12 +678,24 @@ class TestAsyncLithic: @pytest.mark.respx(base_url=base_url) @pytest.mark.asyncio async def test_raw_response(self, respx_mock: MockRouter) -> None: - respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + respx_mock.post("/foo").mock(return_value=httpx.Response(200, json='{"foo": "bar"}')) + + response = await self.client.post("/foo", cast_to=httpx.Response) + assert response.status_code == 200 + assert isinstance(response, httpx.Response) + assert response.json() == '{"foo": "bar"}' + + @pytest.mark.respx(base_url=base_url) + @pytest.mark.asyncio + async def test_raw_response_for_binary(self, respx_mock: MockRouter) -> None: + respx_mock.post("/foo").mock( + return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') + ) response = await self.client.post("/foo", cast_to=httpx.Response) assert response.status_code == 200 assert isinstance(response, httpx.Response) - assert response.json() == {"foo": "bar"} + assert response.json() == '{"foo": "bar"}' def test_copy(self) -> None: copied = self.client.copy() diff --git a/tests/test_qs.py b/tests/test_qs.py index 7862bed8..7b9609fc 100644 --- a/tests/test_qs.py +++ b/tests/test_qs.py @@ -61,6 +61,18 @@ def test_array_repeat() -> None: assert unquote(stringify({"in": ["foo", {"b": {"c": ["d", "e"]}}]})) == "in=foo&in[b][c]=d&in[b][c]=e" +@pytest.mark.parametrize("method", ["class", "function"]) +def test_array_brackets(method: str) -> None: + if method == "class": + serialise = Querystring(array_format="brackets").stringify + else: + serialise = partial(stringify, array_format="brackets") + + assert unquote(serialise({"in": ["foo", "bar"]})) == "in[]=foo&in[]=bar" + assert unquote(serialise({"a": {"b": [True, False]}})) == "a[b][]=true&a[b][]=false" + assert unquote(serialise({"a": {"b": [True, False, None, True]}})) == "a[b][]=true&a[b][]=false&a[b][]=true" + + def test_unknown_array_format() -> None: with pytest.raises(NotImplementedError, match="Unknown array_format value: foo, choose from comma, repeat"): stringify({"a": ["foo", "bar"]}, array_format=cast(Any, "foo")) diff --git a/tests/test_transform.py b/tests/test_transform.py index c657222b..2de7921f 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -1,10 +1,13 @@ from __future__ import annotations -from typing import List, Union, Optional +from typing import Any, List, Union, Optional from datetime import date, datetime from typing_extensions import Required, Annotated, TypedDict +import pytest + from lithic._utils import PropertyInfo, transform, parse_datetime +from lithic._models import BaseModel class Foo1(TypedDict): @@ -186,3 +189,44 @@ class DateDictWithRequiredAlias(TypedDict, total=False): def test_datetime_with_alias() -> None: assert transform({"required_prop": None}, DateDictWithRequiredAlias) == {"prop": None} # type: ignore[comparison-overlap] assert transform({"required_prop": date.fromisoformat("2023-02-23")}, DateDictWithRequiredAlias) == {"prop": "2023-02-23"} # type: ignore[comparison-overlap] + + +class MyModel(BaseModel): + foo: str + + +def test_pydantic_model_to_dictionary() -> None: + assert transform(MyModel(foo="hi!"), Any) == {"foo": "hi!"} + assert transform(MyModel.construct(foo="hi!"), Any) == {"foo": "hi!"} + + +def test_pydantic_empty_model() -> None: + assert transform(MyModel.construct(), Any) == {} + + +def test_pydantic_unknown_field() -> None: + assert transform(MyModel.construct(my_untyped_field=True), Any) == {"my_untyped_field": True} + + +def test_pydantic_mismatched_types() -> None: + model = MyModel.construct(foo=True) + with pytest.warns(UserWarning): + params = transform(model, Any) + assert params == {"foo": True} + + +def test_pydantic_mismatched_object_type() -> None: + model = MyModel.construct(foo=MyModel.construct(hello="world")) + with pytest.warns(UserWarning): + params = transform(model, Any) + assert params == {"foo": {"hello": "world"}} + + +class ModelNestedObjects(BaseModel): + nested: MyModel + + +def test_pydantic_nested_objects() -> None: + model = ModelNestedObjects.construct(nested={"foo": "stainless"}) + assert isinstance(model.nested, MyModel) + assert transform(model, Any) == {"nested": {"foo": "stainless"}}