Switching request to aiohttp

This commit is contained in:
FoxMaSk
2017-08-20 15:18:24 +02:00
4 changed files with 280 additions and 297 deletions

View File

@@ -3,11 +3,6 @@
:alt: Python version supported :alt: Python version supported
.. image:: http://img.shields.io/badge/python-3.5-orange.svg
:target: https://pypi.python.org/pypi/django-th/
:alt: Python version supported
.. image:: http://img.shields.io/badge/license-BSD-blue.svg .. image:: http://img.shields.io/badge/license-BSD-blue.svg
:target: https://pypi.python.org/pypi/django-th/ :target: https://pypi.python.org/pypi/django-th/
:alt: License :alt: License
@@ -22,7 +17,7 @@ Python API for Wallabag v2.2.3
Requirements : Requirements :
============== ==============
* requests 2.13.0 * aiohttp
Installation: Installation:
@@ -51,27 +46,66 @@ Creating a post :
.. code:: python .. code:: python
#!/usr/bin/env python
import aiohttp
import asyncio
from wallabag_api.wallabag import Wallabag from wallabag_api.wallabag import Wallabag
# settings # settings
params = {'username': 'foxmask',
'password': 'mypass',
'client_id': 'myid',
'client_secret': 'mysecret'}
my_host = 'http://localhost:8080' my_host = 'http://localhost:8080'
# get token
token = Wallabag.get_token(host=my_host, **params)
# create a post
wall = Wallabag(host=my_host,
client_secret='mysecret',
client_id='myid',
token=token)
my_url = 'https://blog.trigger-happy.eu' async def main(loop):
my_title = 'Trigger Happy blog'
my_tags = ['python', 'wallabag']
wall.post_entries(url=my_url, title=my_title, tags=my_tags) params = {'username': 'foxmask',
'password': 'mypass',
'client_id': 'myid',
'client_secret': 'mysecret',
'extension': 'pdf'}
# get a new token
token = await Wallabag.get_token(host=my_host, **params)
# initializing
async with aiohttp.ClientSession(loop=loop) as session:
wall = Wallabag(host=my_host,
client_secret=params.get('client_secret'),
client_id=params.get('client_id'),
token=token,
extension=params['extension'],
aio_sess=session)
url = 'https://foxmask.trigger-happy.eu'
title = 'foxmask\'s blog'
await wall.post_entries(url, title, '', 0, 0)
url = 'https://trigger-happy.eu'
title = 'Project TrigerHappy'
await wall.post_entries(url, title, '', 0, 0)
# get all the articles
my_wallabag = await wall.get_entries()
all_article = my_wallabag['_embedded']['items']
for article in all_article:
print(article['id'], article['title'])
# get the version of wallabag
version = await wall.version
print(f"version {version}")
# export one article into PDF
my_wallabag = await wall.get_entry_export(entry=1)
with open("foobar.pdf", "wb") as f:
f.write(my_wallabag)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
this will give you something like this : this will give you something like this :
@@ -79,42 +113,6 @@ this will give you something like this :
.. image:: https://github.com/foxmask/wallabag_api/blob/master/wallabag.png .. image:: https://github.com/foxmask/wallabag_api/blob/master/wallabag.png
3) get all the entries
.. code:: python
# get all the entries
wall = wall.get_entries()
all_article = wall['_embedded']['items']
for article in all_article:
print(article['title'])
print(article['content'])
print("******")
4) version of wallabag
.. code:: python
# get the version of your wallabag instance
print("version {}".format(wall.version))
5) to get the article in PDF
.. code:: python
# to get the article in PDF for example,
wall = Wallabag(host=my_host,
client_secret='mysecret',
client_id='myid',
token=token,
extension='pdf')
article = wall.get_entry(entry=1)
with open("my_file.pdf", "wb") as f:
f.write(article)
Testing : Testing :
========= =========
@@ -124,7 +122,7 @@ Then run the development version (with make run)
Then create a client API like explain here http://doc.wallabag.org/en/v2/developer/api.html Then create a client API like explain here http://doc.wallabag.org/en/v2/developer/api.html
this will give you somthing like this this will give you something like this
.. image:: https://github.com/foxmask/wallabag_api/blob/master/wallabag_api_key.png .. image:: https://github.com/foxmask/wallabag_api/blob/master/wallabag_api_key.png

