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
dad73637
Unverified
Commit
dad73637
authored
Nov 14, 2017
by
Brian Mesick
Committed by
GitHub
Nov 14, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #16495 from edx/bmedx/django111_startup_fixes
Changes necessary for Django 1.11 tests to start
parents
d9970ef9
d3bbb86f
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
161 additions
and
162 deletions
+161
-162
cms/djangoapps/xblock_config/apps.py
+2
-1
cms/startup.py
+3
-0
cms/urls.py
+2
-1
common/djangoapps/third_party_auth/admin.py
+2
-1
lms/djangoapps/certificates/management/commands/create_fake_cert.py
+23
-18
lms/djangoapps/certificates/management/commands/regenerate_user.py
+23
-34
lms/djangoapps/certificates/management/commands/resubmit_error_certificates.py
+5
-6
lms/djangoapps/certificates/management/commands/ungenerated_certs.py
+32
-35
lms/djangoapps/certificates/tests/test_cert_management.py
+26
-29
lms/djangoapps/certificates/tests/test_create_fake_cert.py
+7
-6
lms/djangoapps/commerce/api/v0/tests/test_views.py
+2
-2
lms/djangoapps/commerce/api/v1/tests/test_views.py
+3
-3
lms/djangoapps/courseware/models.py
+3
-8
lms/djangoapps/courseware/tests/test_i18n.py
+5
-3
lms/djangoapps/courseware/tests/test_views.py
+2
-2
lms/djangoapps/learner_dashboard/tests/test_programs.py
+3
-3
lms/djangoapps/lms_xblock/apps.py
+2
-1
lms/startup.py
+3
-1
lms/urls.py
+4
-2
openedx/core/djangoapps/coursegraph/tasks.py
+2
-1
openedx/core/djangoapps/xmodule_django/models.py
+4
-3
openedx/features/learner_profile/urls.py
+2
-1
requirements/edx/base.txt
+1
-1
No files found.
cms/djangoapps/xblock_config/apps.py
View file @
dad73637
...
...
@@ -7,7 +7,6 @@ from django.apps import AppConfig
import
cms.lib.xblock.runtime
import
xmodule.x_module
from
openedx.core.lib.xblock_utils
import
xblock_local_resource_url
class
XBlockConfig
(
AppConfig
):
...
...
@@ -18,6 +17,8 @@ class XBlockConfig(AppConfig):
verbose_name
=
u'XBlock Configuration'
def
ready
(
self
):
from
openedx.core.lib.xblock_utils
import
xblock_local_resource_url
# In order to allow descriptors to use a handler url, we need to
# monkey-patch the x_module library.
# TODO: Remove this code when Runtimes are no longer created by modulestores
...
...
cms/startup.py
View file @
dad73637
...
...
@@ -19,6 +19,9 @@ def run():
NOTE: DO **NOT** add additional code to this method or this file! The Platform Team
is moving all startup code to more standard locations using Django best practices.
"""
# TODO: Remove Django 1.11 upgrade shim
# SHIM: We should be able to get rid of this monkey patch post-upgrade
if
django
.
VERSION
[
0
]
==
1
and
django
.
VERSION
[
1
]
<
10
:
django_db_models_options
.
patch
()
django
.
setup
()
cms/urls.py
View file @
dad73637
...
...
@@ -5,7 +5,6 @@ from django.contrib.admin import autodiscover as django_autodiscover
from
django.utils.translation
import
ugettext_lazy
as
_
import
contentstore.views
import
django_cas.views
import
openedx.core.djangoapps.common_views.xblock
import
openedx.core.djangoapps.debug.views
import
openedx.core.djangoapps.external_auth.views
...
...
@@ -180,6 +179,8 @@ if settings.FEATURES.get('ENABLE_SERVICE_STATUS'):
urlpatterns
.
append
(
url
(
r'^status/'
,
include
(
'openedx.core.djangoapps.service_status.urls'
)))
if
settings
.
FEATURES
.
get
(
'AUTH_USE_CAS'
):
import
django_cas.views
urlpatterns
+=
[
url
(
r'^cas-auth/login/$'
,
openedx
.
core
.
djangoapps
.
external_auth
.
views
.
cas_login
,
name
=
"cas-login"
),
url
(
r'^cas-auth/logout/$'
,
django_cas
.
views
.
logout
,
{
'next_page'
:
'/'
},
name
=
"cas-logout"
),
...
...
common/djangoapps/third_party_auth/admin.py
View file @
dad73637
...
...
@@ -116,9 +116,10 @@ class SAMLProviderDataAdmin(admin.ModelAdmin):
def
get_readonly_fields
(
self
,
request
,
obj
=
None
):
if
obj
:
# editing an existing object
return
self
.
model
.
_meta
.
get_all_field_names
()
# pylint: disable=protected-access
return
[
field
.
name
for
field
in
self
.
model
.
_meta
.
get_fields
()]
# pylint: disable=protected-access
return
self
.
readonly_fields
admin
.
site
.
register
(
SAMLProviderData
,
SAMLProviderDataAdmin
)
...
...
lms/djangoapps/certificates/management/commands/create_fake_cert.py
View file @
dad73637
...
...
@@ -10,11 +10,11 @@ Example usage:
"""
import
logging
from
optparse
import
make_option
from
django.contrib.auth.models
import
User
from
django.core.management.base
import
BaseCommand
,
CommandError
from
django.core.management.base
import
BaseCommand
from
opaque_keys.edx.keys
import
CourseKey
from
six
import
text_type
from
certificates.models
import
CertificateStatuses
,
GeneratedCertificate
...
...
@@ -24,32 +24,40 @@ LOGGER = logging.getLogger(__name__)
class
Command
(
BaseCommand
):
"""Create a fake certificate for a user in a course. """
USAGE
=
u'Usage: create_fake_cert <USERNAME> <COURSE_KEY> --mode <MODE> --status <STATUS> --grade <GRADE>'
def
add_arguments
(
self
,
parser
):
parser
.
add_argument
(
'username'
,
metavar
=
'USERNAME'
,
help
=
'Username of the user to create the fake cert for'
)
parser
.
add_argument
(
'course_key'
,
metavar
=
'COURSE_KEY'
,
help
=
'Course key of the course to grant the cert for'
)
option_list
=
BaseCommand
.
option_list
+
(
make_option
(
parser
.
add_argument
(
'-m'
,
'--mode'
,
metavar
=
'CERT_MODE'
,
dest
=
'cert_mode'
,
default
=
'honor'
,
help
=
'The course mode of the certificate (e.g. "honor", "verified", or "professional")'
)
,
)
make_option
(
parser
.
add_argument
(
'-s'
,
'--status'
,
metavar
=
'CERT_STATUS'
,
dest
=
'status'
,
default
=
CertificateStatuses
.
downloadable
,
help
=
'The status of the certificate'
)
,
)
make_option
(
parser
.
add_argument
(
'-g'
,
'--grade'
,
metavar
=
'CERT_GRADE'
,
dest
=
'grade'
,
default
=
''
,
help
=
'The grade for the course, as a decimal (e.g. "0.89" for 89
%
)'
),
help
=
'The grade for the course, as a decimal (e.g. "0.89" for 89 percent)'
)
def
handle
(
self
,
*
args
,
**
options
):
...
...
@@ -68,11 +76,8 @@ class Command(BaseCommand):
CommandError
"""
if
len
(
args
)
<
2
:
raise
CommandError
(
self
.
USAGE
)
user
=
User
.
objects
.
get
(
username
=
args
[
0
])
course_key
=
CourseKey
.
from_string
(
args
[
1
])
user
=
User
.
objects
.
get
(
username
=
options
[
'username'
])
course_key
=
CourseKey
.
from_string
(
options
[
'course_key'
])
cert_mode
=
options
.
get
(
'cert_mode'
,
'honor'
)
status
=
options
.
get
(
'status'
,
CertificateStatuses
.
downloadable
)
grade
=
options
.
get
(
'grade'
,
''
)
...
...
@@ -97,7 +102,7 @@ class Command(BaseCommand):
u"Created certificate for user
%
s in course
%
s "
u"with mode
%
s, status
%
s, "
u"and grade
%
s"
,
user
.
id
,
unicod
e
(
course_key
),
user
.
id
,
text_typ
e
(
course_key
),
cert_mode
,
status
,
grade
)
...
...
@@ -106,6 +111,6 @@ class Command(BaseCommand):
u"Updated certificate for user
%
s in course
%
s "
u"with mode
%
s, status
%
s, "
u"and grade
%
s"
,
user
.
id
,
unicod
e
(
course_key
),
user
.
id
,
text_typ
e
(
course_key
),
cert_mode
,
status
,
grade
)
lms/djangoapps/certificates/management/commands/regenerate_user.py
View file @
dad73637
"""Django management command to force certificate regeneration for one user"""
import
copy
import
logging
from
optparse
import
make_option
from
django.contrib.auth.models
import
User
from
django.core.management.base
import
BaseCommand
,
CommandError
from
django.core.management.base
import
BaseCommand
from
opaque_keys.edx.keys
import
CourseKey
from
six
import
text_type
from
badges.events.course_complete
import
get_completion_badge
from
badges.utils
import
badges_enabled
...
...
@@ -24,39 +23,36 @@ class Command(BaseCommand):
help
=
"""Put a request on the queue to recreate the certificate for a particular user in a particular course."""
option_list
=
BaseCommand
.
option_list
+
(
make_option
(
'-n'
,
'--noop'
,
def
add_arguments
(
self
,
parser
):
parser
.
add_argument
(
'-n'
,
'--noop'
,
action
=
'store_true'
,
dest
=
'noop'
,
default
=
False
,
help
=
"Don't grade or add certificate requests to the queue"
),
make_option
(
'--insecure'
,
help
=
"Don't grade or add certificate requests to the queue"
)
parser
.
add_argument
(
'--insecure'
,
action
=
'store_true'
,
dest
=
'insecure'
,
default
=
False
,
help
=
"Don't use https for the callback url to the LMS, useful in http test environments"
),
make_option
(
'-c'
,
'--course'
,
help
=
"Don't use https for the callback url to the LMS, useful in http test environments"
)
parser
.
add_argument
(
'-c'
,
'--course'
,
metavar
=
'COURSE_ID'
,
dest
=
'course'
,
default
=
Fals
e
,
help
=
'The course id (e.g., mit/6-002x/circuits-and-electronics) for which the student named in
'
'<username> should be graded'
),
make_option
(
'-u'
,
'--user'
,
required
=
Tru
e
,
help
=
'The course id (e.g., mit/6-002x/circuits-and-electronics) for which the student
'
'named in <username> should be graded'
)
parser
.
add_argument
(
'-u'
,
'--user'
,
metavar
=
'USERNAME'
,
dest
=
'username'
,
default
=
Fals
e
,
help
=
'The username or email address for whom grading and certification should be requested'
),
make_option
(
'-G'
,
'--grade'
,
required
=
Tru
e
,
help
=
'The username or email address for whom grading and certification should be requested'
)
parser
.
add_argument
(
'-G'
,
'--grade'
,
metavar
=
'GRADE'
,
dest
=
'grade_value'
,
default
=
None
,
help
=
'The grade string, such as "Distinction", which should be passed to the certificate agent'
),
make_option
(
'-T'
,
'--template'
,
help
=
'The grade string, such as "Distinction", which is passed to the certificate agent'
)
parser
.
add_argument
(
'-T'
,
'--template'
,
metavar
=
'TEMPLATE'
,
dest
=
'template_file'
,
default
=
None
,
help
=
'The template file used to render this certificate, like "QMSE01-distinction.pdf"'
),
)
help
=
'The template file used to render this certificate, like "QMSE01-distinction.pdf"'
)
def
handle
(
self
,
*
args
,
**
options
):
...
...
@@ -69,21 +65,14 @@ class Command(BaseCommand):
u"Starting to create tasks to regenerate certificates "
u"with arguments
%
s and options
%
s"
),
unicod
e
(
args
),
unicod
e
(
cleaned_options
)
text_typ
e
(
args
),
text_typ
e
(
cleaned_options
)
)
if
options
[
'course'
]:
# try to parse out the course from the serialized form
course_id
=
CourseKey
.
from_string
(
options
[
'course'
])
else
:
raise
CommandError
(
"You must specify a course"
)
user
=
options
[
'username'
]
if
not
(
course_id
and
user
):
raise
CommandError
(
'both course id and student username are required'
)
student
=
None
if
'@'
in
user
:
student
=
User
.
objects
.
get
(
email
=
user
,
courseenrollment__course_id
=
course_id
)
else
:
...
...
@@ -124,7 +113,7 @@ class Command(BaseCommand):
u"The new certificate status is '
%
s'."
),
student
.
id
,
unicod
e
(
course_id
),
text_typ
e
(
course_id
),
ret
)
...
...
@@ -136,7 +125,7 @@ class Command(BaseCommand):
u"because the noop flag is set."
),
student
.
id
,
unicod
e
(
course_id
)
text_typ
e
(
course_id
)
)
LOGGER
.
info
(
...
...
@@ -145,5 +134,5 @@ class Command(BaseCommand):
u"user
%
s and course '
%
s'."
),
student
.
id
,
unicod
e
(
course_id
)
text_typ
e
(
course_id
)
)
lms/djangoapps/certificates/management/commands/resubmit_error_certificates.py
View file @
dad73637
...
...
@@ -17,11 +17,11 @@ Example usage:
"""
import
logging
from
optparse
import
make_option
from
django.core.management.base
import
BaseCommand
,
CommandError
from
opaque_keys
import
InvalidKeyError
from
opaque_keys.edx.keys
import
CourseKey
from
six
import
text_type
from
certificates
import
api
as
certs_api
from
certificates.models
import
CertificateStatuses
,
GeneratedCertificate
...
...
@@ -33,15 +33,14 @@ LOGGER = logging.getLogger(__name__)
class
Command
(
BaseCommand
):
"""Resubmit certificates with error status. """
option_list
=
BaseCommand
.
option_list
+
(
make_option
(
def
add_arguments
(
self
,
parser
):
parser
.
add_argument
(
'-c'
,
'--course'
,
metavar
=
'COURSE_KEY'
,
dest
=
'course_key_list'
,
action
=
'append'
,
default
=
[],
help
=
'Only re-submit certificates for these courses.'
),
)
def
handle
(
self
,
*
args
,
**
options
):
...
...
@@ -58,7 +57,7 @@ class Command(BaseCommand):
"""
only_course_keys
=
[]
for
course_key_str
in
options
.
get
(
'course_key_list'
,
[])
:
for
course_key_str
in
options
[
'course_key_list'
]
:
try
:
only_course_keys
.
append
(
CourseKey
.
from_string
(
course_key_str
))
except
InvalidKeyError
:
...
...
@@ -73,7 +72,7 @@ class Command(BaseCommand):
(
u'Starting to re-submit certificates with status "error" '
u'in these courses:
%
s'
),
", "
.
join
([
unicod
e
(
key
)
for
key
in
only_course_keys
])
),
", "
.
join
([
text_typ
e
(
key
)
for
key
in
only_course_keys
])
)
else
:
LOGGER
.
info
(
u'Starting to re-submit certificates with status "error".'
)
...
...
lms/djangoapps/certificates/management/commands/ungenerated_certs.py
View file @
dad73637
...
...
@@ -2,14 +2,15 @@
Management command to find all students that need certificates for
courses that have finished, and put their cert requests on the queue.
"""
from
__future__
import
print_function
import
datetime
import
logging
from
optparse
import
make_option
from
django.contrib.auth.models
import
User
from
django.core.management.base
import
BaseCommand
,
CommandError
from
django.core.management.base
import
BaseCommand
from
opaque_keys.edx.keys
import
CourseKey
from
pytz
import
UTC
from
six
import
text_type
from
certificates.api
import
generate_user_certificates
from
certificates.models
import
CertificateStatuses
,
certificate_status_for_student
...
...
@@ -34,42 +35,43 @@ class Command(BaseCommand):
queue to be generated.
"""
option_list
=
BaseCommand
.
option_list
+
(
make_option
(
'-n'
,
'--noop'
,
def
add_arguments
(
self
,
parser
):
parser
.
add_argument
(
'-n'
,
'--noop'
,
action
=
'store_true'
,
dest
=
'noop'
,
default
=
False
,
help
=
"Don't add certificate requests to the queue"
),
make_option
(
'--insecure'
,
help
=
"Don't add certificate requests to the queue"
)
parser
.
add_argument
(
'--insecure'
,
action
=
'store_true'
,
dest
=
'insecure'
,
default
=
False
,
help
=
"Don't use https for the callback url to the LMS, useful in http test environments"
),
make_option
(
'-c'
,
'--course'
,
help
=
"Don't use https for the callback url to the LMS, useful in http test environments"
)
parser
.
add_argument
(
'-c'
,
'--course'
,
metavar
=
'COURSE_ID'
,
dest
=
'course'
,
default
=
False
,
help
=
'Grade and generate certificates '
'for a specific course'
),
make_option
(
'-f'
,
'--force-gen'
,
required
=
True
,
help
=
'Grade and generate certificates for a specific course'
)
parser
.
add_argument
(
'-f'
,
'--force-gen'
,
metavar
=
'STATUS'
,
dest
=
'force'
,
default
=
False
,
help
=
'Will generate new certificates for only those users '
'whose entry in the certificate table matches STATUS. '
'STATUS can be generating, unavailable, deleted, error '
'or notpassing.'
),
help
=
'Will generate new certificates for only those users whose entry in the certificate table matches '
'STATUS. STATUS can be generating, unavailable, deleted, error or notpassing.'
)
def
handle
(
self
,
*
args
,
**
options
):
LOGGER
.
info
(
(
u"Starting to create tasks for ungenerated certificates "
u"with arguments
%
s and options
%
s"
),
unicod
e
(
args
),
unicod
e
(
options
)
text_typ
e
(
args
),
text_typ
e
(
options
)
)
# Will only generate a certificate if the current
...
...
@@ -82,14 +84,10 @@ class Command(BaseCommand):
valid_statuses
=
[
CertificateStatuses
.
unavailable
]
# Print update after this many students
status_interval
=
500
STATUS_INTERVAL
=
500
if
options
[
'course'
]:
course
=
CourseKey
.
from_string
(
options
[
'course'
])
ended_courses
=
[
course
]
else
:
raise
CommandError
(
"You must specify a course"
)
for
course_key
in
ended_courses
:
# prefetch all chapters/sequentials by saying depth=2
...
...
@@ -105,16 +103,15 @@ class Command(BaseCommand):
for
student
in
enrolled_students
:
count
+=
1
if
count
%
STATUS_INTERVAL
==
0
:
if
count
%
status_interval
==
0
:
# Print a status update with an approximation of
# how much time is left based on how long the last
# interval took
diff
=
datetime
.
datetime
.
now
(
UTC
)
-
start
timeleft
=
diff
*
(
total
-
count
)
/
STATUS_INTERVAL
timeleft
=
diff
*
(
total
-
count
)
/
status_interval
hours
,
remainder
=
divmod
(
timeleft
.
seconds
,
3600
)
minutes
,
_seconds
=
divmod
(
remainder
,
60
)
print
"{0}/{1} completed ~{2:02}:{3:02}m remaining"
.
format
(
count
,
total
,
hours
,
minutes
)
print
(
"{0}/{1} completed ~{2:02}:{3:02}m remaining"
.
format
(
count
,
total
,
hours
,
minutes
))
start
=
datetime
.
datetime
.
now
(
UTC
)
cert_status
=
certificate_status_for_student
(
student
,
course_key
)[
'status'
]
...
...
@@ -125,7 +122,7 @@ class Command(BaseCommand):
),
student
.
id
,
cert_status
,
unicod
e
(
course_key
)
text_typ
e
(
course_key
)
)
if
cert_status
in
valid_statuses
:
...
...
@@ -147,7 +144,7 @@ class Command(BaseCommand):
u"The new certificate status is '
%
s'."
),
student
.
id
,
unicod
e
(
course_key
),
text_typ
e
(
course_key
),
ret
)
...
...
@@ -159,7 +156,7 @@ class Command(BaseCommand):
u"because the noop flag is set."
),
student
.
id
,
unicod
e
(
course_key
)
text_typ
e
(
course_key
)
)
else
:
...
...
@@ -170,7 +167,7 @@ class Command(BaseCommand):
),
student
.
id
,
cert_status
,
unicod
e
(
valid_statuses
)
text_typ
e
(
valid_statuses
)
)
LOGGER
.
info
(
...
...
@@ -178,5 +175,5 @@ class Command(BaseCommand):
u"Completed ungenerated certificates command "
u"for course '
%
s'"
),
unicod
e
(
course_key
)
text_typ
e
(
course_key
)
)
lms/djangoapps/certificates/tests/test_cert_management.py
View file @
dad73637
"""Tests for the resubmit_error_certificates management command. """
import
ddt
from
django.core.management
import
call_command
from
django.core.management.base
import
CommandError
from
django.test.utils
import
override_settings
from
mock
import
patch
from
nose.plugins.attrib
import
attr
from
opaque_keys.edx.locator
import
CourseLocator
from
six
import
text_type
from
badges.events.course_complete
import
get_completion_badge
from
badges.models
import
BadgeAssertion
from
badges.tests.factories
import
BadgeAssertionFactory
,
CourseCompleteImageConfigurationFactory
from
certificates.management.commands
import
regenerate_user
,
resubmit_error_certificates
,
ungenerated_certs
from
certificates.models
import
CertificateStatuses
,
GeneratedCertificate
from
course_modes.models
import
CourseMode
from
lms.djangoapps.grades.tests.utils
import
mock_passing_grade
...
...
@@ -23,7 +24,7 @@ class CertificateManagementTest(ModuleStoreTestCase):
Base test class for Certificate Management command tests.
"""
# Override with the command module you wish to test.
command
=
resubmit_error_certificates
command
=
'resubmit_error_certificates'
def
setUp
(
self
):
super
(
CertificateManagementTest
,
self
)
.
setUp
()
...
...
@@ -53,11 +54,6 @@ class CertificateManagementTest(ModuleStoreTestCase):
status
=
status
)
def
_run_command
(
self
,
*
args
,
**
kwargs
):
"""Run the management command to generate a fake cert. """
command
=
self
.
command
.
Command
()
return
command
.
handle
(
*
args
,
**
kwargs
)
def
_assert_cert_status
(
self
,
course_key
,
user
,
expected_status
):
"""Check the status of a certificate. """
cert
=
GeneratedCertificate
.
eligible_certificates
.
get
(
user
=
user
,
course_id
=
course_key
)
...
...
@@ -77,7 +73,7 @@ class ResubmitErrorCertificatesTest(CertificateManagementTest):
# Re-submit all certificates with status 'error'
with
check_mongo_calls
(
1
):
self
.
_run_command
(
)
call_command
(
self
.
command
)
# Expect that the certificate was re-submitted
self
.
_assert_cert_status
(
self
.
courses
[
0
]
.
id
,
self
.
user
,
CertificateStatuses
.
notpassing
)
...
...
@@ -89,9 +85,9 @@ class ResubmitErrorCertificatesTest(CertificateManagementTest):
self
.
_create_cert
(
self
.
courses
[
idx
]
.
id
,
self
.
user
,
CertificateStatuses
.
error
)
# Re-submit certificates for two of the courses
self
.
_run_command
(
course_key_list
=
[
unicod
e
(
self
.
courses
[
0
]
.
id
),
unicod
e
(
self
.
courses
[
1
]
.
id
)
call_command
(
self
.
command
,
course_key_list
=
[
text_typ
e
(
self
.
courses
[
0
]
.
id
),
text_typ
e
(
self
.
courses
[
1
]
.
id
)
])
# Expect that the first two courses have been re-submitted,
...
...
@@ -115,7 +111,7 @@ class ResubmitErrorCertificatesTest(CertificateManagementTest):
self
.
_create_cert
(
self
.
courses
[
1
]
.
id
,
self
.
user
,
other_status
)
# Re-submit certificates for all courses
self
.
_run_command
(
)
call_command
(
self
.
command
)
# Only the certificate with status "error" should have been re-submitted
self
.
_assert_cert_status
(
self
.
courses
[
0
]
.
id
,
self
.
user
,
CertificateStatuses
.
notpassing
)
...
...
@@ -123,7 +119,7 @@ class ResubmitErrorCertificatesTest(CertificateManagementTest):
def
test_resubmit_error_certificate_none_found
(
self
):
self
.
_create_cert
(
self
.
courses
[
0
]
.
id
,
self
.
user
,
CertificateStatuses
.
downloadable
)
self
.
_run_command
(
)
call_command
(
self
.
command
)
self
.
_assert_cert_status
(
self
.
courses
[
0
]
.
id
,
self
.
user
,
CertificateStatuses
.
downloadable
)
def
test_course_caching
(
self
):
...
...
@@ -135,17 +131,17 @@ class ResubmitErrorCertificatesTest(CertificateManagementTest):
# Verify that we make only one Mongo query
# because the course is cached.
with
check_mongo_calls
(
1
):
self
.
_run_command
(
)
call_command
(
self
.
command
)
def
test_invalid_course_key
(
self
):
invalid_key
=
u"invalid/"
with
self
.
assertRaisesRegexp
(
CommandError
,
invalid_key
):
self
.
_run_command
(
course_key_list
=
[
invalid_key
])
call_command
(
self
.
command
,
course_key_list
=
[
invalid_key
])
def
test_course_does_not_exist
(
self
):
phantom_course
=
CourseLocator
(
org
=
'phantom'
,
course
=
'phantom'
,
run
=
'phantom'
)
self
.
_create_cert
(
phantom_course
,
self
.
user
,
'error'
)
self
.
_run_command
(
)
call_command
(
self
.
command
)
# Expect that the certificate was NOT resubmitted
# since the course doesn't actually exist.
...
...
@@ -158,7 +154,7 @@ class RegenerateCertificatesTest(CertificateManagementTest):
"""
Tests for regenerating certificates.
"""
command
=
regenerate_user
command
=
'regenerate_user'
def
setUp
(
self
):
"""
...
...
@@ -185,10 +181,10 @@ class RegenerateCertificatesTest(CertificateManagementTest):
self
.
assertTrue
(
BadgeAssertion
.
objects
.
filter
(
user
=
self
.
user
,
badge_class
=
badge_class
))
self
.
course
.
issue_badges
=
issue_badges
self
.
store
.
update_item
(
self
.
course
,
None
)
self
.
_run_command
(
username
=
self
.
user
.
email
,
course
=
unicode
(
key
),
noop
=
False
,
insecure
=
False
,
template_file
=
None
,
grade_value
=
None
)
args
=
'-u {} -c {}'
.
format
(
self
.
user
.
email
,
text_type
(
key
))
call_command
(
self
.
command
,
*
args
.
split
(
' '
))
xqueue
.
return_value
.
regen_cert
.
assert_called_with
(
self
.
user
,
key
,
...
...
@@ -211,10 +207,10 @@ class RegenerateCertificatesTest(CertificateManagementTest):
"""
key
=
self
.
course
.
location
.
course_key
self
.
_create_cert
(
key
,
self
.
user
,
CertificateStatuses
.
downloadable
)
self
.
_run_command
(
username
=
self
.
user
.
email
,
course
=
unicode
(
key
),
noop
=
False
,
insecure
=
True
,
template_file
=
None
,
grade_value
=
None
)
args
=
'-u {} -c {} --insecure'
.
format
(
self
.
user
.
email
,
text_type
(
key
))
call_command
(
self
.
command
,
*
args
.
split
(
' '
))
certificate
=
GeneratedCertificate
.
eligible_certificates
.
get
(
user
=
self
.
user
,
course_id
=
key
...
...
@@ -228,7 +224,7 @@ class UngenerateCertificatesTest(CertificateManagementTest):
"""
Tests for generating certificates.
"""
command
=
ungenerated_certs
command
=
'ungenerated_certs'
def
setUp
(
self
):
"""
...
...
@@ -248,10 +244,11 @@ class UngenerateCertificatesTest(CertificateManagementTest):
mock_send_to_queue
.
return_value
=
(
0
,
"Successfully queued"
)
key
=
self
.
course
.
location
.
course_key
self
.
_create_cert
(
key
,
self
.
user
,
CertificateStatuses
.
unavailable
)
with
mock_passing_grade
():
self
.
_run_command
(
course
=
unicode
(
key
),
noop
=
False
,
insecure
=
True
,
force
=
False
)
args
=
'-c {} --insecure'
.
format
(
text_type
(
key
))
call_command
(
self
.
command
,
*
args
.
split
(
' '
))
self
.
assertTrue
(
mock_send_to_queue
.
called
)
certificate
=
GeneratedCertificate
.
eligible_certificates
.
get
(
user
=
self
.
user
,
...
...
lms/djangoapps/certificates/tests/test_create_fake_cert.py
View file @
dad73637
"""Tests for the create_fake_certs management command. """
from
django.core.management
import
call_command
from
django.core.management.base
import
CommandError
from
django.test
import
TestCase
from
nose.plugins.attrib
import
attr
from
opaque_keys.edx.locator
import
CourseLocator
from
six
import
text_type
from
certificates.management.commands
import
create_fake_cert
from
certificates.models
import
GeneratedCertificate
from
student.tests.factories
import
UserFactory
...
...
@@ -24,7 +26,7 @@ class CreateFakeCertTest(TestCase):
# No existing cert, so create it
self
.
_run_command
(
self
.
USERNAME
,
unicod
e
(
self
.
COURSE_KEY
),
text_typ
e
(
self
.
COURSE_KEY
),
cert_mode
=
'verified'
,
grade
=
'0.89'
)
...
...
@@ -38,17 +40,16 @@ class CreateFakeCertTest(TestCase):
# Cert already exists; modify it
self
.
_run_command
(
self
.
USERNAME
,
unicod
e
(
self
.
COURSE_KEY
),
text_typ
e
(
self
.
COURSE_KEY
),
cert_mode
=
'honor'
)
cert
=
GeneratedCertificate
.
eligible_certificates
.
get
(
user
=
self
.
user
,
course_id
=
self
.
COURSE_KEY
)
self
.
assertEqual
(
cert
.
mode
,
'honor'
)
def
test_too_few_args
(
self
):
with
self
.
assertRaisesRegexp
(
CommandError
,
'
Usage
'
):
with
self
.
assertRaisesRegexp
(
CommandError
,
'
Error: too few arguments
'
):
self
.
_run_command
(
self
.
USERNAME
)
def
_run_command
(
self
,
*
args
,
**
kwargs
):
"""Run the management command to generate a fake cert. """
command
=
create_fake_cert
.
Command
()
return
command
.
handle
(
*
args
,
**
kwargs
)
return
call_command
(
'create_fake_cert'
,
*
args
,
**
kwargs
)
lms/djangoapps/commerce/api/v0/tests/test_views.py
View file @
dad73637
...
...
@@ -8,7 +8,7 @@ import ddt
import
mock
import
pytz
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
,
reverse_lazy
from
django.test
import
TestCase
from
django.test.utils
import
override_settings
from
edx_rest_api_client
import
exceptions
...
...
@@ -285,7 +285,7 @@ class BasketOrderViewTests(UserMixin, TestCase):
""" Tests for the basket order view. """
view_name
=
'commerce_api:v0:baskets:retrieve_order'
MOCK_ORDER
=
{
'number'
:
1
}
path
=
reverse
(
view_name
,
kwargs
=
{
'basket_id'
:
1
})
path
=
reverse
_lazy
(
view_name
,
kwargs
=
{
'basket_id'
:
1
})
def
setUp
(
self
):
super
(
BasketOrderViewTests
,
self
)
.
setUp
()
...
...
lms/djangoapps/commerce/api/v1/tests/test_views.py
View file @
dad73637
...
...
@@ -7,7 +7,7 @@ import ddt
import
pytz
from
django.conf
import
settings
from
django.contrib.auth.models
import
Permission
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
,
reverse_lazy
from
django.test
import
TestCase
from
django.test.utils
import
override_settings
from
edx_rest_api_client
import
exceptions
...
...
@@ -83,7 +83,7 @@ class CourseApiViewTestMixin(object):
class
CourseListViewTests
(
CourseApiViewTestMixin
,
ModuleStoreTestCase
):
""" Tests for CourseListView. """
path
=
reverse
(
'commerce_api:v1:courses:list'
)
path
=
reverse
_lazy
(
'commerce_api:v1:courses:list'
)
def
test_authentication_required
(
self
):
""" Verify only authenticated users can access the view. """
...
...
@@ -400,7 +400,7 @@ class OrderViewTests(UserMixin, TestCase):
view_name
=
'commerce_api:v1:orders:detail'
ORDER_NUMBER
=
'EDX-100001'
MOCK_ORDER
=
{
'number'
:
ORDER_NUMBER
}
path
=
reverse
(
view_name
,
kwargs
=
{
'number'
:
ORDER_NUMBER
})
path
=
reverse
_lazy
(
view_name
,
kwargs
=
{
'number'
:
ORDER_NUMBER
})
def
setUp
(
self
):
super
(
OrderViewTests
,
self
)
.
setUp
()
...
...
lms/djangoapps/courseware/models.py
View file @
dad73637
...
...
@@ -257,14 +257,9 @@ class XBlockFieldBase(models.Model):
modified
=
models
.
DateTimeField
(
auto_now
=
True
,
db_index
=
True
)
def
__unicode__
(
self
):
return
u'{}<{!r}'
.
format
(
self
.
__class__
.
__name__
,
{
key
:
getattr
(
self
,
key
)
for
key
in
self
.
_meta
.
get_all_field_names
()
if
key
not
in
(
'created'
,
'modified'
)
}
)
# pylint: disable=protected-access
keys
=
[
field
.
name
for
field
in
self
.
_meta
.
get_fields
()
if
field
.
name
not
in
(
'created'
,
'modified'
)]
return
u'{}<{!r}'
.
format
(
self
.
__class__
.
__name__
,
{
key
:
getattr
(
self
,
key
)
for
key
in
keys
})
class
XModuleUserStateSummaryField
(
XBlockFieldBase
):
...
...
lms/djangoapps/courseware/tests/test_i18n.py
View file @
dad73637
...
...
@@ -7,7 +7,7 @@ import re
from
django.conf
import
settings
from
django.contrib.auth.models
import
User
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
,
reverse_lazy
from
django.test
import
TestCase
from
django.test.client
import
Client
from
django.utils
import
translation
...
...
@@ -23,9 +23,9 @@ class BaseI18nTestCase(TestCase):
Base utilities for i18n test classes to derive from
"""
preview_language_url
=
'/update_lang/'
url
=
reverse
(
'dashboard'
)
site_lang
=
settings
.
LANGUAGE_CODE
pwd
=
'test_password'
url
=
reverse_lazy
(
'dashboard'
)
def
setUp
(
self
):
super
(
BaseI18nTestCase
,
self
)
.
setUp
()
...
...
@@ -171,7 +171,9 @@ class I18nLangPrefTests(BaseI18nTestCase):
self
.
user_login
()
def
set_lang_preference
(
self
,
language
):
"""Sets the user's language preference, allowing the LangPref middleware to operate to set the preference cookie."""
"""
Sets the user's language preference, allowing the LangPref middleware to operate to set the preference cookie.
"""
response
=
self
.
client
.
patch
(
reverse
(
'preferences_api'
,
args
=
[
self
.
user
.
username
]),
json
.
dumps
({
LANGUAGE_KEY
:
language
}),
...
...
lms/djangoapps/courseware/tests/test_views.py
View file @
dad73637
...
...
@@ -13,7 +13,7 @@ from uuid import uuid4
import
ddt
from
django.conf
import
settings
from
django.contrib.auth.models
import
AnonymousUser
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
,
reverse_lazy
from
django.http
import
Http404
,
HttpResponseBadRequest
from
django.test
import
TestCase
from
django.test.client
import
Client
,
RequestFactory
...
...
@@ -983,7 +983,7 @@ class ViewsTestCase(ModuleStoreTestCase):
class
TestProgramMarketingView
(
SharedModuleStoreTestCase
):
"""Unit tests for the program marketing page."""
program_uuid
=
str
(
uuid4
())
url
=
reverse
(
'program_marketing_view'
,
kwargs
=
{
'program_uuid'
:
program_uuid
})
url
=
reverse
_lazy
(
'program_marketing_view'
,
kwargs
=
{
'program_uuid'
:
program_uuid
})
@classmethod
def
setUpClass
(
cls
):
...
...
lms/djangoapps/learner_dashboard/tests/test_programs.py
View file @
dad73637
...
...
@@ -10,7 +10,7 @@ from uuid import uuid4
import
mock
from
bs4
import
BeautifulSoup
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
,
reverse_lazy
from
django.test
import
override_settings
from
openedx.core.djangoapps.catalog.tests.factories
import
CourseFactory
,
CourseRunFactory
,
ProgramFactory
...
...
@@ -31,7 +31,7 @@ class TestProgramListing(ProgramsApiConfigMixin, SharedModuleStoreTestCase):
"""Unit tests for the program listing page."""
maxDiff
=
None
password
=
'test'
url
=
reverse
(
'program_listing_view'
)
url
=
reverse
_lazy
(
'program_listing_view'
)
@classmethod
def
setUpClass
(
cls
):
...
...
@@ -176,7 +176,7 @@ class TestProgramDetails(ProgramsApiConfigMixin, CatalogIntegrationMixin, Shared
"""Unit tests for the program details page."""
program_uuid
=
str
(
uuid4
())
password
=
'test'
url
=
reverse
(
'program_details_view'
,
kwargs
=
{
'program_uuid'
:
program_uuid
})
url
=
reverse
_lazy
(
'program_details_view'
,
kwargs
=
{
'program_uuid'
:
program_uuid
})
@classmethod
def
setUpClass
(
cls
):
...
...
lms/djangoapps/lms_xblock/apps.py
View file @
dad73637
...
...
@@ -6,7 +6,6 @@ from __future__ import absolute_import
from
django.apps
import
AppConfig
import
xmodule.x_module
from
.runtime
import
handler_url
,
local_resource_url
class
LMSXBlockConfig
(
AppConfig
):
...
...
@@ -17,6 +16,8 @@ class LMSXBlockConfig(AppConfig):
verbose_name
=
u'LMS XBlock'
def
ready
(
self
):
from
.runtime
import
handler_url
,
local_resource_url
# In order to allow modules to use a handler url, we need to
# monkey-patch the x_module library.
# TODO: Remove this code when Runtimes are no longer created by modulestores
...
...
lms/startup.py
View file @
dad73637
...
...
@@ -8,7 +8,6 @@ from django.conf import settings
from
openedx.core.djangoapps.monkey_patch
import
django_db_models_options
# Force settings to run so that the python path is modified
settings
.
INSTALLED_APPS
# pylint: disable=pointless-statement
...
...
@@ -19,6 +18,9 @@ def run():
NOTE: DO **NOT** add additional code to this method or this file! The Platform Team
is moving all startup code to more standard locations using Django best practices.
"""
# TODO: Remove Django 1.11 upgrade shim
# SHIM: We should be able to get rid of this monkey patch post-upgrade
if
django
.
VERSION
[
0
]
==
1
and
django
.
VERSION
[
1
]
<
10
:
django_db_models_options
.
patch
()
django
.
setup
()
lms/urls.py
View file @
dad73637
...
...
@@ -18,7 +18,6 @@ from courseware.views import views as courseware_views
from
courseware.views.index
import
CoursewareIndex
from
courseware.views.views
import
CourseTabView
,
EnrollStaffView
,
StaticCourseTabView
from
debug
import
views
as
debug_views
from
django_cas
import
views
as
django_cas_views
from
django_comment_common.models
import
ForumsConfig
from
django_openid_auth
import
views
as
django_openid_auth_views
from
lms.djangoapps.discussion
import
views
as
discussion_views
...
...
@@ -40,6 +39,7 @@ from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from
openedx.core.djangoapps.self_paced.models
import
SelfPacedConfiguration
from
openedx.core.djangoapps.site_configuration
import
helpers
as
configuration_helpers
from
openedx.core.djangoapps.verified_track_content
import
views
as
verified_track_content_views
from
openedx.core.djangoapps.common_views.xblock
import
xblock_resource
from
openedx.features.enterprise_support.api
import
enterprise_enabled
from
ratelimitbackend
import
admin
from
static_template_view
import
views
as
static_template_view_views
...
...
@@ -290,7 +290,7 @@ urlpatterns += [
# xblock Resource URL
url
(
r'xblock/resource/(?P<block_type>[^/]+)/(?P<uri>.*)$'
,
'openedx.core.djangoapps.common_views.xblock.xblock_resource'
,
xblock_resource
,
name
=
'xblock_resource_url'
,
),
...
...
@@ -825,6 +825,8 @@ if settings.FEATURES.get('AUTH_USE_SHIB'):
]
if
settings
.
FEATURES
.
get
(
'AUTH_USE_CAS'
):
from
django_cas
import
views
as
django_cas_views
urlpatterns
+=
[
url
(
r'^cas-auth/login/$'
,
external_auth_views
.
cas_login
,
name
=
'cas-login'
),
url
(
r'^cas-auth/logout/$'
,
django_cas_views
.
logout
,
{
'next_page'
:
'/'
},
name
=
'cas-logout'
),
...
...
openedx/core/djangoapps/coursegraph/tasks.py
View file @
dad73637
...
...
@@ -13,7 +13,6 @@ from opaque_keys.edx.keys import CourseKey
from
py2neo
import
Graph
,
Node
,
Relationship
,
authenticate
,
NodeSelector
from
py2neo.compat
import
integer
,
string
,
unicode
as
neo4j_unicode
from
request_cache.middleware
import
RequestCache
from
xmodule.modulestore.store_utilities
import
DETACHED_XBLOCK_TYPES
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -37,6 +36,8 @@ def serialize_item(item):
block_type: the name of the XBlock's type (i.e. 'course'
or 'problem')
"""
from
xmodule.modulestore.store_utilities
import
DETACHED_XBLOCK_TYPES
# convert all fields to a dict and filter out parent and children field
fields
=
dict
(
(
field
,
field_value
.
read_from
(
item
))
...
...
openedx/core/djangoapps/xmodule_django/models.py
View file @
dad73637
...
...
@@ -36,13 +36,14 @@ class NoneToEmptyQuerySet(models.query.QuerySet):
"""
def
_filter_or_exclude
(
self
,
*
args
,
**
kwargs
):
# pylint: disable=protected-access
for
name
in
self
.
model
.
_meta
.
get_all_field_name
s
():
field_object
,
_model
,
direct
,
_m2m
=
self
.
model
.
_meta
.
get_field_by_name
(
name
)
for
field_object
in
self
.
model
.
_meta
.
get_field
s
():
direct
=
not
field_object
.
auto_created
or
field_object
.
concrete
if
direct
and
hasattr
(
field_object
,
'Empty'
):
for
suffix
in
(
''
,
'_exact'
):
key
=
'{}{}'
.
format
(
name
,
suffix
)
key
=
'{}{}'
.
format
(
field_object
.
name
,
suffix
)
if
key
in
kwargs
and
kwargs
[
key
]
is
None
:
kwargs
[
key
]
=
field_object
.
Empty
return
super
(
NoneToEmptyQuerySet
,
self
)
.
_filter_or_exclude
(
*
args
,
**
kwargs
)
...
...
openedx/features/learner_profile/urls.py
View file @
dad73637
...
...
@@ -6,13 +6,14 @@ from django.conf import settings
from
django.conf.urls
import
url
from
views.learner_achievements
import
LearnerAchievementsFragmentView
from
openedx.features.learner_profile.views.learner_profile
import
learner_profile
urlpatterns
=
[
url
(
r'^{username_pattern}$'
.
format
(
username_pattern
=
settings
.
USERNAME_PATTERN
,
),
'openedx.features.learner_profile.views.learner_profile.learner_profile'
,
learner_profile
,
name
=
'learner_profile'
,
),
url
(
...
...
requirements/edx/base.txt
View file @
dad73637
...
...
@@ -11,7 +11,7 @@ bleach==1.4
html5lib==0.999
boto==2.39.0
celery==3.1.18
cryptography==1.
5.3
cryptography==1.
9
cssselect==0.9.1
dealer==2.0.4
defusedxml==0.4.1
...
...
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