Modify course list menu nbgrader (z2jh)


I am using nbgrader together with z2jh for multiple courses where each course has its own configuration (GPU, CPU, RAM, docker image, etc.). Each user (students & instructors) may be registered in multiple courses, therefore to spawn the correct course & its configuration, before spawning their pod I ask them within options_form to choose their course. then in the pre_spawn_hook I use user_options to spawn the correct course. But within the nbgrader assignment list (as shown in the attached picture) they have still the possibility to change the course (while spawner is spun for another course!).

I was wondering how I can avoid this. how can I override the function in nbgrader that generates this dropdown courselist menu? how can I pass the correct courses to this menu?

the picture shows that two courses (pyf1 & pyf2) are visible in the course list menu while only pyf1 (which the user has chosen in the options_form) should be visible.


it seems to me that the function get_student_courses in nbgrader/nbgrader/auth/ (nbgrader/nbgrader/auth/ at 12136c2eccde44ca7a86b7805e240a406704cb74 · jupyter/nbgrader · GitHub) is responsible for listing courses of a student ???

class Authenticator(LoggingConfigurable):

    plugin_class = Type(
        help="A plugin for different authentication methods."

    plugin = Instance(BaseAuthPlugin).tag(config=False)

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, **kwargs)
        self.log.debug("Using authenticator: %s", self.plugin_class.__name__)
        self.plugin = self.plugin_class(parent=self)

    def get_student_courses(self, student_id: str) -> Optional[list]:
        """Gets the list of courses that the student is enrolled in.

            The unique id of the student.

        A list of unique course ids, or None. If None is returned this means
        that the student has access to any course that might exist. Otherwise
        the student is only allowed access to the specific courses returned in
        the list.

        return self.plugin.get_student_courses(student_id)

or get_student_courses in JupyterHubAuthPlugin (nbgrader/nbgrader/auth/ at 12136c2eccde44ca7a86b7805e240a406704cb74 · jupyter/nbgrader · GitHub)

class JupyterHubAuthPlugin(BaseAuthPlugin):

    def get_student_courses(self, student_id: str) -> Optional[list]:
        if student_id == "*":
            student_id = "{authenticated_user}"
        response = None
            response = _query_jupyterhub_api('GET', '/users/%s' % student_id)
        except JupyterhubEnvironmentError: # Should only go here if we are not running on Jupyterhub.
  'Not running on Jupyterhub, not able to GET Jupyterhub user')
        except JupyterhubApiError: # Should only go here if the api_token is invalid.
            self.log.error("Error: Not able to get Jupyterhub user: " + student_id)
            self.log.error("Make sure you start your service with a valid admin_user 'api_token' in your Jupyterhub config")
        courses = set()
        for group in response['groups']:
            if group.startswith('nbgrader-') or group.startswith('formgrade-'):
                course = group.split('-', 1)[1]
                if course:
        return list(courses)

Could someone please explain this part self.plugin = self.plugin_class(parent=self)? I don’t have any familiarity with types & traitlets. Would it be possible to override this function? how & where?