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
dcdbd53e
Commit
dcdbd53e
authored
Oct 28, 2015
by
Nimisha Asthagiri
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Transformer: StartDateTransformer
parent
3f6baa99
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
219 additions
and
0 deletions
+219
-0
lms/djangoapps/course_blocks/transformers/start_date.py
+101
-0
lms/djangoapps/course_blocks/transformers/tests/test_start_date.py
+118
-0
No files found.
lms/djangoapps/course_blocks/transformers/start_date.py
0 → 100644
View file @
dcdbd53e
"""
Start Date Transformer implementation.
"""
from
openedx.core.lib.block_cache.transformer
import
BlockStructureTransformer
from
lms.djangoapps.courseware.access_utils
import
check_start_date
from
xmodule.course_metadata_utils
import
DEFAULT_START_DATE
from
.utils
import
get_field_on_block
class
StartDateTransformer
(
BlockStructureTransformer
):
"""
A transformer that enforces the 'start' and 'days_early_for_beta'
fields on blocks by removing blocks from the block structure for
which the user does not have access. The 'start' field on a
block is percolated down to its descendants, so that all blocks
enforce the 'start' field from their ancestors. The assumed
'start' value for a block is then the maximum of its parent and its
own.
For a block with multiple parents, the assumed parent start date
value is a computed minimum of the start dates of all its parents.
So as long as one parent chain allows access, the block has access.
Staff users are exempted from visibility rules.
"""
VERSION
=
1
MERGED_START_DATE
=
'merged_start_date'
@classmethod
def
name
(
cls
):
"""
Unique identifier for the transformer's class;
same identifier used in setup.py.
"""
return
"start_date"
@classmethod
def
get_merged_start_date
(
cls
,
block_structure
,
block_key
):
"""
Returns the merged value for the start date for the block with
the given block_key in the given block_structure.
"""
return
block_structure
.
get_transformer_block_field
(
block_key
,
cls
,
cls
.
MERGED_START_DATE
,
False
)
@classmethod
def
collect
(
cls
,
block_structure
):
"""
Collects any information that's necessary to execute this
transformer's transform method.
"""
block_structure
.
request_xblock_fields
(
'days_early_for_beta'
)
for
block_key
in
block_structure
.
topological_traversal
():
# compute merged value of start date from all parents
parents
=
block_structure
.
get_parents
(
block_key
)
min_all_parents_start_date
=
min
(
cls
.
get_merged_start_date
(
block_structure
,
parent_key
)
for
parent_key
in
parents
)
if
parents
else
None
# set the merged value for this block
block_start
=
get_field_on_block
(
block_structure
.
get_xblock
(
block_key
),
'start'
)
if
min_all_parents_start_date
is
None
:
# no parents so just use value on block or default
merged_start_value
=
block_start
or
DEFAULT_START_DATE
elif
not
block_start
:
# no value on this block so take value from parents
merged_start_value
=
min_all_parents_start_date
else
:
# max of merged-start-from-all-parents and this block
merged_start_value
=
max
(
min_all_parents_start_date
,
block_start
)
block_structure
.
set_transformer_block_field
(
block_key
,
cls
,
cls
.
MERGED_START_DATE
,
merged_start_value
)
def
transform
(
self
,
usage_info
,
block_structure
):
"""
Mutates block_structure based on the given usage_info.
"""
# Users with staff access bypass the Start Date check.
if
usage_info
.
has_staff_access
:
return
block_structure
.
remove_block_if
(
lambda
block_key
:
not
check_start_date
(
usage_info
.
user
,
block_structure
.
get_xblock_field
(
block_key
,
'days_early_for_beta'
),
self
.
get_merged_start_date
(
block_structure
,
block_key
),
usage_info
.
course_key
,
)
)
lms/djangoapps/course_blocks/transformers/tests/test_start_date.py
0 → 100644
View file @
dcdbd53e
"""
Tests for StartDateTransformer.
"""
import
ddt
from
datetime
import
timedelta
from
django.utils.timezone
import
now
from
mock
import
patch
from
courseware.tests.factories
import
BetaTesterFactory
from
..start_date
import
StartDateTransformer
,
DEFAULT_START_DATE
from
.test_helpers
import
BlockParentsMapTestCase
,
update_block
@ddt.ddt
class
StartDateTransformerTestCase
(
BlockParentsMapTestCase
):
"""
StartDateTransformer Test
"""
STUDENT
=
1
BETA_USER
=
2
class
StartDateType
(
object
):
"""
Use constant enum types for deterministic ddt test method names (rather than dynamically generated timestamps)
"""
released
=
1
,
future
=
2
,
default
=
3
TODAY
=
now
()
LAST_MONTH
=
TODAY
-
timedelta
(
days
=
30
)
NEXT_MONTH
=
TODAY
+
timedelta
(
days
=
30
)
@classmethod
def
start
(
cls
,
enum_value
):
"""
Returns a start date for the given enum value
"""
if
enum_value
==
cls
.
released
:
return
cls
.
LAST_MONTH
elif
enum_value
==
cls
.
future
:
return
cls
.
NEXT_MONTH
else
:
return
DEFAULT_START_DATE
def
setUp
(
self
,
**
kwargs
):
super
(
StartDateTransformerTestCase
,
self
)
.
setUp
(
**
kwargs
)
self
.
beta_user
=
BetaTesterFactory
(
course_key
=
self
.
course
.
id
,
username
=
'beta_tester'
,
password
=
self
.
password
)
course
=
self
.
get_block
(
0
)
course
.
days_early_for_beta
=
33
update_block
(
course
)
# Following test cases are based on BlockParentsMapTestCase.parents_map:
# 0
# / \
# 1 2
# / \ / \
# 3 4 / 5
# \ /
# 6
@patch.dict
(
'django.conf.settings.FEATURES'
,
{
'DISABLE_START_DATES'
:
False
})
@ddt.data
(
(
STUDENT
,
{},
{},
{}),
(
STUDENT
,
{
0
:
StartDateType
.
default
},
{},
{}),
(
STUDENT
,
{
0
:
StartDateType
.
future
},
{},
{}),
(
STUDENT
,
{
0
:
StartDateType
.
released
},
{
0
,
1
,
2
,
3
,
4
,
5
,
6
},
{}),
# has_access checks on block directly and doesn't follow negative access set on parent/ancestor (i.e., 0)
(
STUDENT
,
{
1
:
StartDateType
.
released
},
{},
{
1
,
3
,
4
,
6
}),
(
STUDENT
,
{
2
:
StartDateType
.
released
},
{},
{
2
,
5
,
6
}),
(
STUDENT
,
{
1
:
StartDateType
.
released
,
2
:
StartDateType
.
released
},
{},
{
1
,
2
,
3
,
4
,
5
,
6
}),
# DAG conflicts: has_access relies on field inheritance so it takes only the value from the first parent-chain
(
STUDENT
,
{
0
:
StartDateType
.
released
,
4
:
StartDateType
.
future
},
{
0
,
1
,
2
,
3
,
5
,
6
},
{
6
}),
(
STUDENT
,
{
0
:
StartDateType
.
released
,
2
:
StartDateType
.
released
,
4
:
StartDateType
.
future
},
{
0
,
1
,
2
,
3
,
5
,
6
},
{
6
},
),
(
STUDENT
,
{
0
:
StartDateType
.
released
,
2
:
StartDateType
.
future
,
4
:
StartDateType
.
released
},
{
0
,
1
,
3
,
4
,
6
},
{}),
# beta user cases
(
BETA_USER
,
{},
{},
{}),
(
BETA_USER
,
{
0
:
StartDateType
.
default
},
{},
{}),
(
BETA_USER
,
{
0
:
StartDateType
.
future
},
{
0
,
1
,
2
,
3
,
4
,
5
,
6
},
{}),
(
BETA_USER
,
{
0
:
StartDateType
.
released
},
{
0
,
1
,
2
,
3
,
4
,
5
,
6
},
{}),
(
BETA_USER
,
{
0
:
StartDateType
.
released
,
2
:
StartDateType
.
default
,
5
:
StartDateType
.
future
},
{
0
,
1
,
3
,
4
,
6
},
{
5
},
),
(
BETA_USER
,
{
1
:
StartDateType
.
released
,
2
:
StartDateType
.
default
},
{},
{
1
,
3
,
4
,
6
}),
(
BETA_USER
,
{
0
:
StartDateType
.
released
,
4
:
StartDateType
.
future
},
{
0
,
1
,
2
,
3
,
4
,
5
,
6
},
{}),
(
BETA_USER
,
{
0
:
StartDateType
.
released
,
4
:
StartDateType
.
default
},
{
0
,
1
,
2
,
3
,
5
,
6
},
{
6
}),
)
@ddt.unpack
# pylint: disable=invalid-name
def
test_block_start_date
(
self
,
user_type
,
start_date_type_values
,
expected_student_visible_blocks
,
blocks_with_differing_student_access
):
for
idx
,
start_date_type
in
start_date_type_values
.
iteritems
():
block
=
self
.
get_block
(
idx
)
block
.
start
=
self
.
StartDateType
.
start
(
start_date_type
)
update_block
(
block
)
self
.
assert_transform_results
(
self
.
beta_user
if
user_type
==
self
.
BETA_USER
else
self
.
student
,
expected_student_visible_blocks
,
blocks_with_differing_student_access
,
[
StartDateTransformer
()],
)
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