Hello community,

here is the log from the commit of package python-tweepy for openSUSE:Factory 
checked in at 2013-11-24 12:32:22
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-tweepy (Old)
 and      /work/SRC/openSUSE:Factory/.python-tweepy.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-tweepy"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-tweepy/python-tweepy.changes      
2013-10-25 11:34:23.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python-tweepy.new/python-tweepy.changes 
2013-11-24 12:32:23.000000000 +0100
@@ -1,0 +2,6 @@
+Fri Nov 15 23:25:43 UTC 2013 - [email protected]
+
+- Update to version 2.1
+  + No changelog available
+
+-------------------------------------------------------------------

Old:
----
  tweepy-2.0.tar.gz

New:
----
  tweepy-2.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-tweepy.spec ++++++
--- /var/tmp/diff_new_pack.PRtI4N/_old  2013-11-24 12:32:23.000000000 +0100
+++ /var/tmp/diff_new_pack.PRtI4N/_new  2013-11-24 12:32:23.000000000 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           python-tweepy
-Version:        2.0
+Version:        2.1
 Release:        0
 Url:            http://github.com/joshthecoder/tweepy
 Summary:        Twitter library for python

++++++ tweepy-2.0.tar.gz -> tweepy-2.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/PKG-INFO new/tweepy-2.1/PKG-INFO
--- old/tweepy-2.0/PKG-INFO     2013-02-10 22:45:51.000000000 +0100
+++ new/tweepy-2.1/PKG-INFO     2013-07-14 20:59:03.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: tweepy
-Version: 2.0
+Version: 2.1
 Summary: Twitter library for python
 Home-page: http://github.com/tweepy/tweepy
 Author: Joshua Roesslein
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tests/__init__.py 
new/tweepy-2.1/tests/__init__.py
--- old/tweepy-2.0/tests/__init__.py    1970-01-01 01:00:00.000000000 +0100
+++ new/tweepy-2.1/tests/__init__.py    2013-05-19 10:17:49.000000000 +0200
@@ -0,0 +1 @@
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tests/config.py 
new/tweepy-2.1/tests/config.py
--- old/tweepy-2.0/tests/config.py      1970-01-01 01:00:00.000000000 +0100
+++ new/tweepy-2.1/tests/config.py      2013-06-08 22:30:54.000000000 +0200
@@ -0,0 +1,15 @@
+import os
+
+from tweepy.auth import OAuthHandler
+
+username = os.environ.get('TWITTER_USERNAME', '')
+oauth_consumer_key = os.environ.get('CONSUMER_KEY', '')
+oauth_consumer_secret = os.environ.get('CONSUMER_SECRET', '')
+oauth_token = os.environ.get('ACCESS_KEY', '')
+oauth_token_secret = os.environ.get('ACCESS_SECRET', '')
+
+def create_auth():
+    auth = OAuthHandler(oauth_consumer_key, oauth_consumer_secret)
+    auth.set_access_token(oauth_token, oauth_token_secret)
+    return auth
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tests/mock.py new/tweepy-2.1/tests/mock.py
--- old/tweepy-2.0/tests/mock.py        1970-01-01 01:00:00.000000000 +0100
+++ new/tweepy-2.1/tests/mock.py        2013-05-19 10:17:49.000000000 +0200
@@ -0,0 +1,8 @@
+import random
+import string
+
+def mock_tweet():
+    """Generate some random tweet text."""
+    count = random.randint(70, 140)
+    return ''.join([random.choice(string.letters) for i in xrange(count)])
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tests/test_api.py 
new/tweepy-2.1/tests/test_api.py
--- old/tweepy-2.0/tests/test_api.py    1970-01-01 01:00:00.000000000 +0100
+++ new/tweepy-2.1/tests/test_api.py    2013-06-11 05:30:38.000000000 +0200
@@ -0,0 +1,359 @@
+import unittest
+import random
+from time import sleep
+import os
+
+from nose import SkipTest
+
+from tweepy import (API, OAuthHandler, Friendship, Cursor,
+                    MemoryCache, FileCache)
+
+from config import *
+
+test_tweet_id = '266367358078169089'
+
+"""Unit tests"""
+
+class TweepyErrorTests(unittest.TestCase):
+
+    def testpickle(self):
+        """Verify exceptions can be pickled and unpickled."""
+        import pickle
+        from tweepy.error import TweepError
+
+        e = TweepError('no reason', {'status': 200})
+        e2 = pickle.loads(pickle.dumps(e))
+
+        self.assertEqual(e.reason, e2.reason)
+        self.assertEqual(e.response, e2.response)
+
+class TweepyAPITests(unittest.TestCase):
+
+    def setUp(self):
+        auth = OAuthHandler(oauth_consumer_key, oauth_consumer_secret)
+        auth.set_access_token(oauth_token, oauth_token_secret)
+        self.api = API(auth)
+        self.api.retry_count = 2
+        self.api.retry_delay = 5
+
+    # TODO: Actually have some sort of better assertion
+    def testgetoembed(self):
+        data = self.api.get_oembed(test_tweet_id)
+        self.assertEqual(data['author_name'], "Twitter")
+
+
+    def testhometimeline(self):
+        self.api.home_timeline()
+
+    def testusertimeline(self):
+        self.api.user_timeline()
+        self.api.user_timeline('twitter')
+
+    def testmentionstimeline(self):
+        self.api.mentions_timeline()
+
+    def testretweetsofme(self):
+        self.api.retweets_of_me()
+
+    def testretweet(self):
+        # TODO(josh): Need a way to get random tweets to retweet.
+        raise SkipTest()
+
+    def testretweets(self):
+        self.api.retweets(test_tweet_id)
+
+    def testgetstatus(self):
+        self.api.get_status(id=test_tweet_id)
+
+    def testupdateanddestroystatus(self):
+        # test update
+        text = 'testing %i' % random.randint(0, 1000)
+        update = self.api.update_status(status=text)
+        self.assertEqual(update.text, text)
+
+        # test destroy
+        deleted = self.api.destroy_status(id=update.id)
+        self.assertEqual(deleted.id, update.id)
+
+    def testgetuser(self):
+        u = self.api.get_user('twitter')
+        self.assertEqual(u.screen_name, 'twitter')
+
+        u = self.api.get_user(783214)
+        self.assertEqual(u.screen_name, 'twitter')
+
+    def testsearchusers(self):
+        self.api.search_users('twitter')
+
+    def testsuggestedcategories(self):
+        self.api.suggested_categories()
+
+    def testsuggestedusers(self):
+        categories = self.api.suggested_categories()
+        if len(categories) != 0:
+            self.api.suggested_users(categories[0].slug)
+
+    def testsuggesteduserstweets(self):
+        categories = self.api.suggested_categories()
+        if len(categories) != 0:
+            self.api.suggested_users_tweets(categories[0].slug)
+
+    def testme(self):
+        me = self.api.me()
+        self.assertEqual(me.screen_name, username)
+
+    def testdirectmessages(self):
+        self.api.direct_messages()
+
+    def testsentdirectmessages(self):
+        self.api.sent_direct_messages()
+
+    def testsendanddestroydirectmessage(self):
+        # send
+        sent_dm = self.api.send_direct_message(username, text='test message')
+        self.assertEqual(sent_dm.text, 'test message')
+        self.assertEqual(sent_dm.sender.screen_name, username)
+        self.assertEqual(sent_dm.recipient.screen_name, username)
+
+        # destroy
+        destroyed_dm = self.api.destroy_direct_message(sent_dm.id)
+        self.assertEqual(destroyed_dm.text, sent_dm.text)
+        self.assertEqual(destroyed_dm.id, sent_dm.id)
+        self.assertEqual(destroyed_dm.sender.screen_name, username)
+        self.assertEqual(destroyed_dm.recipient.screen_name, username)
+
+    def testcreatedestroyfriendship(self):
+        enemy = self.api.destroy_friendship('twitter')
+        self.assertEqual(enemy.screen_name, 'twitter')
+
+        # Wait 5 seconds to allow Twitter time
+        # to process the friendship destroy request.
+        sleep(5)
+
+        friend = self.api.create_friendship('twitter')
+        self.assertEqual(friend.screen_name, 'twitter')
+
+    def testshowfriendship(self):
+        source, target = self.api.show_friendship(target_screen_name='twtiter')
+        self.assert_(isinstance(source, Friendship))
+        self.assert_(isinstance(target, Friendship))
+
+    def testfriendsids(self):
+        self.api.friends_ids(username)
+
+    def testfollowersids(self):
+        self.api.followers_ids(username)
+
+    def testfriends(self):
+        self.api.friends(username)
+
+    def testfollowers(self):
+        self.api.followers(username)
+
+    def testverifycredentials(self):
+        self.assertNotEqual(self.api.verify_credentials(), False)
+
+        # make sure that `me.status.entities` is not an empty dict
+        me = self.api.verify_credentials(include_entities=True)
+        self.assertTrue(me.status.entities)
+
+        # `status` shouldn't be included
+        me = self.api.verify_credentials(skip_status=True)
+        self.assertFalse(hasattr(me, 'status'))
+
+    def testratelimitstatus(self):
+        self.api.rate_limit_status()
+
+    """ TODO(josh): Remove once this deprecated API is gone.
+    def testsetdeliverydevice(self):
+        self.api.set_delivery_device('im')
+        self.api.set_delivery_device('none')
+    """
+
+    def testupdateprofilecolors(self):
+        original = self.api.me()
+        updated = self.api.update_profile_colors('000', '000', '000', '000', 
'000')
+
+        # restore colors
+        self.api.update_profile_colors(
+            original.profile_background_color,
+            original.profile_text_color,
+            original.profile_link_color,
+            original.profile_sidebar_fill_color,
+            original.profile_sidebar_border_color
+        )
+
+        self.assertEqual(updated.profile_background_color, '000000')
+        self.assertEqual(updated.profile_text_color, '000000')
+        self.assertEqual(updated.profile_link_color, '000000')
+        self.assertEqual(updated.profile_sidebar_fill_color, '000000')
+        self.assertEqual(updated.profile_sidebar_border_color, '000000')
+
+    """
+    def testupateprofileimage(self):
+        self.api.update_profile_image('examples/profile.png')
+
+    def testupdateprofilebg(self):
+        self.api.update_profile_background_image('examples/bg.png')
+    """
+
+    def testupdateprofile(self):
+        original = self.api.me()
+        profile = {
+            'name': 'Tweepy test 123',
+            'location': 'pytopia',
+            'description': 'just testing things out'
+        }
+        updated = self.api.update_profile(**profile)
+        self.api.update_profile(
+            name = original.name, url = original.url,
+            location = original.location, description = original.description
+        )
+
+        for k,v in profile.items():
+            if k == 'email': continue
+            self.assertEqual(getattr(updated, k), v)
+
+    def testfavorites(self):
+        self.api.favorites()
+
+    def testcreatedestroyfavorite(self):
+        self.api.create_favorite(4901062372)
+        self.api.destroy_favorite(4901062372)
+
+    def testcreatedestroyblock(self):
+        self.api.create_block('twitter')
+        self.api.destroy_block('twitter')
+        self.api.create_friendship('twitter') # restore
+
+    def testblocks(self):
+        self.api.blocks()
+
+    def testblocksids(self):
+        self.api.blocks_ids()
+
+    def testcreateupdatedestroylist(self):
+        params = {
+            'owner_screen_name': username,
+            'slug': 'tweeps'
+        }
+        l = self.api.create_list(name=params['slug'], **params)
+        l = self.api.update_list(list_id=l.id, description='updated!')
+        self.assertEqual(l.description, 'updated!')
+        self.api.destroy_list(list_id=l.id)
+
+    def testlistsall(self):
+        self.api.lists_all()
+
+    def testlistsmemberships(self):
+        self.api.lists_memberships()
+
+    def testlistssubscriptions(self):
+        self.api.lists_subscriptions()
+
+    def testlisttimeline(self):
+        self.api.list_timeline('applepie', 'stars')
+
+    def testgetlist(self):
+        self.api.get_list(owner_screen_name='applepie', slug='stars')
+
+    def testaddremovelistmember(self):
+        params = {
+            'slug': 'test',
+            'owner_screen_name': username,
+            'screen_name': 'twitter'
+        }
+
+        def assert_list(l):
+            self.assertEqual(l.name, params['slug'])
+
+        assert_list(self.api.add_list_member(**params))
+        assert_list(self.api.remove_list_member(**params))
+
+    def testlistmembers(self):
+        self.api.list_members('applepie', 'stars')
+
+    def testshowlistmember(self):
+        
self.assertTrue(self.api.show_list_member(owner_screen_name='applepie', 
slug='stars', screen_name='NathanFillion'))
+
+    def testsubscribeunsubscribelist(self):
+        params = {
+            'owner_screen_name': 'applepie',
+            'slug': 'stars'
+        }
+        self.api.subscribe_list(**params)
+        self.api.unsubscribe_list(**params)
+
+    def testlistsubscribers(self):
+        self.api.list_subscribers('applepie', 'stars')
+
+    def testshowlistsubscriber(self):
+        self.assertTrue(self.api.show_list_subscriber('twitter', 'team', 
username))
+
+    def testsavedsearches(self):
+        s = self.api.create_saved_search('test')
+        self.api.saved_searches()
+        self.assertEqual(self.api.get_saved_search(s.id).query, 'test')
+        self.api.destroy_saved_search(s.id)
+
+    def testsearch(self):
+        self.api.search('tweepy')
+
+    def testgeoapis(self):
+        def place_name_in_list(place_name, place_list):
+            """Return True if a given place_name is in place_list."""
+            return any([x.full_name.lower() == place_name.lower() for x in 
place_list])
+
+        twitter_hq = self.api.geo_similar_places(lat=37, long= -122, 
name='Twitter HQ')
+        # Assumes that twitter_hq is first Place returned...
+        self.assertEqual(twitter_hq[0].id, '3bdf30ed8b201f31')
+        # Test various API functions using Austin, TX, USA
+        self.assertEqual(self.api.geo_id(id='c3f37afa9efcf94b').full_name, 
'Austin, TX')
+        self.assertTrue(place_name_in_list('Austin, TX',
+            self.api.reverse_geocode(lat=30.267370168467806, long= 
-97.74261474609375))) # Austin, TX, USA
+
+class TweepyCacheTests(unittest.TestCase):
+
+    timeout = 2.0
+    memcache_servers = ['127.0.0.1:11211']  # must be running for test to pass
+
+    def _run_tests(self, do_cleanup=True):
+        # test store and get
+        self.cache.store('testkey', 'testvalue')
+        self.assertEqual(self.cache.get('testkey'), 'testvalue',
+            'Stored value does not match retrieved value')
+
+        # test timeout
+        sleep(self.timeout)
+        self.assertEqual(self.cache.get('testkey'), None,
+            'Cache entry should have expired')
+
+        # test cleanup
+        if do_cleanup:
+            self.cache.store('testkey', 'testvalue')
+            sleep(self.timeout)
+            self.cache.cleanup()
+            self.assertEqual(self.cache.count(), 0, 'Cache cleanup failed')
+
+        # test count
+        for i in range(0, 20):
+            self.cache.store('testkey%i' % i, 'testvalue')
+        self.assertEqual(self.cache.count(), 20, 'Count is wrong')
+
+        # test flush
+        self.cache.flush()
+        self.assertEqual(self.cache.count(), 0, 'Cache failed to flush')
+
+    def testmemorycache(self):
+        self.cache = MemoryCache(timeout=self.timeout)
+        self._run_tests()
+
+    def testfilecache(self):
+        os.mkdir('cache_test_dir')
+        self.cache = FileCache('cache_test_dir', self.timeout)
+        self._run_tests()
+        self.cache.flush()
+        os.rmdir('cache_test_dir')
+
+if __name__ == '__main__':
+    unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tests/test_auth.py 
new/tweepy-2.1/tests/test_auth.py
--- old/tweepy-2.0/tests/test_auth.py   1970-01-01 01:00:00.000000000 +0100
+++ new/tweepy-2.1/tests/test_auth.py   2013-06-08 22:30:54.000000000 +0200
@@ -0,0 +1,23 @@
+import unittest
+
+from config import *
+from tweepy import API, OAuthHandler
+
+class TweepyAuthTests(unittest.TestCase):
+
+    def testoauth(self):
+        auth = OAuthHandler(oauth_consumer_key, oauth_consumer_secret)
+
+        # test getting access token
+        auth_url = auth.get_authorization_url()
+        print 'Please authorize: ' + auth_url
+        verifier = raw_input('PIN: ').strip()
+        self.assert_(len(verifier) > 0)
+        access_token = auth.get_access_token(verifier)
+        self.assert_(access_token is not None)
+
+        # build api object test using oauth
+        api = API(auth)
+        s = api.update_status('test %i' % random.randint(0, 1000))
+        api.destroy_status(s.id)
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tests/test_cursors.py 
new/tweepy-2.1/tests/test_cursors.py
--- old/tweepy-2.0/tests/test_cursors.py        1970-01-01 01:00:00.000000000 
+0100
+++ new/tweepy-2.1/tests/test_cursors.py        2013-06-16 21:31:54.000000000 
+0200
@@ -0,0 +1,33 @@
+import unittest
+
+from tweepy import API, Cursor
+
+from config import create_auth
+
+class TweepyCursorTests(unittest.TestCase):
+
+    def setUp(self):
+        self.api = API(create_auth())
+
+    def testidcursoritems(self):
+        items = list(Cursor(self.api.user_timeline).items(25))
+        self.assertEqual(len(items), 25)
+
+    def testidcursorpages(self):
+        pages = list(Cursor(self.api.user_timeline).pages(5))
+        self.assertEqual(len(pages), 5)
+
+    def testcursorcursoritems(self):
+        items = list(Cursor(self.api.friends_ids).items(10))
+        self.assertEqual(len(items), 10)
+
+        items = list(Cursor(self.api.followers_ids, 'twitter').items(10))
+        self.assertEqual(len(items), 10)
+
+    def testcursorcursorpages(self):
+        pages = list(Cursor(self.api.friends_ids).pages(1))
+        self.assert_(len(pages) == 1)
+
+        pages = list(Cursor(self.api.followers_ids, 'twitter').pages(1))
+        self.assert_(len(pages) == 1)
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tests/test_resultset.py 
new/tweepy-2.1/tests/test_resultset.py
--- old/tweepy-2.0/tests/test_resultset.py      1970-01-01 01:00:00.000000000 
+0100
+++ new/tweepy-2.1/tests/test_resultset.py      2013-06-11 05:30:38.000000000 
+0200
@@ -0,0 +1,29 @@
+import unittest
+
+from tweepy.models import ResultSet
+
+class NoIdItem(object): pass
+
+class IdItem(object):
+    def __init__(self, id):
+        self.id = id
+
+ids_fixture = [1, 10, 8, 50, 2, 100, 5]
+
+class TweepyResultSetTests(unittest.TestCase):
+    def setUp(self):
+        self.results = ResultSet()
+        for i in ids_fixture:
+            self.results.append(IdItem(i))
+            self.results.append(NoIdItem())
+
+    def testids(self):
+        ids = self.results.ids()
+        self.assertListEqual(ids, ids_fixture)
+
+    def testmaxid(self):
+        self.assertEqual(self.results.max_id, 100)
+
+    def testsinceid(self):
+        self.assertEqual(self.results.since_id, 1)
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tests/test_streaming.py 
new/tweepy-2.1/tests/test_streaming.py
--- old/tweepy-2.0/tests/test_streaming.py      1970-01-01 01:00:00.000000000 
+0100
+++ new/tweepy-2.1/tests/test_streaming.py      2013-05-19 10:17:49.000000000 
+0200
@@ -0,0 +1,64 @@
+from time import sleep
+import unittest
+
+from tweepy.api import API
+from tweepy.models import Status
+from tweepy.streaming import Stream, StreamListener
+
+from config import create_auth
+from mock import mock_tweet
+
+class MockStreamListener(StreamListener):
+    def __init__(self, test_case):
+        super(MockStreamListener, self).__init__()
+        self.test_case = test_case
+        self.status_count = 0
+        self.status_stop_count = 0
+        self.connect_cb = None
+
+    def on_connect(self):
+        if self.connect_cb:
+            self.connect_cb()
+
+    def on_timeout(self):
+        self.test_case.fail('timeout')
+        return False
+
+    def on_status(self, status):
+        self.status_count += 1
+        self.test_case.assertIsInstance(status, Status)
+        if self.status_stop_count == self.status_count:
+            return False
+
+class TweepyStreamTests(unittest.TestCase):
+    def setUp(self):
+        self.auth = create_auth()
+        self.listener = MockStreamListener(self)
+        self.stream = Stream(self.auth, self.listener, timeout=3.0)
+
+    def tearDown(self):
+        self.stream.disconnect()
+
+    def test_userstream(self):
+        # Generate random tweet which should show up in the stream.
+        def on_connect():
+            API(self.auth).update_status(mock_tweet())
+
+        self.listener.connect_cb = on_connect
+        self.listener.status_stop_count = 1
+        self.stream.userstream()
+        self.assertEqual(self.listener.status_count, 1)
+
+    def test_sample(self):
+        self.listener.status_stop_count = 10
+        self.stream.sample()
+        self.assertEquals(self.listener.status_count,
+                          self.listener.status_stop_count)
+
+    def test_filter_track(self):
+        self.listener.status_stop_count = 5
+        phrases = ['twitter']
+        self.stream.filter(track=phrases)
+        self.assertEquals(self.listener.status_count,
+                          self.listener.status_stop_count)
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tweepy/__init__.py 
new/tweepy-2.1/tweepy/__init__.py
--- old/tweepy-2.0/tweepy/__init__.py   2013-02-10 22:35:43.000000000 +0100
+++ new/tweepy-2.1/tweepy/__init__.py   2013-06-16 21:02:22.000000000 +0200
@@ -5,11 +5,11 @@
 """
 Tweepy Twitter API library
 """
-__version__ = '2.0'
+__version__ = '2.1'
 __author__ = 'Joshua Roesslein'
 __license__ = 'MIT'
 
-from tweepy.models import Status, User, DirectMessage, Friendship, 
SavedSearch, SearchResult, ModelFactory, Category
+from tweepy.models import Status, User, DirectMessage, Friendship, 
SavedSearch, SearchResults, ModelFactory, Category
 from tweepy.error import TweepError
 from tweepy.api import API
 from tweepy.cache import Cache, MemoryCache, FileCache
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tweepy/api.py new/tweepy-2.1/tweepy/api.py
--- old/tweepy-2.0/tweepy/api.py        2013-02-10 22:10:33.000000000 +0100
+++ new/tweepy-2.1/tweepy/api.py        2013-06-16 21:01:25.000000000 +0200
@@ -17,8 +17,8 @@
     def __init__(self, auth_handler=None,
             host='api.twitter.com', search_host='search.twitter.com',
              cache=None, secure=True, api_root='/1.1', search_root='',
-            retry_count=0, retry_delay=0, retry_errors=None,
-            parser=None):
+            retry_count=0, retry_delay=0, retry_errors=None, timeout=60,
+            parser=None, compression=False):
         self.auth = auth_handler
         self.host = host
         self.search_host = search_host
@@ -26,16 +26,18 @@
         self.search_root = search_root
         self.cache = cache
         self.secure = secure
+        self.compression = compression
         self.retry_count = retry_count
         self.retry_delay = retry_delay
         self.retry_errors = retry_errors
+        self.timeout = timeout
         self.parser = parser or ModelParser()
 
     """ statuses/home_timeline """
     home_timeline = bind_api(
         path = '/statuses/home_timeline.json',
         payload_type = 'status', payload_list = True,
-        allowed_param = ['since_id', 'max_id', 'count', 'page'],
+        allowed_param = ['since_id', 'max_id', 'count'],
         require_auth = True
     )
 
@@ -44,7 +46,7 @@
         path = '/statuses/user_timeline.json',
         payload_type = 'status', payload_list = True,
         allowed_param = ['id', 'user_id', 'screen_name', 'since_id',
-                          'max_id', 'count', 'page', 'include_rts']
+                          'max_id', 'count', 'include_rts']
     )
 
     """ statuses/mentions """
@@ -83,7 +85,7 @@
     retweets_of_me = bind_api(
         path = '/statuses/retweets_of_me.json',
         payload_type = 'status', payload_list = True,
-        allowed_param = ['since_id', 'max_id', 'count', 'page'],
+        allowed_param = ['since_id', 'max_id', 'count'],
         require_auth = True
     )
 
