Skip to content

Commit

Permalink
Integrate syntax sugar for repo operations upon records (#266)
Browse files Browse the repository at this point in the history
  • Loading branch information
MarshalX authored Feb 4, 2024
1 parent b6cad53 commit fddf9ac
Show file tree
Hide file tree
Showing 32 changed files with 839 additions and 1,013 deletions.
77 changes: 72 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
> ⚠️ Under construction. Until the 1.0.0 release compatibility between versions is not guaranteed.
Code snippet:

```python
from atproto import Client, client_utils

Expand Down Expand Up @@ -85,14 +86,15 @@ This SDK attempts to implement everything that provides ATProto. There is suppor
### Installing

``` bash
pip install -U atproto
pip install atproto
```

### Quick start

First of all, you need to create the instance of the XRPC Client. To do so, you have two major options: asynchronous, and synchronous. The difference only in import and how you call the methods. If you are not familiar with async, use sync instead.

For sync:

```python
from atproto import Client

Expand All @@ -102,6 +104,7 @@ client = Client()
```

For async:

```python
from atproto import AsyncClient

Expand All @@ -124,6 +127,7 @@ client.login('my-username', 'my-password')
You are awesome! Now you feel to pick any high-level method that you want and perform it!

Code to send post:

```python
from atproto import Client

Expand All @@ -133,6 +137,7 @@ client.send_post(text='Hello World!')
```

Useful links to continue:

- [List of all methods with documentation](https://atproto.readthedocs.io/en/latest/atproto_client/index.html).
- [Examples of using the methods](https://github.com/MarshalX/atproto/tree/main/examples).

Expand Down Expand Up @@ -173,18 +178,24 @@ I'll be honest. The high-level Client that was shown in the "Quick Start" sectio

The basics:
- Namespaces – classes that group sub-namespaces and the XRPC queries and procedures. Built upon NSID ATProto semantic.
- Model – dataclasses for input, output, and params of the methods from namespaces. Models describe Record and all other types in the Lexicon Schemes.
- Model – dataclasses for input, output, and params of the methods from namespaces. Models describe Record and all other types in the Lexicon Schemes.

#### Namespaces

The client contains references to the root of all namespaces. It's `com` and `app` for now.

```python
from atproto import Client

Client().com
Client().app
```

To dive deeper, you can navigate using hints from your IDE. Thanks to well-type hinted SDK, it's much easier.

```python
from atproto import Client

Client().com.atproto.server.create_session(...)
Client().com.atproto.sync.get_blob(...)
Client().app.bsky.feed.get_likes(...)
Expand All @@ -193,46 +204,95 @@ Client().app.bsky.graph.get_follows(...)

The endpoint of the path is always the method that you want to call. The method presents a query or procedure in XRPC. You should not care about it much. The only thing you need to know is that the procedures required data objects. Queries could be called with or without params.

#### Records

In some sub-namespaces, you can find records. Such record classes provide a syntax sugar not defined in the lexicon scheme. This sugar provides a more convenient way to work with repository operations. Such as creating a record, deleting a record, and so on.

Here are some available records of Bluesky records:

```python
from atproto import Client

Client().app.bsky.feed.post
Client().app.bsky.feed.like
Client().app.bsky.graph.follow
Client().app.bsky.graph.block
Client().app.bsky.actor.profile
# ... more
```

Usage example with the `post` record:

```python
from atproto import AtUri, Client, models

client = Client()
client.login('my-username', 'my-password')

posts = client.app.bsky.feed.post.list(client.me.did, limit=10)
for uri, post in posts.records.items():
print(uri, post.text)

post = client.app.bsky.feed.post.get(client.me.did, AtUri.from_str(uri).rkey)
print(post.value.text)

post_record = models.AppBskyFeedPost.Main(text='test record namespaces', created_at=client.get_current_time_iso())
new_post = client.app.bsky.feed.post.create(client.me.did, post_record)
print(new_post)

deleted_post = client.app.bsky.feed.post.delete(client.me.did, AtUri.from_str(new_post.uri).rkey)
print(deleted_post)
```

Please note that not all repository operations are covered by these syntax sugars. You can always use the low-level methods to perform any desired action. One such action is updating a record.

#### Models

To deal with methods, we need to deal with models! Models are available in the `models` module and have NSID-based aliases. Let's take a look at it.

```python
from atproto import models

models.ComAtprotoIdentityResolveHandle
models.AppBskyFeedPost
models.AppBskyActorGetProfile
# 90+ more...
```

The model classes in the "models" aliases could be:

- Data model
- Params model
- Response model
- Sugar response model
- Record model
- Type model

The only thing you need to know is how to create instances of models. Not with all models, you will work as model-creator. For example, SDK will create Response models for you.

There are a few ways how to create the instance of a model:

- Dict-based
- Class-based

The instances of data and params models should be passed as arguments to the methods that were described above.

Dict-based:

```python
from atproto import Client


client = Client()
client.login('my-username', 'my-password')
# The params model will be created automatically internally for you!
print(client.com.atproto.identity.resolve_handle({'handle': 'marshal.dev'}))
```

Class-based:

```python
from atproto import Client, models


client = Client()
client.login('my-username', 'my-password')
params = models.ComAtprotoIdentityResolveHandle.Params(handle='marshal.dev')
Expand All @@ -246,10 +306,10 @@ Pro Tip: use IDE autocompletion to find necessary models! Just start typing the
Models could be nested as hell. Be ready for it!

This is how we can send a post with the image using low-level XRPC Client:

```python
from atproto import Client, models


client = Client()
client.login('my-username', 'my-password')

Expand All @@ -269,6 +329,13 @@ with open('cat.jpg', 'rb') as f:
),
)
)

# of course, you can use the syntax sugar here instead
post = models.AppBskyFeedPost.Record(text='Text of the post', embed=embed, created_at=client.get_current_time_iso())
client.app.bsky.feed.post.create(client.me.did, post)
# or even high-level client
client.send_image(text='Text of the post', image=img_data, image_alt='Img alt')
# these three methods are equivalent
```

I hope you are not scared. May the Force be with you. Good luck!
Expand Down

This file was deleted.

1 change: 0 additions & 1 deletion docs/source/atproto/atproto_codegen.namespaces.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,3 @@ Submodules

atproto_codegen.namespaces.builder
atproto_codegen.namespaces.generator
atproto_codegen.namespaces.record_templates
7 changes: 7 additions & 0 deletions docs/source/atproto/atproto_codegen.record_templates.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
atproto\_codegen.record\_templates
==================================

.. automodule:: atproto_codegen.record_templates
:members:
:undoc-members:
:show-inheritance:
1 change: 1 addition & 0 deletions docs/source/atproto/atproto_codegen.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ Submodules
:maxdepth: 4

atproto_codegen.consts
atproto_codegen.record_templates
atproto_codegen.utils
Loading

0 comments on commit fddf9ac

Please sign in to comment.