def expand_scopes(scopes, owner=None, oauth_client=None):
    """Returns a set of fully expanded scopes for a collection of raw scopes

    Arguments:
      scopes (collection(str)): collection of raw scopes
      owner (obj, optional): orm.User or orm.Service as owner of orm.APIToken
          Used for expansion of metascopes such as `self`
          and owner-based filters such as `!user`
      oauth_client (obj, optional): orm.OAuthClient
          The issuing OAuth client of an API token.

    Returns:
      expanded scopes (set): set of all expanded scopes, with filters applied for the owner
    """
    expanded_scopes = set(chain.from_iterable(map(_expand_scope, scopes)))

    filter_replacements = {
        "user": None,
        "service": None,
        "server": None,
    }
    user_name = None
    if isinstance(owner, orm.User):
        user_name = owner.name
        filter_replacements["user"] = f"user={user_name}"
    elif isinstance(owner, orm.Service):
        filter_replacements["service"] = f"service={owner.name}"

    if oauth_client is not None:
        if oauth_client.service is not None:
            filter_replacements["service"] = f"service={oauth_client.service.name}"
        elif oauth_client.spawner is not None:
            spawner = oauth_client.spawner
            filter_replacements["server"] = f"server={spawner.user.name}/{spawner.name}"

    for scope in expanded_scopes.copy():
        base_scope, _, filter = scope.partition('!')
        if filter in filter_replacements:
            # translate !user into !user={username}
            # and !service into !service={servicename}
            # and !server into !server={username}/{servername}
            expanded_scopes.remove(scope)
            expanded_filter = filter_replacements[filter]
            if expanded_filter:
                # translate
                expanded_scopes.add(f'{base_scope}!{expanded_filter}')
            else:
                warnings.warn(
                    f"Not expanding !{filter} filter without target {filter} in {scope}",
                    stacklevel=3,
                )

    if 'self' in expanded_scopes:
        expanded_scopes.remove('self')
        if user_name:
            expanded_scopes |= _expand_self_scope(user_name)
        else:
            warnings.warn(
                f"Not expanding 'self' scope for owner {owner} which is not a User",
                stacklevel=3,
            )

    # reduce to discard overlapping scopes
    # return immutable frozenset because the result is cached
    return frozenset(reduce_scopes(expanded_scopes))
Returns a set of fully expanded scopes for a collection of raw scopes

Arguments:
scopes (collection(str)): collection of raw scopes
owner (obj, optional): orm.User or orm.Service as owner of orm.APIToken
Used for expansion of metascopes such as `self`
and owner-based filters such as `!user`
oauth_client (obj, optional): orm.OAuthClient
The issuing OAuth client of an API token.

Returns:
expanded scopes (set): set of all expanded scopes, with filters applied for the owner
jupyterhub/scopes.py