Merge branch 'release-0.5'
This commit is contained in:
commit
ed5cc0ac11
20 changed files with 523 additions and 107 deletions
|
@ -7,8 +7,9 @@ install:
|
||||||
script: tox
|
script: tox
|
||||||
|
|
||||||
after_script:
|
after_script:
|
||||||
|
# Install dependencies for Pylint
|
||||||
|
- pip install requests requests-oauthlib
|
||||||
|
|
||||||
# Run Pylint
|
# Run Pylint
|
||||||
# (for information only, any errors don't affect the Travis result)
|
# (for information only, any errors don't affect the Travis result)
|
||||||
- pylint --use-ignore-patch=y openphoto
|
- pylint --use-ignore-patch=y trovebox
|
||||||
- pylint --use-ignore-patch=y tests
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
# Until the --use-ignore-patch makes it into pylint upstream, we need to
|
# Until the --use-ignore-patch makes it into pylint upstream, we need to
|
||||||
# download and install from sneakypete81's pylint fork
|
# download and install from sneakypete81's pylint fork
|
||||||
HG_HASH=16de8b9518be
|
|
||||||
|
|
||||||
wget https://bitbucket.org/sneakypete81/pylint/get/$HG_HASH.zip
|
wget https://bitbucket.org/sneakypete81/pylint/get/use_ignore_patch.zip
|
||||||
unzip $HG_HASH.zip
|
unzip use_ignore_patch.zip
|
||||||
cd sneakypete81-pylint-$HG_HASH
|
cd sneakypete81-pylint-*
|
||||||
python setup.py install
|
python setup.py install
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
rm -r sneakypete81-pylint-$HG_HASH
|
rm -r sneakypete81-pylint-*
|
||||||
|
|
25
CHANGELOG
Normal file
25
CHANGELOG
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
=================================
|
||||||
|
Trovebox Python Library Changelog
|
||||||
|
=================================
|
||||||
|
|
||||||
|
v0.5
|
||||||
|
====
|
||||||
|
* Pylint improvements - using .pylint-ignores to waive warnings (#49)
|
||||||
|
* Add support for https URLs (#51)
|
||||||
|
* Configuration improvements (#53)
|
||||||
|
* Allow https SSL verification bypass (#50)
|
||||||
|
* Test improvements (#54)
|
||||||
|
|
||||||
|
v0.4
|
||||||
|
====
|
||||||
|
|
||||||
|
First release
|
||||||
|
|
||||||
|
* Added more unit tests (#44, #45)
|
||||||
|
* Fixed consistency problems found with unit tests (#46)
|
||||||
|
* Renamed to Trovebox (#48)
|
||||||
|
* Packaged for PyPI:
|
||||||
|
- Updated metadata
|
||||||
|
- Store the version number inside the package, and add --version CLI option
|
||||||
|
- Update README and convert to ReStructuredText, as required by PyPI
|
||||||
|
|
1
MANIFEST.in
Normal file
1
MANIFEST.in
Normal file
|
@ -0,0 +1 @@
|
||||||
|
include README.rst
|
13
README.rst
13
README.rst
|
@ -3,7 +3,7 @@ Trovebox Python Library
|
||||||
=======================
|
=======================
|
||||||
(Previously known as openphoto-python)
|
(Previously known as openphoto-python)
|
||||||
|
|
||||||
.. image:: https://api.travis-ci.org/photo/openphoto-python.png
|
.. image:: https://travis-ci.org/photo/openphoto-python.png?branch=master
|
||||||
:alt: Build Status
|
:alt: Build Status
|
||||||
:target: https://travis-ci.org/photo/openphoto-python
|
:target: https://travis-ci.org/photo/openphoto-python
|
||||||
|
|
||||||
|
@ -77,11 +77,16 @@ API Versioning
|
||||||
==============
|
==============
|
||||||
It may be useful to lock your application to a particular version of the Trovebox API.
|
It may be useful to lock your application to a particular version of the Trovebox API.
|
||||||
This ensures that future API updates won't cause unexpected breakages.
|
This ensures that future API updates won't cause unexpected breakages.
|
||||||
|
To do this, configure your Trovebox client as follows::
|
||||||
|
|
||||||
To do this, add the optional ``api_version`` parameter when creating the client object::
|
client.configure(api_version=2)
|
||||||
|
|
||||||
from trovebox import Trovebox
|
SSL Verification
|
||||||
client = Trovebox(api_version=2)
|
================
|
||||||
|
If you connect to your Trovebox server over HTTPS, its SSL certificate is automatically verified.
|
||||||
|
You can configure your Trovebox client to bypass this verification step::
|
||||||
|
|
||||||
|
client.configure(ssl_verify=False)
|
||||||
|
|
||||||
Commandline Tool
|
Commandline Tool
|
||||||
================
|
================
|
||||||
|
|
|
@ -12,6 +12,7 @@ They run very quickly and don't require any external test hosts.
|
||||||
#### Requirements
|
#### Requirements
|
||||||
* mock >= 1.0.0
|
* mock >= 1.0.0
|
||||||
* httpretty >= 0.6.1
|
* httpretty >= 0.6.1
|
||||||
|
* ddt >= 0.3.0
|
||||||
* tox (optional)
|
* tox (optional)
|
||||||
|
|
||||||
#### Running the Unit Tests
|
#### Running the Unit Tests
|
||||||
|
|
|
@ -10,7 +10,7 @@ from trovebox import Trovebox
|
||||||
CONFIG_HOME_PATH = os.path.join("tests", "config")
|
CONFIG_HOME_PATH = os.path.join("tests", "config")
|
||||||
CONFIG_PATH = os.path.join(CONFIG_HOME_PATH, "trovebox")
|
CONFIG_PATH = os.path.join(CONFIG_HOME_PATH, "trovebox")
|
||||||
|
|
||||||
class TestConfig(unittest.TestCase):
|
class TestAuth(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
""" Override XDG_CONFIG_HOME env var, to use test configs """
|
""" Override XDG_CONFIG_HOME env var, to use test configs """
|
||||||
try:
|
try:
|
||||||
|
@ -42,47 +42,47 @@ class TestConfig(unittest.TestCase):
|
||||||
""" Ensure the default config is loaded """
|
""" Ensure the default config is loaded """
|
||||||
self.create_config("default", "Test Default Host")
|
self.create_config("default", "Test Default Host")
|
||||||
client = Trovebox()
|
client = Trovebox()
|
||||||
config = client.config
|
auth = client.auth
|
||||||
self.assertEqual(client.host, "Test Default Host")
|
self.assertEqual(client.host, "Test Default Host")
|
||||||
self.assertEqual(config.consumer_key, "default_consumer_key")
|
self.assertEqual(auth.consumer_key, "default_consumer_key")
|
||||||
self.assertEqual(config.consumer_secret, "default_consumer_secret")
|
self.assertEqual(auth.consumer_secret, "default_consumer_secret")
|
||||||
self.assertEqual(config.token, "default_token")
|
self.assertEqual(auth.token, "default_token")
|
||||||
self.assertEqual(config.token_secret, "default_token_secret")
|
self.assertEqual(auth.token_secret, "default_token_secret")
|
||||||
|
|
||||||
def test_custom_config(self):
|
def test_custom_config(self):
|
||||||
""" Ensure a custom config can be loaded """
|
""" Ensure a custom config can be loaded """
|
||||||
self.create_config("default", "Test Default Host")
|
self.create_config("default", "Test Default Host")
|
||||||
self.create_config("custom", "Test Custom Host")
|
self.create_config("custom", "Test Custom Host")
|
||||||
client = Trovebox(config_file="custom")
|
client = Trovebox(config_file="custom")
|
||||||
config = client.config
|
auth = client.auth
|
||||||
self.assertEqual(client.host, "Test Custom Host")
|
self.assertEqual(client.host, "Test Custom Host")
|
||||||
self.assertEqual(config.consumer_key, "custom_consumer_key")
|
self.assertEqual(auth.consumer_key, "custom_consumer_key")
|
||||||
self.assertEqual(config.consumer_secret, "custom_consumer_secret")
|
self.assertEqual(auth.consumer_secret, "custom_consumer_secret")
|
||||||
self.assertEqual(config.token, "custom_token")
|
self.assertEqual(auth.token, "custom_token")
|
||||||
self.assertEqual(config.token_secret, "custom_token_secret")
|
self.assertEqual(auth.token_secret, "custom_token_secret")
|
||||||
|
|
||||||
def test_full_config_path(self):
|
def test_full_config_path(self):
|
||||||
""" Ensure a full custom config path can be loaded """
|
""" Ensure a full custom config path can be loaded """
|
||||||
self.create_config("path", "Test Path Host")
|
self.create_config("path", "Test Path Host")
|
||||||
full_path = os.path.abspath(CONFIG_PATH)
|
full_path = os.path.abspath(CONFIG_PATH)
|
||||||
client = Trovebox(config_file=os.path.join(full_path, "path"))
|
client = Trovebox(config_file=os.path.join(full_path, "path"))
|
||||||
config = client.config
|
auth = client.auth
|
||||||
self.assertEqual(client.host, "Test Path Host")
|
self.assertEqual(client.host, "Test Path Host")
|
||||||
self.assertEqual(config.consumer_key, "path_consumer_key")
|
self.assertEqual(auth.consumer_key, "path_consumer_key")
|
||||||
self.assertEqual(config.consumer_secret, "path_consumer_secret")
|
self.assertEqual(auth.consumer_secret, "path_consumer_secret")
|
||||||
self.assertEqual(config.token, "path_token")
|
self.assertEqual(auth.token, "path_token")
|
||||||
self.assertEqual(config.token_secret, "path_token_secret")
|
self.assertEqual(auth.token_secret, "path_token_secret")
|
||||||
|
|
||||||
def test_host_override(self):
|
def test_host_override(self):
|
||||||
""" Ensure that specifying a host overrides the default config """
|
""" Ensure that specifying a host overrides the default config """
|
||||||
self.create_config("default", "Test Default Host")
|
self.create_config("default", "Test Default Host")
|
||||||
client = Trovebox(host="host_override")
|
client = Trovebox(host="host_override")
|
||||||
config = client.config
|
auth = client.auth
|
||||||
self.assertEqual(config.host, "host_override")
|
self.assertEqual(auth.host, "host_override")
|
||||||
self.assertEqual(config.consumer_key, "")
|
self.assertEqual(auth.consumer_key, "")
|
||||||
self.assertEqual(config.consumer_secret, "")
|
self.assertEqual(auth.consumer_secret, "")
|
||||||
self.assertEqual(config.token, "")
|
self.assertEqual(auth.token, "")
|
||||||
self.assertEqual(config.token_secret, "")
|
self.assertEqual(auth.token_secret, "")
|
||||||
|
|
||||||
def test_missing_config_files(self):
|
def test_missing_config_files(self):
|
||||||
""" Ensure that missing config files raise exceptions """
|
""" Ensure that missing config files raise exceptions """
|
|
@ -1,7 +1,10 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import mock
|
||||||
import httpretty
|
import httpretty
|
||||||
|
from httpretty import GET, POST
|
||||||
|
from ddt import ddt, data
|
||||||
try:
|
try:
|
||||||
import unittest2 as unittest # Python2.6
|
import unittest2 as unittest # Python2.6
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -9,6 +12,21 @@ except ImportError:
|
||||||
|
|
||||||
import trovebox
|
import trovebox
|
||||||
|
|
||||||
|
class GetOrPost(object):
|
||||||
|
"""Helper class to call the correct (GET/POST) method"""
|
||||||
|
def __init__(self, client, method):
|
||||||
|
self.client = client
|
||||||
|
self.method = method
|
||||||
|
|
||||||
|
def call(self, *args, **kwds):
|
||||||
|
if self.method == GET:
|
||||||
|
return self.client.get(*args, **kwds)
|
||||||
|
elif self.method == POST:
|
||||||
|
return self.client.post(*args, **kwds)
|
||||||
|
else:
|
||||||
|
raise ValueError("unknown method: %s" % self.method)
|
||||||
|
|
||||||
|
@ddt
|
||||||
class TestHttp(unittest.TestCase):
|
class TestHttp(unittest.TestCase):
|
||||||
test_host = "test.example.com"
|
test_host = "test.example.com"
|
||||||
test_endpoint = "test.json"
|
test_endpoint = "test.json"
|
||||||
|
@ -44,7 +62,55 @@ class TestHttp(unittest.TestCase):
|
||||||
def test_attributes(self):
|
def test_attributes(self):
|
||||||
"""Check that the host attribute has been set correctly"""
|
"""Check that the host attribute has been set correctly"""
|
||||||
self.assertEqual(self.client.host, self.test_host)
|
self.assertEqual(self.client.host, self.test_host)
|
||||||
self.assertEqual(self.client.config.host, self.test_host)
|
self.assertEqual(self.client.auth.host, self.test_host)
|
||||||
|
|
||||||
|
@httpretty.activate
|
||||||
|
@data(GET, POST)
|
||||||
|
def test_http_scheme(self, method):
|
||||||
|
"""Check that we can access hosts starting with 'http://'"""
|
||||||
|
self._register_uri(method,
|
||||||
|
uri="http://test.example.com/%s" % self.test_endpoint)
|
||||||
|
|
||||||
|
self.client = trovebox.Trovebox(host="http://test.example.com",
|
||||||
|
**self.test_oauth)
|
||||||
|
response = GetOrPost(self.client, method).call(self.test_endpoint)
|
||||||
|
self.assertIn("OAuth", self._last_request().headers["authorization"])
|
||||||
|
self.assertEqual(response, self.test_data)
|
||||||
|
self.assertEqual(self.client.last_url,
|
||||||
|
"http://test.example.com/%s" % self.test_endpoint)
|
||||||
|
self.assertEqual(self.client.last_response.json(), self.test_data)
|
||||||
|
|
||||||
|
@httpretty.activate
|
||||||
|
@data(GET, POST)
|
||||||
|
def test_no_scheme(self, method):
|
||||||
|
"""Check that we can access hosts without a 'http://' prefix"""
|
||||||
|
self._register_uri(method,
|
||||||
|
uri="http://test.example.com/%s" % self.test_endpoint)
|
||||||
|
|
||||||
|
self.client = trovebox.Trovebox(host="test.example.com",
|
||||||
|
**self.test_oauth)
|
||||||
|
response = GetOrPost(self.client, method).call(self.test_endpoint)
|
||||||
|
self.assertIn("OAuth", self._last_request().headers["authorization"])
|
||||||
|
self.assertEqual(response, self.test_data)
|
||||||
|
self.assertEqual(self.client.last_url,
|
||||||
|
"http://test.example.com/%s" % self.test_endpoint)
|
||||||
|
self.assertEqual(self.client.last_response.json(), self.test_data)
|
||||||
|
|
||||||
|
@httpretty.activate
|
||||||
|
@data(GET, POST)
|
||||||
|
def test_https_scheme(self, method):
|
||||||
|
"""Check that we can access hosts starting with 'https://'"""
|
||||||
|
self._register_uri(method,
|
||||||
|
uri="https://test.example.com/%s" % self.test_endpoint)
|
||||||
|
|
||||||
|
self.client = trovebox.Trovebox(host="https://test.example.com",
|
||||||
|
**self.test_oauth)
|
||||||
|
response = GetOrPost(self.client, method).call(self.test_endpoint)
|
||||||
|
self.assertIn("OAuth", self._last_request().headers["authorization"])
|
||||||
|
self.assertEqual(response, self.test_data)
|
||||||
|
self.assertEqual(self.client.last_url,
|
||||||
|
"https://test.example.com/%s" % self.test_endpoint)
|
||||||
|
self.assertEqual(self.client.last_response.json(), self.test_data)
|
||||||
|
|
||||||
@httpretty.activate
|
@httpretty.activate
|
||||||
def test_get_with_parameters(self):
|
def test_get_with_parameters(self):
|
||||||
|
@ -93,17 +159,12 @@ class TestHttp(unittest.TestCase):
|
||||||
self.client.post(self.test_endpoint)
|
self.client.post(self.test_endpoint)
|
||||||
|
|
||||||
@httpretty.activate
|
@httpretty.activate
|
||||||
def test_get_without_response_processing(self):
|
@data(GET, POST)
|
||||||
"""Check that the get method works with response processing disabled"""
|
def test_no_response_processing(self, method):
|
||||||
self._register_uri(httpretty.GET)
|
"""Check that get/post methods work with response processing disabled"""
|
||||||
response = self.client.get(self.test_endpoint, process_response=False)
|
self._register_uri(method)
|
||||||
self.assertEqual(response, json.dumps(self.test_data))
|
response = GetOrPost(self.client, method).call(self.test_endpoint,
|
||||||
|
process_response=False)
|
||||||
@httpretty.activate
|
|
||||||
def test_post_without_response_processing(self):
|
|
||||||
"""Check that the post method works with response processing disabled"""
|
|
||||||
self._register_uri(httpretty.POST)
|
|
||||||
response = self.client.post(self.test_endpoint, process_response=False)
|
|
||||||
self.assertEqual(response, json.dumps(self.test_data))
|
self.assertEqual(response, json.dumps(self.test_data))
|
||||||
|
|
||||||
@httpretty.activate
|
@httpretty.activate
|
||||||
|
@ -127,23 +188,31 @@ class TestHttp(unittest.TestCase):
|
||||||
self.assertIn(params["unicode_"], [["\xc3\xbcmlaut"], ["\xfcmlaut"]])
|
self.assertIn(params["unicode_"], [["\xc3\xbcmlaut"], ["\xfcmlaut"]])
|
||||||
|
|
||||||
@httpretty.activate
|
@httpretty.activate
|
||||||
def test_get_with_api_version(self):
|
@data(GET, POST)
|
||||||
"""Check that an API version can be specified for the get method"""
|
def test_api_version(self, method):
|
||||||
self.client = trovebox.Trovebox(host=self.test_host, api_version=1)
|
"""Check that an API version can be specified"""
|
||||||
self._register_uri(httpretty.GET,
|
self.client = trovebox.Trovebox(host=self.test_host, **self.test_oauth)
|
||||||
|
self.client.configure(api_version=1)
|
||||||
|
self._register_uri(method,
|
||||||
uri="http://%s/v1/%s" % (self.test_host,
|
uri="http://%s/v1/%s" % (self.test_host,
|
||||||
self.test_endpoint))
|
self.test_endpoint))
|
||||||
self.client.get(self.test_endpoint)
|
GetOrPost(self.client, method).call(self.test_endpoint)
|
||||||
|
|
||||||
@httpretty.activate
|
@mock.patch.object(trovebox.http.requests, 'Session')
|
||||||
def test_post_with_api_version(self):
|
@data(GET, POST)
|
||||||
"""Check that an API version can be specified for the post method"""
|
def test_ssl_verify_disabled(self, method, mock_session):
|
||||||
self.client = trovebox.Trovebox(host=self.test_host, api_version=1,
|
"""Check that SSL verification can be disabled for the get method"""
|
||||||
**self.test_oauth)
|
session = mock_session.return_value.__enter__.return_value
|
||||||
self._register_uri(httpretty.POST,
|
session.get.return_value.text = "response text"
|
||||||
uri="http://%s/v1/%s" % (self.test_host,
|
session.get.return_value.status_code = 200
|
||||||
self.test_endpoint))
|
session.get.return_value.json.return_value = self.test_data
|
||||||
self.client.post(self.test_endpoint)
|
# Handle either post or get
|
||||||
|
session.post = session.get
|
||||||
|
|
||||||
|
self.client = trovebox.Trovebox(host=self.test_host, **self.test_oauth)
|
||||||
|
self.client.configure(ssl_verify=False)
|
||||||
|
GetOrPost(self.client, method).call(self.test_endpoint)
|
||||||
|
self.assertEqual(session.verify, False)
|
||||||
|
|
||||||
@httpretty.activate
|
@httpretty.activate
|
||||||
def test_post_file(self):
|
def test_post_file(self):
|
||||||
|
|
2
tox.ini
2
tox.ini
|
@ -6,11 +6,13 @@ commands = python -m unittest discover --catch tests/unit
|
||||||
deps =
|
deps =
|
||||||
mock >= 1.0.0
|
mock >= 1.0.0
|
||||||
httpretty >= 0.6.1
|
httpretty >= 0.6.1
|
||||||
|
ddt >= 0.3.0
|
||||||
|
|
||||||
[testenv:py26]
|
[testenv:py26]
|
||||||
commands = unit2 discover --catch tests/unit
|
commands = unit2 discover --catch tests/unit
|
||||||
deps =
|
deps =
|
||||||
mock >= 1.0.0
|
mock >= 1.0.0
|
||||||
httpretty >= 0.6.1
|
httpretty >= 0.6.1
|
||||||
|
ddt >= 0.3.0
|
||||||
unittest2
|
unittest2
|
||||||
discover
|
discover
|
||||||
|
|
238
trovebox/.pylint-ignores.patch
Normal file
238
trovebox/.pylint-ignores.patch
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/api_album.py patched/api_album.py
|
||||||
|
--- original/api_album.py 2013-08-16 18:12:30.434212000 +0100
|
||||||
|
+++ patched/api_album.py 2013-08-16 18:13:29.678506001 +0100
|
||||||
|
@@ -3,7 +3,7 @@
|
||||||
|
"""
|
||||||
|
from .objects import Album
|
||||||
|
|
||||||
|
-class ApiAlbums(object):
|
||||||
|
+class ApiAlbums(object): # pylint: disable=R0903,C0111
|
||||||
|
def __init__(self, client):
|
||||||
|
self._client = client
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@
|
||||||
|
results = self._client.get("/albums/list.json", **kwds)["result"]
|
||||||
|
return [Album(self._client, album) for album in results]
|
||||||
|
|
||||||
|
-class ApiAlbum(object):
|
||||||
|
+class ApiAlbum(object): # pylint: disable=C0111
|
||||||
|
def __init__(self, client):
|
||||||
|
self._client = client
|
||||||
|
|
||||||
|
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/api_photo.py patched/api_photo.py
|
||||||
|
--- original/api_photo.py 2013-08-16 18:12:30.434212000 +0100
|
||||||
|
+++ patched/api_photo.py 2013-08-16 18:13:29.678506001 +0100
|
||||||
|
@@ -20,7 +20,7 @@
|
||||||
|
ids.append(photo)
|
||||||
|
return ids
|
||||||
|
|
||||||
|
-class ApiPhotos(object):
|
||||||
|
+class ApiPhotos(object): # pylint: disable=C0111
|
||||||
|
def __init__(self, client):
|
||||||
|
self._client = client
|
||||||
|
|
||||||
|
@@ -54,7 +54,7 @@
|
||||||
|
raise TroveboxError("Delete response returned False")
|
||||||
|
return True
|
||||||
|
|
||||||
|
-class ApiPhoto(object):
|
||||||
|
+class ApiPhoto(object): # pylint: disable=C0111
|
||||||
|
def __init__(self, client):
|
||||||
|
self._client = client
|
||||||
|
|
||||||
|
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/api_tag.py patched/api_tag.py
|
||||||
|
--- original/api_tag.py 2013-08-16 18:12:30.434212000 +0100
|
||||||
|
+++ patched/api_tag.py 2013-08-16 18:13:29.678506001 +0100
|
||||||
|
@@ -3,7 +3,7 @@
|
||||||
|
"""
|
||||||
|
from .objects import Tag
|
||||||
|
|
||||||
|
-class ApiTags(object):
|
||||||
|
+class ApiTags(object): # pylint: disable=R0903,C0111
|
||||||
|
def __init__(self, client):
|
||||||
|
self._client = client
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@
|
||||||
|
results = self._client.get("/tags/list.json", **kwds)["result"]
|
||||||
|
return [Tag(self._client, tag) for tag in results]
|
||||||
|
|
||||||
|
-class ApiTag(object):
|
||||||
|
+class ApiTag(object): # pylint: disable=C0111
|
||||||
|
def __init__(self, client):
|
||||||
|
self._client = client
|
||||||
|
|
||||||
|
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/auth.py patched/auth.py
|
||||||
|
--- original/auth.py 2013-08-16 18:13:24.966482000 +0100
|
||||||
|
+++ patched/auth.py 2013-08-16 18:13:51.766615537 +0100
|
||||||
|
@@ -4,7 +4,7 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import os
|
||||||
|
try:
|
||||||
|
- from configparser import ConfigParser # Python3
|
||||||
|
+ from configparser import ConfigParser # Python3 # pylint: disable=F0401
|
||||||
|
except ImportError:
|
||||||
|
from ConfigParser import SafeConfigParser as ConfigParser # Python2
|
||||||
|
try:
|
||||||
|
@@ -12,9 +12,9 @@
|
||||||
|
except ImportError:
|
||||||
|
import StringIO as io # Python2
|
||||||
|
|
||||||
|
-class Auth(object):
|
||||||
|
+class Auth(object): # pylint: disable=R0903
|
||||||
|
"""OAuth secrets"""
|
||||||
|
- def __init__(self, config_file, host,
|
||||||
|
+ def __init__(self, config_file, host, # pylint: disable=R0913
|
||||||
|
consumer_key, consumer_secret,
|
||||||
|
token, token_secret):
|
||||||
|
if host is None:
|
||||||
|
@@ -69,7 +69,7 @@
|
||||||
|
parser = ConfigParser()
|
||||||
|
parser.optionxform = str # Case-sensitive options
|
||||||
|
try:
|
||||||
|
- parser.read_file(buf) # Python3
|
||||||
|
+ parser.read_file(buf) # Python3 # pylint: disable=E1103
|
||||||
|
except AttributeError:
|
||||||
|
parser.readfp(buf) # Python2
|
||||||
|
|
||||||
|
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/http.py patched/http.py
|
||||||
|
--- original/http.py 2013-08-16 17:54:30.688858000 +0100
|
||||||
|
+++ patched/http.py 2013-08-16 18:14:14.106726301 +0100
|
||||||
|
@@ -7,18 +7,18 @@
|
||||||
|
import requests_oauthlib
|
||||||
|
import logging
|
||||||
|
try:
|
||||||
|
- from urllib.parse import urlparse, urlunparse # Python3
|
||||||
|
+ from urllib.parse import urlparse, urlunparse # Python3 # pylint: disable=F0401,E0611
|
||||||
|
except ImportError:
|
||||||
|
from urlparse import urlparse, urlunparse # Python2
|
||||||
|
|
||||||
|
from .objects import TroveboxObject
|
||||||
|
-from .errors import *
|
||||||
|
+from .errors import * # pylint: disable=W0401
|
||||||
|
from .auth import Auth
|
||||||
|
|
||||||
|
if sys.version < '3':
|
||||||
|
- TEXT_TYPE = unicode
|
||||||
|
+ TEXT_TYPE = unicode # pylint: disable=C0103
|
||||||
|
else:
|
||||||
|
- TEXT_TYPE = str
|
||||||
|
+ TEXT_TYPE = str # pylint: disable=C0103
|
||||||
|
|
||||||
|
DUPLICATE_RESPONSE = {"code": 409,
|
||||||
|
"message": "This photo already exists"}
|
||||||
|
@@ -37,7 +37,7 @@
|
||||||
|
"ssl_verify" : True,
|
||||||
|
}
|
||||||
|
|
||||||
|
- def __init__(self, config_file=None, host=None,
|
||||||
|
+ def __init__(self, config_file=None, host=None, # pylint: disable=R0913
|
||||||
|
consumer_key='', consumer_secret='',
|
||||||
|
token='', token_secret='', api_version=None):
|
||||||
|
|
||||||
|
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/__init__.py patched/__init__.py
|
||||||
|
--- original/__init__.py 2013-08-16 18:12:30.438212000 +0100
|
||||||
|
+++ patched/__init__.py 2013-08-16 18:13:29.678506001 +0100
|
||||||
|
@@ -2,7 +2,7 @@
|
||||||
|
__init__.py : Trovebox package top level
|
||||||
|
"""
|
||||||
|
from .http import Http
|
||||||
|
-from .errors import *
|
||||||
|
+from .errors import * # pylint: disable=W0401
|
||||||
|
from ._version import __version__
|
||||||
|
from . import api_photo
|
||||||
|
from . import api_tag
|
||||||
|
@@ -22,7 +22,7 @@
|
||||||
|
This should be used to ensure that your application will continue to work
|
||||||
|
even if the Trovebox API is updated to a new revision.
|
||||||
|
"""
|
||||||
|
- def __init__(self, config_file=None, host=None,
|
||||||
|
+ def __init__(self, config_file=None, host=None, # pylint: disable=R0913
|
||||||
|
consumer_key='', consumer_secret='',
|
||||||
|
token='', token_secret='',
|
||||||
|
api_version=None):
|
||||||
|
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/main.py patched/main.py
|
||||||
|
--- original/main.py 2013-08-16 18:12:30.438212000 +0100
|
||||||
|
+++ patched/main.py 2013-08-16 18:13:29.678506001 +0100
|
||||||
|
@@ -26,7 +26,7 @@
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
-def main(args=sys.argv[1:]):
|
||||||
|
+def main(args=sys.argv[1:]): # pylint: disable=R0912,C0111
|
||||||
|
usage = "%prog --help"
|
||||||
|
parser = OptionParser(usage, add_help_option=False)
|
||||||
|
parser.add_option('-c', '--config', help="Configuration file to use",
|
||||||
|
@@ -84,13 +84,13 @@
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if options.method == "GET":
|
||||||
|
- result = client.get(options.endpoint, process_response=False,
|
||||||
|
+ result = client.get(options.endpoint, process_response=False, # pylint: disable=W0142
|
||||||
|
**params)
|
||||||
|
else:
|
||||||
|
params, files = extract_files(params)
|
||||||
|
- result = client.post(options.endpoint, process_response=False,
|
||||||
|
+ result = client.post(options.endpoint, process_response=False, # pylint: disable=W0142
|
||||||
|
files=files, **params)
|
||||||
|
- for f in files:
|
||||||
|
+ for f in files: # pylint: disable=C0103
|
||||||
|
files[f].close()
|
||||||
|
|
||||||
|
if options.verbose:
|
||||||
|
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/objects.py patched/objects.py
|
||||||
|
--- original/objects.py 2013-08-16 18:12:30.438212000 +0100
|
||||||
|
+++ patched/objects.py 2013-08-16 18:13:29.682506021 +0100
|
||||||
|
@@ -2,16 +2,16 @@
|
||||||
|
objects.py : Basic Trovebox API Objects
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
- from urllib.parse import quote # Python3
|
||||||
|
+ from urllib.parse import quote # Python3 # pylint: disable=F0401,E0611
|
||||||
|
except ImportError:
|
||||||
|
from urllib import quote # Python2
|
||||||
|
|
||||||
|
from .errors import TroveboxError
|
||||||
|
|
||||||
|
-class TroveboxObject(object):
|
||||||
|
+class TroveboxObject(object): # pylint: disable=R0903
|
||||||
|
""" Base object supporting the storage of custom fields as attributes """
|
||||||
|
def __init__(self, trovebox, json_dict):
|
||||||
|
- self.id = None
|
||||||
|
+ self.id = None # pylint: disable=C0103
|
||||||
|
self.name = None
|
||||||
|
self._trovebox = trovebox
|
||||||
|
self._json_dict = json_dict
|
||||||
|
@@ -57,7 +57,7 @@
|
||||||
|
return self._json_dict
|
||||||
|
|
||||||
|
|
||||||
|
-class Photo(TroveboxObject):
|
||||||
|
+class Photo(TroveboxObject): # pylint: disable=C0111
|
||||||
|
def delete(self, **kwds):
|
||||||
|
"""
|
||||||
|
Delete this photo.
|
||||||
|
@@ -147,7 +147,7 @@
|
||||||
|
|
||||||
|
self._replace_fields(new_dict)
|
||||||
|
|
||||||
|
-class Tag(TroveboxObject):
|
||||||
|
+class Tag(TroveboxObject): # pylint: disable=C0111
|
||||||
|
def delete(self, **kwds):
|
||||||
|
"""
|
||||||
|
Delete this tag.
|
||||||
|
@@ -168,7 +168,7 @@
|
||||||
|
self._replace_fields(new_dict)
|
||||||
|
|
||||||
|
|
||||||
|
-class Album(TroveboxObject):
|
||||||
|
+class Album(TroveboxObject): # pylint: disable=C0111
|
||||||
|
def __init__(self, trovebox, json_dict):
|
||||||
|
self.photos = None
|
||||||
|
self.cover = None
|
||||||
|
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/_version.py patched/_version.py
|
||||||
|
--- original/_version.py 2013-08-16 18:12:30.438212000 +0100
|
||||||
|
+++ patched/_version.py 2013-08-16 18:13:29.682506021 +0100
|
||||||
|
@@ -1,2 +1,2 @@
|
||||||
|
-
|
||||||
|
+ # pylint: disable=C0111
|
||||||
|
__version__ = "0.4"
|
|
@ -1,3 +1,6 @@
|
||||||
|
"""
|
||||||
|
__init__.py : Trovebox package top level
|
||||||
|
"""
|
||||||
from .http import Http
|
from .http import Http
|
||||||
from .errors import *
|
from .errors import *
|
||||||
from ._version import __version__
|
from ._version import __version__
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
__version__ = "0.4"
|
|
||||||
|
__version__ = "0.5"
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
"""
|
||||||
|
api_album.py : Trovebox Album API Classes
|
||||||
|
"""
|
||||||
from .objects import Album
|
from .objects import Album
|
||||||
|
|
||||||
class ApiAlbums:
|
class ApiAlbums(object):
|
||||||
def __init__(self, client):
|
def __init__(self, client):
|
||||||
self._client = client
|
self._client = client
|
||||||
|
|
||||||
|
@ -9,7 +12,7 @@ class ApiAlbums:
|
||||||
results = self._client.get("/albums/list.json", **kwds)["result"]
|
results = self._client.get("/albums/list.json", **kwds)["result"]
|
||||||
return [Album(self._client, album) for album in results]
|
return [Album(self._client, album) for album in results]
|
||||||
|
|
||||||
class ApiAlbum:
|
class ApiAlbum(object):
|
||||||
def __init__(self, client):
|
def __init__(self, client):
|
||||||
self._client = client
|
self._client = client
|
||||||
|
|
||||||
|
@ -30,12 +33,15 @@ class ApiAlbum:
|
||||||
return album.delete(**kwds)
|
return album.delete(**kwds)
|
||||||
|
|
||||||
def form(self, album, **kwds):
|
def form(self, album, **kwds):
|
||||||
|
""" Not yet implemented """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def add_photos(self, album, photos, **kwds):
|
def add_photos(self, album, photos, **kwds):
|
||||||
|
""" Not yet implemented """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def remove_photos(self, album, photos, **kwds):
|
def remove_photos(self, album, photos, **kwds):
|
||||||
|
""" Not yet implemented """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def update(self, album, **kwds):
|
def update(self, album, **kwds):
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
"""
|
||||||
|
api_photo.py : Trovebox Photo API Classes
|
||||||
|
"""
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
from .errors import TroveboxError
|
from .errors import TroveboxError
|
||||||
|
@ -17,7 +20,7 @@ def extract_ids(photos):
|
||||||
ids.append(photo)
|
ids.append(photo)
|
||||||
return ids
|
return ids
|
||||||
|
|
||||||
class ApiPhotos:
|
class ApiPhotos(object):
|
||||||
def __init__(self, client):
|
def __init__(self, client):
|
||||||
self._client = client
|
self._client = client
|
||||||
|
|
||||||
|
@ -51,7 +54,7 @@ class ApiPhotos:
|
||||||
raise TroveboxError("Delete response returned False")
|
raise TroveboxError("Delete response returned False")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
class ApiPhoto:
|
class ApiPhoto(object):
|
||||||
def __init__(self, client):
|
def __init__(self, client):
|
||||||
self._client = client
|
self._client = client
|
||||||
|
|
||||||
|
@ -72,9 +75,11 @@ class ApiPhoto:
|
||||||
return photo.edit(**kwds)
|
return photo.edit(**kwds)
|
||||||
|
|
||||||
def replace(self, photo, photo_file, **kwds):
|
def replace(self, photo, photo_file, **kwds):
|
||||||
|
""" Not yet implemented """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def replace_encoded(self, photo, photo_file, **kwds):
|
def replace_encoded(self, photo, photo_file, **kwds):
|
||||||
|
""" Not yet implemented """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def update(self, photo, **kwds):
|
def update(self, photo, **kwds):
|
||||||
|
@ -114,6 +119,7 @@ class ApiPhoto:
|
||||||
return Photo(self._client, result)
|
return Photo(self._client, result)
|
||||||
|
|
||||||
def dynamic_url(self, photo, **kwds):
|
def dynamic_url(self, photo, **kwds):
|
||||||
|
""" Not yet implemented """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def next_previous(self, photo, **kwds):
|
def next_previous(self, photo, **kwds):
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
"""
|
||||||
|
api_tag.py : Trovebox Tag API Classes
|
||||||
|
"""
|
||||||
from .objects import Tag
|
from .objects import Tag
|
||||||
|
|
||||||
class ApiTags:
|
class ApiTags(object):
|
||||||
def __init__(self, client):
|
def __init__(self, client):
|
||||||
self._client = client
|
self._client = client
|
||||||
|
|
||||||
|
@ -9,7 +12,7 @@ class ApiTags:
|
||||||
results = self._client.get("/tags/list.json", **kwds)["result"]
|
results = self._client.get("/tags/list.json", **kwds)["result"]
|
||||||
return [Tag(self._client, tag) for tag in results]
|
return [Tag(self._client, tag) for tag in results]
|
||||||
|
|
||||||
class ApiTag:
|
class ApiTag(object):
|
||||||
def __init__(self, client):
|
def __init__(self, client):
|
||||||
self._client = client
|
self._client = client
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
"""
|
||||||
|
auth.py : OAuth Config File Parser
|
||||||
|
"""
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import os
|
import os
|
||||||
try:
|
try:
|
||||||
|
@ -9,7 +12,8 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import StringIO as io # Python2
|
import StringIO as io # Python2
|
||||||
|
|
||||||
class Config:
|
class Auth(object):
|
||||||
|
"""OAuth secrets"""
|
||||||
def __init__(self, config_file, host,
|
def __init__(self, config_file, host,
|
||||||
consumer_key, consumer_secret,
|
consumer_key, consumer_secret,
|
||||||
token, token_secret):
|
token, token_secret):
|
||||||
|
@ -46,7 +50,8 @@ def get_config_path(config_file):
|
||||||
def read_config(config_path):
|
def read_config(config_path):
|
||||||
"""
|
"""
|
||||||
Loads config data from the specified file path.
|
Loads config data from the specified file path.
|
||||||
If config_file doesn't exist, returns an empty authentication config for localhost.
|
If config_file doesn't exist, returns an empty authentication config
|
||||||
|
for localhost.
|
||||||
"""
|
"""
|
||||||
section = "DUMMY"
|
section = "DUMMY"
|
||||||
defaults = {'host': 'localhost',
|
defaults = {'host': 'localhost',
|
|
@ -1,3 +1,6 @@
|
||||||
|
"""
|
||||||
|
errors.py : Trovebox Error Classes
|
||||||
|
"""
|
||||||
class TroveboxError(Exception):
|
class TroveboxError(Exception):
|
||||||
""" Indicates that an Trovebox operation failed """
|
""" Indicates that an Trovebox operation failed """
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
|
"""
|
||||||
|
http.py : Trovebox HTTP Access
|
||||||
|
"""
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import sys
|
import sys
|
||||||
import requests
|
import requests
|
||||||
import requests_oauthlib
|
import requests_oauthlib
|
||||||
import logging
|
import logging
|
||||||
try:
|
try:
|
||||||
from urllib.parse import urlunparse # Python3
|
from urllib.parse import urlparse, urlunparse # Python3
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from urlparse import urlunparse # Python2
|
from urlparse import urlparse, urlunparse # Python2
|
||||||
|
|
||||||
from .objects import TroveboxObject
|
from .objects import TroveboxObject
|
||||||
from .errors import *
|
from .errors import *
|
||||||
from .config import Config
|
from .auth import Auth
|
||||||
|
|
||||||
if sys.version < '3':
|
if sys.version < '3':
|
||||||
TEXT_TYPE = unicode
|
TEXT_TYPE = unicode
|
||||||
|
@ -20,36 +23,58 @@ else:
|
||||||
DUPLICATE_RESPONSE = {"code": 409,
|
DUPLICATE_RESPONSE = {"code": 409,
|
||||||
"message": "This photo already exists"}
|
"message": "This photo already exists"}
|
||||||
|
|
||||||
class Http:
|
class Http(object):
|
||||||
"""
|
"""
|
||||||
Base class to handle HTTP requests to an Trovebox server.
|
Base class to handle HTTP requests to an Trovebox server.
|
||||||
If no parameters are specified, config is loaded from the default
|
If no parameters are specified, auth config is loaded from the
|
||||||
location (~/.config/trovebox/default).
|
default location (~/.config/trovebox/default).
|
||||||
The config_file parameter is used to specify an alternate config file.
|
The config_file parameter is used to specify an alternate config file.
|
||||||
If the host parameter is specified, no config file is loaded and
|
If the host parameter is specified, no config file is loaded and
|
||||||
OAuth tokens (consumer*, token*) can optionally be specified.
|
OAuth tokens (consumer*, token*) can optionally be specified.
|
||||||
All requests will include the api_version path, if specified.
|
|
||||||
This should be used to ensure that your application will continue to work
|
|
||||||
even if the Trovebox API is updated to a new revision.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_CONFIG_DEFAULTS = {"api_version" : None,
|
||||||
|
"ssl_verify" : True,
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, config_file=None, host=None,
|
def __init__(self, config_file=None, host=None,
|
||||||
consumer_key='', consumer_secret='',
|
consumer_key='', consumer_secret='',
|
||||||
token='', token_secret='', api_version=None):
|
token='', token_secret='', api_version=None):
|
||||||
self._api_version = api_version
|
|
||||||
|
self.config = dict(self._CONFIG_DEFAULTS)
|
||||||
|
|
||||||
|
if api_version is not None:
|
||||||
|
print("Deprecation Warning: api_version should be set by "
|
||||||
|
"calling the configure function")
|
||||||
|
self.config["api_version"] = api_version
|
||||||
|
|
||||||
self._logger = logging.getLogger("trovebox")
|
self._logger = logging.getLogger("trovebox")
|
||||||
|
|
||||||
self.config = Config(config_file, host,
|
self.auth = Auth(config_file, host,
|
||||||
consumer_key, consumer_secret,
|
consumer_key, consumer_secret,
|
||||||
token, token_secret)
|
token, token_secret)
|
||||||
|
|
||||||
self.host = self.config.host
|
self.host = self.auth.host
|
||||||
|
|
||||||
# Remember the most recent HTTP request and response
|
# Remember the most recent HTTP request and response
|
||||||
self.last_url = None
|
self.last_url = None
|
||||||
self.last_params = None
|
self.last_params = None
|
||||||
self.last_response = None
|
self.last_response = None
|
||||||
|
|
||||||
|
def configure(self, **kwds):
|
||||||
|
"""
|
||||||
|
Update Trovebox HTTP client configuration.
|
||||||
|
|
||||||
|
:param api_version: Include a Trovebox API version in all requests.
|
||||||
|
This can be used to ensure that your application will continue
|
||||||
|
to work even if the Trovebox API is updated to a new revision.
|
||||||
|
[default: None]
|
||||||
|
:param ssl_verify: If true, HTTPS SSL certificates will always be
|
||||||
|
verified [default: True]
|
||||||
|
"""
|
||||||
|
for item in kwds:
|
||||||
|
self.config[item] = kwds[item]
|
||||||
|
|
||||||
def get(self, endpoint, process_response=True, **params):
|
def get(self, endpoint, process_response=True, **params):
|
||||||
"""
|
"""
|
||||||
Performs an HTTP GET from the specified endpoint (API path),
|
Performs an HTTP GET from the specified endpoint (API path),
|
||||||
|
@ -62,21 +87,18 @@ class Http:
|
||||||
Returns the raw response if process_response=False
|
Returns the raw response if process_response=False
|
||||||
"""
|
"""
|
||||||
params = self._process_params(params)
|
params = self._process_params(params)
|
||||||
if not endpoint.startswith("/"):
|
url = self._construct_url(endpoint)
|
||||||
endpoint = "/" + endpoint
|
|
||||||
if self._api_version is not None:
|
|
||||||
endpoint = "/v%d%s" % (self._api_version, endpoint)
|
|
||||||
url = urlunparse(('http', self.host, endpoint, '', '', ''))
|
|
||||||
|
|
||||||
if self.config.consumer_key:
|
if self.auth.consumer_key:
|
||||||
auth = requests_oauthlib.OAuth1(self.config.consumer_key,
|
auth = requests_oauthlib.OAuth1(self.auth.consumer_key,
|
||||||
self.config.consumer_secret,
|
self.auth.consumer_secret,
|
||||||
self.config.token,
|
self.auth.token,
|
||||||
self.config.token_secret)
|
self.auth.token_secret)
|
||||||
else:
|
else:
|
||||||
auth = None
|
auth = None
|
||||||
|
|
||||||
with requests.Session() as session:
|
with requests.Session() as session:
|
||||||
|
session.verify = self.config["ssl_verify"]
|
||||||
response = session.get(url, params=params, auth=auth)
|
response = session.get(url, params=params, auth=auth)
|
||||||
|
|
||||||
self._logger.info("============================")
|
self._logger.info("============================")
|
||||||
|
@ -105,20 +127,17 @@ class Http:
|
||||||
Returns the raw response if process_response=False
|
Returns the raw response if process_response=False
|
||||||
"""
|
"""
|
||||||
params = self._process_params(params)
|
params = self._process_params(params)
|
||||||
if not endpoint.startswith("/"):
|
url = self._construct_url(endpoint)
|
||||||
endpoint = "/" + endpoint
|
|
||||||
if self._api_version is not None:
|
|
||||||
endpoint = "/v%d%s" % (self._api_version, endpoint)
|
|
||||||
url = urlunparse(('http', self.host, endpoint, '', '', ''))
|
|
||||||
|
|
||||||
if not self.config.consumer_key:
|
if not self.auth.consumer_key:
|
||||||
raise TroveboxError("Cannot issue POST without OAuth tokens")
|
raise TroveboxError("Cannot issue POST without OAuth tokens")
|
||||||
|
|
||||||
auth = requests_oauthlib.OAuth1(self.config.consumer_key,
|
auth = requests_oauthlib.OAuth1(self.auth.consumer_key,
|
||||||
self.config.consumer_secret,
|
self.auth.consumer_secret,
|
||||||
self.config.token,
|
self.auth.token,
|
||||||
self.config.token_secret)
|
self.auth.token_secret)
|
||||||
with requests.Session() as session:
|
with requests.Session() as session:
|
||||||
|
session.verify = self.config["ssl_verify"]
|
||||||
if files:
|
if files:
|
||||||
# Need to pass parameters as URL query, so they get OAuth signed
|
# Need to pass parameters as URL query, so they get OAuth signed
|
||||||
response = session.post(url, params=params,
|
response = session.post(url, params=params,
|
||||||
|
@ -146,6 +165,22 @@ class Http:
|
||||||
else:
|
else:
|
||||||
return response.text
|
return response.text
|
||||||
|
|
||||||
|
def _construct_url(self, endpoint):
|
||||||
|
"""Return the full URL to the specified endpoint"""
|
||||||
|
parsed_url = urlparse(self.host)
|
||||||
|
scheme = parsed_url[0]
|
||||||
|
host = parsed_url[1]
|
||||||
|
# Handle host without a scheme specified (eg. www.example.com)
|
||||||
|
if scheme == "":
|
||||||
|
scheme = "http"
|
||||||
|
host = self.host
|
||||||
|
|
||||||
|
if not endpoint.startswith("/"):
|
||||||
|
endpoint = "/" + endpoint
|
||||||
|
if self.config["api_version"] is not None:
|
||||||
|
endpoint = "/v%d%s" % (self.config["api_version"], endpoint)
|
||||||
|
return urlunparse((scheme, host, endpoint, '', '', ''))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _process_params(params):
|
def _process_params(params):
|
||||||
""" Converts Unicode/lists/booleans inside HTTP parameters """
|
""" Converts Unicode/lists/booleans inside HTTP parameters """
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
main.py : Trovebox Console Script
|
||||||
|
"""
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
@ -44,7 +47,7 @@ def main(args=sys.argv[1:]):
|
||||||
action="store_true", dest="pretty", default=False)
|
action="store_true", dest="pretty", default=False)
|
||||||
parser.add_option('-v', help="Verbose output",
|
parser.add_option('-v', help="Verbose output",
|
||||||
action="store_true", dest="verbose", default=False)
|
action="store_true", dest="verbose", default=False)
|
||||||
parser.add_option('--version', help="Display the current version information",
|
parser.add_option('--version', help="Display the current version",
|
||||||
action="store_true")
|
action="store_true")
|
||||||
parser.add_option('--help', help='show this help message',
|
parser.add_option('--help', help='show this help message',
|
||||||
action="store_true")
|
action="store_true")
|
||||||
|
@ -107,7 +110,8 @@ def main(args=sys.argv[1:]):
|
||||||
|
|
||||||
def extract_files(params):
|
def extract_files(params):
|
||||||
"""
|
"""
|
||||||
Extract filenames from the "photo" parameter, so they can be uploaded, returning (updated_params, files).
|
Extract filenames from the "photo" parameter so they can be uploaded,
|
||||||
|
returning (updated_params, files).
|
||||||
Uses the same technique as the Trovebox PHP commandline tool:
|
Uses the same technique as the Trovebox PHP commandline tool:
|
||||||
* Filename can only be in the "photo" parameter
|
* Filename can only be in the "photo" parameter
|
||||||
* Filename must be prefixed with "@"
|
* Filename must be prefixed with "@"
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
"""
|
||||||
|
objects.py : Basic Trovebox API Objects
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
from urllib.parse import quote # Python3
|
from urllib.parse import quote # Python3
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -5,7 +8,7 @@ except ImportError:
|
||||||
|
|
||||||
from .errors import TroveboxError
|
from .errors import TroveboxError
|
||||||
|
|
||||||
class TroveboxObject:
|
class TroveboxObject(object):
|
||||||
""" Base object supporting the storage of custom fields as attributes """
|
""" Base object supporting the storage of custom fields as attributes """
|
||||||
def __init__(self, trovebox, json_dict):
|
def __init__(self, trovebox, json_dict):
|
||||||
self.id = None
|
self.id = None
|
||||||
|
@ -75,9 +78,11 @@ class Photo(TroveboxObject):
|
||||||
return result["markup"]
|
return result["markup"]
|
||||||
|
|
||||||
def replace(self, photo_file, **kwds):
|
def replace(self, photo_file, **kwds):
|
||||||
|
""" Not implemented yet """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def replace_encoded(self, photo_file, **kwds):
|
def replace_encoded(self, photo_file, **kwds):
|
||||||
|
""" Not implemented yet """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def update(self, **kwds):
|
def update(self, **kwds):
|
||||||
|
@ -96,6 +101,7 @@ class Photo(TroveboxObject):
|
||||||
self._replace_fields(new_dict)
|
self._replace_fields(new_dict)
|
||||||
|
|
||||||
def dynamic_url(self, **kwds):
|
def dynamic_url(self, **kwds):
|
||||||
|
""" Not implemented yet """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def next_previous(self, **kwds):
|
def next_previous(self, **kwds):
|
||||||
|
@ -194,12 +200,15 @@ class Album(TroveboxObject):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def form(self, **kwds):
|
def form(self, **kwds):
|
||||||
|
""" Not implemented yet """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def add_photos(self, photos, **kwds):
|
def add_photos(self, photos, **kwds):
|
||||||
|
""" Not implemented yet """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def remove_photos(self, photos, **kwds):
|
def remove_photos(self, photos, **kwds):
|
||||||
|
""" Not implemented yet """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def update(self, **kwds):
|
def update(self, **kwds):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue