Commit 2838dba1 by Arthur Barrett

fix pep8 violations

parent dd583ce4
...@@ -28,6 +28,7 @@ API_SETTINGS = { ...@@ -28,6 +28,7 @@ API_SETTINGS = {
#----------------------------------------------------------------------# #----------------------------------------------------------------------#
# API requests are routed through api_request() using the resource map. # API requests are routed through api_request() using the resource map.
def api_enabled(request, course_id): def api_enabled(request, course_id):
''' '''
Returns True if the api is enabled for the course, otherwise False. Returns True if the api is enabled for the course, otherwise False.
...@@ -35,6 +36,7 @@ def api_enabled(request, course_id): ...@@ -35,6 +36,7 @@ def api_enabled(request, course_id):
course = _get_course(request, course_id) course = _get_course(request, course_id)
return notes_enabled_for_course(course) return notes_enabled_for_course(course)
@login_required @login_required
def api_request(request, course_id, **kwargs): def api_request(request, course_id, **kwargs):
''' '''
...@@ -86,6 +88,7 @@ def api_request(request, course_id, **kwargs): ...@@ -86,6 +88,7 @@ def api_request(request, course_id, **kwargs):
return response return response
def api_format(request, response, data): def api_format(request, response, data):
''' '''
Returns a two-element list containing the content type and content. Returns a two-element list containing the content type and content.
...@@ -97,6 +100,7 @@ def api_format(request, response, data): ...@@ -97,6 +100,7 @@ def api_format(request, response, data):
content = json.dumps(data) content = json.dumps(data)
return [content_type, content] return [content_type, content]
def _get_course(request, course_id): def _get_course(request, course_id):
''' '''
Helper function to load and return a user's course. Helper function to load and return a user's course.
...@@ -106,6 +110,7 @@ def _get_course(request, course_id): ...@@ -106,6 +110,7 @@ def _get_course(request, course_id):
#----------------------------------------------------------------------# #----------------------------------------------------------------------#
# API actions exposed via the resource map. # API actions exposed via the resource map.
def index(request, course_id): def index(request, course_id):
''' '''
Returns a list of annotation objects. Returns a list of annotation objects.
...@@ -117,6 +122,7 @@ def index(request, course_id): ...@@ -117,6 +122,7 @@ def index(request, course_id):
return [HttpResponse(), [note.as_dict() for note in notes]] return [HttpResponse(), [note.as_dict() for note in notes]]
def create(request, course_id): def create(request, course_id):
''' '''
Receives an annotation object to create and returns a 303 with the read location. Receives an annotation object to create and returns a 303 with the read location.
...@@ -135,6 +141,7 @@ def create(request, course_id): ...@@ -135,6 +141,7 @@ def create(request, course_id):
return [response, None] return [response, None]
def read(request, course_id, note_id): def read(request, course_id, note_id):
''' '''
Returns a single annotation object. Returns a single annotation object.
...@@ -149,6 +156,7 @@ def read(request, course_id, note_id): ...@@ -149,6 +156,7 @@ def read(request, course_id, note_id):
return [HttpResponse(), note.as_dict()] return [HttpResponse(), note.as_dict()]
def update(request, course_id, note_id): def update(request, course_id, note_id):
''' '''
Updates an annotation object and returns a 303 with the read location. Updates an annotation object and returns a 303 with the read location.
...@@ -174,6 +182,7 @@ def update(request, course_id, note_id): ...@@ -174,6 +182,7 @@ def update(request, course_id, note_id):
return [response, None] return [response, None]
def delete(request, course_id, note_id): def delete(request, course_id, note_id):
''' '''
Deletes the annotation object and returns a 204 with no content. Deletes the annotation object and returns a 204 with no content.
...@@ -190,6 +199,7 @@ def delete(request, course_id, note_id): ...@@ -190,6 +199,7 @@ def delete(request, course_id, note_id):
return [HttpResponse('', status=204), None] return [HttpResponse('', status=204), None]
def search(request, course_id): def search(request, course_id):
''' '''
Returns a subset of annotation objects based on a search query. Returns a subset of annotation objects based on a search query.
...@@ -222,7 +232,7 @@ def search(request, course_id): ...@@ -222,7 +232,7 @@ def search(request, course_id):
# retrieve notes # retrieve notes
notes = Note.objects.order_by('id').filter(**filters) notes = Note.objects.order_by('id').filter(**filters)
total = notes.count() total = notes.count()
rows = notes[offset:offset+limit] rows = notes[offset:offset + limit]
result = { result = {
'total': total, 'total': total,
'rows': [note.as_dict() for note in rows] 'rows': [note.as_dict() for note in rows]
...@@ -230,6 +240,7 @@ def search(request, course_id): ...@@ -230,6 +240,7 @@ def search(request, course_id):
return [HttpResponse(), result] return [HttpResponse(), result]
def root(request, course_id): def root(request, course_id):
''' '''
Returns version information about the API. Returns version information about the API.
......
...@@ -2,12 +2,12 @@ from django.db import models ...@@ -2,12 +2,12 @@ from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
import json import json
import logging import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class Note(models.Model): class Note(models.Model):
user = models.ForeignKey(User, db_index=True) user = models.ForeignKey(User, db_index=True)
course_id = models.CharField(max_length=255, db_index=True) course_id = models.CharField(max_length=255, db_index=True)
......
...@@ -14,6 +14,7 @@ import logging ...@@ -14,6 +14,7 @@ import logging
from . import utils, api, models from . import utils, api, models
class UtilsTest(TestCase): class UtilsTest(TestCase):
def setUp(self): def setUp(self):
''' '''
...@@ -35,13 +36,13 @@ class UtilsTest(TestCase): ...@@ -35,13 +36,13 @@ class UtilsTest(TestCase):
Tests that notes are enabled when the course tab configuration contains Tests that notes are enabled when the course tab configuration contains
a tab with type "notes." a tab with type "notes."
''' '''
self.course.tabs = [ self.course.tabs = [{'type': 'foo'},
{'type': 'foo'},
{'name': 'My Notes', 'type': 'notes'}, {'name': 'My Notes', 'type': 'notes'},
{'type':'bar'}] {'type': 'bar'}]
self.assertTrue(utils.notes_enabled_for_course(self.course)) self.assertTrue(utils.notes_enabled_for_course(self.course))
class ApiTest(TestCase): class ApiTest(TestCase):
def setUp(self): def setUp(self):
...@@ -57,16 +58,16 @@ class ApiTest(TestCase): ...@@ -57,16 +58,16 @@ class ApiTest(TestCase):
self.instructor = User.objects.create_user('instructor', 'instructor@test.com', self.password) self.instructor = User.objects.create_user('instructor', 'instructor@test.com', self.password)
self.course_id = 'HarvardX/CB22x/The_Ancient_Greek_Hero' self.course_id = 'HarvardX/CB22x/The_Ancient_Greek_Hero'
self.note = { self.note = {
'user':self.student, 'user': self.student,
'course_id':self.course_id, 'course_id': self.course_id,
'uri':'/', 'uri': '/',
'text':'foo', 'text': 'foo',
'quote':'bar', 'quote': 'bar',
'range_start':0, 'range_start': 0,
'range_start_offset':0, 'range_start_offset': 0,
'range_end':100, 'range_end': 100,
'range_end_offset':0, 'range_end_offset': 0,
'tags':'a,b,c' 'tags': 'a,b,c'
} }
def mock_api_enabled(self, is_enabled): def mock_api_enabled(self, is_enabled):
...@@ -84,7 +85,7 @@ class ApiTest(TestCase): ...@@ -84,7 +85,7 @@ class ApiTest(TestCase):
self.client.login(username=username, password=password) self.client.login(username=username, password=password)
def url(self, name, args={}): def url(self, name, args={}):
args.update({'course_id':self.course_id}) args.update({'course_id': self.course_id})
return reverse(name, kwargs=args) return reverse(name, kwargs=args)
def create_notes(self, num_notes, create=True): def create_notes(self, num_notes, create=True):
...@@ -105,7 +106,7 @@ class ApiTest(TestCase): ...@@ -105,7 +106,7 @@ class ApiTest(TestCase):
content = json.loads(resp.content) content = json.loads(resp.content)
self.assertEqual(set(('name','version')), set(content.keys())) self.assertEqual(set(('name', 'version')), set(content.keys()))
self.assertIsInstance(content['version'], int) self.assertIsInstance(content['version'], int)
self.assertEqual(content['name'], 'Notes API') self.assertEqual(content['name'], 'Notes API')
...@@ -155,9 +156,10 @@ class ApiTest(TestCase): ...@@ -155,9 +156,10 @@ class ApiTest(TestCase):
note_dict = notes[0].as_dict() note_dict = notes[0].as_dict()
excluded_fields = ['id', 'user_id', 'created', 'updated'] excluded_fields = ['id', 'user_id', 'created', 'updated']
note = dict([(k, v) for k,v in note_dict.items() if k not in excluded_fields]) note = dict([(k, v) for k, v in note_dict.items() if k not in excluded_fields])
resp = self.client.post(self.url('notes_api_notes'), json.dumps(note), resp = self.client.post(self.url('notes_api_notes'),
json.dumps(note),
content_type='application/json', content_type='application/json',
HTTP_X_REQUESTED_WITH='XMLHttpRequest') HTTP_X_REQUESTED_WITH='XMLHttpRequest')
...@@ -168,7 +170,8 @@ class ApiTest(TestCase): ...@@ -168,7 +170,8 @@ class ApiTest(TestCase):
self.login() self.login()
for empty_test in [None, [], '']: for empty_test in [None, [], '']:
resp = self.client.post(self.url('notes_api_notes'), json.dumps(empty_test), resp = self.client.post(self.url('notes_api_notes'),
json.dumps(empty_test),
content_type='application/json', content_type='application/json',
HTTP_X_REQUESTED_WITH='XMLHttpRequest') HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertEqual(resp.status_code, 500) self.assertEqual(resp.status_code, 500)
...@@ -181,9 +184,10 @@ class ApiTest(TestCase): ...@@ -181,9 +184,10 @@ class ApiTest(TestCase):
note_dict = notes[0].as_dict() note_dict = notes[0].as_dict()
excluded_fields = ['id', 'user_id', 'created', 'updated'] + ['ranges'] excluded_fields = ['id', 'user_id', 'created', 'updated'] + ['ranges']
note = dict([(k, v) for k,v in note_dict.items() if k not in excluded_fields]) note = dict([(k, v) for k, v in note_dict.items() if k not in excluded_fields])
resp = self.client.post(self.url('notes_api_notes'), json.dumps(note), resp = self.client.post(self.url('notes_api_notes'),
json.dumps(note),
content_type='application/json', content_type='application/json',
HTTP_X_REQUESTED_WITH='XMLHttpRequest') HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertEqual(resp.status_code, 500) self.assertEqual(resp.status_code, 500)
...@@ -220,12 +224,14 @@ class ApiTest(TestCase): ...@@ -220,12 +224,14 @@ class ApiTest(TestCase):
# set the student id to a different student (not the one that created the notes) # set the student id to a different student (not the one that created the notes)
self.login(as_student=self.student2) self.login(as_student=self.student2)
resp = self.client.get(self.url('notes_api_note', { 'note_id': note.id})) resp = self.client.get(self.url('notes_api_note', {'note_id': note.id}))
self.assertEqual(resp.status_code, 403) self.assertEqual(resp.status_code, 403)
self.assertEqual(resp.content, '') self.assertEqual(resp.content, '')
@unittest.skip("skipping update test stub") @unittest.skip("skipping update test stub")
def test_update_note(self): pass def test_update_note(self):
pass
@unittest.skip("skipping search test stub") @unittest.skip("skipping search test stub")
def test_search_note(self): pass def test_search_note(self):
pass
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
id_regex = r"(?P<note_id>[0-9A-Fa-f]+)" id_regex = r"(?P<note_id>[0-9A-Fa-f]+)"
urlpatterns = patterns('notes.api', urlpatterns = patterns('notes.api',
url(r'^api$', 'api_request', {'resource':'root'}, name='notes_api_root'), url(r'^api$', 'api_request', {'resource': 'root'}, name='notes_api_root'),
url(r'^api/annotations$', 'api_request', {'resource':'notes'}, name='notes_api_notes'), url(r'^api/annotations$', 'api_request', {'resource': 'notes'}, name='notes_api_notes'),
url(r'^api/annotations/' + id_regex + r'$', 'api_request', {'resource':'note'}, name='notes_api_note'), url(r'^api/annotations/' + id_regex + r'$', 'api_request', {'resource': 'note'}, name='notes_api_note'),
url(r'^api/search', 'api_request', {'resource':'search'}, name='notes_api_search') url(r'^api/search', 'api_request', {'resource': 'search'}, name='notes_api_search')
) )
from django.conf import settings
def notes_enabled_for_course(course): def notes_enabled_for_course(course):
''' '''
Returns True if the notes app is enabled for the course, False otherwise. Returns True if the notes app is enabled for the course, False otherwise.
In order for the app to be enabled it must be:
1) enabled globally via MITX_FEATURES.
2) present in the course tab configuration.
''' '''
# TODO: create a separate policy setting to enable/disable notes
tab_type = 'notes' tab_found = next((True for t in course.tabs if t['type'] == 'notes'), False)
tabs = course.tabs feature_enabled = settings.MITX_FEATURES.get('ENABLE_STUDENT_NOTES')
tab_found = next((True for t in tabs if t['type'] == tab_type), False)
return tab_found return feature_enabled and tab_found
...@@ -6,6 +6,7 @@ from notes.models import Note ...@@ -6,6 +6,7 @@ from notes.models import Note
from notes.utils import notes_enabled_for_course from notes.utils import notes_enabled_for_course
import json import json
@login_required @login_required
def notes(request, course_id): def notes(request, course_id):
''' Displays the student's notes. ''' ''' Displays the student's notes. '''
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment