nbgrader
nbgrader copied to clipboard
Open formgrader with a local configuration file
This PR aims to open formgrader with a configuration file (nbgrader_config.py) from the local directory.
Currently, the formgrader loads the nbgrader_config.py files from:
- the directories in
jupyter_config_path - the directory where Jupyter lab started:
os.cwd() - the directory
CourseDirectory.root(which can be configured by one of the previous files)
With this PR, it will be possible to start the Formgrader with a config file in the curent directory in lab filebrowser, by using the new menu entry Formgrader (local).
It will reinitialize the FormgradeExtension object with the additional configuration of the current directory.
In this case, the configuration file existing in the root directory of Jupyter lab app will not been loaded.
Using the classic menu entry Formgrader will restore the FormgradeExtension object with the initial configuration.
This feature is not enabled by default, and must be set by user in settings panel (or user settings file):
This PR also adds a command line configuration to display the current config in the formgrader UI: --FormgradeExtension.debug=true.
This can be helpful to test this PR (at least).
I tested it on a local jupyterlab server and using jupyterhub in docker (demo multiple classes), but I think it must be tested in some real environments to ensure it does not break any existing behavior.
** CAUTION **
- it is probably not usable if several users access the same jupyterlab server, as it modifies the
FormgradeExtensionobject on the server. - if one of the config file provides a
CourseDirectory.rootconfiguration (which is the case on jupyterhub AFAIK), this parameter must be overwritten in the local config file. This is intentional, we don't silently remove certain parameters from the loaded files, we just change the files that are loaded.
cc. @nthiery
Excellent! Our next project to grade is on February the 9th. So I have to test it seriously before that, and we will have more massive testing then :-)
Tiny update: the debug flag is actually --FormgradeExtension.debug=true
I just tried this branch on my machine. In my home directory ~/, I have a subdirectory ~/C
for one of my courses. I
- launched jupyter lab from my home directory using
--FormgradeExtension.debug=True, - navigated to
~/Cin jupyterlab's file navigator - activated the feature in the settings panel
- opened the local formgrader
- checked the nbgrader config
- navigated around in the formgraded.
All of this went smoothly :-)
However, when going to Grade manually -> AssignmentXX, I get 'No data available in table'. Whereas if I launch jupyter lab from ~/C, and do the same with the formgrader or local form grader, I do see my student's submissions.
For the record, another difference is that the current configuration is displayed in a long single line in the second case, and properly line wrapped and indented in the first case.
I am not sure how to proceed to debug further.
In case this can help, I am available tomorrow starting from 10:30 for live debugging.
Cheers,
Tiny update: the debug flag is actually
--FormgradeExtension.debug=true
Thanks, I updated the description.
Ok, I found the issue and a workaround. In my nbgrader_config.py,
the path of the gradebook is configured relatively to the current directory:
c.CourseDirectory.db_url = 'sqlite:///.gradebook.db'
However the formgrader apparently fetches the gradebook from ~/.gradebook
instead of ~/C/.gradebook. If instead I set:
c.CourseDirectory.db_url = 'sqlite:///C/.gradebook.db'
then I can see my student's submissions.
Another issue: if RTC is enabled, then the local formgrader seems to be opened with the URL
http://localhost:8888/formgrader?path=RTC C
Forcing the url:
http://localhost:8888/formgrader?path=C
works around this.
Aside from this, it seems at this stage completely functional. I'll grade my assignment and report again in case I stumble on anything else.
Hello @brichet,
After experimenting, I confirm that the workaround we discussed this morning about paths relative to the course root in db_url works. For the record, here is what I inserted in my nbgrader_config.py:
import os
server_root = os.getcwd()
course_root = os.path.dirname(__file__)
course_root = os.path.relpath(course_root, server_root)
c.CourseDirectory.db_url = f'sqlite:///{course_root}/.gradebook.db'
Ideally, we could make the idiom into:
c.CourseDirectory.db_url = f'sqlite:///{c.CourseDirectory.root}/.gradebook.db'
And then it would only be a question of documenting it together with the feature of opening locally the formgrader.
@nthiery I haven't found a way to retrieve the config from the config file.
The Config object c seems to be always empty when the config file is executed. I don't know if this is expected or not.
Ok, too bad. Thanks for trying out!
For the record, the trick above worked smoothly while I graded a bunch of notebooks. So, at this stage, I suggest to:
- Document the trick and get this ticket merged.
- Think about another way of having a short hand, in a potential follow up ticket.
Failures seems to be related to incompatibility between pytest 8.1.0 and nbval 0.10.0
https://github.com/computationalmodelling/nbval/issues/202
https://github.com/computationalmodelling/nbval/pull/203
Hi @brichet,
For the record: in fact absolute paths work for the gradebook. This is a bit simpler, and in fact slightly more robust, in case the course root is not a subdirectory of the server root. Yes, I thought this could not happen, but I actually encountered this today ... probably a bug of our server. Anyway, here is the updated trick for the nbgraderconfig.py:
import os
course_root = os.path.dirname(__file__)
c.CourseDirectory.db_url = f'sqlite:///{course_root}/.gradebook.db'
I don't have something solid to report yet, but it seems that there is some hidden state somewhere. If a local formgrader is loaded once with formgrader?path=foo, opening it again with formgrader?path=bar still reloads the configuration from foo. It might even persist across sessions (???).
We have a grading session this afternoon, so I'll try to use the occasion to analyse further. Let me know if you manage to reproduce it.
I don't have something solid to report yet, but it seems that there is some hidden state somewhere. If a local formgrader is loaded once with
formgrader?path=foo, opening it again withformgrader?path=barstill reloads the configuration fromfoo. It might even persist across sessions (???).We have a grading session this afternoon, so I'll try to use the occasion to analyse further. Let me know if you manage to reproduce it.
@nthiery I can't reproduce it. Were you able to reproduce it ? If so, are there any error messages in the terminal ?
No haven't been able to reproduce it lately. So I'll assume it was related to our server having a misconfigured server root. Sorry for the noise and thanks for checking!
Thanks for the feedback @nthiery.
- Scrap the "local formgrader" item in the global menu
What is the motivation to remove it? It is only a shortcut to avoid using the URL, and it explicitly shows that we can open formgrader with different settings.
and the configuration option to activate it.
I like the idea of keeping it intentional, as it changes the server configuration when used. This setting should not be used if several users are using on the same Jupyterlab server. Maybe some feedback from other usage of nbgrader could help.
- Enable the ?path=... also for subpaths of the formgrader. E.g. /formgrader/grading/?path=...
I'll see if there is an easy way to handle it.
- Scrap the optional command line option "--FormgradeExtension.debug=true
Let's set it to true by default, so that people can disable it.
motivation to remove it
That's with the alternate UI (activity in the launcher) in mind to avoid having two UI's for the same action. It could be left there until the alternate UI is implemented, but then users will learn it and have to unlearn it.
several users on the same Jupyterlab server
To make sure I get the technical details right: you could actually have two users use the local formgrader on the same JupyterLab server; but only if this is in the same local directory, right? That there are one or several users does not make a difference, except of course that it's easier to coordinate with just yourself than with someone else :-)
It seems to me that launching the formgrader from the URL with a path argument, or through the activity in the launcher, is quite intentional. Of course, that's only reasonable if there can be some security check, with an error if opening a formgrader while another formgrader is already in use with another path. For the "activity in the launcher" UI, it would be nice if the activity would be grayed out if there is another formgrader running with a different path.
Optional command line option with default to true
Yes, that works too.
To make sure I get the technical details right: you could actually have two users use the local formgrader on the same JupyterLab server; but only if this is in the same local directory, right?
This is right. Indeed, if the users open formgrader in the same directory it will work.
But there is only one Formgrader object on the server side, which is now configured on the fly.
This is more flexible, but also less safe, depending on the use.
Let's take an example:
- User1 opens formgrader from directory A →
Formgraderobject is configured according to nbgrader_config.py in directory A - User2 opens formgrader globally (or from directory B) →
Formgraderobject is configured according to global nbgrader_config.py file (or the one in directory B) - User1 also get the global config (or the directory B one) without knowing. Behavior will be rather unstable for him.
How to fix it ?
We could manage several Formgrader objects on the server (probably one per user, or one per config).
Or we could manage the current connected (and active) clients, to disallow users to open an other configuration if one is in use (as you proposed IIUC).
I'd advocate the first solution, but it will require (much?) more work, and could be done in a later PR. As it stands, it's probably safer to keep it as optional, and add a warning about using it with multiple users on the same Jupyterlab instance.
Thanks for the confirmation!
Agreed the first solution is definitely the proper solution and we should eventually have it. Presumably the proper granularity is one configuration object per directory on the server (with lazyness: the configuration is only created if a formagrader is open with that directory); I guess that's what you meant by "one per config".
Agreed also that the current solution is just temporary, so it's not worth investing a lot of energy polishing/hardening it, let alone discussing it :-) Also, presumably it will be a rare event that people will use local configuration on a shared jupyter server. With that in mind, I let you finalize this PR as you see fit. If some of the hardening actions (like warning against already running sessions with different config) are trivial to implement, that's great. Otherwise that's fine too!
Hi @brichet ! A quick update: we have been using this branch smoothly this semester and it worked great. That was much more robust. Thank you so much for your work on it!
Yesterday, we made a few tests with 2-3 other courses, and updated the dashboard in Travo to use it. With that, we plan to use it systematically next semester. If we could move forward and get this branch merged, that would be great so that we could use a stock nbgrader!
What would remain to be done?
Thanks for the live deployment testing and your feedback @nthiery, glad to hear it's pretty robust. Let me check again next week to merge and release.
Thanks for the progress!
Just for information: I tried to install the latest version with:
pip install git+https://github.com/brichet/nbgrader.git@local_formgrader
This used to work last time I tried. However now the nbgrader menu does not appear when launching JupyterLab, and I see the following error in the logs:
[W 2024-06-17 19:40:58.076 ServerApp] 404 GET /lab/extensions/@jupyter/nbgrader/static/remoteEntry.f76bf1ceccb4822da7d7.js ([email protected]) 24.29ms referer=http://localhost:8889/lab
I also tried a developer install following the nbgrader doc. It worked, up to one point: I had to install manually the schema file nbgrader/labextension/schemas/@jupyter/nbgrader/formgrader.json.
Cheers,
I have the same issue, I think it is related to https://github.com/jupyter/nbgrader/pull/1875
For information: I installed with pip the current version of the branch, and it seems to work smoothly. Thank you!
This used to work last time I tried. However now the nbgrader menu does not appear when launching JupyterLab, and I see the following error in the logs:
It should be fixed now
EDIT: I haven't seen your previous message.
Thanks again @nthiery for suggestions and feedback
@nthiery FYI it has been released in version 0.9.3
Yiiah!!! That was quite a sprint. Thank you so much. Will install it right away!