@@ -136,6 +138,13 @@
         allowed_param = ['id', 'user_id', 'screen_name']
     )
 
+    ''' statuses/oembed '''
+    get_oembed = bind_api(
+        path = '/statuses/oembed.json',
+        payload_type = 'json',
+        allowed_param = ['id', 'url', 'maxwidth', 'hide_media', 'omit_script', 
'align', 'related', 'lang']
+    )
+
     """ Perform bulk look up of users from user ID or screenname """
     def lookup_users(self, user_ids=None, screen_names=None):
         return self._lookup_users(list_to_csv(user_ids), 
list_to_csv(screen_names))
@@ -186,7 +195,7 @@
     direct_messages = bind_api(
         path = '/direct_messages.json',
         payload_type = 'direct_message', payload_list = True,
-        allowed_param = ['since_id', 'max_id', 'count', 'page'],
+        allowed_param = ['since_id', 'max_id', 'count'],
         require_auth = True
     )
 
@@ -242,13 +251,6 @@
         require_auth = True
     )
 
-    """ friendships/exists """
-    exists_friendship = bind_api(
-        path = '/friendships/exists.json',
-        payload_type = 'json',
-        allowed_param = ['user_a', 'user_b']
-    )
-
     """ friendships/show """
     show_friendship = bind_api(
         path = '/friendships/show.json',
@@ -257,10 +259,9 @@
                           'target_id', 'target_screen_name']
     )
 
