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
42829bd2
Commit
42829bd2
authored
Sep 18, 2017
by
Alex Dusenbery
Committed by
Alex Dusenbery
Sep 19, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
EDUCATOR-1103 | Restrict the number of courses to run a single opt-in query for.
parent
7a875096
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
41 additions
and
5 deletions
+41
-5
openedx/core/djangoapps/user_api/management/commands/email_opt_in_list.py
+18
-2
openedx/core/djangoapps/user_api/management/tests/test_email_opt_in_list.py
+23
-3
No files found.
openedx/core/djangoapps/user_api/management/commands/email_opt_in_list.py
View file @
42829bd2
...
...
@@ -35,16 +35,29 @@ from opaque_keys.edx.keys import CourseKey
from
xmodule.modulestore.django
import
modulestore
DEFAULT_CHUNK_SIZE
=
10
LOGGER
=
logging
.
getLogger
(
__name__
)
def
chunks
(
sequence
,
chunk_size
):
return
(
sequence
[
index
:
index
+
chunk_size
]
for
index
in
xrange
(
0
,
len
(
sequence
),
chunk_size
))
class
Command
(
BaseCommand
):
"""Generate a list of email opt-in values for user enrollments. """
args
=
"<OUTPUT_FILENAME> <ORG_ALIASES> --courses=COURSE_ID_LIST"
args
=
"<OUTPUT_FILENAME> <ORG_ALIASES> --courses=COURSE_ID_LIST
--email-optin-chunk-size=CHUNK_SIZE
"
help
=
"Generate a list of email opt-in values for user enrollments."
option_list
=
BaseCommand
.
option_list
+
(
optparse
.
make_option
(
'--courses '
,
action
=
'store'
),
optparse
.
make_option
(
'--email-optin-chunk-size'
,
action
=
'store'
,
type
=
'int'
,
default
=
DEFAULT_CHUNK_SIZE
,
dest
=
'email_optin_chunk_size'
,
help
=
'The number of courses to get opt-in information for in a single query.'
)
)
# Fields output in the CSV
...
...
@@ -114,10 +127,13 @@ class Command(BaseCommand):
)
)
email_optin_chunk_size
=
options
.
get
(
'email_optin_chunk_size'
,
DEFAULT_CHUNK_SIZE
)
# Open the output file and generate the report.
with
open
(
file_path
,
"w"
)
as
file_handle
:
with
self
.
_log_execution_time
():
self
.
_write_email_opt_in_prefs
(
file_handle
,
org_list
,
courses
)
for
course_group
in
chunks
(
courses
,
email_optin_chunk_size
):
self
.
_write_email_opt_in_prefs
(
file_handle
,
org_list
,
course_group
)
# Remind the user where the output file is
LOGGER
.
info
(
u"Output file: {file_path}"
.
format
(
file_path
=
file_path
))
...
...
openedx/core/djangoapps/user_api/management/tests/test_email_opt_in_list.py
View file @
42829bd2
...
...
@@ -202,6 +202,20 @@ class EmailOptInListTest(ModuleStoreTestCase):
only_courses
=
[
self
.
courses
[
0
]
.
id
,
self
.
courses
[
1
]
.
id
]
self
.
_run_command
(
self
.
TEST_ORG
,
only_courses
=
only_courses
)
def
test_specify_chunk_size
(
self
):
# Create several courses in the same org
self
.
_create_courses_and_enrollments
(
(
self
.
TEST_ORG
,
True
),
(
self
.
TEST_ORG
,
True
),
(
self
.
TEST_ORG
,
True
),
)
# Execute the command, but exclude the second course from the list
output
=
self
.
_run_command
(
self
.
TEST_ORG
,
chunk_size
=
2
)
course_ids
=
[
row
[
'course_id'
]
.
strip
()
.
decode
(
'utf-8'
)
for
row
in
output
]
for
course
in
self
.
courses
:
assert
unicode
(
course
.
id
)
in
course_ids
# Choose numbers before and after the query interval boundary
@ddt.data
(
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
)
def
test_many_users
(
self
,
num_users
):
...
...
@@ -246,7 +260,9 @@ class EmailOptInListTest(ModuleStoreTestCase):
@ddt.data
(
0
,
1
)
def
test_not_enough_args
(
self
,
num_args
):
args
=
[
"dummy"
]
*
num_args
expected_msg_regex
=
"^Usage: <OUTPUT_FILENAME> <ORG_ALIASES> --courses=COURSE_ID_LIST$"
expected_msg_regex
=
(
"^Usage: <OUTPUT_FILENAME> <ORG_ALIASES> --courses=COURSE_ID_LIST --email-optin-chunk-size=CHUNK_SIZE$"
)
with
self
.
assertRaisesRegexp
(
CommandError
,
expected_msg_regex
):
email_opt_in_list
.
Command
()
.
handle
(
*
args
)
...
...
@@ -332,7 +348,7 @@ class EmailOptInListTest(ModuleStoreTestCase):
pref
=
UserOrgTag
.
objects
.
filter
(
user
=
user
)
.
order_by
(
"-modified"
)
return
pref
[
0
]
.
modified
.
isoformat
(
' '
)
if
len
(
pref
)
>
0
else
self
.
DEFAULT_DATETIME_STR
def
_run_command
(
self
,
org
,
other_names
=
None
,
only_courses
=
None
,
query_interval
=
None
):
def
_run_command
(
self
,
org
,
other_names
=
None
,
only_courses
=
None
,
query_interval
=
None
,
chunk_size
=
None
):
"""Execute the management command to generate the email opt-in list.
Arguments:
...
...
@@ -342,6 +358,7 @@ class EmailOptInListTest(ModuleStoreTestCase):
other_names (list): List of other aliases for the org.
only_courses (list): If provided, include only these course IDs in the report.
query_interval (int): If provided, override the default query interval.
chunk_size (int): If provided, overrides the default number of chunks for query iteration.
Returns:
list: The rows of the generated CSV report. Each item is a dictionary.
...
...
@@ -368,7 +385,10 @@ class EmailOptInListTest(ModuleStoreTestCase):
command
.
QUERY_INTERVAL
=
query_interval
# Execute the command
command
.
handle
(
output_path
,
*
org_list
,
courses
=
only_courses
)
kwargs
=
{
'courses'
:
only_courses
}
if
chunk_size
:
kwargs
[
'email_optin_chunk_size'
]
=
chunk_size
command
.
handle
(
output_path
,
*
org_list
,
**
kwargs
)
# Retrieve the output from the file
try
:
...
...
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