Merge pull request #63 from sneakypete81/pylint-patcher

Pylint patcher
This commit is contained in:
sneakypete81 2013-11-03 04:48:40 -08:00
commit ea1fcc8d0f
7 changed files with 132 additions and 180 deletions

View file

@ -4,7 +4,6 @@ install:
# Install test dependencies
- pip install tox --use-mirrors
- pip install coveralls --use-mirrors
- .travis/install_pylint
script: tox
@ -14,8 +13,11 @@ after_success:
after_script:
# Install dependencies for Pylint
- pip install requests requests-oauthlib --use-mirrors
- pip install pylint-patcher --use-mirrors
- pip install requests --use-mirrors
- pip install requests-oauthlib --use-mirrors
# Run Pylint
# Uses pylint-patcher to allow exceptions to be stored in a patchfile
# (for information only, any errors don't affect the Travis result)
- pylint --use-ignore-patch=y trovebox
- pylint-patcher trovebox

View file

@ -1,10 +0,0 @@
# Until the --use-ignore-patch makes it into pylint upstream, we need to
# download and install from sneakypete81's pylint fork
wget https://bitbucket.org/sneakypete81/pylint/get/use_ignore_patch.zip
unzip use_ignore_patch.zip
cd sneakypete81-pylint-*
python setup.py install
cd ..
rm -r sneakypete81-pylint-*

View file

@ -9,16 +9,21 @@ import trovebox
class TestAlbums(unittest.TestCase):
test_host = "test.example.com"
test_photo_dict = {"id": "1a", "tags": ["tag1", "tag2"]}
test_albums_dict = [{"cover": {"id": "1a", "tags": ["tag1", "tag2"]},
"id": "1",
"name": "Album 1",
"photos": [test_photo_dict],
"totalRows": 2},
{"cover": {"id": "2b", "tags": ["tag3", "tag4"]},
"id": "2",
"name": "Album 2",
"photos": [test_photo_dict],
"totalRows": 2}]
def setUp(self):
self.client = trovebox.Trovebox(host=self.test_host)
self.test_photo = trovebox.objects.photo.Photo(self.client,
self.test_photo_dict)
self.test_albums = [trovebox.objects.album.Album(self.client, album)
for album in self.test_albums_dict]
@ -228,33 +233,35 @@ class TestAlbumView(TestAlbums):
def test_album_view(self, mock_get):
"""Check that an album can be viewed"""
mock_get.return_value = self._return_value(self.test_albums_dict[1])
result = self.client.album.view(self.test_albums[0], name="Test")
mock_get.assert_called_with("/album/1/view.json", name="Test")
result = self.client.album.view(self.test_albums[0], includeElements=True)
mock_get.assert_called_with("/album/1/view.json", includeElements=True)
self.assertEqual(result.id, "2")
self.assertEqual(result.name, "Album 2")
self.assertEqual(result.cover.id, "2b")
self.assertEqual(result.cover.tags, ["tag3", "tag4"])
self.assertEqual(result.photos[0].id, self.test_photo.id)
@mock.patch.object(trovebox.Trovebox, 'get')
def test_album_view_id(self, mock_get):
"""Check that an album can be viewed using its ID"""
mock_get.return_value = self._return_value(self.test_albums_dict[1])
result = self.client.album.view("1", name="Test")
mock_get.assert_called_with("/album/1/view.json", name="Test")
result = self.client.album.view("1", includeElements=True)
mock_get.assert_called_with("/album/1/view.json", includeElements=True)
self.assertEqual(result.id, "2")
self.assertEqual(result.name, "Album 2")
self.assertEqual(result.cover.id, "2b")
self.assertEqual(result.cover.tags, ["tag3", "tag4"])
self.assertEqual(result.photos[0].id, self.test_photo.id)
@mock.patch.object(trovebox.Trovebox, 'get')
def test_album_object_view(self, mock_get):
"""Check that an album can be viewed using the album object directly"""
mock_get.return_value = self._return_value(self.test_albums_dict[1])
album = self.test_albums[0]
album.view(name="Test")
mock_get.assert_called_with("/album/1/view.json", name="Test")
album.view(includeElements=True)
mock_get.assert_called_with("/album/1/view.json", includeElements=True)
self.assertEqual(album.id, "2")
self.assertEqual(album.name, "Album 2")
self.assertEqual(album.cover.id, "2b")
self.assertEqual(album.cover.tags, ["tag3", "tag4"])
self.assertEqual(album.photos[0].id, self.test_photo.id)

View file

@ -1,14 +1,18 @@
from __future__ import unicode_literals
import json
import httpretty
from httpretty import GET, POST
from ddt import ddt, data
try:
import unittest2 as unittest # Python2.6
except ImportError:
import unittest
from test_http import GetOrPost
import trovebox
@ddt
class TestHttpErrors(unittest.TestCase):
test_host = "test.example.com"
test_endpoint = "test.json"
@ -38,146 +42,93 @@ class TestHttpErrors(unittest.TestCase):
**kwds)
@httpretty.activate
def test_get_with_error_status(self):
@data(GET, POST)
def test_error_status(self, method):
"""
Check that an error status causes the get method
Check that an error status causes the get/post methods
to raise an exception
"""
self._register_uri(httpretty.GET, status=500)
self._register_uri(method, status=500)
with self.assertRaises(trovebox.TroveboxError):
self.client.get(self.test_endpoint)
GetOrPost(self.client, method).call(self.test_endpoint)
@httpretty.activate
def test_post_with_error_status(self):
@data(GET, POST)
def test_404_status(self, method):
"""
Check that an error status causes the post method
to raise an exception
"""
self._register_uri(httpretty.POST, status=500)
with self.assertRaises(trovebox.TroveboxError):
self.client.post(self.test_endpoint)
@httpretty.activate
def test_get_with_404_status(self):
"""
Check that a 404 status causes the get method
Check that a 404 status causes the get/post methods
to raise a 404 exception
"""
self._register_uri(httpretty.GET, status=404)
self._register_uri(method, status=404)
with self.assertRaises(trovebox.Trovebox404Error):
self.client.get(self.test_endpoint)
GetOrPost(self.client, method).call(self.test_endpoint)
@httpretty.activate
def test_post_with_404_status(self):
@data(GET, POST)
def test_with_invalid_json(self, method):
"""
Check that a 404 status causes the post method
to raise a 404 exception
"""
self._register_uri(httpretty.POST, status=404)
with self.assertRaises(trovebox.Trovebox404Error):
self.client.post(self.test_endpoint)
@httpretty.activate
def test_get_with_invalid_json(self):
"""
Check that invalid JSON causes the get method to
Check that invalid JSON causes the get/post methods to
raise an exception
"""
self._register_uri(httpretty.GET, body="Invalid JSON")
self._register_uri(method, body="Invalid JSON")
with self.assertRaises(ValueError):
self.client.get(self.test_endpoint)
GetOrPost(self.client, method).call(self.test_endpoint)
@httpretty.activate
def test_post_with_invalid_json(self):
@data(GET, POST)
def test_with_error_status_and_invalid_json(self, method):
"""
Check that invalid JSON causes the post method to
raise an exception
Check that invalid JSON causes the get/post methods to raise
an exception, even with an error status is returned
"""
self._register_uri(httpretty.POST, body="Invalid JSON")
with self.assertRaises(ValueError):
self.client.post(self.test_endpoint)
@httpretty.activate
def test_get_with_error_status_and_invalid_json(self):
"""
Check that invalid JSON causes the get method to raise an exception,
even with an error status is returned
"""
self._register_uri(httpretty.GET, body="Invalid JSON", status=500)
self._register_uri(method, body="Invalid JSON", status=500)
with self.assertRaises(trovebox.TroveboxError):
self.client.get(self.test_endpoint)
GetOrPost(self.client, method).call(self.test_endpoint)
@httpretty.activate
def test_post_with_error_status_and_invalid_json(self):
@data(GET, POST)
def test_with_404_status_and_invalid_json(self, method):
"""
Check that invalid JSON causes the post method to raise an exception,
even with an error status is returned
Check that invalid JSON causes the get/post methods to raise
an exception, even with a 404 status is returned
"""
self._register_uri(httpretty.POST, body="Invalid JSON", status=500)
with self.assertRaises(trovebox.TroveboxError):
self.client.post(self.test_endpoint)
@httpretty.activate
def test_get_with_404_status_and_invalid_json(self):
"""
Check that invalid JSON causes the get method to raise an exception,
even with a 404 status is returned
"""
self._register_uri(httpretty.GET, body="Invalid JSON", status=404)
self._register_uri(method, body="Invalid JSON", status=404)
with self.assertRaises(trovebox.Trovebox404Error):
self.client.get(self.test_endpoint)
GetOrPost(self.client, method).call(self.test_endpoint)
@httpretty.activate
def test_post_with_404_status_and_invalid_json(self):
@data(GET, POST)
def test_with_duplicate_status(self, method):
"""
Check that invalid JSON causes the post method to raise an exception,
even with a 404 status is returned
"""
self._register_uri(httpretty.POST, body="Invalid JSON", status=404)
with self.assertRaises(trovebox.Trovebox404Error):
self.client.post(self.test_endpoint)
@httpretty.activate
def test_get_with_duplicate_status(self):
"""
Check that a get with a duplicate status
Check that a get/post with a duplicate status
raises a duplicate exception
"""
data = {"message": "This photo already exists", "code": 409}
self._register_uri(httpretty.GET, data=data, status=409)
self._register_uri(method, data=data, status=409)
with self.assertRaises(trovebox.TroveboxDuplicateError):
self.client.get(self.test_endpoint)
GetOrPost(self.client, method).call(self.test_endpoint)
@httpretty.activate
def test_post_with_duplicate_status(self):
"""
Check that a post with a duplicate status
raises a duplicate exception
"""
data = {"message": "This photo already exists", "code": 409}
self._register_uri(httpretty.POST, data=data, status=409)
with self.assertRaises(trovebox.TroveboxDuplicateError):
self.client.post(self.test_endpoint)
@httpretty.activate
def test_get_with_status_code_mismatch(self):
@data(GET, POST)
def test_with_status_code_mismatch(self, method):
"""
Check that a mismatched HTTP status code still returns the
JSON status code for get requests.
JSON status code.
"""
data = {"message": "Test Message", "code": 202}
self._register_uri(httpretty.GET, data=data, status=200)
response = self.client.get(self.test_endpoint)
self._register_uri(method, data=data, status=200)
response = GetOrPost(self.client, method).call(self.test_endpoint)
self.assertEqual(response["code"], 202)
@httpretty.activate
def test_post_with_status_code_mismatch(self):
@data(GET, POST)
def test_http_error_with_no_response_processing(self, method):
"""
Check that a mismatched HTTP status code still returns the
JSON status code for post requests.
Check that get/post methods work with response processing disabled
when an HTTP error code is returned.
"""
data = {"message": "Test Message", "code": 202}
self._register_uri(httpretty.POST, data=data, status=200)
response = self.client.post(self.test_endpoint)
self.assertEqual(response["code"], 202)
httpretty.register_uri(method, self.test_uri, status=500)
with self.assertRaises(trovebox.TroveboxError):
response = GetOrPost(self.client, method).call(self.test_endpoint,
process_response=False)