-
     """ Perform bulk look up of friendships from user ID or screenname """
     def lookup_friendships(self, user_ids=None, screen_names=None):
-           return self._lookup_friendships(list_to_csv(user_ids), 
list_to_csv(screen_names))
+        return self._lookup_friendships(list_to_csv(user_ids), 
list_to_csv(screen_names))
 
     _lookup_friendships = bind_api(
         path = '/friendships/lookup.json',
@@ -277,6 +278,13 @@
         allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
     )
 
+    """ friends/list """
+    friends = bind_api(
+        path = '/friends/list.json',
+        payload_type = 'user', payload_list = True,
+        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
+    )
+
     """ friendships/incoming """
     friendships_incoming = bind_api(
         path = '/friendships/incoming.json',
@@ -298,6 +306,13 @@
         allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
     )
 
+    """ followers/list """
+    followers = bind_api(
+        path = '/followers/list.json',
+        payload_type = 'user', payload_list = True,
+        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
+    )
+
     """ account/verify_credentials """
     def verify_credentials(self, **kargs):
         try:
@@ -417,7 +432,7 @@
     blocks = bind_api(
         path = '/blocks/list.json',
         payload_type = 'user', payload_list = True,
-        allowed_param = ['page'],
+        allowed_param = ['cursor'],
         require_auth = True
     )
 
@@ -430,10 +445,10 @@
 
     """ report_spam """
     report_spam = bind_api(
-        path = '/report_spam.json',
+        path = '/users/report_spam.json',
         method = 'POST',
         payload_type = 'user',
-        allowed_param = ['id', 'user_id', 'screen_name'],
+        allowed_param = ['user_id', 'screen_name'],
         require_auth = True
     )
 
@@ -613,12 +628,10 @@
 
     """ search """
     search = bind_api(
-        search_api = True,
-        path = '/search.json',
-        payload_type = 'search_result', payload_list = True,
-        allowed_param = ['q', 'lang', 'locale', 'rpp', 'page', 'since_id', 
'geocode', 'show_user', 'max_id', 'since', 'until', 'result_type']
+        path = '/search/tweets.json',
+        payload_type = 'search_results',
+        allowed_param = ['q', 'lang', 'locale', 'since_id', 'geocode', 
'show_user', 'max_id', 'since', 'until', 'result_type']
     )
-    search.pagination_mode = 'page'
 
     """ trends/daily """
     trends_daily = bind_api(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tweepy/auth.py 
new/tweepy-2.1/tweepy/auth.py
--- old/tweepy-2.0/tweepy/auth.py       2013-02-10 21:49:34.000000000 +0100
+++ new/tweepy-2.1/tweepy/auth.py       2013-06-08 22:30:54.000000000 +0200
@@ -138,9 +138,9 @@
                 oauth_consumer=self._consumer,
                 http_method='POST', http_url=url,
                 parameters = {
-                           'x_auth_mode': 'client_auth',
-                           'x_auth_username': username,
-                           'x_auth_password': password
+                    'x_auth_mode': 'client_auth',
+                    'x_auth_username': username,
+                    'x_auth_password': password
                 }
             )
             request.sign_request(self._sigmethod, self._consumer, None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tweepy/binder.py 
new/tweepy-2.1/tweepy/binder.py
--- old/tweepy-2.0/tweepy/binder.py     2013-02-10 21:49:34.000000000 +0100
+++ new/tweepy-2.1/tweepy/binder.py     2013-06-11 05:30:38.000000000 +0200
@@ -6,6 +6,8 @@
 import urllib
 import time
 import re
+from StringIO import StringIO
+import gzip
 
 from tweepy.error import TweepError
 from tweepy.utils import convert_to_utf8_str
@@ -128,11 +130,10 @@
             retries_performed = 0
             while retries_performed < self.retry_count + 1:
                 # Open connection
-                # FIXME: add timeout
                 if self.api.secure:
-                    conn = httplib.HTTPSConnection(self.host)
+                    conn = httplib.HTTPSConnection(self.host, 
timeout=self.api.timeout)
                 else:
-                    conn = httplib.HTTPConnection(self.host)
+                    conn = httplib.HTTPConnection(self.host, 
timeout=self.api.timeout)
 
                 # Apply authentication
                 if self.api.auth:
@@ -141,6 +142,10 @@
                             self.method, self.headers, self.parameters
                     )
 
