3 Commits
1.1.0 ... 1.1.3

Author SHA1 Message Date
FoxMaSk
e892d3ceeb upd few things 2018-04-18 11:07:46 +02:00
FoxMaSk
e52b8befe4 upd few things 2018-04-18 11:07:23 +02:00
FoxMaSk
259f62efd9 last wallagab api - with requests 2017-09-24 22:35:20 +02:00
6 changed files with 262 additions and 97 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.idea

View File

@@ -7,8 +7,7 @@ Python API for Wallabag v2
Requirements : Requirements :
============== ==============
* requests 2.5.0 * requests
Installation: Installation:
============= =============

View File

@@ -2,18 +2,19 @@ from setuptools import setup, find_packages
from wallabag_api import __version__ as version from wallabag_api import __version__ as version
install_requires = [ install_requires = [
'requests==2.5.0', 'requests',
] ]
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='Wallabag API to add every pages you want to your Wallabag account',
long_desc='Wallabag is a "read it later" service, and that Wallabag API allow you to save web pages '
'to your own account',
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/push-things/wallabag_api',
download_url="https://github.com/foxmask/wallabag_api/archive/" download_url="https://github.com/push-things/wallabag_api/archive/wallabag_api-" + version + ".zip",
"wallabag_api-" + version + ".zip",
packages=find_packages(), packages=find_packages(),
classifiers=[ classifiers=[
'Development Status :: 4 - Beta', 'Development Status :: 4 - Beta',
@@ -23,6 +24,7 @@ setup(
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Internet', 'Topic :: Internet',
'Topic :: Communications', 'Topic :: Communications',
], ],

View File

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

View File

@@ -16,7 +16,7 @@ class Wallabag(object):
Python Class 'Wallabag' to deal with Wallabag REST API Python Class 'Wallabag' to deal with Wallabag REST API
This class is able to handle any data from your Wallabag account This class is able to handle any data from your Wallabag account
""" """
EXTENTIONS = ('xml', 'json', 'txt', 'csv', 'pdf', 'epub', 'mobi', 'html')
host = '' host = ''
token = '' token = ''
client_id = '' client_id = ''
@@ -40,7 +40,7 @@ class Wallabag(object):
: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: json/xml/html :param extension: xml|json|txt|csv|pdf|epub|mobi|html
:param user_agent :param user_agent
""" """
self.host = host self.host = host
@@ -50,6 +50,10 @@ class Wallabag(object):
self.format = extension self.format = extension
self.user_agent = user_agent self.user_agent = user_agent
if self.format not in self.EXTENTIONS:
raise ValueError("format invalid {0} should be one of {1}".format(
self.format, self.EXTENTIONS))
def get_host(self): def get_host(self):
""" """
get the host from which to get API get the host from which to get API
@@ -88,9 +92,13 @@ class Wallabag(object):
: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:
raise HTTPError(responses.status_code, responses.json())
json_data = {} json_data = {}
if responses.status_code != 200:
err_msg = HTTPError(responses.status_code, responses.reason)
msg = "Wallabag: error {err_msg}".format(err_msg=err_msg)
logging.error(msg)
raise HTTPError(msg)
else:
try: try:
json_data = responses.json() json_data = responses.json()
except: except:
@@ -99,6 +107,7 @@ class Wallabag(object):
logging.error("Wallabag: {error}".format(error=error_json)) logging.error("Wallabag: {error}".format(error=error_json))
return json_data return json_data
# ENTRIES
def get_entries(self, **kwargs): def get_entries(self, **kwargs):
""" """
@@ -150,7 +159,6 @@ class Wallabag(object):
def post_entries(self, url, title='', tags='', starred=0, archive=0): 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
@@ -171,7 +179,6 @@ class Wallabag(object):
def get_entry(self, entry): def get_entry(self, entry):
""" """
GET /api/entries/{entry}.{_format} GET /api/entries/{entry}.{_format}
Retrieve a single entry Retrieve a single entry
@@ -185,7 +192,6 @@ class Wallabag(object):
def patch_entries(self, entry, **kwargs): 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
@@ -207,6 +213,7 @@ class Wallabag(object):
'tags': [], 'tags': [],
'star': 0, 'star': 0,
'delete': 0} 'delete': 0}
if 'title' in kwargs: if 'title' in kwargs:
params['title'] = kwargs['title'] params['title'] = kwargs['title']
if 'tags' in kwargs and isinstance(kwargs['tags'], list): if 'tags' in kwargs and isinstance(kwargs['tags'], list):
@@ -221,9 +228,38 @@ class Wallabag(object):
entry=entry, ext=self.format) entry=entry, ext=self.format)
return self.query(path, "patch", **params) return self.query(path, "patch", **params)
def get_entry_export(self, entry):
"""
GET /api/entries/{entry}/export.{_format}
Retrieve a single entry as a predefined format.
:param entry: \w+ an integer The Entry ID
:return data related to the ext
"""
params = {'access_token': self.token}
url = '/api/entries/{entry}/export.{ext}'.format(entry=entry,
ext=self.format)
return self.query(url, "get", **params)
def patch_entry_reload(self, entry):
"""
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).
:param entry: \w+ an integer The Entry ID
:return data related to the ext
"""
params = {'access_token': self.token}
url = '/api/entries/{entry}/reload.{ext}'.format(entry=entry,
ext=self.format)
return self.query(url, "patch", **params)
def delete_entries(self, entry): def delete_entries(self, entry):
""" """
DELETE /api/entries/{entry}.{_format} DELETE /api/entries/{entry}.{_format}
Delete permanently an entry Delete permanently an entry
@@ -237,9 +273,28 @@ class Wallabag(object):
entry=entry, ext=self.format) entry=entry, ext=self.format)
return self.query(path, "delete", **params) return self.query(path, "delete", **params)
def entries_exists(self, url, urls=''):
"""
GET /api/entries/exists.{_format}
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
:return result
"""
params = {'url': url,
'urls': urls}
path = '/api/entries/exists.{ext}'.format(ext=self.format)
return self.query(path, "get", **params)
# TAGS
def get_entry_tags(self, entry): 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
@@ -254,7 +309,6 @@ class Wallabag(object):
def post_entry_tags(self, entry, tags): 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
@@ -272,7 +326,6 @@ class Wallabag(object):
def delete_entry_tag(self, entry, tag): 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
@@ -288,7 +341,6 @@ class Wallabag(object):
def get_tags(self): def get_tags(self):
""" """
GET /api/tags.{_format} GET /api/tags.{_format}
Retrieve all tags Retrieve all tags
@@ -301,7 +353,6 @@ class Wallabag(object):
def delete_tag(self, tag): 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
@@ -313,9 +364,129 @@ class Wallabag(object):
params = {'access_token': self.token} params = {'access_token': self.token}
return self.query(path, "delete", **params) return self.query(path, "delete", **params)
def delete_tag_label(self, tag):
"""
DELETE /api/tag/label.{_format}
Permanently remove one tag from every entry.
:param tag: string The Tag
:return data related to the ext
"""
path = '/api/tag/label.{ext}'.format(ext=self.format)
params = {'access_token': self.token,
'tag': tag}
return self.query(path, "delete", **params)
def delete_tags_label(self, tags):
"""
DELETE /api/tags/label.{_format}
Permanently remove some tags from every entry.
:param tags: string tags as strings (comma splitted)
:return data related to the ext
"""
path = '/api/tag/label.{ext}'.format(ext=self.format)
params = {'access_token': self.token,
'tags': tags}
return self.query(path, "delete", **params)
# ANNOTATIONS
def delete_annotations(self, annotation):
"""
DELETE /api/annotations/{annotation}.{_format}
Removes an annotation.
:param annotation \w+ string The annotation ID
Will returns annotation for this entry
:return data related to the ext
"""
params = {'access_token': self.token}
url = '/api/annotations/{annotation}.{ext}'.format(
annotation=annotation, ext=self.format)
return self.query(url, "delete", **params)
def put_annotations(self, annotation):
"""
PUT /api/annotations/{annotation}.{_format}
Updates an annotation.
:param annotation \w+ string The annotation ID
Will returns annotation for this entry
:return data related to the ext
"""
params = {'access_token': self.token}
url = '/api/annotations/{annotation}.{ext}'.format(
annotation=annotation, ext=self.format)
return self.query(url, "put", **params)
def get_annotations(self, entry):
"""
GET /api/annotations/{entry}.{_format}
Retrieve annotations for an entry
:param entry \w+ integer The entry ID
Will returns annotation for this entry
:return data related to the ext
"""
params = {'access_token': self.token}
url = '/api/annotations/{entry}.{ext}'.format(entry=entry,
ext=self.format)
return self.query(url, "get", **params)
def post_annotations(self, entry, **kwargs):
"""
POST /api/annotations/{entry}.{_format}
Creates a new annotation.
:param entry \w+ integer The entry ID
:return
"""
params = dict({'access_token': self.token,
'ranges': [],
'quote': '',
'text': ''})
if 'ranges' in kwargs:
params['ranges'] = kwargs['ranges']
if 'quote' in kwargs:
params['quote'] = kwargs['quote']
if 'text' in kwargs:
params['text'] = kwargs['text']
url = '/api/annotations/{entry}.{ext}'.format(entry=entry,
ext=self.format)
return self.query(url, "post", **params)
# VERSION
@property
def version(self):
"""
GET /api/version.{_format}
Retrieve version number
:return data related to the ext
"""
params = {'access_token': self.token}
url = '/api/version.{ext}'.format(ext=self.format)
return self.query(url, "get", **params)
@classmethod @classmethod
def get_token(cls, host, **params): 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 :
@@ -327,7 +498,8 @@ 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) resp = requests.post(host + path, data=params)
return cls.handle_json_response(r)['access_token'] data = cls.handle_json_response(resp)
return data.get('access_token')

View File

@@ -5,7 +5,7 @@ from wallabag import Wallabag
class TestWallabag(unittest.TestCase): class TestWallabag(unittest.TestCase):
host = 'http://localhost:8080' host = 'http://bag.foxmask'
client_id = '' client_id = ''
client_secret = '' client_secret = ''
token = '' token = ''
@@ -20,18 +20,18 @@ class TestWallabag(unittest.TestCase):
def test_get_token(self): def test_get_token(self):
params = {"grant_type": "password", params = {"grant_type": "password",
"client_id": '1_37e16ub8a62oc4gwcg0o0wssks800kw0ok408kkwo4kosgc88g', "client_id": '1_3to3042y05gk8g4wcsk40w40k8kk00s04gwcoo4sows8wskcg0',
"client_secret": '49etxpn66da8okg4cs40sswsog0sskwg4woc400c4w4w8s4wo4', "client_secret": 'ift9k07vd20ccg4ocosg0cw4kkgk4o8080848scwg0oosowow',
"username": 'foxmask', "username": 'foxmask',
"password": 'ratatab00m'} "password": 'ratatab00m'}
data = Wallabag.get_token(host='http://localhost:8080', **params) data = Wallabag.get_token(host=self.host, **params)
self.assertTrue(isinstance(data, str), True) self.assertTrue(isinstance(data, str), True)
return data return data
def create_entry(self): def create_entry(self):
title = 'foobar title' title = 'foobar title'
url = 'https://smcomm.trigger-happy.eu/' url = 'https://trigger-happy.eu/'
tags = ['foo', 'bar'] tags = ['foo', 'bar']
starred = 0 starred = 0
archive = 0 archive = 0
@@ -96,15 +96,6 @@ class TestWallabag(unittest.TestCase):
data = self.w.post_entry_tags(entry, tags) data = self.w.post_entry_tags(entry, tags)
self.assertTrue(data, True) self.assertTrue(data, True)
"""
def test_delete_entry_tag(self):
entry = self.create_entry()
tag = 'bar'
self.assertTrue(isinstance(entry['id'], int), True)
self.assertTrue(isinstance(tag, str), True)
resp = self.w.delete_entry_tag(entry['id'], tag)
self.assertTrue(resp, True)
"""
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()