Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Python 3.13 support #416

Merged
merged 5 commits into from
Oct 24, 2024
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 .github/workflows/codegen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
- name: Setup Poetry.
uses: snok/install-poetry@v1
with:
version: 1.5.1
version: 1.8.3

- name: Install dependencies.
run: poetry install --no-interaction
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Setup Poetry.
uses: snok/install-poetry@v1
with:
version: 1.5.1
version: 1.8.3

- name: Install Poetry Plugin.
run: poetry self add "poetry-dynamic-versioning[plugin]"
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/ruff.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ jobs:
python-version: 3.8

- name: Run linter check.
uses: chartboost/ruff-action@v1
uses: astral-sh/ruff-action@v1
with:
version: 0.1.2
version: 0.7.0

- name: Run code style check.
uses: chartboost/ruff-action@v1
uses: astral-sh/ruff-action@v1
with:
version: 0.1.2
args: format --check
version: 0.7.0
args: "format --check"
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
strategy:
matrix:
os: [ macos-latest, ubuntu-latest, windows-latest ]
python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]
python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12", "3.13" ]

runs-on: ${{matrix.os}}

Expand Down Expand Up @@ -43,7 +43,7 @@ jobs:
- name: Setup Poetry.
uses: snok/install-poetry@v1
with:
version: 1.5.1
version: 1.8.3

- name: Install dependencies.
run: poetry install --without docs
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/update_lexicons.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Setup Poetry.
uses: snok/install-poetry@v1
with:
version: 1.5.1
version: 1.8.3

- name: Install dependencies.
run: poetry install --no-interaction
Expand Down
2 changes: 1 addition & 1 deletion examples/advanced_usage/notifications_callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ async def on_notification_callback(notification: Notification) -> None:
# example: "Got new notification! Type: like; from: did:plc:hlorqa2iqfooopmyzvb4byaz"

async def listen_for_notifications(
on_notification: t.Callable[[Notification], t.Coroutine[t.Any, t.Any, None]]
on_notification: t.Callable[[Notification], t.Coroutine[t.Any, t.Any, None]],
) -> None:
print('Start listening for notifications...')
while True:
Expand Down
3 changes: 2 additions & 1 deletion examples/firehose/stop_client_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ async def _stop_after_n_sec() -> None:
await client.stop()

# save ref to task to eliminate problems with GC
_ = asyncio.create_task(_stop_after_n_sec())
_stop_after_n_sec_task = asyncio.create_task(_stop_after_n_sec())

await client.start(on_message_handler)
await _stop_after_n_sec_task

print(f'Successfully stopped after {_STOP_AFTER_SECONDS} seconds!')

Expand Down
2 changes: 1 addition & 1 deletion packages/atproto_client/client/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def _handle_kwagrs(kwargs: dict) -> None:
if content_type == _CONTENT_TYPE_JSON and 'data' in kwargs and kwargs['data']:
kwargs['data'] = get_model_as_json(kwargs['data'])

if 'params' in kwargs and kwargs['params']:
if kwargs.get('params'):
kwargs['params'] = get_model_as_dict(kwargs['params'])

# pop non-request kwargs
Expand Down
21 changes: 7 additions & 14 deletions packages/atproto_client/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,30 @@
_DEFAULT_LOGING_REQUIRED_ERROR_MESSAGE = 'To perform this action, you must be logged in. Use the `login` method first.'


class ModelError(AtProtocolError):
...
class ModelError(AtProtocolError): ...


class ModelFieldNotFoundError(ModelError):
...
class ModelFieldNotFoundError(ModelError): ...


class RequestErrorBase(AtProtocolError):
def __init__(self, response: t.Optional['Response'] = None) -> None:
self.response: t.Optional['Response'] = response


class NetworkError(RequestErrorBase):
...
class NetworkError(RequestErrorBase): ...


class InvokeTimeoutError(NetworkError):
...
class InvokeTimeoutError(NetworkError): ...


class UnauthorizedError(RequestErrorBase):
...
class UnauthorizedError(RequestErrorBase): ...


class RequestException(RequestErrorBase):
...
class RequestException(RequestErrorBase): ...


class BadRequestError(RequestErrorBase):
...
class BadRequestError(RequestErrorBase): ...


class LoginRequiredError(AtProtocolError):
Expand Down
30 changes: 15 additions & 15 deletions packages/atproto_client/models/app/bsky/actor/defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ class ProfileViewDetailed(base.ModelBase):
followers_count: t.Optional[int] = None #: Followers count.
follows_count: t.Optional[int] = None #: Follows count.
indexed_at: t.Optional[str] = None #: Indexed at.
joined_via_starter_pack: t.Optional[
'models.AppBskyGraphDefs.StarterPackViewBasic'
] = None #: Joined via starter pack.
joined_via_starter_pack: t.Optional['models.AppBskyGraphDefs.StarterPackViewBasic'] = (
None #: Joined via starter pack.
)
labels: t.Optional[t.List['models.ComAtprotoLabelDefs.Label']] = None #: Labels.
pinned_post: t.Optional['models.ComAtprotoRepoStrongRef.Main'] = None #: Pinned post.
posts_count: t.Optional[int] = None #: Posts count.
Expand Down Expand Up @@ -226,9 +226,9 @@ class FeedViewPref(base.ModelBase):
feed: str #: The URI of the feed, or an identifier which describes the feed.
hide_quote_posts: t.Optional[bool] = None #: Hide quote posts in the feed.
hide_replies: t.Optional[bool] = None #: Hide replies in the feed.
hide_replies_by_like_count: t.Optional[
int
] = None #: Hide replies in the feed if they do not have this number of likes.
hide_replies_by_like_count: t.Optional[int] = (
None #: Hide replies in the feed if they do not have this number of likes.
)
hide_replies_by_unfollowed: t.Optional[bool] = True #: Hide replies in the feed if they are not by followed users.
hide_reposts: t.Optional[bool] = None #: Hide reposts in the feed.

Expand Down Expand Up @@ -270,12 +270,12 @@ class MutedWord(base.ModelBase):

targets: t.List['models.AppBskyActorDefs.MutedWordTarget'] #: The intended targets of the muted word.
value: str = Field(max_length=10000) #: The muted word itself.
actor_target: t.Optional[
t.Union[t.Literal['all'], t.Literal['exclude-following'], str]
] = 'all' #: Groups of users to apply the muted word to. If undefined, applies to all users.
expires_at: t.Optional[
str
] = None #: The date and time at which the muted word will expire and no longer be applied.
actor_target: t.Optional[t.Union[t.Literal['all'], t.Literal['exclude-following'], str]] = (
'all' #: Groups of users to apply the muted word to. If undefined, applies to all users.
)
expires_at: t.Optional[str] = (
None #: The date and time at which the muted word will expire and no longer be applied.
)
id: t.Optional[str] = None #: Id.

py_type: t.Literal['app.bsky.actor.defs#mutedWord'] = Field(
Expand Down Expand Up @@ -357,8 +357,8 @@ class Nux(base.ModelBase):
data: t.Optional[str] = Field(
default=None, max_length=3000
) #: Arbitrary data for the NUX. The structure is defined by the NUX itself. Limited to 300 characters.
expires_at: t.Optional[
str
] = None #: The date and time at which the NUX will expire and should be considered completed.
expires_at: t.Optional[str] = (
None #: The date and time at which the NUX will expire and should be considered completed.
)

py_type: t.Literal['app.bsky.actor.defs#nux'] = Field(default='app.bsky.actor.defs#nux', alias='$type', frozen=True)
6 changes: 3 additions & 3 deletions packages/atproto_client/models/app/bsky/actor/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
class Record(base.RecordModelBase):
"""Record model for :obj:`app.bsky.actor.profile`."""

avatar: t.Optional[
'BlobRef'
] = None #: Small image to be displayed next to posts from account. AKA, 'profile picture'.
avatar: t.Optional['BlobRef'] = (
None #: Small image to be displayed next to posts from account. AKA, 'profile picture'.
)
banner: t.Optional['BlobRef'] = None #: Larger horizontal image to display behind profile view.
created_at: t.Optional[str] = None #: Created at.
description: t.Optional[str] = Field(default=None, max_length=2560) #: Free-form profile description text.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class Params(base.ParamsModelBase):

cursor: t.Optional[str] = None #: Cursor.
limit: t.Optional[int] = Field(default=25, ge=1, le=100) #: Limit.
q: t.Optional[
str
] = None #: Search query string. Syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended.
q: t.Optional[str] = (
None #: Search query string. Syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended.
)
term: t.Optional[str] = None #: DEPRECATED: use 'q' instead.


Expand Down
6 changes: 3 additions & 3 deletions packages/atproto_client/models/app/bsky/feed/defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ class ReplyRef(base.ModelBase):
],
Field(discriminator='py_type'),
] #: Root.
grandparent_author: t.Optional[
'models.AppBskyActorDefs.ProfileViewBasic'
] = None #: When parent is a reply to another post, this is the author of that post.
grandparent_author: t.Optional['models.AppBskyActorDefs.ProfileViewBasic'] = (
None #: When parent is a reply to another post, this is the author of that post.
)

