From 26abb61fe14cb7bfd915217abe38075829aabd87 Mon Sep 17 00:00:00 2001 From: Alexandr Vorobyov Date: Tue, 27 Jan 2015 13:05:29 +0200 Subject: [PATCH 01/12] python3 fix --- examples/authentication.py | 2 +- examples/http_api.py | 2 +- linkedin/linkedin.py | 4 ++-- linkedin/server.py | 2 +- linkedin/utils.py | 1 + 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/authentication.py b/examples/authentication.py index cb1a22b..a43771d 100644 --- a/examples/authentication.py +++ b/examples/authentication.py @@ -8,5 +8,5 @@ RETURN_URL = 'http://localhost:8000' authentication = LinkedInAuthentication(API_KEY, API_SECRET, RETURN_URL, PERMISSIONS.enums.values()) - print authentication.authorization_url + print(authentication.authorization_url) application = LinkedInApplication(authentication) diff --git a/examples/http_api.py b/examples/http_api.py index 92c63a4..aa9c9b5 100644 --- a/examples/http_api.py +++ b/examples/http_api.py @@ -68,5 +68,5 @@ def do_GET(self): if __name__ == '__main__': httpd = ThreadingTCPServer(('localhost', PORT), CustomHandler) - print 'Server started on port:', PORT + print('Server started on port:', PORT) httpd.serve_forever() diff --git a/linkedin/linkedin.py b/linkedin/linkedin.py index 81fe33a..478ad5e 100644 --- a/linkedin/linkedin.py +++ b/linkedin/linkedin.py @@ -306,7 +306,7 @@ def like_post(self, post_id, action): url = '%s/%s/relation-to-viewer/is-liked' % (ENDPOINTS.POSTS, str(post_id)) try: self.make_request('PUT', url, data=json.dumps(action)) - except (requests.ConnectionError, requests.HTTPError), error: + except (requests.ConnectionError, requests.HTTPError) as error: raise LinkedInError(error.message) else: return True @@ -318,7 +318,7 @@ def comment_post(self, post_id, comment): url = '%s/%s/comments' % (ENDPOINTS.POSTS, str(post_id)) try: self.make_request('POST', url, data=json.dumps(post)) - except (requests.ConnectionError, requests.HTTPError), error: + except (requests.ConnectionError, requests.HTTPError) as error: raise LinkedInError(error.message) else: return True diff --git a/linkedin/server.py b/linkedin/server.py index 4032a2a..4a892bd 100644 --- a/linkedin/server.py +++ b/linkedin/server.py @@ -21,7 +21,7 @@ def quick_api(api_key, secret_key, port=8000): auth = LinkedInAuthentication(api_key, secret_key, 'http://localhost:8000/', PERMISSIONS.enums.values()) app = LinkedInApplication(authentication=auth) - print auth.authorization_url + print(auth.authorization_url) _wait_for_user_to_enter_browser(app, port) return app diff --git a/linkedin/utils.py b/linkedin/utils.py index 7eda996..d0c31f8 100644 --- a/linkedin/utils.py +++ b/linkedin/utils.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import requests +from setuptools.compat import unicode from .exceptions import LinkedInError, get_exception_for_error_code try: From 7438e3620c4a00785553a45d3705e5a05c563bb8 Mon Sep 17 00:00:00 2001 From: Alexandr Vorobyov Date: Tue, 27 Jan 2015 13:22:59 +0200 Subject: [PATCH 02/12] python3 fix --- linkedin/utils.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/linkedin/utils.py b/linkedin/utils.py index d0c31f8..826426a 100644 --- a/linkedin/utils.py +++ b/linkedin/utils.py @@ -3,11 +3,6 @@ from setuptools.compat import unicode from .exceptions import LinkedInError, get_exception_for_error_code -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO - try: import simplejson as json except ImportError: From cccd27fa55c221b979c2a9ecf4508c5c10f3a982 Mon Sep 17 00:00:00 2001 From: Alexandr Vorobyov Date: Tue, 27 Jan 2015 13:24:31 +0200 Subject: [PATCH 03/12] python3 fix --- linkedin/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linkedin/utils.py b/linkedin/utils.py index 826426a..e24f8c6 100644 --- a/linkedin/utils.py +++ b/linkedin/utils.py @@ -27,7 +27,7 @@ def __init__(instance, *args, **kwargs): methods = {} base_classes = base_classes + (object,) - for k, v in methods.iteritems(): + for k, v in methods.items(): methods[k] = classmethod(v) attrs['enums'] = attrs.copy() From 0812c10ae070c37724f2971d7f7e5b70f8aea3ec Mon Sep 17 00:00:00 2001 From: Alexandr Vorobyov Date: Tue, 27 Jan 2015 13:28:49 +0200 Subject: [PATCH 04/12] python3 fix --- linkedin/linkedin.py | 76 +++++++++++++++++++++++++++++--------------- linkedin/utils.py | 9 ------ 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/linkedin/linkedin.py b/linkedin/linkedin.py index 478ad5e..4bf5160 100644 --- a/linkedin/linkedin.py +++ b/linkedin/linkedin.py @@ -9,7 +9,9 @@ from .exceptions import LinkedInError from .models import AccessToken, LinkedInInvitation, LinkedInMessage -from .utils import enum, to_utf8, raise_for_error, json, StringIO +from .utils import enum, to_utf8, raise_for_error +import json +from io import StringIO __all__ = ['LinkedInAuthentication', 'LinkedInApplication', 'PERMISSIONS'] @@ -94,7 +96,8 @@ def authorization_url(self): 'redirect_uri': self.redirect_uri} # urlencode uses quote_plus when encoding the query string so, # we ought to be encoding the qs by on our own. - qsl = ['%s=%s' % (urllib.quote(k), urllib.quote(v)) for k, v in qd.items()] + qsl = ['%s=%s' % (urllib.quote(k), urllib.quote(v)) for k, v in + qd.items()] return '%s?%s' % (self.AUTHORIZATION_URL, '&'.join(qsl)) @property @@ -112,10 +115,12 @@ def get_access_token(self, timeout=60): 'redirect_uri': self.redirect_uri, 'client_id': self.key, 'client_secret': self.secret} - response = requests.post(self.ACCESS_TOKEN_URL, data=qd, timeout=timeout) + response = requests.post(self.ACCESS_TOKEN_URL, data=qd, + timeout=timeout) raise_for_error(response) response = response.json() - self.token = AccessToken(response['access_token'], response['expires_in']) + self.token = AccessToken(response['access_token'], + response['expires_in']) return self.token @@ -146,9 +151,11 @@ def __init__(self, authentication=None, token=None): def make_request(self, method, url, data=None, params=None, headers=None, timeout=60): if headers is None: - headers = {'x-li-format': 'json', 'Content-Type': 'application/json'} + headers = {'x-li-format': 'json', + 'Content-Type': 'application/json'} else: - headers.update({'x-li-format': 'json', 'Content-Type': 'application/json'}) + headers.update( + {'x-li-format': 'json', 'Content-Type': 'application/json'}) if params is None: params = {} @@ -157,11 +164,14 @@ def make_request(self, method, url, data=None, params=None, headers=None, if isinstance(self.authentication, LinkedInDeveloperAuthentication): # Let requests_oauthlib.OAuth1 do *all* of the work here - auth = OAuth1(self.authentication.consumer_key, self.authentication.consumer_secret, - self.authentication.user_token, self.authentication.user_secret) + auth = OAuth1(self.authentication.consumer_key, + self.authentication.consumer_secret, + self.authentication.user_token, + self.authentication.user_secret) kw.update({'auth': auth}) else: - params.update({'oauth2_access_token': self.authentication.token.access_token}) + params.update( + {'oauth2_access_token': self.authentication.token.access_token}) return requests.request(method.upper(), url, **kw) @@ -175,7 +185,8 @@ def get_profile(self, member_id=None, member_url=None, selectors=None, else: url = '%s/id=%s' % (ENDPOINTS.PEOPLE, str(member_id)) elif member_url: - url = '%s/url=%s' % (ENDPOINTS.PEOPLE, urllib.quote_plus(member_url)) + url = '%s/url=%s' % ( + ENDPOINTS.PEOPLE, urllib.quote_plus(member_url)) else: url = '%s/~' % ENDPOINTS.PEOPLE if selectors: @@ -198,10 +209,12 @@ def search_profile(self, selectors=None, params=None, headers=None): def get_picture_urls(self, member_id=None, member_url=None, params=None, headers=None): if member_id: - url = '%s/id=%s/picture-urls::(original)' % (ENDPOINTS.PEOPLE, str(member_id)) + url = '%s/id=%s/picture-urls::(original)' % ( + ENDPOINTS.PEOPLE, str(member_id)) elif member_url: url = '%s/url=%s/picture-urls::(original)' % (ENDPOINTS.PEOPLE, - urllib.quote_plus(member_url)) + urllib.quote_plus( + member_url)) else: url = '%s/~/picture-urls::(original)' % ENDPOINTS.PEOPLE @@ -228,10 +241,12 @@ def get_connections(self, member_id=None, member_url=None, selectors=None, def get_memberships(self, member_id=None, member_url=None, group_id=None, selectors=None, params=None, headers=None): if member_id: - url = '%s/id=%s/group-memberships' % (ENDPOINTS.PEOPLE, str(member_id)) + url = '%s/id=%s/group-memberships' % ( + ENDPOINTS.PEOPLE, str(member_id)) elif member_url: url = '%s/url=%s/group-memberships' % (ENDPOINTS.PEOPLE, - urllib.quote_plus(member_url)) + urllib.quote_plus( + member_url)) else: url = '%s/~/group-memberships' % ENDPOINTS.PEOPLE @@ -264,7 +279,8 @@ def get_posts(self, group_id, post_ids=None, selectors=None, params=None, raise_for_error(response) return response.json() - def get_post_comments(self, post_id, selectors=None, params=None, headers=None): + def get_post_comments(self, post_id, selectors=None, params=None, + headers=None): url = '%s/%s/comments' % (ENDPOINTS.POSTS, post_id) if selectors: url = '%s:(%s)' % (url, LinkedInSelector.parse(selectors)) @@ -276,7 +292,8 @@ def get_post_comments(self, post_id, selectors=None, params=None, headers=None): def join_group(self, group_id): url = '%s/~/group-memberships/%s' % (ENDPOINTS.PEOPLE, str(group_id)) response = self.make_request('PUT', url, - data=json.dumps({'membershipState': {'code': 'member'}})) + data=json.dumps({ + 'membershipState': {'code': 'member'}})) raise_for_error(response) return True @@ -303,7 +320,8 @@ def submit_group_post(self, group_id, title, summary, submitted_url, return True def like_post(self, post_id, action): - url = '%s/%s/relation-to-viewer/is-liked' % (ENDPOINTS.POSTS, str(post_id)) + url = '%s/%s/relation-to-viewer/is-liked' % ( + ENDPOINTS.POSTS, str(post_id)) try: self.make_request('PUT', url, data=json.dumps(action)) except (requests.ConnectionError, requests.HTTPError) as error: @@ -323,14 +341,16 @@ def comment_post(self, post_id, comment): else: return True - def get_company_by_email_domain(self, email_domain, params=None, headers=None): + def get_company_by_email_domain(self, email_domain, params=None, + headers=None): url = '%s?email-domain=%s' % (ENDPOINTS.COMPANIES, email_domain) response = self.make_request('GET', url, params=params, headers=headers) raise_for_error(response) return response.json() - def get_companies(self, company_ids=None, universal_names=None, selectors=None, + def get_companies(self, company_ids=None, universal_names=None, + selectors=None, params=None, headers=None): identifiers = [] url = ENDPOINTS.COMPANIES @@ -373,7 +393,8 @@ def follow_company(self, company_id): return True def unfollow_company(self, company_id): - url = '%s/~/following/companies/id=%s' % (ENDPOINTS.PEOPLE, str(company_id)) + url = '%s/~/following/companies/id=%s' % ( + ENDPOINTS.PEOPLE, str(company_id)) response = self.make_request('DELETE', url) raise_for_error(response) return True @@ -387,7 +408,8 @@ def search_company(self, selectors=None, params=None, headers=None): raise_for_error(response) return response.json() - def submit_company_share(self, company_id, comment=None, title=None, description=None, + def submit_company_share(self, company_id, comment=None, title=None, + description=None, submitted_url=None, submitted_image_url=None, visibility_code='anyone'): @@ -483,7 +505,8 @@ def get_network_updates(self, types, member_id=None, def get_network_update(self, types, update_key, self_scope=True, params=None, headers=None): - url = '%s/~/network/updates/key=%s' % (ENDPOINTS.PEOPLE, str(update_key)) + url = '%s/~/network/updates/key=%s' % ( + ENDPOINTS.PEOPLE, str(update_key)) if not params: params = {} @@ -505,7 +528,8 @@ def get_network_status(self, params=None, headers=None): return response.json() def send_invitation(self, invitation): - assert type(invitation) == LinkedInInvitation, 'LinkedInInvitation required' + assert type( + invitation) == LinkedInInvitation, 'LinkedInInvitation required' url = '%s/~/mailbox' % ENDPOINTS.PEOPLE response = self.make_request('POST', url, data=json.dumps(invitation.json)) @@ -522,13 +546,15 @@ def send_message(self, message): def comment_on_update(self, update_key, comment): comment = {'comment': comment} - url = '%s/~/network/updates/key=%s/update-comments' % (ENDPOINTS.PEOPLE, update_key) + url = '%s/~/network/updates/key=%s/update-comments' % ( + ENDPOINTS.PEOPLE, update_key) response = self.make_request('POST', url, data=json.dumps(comment)) raise_for_error(response) return True def like_update(self, update_key, is_liked=True): - url = '%s/~/network/updates/key=%s/is-liked' % (ENDPOINTS.PEOPLE, update_key) + url = '%s/~/network/updates/key=%s/is-liked' % ( + ENDPOINTS.PEOPLE, update_key) response = self.make_request('PUT', url, data=json.dumps(is_liked)) raise_for_error(response) return True diff --git a/linkedin/utils.py b/linkedin/utils.py index e24f8c6..b948ccd 100644 --- a/linkedin/utils.py +++ b/linkedin/utils.py @@ -3,15 +3,6 @@ from setuptools.compat import unicode from .exceptions import LinkedInError, get_exception_for_error_code -try: - import simplejson as json -except ImportError: - try: - from django.utils import simplejson as json - except ImportError: - import json - - def enum(enum_type='enum', base_classes=None, methods=None, **attrs): """ Generates a enumeration with the given attributes. From 158619fd8f13fad89416652ef7cc7813a8708101 Mon Sep 17 00:00:00 2001 From: Alexandr Vorobyov Date: Tue, 27 Jan 2015 13:36:13 +0200 Subject: [PATCH 05/12] python3 fix --- linkedin/linkedin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linkedin/linkedin.py b/linkedin/linkedin.py index 4bf5160..aab4bf5 100644 --- a/linkedin/linkedin.py +++ b/linkedin/linkedin.py @@ -105,8 +105,8 @@ def last_error(self): return self._error def _make_new_state(self): - return hashlib.md5( - '%s%s' % (random.randrange(0, 2 ** 63), self.secret)).hexdigest() + h_str = '%s%s' % (random.randrange(0, 2 ** 63), self.secret) + return hashlib.md5(h_str.encode("utf-8")).hexdigest() def get_access_token(self, timeout=60): assert self.authorization_code, 'You must first get the authorization code' From 597ce00dd61c405ac72832b312f355e57f252c75 Mon Sep 17 00:00:00 2001 From: Alexandr Vorobyov Date: Tue, 27 Jan 2015 13:40:03 +0200 Subject: [PATCH 06/12] python3 fix --- linkedin/linkedin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linkedin/linkedin.py b/linkedin/linkedin.py index aab4bf5..39a3ba8 100644 --- a/linkedin/linkedin.py +++ b/linkedin/linkedin.py @@ -2,7 +2,7 @@ import contextlib import hashlib import random -import urllib +import urllib.parse as urllib import requests from requests_oauthlib import OAuth1 From dc157816efce9515677bf1f598db5138c255715c Mon Sep 17 00:00:00 2001 From: Alexandr Vorobyov Date: Tue, 27 Jan 2015 15:49:47 +0200 Subject: [PATCH 07/12] python3 fix --- linkedin/linkedin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linkedin/linkedin.py b/linkedin/linkedin.py index 39a3ba8..d82cb87 100644 --- a/linkedin/linkedin.py +++ b/linkedin/linkedin.py @@ -134,7 +134,7 @@ def parse(cls, selector): elif type(selector) in (list, tuple): result.write(','.join(map(cls.parse, selector))) else: - result.write(to_utf8(selector)) + result.write(selector) return result.getvalue() From fc5717818244274b64826a5c472972f6931e5508 Mon Sep 17 00:00:00 2001 From: Alexandr Vorobyov Date: Wed, 28 Jan 2015 15:57:20 +0200 Subject: [PATCH 08/12] add types=None to get_network_update --- linkedin/linkedin.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/linkedin/linkedin.py b/linkedin/linkedin.py index d82cb87..8e24dae 100644 --- a/linkedin/linkedin.py +++ b/linkedin/linkedin.py @@ -186,7 +186,7 @@ def get_profile(self, member_id=None, member_url=None, selectors=None, url = '%s/id=%s' % (ENDPOINTS.PEOPLE, str(member_id)) elif member_url: url = '%s/url=%s' % ( - ENDPOINTS.PEOPLE, urllib.quote_plus(member_url)) + ENDPOINTS.PEOPLE, urllib.quote_plus(member_url)) else: url = '%s/~' % ENDPOINTS.PEOPLE if selectors: @@ -210,7 +210,7 @@ def get_picture_urls(self, member_id=None, member_url=None, params=None, headers=None): if member_id: url = '%s/id=%s/picture-urls::(original)' % ( - ENDPOINTS.PEOPLE, str(member_id)) + ENDPOINTS.PEOPLE, str(member_id)) elif member_url: url = '%s/url=%s/picture-urls::(original)' % (ENDPOINTS.PEOPLE, urllib.quote_plus( @@ -242,7 +242,7 @@ def get_memberships(self, member_id=None, member_url=None, group_id=None, selectors=None, params=None, headers=None): if member_id: url = '%s/id=%s/group-memberships' % ( - ENDPOINTS.PEOPLE, str(member_id)) + ENDPOINTS.PEOPLE, str(member_id)) elif member_url: url = '%s/url=%s/group-memberships' % (ENDPOINTS.PEOPLE, urllib.quote_plus( @@ -293,7 +293,8 @@ def join_group(self, group_id): url = '%s/~/group-memberships/%s' % (ENDPOINTS.PEOPLE, str(group_id)) response = self.make_request('PUT', url, data=json.dumps({ - 'membershipState': {'code': 'member'}})) + 'membershipState': { + 'code': 'member'}})) raise_for_error(response) return True @@ -321,7 +322,7 @@ def submit_group_post(self, group_id, title, summary, submitted_url, def like_post(self, post_id, action): url = '%s/%s/relation-to-viewer/is-liked' % ( - ENDPOINTS.POSTS, str(post_id)) + ENDPOINTS.POSTS, str(post_id)) try: self.make_request('PUT', url, data=json.dumps(action)) except (requests.ConnectionError, requests.HTTPError) as error: @@ -394,7 +395,7 @@ def follow_company(self, company_id): def unfollow_company(self, company_id): url = '%s/~/following/companies/id=%s' % ( - ENDPOINTS.PEOPLE, str(company_id)) + ENDPOINTS.PEOPLE, str(company_id)) response = self.make_request('DELETE', url) raise_for_error(response) return True @@ -503,10 +504,10 @@ def get_network_updates(self, types, member_id=None, raise_for_error(response) return response.json() - def get_network_update(self, types, update_key, + def get_network_update(self, update_key, types=None, self_scope=True, params=None, headers=None): url = '%s/~/network/updates/key=%s' % ( - ENDPOINTS.PEOPLE, str(update_key)) + ENDPOINTS.PEOPLE, str(update_key)) if not params: params = {} @@ -547,14 +548,14 @@ def send_message(self, message): def comment_on_update(self, update_key, comment): comment = {'comment': comment} url = '%s/~/network/updates/key=%s/update-comments' % ( - ENDPOINTS.PEOPLE, update_key) + ENDPOINTS.PEOPLE, update_key) response = self.make_request('POST', url, data=json.dumps(comment)) raise_for_error(response) return True def like_update(self, update_key, is_liked=True): url = '%s/~/network/updates/key=%s/is-liked' % ( - ENDPOINTS.PEOPLE, update_key) + ENDPOINTS.PEOPLE, update_key) response = self.make_request('PUT', url, data=json.dumps(is_liked)) raise_for_error(response) return True From 3372c63b51d8e4f8fa9d446305ebf6014291ce1f Mon Sep 17 00:00:00 2001 From: Alisterion Date: Tue, 29 Dec 2015 13:05:02 +0200 Subject: [PATCH 09/12] add method get_specific_company_update --- linkedin/linkedin.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/linkedin/linkedin.py b/linkedin/linkedin.py index 8e24dae..b5a941e 100644 --- a/linkedin/linkedin.py +++ b/linkedin/linkedin.py @@ -371,6 +371,15 @@ def get_companies(self, company_ids=None, universal_names=None, raise_for_error(response) return response.json() + def get_specific_company_update(self, company_id, update_id, params=None, + headers=None): + url = "%s/%s/updates/key=%s?format=json" % ( + ENDPOINTS.COMPANIES, str(company_id), str(update_id) + ) + response = self.make_request('GET', url, params=params, headers=headers) + raise_for_error(response) + return response.json() + def get_company_updates(self, company_id, params=None, headers=None): url = '%s/%s/updates' % (ENDPOINTS.COMPANIES, str(company_id)) response = self.make_request('GET', url, params=params, headers=headers) From a99559cc8af28e87715f9d634dbc33aaa9fa92cb Mon Sep 17 00:00:00 2001 From: Alisterion Date: Tue, 29 Dec 2015 13:43:40 +0200 Subject: [PATCH 10/12] add method get_statistics_company_page --- linkedin/linkedin.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/linkedin/linkedin.py b/linkedin/linkedin.py index b5a941e..d54676f 100644 --- a/linkedin/linkedin.py +++ b/linkedin/linkedin.py @@ -13,7 +13,6 @@ import json from io import StringIO - __all__ = ['LinkedInAuthentication', 'LinkedInApplication', 'PERMISSIONS'] PERMISSIONS = enum('Permission', @@ -294,7 +293,7 @@ def join_group(self, group_id): response = self.make_request('PUT', url, data=json.dumps({ 'membershipState': { - 'code': 'member'}})) + 'code': 'member'}})) raise_for_error(response) return True @@ -371,6 +370,15 @@ def get_companies(self, company_ids=None, universal_names=None, raise_for_error(response) return response.json() + def get_statistics_company_page(self, company_id, params=None, + headers=None): + url = "%s/%s/company-statistics" % ( + ENDPOINTS.COMPANIES, str(company_id) + ) + response = self.make_request('GET', url, params=params, headers=headers) + raise_for_error(response) + return response.json() + def get_specific_company_update(self, company_id, update_id, params=None, headers=None): url = "%s/%s/updates/key=%s?format=json" % ( From 9c98fb5b64c036e21a60dc4fd7261e0dedbd278a Mon Sep 17 00:00:00 2001 From: Alisterion Date: Tue, 29 Dec 2015 13:55:22 +0200 Subject: [PATCH 11/12] add new mrthod to README --- README.md | 196 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 195 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8852add..c442652 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Python interface to the LinkedIn API -[![LinkedIn](http://developer.linkedin.com/sites/default/files/LinkedIn_Logo60px.png)](http://developer.linkedin.com) +[![LinkedIn](https://content.linkedin.com/etc/designs/linkedin/katy/global/clientlibs/img/logo.png)](http://developer.linkedin.com) This library provides a pure Python interface to the LinkedIn **Profile**, **Group**, **Company**, **Jobs**, **Search**, **Share**, **Network** and **Invitation** REST APIs. @@ -295,7 +295,201 @@ application.get_companies(company_ids=[1035], universal_names=['apple'], selecto {u'_total': 2, u'values': [{u'_key': u'1035', u'name': u'Microsoft'}, {u'_key': u'universal-name=apple', u'name': u'Apple'}]} +``` + +```python +# Get statistics for a company page +application.get_statistics_company_page(1035) +{ + "followStatistics": { + "companySizes": { + "_total": 2, + "values": [ + { + "entryKey": "C", + "entryValue": "79027" + }, + { + "entryKey": "E", + "entryValue": "59788" + } + ] + }, + "count": 386420, + "countries": { + "_total": 1, + "values": [ + { + "entryKey": "us", + "entryValue": "386420" + } + ] + }, + "countsByMonth": { + "_total": 1, + "values": [ + { + "date": { + "month": 1, + "year": 2015 + }, + "newCount": 44868, + "totalCount": 1111157 + } + ] + }, + "employeeCount": 3992, + "functions": { + "_total": 2, + "values": [ + { + "entryKey": "25", + "entryValue": "100" + }, + { + "entryKey": "15", + "entryValue": "3892" + } + ] + }, + "nonEmployeeCount": 107253, + "regions": { + "_total": 1, + "values": [ + { + "entryKey": "us-84", + "entryValue": "107253" + } + ] + }, + "seniorities": { + "_total": 2, + "values": [ + { + "entryKey": "4", + "entryValue": "326866" + }, + { + "entryKey": "3", + "entryValue": "319703" + } + ] + } + }, + "statusUpdateStatistics": { + "viewsByMonth": { + "_total": 1, + "values": [ + { + "clicks": 81333, + "comments": 1203, + "date": { + "month": 1, + "year": 2015 + }, + "engagement": 0.003203537929382338, + "impressions": 32797489, + "likes": 20387, + "shares": 2145 + } + ] + } + } +} +``` +```python +# Get a specific company update +application.get_specific_company_update(1035,"UNIU-c1035-5720424522989961216-FOLLOW_CMPY") +{ + "isCommentable": true, + "isLikable": true, + "isLiked": false, + "likes": { + "_total": 1, + "values": [ + { + "person": { + "firstName": "Frodo", + "headline": "2nd Generation Adventurer", + "id": "12345678", + "lastName": "Baggins", + "pictureUrl": "https://media.licdn.com/mpr/mprx/…" + } + } + ] + }, + "numLikes": 1, + "timestamp": 1423270834567, + "updateComments": { + "_total": 1, + "values": [ + { + "comment": "Great comment!", + "id": 987654321, + "person": { + "apiStandardProfileRequest": { + "headers": { + "_total": 1, + "values": [ + { + "name": "x-li-auth-token", + "value": "name:Ff1A" + } + ] + }, + "url": "https://api.linkedin.com/v1/people/12345678" + }, + "firstName": "Samwise", + "headline": "Journeyman", + "id": "23456789", + "lastName": "Gamgee", + "pictureUrl": "https://media.licdn.com/mpr/mprx/…", + "siteStandardProfileRequest": { + "url": "https://www.linkedin.com/profile/view?id=…" + } + }, + "sequenceNumber": 0, + "timestamp": 1423281179569 + } + ] + }, + "updateContent": { + "company": { + "id": 1337, + "name": "LinkedIn" + }, + "companyStatusUpdate": { + "share": { + "comment": "This is a test comment.", + "content": { + "description": "Test description", + "eyebrowUrl": "http://linkd.in/…", + "shortenedUrl": "http://linkd.in/…", + "submittedImageUrl": "http://m.c.lnkd.licdn.com/…", + "submittedUrl": "http://linkd.in/…", + "thumbnailUrl": "https://media.licdn.com/…", + "title": "Best Advice: Take Jobs Others Don't Want" + }, + "id": "s132435465768", + "source": { + "serviceProvider": { + "name": "LINKEDIN" + }, + "serviceProviderShareId": "s97867564534231" + }, + "timestamp": 1423270834567, + "visibility": { + "code": "anyone" + } + } + } + }, + "updateKey": "UPDATE-c1337-998877665544332211", + "updateType": "CMPY" +} +``` +```python # Get the latest updates about Microsoft application.get_company_updates(1035, params={'count': 2}) {u'_count': 2, From 663e30af6d959f6f82bb6a1bf62eef5aac82ffca Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 11 Aug 2017 15:46:46 +0300 Subject: [PATCH 12/12] *adapted for new setuptools --- linkedin/utils.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/linkedin/utils.py b/linkedin/utils.py index b948ccd..9213e3f 100644 --- a/linkedin/utils.py +++ b/linkedin/utils.py @@ -1,12 +1,14 @@ # -*- coding: utf-8 -*- import requests -from setuptools.compat import unicode from .exceptions import LinkedInError, get_exception_for_error_code +import sys + def enum(enum_type='enum', base_classes=None, methods=None, **attrs): """ Generates a enumeration with the given attributes. """ + # Enumerations can not be initalized as a new instance def __init__(instance, *args, **kwargs): raise RuntimeError('%s types can not be initialized.' % enum_type) @@ -27,11 +29,23 @@ def __init__(instance, *args, **kwargs): return type(enum_type, base_classes, methods) -def to_utf8(st): - if isinstance(st, unicode): - return st.encode('utf-8') - else: - return bytes(st) +if sys.version_info < (3,): + import __builtin__ + + + def to_utf8(x): + return __builtin__.unicode(x) + + + def to_string(x): + return str(x) +else: + def to_utf8(x): + return x + + + def to_string(x): + return x def raise_for_error(response):