+                # Request compression if configured
+                if self.api.compression:
+                    self.headers['Accept-encoding'] = 'gzip'
+
                 # Execute request
                 try:
                     conn.request(self.method, url, headers=self.headers, 
body=self.post_data)
@@ -168,7 +173,14 @@
                 raise TweepError(error_msg, resp)
 
             # Parse the response payload
-            result = self.api.parser.parse(self, resp.read())
+            body = resp.read()
+            if resp.getheader('Content-Encoding', '') == 'gzip':
+                try:
+                    zipper = gzip.GzipFile(fileobj=StringIO(body))
+                    body = zipper.read()
+                except Exception, e:
+                    raise TweepError('Failed to decompress data: %s' % e)
+            result = self.api.parser.parse(self, body)
 
             conn.close()
 
@@ -188,6 +200,9 @@
     # Set pagination mode
     if 'cursor' in APIMethod.allowed_param:
         _call.pagination_mode = 'cursor'
+    elif 'max_id' in APIMethod.allowed_param and \
+         'since_id' in APIMethod.allowed_param:
+        _call.pagination_mode = 'id'
     elif 'page' in APIMethod.allowed_param:
         _call.pagination_mode = 'page'
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tweepy/cursor.py 
new/tweepy-2.1/tweepy/cursor.py
--- old/tweepy-2.0/tweepy/cursor.py     2013-02-10 21:49:34.000000000 +0100
+++ new/tweepy-2.1/tweepy/cursor.py     2013-06-16 21:39:31.000000000 +0200
@@ -11,8 +11,12 @@
         if hasattr(method, 'pagination_mode'):
             if method.pagination_mode == 'cursor':
                 self.iterator = CursorIterator(method, args, kargs)
-            else:
+            elif method.pagination_mode == 'id':
+                self.iterator = IdIterator(method, args, kargs)
+            elif method.pagination_mode == 'page':
                 self.iterator = PageIterator(method, args, kargs)
+            else:
+                raise TweepError('Invalid pagination mode.')
         else:
             raise TweepError('This method does not perform pagination')
 
@@ -74,6 +78,44 @@
         self.count -= 1
         return data
 
+class IdIterator(BaseIterator):
+
+    def __init__(self, method, args, kargs):
+        BaseIterator.__init__(self, method, args, kargs)
+        self.max_id = kargs.get('max_id')
+        self.since_id = kargs.get('since_id')
+        self.count = 0
+
+    def next(self):
+        """Fetch a set of items with IDs less than current set."""
+        if self.limit and self.limit == self.count:
+            raise StopIteration
+
+        # max_id is inclusive so decrement by one
+        # to avoid requesting duplicate items.
+        max_id = self.since_id - 1 if self.max_id else None
+        data = self.method(max_id = max_id, *self.args, **self.kargs)
+        if len(data) == 0:
+            raise StopIteration
+        self.max_id = data.max_id
+        self.since_id = data.since_id
+        self.count += 1
+        return data
+
+    def prev(self):
+        """Fetch a set of items with IDs greater than current set."""
+        if self.limit and self.limit == self.count:
+            raise StopIteration
+
+        since_id = self.max_id
+        data = self.method(since_id = since_id, *self.args, **self.kargs)
+        if len(data) == 0:
+            raise StopIteration
+        self.max_id = data.max_id
+        self.since_id = data.since_id
+        self.count += 1
+        return data
+
 class PageIterator(BaseIterator):
 
     def __init__(self, method, args, kargs):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tweepy/models.py 
new/tweepy-2.1/tweepy/models.py
--- old/tweepy-2.0/tweepy/models.py     2013-02-10 22:10:33.000000000 +0100
+++ new/tweepy-2.1/tweepy/models.py     2013-06-16 21:01:25.000000000 +0200
@@ -9,7 +9,27 @@
 
 class ResultSet(list):
     """A list like object that holds results from a Twitter API query."""
+    def __init__(self, max_id=None, since_id=None):
+        super(ResultSet, self).__init__()
+        self._max_id = max_id
+        self._since_id = since_id
+
+    @property
+    def max_id(self):
+        if self._max_id:
+            return self._max_id
+        ids = self.ids()
+        return max(ids) if ids else None
+
+    @property
+    def since_id(self):
+        if self._since_id:
+            return self._since_id
+        ids = self.ids()
+        return min(ids) if ids else None
 
+    def ids(self):
+        return [item.id for item in self if hasattr(item, 'id')]
 
 class Model(object):
 
@@ -209,34 +229,18 @@
         return self._api.destroy_saved_search(self.id)
 
 
-class SearchResult(Model):
+class SearchResults(ResultSet):
 
     @classmethod
     def parse(cls, api, json):
