Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.22.0"
".": "0.22.1"
}
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Changelog

## 0.22.1 (2025-12-16)

Full Changelog: [v0.22.0...v0.22.1](https://github.com/perplexityai/perplexity-py/compare/v0.22.0...v0.22.1)

### Bug Fixes

* **types:** allow pyright to infer TypedDict types within SequenceNotStr ([1dae6e5](https://github.com/perplexityai/perplexity-py/commit/1dae6e56a918d3ac6cbc38accd3058c169199515))


### Chores

* add missing docstrings ([be56ae3](https://github.com/perplexityai/perplexity-py/commit/be56ae34c5342b345e53b706c006f6a873e1db74))
* **internal:** add missing files argument to base client ([a2599a9](https://github.com/perplexityai/perplexity-py/commit/a2599a9261bf65ee59f611918b05eee8b7c55ead))
* speedup initial import ([2e54d11](https://github.com/perplexityai/perplexity-py/commit/2e54d1119537403fe72903a25cba1ef75fcb274f))

## 0.22.0 (2025-12-05)

Full Changelog: [v0.21.0...v0.22.0](https://github.com/perplexityai/perplexity-py/compare/v0.21.0...v0.22.0)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "perplexityai"
version = "0.22.0"
version = "0.22.1"
description = "The official Python library for the perplexity API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
10 changes: 8 additions & 2 deletions src/perplexity/_base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1247,9 +1247,12 @@ def patch(
*,
cast_to: Type[ResponseT],
body: Body | None = None,
files: RequestFiles | None = None,
options: RequestOptions = {},
) -> ResponseT:
opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options)
opts = FinalRequestOptions.construct(
method="patch", url=path, json_data=body, files=to_httpx_files(files), **options
)
return self.request(cast_to, opts)

def put(
Expand Down Expand Up @@ -1767,9 +1770,12 @@ async def patch(
*,
cast_to: Type[ResponseT],
body: Body | None = None,
files: RequestFiles | None = None,
options: RequestOptions = {},
) -> ResponseT:
opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options)
opts = FinalRequestOptions.construct(
method="patch", url=path, json_data=body, files=to_httpx_files(files), **options
)
return await self.request(cast_to, opts)

async def put(
Expand Down
180 changes: 142 additions & 38 deletions src/perplexity/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import annotations

import os
from typing import Any, Mapping
from typing import TYPE_CHECKING, Any, Mapping
from typing_extensions import Self, override

import httpx
Expand All @@ -20,17 +20,21 @@
not_given,
)
from ._utils import is_given, get_async_library
from ._compat import cached_property
from ._version import __version__
from .resources import search
from ._streaming import Stream as Stream, AsyncStream as AsyncStream
from ._exceptions import APIStatusError, PerplexityError
from ._base_client import (
DEFAULT_MAX_RETRIES,
SyncAPIClient,
AsyncAPIClient,
)
from .resources.chat import chat
from .resources.async_ import async_

if TYPE_CHECKING:
from .resources import chat, async_, search
from .resources.search import SearchResource, AsyncSearchResource
from .resources.chat.chat import ChatResource, AsyncChatResource
from .resources.async_.async_ import AsyncResource, AsyncAsyncResource

__all__ = [
"Timeout",
Expand All @@ -45,12 +49,6 @@


class Perplexity(SyncAPIClient):
chat: chat.ChatResource
search: search.SearchResource
async_: async_.AsyncResource
with_raw_response: PerplexityWithRawResponse
with_streaming_response: PerplexityWithStreamedResponse

# client options
api_key: str

Expand Down Expand Up @@ -107,11 +105,31 @@ def __init__(

self._default_stream_cls = Stream

self.chat = chat.ChatResource(self)
self.search = search.SearchResource(self)
self.async_ = async_.AsyncResource(self)
self.with_raw_response = PerplexityWithRawResponse(self)
self.with_streaming_response = PerplexityWithStreamedResponse(self)
@cached_property
def chat(self) -> ChatResource:
from .resources.chat import ChatResource

return ChatResource(self)

@cached_property
def search(self) -> SearchResource:
from .resources.search import SearchResource

return SearchResource(self)

@cached_property
def async_(self) -> AsyncResource:
from .resources.async_ import AsyncResource

return AsyncResource(self)

@cached_property
def with_raw_response(self) -> PerplexityWithRawResponse:
return PerplexityWithRawResponse(self)

@cached_property
def with_streaming_response(self) -> PerplexityWithStreamedResponse:
return PerplexityWithStreamedResponse(self)

@property
@override
Expand Down Expand Up @@ -219,12 +237,6 @@ def _make_status_error(


class AsyncPerplexity(AsyncAPIClient):
chat: chat.AsyncChatResource
search: search.AsyncSearchResource
async_: async_.AsyncAsyncResource
with_raw_response: AsyncPerplexityWithRawResponse
with_streaming_response: AsyncPerplexityWithStreamedResponse

# client options
api_key: str

Expand Down Expand Up @@ -281,11 +293,31 @@ def __init__(

self._default_stream_cls = AsyncStream

self.chat = chat.AsyncChatResource(self)
self.search = search.AsyncSearchResource(self)
self.async_ = async_.AsyncAsyncResource(self)
self.with_raw_response = AsyncPerplexityWithRawResponse(self)
self.with_streaming_response = AsyncPerplexityWithStreamedResponse(self)
@cached_property
def chat(self) -> AsyncChatResource:
from .resources.chat import AsyncChatResource

return AsyncChatResource(self)

@cached_property
def search(self) -> AsyncSearchResource:
from .resources.search import AsyncSearchResource

return AsyncSearchResource(self)

@cached_property
def async_(self) -> AsyncAsyncResource:
from .resources.async_ import AsyncAsyncResource

return AsyncAsyncResource(self)

@cached_property
def with_raw_response(self) -> AsyncPerplexityWithRawResponse:
return AsyncPerplexityWithRawResponse(self)

@cached_property
def with_streaming_response(self) -> AsyncPerplexityWithStreamedResponse:
return AsyncPerplexityWithStreamedResponse(self)

@property
@override
Expand Down Expand Up @@ -393,31 +425,103 @@ def _make_status_error(


class PerplexityWithRawResponse:
_client: Perplexity

def __init__(self, client: Perplexity) -> None:
self.chat = chat.ChatResourceWithRawResponse(client.chat)
self.search = search.SearchResourceWithRawResponse(client.search)
self.async_ = async_.AsyncResourceWithRawResponse(client.async_)
self._client = client

@cached_property
def chat(self) -> chat.ChatResourceWithRawResponse:
from .resources.chat import ChatResourceWithRawResponse

return ChatResourceWithRawResponse(self._client.chat)

@cached_property
def search(self) -> search.SearchResourceWithRawResponse:
from .resources.search import SearchResourceWithRawResponse

return SearchResourceWithRawResponse(self._client.search)

@cached_property
def async_(self) -> async_.AsyncResourceWithRawResponse:
from .resources.async_ import AsyncResourceWithRawResponse

return AsyncResourceWithRawResponse(self._client.async_)


class AsyncPerplexityWithRawResponse:
_client: AsyncPerplexity

def __init__(self, client: AsyncPerplexity) -> None:
self.chat = chat.AsyncChatResourceWithRawResponse(client.chat)
self.search = search.AsyncSearchResourceWithRawResponse(client.search)
self.async_ = async_.AsyncAsyncResourceWithRawResponse(client.async_)
self._client = client

@cached_property
def chat(self) -> chat.AsyncChatResourceWithRawResponse:
from .resources.chat import AsyncChatResourceWithRawResponse

return AsyncChatResourceWithRawResponse(self._client.chat)

@cached_property
def search(self) -> search.AsyncSearchResourceWithRawResponse:
from .resources.search import AsyncSearchResourceWithRawResponse

return AsyncSearchResourceWithRawResponse(self._client.search)

@cached_property
def async_(self) -> async_.AsyncAsyncResourceWithRawResponse:
from .resources.async_ import AsyncAsyncResourceWithRawResponse

return AsyncAsyncResourceWithRawResponse(self._client.async_)


class PerplexityWithStreamedResponse:
_client: Perplexity

def __init__(self, client: Perplexity) -> None:
self.chat = chat.ChatResourceWithStreamingResponse(client.chat)
self.search = search.SearchResourceWithStreamingResponse(client.search)
self.async_ = async_.AsyncResourceWithStreamingResponse(client.async_)
self._client = client

@cached_property
def chat(self) -> chat.ChatResourceWithStreamingResponse:
from .resources.chat import ChatResourceWithStreamingResponse

return ChatResourceWithStreamingResponse(self._client.chat)

@cached_property
def search(self) -> search.SearchResourceWithStreamingResponse:
from .resources.search import SearchResourceWithStreamingResponse

return SearchResourceWithStreamingResponse(self._client.search)

@cached_property
def async_(self) -> async_.AsyncResourceWithStreamingResponse:
from .resources.async_ import AsyncResourceWithStreamingResponse

return AsyncResourceWithStreamingResponse(self._client.async_)


class AsyncPerplexityWithStreamedResponse:
_client: AsyncPerplexity

def __init__(self, client: AsyncPerplexity) -> None:
self.chat = chat.AsyncChatResourceWithStreamingResponse(client.chat)
self.search = search.AsyncSearchResourceWithStreamingResponse(client.search)
self.async_ = async_.AsyncAsyncResourceWithStreamingResponse(client.async_)
self._client = client

@cached_property
def chat(self) -> chat.AsyncChatResourceWithStreamingResponse:
from .resources.chat import AsyncChatResourceWithStreamingResponse

return AsyncChatResourceWithStreamingResponse(self._client.chat)

@cached_property
def search(self) -> search.AsyncSearchResourceWithStreamingResponse:
from .resources.search import AsyncSearchResourceWithStreamingResponse

return AsyncSearchResourceWithStreamingResponse(self._client.search)

@cached_property
def async_(self) -> async_.AsyncAsyncResourceWithStreamingResponse:
from .resources.async_ import AsyncAsyncResourceWithStreamingResponse

return AsyncAsyncResourceWithStreamingResponse(self._client.async_)


Client = Perplexity
Expand Down
5 changes: 3 additions & 2 deletions src/perplexity/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ class HttpxSendArgs(TypedDict, total=False):
if TYPE_CHECKING:
# This works because str.__contains__ does not accept object (either in typeshed or at runtime)
# https://github.com/hauntsaninja/useful_types/blob/5e9710f3875107d068e7679fd7fec9cfab0eff3b/useful_types/__init__.py#L285
#
# Note: index() and count() methods are intentionally omitted to allow pyright to properly
# infer TypedDict types when dict literals are used in lists assigned to SequenceNotStr.
class SequenceNotStr(Protocol[_T_co]):
@overload
def __getitem__(self, index: SupportsIndex, /) -> _T_co: ...
Expand All @@ -251,8 +254,6 @@ def __getitem__(self, index: slice, /) -> Sequence[_T_co]: ...
def __contains__(self, value: object, /) -> bool: ...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[_T_co]: ...
def index(self, value: Any, start: int = 0, stop: int = ..., /) -> int: ...
def count(self, value: Any, /) -> int: ...
def __reversed__(self) -> Iterator[_T_co]: ...
else:
# just point this to a normal `Sequence` at runtime to avoid having to special case
Expand Down
2 changes: 1 addition & 1 deletion src/perplexity/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "perplexity"
__version__ = "0.22.0" # x-release-please-version
__version__ = "0.22.1" # x-release-please-version
8 changes: 8 additions & 0 deletions src/perplexity/types/shared/chat_message_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,22 +111,30 @@ class ContentStructuredContentChatMessageContentVideoChunk(BaseModel):


class ReasoningStepExecutePython(BaseModel):
"""Code generation step details wrapper class"""

code: str

result: str


class ReasoningStepFetchURLContent(BaseModel):
"""Fetch url content step details wrapper class"""

contents: List[APIPublicSearchResult]


class ReasoningStepWebSearch(BaseModel):
"""Web search step details wrapper class"""

search_keywords: List[str]

search_results: List[APIPublicSearchResult]


class ReasoningStep(BaseModel):
"""Reasoning step wrapper class"""

thought: str

execute_python: Optional[ReasoningStepExecutePython] = None
Expand Down
8 changes: 8 additions & 0 deletions src/perplexity/types/shared/chat_message_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,22 +111,30 @@ class ContentStructuredContentChatMessageContentVideoChunk(BaseModel):


class ReasoningStepExecutePython(BaseModel):
"""Code generation step details wrapper class"""

code: str

result: str


class ReasoningStepFetchURLContent(BaseModel):
"""Fetch url content step details wrapper class"""

contents: List[APIPublicSearchResult]


class ReasoningStepWebSearch(BaseModel):
"""Web search step details wrapper class"""

search_keywords: List[str]

search_results: List[APIPublicSearchResult]


class ReasoningStep(BaseModel):
"""Reasoning step wrapper class"""

thought: str

execute_python: Optional[ReasoningStepExecutePython] = None
Expand Down
Loading