View File

@@ -1,14 +1,15 @@
from setuptools import setup, find_packages from setuptools import setup, find_packages
from wallabag_api import __version__ as version from wallabag_api import __version__ as version
desc = 'Wallabag API to add every pages you want to your Wallabag account'
install_requires = [ install_requires = [
'requests-2.13.0', 'aiohttp==2.2.5',
] ]
setup( setup(
name='wallabag_api', name='wallabag_api',
version=version, version=version,
description='Wallabag API to add every pages you want to your Wallabag account', description=desc,
author='FoxMaSk', author='FoxMaSk',
author_email='foxmask@trigger-happy.eu', author_email='foxmask@trigger-happy.eu',
url='https://github.com/foxmask/wallabag_api', url='https://github.com/foxmask/wallabag_api',
@@ -21,7 +22,6 @@ setup(
'License :: OSI Approved :: BSD License', 'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent', 'Operating System :: OS Independent',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',
'Topic :: Internet', 'Topic :: Internet',
'Topic :: Communications', 'Topic :: Communications',

View File

@@ -1,2 +1,2 @@
VERSION = (1, 3, 0) # PEP 386 VERSION = (1, 2, 0) # PEP 386
__version__ = ".".join([str(x) for x in VERSION]) __version__ = ".".join([str(x) for x in VERSION])

View File

@@ -1,12 +1,11 @@
# coding: utf-8 # coding: utf-8
import logging import logging
import requests import aiohttp
from requests import HTTPError from aiohttp.http_exceptions import HttpProcessingError
from aiohttp.client_exceptions import ClientResponseError
__author__ = 'foxmask' __author__ = 'foxmask'
logging.basicConfig(format='%(message)s', level=logging.INFO) logging.basicConfig(format='%(message)s', level=logging.INFO)
__all__ = ['Wallabag'] __all__ = ['Wallabag']
@@ -26,6 +25,7 @@ class Wallabag(object):
format = '' format = ''
username = '' username = ''
password = '' password = ''
aio_sess = None
def __init__(self, def __init__(self,
host='', host='',
@@ -34,15 +34,17 @@ class Wallabag(object):
client_secret='', client_secret='',
extension='json', extension='json',
user_agent="WallabagPython/1.3 " user_agent="WallabagPython/1.3 "
"+https://github.com/foxmask/wallabag-api"): "+https://github.com/foxmask/wallabag-api",
aio_sess=None):
""" """
init variable init variable
:param host: string url to the official API Wallabag :param host: string url to the official API Wallabag
:param token: string of the key provided by Wallabag :param token: string of the key provided by Wallabag
:param client_id client id :param client_id client id
:param client_secret client secret :param client_secret client secret
:param extension: xml|json|txt|csv|pdf|epub|mobi|html :param extension: xml|json|txt|csv|pdf|epub|mobi|html
:param user_agent :param user_agent
:param aio_sess aiohttp session
""" """
self.host = host self.host = host
self.client_id = client_id self.client_id = client_id
@@ -50,102 +52,98 @@ class Wallabag(object):
self.token = token self.token = token
self.format = extension self.format = extension
self.user_agent = user_agent self.user_agent = user_agent
self.aio_sess = aio_sess
if self.format not in self.EXTENTIONS: if self.format not in self.EXTENTIONS:
raise ValueError("format invalid {0} should be one of {1}".format(self.format, self.EXTENTIONS)) raise ValueError("format invalid {0} should be one of {1}".format(
self.format, self.EXTENTIONS))
def get_host(self): async def query(self, path, method='get', **params):
""" """
get the host from which to get API Do a query to the System API
:return host
"""
return self.host
def query(self, path, method='get', **params): :param path: url to the API
""" :param method: the kind of query to do
Do a query to the System API :param params: a dict with all the
:param path: url to the API necessary things to query the API
:param method: the kind of query to do :return json data
:param params: a dict with all the
necessary things to query the API
:return json data
""" """
if method in ('get', 'post', 'patch', 'delete', 'put'): if method in ('get', 'post', 'patch', 'delete', 'put'):
full_path = self.host + path full_path = self.host + path
if method == 'get': if method == 'get':
r = requests.get(full_path, params=params) resp = await self.aio_sess.get(full_path, params=params)
elif method == 'post': elif method == 'post':
r = requests.post(full_path, data=params) resp = await self.aio_sess.post(full_path, data=params)
elif method == 'patch': elif method == 'patch':
r = requests.patch(full_path, data=params) resp = await self.aio_sess.patch(full_path, data=params)
elif method == 'delete': elif method == 'delete':
r = requests.delete(full_path, headers=params) resp = await self.aio_sess.delete(full_path, headers=params)
elif method == 'put': elif method == 'put':
r = requests.put(full_path, params=params) resp = await self.aio_sess.put(full_path, data=params)
# return the content if its a binary one
if r.headers['Content-Type'].startswith('application/pdf') or\ async with resp:
r.headers['Content-Type'].startswith('application/epub'): # return the content if its a binary one
return r.content if resp.content_type.startswith('application/pdf') or \
else: resp.content_type.startswith('application/epub'):
return self.handle_json_response(r) return await resp.read()
return await self.handle_json_response(resp)
else: else:
raise ValueError('method expected: get, post, patch, delete, put') raise ValueError('method expected: get, post, patch, delete, put')
@staticmethod @staticmethod
def handle_json_response(responses): async def handle_json_response(responses):
""" """
get the json data response get the json data response
:param responses: the json response :param responses: the json response
:return the json data without 'root' node :return the json data without 'root' node
""" """
if responses.status_code != 200: if responses.status != 200:
raise HTTPError(responses.status_code, responses.json()) raise HttpProcessingError(code=responses.status,
message=await responses.json())
json_data = {} json_data = {}
try: try:
json_data = responses.json() json_data = responses.json()
except: except ClientResponseError as e:
# sometimes json_data does not return any json() without # sometimes json_data does not return any json() without
# any error. This is due to the grabbing URL which "rejects" # any error. This is due to the grabbing URL which "rejects"
# the URL # the URL
if 'errors' in json_data: logging.error("Wallabag: aiohttp error {code} {message}"
for error in json_data['errors']: .format(code=e.code, message=e.message))
error_json = json_data['errors'][error]['content'] return await json_data
logging.error("Wallabag: {error}".format(error=error_json))
return json_data
@staticmethod @staticmethod
def __get_attr(what, type_attr, value_attr, **kwargs): def __get_attr(what, type_attr, value_attr, **kwargs):
""" """
get the value of a parm
:param what: :param what: string parm
:param type_attr: :param type_attr: type of parm
:param value_attr: :param value_attr:
:param kwargs: :param kwargs:
:return: :return: value of the parm
""" """
value = int(kwargs[what]) if type_attr == 'int' else kwargs.get(what) value = int(kwargs[what]) if type_attr == 'int' else kwargs[what]
if what in kwargs and value in value_attr: if what in kwargs and value in value_attr:
return value return value
# ENTRIES # ENTRIES
def get_entries(self, **kwargs): async def get_entries(self, **kwargs):
""" """
GET /api/entries.{_format}
GET /api/entries.{_format} Retrieve all entries. It could be filtered by many options.
Retrieve all entries. It could be filtered by many options. :param kwargs: can contain one of the following filters
archive: '0' or '1', default '0' filter by archived status.
:param kwargs: can contain one of the following filters star: '0' or '1', default '0' filter by starred status.
archive: '0' or '1', default '0' filter by archived status. delete: '0' or '1', default '0' filter by deleted status.
star: '0' or '1', default '0' filter by starred status. sort: 'created' or 'updated', default 'created'
delete: '0' or '1', default '0' filter by deleted status. order: 'asc' or 'desc', default 'desc'
sort: 'created' or 'updated', default 'created' page: int default 1 what page you want
order: 'asc' or 'desc', default 'desc' perPage: int default 30 result per page
page: int default 1 what page you want tags: list of tags url encoded.
perPage: int default 30 result per page since: int default 0 from what timestamp you want
tags: list of tags url encoded. Will returns entries that matches ALL tags
since: int default 0 from what timestamp you want :return data related to the ext
Will returns entries that matches ALL tags
:return data related to the ext
""" """
# default values # default values
params = dict({'access_token': self.token, params = dict({'access_token': self.token,
@@ -156,91 +154,88 @@ class Wallabag(object):
'order': 'desc', 'order': 'desc',
'page': 1, 'page': 1,
'perPage': 30, 'perPage': 30,
'tags': [], 'tags': '',
'since': 0}) 'since': 0})
params['archive'] = self.__get_attr(what='archive', params['archive'] = self.__get_attr(what='archive',
type_attr=int, type_attr=int,
value_attr=(0, 1), value_attr=(0, 1),
**kwargs) **params)
params['star'] = self.__get_attr(what='star', params['star'] = self.__get_attr(what='star',
type_attr=int, type_attr=int,
value_attr=(0, 1), value_attr=(0, 1),
**kwargs) **params)
params['delete'] = self.__get_attr(what='delete', params['delete'] = self.__get_attr(what='delete',
type_attr=int, type_attr=int,
value_attr=(0, 1), value_attr=(0, 1),
**kwargs) **params)
params['order'] = self.__get_attr(what='order', params['order'] = self.__get_attr(what='order',
type_attr=str, type_attr=str,
value_attr=('asc', 'desc'), value_attr=('asc', 'desc'),
**kwargs) **params)
if 'page' in kwargs and isinstance(kwargs['page'], int): if 'page' in kwargs and isinstance(kwargs['page'], int):
params['page'] = kwargs['page'] params['page'] = kwargs['page']
if 'perPage' in kwargs and isinstance(kwargs['perPage'], int): if 'perPage' in kwargs and isinstance(kwargs['perPage'], int):
params['perPage'] = kwargs['perPage'] params['perPage'] = kwargs['perPage']
if 'tags' in kwargs and isinstance(kwargs['tags'], list): if 'tags' in kwargs and isinstance(kwargs['tags'], list):
params['tags'] = kwargs['tags'] params['tags'] = ', '.join(kwargs['tags'])
if 'since' in kwargs and isinstance(kwargs['since'], int): if 'since' in kwargs and isinstance(kwargs['since'], int):
params['since'] = kwargs['since'] params['since'] = kwargs['since']
path = '/api/entries.{ext}'.format(ext=self.format) path = '/api/entries.{ext}'.format(ext=self.format)
return self.query(path, "get", **params) return await self.query(path, "get", **params)
def post_entries(self, url, title='', tags='', starred=0, archive=0): async def post_entries(self, url, title='', tags='', starred=0, archive=0):
""" """
POST /api/entries.{_format}
POST /api/entries.{_format} Create an entry
Create an entry :param url: the url of the note to store
:param title: Optional, we'll get the title from the page.
:param url: the url of the note to store :param tags: tag1,tag2,tag3 a comma-separated list of tags.
:param title: Optional, we'll get the title from the page. :param starred entry already starred
:param tags: tag1,tag2,tag3 a comma-separated list of tags. :param archive entry already archived
:param starred entry already starred :return result
:param archive entry already archived
:return result
""" """
params = {'access_token': self.token, 'url': url, 'title': title, params = {'access_token': self.token, 'url': url, 'title': title,
'tags': tags, 'starred': starred, 'archive': archive} 'tags': tags, 'starred': starred, 'archive': archive}
if len(tags) > 0 and ',' in tags: if len(tags) > 0 and ',' in tags:
params['tags'] = tags.split(',') params['tags'] = tags.split(',')
path = '/api/entries.{ext}'.format(ext=self.format) path = '/api/entries.{ext}'.format(ext=self.format)
return self.query(path, "post", **params) return await self.query(path, "post", **params)
def get_entry(self, entry): async def get_entry(self, entry):
""" """
GET /api/entries/{entry}.{_format}
GET /api/entries/{entry}.{_format} Retrieve a single entry
Retrieve a single entry :param entry: \w+ an integer The Entry ID
:return data related to the ext
:param entry: \w+ an integer The Entry ID
:return data related to the ext
""" """
params = {'access_token': self.token} params = {'access_token': self.token}
url = '/api/entries/{entry}.{ext}'.format(entry=entry, url = '/api/entries/{entry}.{ext}'.format(entry=entry,
ext=self.format) ext=self.format)
return self.query(url, "get", **params) return await self.query(url, "get", **params)
def patch_entries(self, entry, **kwargs): async def patch_entries(self, entry, **kwargs):
""" """
PATCH /api/entries/{entry}.{_format}
PATCH /api/entries/{entry}.{_format} Change several properties of an entry
Change several properties of an entry :param entry: the entry to 'patch' / update
:param kwargs: can contain one of the following
:param entry: the entry to 'patch' / update title: string
:param kwargs: can contain one of the following tags: a list of tags tag1,tag2,tag3
title: string archive: '0' or '1', default '0' archived the entry.
tags: a list of tags tag1,tag2,tag3 star: '0' or '1', default '0' starred the entry
archive: '0' or '1', default '0' archived the entry. delete: '0' or '1', default '0' flag as deleted.
star: '0' or '1', default '0' starred the entry In case that you don't want to *really* remove it..
delete: '0' or '1', default '0' flag as deleted. :return data related to the ext
In case that you don't want to *really* remove it..
:return data related to the ext
""" """
# default values # default values
params = {'access_token': self.token, params = {'access_token': self.token,
@@ -274,246 +269,231 @@ class Wallabag(object):
path = '/api/entries/{entry}.{ext}'.format( path = '/api/entries/{entry}.{ext}'.format(
entry=entry, ext=self.format) entry=entry, ext=self.format)
return self.query(path, "patch", **params) return await self.query(path, "patch", **params)
def get_entry_export(self, entry): async def get_entry_export(self, entry):
""" """
GET /api/entries/{entry}/export.{_format}
GET /api/entries/{entry}/export.{_format} Retrieve a single entry as a predefined format.
Retrieve a single entry as a predefined format. :param entry: \w+ an integer The Entry ID
:return data related to the ext
:param entry: \w+ an integer The Entry ID
:return data related to the ext
""" """
params = {'access_token': self.token} params = {'access_token': self.token}
url = '/api/entries/{entry}/export.{ext}'.format(entry=entry, url = '/api/entries/{entry}/export.{ext}'.format(entry=entry,
ext=self.format) ext=self.format)
return self.query(url, "get", **params) return await self.query(url, "get", **params)
def patch_entry_reload(self, entry): async def patch_entry_reload(self, entry):
""" """
PATCH /api/entries/{entry}/reload.{_format}
PATCH /api/entries/{entry}/reload.{_format} Reload an entry. An empty response with HTTP Status 304 will be send
if we weren't able to update the content (because it hasn't changed
or we got an error).
Reload an entry. An empty response with HTTP Status 304 will be send if we weren't able to update :param entry: \w+ an integer The Entry ID
the content (because it hasn't changed or we got an error). :return data related to the ext
:param entry: \w+ an integer The Entry ID
:return data related to the ext
""" """
params = {'access_token': self.token} params = {'access_token': self.token}
url = '/api/entries/{entry}/reload.{ext}'.format(entry=entry, url = '/api/entries/{entry}/reload.{ext}'.format(entry=entry,
ext=self.format) ext=self.format)
return self.query(url, "patch", **params) return await self.query(url, "patch", **params)
def delete_entries(self, entry): async def delete_entries(self, entry):
""" """
DELETE /api/entries/{entry}.{_format}
DELETE /api/entries/{entry}.{_format} Delete permanently an entry
Delete permanently an entry :param entry: \w+ an integer The Entry ID
:return result
:param entry: \w+ an integer The Entry ID
:return result
""" """
params = {'Authorization': 'Bearer {}'.format(self.token)} params = {'Authorization': 'Bearer {}'.format(self.token)}
path = '/api/entries/{entry}.{ext}'.format( path = '/api/entries/{entry}.{ext}'.format(
entry=entry, ext=self.format) entry=entry, ext=self.format)
return self.query(path, "delete", **params) return await self.query(path, "delete", **params)
def entries_exists(self, url, urls=''): async def entries_exists(self, url, urls=''):
""" """
GET /api/entries/exists.{_format}
GET /api/entries/exists.{_format} Check if an entry exist by url.
Check if an entry exist by url. :param url string true An url Url to check if it exists
:param urls string false An array of urls
(?urls[]=http...&urls[]=http...) Urls (as an array)
to check if it exists
:param url string true An url Url to check if it exists :return result
:param urls string false An array of urls (?urls[]=http...&urls[]=http...)
Urls (as an array) to check if it exists
:return result
""" """
params = {'url': url, params = {'url': url,
'urls': urls} 'urls': urls}
path = '/api/entries/exists.{ext}'.format(ext=self.format) path = '/api/entries/exists.{ext}'.format(ext=self.format)
return self.query(path, "get", **params) return await self.query(path, "get", **params)
# TAGS # TAGS
def get_entry_tags(self, entry): async def get_entry_tags(self, entry):
""" """
GET /api/entries/{entry}/tags.{_format}
GET /api/entries/{entry}/tags.{_format} Retrieve all tags for an entry
Retrieve all tags for an entry :param entry: \w+ an integer The Entry ID
:return data related to the ext
:param entry: \w+ an integer The Entry ID
:return data related to the ext
""" """
params = {'access_token': self.token} params = {'access_token': self.token}
url = '/api/entries/{entry}/tags.{ext}'.format( url = '/api/entries/{entry}/tags.{ext}'.format(
entry=entry, ext=self.format) entry=entry, ext=self.format)
return self.query(url, "get", **params) return await self.query(url, "get", **params)
def post_entry_tags(self, entry, tags): async def post_entry_tags(self, entry, tags):
""" """
POST /api/entries/{entry}/tags.{_format}
POST /api/entries/{entry}/tags.{_format} Add one or more tags to an entry
Add one or more tags to an entry :param entry: \w+ an integer The Entry ID
:param tags: string
:param entry: \w+ an integer The Entry ID :return result
:param tags: string
:return result
""" """
params = {'access_token': self.token, 'tags': []} params = {'access_token': self.token, 'tags': []}
if len(tags) > 0 and ',' in tags: if len(tags) > 0 and ',' in tags:
params['tags'] = tags.split(',') params['tags'] = tags.split(',')
path = '/api/entries/{entry}/tags.{ext}'.format( path = '/api/entries/{entry}/tags.{ext}'.format(
entry=entry, ext=self.format) entry=entry, ext=self.format)
return self.query(path, "post", **params) return await self.query(path, "post", **params)
def delete_entry_tag(self, entry, tag): async def delete_entry_tag(self, entry, tag):
""" """
DELETE /api/entries/{entry}/tags/{tag}.{_format}
DELETE /api/entries/{entry}/tags/{tag}.{_format} Permanently remove one tag for an entry
Permanently remove one tag for an entry :param entry: \w+ an integer The Entry ID
:param tag: string The Tag
:param entry: \w+ an integer The Entry ID :return data related to the ext
:param tag: string The Tag
:return data related to the ext
""" """
params = {'access_token': self.token} params = {'access_token': self.token}
url = '/api/entries/{entry}/tags/{tag}.{ext}'.format( url = '/api/entries/{entry}/tags/{tag}.{ext}'.format(
entry=entry, tag=tag, ext=self.format) entry=entry, tag=tag, ext=self.format)
return self.query(url, "delete", **params) return await self.query(url, "delete", **params)
def get_tags(self): async def get_tags(self):
""" """
GET /api/tags.{_format}
GET /api/tags.{_format} Retrieve all tags
Retrieve all tags :return data related to the ext
:return data related to the ext
""" """
params = {'access_token': self.token} params = {'access_token': self.token}
path = '/api/tags.{ext}'.format(ext=self.format) path = '/api/tags.{ext}'.format(ext=self.format)
return self.query(path, "get", **params) return await self.query(path, "get", **params)
def delete_tag(self, tag): async def delete_tag(self, tag):
""" """
DELETE /api/tags/{tag}.{_format}
DELETE /api/tags/{tag}.{_format} Permanently remove one tag from every entry
Permanently remove one tag from every entry :param tag: string The Tag
:return data related to the ext
:param tag: string The Tag
:return data related to the ext
""" """
path = '/api/tags/{tag}.{ext}'.format(tag=tag, ext=self.format) path = '/api/tags/{tag}.{ext}'.format(tag=tag, ext=self.format)
params = {'access_token': self.token} params = {'access_token': self.token}
return self.query(path, "delete", **params) return await self.query(path, "delete", **params)
def delete_tag_label(self, tag): async def delete_tag_label(self, tag):
""" """
DELETE /api/tag/label.{_format}
DELETE /api/tag/label.{_format} Permanently remove one tag from every entry.
Permanently remove one tag from every entry. :param tag: string The Tag
:return data related to the ext
:param tag: string The Tag
:return data related to the ext
""" """
# @TODO check if that method is well documented as its the same as delete_tags !
path = '/api/tag/label.{ext}'.format(ext=self.format) path = '/api/tag/label.{ext}'.format(ext=self.format)
params = {'access_token': self.token, params = {'access_token': self.token,
'tag': tag} 'tag': tag}
return self.query(path, "delete", **params) return await self.query(path, "delete", **params)
def delete_tags_label(self, tags): async def delete_tags_label(self, tags):
""" """
DELETE /api/tags/label.{_format}
DELETE /api/tags/label.{_format} Permanently remove some tags from every entry.
Permanently remove some tags from every entry. :param tags: string tags as strings (comma splitted)
:return data related to the ext
:param tags: string tags as strings (comma splitted)
:return data related to the ext
""" """
# @TODO check if that method is well documented as its the same as delete_tags !
path = '/api/tag/label.{ext}'.format(ext=self.format) path = '/api/tag/label.{ext}'.format(ext=self.format)
params = {'access_token': self.token, params = {'access_token': self.token,
'tags': tags} 'tags': tags}
return self.query(path, "delete", **params) return await self.query(path, "delete", **params)
# ANNOTATIONS # ANNOTATIONS
def delete_annotations(self, annotation): async def delete_annotations(self, annotation):
""" """
DELETE /api/annotations/{annotation}.{_format}
DELETE /api/annotations/{annotation}.{_format} Removes an annotation.
Removes an annotation. :param annotation \w+ string The annotation ID
:param annotation \w+ string The annotation ID Will returns annotation for this entry
:return data related to the ext
Will returns annotation for this entry
:return data related to the ext
""" """
params = {'access_token': self.token} params = {'access_token': self.token}
url = '/api/annotations/{annotation}.{ext}'.format( url = '/api/annotations/{annotation}.{ext}'.format(
annotation=annotation, ext=self.format) annotation=annotation, ext=self.format)
return self.query(url, "delete", **params) return await self.query(url, "delete", **params)
def put_annotations(self, annotation): async def put_annotations(self, annotation):
""" """
PUT /api/annotations/{annotation}.{_format}
PUT /api/annotations/{annotation}.{_format} Updates an annotation.
Updates an annotation. :param annotation \w+ string The annotation ID
:param annotation \w+ string The annotation ID Will returns annotation for this entry
:return data related to the ext
Will returns annotation for this entry
:return data related to the ext
""" """
params = {'access_token': self.token} params = {'access_token': self.token}
url = '/api/annotations/{annotation}.{ext}'.format( url = '/api/annotations/{annotation}.{ext}'.format(
annotation=annotation, ext=self.format) annotation=annotation, ext=self.format)
return self.query(url, "put", **params) return await self.query(url, "put", **params)
def get_annotations(self, entry): async def get_annotations(self, entry):
""" """
GET /api/annotations/{entry}.{_format}
GET /api/annotations/{entry}.{_format} Retrieve annotations for an entry
Retrieve annotations for an entry :param entry \w+ integer The entry ID
:param entry \w+ integer The entry ID Will returns annotation for this entry
:return data related to the ext
Will returns annotation for this entry
:return data related to the ext
""" """
params = {'access_token': self.token} params = {'access_token': self.token}
url = '/api/annotations/{entry}.{ext}'.format(entry=entry, url = '/api/annotations/{entry}.{ext}'.format(entry=entry,
ext=self.format) ext=self.format)
return self.query(url, "get", **params) return await self.query(url, "get", **params)
def post_annotations(self, entry, **kwargs): async def post_annotations(self, entry, **kwargs):
""" """
POST /api/annotations/{entry}.{_format}
POST /api/annotations/{entry}.{_format} Creates a new annotation.
Creates a new annotation. :param entry \w+ integer The entry ID
:param entry \w+ integer The entry ID :return
:return
""" """
params = dict({'access_token': self.token, params = dict({'access_token': self.token,
'ranges': [], 'ranges': [],
@@ -528,26 +508,29 @@ class Wallabag(object):
url = '/api/annotations/{entry}.{ext}'.format(entry=entry, url = '/api/annotations/{entry}.{ext}'.format(entry=entry,
ext=self.format) ext=self.format)
return self.query(url, "post", **params) return await self.query(url, "post", **params)
# VERSION # VERSION
@property @property
def version(self): async def version(self):
""" """
GET /api/version.{_format}
GET /api/version.{_format} Retrieve version number
Retrieve version number :return data related to the ext
:return data related to the ext
""" """
params = {'access_token': self.token} params = {'access_token': self.token}
url = '/api/version.{ext}'.format(ext=self.format) url = '/api/version.{ext}'.format(ext=self.format)
return self.query(url, "get", **params) return await self.query(url, "get", **params)
@classmethod @classmethod
def get_token(cls, host, **params): async def get_token(cls, host, **params):
""" """
POST /oauth/v2/token
Get a new token
:param host: host of the service :param host: host of the service
:param params: will contain : :param params: will contain :
@@ -559,7 +542,9 @@ class Wallabag(object):
:return: access token :return: access token
""" """
params['grant_type'] = ["password"] params['grant_type'] = "password"
path = "/oauth/v2/token" path = "/oauth/v2/token"
r = requests.post(host + path, data=params) async with aiohttp.ClientSession() as sess:
return cls.handle_json_response(r)['access_token'] async with sess.post(host + path, data=params) as resp:
data = await cls.handle_json_response(resp)
return data.get("access_token")