Skip to main content

plone.restapi for Humans™

Project description

Affen: plone.restapi for Humans™

Affen is a requests Session equiped to easily consume plone.restapi

Iterating without Affen

>>> import requests
>>> response = requests.get('https://plonedemo.kitconcept.com/@search?sort_on=path',
... headers={'Accept': 'application/json'}, auth=('admin', 'admin'))
>>> for i, item in enumerate(response.json()['items']):
...     print(i, item['@id'])
...
0 https://plonedemo.kitconcept.com/de
1 https://plonedemo.kitconcept.com/de/Assets
2 https://plonedemo.kitconcept.com/de/demo
3 https://plonedemo.kitconcept.com/de/demo/a-image.jpg
4 https://plonedemo.kitconcept.com/de/demo/big_buck_bunny.mp4
5 https://plonedemo.kitconcept.com/de/demo/ein-link
6 https://plonedemo.kitconcept.com/de/demo/ein-ordner
7 https://plonedemo.kitconcept.com/de/demo/ein-ordner/eine-seite-in-einem-ordner
8 https://plonedemo.kitconcept.com/de/demo/ein-termin
9 https://plonedemo.kitconcept.com/de/demo/eine-nachricht
10 https://plonedemo.kitconcept.com/de/demo/eine-seite
11 https://plonedemo.kitconcept.com/de/demo/ploneconf-plone5.pdf
12 https://plonedemo.kitconcept.com/de/frontpage
13 https://plonedemo.kitconcept.com/en
14 https://plonedemo.kitconcept.com/en/assets
15 https://plonedemo.kitconcept.com/en/demo
16 https://plonedemo.kitconcept.com/en/demo/a-event
17 https://plonedemo.kitconcept.com/en/demo/a-file.pdf
18 https://plonedemo.kitconcept.com/en/demo/a-folder
19 https://plonedemo.kitconcept.com/en/demo/a-folder/a-page-inside-a-folder
20 https://plonedemo.kitconcept.com/en/demo/a-link
21 https://plonedemo.kitconcept.com/en/demo/a-news-item
22 https://plonedemo.kitconcept.com/en/demo/a-page
23 https://plonedemo.kitconcept.com/en/demo/a-photo.jpg
24 https://plonedemo.kitconcept.com/en/demo/a-video.mp4
>>>

And then follow the batching for more. (and remember to start enumerate at the right number)

>>> response = requests.get(response.json()['batching']['next'],
... headers={'Accept': 'application/json'}, auth=2*('admin',))
>>> for i, item in enumerate(response.json()['items'], start=i + 1):
...     print(i, item['@id'])
...
25 https://plonedemo.kitconcept.com/en/frontpage
26 https://plonedemo.kitconcept.com/my-document
>>>

An Affen Session can take credentials and an api_root in the contructor, and has an items function that iterates over anything in restapi that uses the batching protocol; like Folders, Collectors and restapi endpoints like @search:

>>> from affen import Session
>>> plone = Session('admin', 'admin', 'https://plonedemo.kitconcept.com')
>>> for i, item in enumerate(plone.items('@search?sort_on=path')):
...     print(i, item['@id'])
...
0 https://plonedemo.kitconcept.com/de
1 https://plonedemo.kitconcept.com/de/Assets
2 https://plonedemo.kitconcept.com/de/demo
3 https://plonedemo.kitconcept.com/de/demo/a-image.jpg
4 https://plonedemo.kitconcept.com/de/demo/big_buck_bunny.mp4
5 https://plonedemo.kitconcept.com/de/demo/ein-link
6 https://plonedemo.kitconcept.com/de/demo/ein-ordner
7 https://plonedemo.kitconcept.com/de/demo/ein-ordner/eine-seite-in-einem-ordner
8 https://plonedemo.kitconcept.com/de/demo/ein-termin
9 https://plonedemo.kitconcept.com/de/demo/eine-nachricht
10 https://plonedemo.kitconcept.com/de/demo/eine-seite
11 https://plonedemo.kitconcept.com/de/demo/ploneconf-plone5.pdf
12 https://plonedemo.kitconcept.com/de/frontpage
13 https://plonedemo.kitconcept.com/en
14 https://plonedemo.kitconcept.com/en/assets
15 https://plonedemo.kitconcept.com/en/demo
16 https://plonedemo.kitconcept.com/en/demo/a-event
17 https://plonedemo.kitconcept.com/en/demo/a-file.pdf
18 https://plonedemo.kitconcept.com/en/demo/a-folder
19 https://plonedemo.kitconcept.com/en/demo/a-folder/a-page-inside-a-folder
20 https://plonedemo.kitconcept.com/en/demo/a-link
21 https://plonedemo.kitconcept.com/en/demo/a-news-item
22 https://plonedemo.kitconcept.com/en/demo/a-page
23 https://plonedemo.kitconcept.com/en/demo/a-photo.jpg
24 https://plonedemo.kitconcept.com/en/demo/a-video.mp4
25 https://plonedemo.kitconcept.com/en/frontpage
26 https://plonedemo.kitconcept.com/my-document
>>>

