Skip to content

Commit 139f251

Browse files
committed
Merge pull request bear#297 from bear/feature/friendship_update
Update to LookupFriendship
2 parents 349b16b + d239858 commit 139f251

7 files changed

Lines changed: 182 additions & 40 deletions

File tree

doc/migration_v30.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ Changes to Existing Methods
3535
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3636
* No longer accepts ``cursor`` parameter. If you require granular control over the paging of the twitter.list.List members, please user twitter.api.Api.GetListMembersPaged instead.
3737

38-
3938
:py:func:`twitter.api.Api.GetSearch`
4039
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4140
* Adds ``raw_query`` method. See :ref:`raw_queries` for more information.
@@ -44,6 +43,13 @@ Changes to Existing Methods
4443
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4544
* Parameter 'stall_warning' is now 'stall_warnings' in line with GetStreamFilter and Twitter's naming convention. This should now actually return stall warnings, whereas it did not have any effect previously.
4645

46+
47+
:py:func:`twitter.api.Api.LookupFriendship`
48+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
49+
50+
* Method will now accept a list for either ``user_id`` or ``screen_name``. The list can contain either ints, strings, or :py:mod:`twitter.user.User` objects for either ``user_id`` or ``screen_name``.
51+
* Return value is a list of :py:mod:`twitter.user.UserStatus` objects.
52+
4753
:py:func:`twitter.api.Api.PostUpdate`
4854
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4955
* Now accepts three new parameters: ``media``, ``media_additional_owners``, and ``media_category``. ``media`` can be a URL, a local file, or a file-like object (something with a ``read()`` method), or a list of any combination of the above.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"name": "dick costolo", "id": 6385432, "screen_name": "dickc", "id_str": "6385432", "connections": ["muting"]}]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"name": "dick costolo", "id": 6385432, "screen_name": "dickc", "id_str": "6385432", "connections": ["blocking", "muting"]}]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"id_str": "12", "name": "Jack", "connections": ["none"], "screen_name": "jack", "id": 12}]

tests/test_api_30.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,3 +1356,86 @@ def testPostUpdateWithMedia(self):
13561356
status=200)
13571357
resp = self.api.PostUpdate(
13581358
media=[697007311538229248, 697007311538229249], status='test')
1359+
1360+
@responses.activate
1361+
def testLookupFriendship(self):
1362+
with open('testdata/get_friendships_lookup_none.json') as f:
1363+
resp_data = f.read()
1364+
1365+
responses.add(
1366+
responses.GET,
1367+
'https://api.twitter.com/1.1/friendships/lookup.json?user_id=12',
1368+
body=resp_data,
1369+
match_querystring=True,
1370+
status=200)
1371+
1372+
responses.add(
1373+
responses.GET,
1374+
'https://api.twitter.com/1.1/friendships/lookup.json?user_id=12,6385432',
1375+
body=resp_data,
1376+
match_querystring=True,
1377+
status=200)
1378+
responses.add(
1379+
responses.GET,
1380+
'https://api.twitter.com/1.1/friendships/lookup.json?screen_name=jack',
1381+
body=resp_data,
1382+
match_querystring=True,
1383+
status=200)
1384+
responses.add(
1385+
responses.GET,
1386+
'https://api.twitter.com/1.1/friendships/lookup.json?screen_name=jack,dickc',
1387+
body=resp_data,
1388+
match_querystring=True,
1389+
status=200)
1390+
1391+
resp = self.api.LookupFriendship(user_id=12)
1392+
self.assertTrue(isinstance(resp, list))
1393+
self.assertTrue(isinstance(resp[0], twitter.UserStatus))
1394+
self.assertEqual(resp[0].following, False)
1395+
self.assertEqual(resp[0].followed_by, False)
1396+
1397+
# If any of the following produce an unexpect result, the test will
1398+
# fail on a request to a URL that hasn't been set by responses:
1399+
test_user = twitter.User(id=12, screen_name='jack')
1400+
test_user2 = twitter.User(id=6385432, screen_name='dickc')
1401+
1402+
resp = self.api.LookupFriendship(screen_name='jack')
1403+
resp = self.api.LookupFriendship(screen_name=['jack'])
1404+
resp = self.api.LookupFriendship(screen_name=test_user)
1405+
resp = self.api.LookupFriendship(screen_name=[test_user, test_user2])
1406+
1407+
resp = self.api.LookupFriendship(user_id=12)
1408+
resp = self.api.LookupFriendship(user_id=[12])
1409+
resp = self.api.LookupFriendship(user_id=test_user)
1410+
resp = self.api.LookupFriendship(user_id=[test_user, test_user2])
1411+
1412+
self.assertRaises(
1413+
twitter.TwitterError,
1414+
lambda: self.api.LookupFriendship())
1415+
1416+
@responses.activate
1417+
def testLookupFriendshipMute(self):
1418+
with open('testdata/get_friendships_lookup_muting.json') as f:
1419+
resp_data = f.read()
1420+
responses.add(
1421+
responses.GET,
1422+
'https://api.twitter.com/1.1/friendships/lookup.json?screen_name=dickc',
1423+
body=resp_data,
1424+
match_querystring=True,
1425+
status=200)
1426+
resp = self.api.LookupFriendship(screen_name='dickc')
1427+
self.assertEqual(resp[0].muting, True)
1428+
1429+
@responses.activate
1430+
def testLookupFriendshipBlockMute(self):
1431+
with open('testdata/get_friendships_lookup_muting_blocking.json') as f:
1432+
resp_data = f.read()
1433+
responses.add(
1434+
responses.GET,
1435+
'https://api.twitter.com/1.1/friendships/lookup.json?screen_name=dickc',
1436+
body=resp_data,
1437+
match_querystring=True,
1438+
status=200)
1439+
resp = self.api.LookupFriendship(screen_name='dickc')
1440+
self.assertEqual(resp[0].muting, True)
1441+
self.assertEqual(resp[0].blocking, True)

twitter/api.py

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2749,54 +2749,67 @@ def DestroyFriendship(self, user_id=None, screen_name=None):
27492749

27502750
return User.NewFromJsonDict(data)
27512751

2752-
def LookupFriendship(self,
2753-
user_id=None,
2754-
screen_name=None,
2755-
users=None):
2752+
def LookupFriendship(self,
2753+
user_id=None,
2754+
screen_name=None):
27562755
"""Lookup friendship status for user to authed user.
2757-
2756+
27582757
Users may be specified either as lists of either user_ids,
27592758
screen_names, or twitter.User objects. The list of users that
27602759
are queried is the union of all specified parameters.
2761-
2760+
27622761
Up to 100 users may be specified.
2763-
2762+
27642763
Args:
2765-
user_id:
2766-
A list of user_ids to retrieve extended information. [Optional]
2767-
screen_name:
2768-
A list of screen_names to retrieve extended information. [Optional]
2769-
users:
2770-
A list of twitter.User objects to retrieve extended information.
2771-
[Optional]
2772-
2764+
user_id (int, User, or list of ints or Users, optional):
2765+
A list of user_ids to retrieve extended information.
2766+
screen_name (string, User, or list of strings or Users, optional):
2767+
A list of screen_names to retrieve extended information.
2768+
27732769
Returns:
2774-
A twitter.UserStatus instance representing the friendship status
2770+
list: A list of twitter.UserStatus instance representing the
2771+
friendship status between the specified users and the authenticated
2772+
user.
27752773
"""
2776-
if not user_id and not screen_name and not users:
2777-
raise TwitterError({'message': "Specify at least one of user_id, screen_name, users."})
2778-
27792774
url = '%s/friendships/lookup.json' % (self.base_url)
2780-
data = {}
2781-
uids = list()
2775+
parameters = {}
2776+
27822777
if user_id:
2783-
uids.extend(user_id)
2784-
if users:
2785-
uids.extend([u.id for u in users])
2786-
if len(uids):
2787-
data['user_id'] = ','.join(["%s" % u for u in uids])
2778+
if isinstance(user_id, list) or isinstance(user_id, tuple):
2779+
uids = list()
2780+
for user in user_id:
2781+
if isinstance(user, User):
2782+
uids.append(user.id)
2783+
else:
2784+
uids.append(enf_type('user_id', int, user))
2785+
parameters['user_id'] = ",".join([str(uid) for uid in uids])
2786+
else:
2787+
if isinstance(user_id, User):
2788+
parameters['user_id'] = user_id.id
2789+
else:
2790+
parameters['user_id'] = enf_type('user_id', int, user_id)
27882791
if screen_name:
2789-
data['screen_name'] = ','.join(screen_name)
2792+
if isinstance(screen_name, list) or isinstance(screen_name, tuple):
2793+
sn_list = list()
2794+
for user in screen_name:
2795+
if isinstance(user, User):
2796+
sn_list.append(user.screen_name)
2797+
else:
2798+
sn_list.append(enf_type('screen_name', str, user))
2799+
parameters['screen_name'] = ','.join(sn_list)
2800+
else:
2801+
if isinstance(screen_name, User):
2802+
parameters['screen_name'] = screen_name.screen_name
2803+
else:
2804+
parameters['screen_name'] = enf_type('screen_name', str, screen_name)
2805+
if not user_id and not screen_name:
2806+
raise TwitterError(
2807+
"Specify at least one of user_id or screen_name.")
27902808

