Skip to content

Commit d97634c

Browse files
committed
release v0.1, first release!
1 parent 45ab294 commit d97634c

2 files changed

Lines changed: 139 additions & 53 deletions

File tree

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ Here's how to package, test, and ship a new release. (Note that this is [largely
9595
```sh
9696
python3 -m build
9797
setenv ver X.Y
98-
twine upload -r pypitest dist/lexrpc-$ver.tar.gz
98+
twine upload -r pypitest dist/lexrpc-$ver*
9999
```
100100
1. Install from test.pypi.org.
101101
```sh
@@ -142,7 +142,7 @@ Here's how to package, test, and ship a new release. (Note that this is [largely
142142
def ping(input, message=''):
143143
return {'message': message}
144144
145-
print(server.call('io.example.ping', message='hello world')
145+
print(server.call('io.example.ping', {}, message='hello world'))
146146
```
147147
1. Tag the release in git. In the tag message editor, delete the generated comments at bottom, leave the first line blank (to omit the release "title" in github), put `### Notable changes` on the second line, then copy and paste this version's changelog contents below it.
148148
```sh
@@ -152,14 +152,16 @@ Here's how to package, test, and ship a new release. (Note that this is [largely
152152
1. [Click here to draft a new release on GitHub.](https://github.com/snarfed/lexrpc/releases/new) Enter `vX.Y` in the _Tag version_ box. Leave _Release title_ empty. Copy `### Notable changes` and the changelog contents into the description text box.
153153
1. Upload to [pypi.org](https://pypi.org/)!
154154
```sh
155-
twine upload dist/lexrpc-$ver.tar.gz
155+
twine upload dist/lexrpc-$ver*
156156
```
157157
1. [Wait for the docs to build on Read the Docs](https://readthedocs.org/projects/lexrpc/builds/), then check that they look ok.
158158
1. On the [Versions page](https://readthedocs.org/projects/lexrpc/versions/), check that the new version is active, If it's not, activate it in the _Activate a Version_ section.
159159
160160
161161
## Changelog
162162
163-
### 0.1 - unreleased
163+
### 0.1 - 2022-12-13
164164
165165
Initial release!
166+
167+
Tested interoperability with the `lexicon`, `xprc`, and `xrpc-server` packages in [bluesky-social/atproto](https://github.com/bluesky-social/atproto). Lexicon and XRPC are still very early and under active development; caveat hacker!

docs/index.rst

Lines changed: 133 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,95 +3,95 @@ lexrpc
33

44
Python implementation of `AT Protocol <https://atproto.com/>`__\ ’s
55
`XRPC <https://atproto.com/specs/xrpc>`__ +
6-
`Lexicon <https://atproto.com/guides/lexicon>`__, both client and
7-
server. `Docs here. <https://lexrpc.readthedocs.io/>`__
8-
9-
- `Getting started <#getting-started>`__
10-
11-
- `Client <#client>`__
12-
- `Server <#server>`__
13-
- `Flask server <#flask-server>`__
14-
6+
`Lexicon <https://atproto.com/guides/lexicon>`__. lexrpc includes a
7+
simple `XRPC <https://atproto.com/specs/xrpc>`__ client, server, and
8+
`Flask <https://flask.palletsprojects.com/>`__ web server integration.
9+
All three include full `Lexicon <https://atproto.com/guides/lexicon>`__
10+
support for validating inputs, outputs, and parameters against their
11+
schemas.
12+
13+
- `Client <#client>`__
14+
- `Server <#server>`__
15+
- `Flask server <#flask-server>`__
16+
- `Reference <https://lexrpc.readthedocs.io/en/docs/source/lexrpc.html>`__
1517
- `TODO <#todo>`__
1618
- `Changelog <#changelog>`__
1719

1820
License: This project is placed in the public domain.
1921

20-
Getting started
21-
---------------
22-
23-
lexrpc includes a simple `XRPC <https://atproto.com/specs/xrpc>`__
24-
client, server, and `Flask <https://flask.palletsprojects.com/>`__ web
25-
server integration. All three include full
26-
`Lexicon <https://atproto.com/guides/lexicon>`__ support for validating
27-
inputs, outputs, and parameters against their schemas.
28-
2922
Client
30-
~~~~~~
23+
------
3124

3225
The lexrpc client let you `call methods dynamically by their
3326
NSIDs <https://atproto.com/guides/lexicon#rpc-methods>`__. To make a
3427
call, first instantiate a
3528
`Client <https://lexrpc.readthedocs.io/en/latest/source/lexrpc.html#lexrpc.client.Client>`__
36-
object with the server address and method lexicons, then use NSIDs to
37-
make calls, passing input as a dict and parameters as kwargs:
29+
object with the server address and method lexicons, then use method
30+
NSIDs to make calls, passing input as a dict and parameters as kwargs:
3831

3932
.. code:: py
4033
41-
from jsonschema import Client
34+
from lexrpc import Client
4235
4336
lexicons = [...]
4437
client = Client('https://xrpc.example.com', lexicons)
45-
output = client.com.example.my_query({'foo': 'bar'}, a_param=False)
38+
output = client.com.example.my_query({'foo': 'bar'}, param_a=5)
4639
4740
Note that ``-`` characters in method NSIDs are converted to ``_``\ s, eg
4841
the call above is for the method ``com.example.my-query``.
4942

5043
Server
51-
~~~~~~
44+
------
5245

5346
To implement an XRPC server, use the
5447
`Server <https://lexrpc.readthedocs.io/en/latest/source/lexrpc.html#lexrpc.server.Server>`__
5548
class. It validates parameters, inputs, and outputs. Use the
5649
`method <https://lexrpc.readthedocs.io/en/latest/source/lexrpc.html#lexrpc.server.Server.method>`__
57-
decorator to register handlers for each NSID,
58-
`Server.call <https://lexrpc.readthedocs.io/en/latest/source/lexrpc.html#lexrpc.server.Server.call>`__
59-
to call a method from your web framework or anywhere else.
50+
decorator to register method handlers and
51+
`call <https://lexrpc.readthedocs.io/en/latest/source/lexrpc.html#lexrpc.server.Server.call>`__
52+
to call them, whether from your web framework or anywhere else.
6053

6154
.. code:: py
6255
63-
from jsonschema import Server
56+
from lexrpc import Server
6457
6558
lexicons = [...]
6659
server = Server(lexicons)
6760
6861
@server.method('com.example.my-query')
6962
def my_query_hander(input, **params):
70-
...
71-
output = ...
63+
output = {'foo': input['foo'], 'b': params['param_a'] + 1}
7264
return output
7365
74-
# In your web framework, use Server.call to run a method
66+
# Extract nsid and decode query parameters from an HTTP request,
67+
# call the method, return the output in an HTTP response
68+
nsid = request.path.removeprefix('/xrpc/')
7569
input = request.json()
76-
params = request.query_params()
77-
# decode params
70+
params = server.decode_params(nsid, request.query_params())
7871
output = server.call(input, **params)
7972
response.write_json(output)
8073
8174
Flask server
82-
~~~~~~~~~~~~
75+
------------
8376

84-
First, instantiate a ``Server`` and register method handlers as
85-
described above. Then, attach the server to your Flask app with
86-
`lexrpc.init_flask <https://lexrpc.readthedocs.io/en/latest/source/lexrpc.html#lexrpc.flask_server.init_flask>`__.
77+
To serve XRPC methods in a
78+
`Flask <https://flask.palletsprojects.com/>`__ web app, first install
79+
the lexrpc package with the ``flask`` extra, eg
80+
``pip install lexrpc[flask]``. Then, instantiate a
81+
`Server <https://lexrpc.readthedocs.io/en/latest/source/lexrpc.html#lexrpc.server.Server>`__
82+
and register method handlers as described above. Finally, attach the
83+
server to your Flask app with
84+
`flask_server.init_flask <https://lexrpc.readthedocs.io/en/latest/source/lexrpc.html#lexrpc.flask_server.init_flask>`__.
8785

8886
.. code:: py
8987
9088
from flask import Flask
91-
from lexrpc import init_flask
89+
from lexrpc.flask_server import init_flask
90+
91+
# instantiate a Server like above
92+
server = ...
9293
9394
app = Flask('my-server')
94-
...
9595
init_flask(server, app)
9696
9797
This configures the Flask app to serve the methods registered with the
@@ -105,20 +105,104 @@ set to ``application/json``.
105105
TODO
106106
----
107107

108-
- validate records/tokens in input/output? or are those only
109-
primitives?
110-
- extensions, https://atproto.com/guides/lexicon#extensibility . is
111-
there anything to do? ah, it’s currently TODO in the spec:
112-
https://atproto.com/specs/xrpc#todos
113-
- “binary blob” support, as in https://atproto.com/specs/xrpc . is it
114-
currently undefined?
115-
- authentication, currently TODO in the spec:
116-
https://atproto.com/specs/xrpc#todos
108+
- support record types, eg via type “ref” and ref field pointing to the
109+
nsid `example
110+
here <https://github.com/bluesky-social/atproto/blob/main/lexicons/app/bsky/graph/follow.json#L13>`__,
111+
ref points to
112+
`app.bsky.actor.ref <https://github.com/bluesky-social/atproto/blob/main/lexicons/app/bsky/actor/ref.json>`__.
113+
ref isn’t documented yet though, and these lexicons also use a
114+
``defs`` field, which isn’t really documented either. `they plan to
115+
update the docs and specs
116+
soon. <https://github.com/bluesky-social/atproto/pull/409#issuecomment-1348766856>`__
117+
- `extensions <https://atproto.com/guides/lexicon#extensibility>`__. is
118+
there anything to do? ah, `they’re currently TODO in the
119+
spec <https://atproto.com/specs/xrpc#todos>`__.
120+
- `“binary blob” support. <https://atproto.com/specs/xrpc>`__ currently
121+
undefined ish? is it based on the ``encoding`` field?
122+
- `authentication, currently TODO in the
123+
spec <https://atproto.com/specs/xrpc#todos>`__
124+
125+
Release instructions
126+
--------------------
127+
128+
Here’s how to package, test, and ship a new release. (Note that this is
129+
`largely duplicated in the oauth-dropins readme
130+
too <https://github.com/snarfed/oauth-dropins#release-instructions>`__.)
131+
132+
1. Run the unit tests.
133+
``sh source local/bin/activate.csh python3 -m unittest discover``
134+
135+
2. Bump the version number in ``setup.py`` and ``docs/conf.py``.
136+
``git grep`` the old version number to make sure it only appears in
137+
the changelog. Change the current changelog entry in ``README.md``
138+
for this new version from *unreleased* to the current date.
139+
140+
3. Build the docs. If you added any new modules, add them to the
141+
appropriate file(s) in ``docs/source/``. Then run
142+
``./docs/build.sh``. Check that the generated HTML looks fine by
143+
opening ``docs/_build/html/index.html`` and looking around.
144+
145+
4. ``git commit -am 'release vX.Y'``
146+
147+
5. Upload to `test.pypi.org <https://test.pypi.org/>`__ for testing.
148+
``sh python3 -m build setenv ver X.Y twine upload -r pypitest dist/lexrpc-$ver*``
149+
150+
6. Install from test.pypi.org.
151+
``sh cd /tmp python3 -m venv local source local/bin/activate.csh pip3 uninstall lexrpc # make sure we force pip to use the uploaded version pip3 install --upgrade pip pip3 install -i https://test.pypi.org/simple --extra-index-url https://pypi.org/simple lexrpc==$ver deactivate``
152+
153+
7. Smoke test that the code trivially loads and runs.
154+
``sh source local/bin/activate.csh python3 # run test code below deactivate``
155+
Test code to paste into the interpreter: \`py from lexrpc import
156+
Server
157+
158+
server = Server([{ ‘lexicon’: 1, ‘id’: ‘io.example.ping’, ‘defs’: {
159+
‘main’: { ‘type’: ‘query’, ‘description’: ‘Ping the server’,
160+
‘parameters’: {‘message’: { ‘type’: ‘string’ }}, ‘output’: {
161+
‘encoding’: ‘application/json’, ‘schema’: { ‘type’: ‘object’,
162+
‘required’: [‘message’], ‘properties’: {‘message’: { ‘type’:
163+
‘string’ }}, }, }, }, }, }])
164+
165+
@server.method(‘io.example.ping’) def ping(input, message=’‘):
166+
return {’message’: message}
167+
168+
print(server.call(‘io.example.ping’, {}, message=‘hello world’))
169+
\``\`
170+
171+
8. Tag the release in git. In the tag message editor, delete the
172+
generated comments at bottom, leave the first line blank (to omit
173+
the release “title” in github), put ``### Notable changes`` on the
174+
second line, then copy and paste this version’s changelog contents
175+
below it.
176+
``sh git tag -a v$ver --cleanup=verbatim git push && git push --tags``
177+
178+
9. `Click here to draft a new release on
179+
GitHub. <https://github.com/snarfed/lexrpc/releases/new>`__ Enter
180+
``vX.Y`` in the *Tag version* box. Leave *Release title* empty. Copy
181+
``### Notable changes`` and the changelog contents into the
182+
description text box.
183+
184+
10. Upload to `pypi.org <https://pypi.org/>`__!
185+
``sh twine upload dist/lexrpc-$ver*``
186+
187+
11. `Wait for the docs to build on Read the
188+
Docs <https://readthedocs.org/projects/lexrpc/builds/>`__, then
189+
check that they look ok.
190+
191+
12. On the `Versions
192+
page <https://readthedocs.org/projects/lexrpc/versions/>`__, check
193+
that the new version is active, If it’s not, activate it in the
194+
*Activate a Version* section.
117195

118196
Changelog
119197
---------
120198

121-
0.1 - unreleased
199+
0.1 - 2022-12-13
122200
~~~~~~~~~~~~~~~~
123201

124202
Initial release!
203+
204+
Tested interoperability with the ``lexicon``, ``xprc``, and
205+
``xrpc-server`` packages in
206+
`bluesky-social/atproto <https://github.com/bluesky-social/atproto>`__.
207+
Lexicon and XRPC are still very early and under active development;
208+
caveat hacker!

0 commit comments

Comments
 (0)