py_type: t.Literal['app.bsky.feed.defs#replyRef'] = Field(
default='app.bsky.feed.defs#replyRef', alias='$type', frozen=True
Expand Down
8 changes: 3 additions & 5 deletions packages/atproto_client/models/app/bsky/feed/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@ class Record(base.RecordModelBase):
created_at: str #: Created at.
did: str #: Did.
display_name: str = Field(max_length=240) #: Display name.
accepts_interactions: t.Optional[
bool
] = (
None
) #: Declaration that a feed accepts feedback interactions from a client through app.bsky.feed.sendInteractions.
accepts_interactions: t.Optional[bool] = (
None #: Declaration that a feed accepts feedback interactions from a client through app.bsky.feed.sendInteractions.
)
avatar: t.Optional['BlobRef'] = None #: Avatar.
description: t.Optional[str] = Field(default=None, max_length=3000) #: Description.
description_facets: t.Optional[t.List['models.AppBskyRichtextFacet.Main']] = None #: Description facets.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Response(base.ResponseModelBase):
"""Output data model for :obj:`app.bsky.feed.getFeedGenerator`."""

is_online: (
bool
) #: Indicates whether the feed generator service has been online recently, or else seems to be inactive.
bool #: Indicates whether the feed generator service has been online recently, or else seems to be inactive.
)
is_valid: bool #: Indicates whether the feed generator service is compatible with the record declaration.
view: 'models.AppBskyFeedDefs.GeneratorView' #: View.
6 changes: 3 additions & 3 deletions packages/atproto_client/models/app/bsky/feed/get_timeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
class Params(base.ParamsModelBase):
"""Parameters model for :obj:`app.bsky.feed.getTimeline`."""

algorithm: t.Optional[
str
] = None #: Variant 'algorithm' for timeline. Implementation-specific. NOTE: most feed flexibility has been moved to feed generator mechanism.
algorithm: t.Optional[str] = (
None #: Variant 'algorithm' for timeline. Implementation-specific. NOTE: most feed flexibility has been moved to feed generator mechanism.
)
cursor: t.Optional[str] = None #: Cursor.
limit: t.Optional[int] = Field(default=50, ge=1, le=100) #: Limit.

Expand Down
12 changes: 6 additions & 6 deletions packages/atproto_client/models/app/bsky/feed/post.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ class Record(base.RecordModelBase):
Field(default=None, discriminator='py_type'),
]
] = None #: Embed.
entities: t.Optional[
t.List['models.AppBskyFeedPost.Entity']
] = None #: DEPRECATED: replaced by app.bsky.richtext.facet.
facets: t.Optional[
t.List['models.AppBskyRichtextFacet.Main']
] = None #: Annotations of text (mentions, URLs, hashtags, etc).
entities: t.Optional[t.List['models.AppBskyFeedPost.Entity']] = (
None #: DEPRECATED: replaced by app.bsky.richtext.facet.
)
facets: t.Optional[t.List['models.AppBskyRichtextFacet.Main']] = (
None #: Annotations of text (mentions, URLs, hashtags, etc).
)
labels: t.Optional[
te.Annotated[t.Union['models.ComAtprotoLabelDefs.SelfLabels'], Field(default=None, discriminator='py_type')]
] = None #: Self-label values for this post. Effectively content warnings.
Expand Down
66 changes: 33 additions & 33 deletions packages/atproto_client/models/app/bsky/feed/search_posts.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,37 +19,37 @@ class Params(base.ParamsModelBase):
"""Parameters model for :obj:`app.bsky.feed.searchPosts`."""