View file

@ -1,60 +1,60 @@
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/api/api_activity.py patched/api/api_activity.py
--- original/api/api_activity.py 2013-08-19 17:59:15.592149000 +0100
+++ patched/api/api_activity.py 2013-08-19 18:08:39.950947589 +0100
--- original/api/api_activity.py
+++ patched/api/api_activity.py
@@ -22,7 +22,7 @@
raise TroveboxError("Purge response returned False")
return True
-class ApiActivity(object):
+class ApiActivity(object): # pylint: disable=R0903
+class ApiActivity(object): # pylint: disable=too-few-public-methods
""" Definitions of /activity/ API endpoints """
def __init__(self, client):
self._client = client
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/api/api_album.py patched/api/api_album.py
--- original/api/api_album.py 2013-08-19 16:09:53.539609000 +0100
+++ patched/api/api_album.py 2013-08-19 18:08:20.118849270 +0100
@@ -3,7 +3,7 @@
"""
--- original/api/api_album.py
+++ patched/api/api_album.py
@@ -4,7 +4,7 @@
from trovebox.objects.album import Album
from trovebox import http
-class ApiAlbums(object):
+class ApiAlbums(object): # pylint: disable=R0903
+class ApiAlbums(object): # pylint: disable=too-few-public-methods
""" Definitions of /albums/ API endpoints """
def __init__(self, client):
self._client = client
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/api/api_tag.py patched/api/api_tag.py
--- original/api/api_tag.py 2013-08-19 16:09:53.539609000 +0100
+++ patched/api/api_tag.py 2013-08-19 18:08:20.118849270 +0100
@@ -3,7 +3,7 @@
"""
--- original/api/api_tag.py
+++ patched/api/api_tag.py
@@ -4,7 +4,7 @@
from trovebox import http
from trovebox.objects.tag import Tag
-class ApiTags(object):
+class ApiTags(object): # pylint: disable=R0903
+class ApiTags(object): # pylint: disable=too-few-public-methods
""" Definitions of /tags/ API endpoints """
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-19 16:09:53.543609000 +0100
+++ patched/auth.py 2013-08-19 18:08:20.118849270 +0100
--- original/auth.py
+++ patched/auth.py
@@ -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
+ from configparser import ConfigParser # Python3 # pylint: disable=import-error
except ImportError:
from ConfigParser import SafeConfigParser as ConfigParser # Python2
try:
@@ -12,9 +12,9 @@
except ImportError:
except ImportError: # pragma: no cover
import StringIO as io # Python2
-class Auth(object):
+class Auth(object): # pylint: disable=R0903
+class Auth(object): # pylint: disable=too-few-public-methods
"""OAuth secrets"""
- def __init__(self, config_file, host,
+ def __init__(self, config_file, host, # pylint: disable=R0913
+ def __init__(self, config_file, host, # pylint: disable=too-many-arguments
consumer_key, consumer_secret,
token, token_secret):
if host is None:
@ -63,33 +63,33 @@ diff --unified --recursive '--exclude=.pylint-ignores.patch' original/auth.py pa
parser.optionxform = str # Case-sensitive options
try:
- parser.read_file(buf) # Python3
+ parser.read_file(buf) # Python3 # pylint: disable=E1103
+ parser.read_file(buf) # Python3 # pylint: disable=maybe-no-member
except AttributeError:
parser.readfp(buf) # Python2
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/http.py patched/http.py
--- original/http.py 2013-08-19 16:09:53.543609000 +0100
+++ patched/http.py 2013-08-19 18:08:20.118849270 +0100
--- original/http.py
+++ patched/http.py
@@ -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
+ from urllib.parse import urlparse, urlunparse # Python3 # pylint: disable=import-error,no-name-in-module
except ImportError:
from urlparse import urlparse, urlunparse # Python2
from trovebox.objects.trovebox_object import TroveboxObject
-from .errors import *
+from .errors import * # pylint: disable=W0401
+from .errors import * # pylint: disable=wildcard-import
from .auth import Auth
if sys.version < '3':
- TEXT_TYPE = unicode
+ TEXT_TYPE = unicode # pylint: disable=C0103
else:
+ TEXT_TYPE = unicode # pylint: disable=invalid-name
else: # pragma: no cover
- TEXT_TYPE = str
+ TEXT_TYPE = str # pylint: disable=C0103
+ TEXT_TYPE = str # pylint: disable=invalid-name
DUPLICATE_RESPONSE = {"code": 409,
"message": "This photo already exists"}
@ -98,19 +98,19 @@ diff --unified --recursive '--exclude=.pylint-ignores.patch' original/http.py pa
}
- def __init__(self, config_file=None, host=None,
+ def __init__(self, config_file=None, host=None, # pylint: disable=R0913
+ def __init__(self, config_file=None, host=None, # pylint: disable=too-many-arguments
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-19 17:02:22.951226000 +0100
+++ patched/__init__.py 2013-08-19 18:08:36.194928993 +0100
--- original/__init__.py
+++ patched/__init__.py
@@ -2,7 +2,7 @@
__init__.py : Trovebox package top level
"""
from .http import Http
-from .errors import *
+from .errors import * # pylint: disable=W0401
+from .errors import * # pylint: disable=wildcard-import
from ._version import __version__
from trovebox.api import api_photo
from trovebox.api import api_tag
@ -119,7 +119,7 @@ diff --unified --recursive '--exclude=.pylint-ignores.patch' original/__init__.p
LATEST_API_VERSION = 2
-class Trovebox(Http):
+class Trovebox(Http): # pylint: disable=R0902
+class Trovebox(Http): # pylint: disable=too-many-instance-attributes
"""
Client library for Trovebox
If no parameters are specified, config is loaded from the default
@ -128,73 +128,61 @@ diff --unified --recursive '--exclude=.pylint-ignores.patch' original/__init__.p
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
+ def __init__(self, config_file=None, host=None, # pylint: disable=too-many-arguments
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-19 16:09:53.543609000 +0100
+++ patched/main.py 2013-08-19 18:08:20.118849270 +0100
--- original/main.py
+++ patched/main.py
@@ -26,7 +26,7 @@
#################################################################
-def main(args=sys.argv[1:]):
+def main(args=sys.argv[1:]): # pylint: disable=R0912,C0111
+def main(args=sys.argv[1:]): # pylint: disable=too-many-branches
usage = "%prog --help"
parser = OptionParser(usage, add_help_option=False)
parser.add_option('-c', '--config', help="Configuration file to use",
@@ -84,13 +84,13 @@
@@ -84,11 +84,11 @@
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
+ result = client.get(options.endpoint, process_response=False, # pylint: disable=star-args
**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
+ result = client.post(options.endpoint, process_response=False, # pylint: disable=star-args
files=files, **params)
- for f in files:
+ for f in files: # pylint: disable=C0103
for f in files:
files[f].close()
if options.verbose:
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/objects/tag.py patched/objects/tag.py
--- original/objects/tag.py 2013-08-19 16:09:53.543609000 +0100
+++ patched/objects/tag.py 2013-08-19 18:08:20.118849270 +0100
@@ -1,8 +1,8 @@
-"""
+""" # pylint: disable=R0801
--- original/objects/tag.py
+++ patched/objects/tag.py
@@ -2,7 +2,7 @@
Representation of a Tag object
"""
try:
- from urllib.parse import quote # Python3
+ from urllib.parse import quote # Python3 # pylint: disable=F0401,E0611
+ from urllib.parse import quote # Python3 # pylint: disable=import-error,no-name-in-module
except ImportError:
from urllib import quote # Python2
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/objects/trovebox_object.py patched/objects/trovebox_object.py
--- original/objects/trovebox_object.py 2013-08-19 16:09:53.543609000 +0100
+++ patched/objects/trovebox_object.py 2013-08-19 18:08:20.118849270 +0100
--- original/objects/trovebox_object.py
+++ patched/objects/trovebox_object.py
@@ -1,10 +1,10 @@
"""
Base object supporting the storage of custom fields as attributes
"""
-class TroveboxObject(object):
+class TroveboxObject(object): # pylint: disable=R0903
+class TroveboxObject(object): # pylint: disable=too-few-public-methods
""" 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.id = None # pylint: disable=invalid-name
self.name = None
self._trovebox = trovebox
self._json_dict = json_dict
diff --unified --recursive '--exclude=.pylint-ignores.patch' original/_version.py patched/_version.py
--- original/_version.py 2013-08-19 16:09:53.543609000 +0100
+++ patched/_version.py 2013-08-19 18:08:20.118849270 +0100
@@ -1,2 +1,2 @@
-
+ # pylint: disable=C0111
__version__ = "0.5"

View file

@ -113,7 +113,11 @@ class Http(object):
if process_response:
return self._process_response(response)
else:
if 200 <= response.status_code < 300:
return response.text
else:
raise TroveboxError("HTTP Error %d: %s" %
(response.status_code, response.reason))
def post(self, endpoint, process_response=True, files=None, **params):
"""
@ -163,7 +167,11 @@ class Http(object):
if process_response:
return self._process_response(response)
else:
if 200 <= response.status_code < 300:
return response.text
else:
raise TroveboxError("HTTP Error %d: %s" %
(response.status_code, response.reason))
def _construct_url(self, endpoint):
"""Return the full URL to the specified endpoint"""

View file

@ -8,6 +8,7 @@ from .photo import Photo
class Album(TroveboxObject):
""" Representation of an Album object """
def __init__(self, trovebox, json_dict):
self.photos = None
self.cover = None
TroveboxObject.__init__(self, trovebox, json_dict)
self._update_fields_with_objects()
@ -17,6 +18,11 @@ class Album(TroveboxObject):
# Update the cover with a photo object
if isinstance(self.cover, dict):
self.cover = Photo(self._trovebox, self.cover)
# Update the photo list with photo objects
if isinstance(self.photos, list):
for i, photo in enumerate(self.photos):
if isinstance(photo, dict):
self.photos[i] = Photo(self._trovebox, photo)
def delete(self, **kwds):
"""