From a43e15d497cb3fe50bb76bda4a597fad3df0c199 Mon Sep 17 00:00:00 2001 From: Chris Schomaker Date: Mon, 31 Mar 2014 10:56:45 -0700 Subject: [PATCH 1/4] setup 0.2.4 branch --- docs/conf.py | 4 ++-- setup.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 07f4aaa..da4059b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -48,9 +48,9 @@ # built documents. # # The short X.Y version. -version = '0.2.3' +version = '0.2.4' # The full version, including alpha/beta/rc tags. -release = '0.2.3' +release = '0.2.4' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/setup.py b/setup.py index 6fbe013..25c66e9 100755 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ setup( name='readability-api', - version='0.2.3', + version='0.2.4', description='Python wrapper for the Readability API.', long_description=open('README.rst').read(), author='The Readability Team', From 946447820d132e5c792c121d82c535f1fad52dcc Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Mon, 31 Mar 2014 23:39:27 +0200 Subject: [PATCH 2/4] Add update_bookmark() and related functions --- readability/clients.py | 61 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/readability/clients.py b/readability/clients.py index a2624d0..0fc88b1 100644 --- a/readability/clients.py +++ b/readability/clients.py @@ -197,6 +197,67 @@ def add_bookmark(self, url, favorite=False, archive=False): params = dict(url=url, favorite=int(favorite), archive=int(archive)) return self.post(rdb_url, params) + def update_bookmark(self, bookmark_id, favorite=None, archive=None, read_percent=None): + """Updates given bookmark. + + The requested bookmark must belong to the current user. + + :param bookmark_id: ID of the bookmark to update. + :param favorite (optional): Whether this article is favorited or not. + :param archive (optional): Whether this article is archived or not. + :param read_percent (optional): The read progress made in this article, + where 1.0 means the bottom and 0.0 means the very top. + + """ + + rdb_url = self._generate_url('bookmarks/{0}'.format(bookmark_id)) + params = {} + if favorite is not None: + params['favorite'] = 1 if favorite == True else 0 + if archive is not None: + params['archive'] = 1 if archive == True else 0 + if read_percent is not None: + try: + params['read_percent'] = float(read_percent) + except ValueError: + pass + return self.post(rdb_url, params) + + def favorite_bookmark(self, bookmark_id): + """Favorites given bookmark. + + The requested bookmark must belong to the current user. + + :param bookmark_id: ID of the bookmark to favorite. + + """ + + return self.update_bookmark(bookmark_id, favorite=True) + + def archive_bookmark(self, bookmark_id): + """Archives given bookmark. + + The requested bookmark must belong to the current user. + + :param bookmark_id: ID of the bookmark to archive. + + """ + + return self.update_bookmark(bookmark_id, archive=True) + + def set_read_percent_of_bookmark(self, bookmark_id, read_percent): + """Set read progress of given bookmark. + + The requested bookmark must belong to the current user. + + :param bookmark_id: ID of the bookmark to update. + :param read_percent: The read progress made in this article, + where 1.0 means the bottom and 0.0 means the very top. + + """ + + return self.update_bookmark(bookmark_id, read_percent=read_percent) + def delete_bookmark(self, bookmark_id): """Delete a single bookmark represented by `bookmark_id`. From ff353bb143753ac011f95ea6e4974b1f7cf7805c Mon Sep 17 00:00:00 2001 From: Chris Schomaker Date: Wed, 2 Apr 2014 11:12:59 -0700 Subject: [PATCH 3/4] Docstring updates --- readability/auth.py | 3 +- readability/clients.py | 155 ++++++++++++++---------------- readability/tests/test_auth.py | 28 +++--- readability/tests/test_clients.py | 92 +++++++++--------- readability/tests/test_utils.py | 59 ++++++------ 5 files changed, 162 insertions(+), 175 deletions(-) diff --git a/readability/auth.py b/readability/auth.py index 06c349a..a37dcf5 100644 --- a/readability/auth.py +++ b/readability/auth.py @@ -22,7 +22,8 @@ def xauth(consumer_key, consumer_secret, username, password, base_url_template=DEFAULT_BASE_URL_TEMPLATE): - """Returns an OAuth token that can be used with clients.ReaderClient. + """ + Returns an OAuth token that can be used with clients.ReaderClient. :param consumer_key: Readability consumer key :param consumer_secret: Readability consumer secret diff --git a/readability/clients.py b/readability/clients.py index 0fc88b1..11f39ae 100644 --- a/readability/clients.py +++ b/readability/clients.py @@ -28,12 +28,12 @@ class BaseClient(object): - """A base class for Readability clients. - """ - + A base class for Readability clients. + """ def _create_response(self, response, content): - """Modify the httplib2.Repsonse object to return. + """ + Modify the httplib2.Repsonse object to return. Add two attributes to it: @@ -69,15 +69,15 @@ def _create_response(self, response, content): class ReaderClient(BaseClient): - """Client for interacting with the Readability Reader API. + """ + Client for interacting with the Readability Reader API. Docs can be found at `http://www.readability.com/developers/api/reader`. - """ - def __init__(self, consumer_key, consumer_secret, token_key, token_secret, base_url_template=DEFAULT_READER_URL_TEMPLATE): - """Initialize the ReadeClient. + """ + Initialize the ReadeClient. :param consumer_key: Reader API key :param consumer_secret: Reader API secret @@ -87,30 +87,28 @@ def __init__(self, consumer_key, consumer_secret, token_key, token_secret, which requests will be sent. This shouldn't need to be passed as the main purpose for it is testing environments that the user probably doesn't have access to (staging, local dev, etc). - """ - self.base_url_template = base_url_template self.token = oauth2.Token(token_key, token_secret) self.consumer = oauth2.Consumer(consumer_key, consumer_secret) self.oauth_client = oauth2.Client(self.consumer, self.token) def get(self, url): - """Make a HTTP GET request to the Reader API. + """ + Make a HTTP GET request to the Reader API. :param url: url to which to make a GET request. - """ logger.debug('Making GET request to %s', url) return self._create_response( *self.oauth_client.request(url, method='GET')) def post(self, url, post_params=None): - """Make a HTTP POST request to the Reader API. + """ + Make a HTTP POST request to the Reader API. :param url: url to which to make a POST request. :param post_params: parameters to be sent in the request's body. - """ params = urllib.urlencode(post_params) logger.debug('Making POST request to %s with body %s', url, params) @@ -118,23 +116,23 @@ def post(self, url, post_params=None): *self.oauth_client.request(url, method='POST', body=params)) def delete(self, url): - """Make a HTTP DELETE request to the Readability API. + """ + Make a HTTP DELETE request to the Readability API. :param url: The url to which to send a DELETE request. - """ logger.debug('Making DELETE request to %s', url) return self._create_response( *self.oauth_client.request(url, method='DELETE')) def _generate_url(self, resource, query_params=None): - """Generate a Readability URL to the given resource. + """ + Generate a Readability URL to the given resource. :param resource: the path to the resource that the request should go to. :param query_params (optional): a dict of query params that should be added to the url. - """ if query_params: resource = '{0}?{1}'.format( @@ -143,16 +141,17 @@ def _generate_url(self, resource, query_params=None): return self.base_url_template.format(resource) def get_article(self, article_id): - """Get a single article represented by `article_id`. + """ + Get a single article represented by `article_id`. :param article_id: ID of the article to retrieve. - """ url = self._generate_url('articles/{0}'.format(article_id)) return self.get(url) def get_bookmarks(self, **filters): - """Get Bookmarks for the current user. + """ + Get Bookmarks for the current user. Filters: @@ -171,45 +170,41 @@ def get_bookmarks(self, **filters): :param per_page: How many results to return per page. Default is 20, max is 50. :param only_deleted: Return only bookmarks that this user has deleted. :param tags: Comma separated string of tags to filter bookmarks. - """ filter_dict = filter_args_to_dict(filters, ACCEPTED_BOOKMARK_FILTERS) url = self._generate_url('bookmarks', query_params=filter_dict) return self.get(url) def get_bookmark(self, bookmark_id): - """Get a single bookmark represented by `bookmark_id`. + """ + Get a single bookmark represented by `bookmark_id`. The requested bookmark must belong to the current user. :param bookmark_id: ID of the bookmark to retrieve. - """ url = self._generate_url('bookmarks/{0}'.format(bookmark_id)) return self.get(url) def add_bookmark(self, url, favorite=False, archive=False): - """Adds given bookmark. - """ - + Adds given bookmark. + """ rdb_url = self._generate_url('bookmarks') params = dict(url=url, favorite=int(favorite), archive=int(archive)) return self.post(rdb_url, params) def update_bookmark(self, bookmark_id, favorite=None, archive=None, read_percent=None): - """Updates given bookmark. - - The requested bookmark must belong to the current user. + """ + Updates given bookmark. The requested bookmark must belong to the + current user. :param bookmark_id: ID of the bookmark to update. :param favorite (optional): Whether this article is favorited or not. :param archive (optional): Whether this article is archived or not. :param read_percent (optional): The read progress made in this article, - where 1.0 means the bottom and 0.0 means the very top. - + where 1.0 means the bottom and 0.0 means the very top. """ - rdb_url = self._generate_url('bookmarks/{0}'.format(bookmark_id)) params = {} if favorite is not None: @@ -224,122 +219,116 @@ def update_bookmark(self, bookmark_id, favorite=None, archive=None, read_percent return self.post(rdb_url, params) def favorite_bookmark(self, bookmark_id): - """Favorites given bookmark. - - The requested bookmark must belong to the current user. + """ + Favorites given bookmark. The requested bookmark must belong to the + current user. :param bookmark_id: ID of the bookmark to favorite. - """ - return self.update_bookmark(bookmark_id, favorite=True) def archive_bookmark(self, bookmark_id): - """Archives given bookmark. - - The requested bookmark must belong to the current user. + """ + Archives given bookmark. The requested bookmark must belong to the + current user. :param bookmark_id: ID of the bookmark to archive. - """ - return self.update_bookmark(bookmark_id, archive=True) def set_read_percent_of_bookmark(self, bookmark_id, read_percent): - """Set read progress of given bookmark. - - The requested bookmark must belong to the current user. + """ + Set read progress of given bookmark. The requested bookmark must + belong to the current user. :param bookmark_id: ID of the bookmark to update. :param read_percent: The read progress made in this article, where 1.0 means the bottom and 0.0 means the very top. - """ - return self.update_bookmark(bookmark_id, read_percent=read_percent) def delete_bookmark(self, bookmark_id): - """Delete a single bookmark represented by `bookmark_id`. + """ + Delete a single bookmark represented by `bookmark_id`. The requested bookmark must belong to the current user. :param bookmark_id: ID of the bookmark to delete. - """ url = self._generate_url('bookmarks/{0}'.format(bookmark_id)) return self.delete(url) def get_bookmark_tags(self, bookmark_id): - """Retrieve tags that have been applied to a bookmark. + """ + Retrieve tags that have been applied to a bookmark. The requested bookmark must belong to the current user. :param bookmark_id: ID of the bookmark to delete. - """ url = self._generate_url('bookmarks/{0}/tags'.format(bookmark_id)) return self.get(url) def add_tags_to_bookmark(self, bookmark_id, tags): - """Add tags to to a bookmark. + """ + Add tags to to a bookmark. The identified bookmark must belong to the current user. :param bookmark_id: ID of the bookmark to delete. :param tags: Comma separated tags to be applied. - """ url = self._generate_url('bookmarks/{0}/tags'.format(bookmark_id)) params = dict(tags=tags) return self.post(url, params) def delete_tag_from_bookmark(self, bookmark_id, tag_id): - """Remove a single tag from a bookmark. + """ + Remove a single tag from a bookmark. The identified bookmark must belong to the current user. :param bookmark_id: ID of the bookmark to delete. - """ url = self._generate_url('bookmarks/{0}/tags/{1}'.format( bookmark_id, tag_id)) return self.delete(url) def get_tag(self, tag_id): - """Get a single tag represented by `tag_id`. + """ + Get a single tag represented by `tag_id`. The requested tag must belong to the current user. :param tag_id: ID fo the tag to retrieve. - """ url = self._generate_url('tags/{0}'.format(tag_id)) return self.get(url) def get_tags(self): - """Get all tags belonging to the current user. - + """ + Get all tags belonging to the current user. """ url = self._generate_url('tags') return self.get(url) def get_user(self): - """Retrives the current user. - + """ + Retrives the current user. """ url = self._generate_url('users/_current') return self.get(url) class ParserClient(BaseClient): - """Client for interacting with the Readability Parser API. + """ + Client for interacting with the Readability Parser API. Docs can be found at `http://www.readability.com/developers/api/parser`. - """ - def __init__(self, token, base_url_template=DEFAULT_PARSER_URL_TEMPLATE): - """Initialize client. + """ + Initialize client. :param token: parser API token. :param base_url_template (optional): Template used to build URL to @@ -353,33 +342,32 @@ def __init__(self, token, base_url_template=DEFAULT_PARSER_URL_TEMPLATE): self.token = token self.base_url_template = base_url_template - def get(self, url): - """Make an HTTP GET request to the Parser API. + """ + Make an HTTP GET request to the Parser API. :param url: url to which to make the request - """ logger.debug('Making GET request to %s', url) http = httplib2.Http() return self._create_response(*http.request(url, 'GET')) def head(self, url): - """Make an HTTP HEAD request to the Parser API. + """ + Make an HTTP HEAD request to the Parser API. :param url: url to which to make the request - """ logger.debug('Making HEAD request to %s', url) http = httplib2.Http() return self._create_response(*http.request(url, 'HEAD')) def post(self, url, post_params=None): - """Make an HTTP POST request to the Parser API. + """ + Make an HTTP POST request to the Parser API. :param url: url to which to make the request :param post_params: POST data to send along. Expected to be a dict. - """ post_params['token'] = self.token params = urllib.urlencode(post_params) @@ -388,12 +376,12 @@ def post(self, url, post_params=None): return self._create_response(*http.request(url, 'POST', body=params)) def _generate_url(self, resource, query_params=None): - """Build the url to resource. + """ + Build the url to resource. :param resource: Name of the resource that is being called. Options are `''` (empty string) for root resource, `'parser'`, `'confidence'`. :param query_params: Data to be passed as query parameters. - """ if query_params: # extra & is for the token to be added @@ -412,14 +400,15 @@ def _generate_url(self, resource, query_params=None): return self.base_url_template.format(resource) def get_root(self): - """Send a GET request to the root resource of the Parser API. - + """ + Send a GET request to the root resource of the Parser API. """ url = self._generate_url('') return self.get(url) def get_article_content(self, url=None, article_id=None, max_pages=25): - """Send a GET request to the `parser` endpoint of the parser API to get + """ + Send a GET request to the `parser` endpoint of the parser API to get article content. The article can be identified by either a URL or an id that exists @@ -443,7 +432,8 @@ def get_article_content(self, url=None, article_id=None, max_pages=25): return self.get(url) def post_article_content(self, content, url, max_pages=25): - """POST content to be parsed to the Parser API. + """ + POST content to be parsed to the Parser API. Note: Even when POSTing content, a url must still be provided. @@ -451,7 +441,6 @@ def post_article_content(self, content, url, max_pages=25): :param url: the url that represents the content :param max_pages (optional): the maximum number of pages to parse and combine. Default is 25. - """ params = { 'doc': content, @@ -462,7 +451,8 @@ def post_article_content(self, content, url, max_pages=25): return self.post(url, post_params=params) def get_article_status(self, url=None, article_id=None): - """Send a HEAD request to the `parser` endpoint to the parser API to + """ + Send a HEAD request to the `parser` endpoint to the parser API to get the articles status. Returned is a `httplib2.Response` object. The id and status for the @@ -484,7 +474,8 @@ def get_article_status(self, url=None, article_id=None): return self.head(url) def get_confidence(self, url=None, article_id=None): - """Send a GET request to the `confidence` endpoint of the Parser API. + """ + Send a GET request to the `confidence` endpoint of the Parser API. Note that either the `url` or `article_id` param should be passed. diff --git a/readability/tests/test_auth.py b/readability/tests/test_auth.py index 01be154..74cb9f8 100644 --- a/readability/tests/test_auth.py +++ b/readability/tests/test_auth.py @@ -9,13 +9,13 @@ class XAuthTestCase(TestCase): - """Test XAuth functionality. - + """ + Test XAuth functionality. """ def test_bad_base_url(self): - """If given a bad base url template, the request to the + """ + If given a bad base url template, the request to the ACCESS_TOKEN_URL should fail and an exception be raised. - """ token = None with self.assertRaises(Exception): @@ -24,9 +24,9 @@ def test_bad_base_url(self): self.assertEqual(token, None) def test_bad_consumer_key(self): - """If given a bad consumer key, the `xauth` method should raise + """ + If given a bad consumer key, the `xauth` method should raise an exception. - """ token = None with self.assertRaises(Exception): @@ -35,9 +35,9 @@ def test_bad_consumer_key(self): self.assertEqual(token, None) def test_bad_consumer_secret(self): - """If given a bad consumer key, the `xauth` method should raise + """ + If given a bad consumer key, the `xauth` method should raise an exception. - """ token = None with self.assertRaises(Exception): @@ -46,8 +46,8 @@ def test_bad_consumer_secret(self): self.assertEqual(token, None) def test_bad_username(self): - """If given a bad username, an exception should be raised. - + """ + If given a bad username, an exception should be raised. """ token = None with self.assertRaises(Exception): @@ -56,8 +56,8 @@ def test_bad_username(self): self.assertEqual(token, None) def test_bad_password(self): - """If given a bad password, an exception should be raised. - + """ + If given a bad password, an exception should be raised. """ token = None with self.assertRaises(Exception): @@ -66,8 +66,8 @@ def test_bad_password(self): self.assertEqual(token, None) def test_successful_auth(self): - """Test getting a token with proper creds - + """ + Test getting a token with proper creds """ token = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD) self.assertEqual(len(token), 2) diff --git a/readability/tests/test_clients.py b/readability/tests/test_clients.py index 3e253c8..cbf26c4 100644 --- a/readability/tests/test_clients.py +++ b/readability/tests/test_clients.py @@ -9,12 +9,12 @@ class ReaderClientNoBookmarkTest(TestCase): - """Tests for the Readability ReaderClient class that need no bookmarks. - + """ + Tests for the Readability ReaderClient class that need no bookmarks. """ def setUp(self): - """Need to get a token for each test. - + """ + Need to get a token for each test. """ token_pair = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD) self.token_key = token_pair[0] @@ -24,8 +24,8 @@ def setUp(self): self.token_key, self.token_secret) def test_get_article(self): - """Test the `get_article` method. - + """ + Test the `get_article` method. """ article_id = 'lun3elns' response = self.base_client.get_article(article_id) @@ -39,8 +39,8 @@ def test_get_article(self): self.assertTrue(some_expected_keys.issubset(keys_set)) def test_get_article_404(self): - """Try getting an article that doesn't exist. - + """ + Try getting an article that doesn't exist. """ article_id = 1 response = self.base_client.get_article(article_id) @@ -49,8 +49,8 @@ def test_get_article_404(self): self.assertTrue('error_message' in response.content) def test_get_user(self): - """Test getting user data - + """ + Test getting user data """ user_response = self.base_client.get_user() self.assertEqual(user_response.status, 200) @@ -60,8 +60,8 @@ def test_get_user(self): self.assertTrue(some_expected_keys.issubset(received_keys)) def _test_get_tags(self): - """Test getting tags. - + """ + Test getting tags. """ tag_response = self.base_client.get_tags() self.assertEqual(tag_response.status, 200) @@ -70,12 +70,12 @@ def _test_get_tags(self): class ReaderClientSingleBookmarkTest(TestCase): - """Tests that only need one bookmark - + """ + Tests that only need one bookmark """ def setUp(self): - """Get a client and add a bookmark - + """ + Get a client and add a bookmark """ token_pair = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD) self.token_key = token_pair[0] @@ -89,16 +89,16 @@ def setUp(self): self.assertEqual(add_response.status, 202) def tearDown(self): - """Remove all added bookmarks. - + """ + Remove all added bookmarks. """ for bm in self.base_client.get_bookmarks().content['bookmarks']: del_response = self.base_client.delete_bookmark(bm['id']) self.assertEqual(del_response.status, 204) def test_get_bookmark(self): - """Test getting one bookmark by id - + """ + Test getting one bookmark by id """ # get a bookmark id bm_response = self.base_client.get_bookmarks() @@ -114,8 +114,8 @@ def test_get_bookmark(self): def test_bookmark_tag_functionality(self): - """Test adding, fetching and deleting tags on a bookmark. - + """ + Test adding, fetching and deleting tags on a bookmark. """ # get a bookmark id bm_response = self.base_client.get_bookmarks() @@ -169,13 +169,12 @@ def test_bookmark_tag_functionality(self): class ReaderClientMultipleBookmarkTest(TestCase): - """Tests for bookmark functionality - """ - + Tests for bookmark functionality + """ def setUp(self): - """Add a few bookmarks. - + """ + Add a few bookmarks. """ token_pair = xauth(CONSUMER_KEY, CONSUMER_SECRET, USERNAME, PASSWORD) self.token_key = token_pair[0] @@ -214,8 +213,8 @@ def setUp(self): self.assertEqual(add_response.status, 202) def test_get_bookmarks(self): - """Test getting all bookmarks - + """ + Test getting all bookmarks """ bm_response = self.base_client.get_bookmarks() self.assertEqual(bm_response.status, 200) @@ -239,8 +238,8 @@ def test_get_bookmarks(self): self.assertTrue(bm['article']['url'] in self.archive_urls) def tearDown(self): - """Remove all added bookmarks. - + """ + Remove all added bookmarks. """ for bm in self.base_client.get_bookmarks().content['bookmarks']: del_response = self.base_client.delete_bookmark(bm['id']) @@ -248,17 +247,16 @@ def tearDown(self): class ParserClientTest(TestCase): - """Test case for the Parser Client - """ - + Test case for the Parser Client + """ def setUp(self): self.parser_client = ParserClient(PARSER_TOKEN) self.test_url = 'https://en.wikipedia.org/wiki/Mark_Twain' def test_generate_url(self): - """Test the clients ability to generate urls to endpoints. - + """ + Test the clients ability to generate urls to endpoints. """ # test root resource expected_url = DEFAULT_PARSER_URL_TEMPLATE.format('') @@ -276,8 +274,8 @@ def test_generate_url(self): self.assertEqual(generated_url, expected_url) def test_get_root(self): - """Test the client's ability to hit the root endpoint. - + """ + Test the client's ability to hit the root endpoint. """ response = self.parser_client.get_root() @@ -285,8 +283,8 @@ def test_get_root(self): self.assertEqual(set(response.content.keys()), expected_keys) def test_get_confidence(self): - """Test the client's ability to hit the confidence endpoint. - + """ + Test the client's ability to hit the confidence endpoint. """ # hit without an article_id or url. Should get an error. response = self.parser_client.get_confidence() @@ -301,9 +299,8 @@ def test_get_confidence(self): self.assertTrue(response.content['confidence'] >= .5) def test_get_article_status(self): - """Test the client's ability to hit the parser endpoint with a HEAD - request. - + """ + Test the client's ability to hit the parser endpoint with a HEAD """ # hit without an article_id or url. Should get an error. response = self.parser_client.get_confidence() @@ -315,9 +312,8 @@ def test_get_article_status(self): self.assertTrue(response.get('x-article-id') is not None) def test_get_article_content(self): - """Test the client's ability to hit the parser endpoint with a GET - request. - + """ + Test the client's ability to hit the parser endpoint with a GET """ # test with incorrect params response = self.parser_client.get_article_content() @@ -332,9 +328,9 @@ def test_get_article_content(self): some_expected_keys.issubset(set(response.content.keys()))) def test_post_article_content(self): - """Test the client's ability to hit the parser endpoint with a POST + """ + Test the client's ability to hit the parser endpoint with a POST request. - """ # I'm sorry... content = """ diff --git a/readability/tests/test_utils.py b/readability/tests/test_utils.py index fc93f08..546e3be 100644 --- a/readability/tests/test_utils.py +++ b/readability/tests/test_utils.py @@ -8,29 +8,28 @@ class CastDatetimeFilterTestCase(TestCase): - """Tests for the `cast_datetime_filter` function. - + """ + Tests for the `cast_datetime_filter` function. """ def test_int(self): - """Pass an int. Should raise a `ValueError` - + """ + Pass an int. Should raise a `ValueError` """ with self.assertRaises(ValueError): cast_datetime_filter(1) def test_non_iso_string(self): - """Pass a string that's not in ISO format. - - Should get a string back that's in ISO format. - + """ + Pass a string that's not in ISO format. Should get a string back + that's in ISO format. """ date_string = '08-03-2010' expected_iso = cast_datetime_filter(date_string) self.assertEqual(expected_iso, '2010-08-03T00:00:00') def test_datetime_object(self): - """Pass a datetime object. Should get a string back in ISO format. - + """ + Pass a datetime object. Should get a string back in ISO format. """ now = datetime.now() expected_output = now.isoformat() @@ -39,36 +38,36 @@ def test_datetime_object(self): class CastIntegerFilter(TestCase): - """Test for the `cast_integer_filter` function. - + """ + Test for the `cast_integer_filter` function. """ def test_int(self): - """Pass an int. Should get it back. - + """ + Pass an int. Should get it back. """ value_to_cast = 1 output = cast_integer_filter(value_to_cast) self.assertEqual(value_to_cast, output) def test_false(self): - """Pass a boolean False. Should get a 0 back. - + """ + Pass a boolean False. Should get a 0 back. """ output = cast_integer_filter(False) expected_output = 0 self.assertEqual(output, expected_output) def test_true(self): - """Pass a boolean True. Should get a 1 back. - + """ + Pass a boolean True. Should get a 1 back. """ output = cast_integer_filter(True) expected_output = 1 self.assertEqual(output, expected_output) def test_numeric_string(self): - """Pass a numeric string. Should get the integer version back. - + """ + Pass a numeric string. Should get the integer version back. """ numeric_string = '123' expected_output = 123 @@ -77,12 +76,12 @@ def test_numeric_string(self): class FilterArgsToDictTestCase(TestCase): - """Test for the `filter_args_to_dict` function. - """ - + Test for the `filter_args_to_dict` function. + """ def test_all_bad_filter_keys(self): - """Pass a dict who's keys are not in the acceptable filter list. + """ + Pass a dict who's keys are not in the acceptable filter list. Should get an empty dict back. """ @@ -97,8 +96,8 @@ def test_all_bad_filter_keys(self): self.assertEqual(expected_empty, {}) def test_some_bad_filter_keys(self): - """Pass a mixture of good and bad filter keys. - + """ + Pass a mixture of good and bad filter keys. """ filters = { 'favorite': True, @@ -117,8 +116,8 @@ def test_some_bad_filter_keys(self): self.assertEqual(set(filter_dict.keys()), set(acceptable_filter_keys)) def test_casting_of_integer_filters(self): - """Pass keys that correspond to integer filters. - + """ + Pass keys that correspond to integer filters. """ filters = { 'favorite': True, @@ -131,8 +130,8 @@ def test_casting_of_integer_filters(self): self.assertEqual(filter_dict['archive'], 0) def test_casting_of_datetime_filters(self): - """Pass keys that correspond to datetime filters. - + """ + Pass keys that correspond to datetime filters. """ now = datetime.now() filters = { From ae3e5ede556365a32031e638b6aecae24b88087b Mon Sep 17 00:00:00 2001 From: Chris Schomaker Date: Wed, 2 Apr 2014 12:25:08 -0700 Subject: [PATCH 4/4] Add test for update_bookmark method --- readability/tests/test_clients.py | 80 +++++++++++++++++-------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/readability/tests/test_clients.py b/readability/tests/test_clients.py index cbf26c4..1d3e33f 100644 --- a/readability/tests/test_clients.py +++ b/readability/tests/test_clients.py @@ -20,7 +20,7 @@ def setUp(self): self.token_key = token_pair[0] self.token_secret = token_pair[1] - self.base_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET, + self.reader_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET, self.token_key, self.token_secret) def test_get_article(self): @@ -28,7 +28,7 @@ def test_get_article(self): Test the `get_article` method. """ article_id = 'lun3elns' - response = self.base_client.get_article(article_id) + response = self.reader_client.get_article(article_id) self.assertEqual(response.status, 200) self.assertTrue(isinstance(response.content, dict)) @@ -43,7 +43,7 @@ def test_get_article_404(self): Try getting an article that doesn't exist. """ article_id = 1 - response = self.base_client.get_article(article_id) + response = self.reader_client.get_article(article_id) self.assertEqual(response.status, 404) self.assertTrue(isinstance(response.content, dict)) self.assertTrue('error_message' in response.content) @@ -52,7 +52,7 @@ def test_get_user(self): """ Test getting user data """ - user_response = self.base_client.get_user() + user_response = self.reader_client.get_user() self.assertEqual(user_response.status, 200) some_expected_keys = set(['username', 'first_name', 'last_name', 'date_joined', 'email_into_address']) @@ -63,7 +63,7 @@ def _test_get_tags(self): """ Test getting tags. """ - tag_response = self.base_client.get_tags() + tag_response = self.reader_client.get_tags() self.assertEqual(tag_response.status, 200) self.assertTrue('tags' in tag_response.content) self.assertTrue(len(tag_response.content['tags']) > 0) @@ -81,50 +81,49 @@ def setUp(self): self.token_key = token_pair[0] self.token_secret = token_pair[1] - self.base_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET, + self.reader_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET, self.token_key, self.token_secret) self.url = 'http://www.theatlantic.com/technology/archive/2013/01/the-never-before-told-story-of-the-worlds-first-computer-art-its-a-sexy-dame/267439/' - add_response = self.base_client.add_bookmark(self.url) + add_response = self.reader_client.add_bookmark(self.url) self.assertEqual(add_response.status, 202) def tearDown(self): """ Remove all added bookmarks. """ - for bm in self.base_client.get_bookmarks().content['bookmarks']: - del_response = self.base_client.delete_bookmark(bm['id']) + for bm in self.reader_client.get_bookmarks().content['bookmarks']: + del_response = self.reader_client.delete_bookmark(bm['id']) self.assertEqual(del_response.status, 204) def test_get_bookmark(self): """ Test getting one bookmark by id """ - # get a bookmark id - bm_response = self.base_client.get_bookmarks() - self.assertEqual(bm_response.status, 200) - self.assertTrue(len(bm_response.content['bookmarks']) > 0) - bookmark_id = bm_response.content['bookmarks'][0]['id'] + bookmark_id = self._get_bookmark_data()['id'] - bm_response = self.base_client.get_bookmark(bookmark_id) + bm_response = self.reader_client.get_bookmark(bookmark_id) self.assertEqual(bm_response.status, 200) some_expected_keys = set(['article', 'user_id', 'favorite', 'id']) received_keys = set(bm_response.content.keys()) self.assertTrue(some_expected_keys.issubset(received_keys)) + def test_archive_bookmark(self): + """ + Test archiving a bookmark. The ``archive_bookmark`` method is just + a convenient wrapper around the ``update_bookmark`` method but + we'll go ahead and test it anyway. + """ + bm_data = self._get_bookmark_data() def test_bookmark_tag_functionality(self): """ Test adding, fetching and deleting tags on a bookmark. """ - # get a bookmark id - bm_response = self.base_client.get_bookmarks() - self.assertEqual(bm_response.status, 200) - self.assertTrue(len(bm_response.content['bookmarks']) > 0) - bookmark_id = bm_response.content['bookmarks'][0]['id'] + bookmark_id = self._get_bookmark_data()['id'] # test getting empty tags - tag_response = self.base_client.get_bookmark_tags(bookmark_id) + tag_response = self.reader_client.get_bookmark_tags(bookmark_id) self.assertEqual(tag_response.status, 200) self.assertEqual(len(tag_response.content['tags']), 0) @@ -132,25 +131,25 @@ def test_bookmark_tag_functionality(self): tags = ['tag', 'another tag'] tag_string = ', '.join(tags) tag_add_response = \ - self.base_client.add_tags_to_bookmark(bookmark_id, tag_string) + self.reader_client.add_tags_to_bookmark(bookmark_id, tag_string) self.assertEqual(tag_add_response.status, 202) # re-fetch tags. should have 2 - retag_response = self.base_client.get_bookmark_tags(bookmark_id) + retag_response = self.reader_client.get_bookmark_tags(bookmark_id) self.assertEqual(retag_response.status, 200) self.assertEqual(len(retag_response.content['tags']), 2) for tag in retag_response.content['tags']: self.assertTrue(tag['text'] in tags) # test getting tags for user - user_tag_resp = self.base_client.get_tags() + user_tag_resp = self.reader_client.get_tags() self.assertEqual(user_tag_resp.status, 200) self.assertEqual(len(user_tag_resp.content['tags']), 2) for tag in user_tag_resp.content['tags']: self.assertTrue(tag['text'] in tags) # test getting a single tag while we're here - single_tag_resp = self.base_client.get_tag(tag['id']) + single_tag_resp = self.reader_client.get_tag(tag['id']) self.assertEqual(single_tag_resp.status, 200) self.assertTrue('applied_count' in single_tag_resp.content) self.assertTrue('id' in single_tag_resp.content) @@ -158,15 +157,24 @@ def test_bookmark_tag_functionality(self): # delete tags for tag in retag_response.content['tags']: - del_response = self.base_client.delete_tag_from_bookmark( + del_response = self.reader_client.delete_tag_from_bookmark( bookmark_id, tag['id']) self.assertEqual(del_response.status, 204) # check that tags are gone - tag_response = self.base_client.get_bookmark_tags(bookmark_id) + tag_response = self.reader_client.get_bookmark_tags(bookmark_id) self.assertEqual(tag_response.status, 200) self.assertEqual(len(tag_response.content['tags']), 0) + def _get_bookmark_data(self): + """ + Convenience method to get a single bookmark's data. + """ + bm_response = self.reader_client.get_bookmarks() + self.assertEqual(bm_response.status, 200) + self.assertTrue(len(bm_response.content['bookmarks']) > 0) + return bm_response.content['bookmarks'][0] + class ReaderClientMultipleBookmarkTest(TestCase): """ @@ -180,7 +188,7 @@ def setUp(self): self.token_key = token_pair[0] self.token_secret = token_pair[1] - self.base_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET, + self.reader_client = ReaderClient(CONSUMER_KEY, CONSUMER_SECRET, self.token_key, self.token_secret) self.urls = [ @@ -201,28 +209,28 @@ def setUp(self): self.all_urls = self.urls + self.favorite_urls + self.archive_urls for url in self.urls: - add_response = self.base_client.add_bookmark(url) + add_response = self.reader_client.add_bookmark(url) self.assertEqual(add_response.status, 202) for url in self.favorite_urls: - add_response = self.base_client.add_bookmark(url, favorite=True) + add_response = self.reader_client.add_bookmark(url, favorite=True) self.assertEqual(add_response.status, 202) for url in self.archive_urls: - add_response = self.base_client.add_bookmark(url, archive=True) + add_response = self.reader_client.add_bookmark(url, archive=True) self.assertEqual(add_response.status, 202) def test_get_bookmarks(self): """ Test getting all bookmarks """ - bm_response = self.base_client.get_bookmarks() + bm_response = self.reader_client.get_bookmarks() self.assertEqual(bm_response.status, 200) self.assertEqual( len(bm_response.content['bookmarks']), len(self.all_urls)) # test favorite bookmarks - bm_response = self.base_client.get_bookmarks(favorite=True) + bm_response = self.reader_client.get_bookmarks(favorite=True) self.assertEqual(bm_response.status, 200) self.assertEqual( len(bm_response.content['bookmarks']), len(self.favorite_urls)) @@ -230,7 +238,7 @@ def test_get_bookmarks(self): self.assertTrue(bm['article']['url'] in self.favorite_urls) # test archive bookmarks - bm_response = self.base_client.get_bookmarks(archive=True) + bm_response = self.reader_client.get_bookmarks(archive=True) self.assertEqual(bm_response.status, 200) self.assertEqual( len(bm_response.content['bookmarks']), len(self.archive_urls)) @@ -241,8 +249,8 @@ def tearDown(self): """ Remove all added bookmarks. """ - for bm in self.base_client.get_bookmarks().content['bookmarks']: - del_response = self.base_client.delete_bookmark(bm['id']) + for bm in self.reader_client.get_bookmarks().content['bookmarks']: + del_response = self.reader_client.delete_bookmark(bm['id']) self.assertEqual(del_response.status, 204)