Wrangling the Registry

And if you have the permissions, you can read and write to the registry as if it were a dictionary:

>>> plone = Session('admin', 'admin', 'http://127.0.0.1:8080/Plone')
>>> plone.registry['plone.allowed_sizes']
['large 768:768',
 'preview 400:400',
 'mini 200:200',
 'thumb 128:128',
 'tile 64:64',
 'icon 32:32',
 'listing 16:16']
>>> plone.registry['plone.allowed_sizes'] = ['supersize_me 3840:2160']
>>> plone.registry['plone.allowed_sizes']
['supersize_me 3840:2160']
>>>

But my requests.Session does almost the same!

>>> vanilla = requests.Session()
>>> vanilla.auth = ('admin', 'admin')
>>> vanilla.headers['accept'] = 'application/json'
>>> ROOT = 'http://127.0.0.1:8080/Plone'
>>> # these two lines make it almost as short as Affen...
>>> [t['title'] for t in vanilla.get(f'{ROOT}/@types').json()]
['Collection', 'Event', 'File', 'Folder', 'Image', 'Link', 'News Item', 'Page']
>>> # see? f-strings were such a great idea!
>>> # Affen is hardly shorter
>>> [t['title'] for t in plone.get('@types').json()]
['Collection', 'Event', 'File', 'Folder', 'Image', 'Link', 'News Item', 'Page']
>>>

Sure, until you accidentally reuse the session for requests to a different host. It's so conveniently close, and seems to behave like requests.get. So your mypy powered IDE didn't catch it. In fact, it provided handy autocompletion, so it looked like the Right Thing™.

>>> vanilla.get('https://httpbin.org/headers').json()['headers']['Authorization']
'Basic YWRtaW46YWRtaW4='
>>>

OOPS, did we just send our 'Authorization' header to the nice people of httpbin.org? An Affen Session will throw a fit when you try to do that:

>>> plone.get('https://httpbin.org/headers').json()
Traceback (most recent call last):
    ...
ValueError: Making requests to other hosts than http://127.0.0.1:8080/Plone/ may leak credentials. Use a different requests.Session for those or change root

>>> # and even when whe change the api root
>>> plone.root = 'https://httpbin.org'
>>> plone.get('headers').json()['headers']['Authorization']
Traceback (most recent call last):
    ...
KeyError: 'Authorization'
>>> # it won't send the secrets

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

affen-0.2.1.tar.gz (34.5 kB view details)

Uploaded Source

Built Distribution

affen-0.2.1-py3-none-any.whl (6.6 kB view details)

Uploaded Python 3

File details

Details for the file affen-0.2.1.tar.gz.

File metadata

  • Download URL: affen-0.2.1.tar.gz
  • Upload date:
  • Size: 34.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.7.1 importlib_metadata/4.10.1 pkginfo/1.8.2 requests/2.27.1 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7

File hashes

Hashes for affen-0.2.1.tar.gz
Algorithm Hash digest
SHA256 c1a9b3fd3f4feeb91de0409a9ffebcd1b75990a12bc0328ec1e2c073a8657e06
MD5 a0e3e14710f616a8a2068bad7b175088
BLAKE2b-256 d622ebce056f9038d77fc0ae9ca421975c18ca937d403672d581a24cc60ad608

See more details on using hashes here.

File details

Details for the file affen-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: affen-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 6.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.7.1 importlib_metadata/4.10.1 pkginfo/1.8.2 requests/2.27.1 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7

File hashes

Hashes for affen-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 28726d0cc0a628bb7d9bbb28d0d6491a454c19bc2f89e658f6d336552a7e19e7
MD5 f225d14d71b1c62b25335d4b7c92e4b0
BLAKE2b-256 ff91c0bac87142d91407d248be69ebe8064ee4e6593c88f96123ac75ea52d859

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page