Unexpected behavior in spawner z2jh


I noticed an unexpected behavior in the way users and groups are managed in spawner. You can confirm that in pre_spawn_hook for example.

def pre_spawn_hook(spawner):
    user = spawner.user
    groups = spawner.user.groups
    for group in groups:
        print(user in group.users)  # gives False 
        print([user == u for u in group.users]) # the same, all are False
        # each user in groups.users has again groups and so on

That means copies of users are stored in group.users but Why? is it done like this for a reason? or seems like a bug!


There are 2 kinds of User objects. Spawner.user is a high-level wrapper object (jupyterhub.user.User), while group.users is an sqlalchemy relationship (jupyterhub.orm.User). The wrapper instance has the orm instance as self.orm_user, so spawner.user.orm_user in group.users will be True.

Eventually (I don’t know when I will get to it), Spawners will lose all access to the database, which will mean no more ORM objects, only static, read-only copies of user and group info.

1 Like