q: str #: Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended.
author: t.Optional[
str
] = None #: Filter to posts by the given account. Handles are resolved to DID before query-time.
cursor: t.Optional[
str
] = None #: Optional pagination mechanism; may not necessarily allow scrolling through entire result set.
domain: t.Optional[
str
] = None #: Filter to posts with URLs (facet links or embeds) linking to the given domain (hostname). Server may apply hostname normalization.
lang: t.Optional[
str
] = None #: Filter to posts in the given language. Expected to be based on post language field, though server may override language detection.
author: t.Optional[str] = (
None #: Filter to posts by the given account. Handles are resolved to DID before query-time.
)
cursor: t.Optional[str] = (
None #: Optional pagination mechanism; may not necessarily allow scrolling through entire result set.
)
domain: t.Optional[str] = (
None #: Filter to posts with URLs (facet links or embeds) linking to the given domain (hostname). Server may apply hostname normalization.
)
lang: t.Optional[str] = (
None #: Filter to posts in the given language. Expected to be based on post language field, though server may override language detection.
)
limit: t.Optional[int] = Field(default=25, ge=1, le=100) #: Limit.
mentions: t.Optional[
str
] = None #: Filter to posts which mention the given account. Handles are resolved to DID before query-time. Only matches rich-text facet mentions.
since: t.Optional[
str
] = None #: Filter results for posts after the indicated datetime (inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYYY-MM-DD).
sort: t.Optional[
t.Union[t.Literal['top'], t.Literal['latest'], str]
] = 'latest' #: Specifies the ranking order of results.
tag: t.Optional[
t.List[str]
] = None #: Filter to posts with the given tag (hashtag), based on rich-text facet or tag field. Do not include the hash (#) prefix. Multiple tags can be specified, with 'AND' matching.
until: t.Optional[
str
] = None #: Filter results for posts before the indicated datetime (not inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYY-MM-DD).
url: t.Optional[
str
] = None #: Filter to posts with links (facet links or embeds) pointing to this URL. Server may apply URL normalization or fuzzy matching.
mentions: t.Optional[str] = (
None #: Filter to posts which mention the given account. Handles are resolved to DID before query-time. Only matches rich-text facet mentions.
)
since: t.Optional[str] = (
None #: Filter results for posts after the indicated datetime (inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYYY-MM-DD).
)
sort: t.Optional[t.Union[t.Literal['top'], t.Literal['latest'], str]] = (
'latest' #: Specifies the ranking order of results.
)
tag: t.Optional[t.List[str]] = (
None #: Filter to posts with the given tag (hashtag), based on rich-text facet or tag field. Do not include the hash (#) prefix. Multiple tags can be specified, with 'AND' matching.
)
until: t.Optional[str] = (
None #: Filter results for posts before the indicated datetime (not inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYY-MM-DD).
)
url: t.Optional[str] = (
None #: Filter to posts with links (facet links or embeds) pointing to this URL. Server may apply URL normalization or fuzzy matching.
)


class ParamsDict(t.TypedDict):
Expand Down Expand Up @@ -92,6 +92,6 @@ class Response(base.ResponseModelBase):

posts: t.List['models.AppBskyFeedDefs.PostView'] #: Posts.
cursor: t.Optional[str] = None #: Cursor.
hits_total: t.Optional[
int
] = None #: Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits.
hits_total: t.Optional[int] = (
None #: Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits.
)
6 changes: 3 additions & 3 deletions packages/atproto_client/models/app/bsky/graph/defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ class Relationship(base.ModelBase):
"""Definition model for :obj:`app.bsky.graph.defs`. lists the bi-directional graph relationships between one actor (not indicated in the object), and the target actors (the DID included in the object)."""

did: str #: Did.
followed_by: t.Optional[
str
] = None #: if the actor is followed by this DID, contains the AT-URI of the follow record.
followed_by: t.Optional[str] = (
None #: if the actor is followed by this DID, contains the AT-URI of the follow record.
)
following: t.Optional[str] = None #: if the actor follows this DID, this is the AT-URI of the follow record.

py_type: t.Literal['app.bsky.graph.defs#relationship'] = Field(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ class Response(base.ResponseModelBase):
"""Output data model for :obj:`app.bsky.graph.getSuggestedFollowsByActor`."""

suggestions: t.List['models.AppBskyActorDefs.ProfileView'] #: Suggestions.
is_fallback: t.Optional[
bool
] = False #: If true, response has fallen-back to generic results, and is not scoped using relativeToDid.
is_fallback: t.Optional[bool] = (
False #: If true, response has fallen-back to generic results, and is not scoped using relativeToDid.
)
Loading
Loading