Skip to content

Commit

Permalink
Merge pull request #8 from edx/release_review
Browse files Browse the repository at this point in the history
Release review changes
  • Loading branch information
mattdrayer committed Jan 15, 2015
2 parents 6e844a3 + a76c936 commit 4dfe78a
Show file tree
Hide file tree
Showing 10 changed files with 829 additions and 508 deletions.
135 changes: 91 additions & 44 deletions milestones/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ def _validate_content_key(content_key):
)


def _validate_milestone(milestone):
def _validate_milestone_data(milestone):
""" Validation helper """
if not validators.milestone_is_valid(milestone):
if not validators.milestone_data_is_valid(milestone):
exceptions.raise_exception(
"Milestone",
milestone,
Expand Down Expand Up @@ -70,11 +70,18 @@ def _validate_user(user):


# PUBLIC FUNCTIONS
def get_milestone_relationship_types():
"""
Exposes the available relationship type choices without exposing the data layer
"""
return data.fetch_milestone_relationship_types()


def add_milestone(milestone):
"""
Passes a new milestone to the data layer for storage
"""
_validate_milestone(milestone)
_validate_milestone_data(milestone)
milestone = data.create_milestone(milestone)
return milestone

Expand All @@ -83,35 +90,25 @@ def edit_milestone(milestone):
"""
Passes an updated milestone to the data layer for storage
"""
_validate_milestone(milestone)
try:
return data.update_milestone(milestone)
except exceptions.InvalidMilestoneException:
raise
_validate_milestone_data(milestone)
return data.update_milestone(milestone)


def get_milestone(milestone_id):
"""
Retrieves the specified milestone
"""
milestone = {
'id': milestone_id,
}
milestones = data.fetch_milestones(milestone)
if not len(milestones):
return None
return milestones[0]
return data.fetch_milestone(milestone_id)


def get_milestones(namespace):
"""
Retrieves the specified milestone by namespace
Retrieves a set of milestones by namespace
(no other way to really do it right now)
"""
milestone = {
'namespace': namespace,
}
_validate_milestone(milestone)
return data.fetch_milestones(milestone)


Expand All @@ -132,8 +129,12 @@ def add_course_milestone(course_key, relationship, milestone):
"""
_validate_course_key(course_key)
_validate_milestone_relationship_type(relationship)
_validate_milestone(milestone)
data.create_course_milestone(course_key=course_key, relationship=relationship, milestone=milestone)
_validate_milestone_data(milestone)
data.create_course_milestone(
course_key=course_key,
relationship=relationship,
milestone=milestone
)


def get_course_milestones(course_key, relationship=None):
Expand All @@ -155,38 +156,83 @@ def get_course_required_milestones(course_key, user):
"""
_validate_course_key(course_key)
_validate_user(user)
required_milestones = data.fetch_courses_milestones([course_key], 'requires', user)
required_milestones = data.fetch_courses_milestones(
[course_key],
get_milestone_relationship_types()['REQUIRES'],
user
)
return required_milestones


def get_course_milestones_fulfillment_paths(course_key, user):
"""
Returns a collection composed of the possible fulfillment/collection opportunites
Returns a collection composed of the possible fulfillment/collection options/opportunites
Inputs:
course_key: string representation of a CourseKey -- eg, unicode(course.id)
user: dictionary representation of a User object ('id' field is required)
Output:
A complex dict-of-dicts containing the currently-required milestones for the
specified course+user combo, and the options for collecting them
(courses and/or content to complete which leads to their fulfillment)
{
'milestone_1': {
'content': [
u'i4x://the/content/key/123456789',
u'i4x://the/content/key/987654321'
]
},
'milestone_2': {
'courses': [
u'the/prerequisite/course_key'
]
},
'milestone_3': {
'content': [
u'i4x://the/content/key/123456789'
],
'courses': [
u'the/prerequisite/course_key'
]
}
}
"""
_validate_course_key(course_key)
_validate_user(user)

# Retrieve the outstanding milestones for this course, for this user
required_milestones = data.fetch_courses_milestones([course_key], 'requires', user)
required_milestones = data.fetch_courses_milestones(
[course_key],
get_milestone_relationship_types()['REQUIRES'],
user
)

# Build the set of fulfillment paths for the outstanding milestones
fulfillment_paths = {}
for milestone in required_milestones:
dict_key = 'milestone_{}'.format(milestone['id'])
dict_key = '{}.{}'.format(milestone['namespace'], milestone['name'])
fulfillment_paths[dict_key] = {}
milestone_courses = data.fetch_milestone_courses(milestone, 'fulfills')
if len(milestone_courses):
fulfillment_paths[dict_key]['courses'] = milestone_courses
milestone_course_content = data.fetch_milestone_course_content(milestone, 'fulfills')
if len(milestone_course_content):
fulfillment_paths[dict_key]['content'] = milestone_course_content
milestone_courses = data.fetch_milestone_courses(
milestone,
get_milestone_relationship_types()['FULFILLS']
)
if milestone_courses:
fulfillment_paths[dict_key]['courses'] = [
milestone['course_id'] for milestone in milestone_courses]
milestone_course_content = data.fetch_milestone_course_content(
milestone,
get_milestone_relationship_types()['FULFILLS']
)
if milestone_course_content:
fulfillment_paths[dict_key]['content'] = [
milestone['content_id'] for milestone in milestone_course_content]
return fulfillment_paths


def get_courses_milestones(course_keys, relationship=None, user=None):
"""
Retrieves the set of milestones for list of courses
'relationship': optional filter on milestone relationship type (string, eg: 'requires')
'user': optional filter to constrain the set to those milestones which a user has already collected
Returns an array of dicts containing milestones
"""
[_validate_course_key(course_key) for course_key in course_keys] # pylint: disable=expression-not-assigned
Expand All @@ -205,7 +251,7 @@ def remove_course_milestone(course_key, milestone):
Removes the specfied milestone from the specified course
"""
_validate_course_key(course_key)
_validate_milestone(milestone)
_validate_milestone_data(milestone)
return data.delete_course_milestone(course_key=course_key, milestone=milestone)


Expand All @@ -217,7 +263,7 @@ def add_course_content_milestone(course_key, content_key, relationship, mileston
_validate_course_key(course_key)
_validate_content_key(content_key)
_validate_milestone_relationship_type(relationship)
_validate_milestone(milestone)
_validate_milestone_data(milestone)
data.create_course_content_milestone(
course_key=course_key,
content_key=content_key,
Expand Down Expand Up @@ -250,7 +296,7 @@ def remove_course_content_milestone(course_key, content_key, milestone):
"""
_validate_course_key(course_key)
_validate_content_key(content_key)
_validate_milestone(milestone)
_validate_milestone_data(milestone)
return data.delete_course_content_milestone(
course_key=course_key,
content_key=content_key,
Expand All @@ -263,35 +309,36 @@ def add_user_milestone(user, milestone):
Adds a new User-Milestone relationship to the system
"""
_validate_user(user)
_validate_milestone(milestone)
_validate_milestone_data(milestone)
data.create_user_milestone(user, milestone)


def get_user_milestones(user):
def get_user_milestones(user, namespace):
"""
Retrieves the set of milestones for a given user
Returns an array of dicts
Returns an array of dicts -- must provide the 'namespace' filter (or else!!!)
"""
_validate_user(user)
return data.fetch_user_milestones(user)
milestone = {'namespace': namespace}
return data.fetch_user_milestones(user, milestone)


def remove_user_milestone(user, milestone):
def user_has_milestone(user, milestone):
"""
Removes the specified User-Milestone link from the system
A helper/convenience method to check for a specific user-milestone link
"""
_validate_user(user)
_validate_milestone(milestone)
return data.delete_user_milestone(user, milestone)
_validate_milestone_data(milestone)
return True if data.fetch_user_milestones(user, milestone) else False


def user_has_milestone(user, milestone):
def remove_user_milestone(user, milestone):
"""
A helper/convenience method to check for a specific user-milestone link
Removes the specified User-Milestone link from the system
"""
_validate_user(user)
_validate_milestone(milestone)
return len(data.fetch_user_milestones(user, milestone))
_validate_milestone_data(milestone)
return data.delete_user_milestone(user, milestone)


def remove_course_references(course_key):
Expand Down
Loading

0 comments on commit 4dfe78a

Please sign in to comment.