    def revoke(cls, db, spawner, share_with, scopes=None):
        """Revoke permissions for share_with on `spawner`

        If scopes are not specified, all scopes are revoked
        """
        share = cls.find(db, spawner, share_with)
        if share is None:
            _log_name = cls._get_log_name(spawner, share_with)
            app_log.info(f"No permissions to revoke from {_log_name}")
            return
        else:
            _log_name = share._log_name

        if scopes is None:
            app_log.info(f"Revoked all permissions from {_log_name}")
            db.delete(share)
            db.commit()
            return None

        # update scopes
        new_scopes = [scope for scope in share.scopes if scope not in scopes]
        revoked_scopes = [scope for scope in scopes if scope in set(share.scopes)]
        if new_scopes == share.scopes:
            app_log.info(f"No change in scopes for {_log_name}")
            return share
        elif not new_scopes:
            # revoked all scopes, delete the Share
            app_log.info(f"Revoked all permissions from {_log_name}")
            db.delete(share)
            db.commit()
        else:
            app_log.info(f"Revoked {revoked_scopes} from {_log_name}")
            share.scopes = new_scopes
            db.commit()

        if new_scopes:
            return share
        else:
            return None
Revoke permissions for share_with on `spawner`

If scopes are not specified, all scopes are revoked
jupyterhub/orm.py