Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-ora2
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-ora2
Commits
7ee10dbe
Commit
7ee10dbe
authored
Mar 10, 2014
by
David Ormsbee
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve docstrings for Workflow API
parent
979ebb78
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
206 additions
and
21 deletions
+206
-21
apps/openassessment/workflow/api.py
+171
-21
apps/openassessment/workflow/models.py
+35
-0
No files found.
apps/openassessment/workflow/api.py
View file @
7ee10dbe
...
...
@@ -68,8 +68,18 @@ def create_workflow(submission_uuid):
assessments will be evaluating.
Returns:
dict: Assessment workflow information containing the keys
`submission_uuid`, `uuid`, `status`, `created`, `modified`
dict: Assessment workflow information with the following
`uuid` = UUID of this `AssessmentWorkflow`
`submission_uuid` = UUID of submission this workflow tracks
`status` = Active step, always "peer" when created.
`created` = created datetime
'modified' = modified datetime (same as `created` for this method)
'score' = should be None in the usual case, but could be a dict
with keys "points_earned" and "points_possible` and int values.
The latter will only happen on workflow creation if something
else has already written the score for this submission (such as
a professor manually entering it). There is no support for such
a feature at present, but it may be added later.
Raises:
AssessmentWorkflowRequestError: If the `submission_uuid` passed in does
...
...
@@ -78,15 +88,6 @@ def create_workflow(submission_uuid):
submissions app not being available or a database configuation
problem.
Examples:
>>> create_assessment_workflow('e12bd3ee-9fb0-11e3-9f68-040ccee02800')
{
'submission_uuid': u'e12bd3ee-9fb0-11e3-9f68-040ccee02800',
'uuid': u'e12ef27a-9fb0-11e3-aad4-040ccee02800',
'status': u'peer',
'created': datetime.datetime(2014, 2, 27, 13, 12, 59, 225359, tzinfo=<UTC>),
'modified': datetime.datetime(2014, 2, 27, 13, 12, 59, 225675, tzinfo=<UTC>)
}
"""
def
sub_err_msg
(
specific_err_msg
):
return
(
...
...
@@ -133,15 +134,43 @@ def get_workflow_for_submission(submission_uuid, assessment_requirements):
"""Returns Assessment Workflow information
This will implicitly call `update_from_assessments()` to make sure we
give the most current information.
give the most current information. Unlike `create_workflow()`, this function
will check our assessment sequences to see if they are complete. We pass
in the `assessment_requirements` each time we make the request because the
canonical requirements are stored in the `OpenAssessmentBlock` problem
definition and may change over time.
Args:
student_item_dict (dict):
submission_uuid (str):
submission_uuid (str): Identifier for the submission the
`AssessmentWorkflow` was created to track. There is a 1:1
relationship between submissions and workflows, so this uniquely
identifies the `AssessmentWorkflow`.
assessment_requirements (dict): Dictionary that currently looks like:
`{"peer": {"must_grade": <int>, "must_be_graded_by": <int>}}`
`must_grade` is the number of assessments a student must complete.
`must_be_graded_by` is the number of assessments a submission must
receive to be scored. `must_grade` should be greater than
`must_be_graded_by` to ensure that everyone will get scored.
The intention is to eventually pass in more assessment sequence
specific requirements in this dict.
Returns:
dict: Assessment workflow information containing the keys
`submission_uuid`, `uuid`, `status`, `created`, `modified`
dict: Assessment workflow information with the following
`uuid` = UUID of this `AssessmentWorkflow`
`submission_uuid` = UUID of submission this workflow tracks
`status` = Active step, always "peer" when created.
`created` = created datetime
'modified' = modified datetime (same as `created` for this method)
'score' = None if no score is present. A dict with keys
`points_earned` and `points_possible` and int values if a score
has been created for this submission. We only do this when we
mark a workflow `done`, but it is possible that other processes
will later manually write that score information.
`status_details` = dict with the keys `peer` and `self`, each of
which has a dict with a key of `complete` and a boolean value.
The intention is to tell you the completion status of each
assessment sequence, but we will likely use this for extra
information later on.
Raises:
AssessmentWorkflowRequestError: If the `workflow_uuid` passed in is not
...
...
@@ -153,13 +182,26 @@ def get_workflow_for_submission(submission_uuid, assessment_requirements):
problem.
Examples:
>>> get_assessment_workflow('e12ef27a-9fb0-11e3-aad4-040ccee02800')
>>> get_workflow_for_submission(
... '222bdf3d-a88e-11e3-859e-040ccee02800',
... {"peer": {"must_grade":5, "must_be_graded_by":3}}
... )
...
{
'
submission_uuid': u'e12bd3ee-9fb0-11e3-9f68
-040ccee02800',
'
uuid': u'e12ef27a-9fb0-11e3-aad4
-040ccee02800',
'
uuid': u'53f27ecc-a88e-11e3-8543
-040ccee02800',
'
submission_uuid': u'222bdf3d-a88e-11e3-859e
-040ccee02800',
'status': u'peer',
'created': datetime.datetime(2014, 2, 27, 13, 12, 59, 225359, tzinfo=<UTC>),
'modified': datetime.datetime(2014, 2, 27, 13, 12, 59, 225675, tzinfo=<UTC>)
'created': datetime.datetime(2014, 3, 10, 19, 58, 19, 846684, tzinfo=<UTC>),
'modified': datetime.datetime(2014, 3, 10, 19, 58, 19, 846957, tzinfo=<UTC>),
'score': None,
'status_details': {
'peer': {
'complete': False
},
'self': {
'complete': False
}
}
}
"""
...
...
@@ -167,12 +209,116 @@ def get_workflow_for_submission(submission_uuid, assessment_requirements):
def
update_from_assessments
(
submission_uuid
,
assessment_requirements
):
"""Update our workflow status based on the status of peer and self assessments.
We pass in the `assessment_requirements` each time we make the request
because the canonical requirements are stored in the `OpenAssessmentBlock`
problem definition and may change over time. Because this method also
returns a copy of the `WorkflowAssessment` information as a convenience,
it's functionally equivalent to calling `get_workflow_for_submission()`.
This is a little wonky from a REST, get-doesn't-change-state point of view,
except that what's stored in the `AssessmentWorkflow` isn't the canonical
true value -- it's just the most recently known state of it based on the
last known requirments. For now, we have to query for truth.
Args:
submission_uuid (str): Identifier for the submission the
`AssessmentWorkflow` was created to track. There is a 1:1
relationship between submissions and workflows, so this uniquely
identifies the `AssessmentWorkflow`.
assessment_requirements (dict): Dictionary that currently looks like:
`{"peer": {"must_grade": <int>, "must_be_graded_by": <int>}}`
`must_grade` is the number of assessments a student must complete.
`must_be_graded_by` is the number of assessments a submission must
receive to be scored. `must_grade` should be greater than
`must_be_graded_by` to ensure that everyone will get scored.
The intention is to eventually pass in more assessment sequence
specific requirements in this dict.
Returns:
dict: Assessment workflow information with the following
`uuid` = UUID of this `AssessmentWorkflow`
`submission_uuid` = UUID of submission this workflow tracks
`status` = Active step, always "peer" when created.
`created` = created datetime
'modified' = modified datetime (same as `created` for this method)
'score' = None if no score is present. A dict with keys
`points_earned` and `points_possible` and int values if a score
has been created for this submission. We only do this when we
mark a workflow `done`, but it is possible that other processes
will later manually write that score information.
`status_details` = dict with the keys `peer` and `self`, each of
which has a dict with a key of `complete` and a boolean value.
The intention is to tell you the completion status of each
assessment sequence, but we will likely use this for extra
information later on.
Raises:
AssessmentWorkflowRequestError: If the `workflow_uuid` passed in is not
a string type.
AssessmentWorkflowNotFoundError: No assessment workflow matching the
requested UUID exists.
AssessmentWorkflowInternalError: Unexpected internal error, such as the
submissions app not being available or a database configuation
problem.
Examples:
>>> get_workflow_for_submission(
... '222bdf3d-a88e-11e3-859e-040ccee02800',
... {"peer": {"must_grade":5, "must_be_graded_by":3}}
... )
...
{
'uuid': u'53f27ecc-a88e-11e3-8543-040ccee02800',
'submission_uuid': u'222bdf3d-a88e-11e3-859e-040ccee02800',
'status': u'peer',
'created': datetime.datetime(2014, 3, 10, 19, 58, 19, 846684, tzinfo=<UTC>),
'modified': datetime.datetime(2014, 3, 10, 19, 58, 19, 846957, tzinfo=<UTC>),
'score': None,
'status_details': {
'peer': {
'complete': False
},
'self': {
'complete': False
}
}
}
"""
workflow
=
_get_workflow_model
(
submission_uuid
)
workflow
.
update_from_assessments
(
assessment_requirements
)
return
_serialized_with_details
(
workflow
,
assessment_requirements
)
def
_get_workflow_model
(
submission_uuid
):
"""Return the `AssessmentWorkflow` model for a given `submission_uuid`.
This method will raise the appropriate `AssessmentWorkflowError` while
trying to fetch the model object. This method assumes the object already
exists and will not attempt to create one.
Args:
submission_uuid (str): Identifier for the submission the
`AssessmentWorkflow` was created to track. There is a 1:1
relationship between submissions and workflows, so this uniquely
identifies the `AssessmentWorkflow`.
Returns:
`AssessmentWorkflow`: The workflow used to track the global progress of
this submission as it works its way through the peer and self
assessment sequences.
Raises:
AssessmentWorkflowRequestError: If the `workflow_uuid` passed in is not
a string type.
AssessmentWorkflowNotFoundError: No assessment workflow matching the
requested UUID exists.
AssessmentWorkflowInternalError: Unexpected internal error, such as the
submissions app not being available or a database configuation
problem.
"""
if
not
isinstance
(
submission_uuid
,
basestring
):
raise
AssessmentWorkflowRequestError
(
"submission_uuid must be a string type"
)
...
...
@@ -194,6 +340,10 @@ def _get_workflow_model(submission_uuid):
return
workflow
def
_serialized_with_details
(
workflow
,
assessment_requirements
):
"""Given a workflow and assessment requirements, return the serialized
version of an `AssessmentWorkflow` and add in the status details. See
`update_from_assessments()` for details on params and return values.
"""
data_dict
=
AssessmentWorkflowSerializer
(
workflow
)
.
data
data_dict
[
"status_details"
]
=
workflow
.
status_details
(
assessment_requirements
)
return
data_dict
...
...
apps/openassessment/workflow/models.py
View file @
7ee10dbe
...
...
@@ -43,6 +43,11 @@ class AssessmentWorkflow(TimeStampedModel, StatusModel):
@property
def
score
(
self
):
"""Latest score for the submission we're tracking.
Note that while it is usually the case that we're setting the score,
that may not always be the case. We may have some course staff override.
"""
return
sub_api
.
get_latest_score_for_submission
(
self
.
submission_uuid
)
def
status_details
(
self
,
assessment_requirements
):
...
...
@@ -63,6 +68,36 @@ class AssessmentWorkflow(TimeStampedModel, StatusModel):
return
self_api
.
is_complete
(
self
.
submission_uuid
)
def
update_from_assessments
(
self
,
assessment_requirements
):
"""Query self and peer APIs and change our status if appropriate.
If the status is done, we do nothing. Once something is done, we never
move back to any other status.
By default, an `AssessmentWorkflow` starts with status `peer`.
If the peer API says that our submitter's requirements are met -- that
the submitter of the submission we're tracking has assessed the required
number of other submissions -- then the status will move to `self`.
If the self API says that the person who created the submission we're
tracking has assessed themselves, then we move to `waiting`.
If we're in the `waiting` status, and the peer API says it can score
this submission (meaning other students have created enough assessments
of it), then we record the score in the submissions API and move our
`status` to `done`.
Args:
assessment_requirements (dict): Dictionary that currently looks like:
`{"peer": {"must_grade": <int>, "must_be_graded_by": <int>}}`
`must_grade` is the number of assessments a student must complete.
`must_be_graded_by` is the number of assessments a submission must
receive to be scored. `must_grade` should be greater than
`must_be_graded_by` to ensure that everyone will get scored.
The intention is to eventually pass in more assessment sequence
specific requirements in this dict.
"""
# If we're done, we're done -- it doesn't matter if requirements have
# changed because we've already written a score.
if
self
.
status
==
self
.
STATUS
.
done
:
...
...
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