2791-
resp = self._RequestUrl(url, 'GET', data=data)
2809+
resp = self._RequestUrl(url, 'GET', data=parameters)
27922810
data = self._ParseAndCheckTwitter(resp.content.decode('utf-8'))
27932811

2794-
if len(data) > 1:
2795-
return [UserStatus.NewFromJsonDict(x) for x in data]
2796-
elif len(data) == 1:
2797-
return UserStatus.NewFromJsonDict(data[0])
2798-
else:
2799-
return None
2812+
return [UserStatus.NewFromJsonDict(x) for x in data]
28002813

28012814
def CreateFavorite(self,
28022815
status=None,

twitter/user.py

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ class UserStatus(object):
1414
userstatus.screen_name
1515
userstatus.following
1616
userstatus.followed_by
17+
userstatus.following_received
18+
userstatus.following_requested
19+
userstatus.blocking
20+
userstatus.muting
1721
"""
1822

1923
def __init__(self, **kwargs):
@@ -34,7 +38,11 @@ def __init__(self, **kwargs):
3438
'id_str': None,
3539
'screen_name': None,
3640
'following': None,
37-
'followed_by': None}
41+
'followed_by': None,
42+
'following_received': None,
43+
'following_requested': None,
44+
'blocking': None,
45+
'muting': None}
3846

3947
for (param, default) in param_defaults.items():
4048
setattr(self, param, kwargs.get(param, default))
@@ -62,7 +70,11 @@ def __eq__(self, other):
6270
self.id_str == other.id_str and \
6371
self.screen_name == other.screen_name and \
6472
self.following == other.following and \
65-
self.followed_by == other.followed_by
73+
self.followed_by == other.followed_by and \
74+
self.following_received == other.following_received and \
75+
self.following_requested == other.following_requested and\
76+
self.muting == other.muting and \
77+
self.blocking == other.blocking
6678
except AttributeError:
6779
return False
6880

@@ -105,6 +117,14 @@ def AsDict(self):
105117
data['following'] = self.following
106118
if self.followed_by:
107119
data['followed_by'] = self.followed_by
120+
if self.following_received:
121+
data['following_received'] = self.following_received
122+
if self.following_requested:
123+
data['following_requested'] = self.following_requested
124+
if self.blocking:
125+
data['blocking'] = self.blocking
126+
if self.muting:
127+
data['muting'] = self.muting
108128
return data
109129

110130
@staticmethod
@@ -116,20 +136,37 @@ def NewFromJsonDict(data):
116136
Returns:
117137
A twitter.UserStatus instance
118138
"""
119-
following = None
120-
followed_by = None
139+
following = False
140+
followed_by = False
141+
following_received = False
142+
following_requested = False
143+
blocking = False
144+
muting = False
145+
121146
if 'connections' in data:
122147
if 'following' in data['connections']:
123148
following = True
124149
if 'followed_by' in data['connections']:
125150
followed_by = True
151+
if 'following_received' in data['connections']:
152+
following_received = True
153+
if 'following_requested' in data['connections']:
154+
following_requested = True
155+
if 'blocking' in data['connections']:
156+
blocking = True
157+
if 'muting' in data['connections']:
158+
muting = True
126159

127160
return UserStatus(name=data.get('name', None),
128161
id=data.get('id', None),
129162
id_str=data.get('id_str', None),
130163
screen_name=data.get('screen_name', None),
131164
following=following,
132-
followed_by=followed_by)
165+
followed_by=followed_by,
166+
following_received=following_received,
167+
following_requested=following_requested,
168+
blocking=blocking,
169+
muting=muting)
133170

134171

135172
class User(object):

0 commit comments

Comments
 (0)