Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2139 from edx-solutions/release-candidate
Browse files Browse the repository at this point in the history
[v1.62.0] Review sync up of master branch with release-candidate
  • Loading branch information
sohaibaslam authored Apr 8, 2021
2 parents 0696906 + 4ffa467 commit 087d669
Show file tree
Hide file tree
Showing 26 changed files with 239 additions and 142 deletions.
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/tests/test_libraries.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from contentstore.views.item import _duplicate_item
from contentstore.views.preview import _load_preview_module
from contentstore.views.tests.test_library import LIBRARY_REST_URL
from course_creators.views import add_user_with_status_granted
from cms.djangoapps.course_creators.views import add_user_with_status_granted
from student import auth
from student.auth import has_studio_read_access, has_studio_write_access
from student.roles import (
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/views/course.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
from contentstore.views.entrance_exam import create_entrance_exam, delete_entrance_exam, update_entrance_exam
from course_action_state.managers import CourseActionStateItemNotFoundError
from course_action_state.models import CourseRerunState, CourseRerunUIStateManager
from course_creators.views import add_user_with_status_unrequested, get_course_creator_status
from cms.djangoapps.course_creators.views import add_user_with_status_unrequested, get_course_creator_status
from course_modes.models import CourseMode
from edxmako.shortcuts import render_to_response
from edx_notifications.data import NotificationMessage
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/views/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

from contentstore.utils import add_instructor, reverse_library_url
from contentstore.views.item import create_xblock_info
from course_creators.views import get_course_creator_status
from cms.djangoapps.course_creators.views import get_course_creator_status
from edxmako.shortcuts import render_to_response
from student.auth import (
STUDIO_EDIT_ROLES,
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/views/tests/test_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from contentstore.utils import reverse_course_url, reverse_library_url
from contentstore.views.component import get_component_templates
from contentstore.views.library import get_library_creator_status
from course_creators.views import add_user_with_status_granted as grant_course_creator_status
from cms.djangoapps.course_creators.views import add_user_with_status_granted as grant_course_creator_status
from student.roles import LibraryUserRole
from xmodule.modulestore.tests.factories import LibraryFactory

Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/views/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locator import LibraryLocator

from course_creators.views import user_requested_access
from cms.djangoapps.course_creators.views import user_requested_access
from edxmako.shortcuts import render_to_response
from student import auth
from student.auth import STUDIO_EDIT_ROLES, STUDIO_VIEW_USERS, get_user_permissions
Expand Down
5 changes: 3 additions & 2 deletions cms/djangoapps/course_creators/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
from django.core.mail import send_mail
from django.dispatch import receiver

from course_creators.models import CourseCreator, send_admin_notification, send_user_notification, update_creator_state
from course_creators.views import update_course_creator_group
from cms.djangoapps.course_creators.models import (CourseCreator, send_admin_notification,
send_user_notification, update_creator_state)
from cms.djangoapps.course_creators.views import update_course_creator_group
from edxmako.shortcuts import render_to_string

log = logging.getLogger("studio.coursecreatoradmin")
Expand Down
3 changes: 3 additions & 0 deletions cms/djangoapps/course_creators/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class CourseCreator(models.Model):
note = models.CharField(max_length=512, blank=True, help_text=_("Optional notes about this user (for example, "
"why course creation access was denied)"))

class Meta:
app_label = 'course_creators'

def __str__(self):
return u"{0} | {1} [{2}]".format(self.user, self.state, self.state_changed)

Expand Down
10 changes: 6 additions & 4 deletions cms/djangoapps/course_creators/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
from django.test import TestCase
from six.moves import range

from course_creators.admin import CourseCreatorAdmin
from course_creators.models import CourseCreator
from cms.djangoapps.course_creators.admin import CourseCreatorAdmin
from cms.djangoapps.course_creators.models import CourseCreator
from student import auth
from student.roles import CourseCreatorRole

Expand Down Expand Up @@ -48,7 +48,8 @@ def setUp(self):
"STUDIO_REQUEST_EMAIL": self.studio_request_email
}

@mock.patch('course_creators.admin.render_to_string', mock.Mock(side_effect=mock_render_to_string, autospec=True))
@mock.patch('cms.djangoapps.course_creators.admin.render_to_string',
mock.Mock(side_effect=mock_render_to_string, autospec=True))
@mock.patch('django.contrib.auth.models.User.email_user')
def test_change_status(self, email_user):
"""
Expand Down Expand Up @@ -92,7 +93,8 @@ def change_state_and_verify_email(state, is_creator):

change_state_and_verify_email(CourseCreator.DENIED, False)

@mock.patch('course_creators.admin.render_to_string', mock.Mock(side_effect=mock_render_to_string, autospec=True))
@mock.patch('cms.djangoapps.course_creators.admin.render_to_string',
mock.Mock(side_effect=mock_render_to_string, autospec=True))
def test_mail_admin_on_pending(self):
"""
Tests that the admin account is notified when a user is in the 'pending' state.
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/course_creators/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from django.test import TestCase
from django.urls import reverse

from course_creators.views import (
from cms.djangoapps.course_creators.views import (
add_user_with_status_granted,
add_user_with_status_unrequested,
get_course_creator_status,
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/course_creators/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""


from course_creators.models import CourseCreator
from cms.djangoapps.course_creators.models import CourseCreator
from student import auth
from student.roles import CourseCreatorRole

Expand Down
2 changes: 1 addition & 1 deletion cms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1356,7 +1356,7 @@
'contentstore.apps.ContentstoreConfig',

'openedx.core.djangoapps.contentserver',
'course_creators',
'cms.djangoapps.course_creators',
'student.apps.StudentConfig', # misleading name due to sharing with lms
'openedx.core.djangoapps.course_groups', # not used in cms (yet), but tests run
'xblock_config.apps.XBlockConfig',
Expand Down
2 changes: 1 addition & 1 deletion common/lib/xmodule/xmodule/modulestore/xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ def load_item(usage_key, for_parent=None):
# id_generator is ignored, because each ImportSystem is already local to
# a course, and has it's own id_generator already in place
def add_node_as_child(self, block, node, id_generator):
child_block = self.process_xml(etree.tostring(node))
child_block = self.process_xml(etree.tostring(node, encoding='unicode'))
block.children.append(child_block.scope_ids.usage_id)


Expand Down
9 changes: 6 additions & 3 deletions lms/djangoapps/courseware/user_state_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,11 +395,11 @@ def get_history(self, username, block_key, scope=Scope.user_state):

yield XBlockUserState(username, block_key, state, history_entry.created, scope)

def iter_all_for_block(self, block_key, scope=Scope.user_state):
def iter_all_for_block(self, block_key, batch_no=None, batch_size=None, scope=Scope.user_state):
"""
Return an iterator over the data stored in the block (e.g. a problem block).
You get no ordering guarantees.If you're using this method, you should be running in an
Results are ordered by student id. If you're using this method, you should be running in an
async task.
Arguments:
Expand All @@ -413,7 +413,10 @@ def iter_all_for_block(self, block_key, scope=Scope.user_state):
if scope != Scope.user_state:
raise ValueError("Only Scope.user_state is supported")

results = StudentModule.objects.order_by('id').filter(module_state_key=block_key)
results = StudentModule.objects.filter(module_state_key=block_key).order_by('student')
if batch_no:
results = results[(batch_no - 1) * batch_size:batch_no * batch_size]

p = Paginator(results, settings.USER_STATE_BATCH_SIZE)

for page_number in p.page_range:
Expand Down
7 changes: 5 additions & 2 deletions lms/djangoapps/instructor_analytics/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ def extract_coupon(coupon, features):
return [extract_coupon(coupon, features) for coupon in coupons_list]


def list_problem_responses(course_key, problem_location, limit_responses=None):
def list_problem_responses(course_key, problem_location, limit_responses=None, batch_no=None, batch_size=None):
"""
Return responses to a given problem as a dict.
Expand Down Expand Up @@ -464,8 +464,11 @@ def list_problem_responses(course_key, problem_location, limit_responses=None):
module_state_key=problem_key
)
smdat = smdat.order_by('student')
if limit_responses is not None:

if limit_responses:
smdat = smdat[:limit_responses]
if batch_no:
smdat = smdat[(batch_no - 1) * batch_size:batch_no * batch_size]

return [
{'username': response.student.username, 'state': get_response_state(response)}
Expand Down
17 changes: 16 additions & 1 deletion lms/djangoapps/instructor_task/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def from_config(cls, config_name):
'bucket': config['BUCKET'],
'location': config['ROOT_PATH'],
'custom_domain': config.get("CUSTOM_DOMAIN", None),
'querystring_expire': 1200,
'querystring_expire': 5400,
'gzip': True,
},
)
Expand Down Expand Up @@ -272,6 +272,21 @@ def from_config(cls, config_name):
getattr(settings, config_name).get('STORAGE_KWARGS'),
)

def add_rows(self, rows, output_buffer=None):
"""
Given an output buffer and rows (each row is an iterable of
strings), add rows to output buffer in csv format and return it.
"""
if not output_buffer:
output_buffer = ContentFile('')
# Adding unicode signature (BOM) for MS Excel 2013 compatibility
if six.PY2:
output_buffer.write(codecs.BOM_UTF8)

csvwriter = csv.writer(output_buffer)
csvwriter.writerows(self._get_utf8_encoded_rows(rows))
return output_buffer

def store(self, course_id, filename, buff):
"""
Store the contents of `buff` in a directory determined by hashing
Expand Down
Loading

0 comments on commit 087d669

Please sign in to comment.