Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
bd581fdb
Commit
bd581fdb
authored
Sep 29, 2014
by
Dave St.Germain
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cleaning up pylint and pep8 errors.
parent
c5530b75
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
117 additions
and
68 deletions
+117
-68
lms/djangoapps/mobile_api/__init__.py
+3
-0
lms/djangoapps/mobile_api/course_info/__init__.py
+3
-0
lms/djangoapps/mobile_api/course_info/models.py
+3
-2
lms/djangoapps/mobile_api/course_info/tests.py
+6
-3
lms/djangoapps/mobile_api/course_info/urls.py
+4
-4
lms/djangoapps/mobile_api/course_info/views.py
+3
-4
lms/djangoapps/mobile_api/models.py
+3
-2
lms/djangoapps/mobile_api/urls.py
+5
-2
lms/djangoapps/mobile_api/users/__init__.py
+3
-0
lms/djangoapps/mobile_api/users/models.py
+3
-2
lms/djangoapps/mobile_api/users/serializers.py
+11
-4
lms/djangoapps/mobile_api/users/tests.py
+11
-8
lms/djangoapps/mobile_api/users/urls.py
+6
-6
lms/djangoapps/mobile_api/users/views.py
+10
-5
lms/djangoapps/mobile_api/video_outlines/__init__.py
+3
-0
lms/djangoapps/mobile_api/video_outlines/models.py
+3
-2
lms/djangoapps/mobile_api/video_outlines/serializers.py
+15
-5
lms/djangoapps/mobile_api/video_outlines/tests.py
+14
-9
lms/djangoapps/mobile_api/video_outlines/urls.py
+6
-5
lms/djangoapps/mobile_api/video_outlines/views.py
+2
-5
No files found.
lms/djangoapps/mobile_api/__init__.py
View file @
bd581fdb
"""
Mobile API
"""
lms/djangoapps/mobile_api/course_info/__init__.py
View file @
bd581fdb
"""
Course info API
"""
lms/djangoapps/mobile_api/course_info/models.py
View file @
bd581fdb
# A models.py is required to make this an app (until we move to Django 1.7)
\ No newline at end of file
"""
A models.py is required to make this an app (until we move to Django 1.7)
"""
lms/djangoapps/mobile_api/course_info/tests.py
View file @
bd581fdb
...
...
@@ -4,7 +4,7 @@ Tests for course_info
from
django.test.utils
import
override_settings
from
django.core.urlresolvers
import
reverse
from
rest_framework.test
import
APITestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
ItemFactory
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
courseware.tests.factories
import
UserFactory
from
courseware.tests.tests
import
TEST_DATA_MONGO_MODULESTORE
...
...
@@ -12,6 +12,9 @@ from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE
@override_settings
(
MODULESTORE
=
TEST_DATA_MONGO_MODULESTORE
)
class
TestVideoOutline
(
ModuleStoreTestCase
,
APITestCase
):
"""
Tests for /api/mobile/v0.5/course_info/...
"""
def
setUp
(
self
):
super
(
TestVideoOutline
,
self
)
.
setUp
()
self
.
user
=
UserFactory
.
create
()
...
...
@@ -22,7 +25,7 @@ class TestVideoOutline(ModuleStoreTestCase, APITestCase):
url
=
reverse
(
'course-about-detail'
,
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)})
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertTrue
(
'overview'
in
response
.
data
)
self
.
assertTrue
(
'overview'
in
response
.
data
)
# pylint: disable=E1103
def
test_handouts
(
self
):
url
=
reverse
(
'course-handouts-list'
,
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)})
...
...
@@ -33,5 +36,5 @@ class TestVideoOutline(ModuleStoreTestCase, APITestCase):
url
=
reverse
(
'course-updates-list'
,
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)})
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
data
,
[])
self
.
assertEqual
(
response
.
data
,
[])
# pylint: disable=E1103
# TODO: add handouts and updates, somehow
lms/djangoapps/mobile_api/course_info/urls.py
View file @
bd581fdb
from
django.conf.urls
import
patterns
,
url
,
include
"""
URLs for course_info API
"""
from
django.conf.urls
import
patterns
,
url
from
django.conf
import
settings
from
rest_framework
import
routers
from
rest_framework.urlpatterns
import
format_suffix_patterns
from
.views
import
CourseAboutDetail
,
CourseUpdatesList
,
CourseHandoutsList
...
...
@@ -23,4 +24,3 @@ urlpatterns = patterns(
name
=
'course-updates-list'
),
)
lms/djangoapps/mobile_api/course_info/views.py
View file @
bd581fdb
...
...
@@ -5,15 +5,11 @@ from django.http import Http404
from
rest_framework
import
generics
,
permissions
from
rest_framework.authentication
import
OAuth2Authentication
,
SessionAuthentication
from
rest_framework.response
import
Response
from
rest_framework.views
import
APIView
from
courseware.model_data
import
FieldDataCache
from
courseware.module_render
import
get_module
from
courseware.courses
import
get_course_about_section
,
get_course_info_section_module
from
opaque_keys.edx.keys
import
CourseKey
from
xmodule.modulestore.django
import
modulestore
from
student.models
import
CourseEnrollment
,
User
class
CourseUpdatesList
(
generics
.
ListAPIView
):
...
...
@@ -55,6 +51,9 @@ class CourseHandoutsList(generics.ListAPIView):
class
CourseAboutDetail
(
generics
.
RetrieveAPIView
):
"""
Renders course 'about' page
"""
authentication_classes
=
(
OAuth2Authentication
,
SessionAuthentication
)
permission_classes
=
(
permissions
.
IsAuthenticated
,)
...
...
lms/djangoapps/mobile_api/models.py
View file @
bd581fdb
# A models.py is required to make this an app (until we move to Django 1.7)
\ No newline at end of file
"""
A models.py is required to make this an app (until we move to Django 1.7)
"""
lms/djangoapps/mobile_api/urls.py
View file @
bd581fdb
"""
URLs for mobile API
"""
from
django.conf.urls
import
patterns
,
url
,
include
from
rest_framework
import
routers
from
.users.views
import
my_user_info
# Additionally, we include login URLs for the browseable API.
urlpatterns
=
patterns
(
''
,
urlpatterns
=
patterns
(
''
,
url
(
r'^users/'
,
include
(
'mobile_api.users.urls'
)),
url
(
r'^my_user_info'
,
my_user_info
),
url
(
r'^video_outlines/'
,
include
(
'mobile_api.video_outlines.urls'
)),
...
...
lms/djangoapps/mobile_api/users/__init__.py
View file @
bd581fdb
"""
User API
"""
lms/djangoapps/mobile_api/users/models.py
View file @
bd581fdb
# A models.py is required to make this an app (until we move to Django 1.7)
\ No newline at end of file
"""
A models.py is required to make this an app (until we move to Django 1.7)
"""
lms/djangoapps/mobile_api/users/serializers.py
View file @
bd581fdb
"""
Serializer for user API
"""
from
rest_framework
import
serializers
from
rest_framework.reverse
import
reverse
from
xmodule.modulestore.search
import
path_to_location
from
courseware.courses
import
course_image_url
from
student.models
import
CourseEnrollment
,
User
...
...
@@ -59,22 +60,28 @@ class CourseField(serializers.RelatedField):
class
CourseEnrollmentSerializer
(
serializers
.
ModelSerializer
):
"""
Serializes CourseEnrollment models
"""
course
=
CourseField
()
class
Meta
:
class
Meta
:
# pylint: disable=C0111
model
=
CourseEnrollment
fields
=
(
'created'
,
'mode'
,
'is_active'
,
'course'
)
lookup_field
=
'username'
class
UserSerializer
(
serializers
.
HyperlinkedModelSerializer
):
"""
Serializes User models
"""
name
=
serializers
.
Field
(
source
=
'profile.name'
)
course_enrollments
=
serializers
.
HyperlinkedIdentityField
(
view_name
=
'courseenrollment-detail'
,
lookup_field
=
'username'
)
class
Meta
:
class
Meta
:
# pylint: disable=C0111
model
=
User
fields
=
(
'id'
,
'username'
,
'email'
,
'name'
,
'course_enrollments'
)
lookup_field
=
'username'
lms/djangoapps/mobile_api/users/tests.py
View file @
bd581fdb
...
...
@@ -4,7 +4,7 @@ Tests for users API
from
rest_framework.test
import
APITestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
courseware.tests.factories
import
StaffFactory
,
UserFactory
from
courseware.tests.factories
import
UserFactory
from
django.core.urlresolvers
import
reverse
from
mobile_api.users.serializers
import
CourseEnrollmentSerializer
from
student.models
import
CourseEnrollment
...
...
@@ -25,7 +25,10 @@ class TestUserApi(ModuleStoreTestCase, APITestCase):
super
(
TestUserApi
,
self
)
.
tearDown
()
self
.
client
.
logout
()
def
enroll
(
self
):
def
_enroll
(
self
):
"""
enroll test user in test course
"""
resp
=
self
.
client
.
post
(
reverse
(
'change_enrollment'
),
{
'enrollment_action'
:
'enroll'
,
'course_id'
:
self
.
course
.
id
.
to_deprecated_string
(),
...
...
@@ -39,13 +42,13 @@ class TestUserApi(ModuleStoreTestCase, APITestCase):
self
.
client
.
login
(
username
=
self
.
username
,
password
=
self
.
password
)
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
data
,
[])
self
.
assertEqual
(
response
.
data
,
[])
# pylint: disable=E1103
self
.
enroll
()
self
.
_
enroll
()
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
courses
=
response
.
data
courses
=
response
.
data
# pylint: disable=E1103
self
.
assertTrue
(
len
(
courses
),
1
)
course
=
courses
[
0
][
'course'
]
...
...
@@ -59,7 +62,7 @@ class TestUserApi(ModuleStoreTestCase, APITestCase):
url
=
reverse
(
'user-detail'
,
kwargs
=
{
'username'
:
self
.
user
.
username
})
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
data
=
response
.
data
data
=
response
.
data
# pylint: disable=E1103
self
.
assertEqual
(
data
[
'username'
],
self
.
user
.
username
)
self
.
assertEqual
(
data
[
'email'
],
self
.
user
.
email
)
...
...
@@ -86,7 +89,7 @@ class TestUserApi(ModuleStoreTestCase, APITestCase):
def
test_course_serializer
(
self
):
self
.
client
.
login
(
username
=
self
.
username
,
password
=
self
.
password
)
self
.
enroll
()
serialized
=
CourseEnrollmentSerializer
(
CourseEnrollment
.
enrollments_for_user
(
self
.
user
)[
0
])
.
data
self
.
_
enroll
()
serialized
=
CourseEnrollmentSerializer
(
CourseEnrollment
.
enrollments_for_user
(
self
.
user
)[
0
])
.
data
# pylint: disable=E1101
self
.
assertEqual
(
serialized
[
'course'
][
'video_outline'
],
None
)
self
.
assertEqual
(
serialized
[
'course'
][
'name'
],
self
.
course
.
display_name
)
lms/djangoapps/mobile_api/users/urls.py
View file @
bd581fdb
from
django.conf.urls
import
patterns
,
url
,
include
from
rest_framework
import
routers
from
rest_framework.urlpatterns
import
format_suffix_patterns
"""
URLs for user API
"""
from
django.conf.urls
import
patterns
,
url
from
.views
import
UserDetail
,
UserCourseEnrollmentsList
urlpatterns
=
patterns
(
'mobile_api.users.views'
,
urlpatterns
=
patterns
(
'mobile_api.users.views'
,
url
(
r'^(?P<username>[\w.+-]+)$'
,
UserDetail
.
as_view
(),
name
=
'user-detail'
),
url
(
r'^(?P<username>[\w.+-]+)/course_enrollments/$'
,
...
...
@@ -13,4 +14,3 @@ urlpatterns = patterns('mobile_api.users.views',
name
=
'courseenrollment-detail'
),
)
lms/djangoapps/mobile_api/users/views.py
View file @
bd581fdb
from
django.core.exceptions
import
PermissionDenied
"""
Views for user API
"""
from
django.shortcuts
import
redirect
from
rest_framework
import
generics
,
permissions
from
rest_framework.authentication
import
OAuth2Authentication
,
SessionAuthentication
from
rest_framework.decorators
import
api_view
,
authentication_classes
,
permission_classes
from
rest_framework.exceptions
import
PermissionDenied
from
rest_framework.permissions
import
IsAuthenticated
from
rest_framework.response
import
Response
from
courseware.access
import
has_access
from
student.forms
import
PasswordResetFormNoActive
from
student.models
import
CourseEnrollment
,
User
from
xmodule.modulestore.django
import
modulestore
from
.serializers
import
CourseEnrollmentSerializer
,
UserSerializer
class
IsUser
(
permissions
.
BasePermission
):
"""
Permission that checks to see if the request user matches the User models
"""
def
has_object_permission
(
self
,
request
,
view
,
obj
):
return
request
.
user
==
obj
...
...
@@ -56,8 +57,12 @@ class UserCourseEnrollmentsList(generics.ListAPIView):
@authentication_classes
((
OAuth2Authentication
,
SessionAuthentication
))
@permission_classes
((
IsAuthenticated
,))
def
my_user_info
(
request
):
"""
Redirect to the currently-logged-in user's info page
"""
return
redirect
(
"user-detail"
,
username
=
request
.
user
.
username
)
def
mobile_course_enrollments
(
enrollments
,
user
):
"""
Return enrollments only if courses are mobile_available (or if the user has staff access)
...
...
lms/djangoapps/mobile_api/video_outlines/__init__.py
View file @
bd581fdb
"""
Video outline API
"""
lms/djangoapps/mobile_api/video_outlines/models.py
View file @
bd581fdb
# A models.py is required to make this an app (until we move to Django 1.7)
\ No newline at end of file
"""
A models.py is required to make this an app (until we move to Django 1.7)
"""
lms/djangoapps/mobile_api/video_outlines/serializers.py
View file @
bd581fdb
"""
Serializer for video outline
"""
from
rest_framework.reverse
import
reverse
from
courseware.access
import
has_access
...
...
@@ -8,19 +11,21 @@ from edxval.api import (
class
BlockOutline
(
object
):
"""
Serializes course videos, pulling data from VAL and the video modules.
"""
def
__init__
(
self
,
course_id
,
start_block
,
categories_to_outliner
,
request
):
"""Create a BlockOutline using `start_block` as a starting point."""
self
.
start_block
=
start_block
self
.
categories_to_outliner
=
categories_to_outliner
self
.
course_id
=
course_id
self
.
request
=
request
# needed for making full URLS
self
.
request
=
request
# needed for making full URLS
self
.
local_cache
=
{}
try
:
self
.
local_cache
[
'course_videos'
]
=
get_video_info_for_course_and_profile
(
unicode
(
course_id
),
"mobile_low"
)
except
ValInternalError
:
# pragma: nocover
except
ValInternalError
:
# pragma: nocover
self
.
local_cache
[
'course_videos'
]
=
{}
def
__iter__
(
self
):
...
...
@@ -29,6 +34,7 @@ class BlockOutline(object):
# path should be optional
def
path
(
block
):
"""path for block"""
block_path
=
[]
while
block
in
child_to_parent
:
block
=
child_to_parent
[
block
]
...
...
@@ -40,6 +46,7 @@ class BlockOutline(object):
return
reversed
(
block_path
)
def
find_urls
(
block
):
"""section and unit urls for block"""
block_path
=
[]
while
block
in
child_to_parent
:
block
=
child_to_parent
[
block
]
...
...
@@ -81,8 +88,8 @@ class BlockOutline(object):
continue
summary_fn
=
self
.
categories_to_outliner
[
curr_block
.
category
]
block_path
=
list
(
path
(
block
))
unit_url
,
section_url
=
find_urls
(
block
)
block_path
=
list
(
path
(
curr_
block
))
unit_url
,
section_url
=
find_urls
(
curr_
block
)
yield
{
"path"
:
block_path
,
"named_path"
:
[
b
[
"name"
]
for
b
in
block_path
[:
-
1
]],
...
...
@@ -98,6 +105,9 @@ class BlockOutline(object):
def
video_summary
(
course
,
course_id
,
video_descriptor
,
request
,
local_cache
):
"""
returns summary dict for the given video module
"""
# First try to check VAL for the URLs we want.
val_video_info
=
local_cache
[
'course_videos'
]
.
get
(
video_descriptor
.
edx_video_id
,
{})
if
val_video_info
:
...
...
lms/djangoapps/mobile_api/video_outlines/tests.py
View file @
bd581fdb
...
...
@@ -17,8 +17,12 @@ import copy
TEST_DATA_CONTENTSTORE
=
copy
.
deepcopy
(
settings
.
CONTENTSTORE
)
TEST_DATA_CONTENTSTORE
[
'DOC_STORE_CONFIG'
][
'db'
]
=
'test_xcontent_
%
s'
%
uuid4
()
.
hex
@override_settings
(
MODULESTORE
=
TEST_DATA_MONGO_MODULESTORE
,
CONTENTSTORE
=
TEST_DATA_CONTENTSTORE
)
class
TestVideoOutline
(
ModuleStoreTestCase
,
APITestCase
):
"""
Tests for /api/mobile/v0.5/video_outlines/
"""
def
setUp
(
self
):
super
(
TestVideoOutline
,
self
)
.
setUp
()
self
.
user
=
UserFactory
.
create
()
...
...
@@ -57,15 +61,16 @@ class TestVideoOutline(ModuleStoreTestCase, APITestCase):
'extension'
:
'mp4'
,
'width'
:
1280
,
'height'
:
720
})
})
api
.
create_profile
({
'profile_name'
:
'mobile_low'
,
'extension'
:
'mp4'
,
'width'
:
640
,
'height'
:
480
})
})
val_video
=
api
.
create_video
({
# create the video in VAL
api
.
create_video
({
'edx_video_id'
:
self
.
edx_video_id
,
'client_video_id'
:
u"test video omega
\u03a9
"
,
'duration'
:
12
,
...
...
@@ -94,7 +99,7 @@ class TestVideoOutline(ModuleStoreTestCase, APITestCase):
sub
=
subid
)
result_location
=
transcripts_utils
.
save_subs_to_store
({
transcripts_utils
.
save_subs_to_store
({
'start'
:
[
100
,
200
,
240
,
390
,
1000
],
'end'
:
[
200
,
240
,
380
,
1000
,
1500
],
'text'
:
[
...
...
@@ -116,20 +121,20 @@ class TestVideoOutline(ModuleStoreTestCase, APITestCase):
self
.
assertEqual
(
response
.
status_code
,
403
)
def
test_course_list
(
self
):
second_video
=
ItemFactory
.
create
(
ItemFactory
.
create
(
parent_location
=
self
.
other_unit
.
location
,
category
=
"video"
,
display_name
=
u"test video omega 2
\u03a9
"
,
html5_sources
=
[
self
.
html5_video_url
]
)
third_video
=
ItemFactory
.
create
(
ItemFactory
.
create
(
parent_location
=
self
.
other_unit
.
location
,
category
=
"video"
,
display_name
=
u"test video omega 3
\u03a9
"
,
source
=
self
.
html5_video_url
)
draft_video
=
ItemFactory
.
create
(
ItemFactory
.
create
(
parent_location
=
self
.
unit
.
location
,
category
=
"video"
,
edx_video_id
=
self
.
edx_video_id
,
...
...
@@ -141,7 +146,7 @@ class TestVideoOutline(ModuleStoreTestCase, APITestCase):
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
course_outline
=
response
.
data
course_outline
=
response
.
data
# pylint: disable=E1103
self
.
assertEqual
(
len
(
course_outline
),
3
)
vid
=
course_outline
[
0
]
self
.
assertTrue
(
'test_subsection_omega_
%
CE
%
A9'
in
vid
[
'section_url'
])
...
...
@@ -161,7 +166,7 @@ class TestVideoOutline(ModuleStoreTestCase, APITestCase):
'course_id'
:
unicode
(
self
.
course
.
id
),
'block_id'
:
unicode
(
self
.
video
.
scope_ids
.
usage_id
.
block_id
),
'lang'
:
'pl'
}
}
url
=
reverse
(
'video-transcripts-detail'
,
kwargs
=
kwargs
)
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
404
)
...
...
lms/djangoapps/mobile_api/video_outlines/urls.py
View file @
bd581fdb
from
django.conf.urls
import
patterns
,
url
,
include
"""
URLs for video outline API
"""
from
django.conf.urls
import
patterns
,
url
from
django.conf
import
settings
from
rest_framework
import
routers
from
rest_framework.urlpatterns
import
format_suffix_patterns
from
.views
import
VideoSummaryList
,
VideoTranscripts
urlpatterns
=
patterns
(
'mobile_api.video_outlines.views'
,
urlpatterns
=
patterns
(
'mobile_api.video_outlines.views'
,
url
(
r'^courses/{}$'
.
format
(
settings
.
COURSE_ID_PATTERN
),
VideoSummaryList
.
as_view
(),
...
...
@@ -17,4 +19,3 @@ urlpatterns = patterns('mobile_api.video_outlines.views',
name
=
'video-transcripts-detail'
),
)
lms/djangoapps/mobile_api/video_outlines/views.py
View file @
bd581fdb
...
...
@@ -8,19 +8,16 @@ general XBlock representation in this rather specialized formatting.
"""
from
functools
import
partial
from
django.core.cache
import
cache
from
django.http
import
Http404
,
HttpResponse
from
rest_framework
import
generics
,
permissions
from
rest_framework.authentication
import
OAuth2Authentication
,
SessionAuthentication
from
rest_framework.response
import
Response
from
rest_framework.views
import
APIView
from
rest_framework.exceptions
import
PermissionDenied
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.locator
import
BlockUsageLocator
from
courseware.access
import
has_access
from
student.models
import
CourseEnrollment
,
User
from
xmodule.exceptions
import
NotFoundError
from
xmodule.modulestore.django
import
modulestore
...
...
@@ -38,8 +35,8 @@ class VideoSummaryList(generics.ListAPIView):
video_outline
=
list
(
BlockOutline
(
course_id
,
course
,
course_id
,
course
,
{
"video"
:
partial
(
video_summary
,
course
)},
request
,
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment