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
1cdf8497
Commit
1cdf8497
authored
Oct 28, 2014
by
John Eskew
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5556 from edx/jeskew/fix_split_old_analytics_call
Fix old analytics api call for Split modulestore.
parents
1f97031f
5e103a91
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
110 additions
and
44 deletions
+110
-44
common/lib/xmodule/xmodule/tests/test_progress.py
+30
-30
lms/djangoapps/instructor/tests/test_api.py
+72
-10
lms/djangoapps/instructor/views/api.py
+6
-3
lms/djangoapps/instructor/views/legacy.py
+2
-1
No files found.
common/lib/xmodule/xmodule/tests/test_progress.py
View file @
1cdf8497
...
...
@@ -23,12 +23,12 @@ class ProgressTest(unittest.TestCase):
def
test_create_object
(
self
):
# These should work:
p
=
Progress
(
0
,
2
)
p
=
Progress
(
1
,
2
)
p
=
Progress
(
2
,
2
)
p
rg1
=
Progress
(
0
,
2
)
# pylint: disable=W0612
p
rg2
=
Progress
(
1
,
2
)
# pylint: disable=W0612
p
rg3
=
Progress
(
2
,
2
)
# pylint: disable=W0612
p
=
Progress
(
2.5
,
5.0
)
p
=
Progress
(
3.7
,
12.3333
)
p
rg4
=
Progress
(
2.5
,
5.0
)
# pylint: disable=W0612
p
rg5
=
Progress
(
3.7
,
12.3333
)
# pylint: disable=W0612
# These shouldn't
self
.
assertRaises
(
ValueError
,
Progress
,
0
,
0
)
...
...
@@ -44,10 +44,10 @@ class ProgressTest(unittest.TestCase):
self
.
assertEqual
((
0
,
2
),
Progress
(
-
2
,
2
)
.
frac
())
def
test_frac
(
self
):
p
=
Progress
(
1
,
2
)
(
a
,
b
)
=
p
.
frac
()
self
.
assertEqual
(
a
,
1
)
self
.
assertEqual
(
b
,
2
)
p
rg
=
Progress
(
1
,
2
)
(
a
_mem
,
b_mem
)
=
prg
.
frac
()
self
.
assertEqual
(
a
_mem
,
1
)
self
.
assertEqual
(
b
_mem
,
2
)
def
test_percent
(
self
):
self
.
assertEqual
(
self
.
not_started
.
percent
(),
0
)
...
...
@@ -98,38 +98,38 @@ class ProgressTest(unittest.TestCase):
def
test_to_js_detail_str
(
self
):
'''Test the Progress.to_js_detail_str() method'''
f
=
Progress
.
to_js_detail_str
for
p
in
(
self
.
not_started
,
self
.
half_done
,
self
.
done
):
self
.
assertEqual
(
f
(
p
),
str
(
p
))
for
p
rg
in
(
self
.
not_started
,
self
.
half_done
,
self
.
done
):
self
.
assertEqual
(
f
(
p
rg
),
str
(
prg
))
# But None should be encoded as 0
self
.
assertEqual
(
f
(
None
),
"0"
)
def
test_add
(
self
):
'''Test the Progress.add_counts() method'''
p
=
Progress
(
0
,
2
)
p2
=
Progress
(
1
,
3
)
p3
=
Progress
(
2
,
5
)
p
N
one
=
None
p
rg1
=
Progress
(
0
,
2
)
p
rg
2
=
Progress
(
1
,
3
)
p
rg
3
=
Progress
(
2
,
5
)
p
rg_n
one
=
None
add
=
lambda
a
,
b
:
Progress
.
add_counts
(
a
,
b
)
.
frac
()
self
.
assertEqual
(
add
(
p
,
p
),
(
0
,
4
))
self
.
assertEqual
(
add
(
p
,
p
2
),
(
1
,
5
))
self
.
assertEqual
(
add
(
p
2
,
p
3
),
(
3
,
8
))
self
.
assertEqual
(
add
(
p
rg1
,
prg1
),
(
0
,
4
))
self
.
assertEqual
(
add
(
p
rg1
,
prg
2
),
(
1
,
5
))
self
.
assertEqual
(
add
(
p
rg2
,
prg
3
),
(
3
,
8
))
self
.
assertEqual
(
add
(
p
2
,
pNone
),
p
2
.
frac
())
self
.
assertEqual
(
add
(
p
None
,
p2
),
p
2
.
frac
())
self
.
assertEqual
(
add
(
p
rg2
,
prg_none
),
prg
2
.
frac
())
self
.
assertEqual
(
add
(
p
rg_none
,
prg2
),
prg
2
.
frac
())
def
test_equality
(
self
):
'''Test that comparing Progress objects for equality
works correctly.'''
p
=
Progress
(
1
,
2
)
p2
=
Progress
(
2
,
4
)
p3
=
Progress
(
1
,
2
)
self
.
assertTrue
(
p
==
p
3
)
self
.
assertFalse
(
p
==
p
2
)
p
rg1
=
Progress
(
1
,
2
)
p
rg
2
=
Progress
(
2
,
4
)
p
rg
3
=
Progress
(
1
,
2
)
self
.
assertTrue
(
p
rg1
==
prg
3
)
self
.
assertFalse
(
p
rg1
==
prg
2
)
# Check != while we're at it
self
.
assertTrue
(
p
!=
p
2
)
self
.
assertFalse
(
p
!=
p
3
)
self
.
assertTrue
(
p
rg1
!=
prg
2
)
self
.
assertFalse
(
p
rg1
!=
prg
3
)
class
ModuleProgressTest
(
unittest
.
TestCase
):
...
...
@@ -137,6 +137,6 @@ class ModuleProgressTest(unittest.TestCase):
'''
def
test_xmodule_default
(
self
):
'''Make sure default get_progress exists, returns None'''
xm
=
x_module
.
XModule
(
Mock
(),
get_test_system
(),
DictFieldData
({
'location'
:
'a://b/c/d/e'
}),
Mock
())
p
=
xm
.
get_progress
()
self
.
assertEqual
(
p
,
None
)
xm
od
=
x_module
.
XModule
(
Mock
(),
get_test_system
(),
DictFieldData
({
'location'
:
'a://b/c/d/e'
}),
Mock
())
p
rg
=
xmod
.
get_progress
()
self
.
assertEqual
(
p
rg
,
None
)
lms/djangoapps/instructor/tests/test_api.py
View file @
1cdf8497
...
...
@@ -29,6 +29,8 @@ from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
courseware.tests.helpers
import
LoginEnrollmentTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
ItemFactory
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore.django
import
modulestore
from
student.tests.factories
import
UserFactory
from
courseware.tests.factories
import
StaffFactory
,
InstructorFactory
,
BetaTesterFactory
from
student.roles
import
CourseBetaTesterRole
...
...
@@ -2563,6 +2565,7 @@ class TestInstructorEmailContentList(ModuleStoreTestCase, LoginEnrollmentTestCas
self
.
assertDictEqual
(
expected_info
,
returned_info
)
@ddt.ddt
@override_settings
(
MODULESTORE
=
TEST_DATA_MIXED_MODULESTORE
)
@override_settings
(
ANALYTICS_SERVER_URL
=
"http://robotanalyticsserver.netbot:900/"
)
@override_settings
(
ANALYTICS_API_KEY
=
"robot_api_key"
)
...
...
@@ -2590,25 +2593,84 @@ class TestInstructorAPIAnalyticsProxy(ModuleStoreTestCase, LoginEnrollmentTestCa
self
.
instructor
=
InstructorFactory
(
course_key
=
self
.
course
.
id
)
self
.
client
.
login
(
username
=
self
.
instructor
.
username
,
password
=
'test'
)
@ddt.data
((
ModuleStoreEnum
.
Type
.
mongo
,
False
),
(
ModuleStoreEnum
.
Type
.
split
,
True
))
@ddt.unpack
@patch.object
(
instructor
.
views
.
api
.
requests
,
'get'
)
def
test_analytics_proxy_url
(
self
,
act
):
def
test_analytics_proxy_url
(
self
,
store_type
,
assert_wo_encoding
,
act
):
""" Test legacy analytics proxy url generation. """
with
modulestore
()
.
default_store
(
store_type
):
course
=
CourseFactory
.
create
()
instructor_local
=
InstructorFactory
(
course_key
=
course
.
id
)
self
.
client
.
login
(
username
=
instructor_local
.
username
,
password
=
'test'
)
act
.
return_value
=
self
.
FakeProxyResponse
()
url
=
reverse
(
'proxy_legacy_analytics'
,
kwargs
=
{
'course_id'
:
course
.
id
.
to_deprecated_string
()})
response
=
self
.
client
.
get
(
url
,
{
'aname'
:
'ProblemGradeDistribution'
})
self
.
assertEqual
(
response
.
status_code
,
200
)
# Make request URL pattern - everything but course id.
url_pattern
=
"{url}get?aname={aname}&course_id={course_id}&apikey={api_key}"
.
format
(
url
=
"http://robotanalyticsserver.netbot:900/"
,
aname
=
"ProblemGradeDistribution"
,
course_id
=
"{course_id!s}"
,
api_key
=
"robot_api_key"
,
)
if
assert_wo_encoding
:
# Format url with no URL-encoding of parameters.
assert_url
=
url_pattern
.
format
(
course_id
=
course
.
id
.
to_deprecated_string
())
with
self
.
assertRaises
(
AssertionError
):
act
.
assert_called_once_with
(
assert_url
)
# Format url *with* URL-encoding of parameters.
expected_url
=
url_pattern
.
format
(
course_id
=
quote
(
course
.
id
.
to_deprecated_string
()))
act
.
assert_called_once_with
(
expected_url
)
@override_settings
(
ANALYTICS_SERVER_URL
=
""
)
@patch.object
(
instructor
.
views
.
api
.
requests
,
'get'
)
def
test_analytics_proxy_server_url
(
self
,
act
):
"""
Test legacy analytics when empty server url.
"""
act
.
return_value
=
self
.
FakeProxyResponse
()
url
=
reverse
(
'proxy_legacy_analytics'
,
kwargs
=
{
'course_id'
:
self
.
course
.
id
.
to_deprecated_string
()})
response
=
self
.
client
.
get
(
url
,
{
'aname'
:
'ProblemGradeDistribution'
})
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
status_code
,
501
)
# check request url
expected_url
=
"{url}get?aname={aname}&course_id={course_id!s}&apikey={api_key}"
.
format
(
url
=
"http://robotanalyticsserver.netbot:900/"
,
aname
=
"ProblemGradeDistribution"
,
course_id
=
self
.
course
.
id
.
to_deprecated_string
(),
api_key
=
"robot_api_key"
,
)
act
.
assert_called_once_with
(
expected_url
)
@override_settings
(
ANALYTICS_API_KEY
=
""
)
@patch.object
(
instructor
.
views
.
api
.
requests
,
'get'
)
def
test_analytics_proxy_api_key
(
self
,
act
):
"""
Test legacy analytics when empty server API key.
"""
act
.
return_value
=
self
.
FakeProxyResponse
()
url
=
reverse
(
'proxy_legacy_analytics'
,
kwargs
=
{
'course_id'
:
self
.
course
.
id
.
to_deprecated_string
()})
response
=
self
.
client
.
get
(
url
,
{
'aname'
:
'ProblemGradeDistribution'
})
self
.
assertEqual
(
response
.
status_code
,
501
)
@override_settings
(
ANALYTICS_SERVER_URL
=
""
)
@override_settings
(
ANALYTICS_API_KEY
=
""
)
@patch.object
(
instructor
.
views
.
api
.
requests
,
'get'
)
def
test_analytics_proxy_empty_url_and_api_key
(
self
,
act
):
"""
Test legacy analytics when empty server url & API key.
"""
act
.
return_value
=
self
.
FakeProxyResponse
()
url
=
reverse
(
'proxy_legacy_analytics'
,
kwargs
=
{
'course_id'
:
self
.
course
.
id
.
to_deprecated_string
()})
response
=
self
.
client
.
get
(
url
,
{
'aname'
:
'ProblemGradeDistribution'
})
self
.
assertEqual
(
response
.
status_code
,
501
)
@patch.object
(
instructor
.
views
.
api
.
requests
,
'get'
)
def
test_analytics_proxy
(
self
,
act
):
...
...
lms/djangoapps/instructor/views/api.py
View file @
1cdf8497
...
...
@@ -25,6 +25,7 @@ from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbid
from
django.utils.html
import
strip_tags
import
string
# pylint: disable=W0402
import
random
import
urllib
from
util.json_request
import
JsonResponse
from
instructor.views.instructor_task_helpers
import
extract_email_features
,
extract_task_features
...
...
@@ -1696,7 +1697,7 @@ def send_email(request, course_id):
course_id
,
request
.
user
,
send_to
,
subject
,
message
,
subject
,
message
,
template_name
=
template_name
,
from_addr
=
from_addr
)
...
...
@@ -1791,13 +1792,15 @@ def proxy_legacy_analytics(request, course_id):
analytics_name
=
request
.
GET
.
get
(
'aname'
)
# abort if misconfigured
if
not
(
hasattr
(
settings
,
'ANALYTICS_SERVER_URL'
)
and
hasattr
(
settings
,
'ANALYTICS_API_KEY'
)):
if
not
(
hasattr
(
settings
,
'ANALYTICS_SERVER_URL'
)
and
hasattr
(
settings
,
'ANALYTICS_API_KEY'
)
and
settings
.
ANALYTICS_SERVER_URL
and
settings
.
ANALYTICS_API_KEY
):
return
HttpResponse
(
"Analytics service not configured."
,
status
=
501
)
url
=
"{}get?aname={}&course_id={}&apikey={}"
.
format
(
settings
.
ANALYTICS_SERVER_URL
,
analytics_name
,
course_id
.
to_deprecated_string
(
),
urllib
.
quote
(
unicode
(
course_id
)
),
settings
.
ANALYTICS_API_KEY
,
)
...
...
lms/djangoapps/instructor/views/legacy.py
View file @
1cdf8497
...
...
@@ -11,6 +11,7 @@ import logging
import
os
import
re
import
requests
import
urllib
from
collections
import
defaultdict
,
OrderedDict
from
markupsafe
import
escape
...
...
@@ -910,7 +911,7 @@ def instructor_dashboard(request, course_id):
"""
url
=
settings
.
ANALYTICS_SERVER_URL
+
\
u"get?aname={}&course_id={}&apikey={}"
.
format
(
analytics_name
,
course_key
.
to_deprecated_string
(
),
settings
.
ANALYTICS_API_KEY
analytics_name
,
urllib
.
quote
(
unicode
(
course_key
)
),
settings
.
ANALYTICS_API_KEY
)
try
:
res
=
requests
.
get
(
url
)
...
...
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