Skip to content

Commit

Permalink
Merge pull request #1118 from damianavila/multiple-classes-dev
Browse files Browse the repository at this point in the history
Integrate course_id into the api and apps
  • Loading branch information
jhamrick authored Jun 1, 2019
2 parents 4dee9e2 + 11dcb2a commit 4b7013a
Show file tree
Hide file tree
Showing 27 changed files with 92 additions and 83 deletions.
2 changes: 1 addition & 1 deletion nbgrader/apps/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def __init__(self, coursedir=None, authenticator=None, **kwargs):
coursedir=self.coursedir,
authenticator=self.authenticator,
parent=self)
self.course_id = lister.course_id
self.course_id = self.coursedir.course_id
self.exchange = lister.root

try:
Expand Down
6 changes: 4 additions & 2 deletions nbgrader/apps/assignapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
from .baseapp import NbGrader, nbgrader_aliases, nbgrader_flags
from ..converters import BaseConverter, Assign, NbGraderException

aliases = {}
aliases = {
'course': 'CourseDirectory.course_id'
}
aliases.update(nbgrader_aliases)
del aliases['student']
aliases.update({
Expand Down Expand Up @@ -36,7 +38,7 @@
'create': (
{'Assign': {'create_assignment': True}},
"Create an entry for the assignment in the database, if one does not already exist."
),
),
'force': (
{'BaseConverter': {'force': True}},
"Overwrite an assignment/submission if it already exists."
Expand Down
4 changes: 3 additions & 1 deletion nbgrader/apps/autogradeapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
from .baseapp import NbGrader, nbgrader_aliases, nbgrader_flags
from ..converters import BaseConverter, Autograde, NbGraderException

aliases = {}
aliases = {
'course': 'CourseDirectory.course_id'
}
aliases.update(nbgrader_aliases)
aliases.update({
})
Expand Down
9 changes: 7 additions & 2 deletions nbgrader/apps/baseapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,15 @@ def _load_config(self, cfg, **kwargs):
delattr(cfg.NbGrader, old_opt)

if "course_id" in cfg.NbGrader:
self.log.warning("Outdated config: use Exchange.course_id rather than NbGrader.course_id")
cfg.Exchange.course_id = cfg.NbGrader.course_id
self.log.warning("Outdated config: use CourseDirectory.course_id rather than NbGrader.course_id")
cfg.CourseDirectory.course_id = cfg.NbGrader.course_id
del cfg.NbGrader.course_id

if "course_id" in cfg.Exchange:
self.log.warning("Outdated config: use CourseDirectory.course_id rather than Exchange.course_id")
cfg.CourseDirectory.course_id = cfg.Exchange.course_id
del cfg.Exchange.course_id

exchange_options = [
("timezone", "timezone"),
("timestamp_format", "timestamp_format"),
Expand Down
4 changes: 2 additions & 2 deletions nbgrader/apps/collectapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
aliases.update(nbgrader_aliases)
aliases.update({
"timezone": "Exchange.timezone",
"course": "Exchange.course_id",
"course": "CourseDirectory.course_id",
})

flags = {}
Expand Down Expand Up @@ -38,7 +38,7 @@ class CollectApp(NbGrader):
It must be unique for each instructor/course combination. To set it in
the config file add a line to the `nbgrader_config.py` file:
c.Exchange.course_id = 'phys101'
c.CourseDirectory.course_id = 'phys101'
To pass the `course_id` at the command line, add `--course=phys101` to any
of the below commands.
Expand Down
2 changes: 1 addition & 1 deletion nbgrader/apps/dbapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class DbBaseApp(NbGrader):
def start(self):
if sys.platform != 'win32':
lister = ExchangeList(coursedir=self.coursedir, parent=self)
self.course_id = lister.course_id
self.course_id = self.coursedir.course_id
else:
self.course_id = ''
super(DbBaseApp, self).start()
Expand Down
4 changes: 2 additions & 2 deletions nbgrader/apps/exportapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
'exporter': 'ExportApp.plugin_class',
'assignment' : 'ExportPlugin.assignment',
'student': 'ExportPlugin.student',

'course': 'CourseDirectory.course_id'
}
flags = {}

Expand Down Expand Up @@ -75,5 +75,5 @@ def _classes_default(self):
def start(self):
super(ExportApp, self).start()
self.init_plugin()
with Gradebook(self.coursedir.db_url) as gb:
with Gradebook(self.coursedir.db_url, self.coursedir.course_id) as gb:
self.plugin_inst.export(gb)
2 changes: 1 addition & 1 deletion nbgrader/apps/fetchapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
aliases.update(nbgrader_aliases)
aliases.update({
"timezone": "Exchange.timezone",
"course": "Exchange.course_id",
"course": "CourseDirectory.course_id",
})

flags = {}
Expand Down
2 changes: 1 addition & 1 deletion nbgrader/apps/listapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
aliases.update(nbgrader_aliases)
aliases.update({
"timezone": "Exchange.timezone",
"course": "Exchange.course_id",
"course": "CourseDirectory.course_id",
})

flags = {}
Expand Down
8 changes: 4 additions & 4 deletions nbgrader/apps/quickstartapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,16 @@ class QuickStartApp(NbGrader):
nbgrader quickstart course101
Note that this class name need not necessarily be the same as the
`Exchange.course_id` configuration option, however by default, the
quickstart command will set `Exchange.course_id` to be the name you give
`CourseDirectory.course_id` configuration option, however by default, the
quickstart command will set `CourseDirectory.course_id` to be the name you give
on the command line. If you want to use a different folder name, go
ahead and just provide the name of the folder where your class files
will be stored, e.g.:
nbgrader quickstart "World Music"
and then after running the quickstart commmand, you can edit the
`nbgrader_config.py` file to change `Exchange.course_id`.
`nbgrader_config.py` file to change `CourseDirectory.course_id`.
"""

Expand Down Expand Up @@ -138,7 +138,7 @@ def start(self):
"""
# You only need this if you are running nbgrader on a shared
# server set up.
c.Exchange.course_id = "{}"
c.CourseDirectory.course_id = "{}"
# Update this list with other assignments you want
c.CourseDirectory.db_assignments = [dict(name="ps1")]
Expand Down
4 changes: 2 additions & 2 deletions nbgrader/apps/releaseapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
aliases.update(nbgrader_aliases)
aliases.update({
"timezone": "Exchange.timezone",
"course": "Exchange.course_id",
"course": "CourseDirectory.course_id",
})

flags = {}
Expand Down Expand Up @@ -44,7 +44,7 @@ class ReleaseApp(NbGrader):
unique for each instructor/course combination. To set it in the config
file add a line to the `nbgrader_config.py` file:
c.Exchange.course_id = 'phys101'
c.CourseDirectory.course_id = 'phys101'
To pass the `course_id` at the command line, add `--course=phys101` to any
of the below commands.
Expand Down
2 changes: 1 addition & 1 deletion nbgrader/apps/submitapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
aliases.update(nbgrader_aliases)
aliases.update({
"timezone": "Exchange.timezone",
"course": "Exchange.course_id",
"course": "CourseDirectory.course_id",
})

flags = {}
Expand Down
6 changes: 3 additions & 3 deletions nbgrader/converters/assign.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def __init__(self, coursedir=None, **kwargs):
super(Assign, self).__init__(coursedir=coursedir, **kwargs)

def _clean_old_notebooks(self, assignment_id, student_id):
with Gradebook(self.coursedir.db_url) as gb:
with Gradebook(self.coursedir.db_url, self.coursedir.course_id) as gb:
assignment = gb.find_assignment(assignment_id)
regexp = re.escape(os.path.sep).join([
self._format_source("(?P<assignment_id>.*)", "(?P<student_id>.*)", escape=True),
Expand Down Expand Up @@ -124,11 +124,11 @@ def init_assignment(self, assignment_id, student_id):
if 'name' in assignment:
del assignment['name']
self.log.info("Updating/creating assignment '%s': %s", assignment_id, assignment)
with Gradebook(self.coursedir.db_url) as gb:
with Gradebook(self.coursedir.db_url, self.coursedir.course_id) as gb:
gb.update_or_create_assignment(assignment_id, **assignment)

else:
with Gradebook(self.coursedir.db_url) as gb:
with Gradebook(self.coursedir.db_url, self.coursedir.course_id) as gb:
try:
gb.find_assignment(assignment_id)
except MissingEntry:
Expand Down
12 changes: 6 additions & 6 deletions nbgrader/converters/autograde.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ def init_assignment(self, assignment_id, student_id):
if 'id' in student:
del student['id']
self.log.info("Creating/updating student with ID '%s': %s", student_id, student)
with Gradebook(self.coursedir.db_url) as gb:
with Gradebook(self.coursedir.db_url, self.coursedir.course_id) as gb:
gb.update_or_create_student(student_id, **student)

else:
with Gradebook(self.coursedir.db_url) as gb:
with Gradebook(self.coursedir.db_url, self.coursedir.course_id) as gb:
try:
gb.find_student(student_id)
except MissingEntry:
Expand All @@ -94,7 +94,7 @@ def init_assignment(self, assignment_id, student_id):
raise NbGraderException(msg)

# make sure the assignment exists
with Gradebook(self.coursedir.db_url) as gb:
with Gradebook(self.coursedir.db_url, self.coursedir.course_id) as gb:
try:
gb.find_assignment(assignment_id)
except MissingEntry:
Expand All @@ -105,7 +105,7 @@ def init_assignment(self, assignment_id, student_id):
# try to read in a timestamp from file
src_path = self._format_source(assignment_id, student_id)
timestamp = self.coursedir.get_existing_timestamp(src_path)
with Gradebook(self.coursedir.db_url) as gb:
with Gradebook(self.coursedir.db_url, self.coursedir.course_id) as gb:
if timestamp:
submission = gb.update_or_create_submission(
assignment_id, student_id, timestamp=timestamp)
Expand Down Expand Up @@ -137,7 +137,7 @@ def init_assignment(self, assignment_id, student_id):

# ignore notebooks that aren't in the database
notebooks = []
with Gradebook(self.coursedir.db_url) as gb:
with Gradebook(self.coursedir.db_url, self.coursedir.course_id) as gb:
for notebook in self.notebooks:
notebook_id = os.path.splitext(os.path.basename(notebook))[0]
try:
Expand All @@ -155,7 +155,7 @@ def init_assignment(self, assignment_id, student_id):

# check for missing notebooks and give them a score of zero if they
# do not exist
with Gradebook(self.coursedir.db_url) as gb:
with Gradebook(self.coursedir.db_url, self.coursedir.course_id) as gb:
assignment = gb.find_assignment(assignment_id)
for notebook in assignment.notebooks:
path = os.path.join(self.coursedir.format_path(
Expand Down
17 changes: 17 additions & 0 deletions nbgrader/coursedir.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,23 @@

class CourseDirectory(LoggingConfigurable):

course_id = Unicode(
'',
help=dedent(
"""
A key that is unique per instructor and course. This can be
specified, either by setting the config option, or using the
--course option on the command line.
"""
)
).tag(config=True)

@validate('course_id')
def _validate_course_id(self, proposal):
if proposal['value'].strip() != proposal['value']:
self.log.warning("course_id '%s' has trailing whitespace, stripping it away", proposal['value'])
return proposal['value'].strip()

student_id = Unicode(
"*",
help=dedent(
Expand Down
2 changes: 1 addition & 1 deletion nbgrader/docs/source/api/high_level_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ assignments. For example:
# create a custom config object to specify options for nbgrader
config = Config()
config.Exchange.course_id = "course101"
config.CourseDirectory.course_id = "course101"
api = NbGraderAPI(config=config)
Expand Down
10 changes: 5 additions & 5 deletions nbgrader/docs/source/user_guide/managing_assignment_files.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"\n",
"c = get_config()\n",
"\n",
"c.Exchange.course_id = \"example_course\"\n",
"c.CourseDirectory.course_id = \"example_course\"\n",
"c.Exchange.root = \"/tmp/exchange\""
]
},
Expand Down Expand Up @@ -283,7 +283,7 @@
"\n",
"c = get_config()\n",
"c.Exchange.root = '/tmp/exchange'\n",
"c.Exchange.course_id = \"example_course\""
"c.CourseDirectory.course_id = \"example_course\""
]
},
{
Expand Down Expand Up @@ -558,7 +558,7 @@
"\n",
"c = get_config()\n",
"c.Exchange.root = '/tmp/exchange'\n",
"c.Exchange.course_id = \"example_course\""
"c.CourseDirectory.course_id = \"example_course\""
]
}
],
Expand Down Expand Up @@ -791,7 +791,7 @@
"\n",
"c = get_config()\n",
"c.Exchange.root = '/tmp/exchange'\n",
"c.Exchange.course_id = \"example_course\"\n",
"c.CourseDirectory.course_id = \"example_course\"\n",
"c.ExchangeSubmit.strict = True"
]
},
Expand Down Expand Up @@ -876,7 +876,7 @@
"\n",
"c = get_config()\n",
"\n",
"c.Exchange.course_id = \"example_course\"\n",
"c.CourseDirectory.course_id = \"example_course\"\n",
"c.Exchange.root = \"/tmp/exchange\""
]
}
Expand Down
2 changes: 1 addition & 1 deletion nbgrader/docs/source/user_guide/philosophy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,6 @@ would live at ``{course_directory}/nbgrader_config.py`` and might look like:
::

c = get_config()
c.Exchange.course_id = "course101"
c.CourseDirectory.course_id = "course101"

There are many additional options you can configure. See :doc:`/configuration/config_options` for a full list.
8 changes: 4 additions & 4 deletions nbgrader/exchange/collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ def _sort_by_timestamp(self, records):
return sorted(records, key=lambda item: item['timestamp'], reverse=True)

def init_src(self):
if self.course_id == '':
if self.coursedir.course_id == '':
self.fail("No course id specified. Re-run with --course flag.")

self.course_path = os.path.join(self.root, self.course_id)
self.course_path = os.path.join(self.root, self.coursedir.course_id)
self.inbound_path = os.path.join(self.course_path, 'inbound')
if not os.path.isdir(self.inbound_path):
self.fail("Course not found: {}".format(self.inbound_path))
Expand All @@ -59,12 +59,12 @@ def copy_files(self):
if len(self.src_records) == 0:
self.log.warning("No submissions of '{}' for course '{}' to collect".format(
self.coursedir.assignment_id,
self.course_id))
self.coursedir.course_id))
else:
self.log.info("Processing {} submissions of '{}' for course '{}'".format(
len(self.src_records),
self.coursedir.assignment_id,
self.course_id))
self.coursedir.course_id))

for rec in self.src_records:
student_id = rec['username']
Expand Down
17 changes: 0 additions & 17 deletions nbgrader/exchange/exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,6 @@ class ExchangeError(Exception):

class Exchange(LoggingConfigurable):

course_id = Unicode(
'',
help=dedent(
"""
A key that is unique per instructor and course. This MUST be
specified, either by setting the config option, or using the
--course option on the command line.
"""
)
).tag(config=True)

@validate('course_id')
def _validate_course_id(self, proposal):
if proposal['value'].strip() != proposal['value']:
self.log.warning("course_id '%s' has trailing whitespace, stripping it away", proposal['value'])
return proposal['value'].strip()

timezone = Unicode(
"UTC",
help="Timezone for recording timestamps"
Expand Down
Loading

0 comments on commit 4b7013a

Please sign in to comment.