-        result = cls()
-        for k, v in json.items():
-            if k == 'created_at':
-                setattr(result, k, parse_search_datetime(v))
-            elif k == 'source':
-                setattr(result, k, parse_html_value(unescape_html(v)))
-            else:
-                setattr(result, k, v)
-        return result
+        metadata = json['search_metadata']
+        results = SearchResults(metadata.get('max_id'), 
metadata.get('since_id'))
+        results.refresh_url = metadata.get('refresh_url')
+        results.completed_in = metadata.get('completed_in')
+        results.query = metadata.get('query')
 
-    @classmethod
-    def parse_list(cls, api, json_list, result_set=None):
-        results = ResultSet()
-        results.max_id = json_list.get('max_id')
-        results.since_id = json_list.get('since_id')
-        results.refresh_url = json_list.get('refresh_url')
-        results.next_page = json_list.get('next_page')
-        results.results_per_page = json_list.get('results_per_page')
-        results.page = json_list.get('page')
-        results.completed_in = json_list.get('completed_in')
-        results.query = json_list.get('query')
-
-        for obj in json_list['results']:
-            results.append(cls.parse(api, obj))
+        for status in json['statuses']:
+            results.append(Status.parse(api, status))
         return results
 
 
@@ -315,7 +319,7 @@
         result = cls(api)
         for k,v in json.items():
             if k == 'connections':
-               setattr(result, 'is_following', 'following' in v)
+                setattr(result, 'is_following', 'following' in v)
                 setattr(result, 'is_followed_by', 'followed_by' in v)
             else:
                 setattr(result, k, v)
@@ -414,7 +418,7 @@
     direct_message = DirectMessage
     friendship = Friendship
     saved_search = SavedSearch
-    search_result = SearchResult
+    search_results = SearchResults
     category = Category
     list = List
     relation = Relation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tweepy/streaming.py 
new/tweepy-2.1/tweepy/streaming.py
--- old/tweepy-2.0/tweepy/streaming.py  2013-02-10 22:10:33.000000000 +0100
+++ new/tweepy-2.1/tweepy/streaming.py  2013-05-19 10:17:49.000000000 +0200
@@ -22,6 +22,15 @@
     def __init__(self, api=None):
         self.api = api or API()
 
+    def on_connect(self):
+        """Called once connected to streaming server.
+
+        This will be invoked once a successful response
+        is received from the server. Allows the listener
+        to perform some work prior to entering the read loop.
+        """
+        pass
+
     def on_data(self, data):
         """Called when raw data is received from connection.
 
@@ -114,6 +123,7 @@
                     sleep(self.retry_time)
                 else:
                     error_counter = 0
+                    self.listener.on_connect()
                     self._read_loop(resp)
             except timeout:
                 if self.listener.on_timeout() == False:
@@ -208,7 +218,7 @@
         self._start(async)
 
     def filter(self, follow=None, track=None, async=False, locations=None, 
-        count = None, stall_warnings=False):
+        count = None, stall_warnings=False, languages=None):
         self.parameters = {}
         self.headers['Content-type'] = "application/x-www-form-urlencoded"
         if self.running:
@@ -225,6 +235,8 @@
             self.parameters['count'] = count
         if stall_warnings:
             self.parameters['stall_warnings'] = stall_warnings
+        if languages:
+            self.parameters['language'] = ','.join(map(str, languages))
         self.body = urlencode_noplus(self.parameters)
         self.parameters['delimited'] = 'length'
         self._start(async)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tweepy.egg-info/PKG-INFO 
new/tweepy-2.1/tweepy.egg-info/PKG-INFO
--- old/tweepy-2.0/tweepy.egg-info/PKG-INFO     2013-02-10 22:45:50.000000000 
+0100
+++ new/tweepy-2.1/tweepy.egg-info/PKG-INFO     2013-07-14 20:59:03.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: tweepy
-Version: 2.0
+Version: 2.1
 Summary: Twitter library for python
 Home-page: http://github.com/tweepy/tweepy
 Author: Joshua Roesslein
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tweepy.egg-info/SOURCES.txt 
new/tweepy-2.1/tweepy.egg-info/SOURCES.txt
--- old/tweepy-2.0/tweepy.egg-info/SOURCES.txt  2013-02-10 22:45:50.000000000 
+0100
+++ new/tweepy-2.1/tweepy.egg-info/SOURCES.txt  2013-07-14 20:59:03.000000000 
+0200
@@ -1,4 +1,12 @@
 setup.py
+tests/__init__.py
+tests/config.py
+tests/mock.py
+tests/test_api.py
+tests/test_auth.py
+tests/test_cursors.py
+tests/test_resultset.py
+tests/test_streaming.py
 tweepy/__init__.py
 tweepy/api.py
 tweepy/auth.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tweepy-2.0/tweepy.egg-info/top_level.txt 
new/tweepy-2.1/tweepy.egg-info/top_level.txt
--- old/tweepy-2.0/tweepy.egg-info/top_level.txt        2013-02-10 
22:45:50.000000000 +0100
+++ new/tweepy-2.1/tweepy.egg-info/top_level.txt        2013-07-14 
20:59:03.000000000 +0200
@@ -1 +1,2 @@
+tests
 tweepy

-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to