From a5d1cb359218b9c6882ea40188d0457d14d983e7 Mon Sep 17 00:00:00 2001 From: Chris Rossi Date: Thu, 12 Dec 2013 11:22:21 -0500 Subject: [PATCH] pep8 and pylint --- .../linkedin/management/commands/findusers.py | 27 ++++- .../commands/tests/test_findusers.py | 98 ++++++++++++------- lms/djangoapps/linkedin/models.py | 6 ++ 3 files changed, 93 insertions(+), 38 deletions(-) diff --git a/lms/djangoapps/linkedin/management/commands/findusers.py b/lms/djangoapps/linkedin/management/commands/findusers.py index 9ea7662366..86a67606e0 100644 --- a/lms/djangoapps/linkedin/management/commands/findusers.py +++ b/lms/djangoapps/linkedin/management/commands/findusers.py @@ -1,3 +1,7 @@ +""" +Provides a command to use with Django's `manage.py` that uses LinkedIn's API to +find edX users that are also users on LinkedIn. +""" import datetime import pytz import time @@ -8,9 +12,9 @@ from django.utils import timezone from optparse import make_option - FRIDAY = 4 + def get_call_limits(): """ Returns a tuple of: (max_checks, checks_per_call, time_between_calls) @@ -42,18 +46,25 @@ def get_call_limits(): class Command(BaseCommand): + """ + Provides a command to use with Django's `manage.py` that uses LinkedIn's + API to find edX users that are also users on LinkedIn. + """ args = '' help = 'Checks LinkedIn for students that are on LinkedIn' option_list = BaseCommand.option_list + ( - make_option('--recheck', + make_option( + '--recheck', action='store_true', dest='recheck', default=False, help='Check users that have been checked in the past to see if ' - 'they have joined or left LinkedIn since the last check'), - ) + 'they have joined or left LinkedIn since the last check'),) def handle(self, *args, **options): + """ + Check users. + """ api = LinkedinAPI() recheck = options.pop('recheck', False) max_checks, checks_per_call, time_between_calls = get_call_limits() @@ -76,6 +87,7 @@ class Command(BaseCommand): for i in xrange(0, len(check_users), checks_per_call)] def do_batch(batch): + "Process a batch of users." emails = [u.email for u in batch] for user, has_account in zip(batch, api.batch(emails)): user.linkedin.has_linkedin_account = has_account @@ -88,7 +100,12 @@ class Command(BaseCommand): class LinkedinAPI(object): + """ + Encapsulates the LinkedIn API. + """ def batch(self, emails): + """ + Get the LinkedIn status for a batch of emails. + """ pass - diff --git a/lms/djangoapps/linkedin/management/commands/tests/test_findusers.py b/lms/djangoapps/linkedin/management/commands/tests/test_findusers.py index d016b67b6f..a6e01ec772 100644 --- a/lms/djangoapps/linkedin/management/commands/tests/test_findusers.py +++ b/lms/djangoapps/linkedin/management/commands/tests/test_findusers.py @@ -1,3 +1,6 @@ +""" +Tests for the findusers script. +""" import datetime import mock import pytz @@ -9,59 +12,76 @@ from linkedin.management.commands import findusers class FindUsersTests(unittest.TestCase): + """ + Tests for the findusers script. + """ @mock.patch('linkedin.management.commands.findusers.timezone') def test_get_call_limits_in_safe_harbor(self, timezone): + """ + We should be able to perform unlimited API calls during "safe harbor". + """ fut = findusers.get_call_limits - tz = pytz.timezone('US/Eastern') + tzinfo = pytz.timezone('US/Eastern') timezone.now.return_value = datetime.datetime( - 2013, 12, 14, 0, 0, tzinfo=tz) + 2013, 12, 14, 0, 0, tzinfo=tzinfo) self.assertEqual(fut(), (-1, 80, 1)) timezone.now.return_value = datetime.datetime( - 2013, 12, 13, 21, 1, tzinfo=tz) + 2013, 12, 13, 21, 1, tzinfo=tzinfo) self.assertEqual(fut(), (-1, 80, 1)) timezone.now.return_value = datetime.datetime( - 2013, 12, 15, 7, 59, tzinfo=tz) + 2013, 12, 15, 7, 59, tzinfo=tzinfo) self.assertEqual(fut(), (-1, 80, 1)) @mock.patch('linkedin.management.commands.findusers.timezone') def test_get_call_limits_in_business_hours(self, timezone): + """ + During business hours we shouldn't be able to make any API calls. + """ fut = findusers.get_call_limits - tz = pytz.timezone('US/Eastern') + tzinfo = pytz.timezone('US/Eastern') timezone.now.return_value = datetime.datetime( - 2013, 12, 11, 11, 3, tzinfo=tz) + 2013, 12, 11, 11, 3, tzinfo=tzinfo) self.assertEqual(fut(), (0, 0, 0)) timezone.now.return_value = datetime.datetime( - 2013, 12, 13, 20, 59, tzinfo=tz) + 2013, 12, 13, 20, 59, tzinfo=tzinfo) self.assertEqual(fut(), (0, 0, 0)) timezone.now.return_value = datetime.datetime( - 2013, 12, 16, 8, 1, tzinfo=tz) + 2013, 12, 16, 8, 1, tzinfo=tzinfo) self.assertEqual(fut(), (0, 0, 0)) @mock.patch('linkedin.management.commands.findusers.timezone') def test_get_call_limits_on_weeknights(self, timezone): + """ + On weeknights outside of "safe harbor" we can only make limited API + calls. + """ fut = findusers.get_call_limits - tz = pytz.timezone('US/Eastern') + tzinfo = pytz.timezone('US/Eastern') timezone.now.return_value = datetime.datetime( - 2013, 12, 11, 21, 3, tzinfo=tz) + 2013, 12, 11, 21, 3, tzinfo=tzinfo) self.assertEqual(fut(), (500, 80, 1)) timezone.now.return_value = datetime.datetime( - 2013, 12, 11, 7, 59, tzinfo=tz) + 2013, 12, 11, 7, 59, tzinfo=tzinfo) self.assertEqual(fut(), (500, 80, 1)) @mock.patch('linkedin.management.commands.findusers.time') @mock.patch('linkedin.management.commands.findusers.User') @mock.patch('linkedin.management.commands.findusers.LinkedinAPI') @mock.patch('linkedin.management.commands.findusers.get_call_limits') - def test_command_success_recheck_no_limits( - self, get_call_limits, API, User, time): - + def test_command_success_recheck_no_limits(self, get_call_limits, apicls, + usercls, time): + """ + Test rechecking all users with no API limits. + """ fut = findusers.Command().handle get_call_limits.return_value = (-1, 6, 42) - api = API.return_value + api = apicls.return_value users = [mock.Mock(email=i) for i in xrange(10)] - User.objects.all.return_value = users + usercls.objects.all.return_value = users + def dummy_batch(emails): + "Mock LinkedIn API." return [email % 2 == 0 for email in emails] api.batch = dummy_batch fut(recheck=True) @@ -73,19 +93,23 @@ class FindUsersTests(unittest.TestCase): @mock.patch('linkedin.management.commands.findusers.User') @mock.patch('linkedin.management.commands.findusers.LinkedinAPI') @mock.patch('linkedin.management.commands.findusers.get_call_limits') - def test_command_success_no_recheck_no_limits( - self, get_call_limits, API, User, time): - + def test_command_success_no_recheck_no_limits(self, get_call_limits, apicls, + usercls, time): + """ + Test checking only unchecked users, with no API limits. + """ fut = findusers.Command().handle get_call_limits.return_value = (-1, 6, 42) - api = API.return_value + api = apicls.return_value users = [mock.Mock(email=i) for i in xrange(10)] for user in users[:6]: user.linkedin.has_linkedin_account = user.email % 2 == 0 for user in users[6:]: user.linkedin.has_linkedin_account = None - User.objects.all.return_value = users + usercls.objects.all.return_value = users + def dummy_batch(emails): + "Mock LinkedIn API." self.assertEqual(len(emails), 4) return [email % 2 == 0 for email in emails] api.batch = dummy_batch @@ -98,18 +122,22 @@ class FindUsersTests(unittest.TestCase): @mock.patch('linkedin.management.commands.findusers.User') @mock.patch('linkedin.management.commands.findusers.LinkedinAPI') @mock.patch('linkedin.management.commands.findusers.get_call_limits') - def test_command_success_no_recheck_no_users( - self, get_call_limits, API, User, time): - + def test_command_success_no_recheck_no_users(self, get_call_limits, apicls, + usercls, time): + """ + Test no users to check. + """ fut = findusers.Command().handle get_call_limits.return_value = (-1, 6, 42) - api = API.return_value + api = apicls.return_value users = [mock.Mock(email=i) for i in xrange(10)] for user in users: user.linkedin.has_linkedin_account = user.email % 2 == 0 - User.objects.all.return_value = users - def dummy_batch(emails): - self.assertTrue(False) # shouldn't be called + usercls.objects.all.return_value = users + + def dummy_batch(_): + "Mock LinkedIn API." + self.assertTrue(False) # shouldn't be called api.batch = dummy_batch fut() time.sleep.assert_not_called() @@ -120,19 +148,23 @@ class FindUsersTests(unittest.TestCase): @mock.patch('linkedin.management.commands.findusers.User') @mock.patch('linkedin.management.commands.findusers.LinkedinAPI') @mock.patch('linkedin.management.commands.findusers.get_call_limits') - def test_command_success_recheck_with_limit( - self, get_call_limits, API, User, time): - + def test_command_success_recheck_with_limit(self, get_call_limits, apicls, + usercls, time): + """ + Test recheck all users with API limit. + """ command = findusers.Command() command.stderr = StringIO.StringIO() fut = command.handle get_call_limits.return_value = (9, 6, 42) - api = API.return_value + api = apicls.return_value users = [mock.Mock(email=i) for i in xrange(10)] for user in users: user.linkedin.has_linkedin_account = None - User.objects.all.return_value = users + usercls.objects.all.return_value = users + def dummy_batch(emails): + "Mock LinkedIn API." return [email % 2 == 0 for email in emails] api.batch = dummy_batch fut() diff --git a/lms/djangoapps/linkedin/models.py b/lms/djangoapps/linkedin/models.py index 738d5ec709..7beea5f6d9 100644 --- a/lms/djangoapps/linkedin/models.py +++ b/lms/djangoapps/linkedin/models.py @@ -1,7 +1,13 @@ +""" +Models for LinkedIn integration app. +""" from django.contrib.auth.models import User from django.db import models class LinkedIn(models.Model): + """ + Defines a table for storing a users's LinkedIn status. + """ user = models.OneToOneField(User, primary_key=True) has_linkedin_account = models.NullBooleanField(default=None)