From ca2e140c30e27143f11e8df6a51d8bb2ed0046e6 Mon Sep 17 00:00:00 2001 From: David Watson Date: Tue, 22 Dec 2015 01:21:22 -0500 Subject: [PATCH 1/8] Add example docs for python-requests-jwt --- docs/examples/python-requests-jwt.md | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 docs/examples/python-requests-jwt.md diff --git a/docs/examples/python-requests-jwt.md b/docs/examples/python-requests-jwt.md new file mode 100644 index 000000000..57a56555f --- /dev/null +++ b/docs/examples/python-requests-jwt.md @@ -0,0 +1,37 @@ +## Accessing PostgREST API using Python Requests and Requests-JWT + +The following HTTP client example should work on Python 3.x. If you're using python < 3.x you may need to change the print functions to statements or use: + + from __future__ import print_function + +This code relies on setting up the PostgreSQL auth functions and grants correctly first. Follow these instructions: + +http://postgrest.com/examples/users/ + +After completing the configuration, be sure to create a user with email, password, role, and verified flag. We'll use that user to login in the code below. + +Install the required libraries + + pip install requests + pip install Requests-jwt + +Then, from a python interpreter or script: + + import requests + import requests_jwt + import json + + # email and password auth through postgrest + resp = requests.post('http://localhost:3000/rpc/login', json={"email": "you@yours.com", "pass": "dog"}) + if resp.status_code != 200: + raise Exception() + + # JWT auth using the token above + token = json.loads(resp.text)['token'] + auth = requests_jwt.JWTAuth(token) + r = requests.get('http://localhost:3000/weight', auth=auth) + if r.status_code != 200: + raise Exception() + + for each in r.json(): + print(each) From bdfb0a76806df13eb8f56b238af77de4aa5f3427 Mon Sep 17 00:00:00 2001 From: David Watson Date: Tue, 22 Dec 2015 01:26:23 -0500 Subject: [PATCH 2/8] Layout tweaks --- docs/examples/python-requests-jwt.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/examples/python-requests-jwt.md b/docs/examples/python-requests-jwt.md index 57a56555f..ab2cfdd98 100644 --- a/docs/examples/python-requests-jwt.md +++ b/docs/examples/python-requests-jwt.md @@ -1,9 +1,5 @@ ## Accessing PostgREST API using Python Requests and Requests-JWT -The following HTTP client example should work on Python 3.x. If you're using python < 3.x you may need to change the print functions to statements or use: - - from __future__ import print_function - This code relies on setting up the PostgreSQL auth functions and grants correctly first. Follow these instructions: http://postgrest.com/examples/users/ @@ -13,7 +9,7 @@ After completing the configuration, be sure to create a user with email, passwor Install the required libraries pip install requests - pip install Requests-jwt + pip install requests-jwt Then, from a python interpreter or script: @@ -32,6 +28,11 @@ Then, from a python interpreter or script: r = requests.get('http://localhost:3000/weight', auth=auth) if r.status_code != 200: raise Exception() - + for each in r.json(): - print(each) + # do as you wish with each row + print(each) + +The preceding HTTP client example should work on Python 3.x. If you're using python < 3.x you may need to change the print functions to statements or use: + + from __future__ import print_function From 4626b4480bc3f18d169d0435b983eb80aa8658b1 Mon Sep 17 00:00:00 2001 From: David Watson Date: Tue, 22 Dec 2015 12:55:54 -0500 Subject: [PATCH 3/8] Update doc with pagination using Range header --- docs/examples/python-requests-jwt.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/examples/python-requests-jwt.md b/docs/examples/python-requests-jwt.md index ab2cfdd98..a82ca0157 100644 --- a/docs/examples/python-requests-jwt.md +++ b/docs/examples/python-requests-jwt.md @@ -25,13 +25,18 @@ Then, from a python interpreter or script: # JWT auth using the token above token = json.loads(resp.text)['token'] auth = requests_jwt.JWTAuth(token) - r = requests.get('http://localhost:3000/weight', auth=auth) if r.status_code != 200: raise Exception() - for each in r.json(): - # do as you wish with each row - print(each) + # Handle pagination using the Range header + for i in range(0, upper_bound, 20): + this_range = '{0}-{1}'.format(i, i+20 if i+20 < upper_bound else upper_bound) + headers = {"Range": "{}".format(this_range)} + r = requests.get('http://localhost:3000/posts', auth=auth, headers=headers) + if r.status_code != 200: + raise Exception() + page = r.json() + # put page into pagination control or the like The preceding HTTP client example should work on Python 3.x. If you're using python < 3.x you may need to change the print functions to statements or use: From 70ff55c8dad85496d5fe6abf29c4d43d334063b3 Mon Sep 17 00:00:00 2001 From: David Watson Date: Tue, 22 Dec 2015 15:16:09 -0500 Subject: [PATCH 4/8] Extract resultset size from Content-Range --- docs/examples/python-requests-jwt.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/examples/python-requests-jwt.md b/docs/examples/python-requests-jwt.md index a82ca0157..7a5454d1f 100644 --- a/docs/examples/python-requests-jwt.md +++ b/docs/examples/python-requests-jwt.md @@ -28,6 +28,12 @@ Then, from a python interpreter or script: if r.status_code != 200: raise Exception() + # Make a request to get the range header + r = requests.get('http://localhost:3000/posts', auth=auth) + + # Extract the size of the resultset from the Content-Range + upper_bound = int(r.headers['Content-Range'].split('/')[1]) + # Handle pagination using the Range header for i in range(0, upper_bound, 20): this_range = '{0}-{1}'.format(i, i+20 if i+20 < upper_bound else upper_bound) From 07f63090bba674a39f5e717165eba68af7b5f391 Mon Sep 17 00:00:00 2001 From: David Watson Date: Wed, 30 Dec 2015 14:43:22 -0500 Subject: [PATCH 5/8] Add link to python client repo --- docs/install/ecosystem.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/install/ecosystem.md b/docs/install/ecosystem.md index 4e153f201..afdd86074 100644 --- a/docs/install/ecosystem.md +++ b/docs/install/ecosystem.md @@ -5,6 +5,8 @@ * [mithril.postgrest](https://github.com/catarse/mithril.postgrest) - Mithril plugin to create and authenticate requests * [lewisjared/postgrest-request](https://github.com/lewisjared/postgrest-request) - node interface to postgrest instances * [JarvusInnovations/jarvus-postgrest-apikit](https://github.com/JarvusInnovations/jarvus-postgrest-apikit) - Sencha framework package for binding models/stores/proxies to PostgREST tables +* +[davidthewatson/postgrest_python_requests_client](https://github.com/davidthewatson/postgrest_python_requests_client) - python client featuring JWT auth and pagination of result sets ### Extensions From 7d343fdccafd13b47a3b30cca16e0ea899312dea Mon Sep 17 00:00:00 2001 From: David Watson Date: Wed, 30 Dec 2015 15:47:49 -0500 Subject: [PATCH 6/8] Rewrite docs for separate client repo --- docs/examples/python-requests-jwt.md | 61 ++++++++++++---------------- 1 file changed, 26 insertions(+), 35 deletions(-) diff --git a/docs/examples/python-requests-jwt.md b/docs/examples/python-requests-jwt.md index 7a5454d1f..a0a5f291b 100644 --- a/docs/examples/python-requests-jwt.md +++ b/docs/examples/python-requests-jwt.md @@ -1,49 +1,40 @@ -## Accessing PostgREST API using Python Requests and Requests-JWT +## Python Client for PostgREST API -This code relies on setting up the PostgreSQL auth functions and grants correctly first. Follow these instructions: +### Setup PostgreSQL -http://postgrest.com/examples/users/ +This code relies on setting up the PostgreSQL auth functions and grants correctly first. Follow [these instructions](http://postgrest.com/examples/users/). -After completing the configuration, be sure to create a user with email, password, role, and verified flag. We'll use that user to login in the code below. +After completing the PostgreSQL configuration, be sure to create a user with email, password, role, and verified flag. We'll use that user to login in the code below. -Install the required libraries +### Setup PostgREST - pip install requests - pip install requests-jwt +Next, setup PostgREST according to the documentation [http://postgrest.com/install/server/](here). -Then, from a python interpreter or script: +### Setup Python Client - import requests - import requests_jwt - import json +Finally, we'll install and configure the python client. Follow the instructions in the [README](https://github.com/davidthewatson/postgrest_python_requests_client/blob/master/README.md). Be sure to set the [credentials](https://github.com/davidthewatson/postgrest_python_requests_client/blob/master/config.in#L3-L5) and [urls](https://github.com/davidthewatson/postgrest_python_requests_client/blob/master/config.in#L7-L9) in config.py. - # email and password auth through postgrest - resp = requests.post('http://localhost:3000/rpc/login', json={"email": "you@yours.com", "pass": "dog"}) - if resp.status_code != 200: - raise Exception() +### Python Client Functions - # JWT auth using the token above - token = json.loads(resp.text)['token'] - auth = requests_jwt.JWTAuth(token) - if r.status_code != 200: - raise Exception() +There are four primary functions to the python client: - # Make a request to get the range header - r = requests.get('http://localhost:3000/posts', auth=auth) +* login +* construct_jwt_auth +* get_result_size +* get_range - # Extract the size of the resultset from the Content-Range - upper_bound = int(r.headers['Content-Range'].split('/')[1]) +The *login* and *construct_jwt_auth* functions will be required for any REST client using a PostgREST server, since a JWT auth instance is presumed. - # Handle pagination using the Range header - for i in range(0, upper_bound, 20): - this_range = '{0}-{1}'.format(i, i+20 if i+20 < upper_bound else upper_bound) - headers = {"Range": "{}".format(this_range)} - r = requests.get('http://localhost:3000/posts', auth=auth, headers=headers) - if r.status_code != 200: - raise Exception() - page = r.json() - # put page into pagination control or the like +The *get_result_size* and *get_range* functions are designed specifically for result sets where pagination is required. You can certainly use them for a single page result set that does not require pagination, but that may be overkill. -The preceding HTTP client example should work on Python 3.x. If you're using python < 3.x you may need to change the print functions to statements or use: +### Login +The [login function](https://github.com/davidthewatson/postgrest_python_requests_client/blob/master/client.py#L12-L17) takes email and password strings (credentials.email and credentials.password, respectively from the config.py) and return the response. - from __future__ import print_function +### Construct JWT Auth +The [construct_jwt_auth](https://github.com/davidthewatson/postgrest_python_requests_client/blob/master/client.py#L20-L23) function takes the auth response returned by the login function, retrieves the token in the response, and returns a JWT auth instance to the caller. The JWT auth instance can then be used for successive calls to the same PostgREST service. + +### Get Result Size +The [get_result_size](https://github.com/davidthewatson/postgrest_python_requests_client/blob/master/client.py#L26-L30) function takes a JWT auth instance calls the URL at urls.data, extracts the size of the result set from the response object and returns the size. + +### Get Range +The [get_range](https://github.com/davidthewatson/postgrest_python_requests_client/blob/master/client.py#L26-L30) function takes a beginning range, ending range, page size, and JWT auth instance, gets only that range of the available result set and returns JSON for that result set. From 0161007390f75bd7859a578e89876a1242ad5b5d Mon Sep 17 00:00:00 2001 From: David Watson Date: Wed, 30 Dec 2015 16:26:25 -0500 Subject: [PATCH 7/8] Remove extraneous newline --- docs/install/ecosystem.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/install/ecosystem.md b/docs/install/ecosystem.md index afdd86074..b927f2871 100644 --- a/docs/install/ecosystem.md +++ b/docs/install/ecosystem.md @@ -5,8 +5,7 @@ * [mithril.postgrest](https://github.com/catarse/mithril.postgrest) - Mithril plugin to create and authenticate requests * [lewisjared/postgrest-request](https://github.com/lewisjared/postgrest-request) - node interface to postgrest instances * [JarvusInnovations/jarvus-postgrest-apikit](https://github.com/JarvusInnovations/jarvus-postgrest-apikit) - Sencha framework package for binding models/stores/proxies to PostgREST tables -* -[davidthewatson/postgrest_python_requests_client](https://github.com/davidthewatson/postgrest_python_requests_client) - python client featuring JWT auth and pagination of result sets +* [davidthewatson/postgrest_python_requests_client](https://github.com/davidthewatson/postgrest_python_requests_client) - python client featuring JWT auth and pagination of result sets ### Extensions From 5408ca26ad5b06aa91bad5f781557c982e405d79 Mon Sep 17 00:00:00 2001 From: David Watson Date: Wed, 30 Dec 2015 16:32:53 -0500 Subject: [PATCH 8/8] Add python client menu link --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index e012d5156..8eaaf5b5a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -25,3 +25,4 @@ pages: - User Management: examples/users.md - External Authentication: examples/external_auth.md - Multi-Tenant Blog: examples/blog.md + - Python Client: examples/python-requests-jwt.md