Source code for globus_sdk.scopes.scope_definition

"""
This defines the Scope object and the scope parser.
Because these components are mutually dependent, it's easiest if they're kept in a
single module.
"""
from __future__ import annotations

import typing as t
import warnings

from globus_sdk._types import ScopeCollectionType


def _iter_scope_collection(obj: ScopeCollectionType) -> t.Iterator[str]:
    if isinstance(obj, str):
        yield obj
    elif isinstance(obj, MutableScope):
        yield str(obj)
    else:
        for item in obj:
            yield str(item)


# TODO: rename MutableScope to Scope
[docs] class MutableScope: """ A scope object is a representation of a scope which allows modifications to be made. In particular, it supports handling scope dependencies via ``add_dependency``. `str(MutableScope(...))` produces a valid scope string for use in various methods. :param scope_string: The string which will be used as the basis for this Scope :type scope_string: str :param optional: The scope may be marked as optional. This means that the scope can be declined by the user without declining consent for other scopes :type optional: bool """ def __init__( self, scope_string: str, *, optional: bool = False, dependencies: list[MutableScope] | None = None, ) -> None: if any(c in scope_string for c in "[]* "): raise ValueError( "MutableScope instances may not contain the special characters '[]* '." ) self.scope_string = scope_string self.optional = optional self.dependencies: list[MutableScope] = ( [] if dependencies is None else dependencies ) def serialize(self) -> str: base_scope = ("*" if self.optional else "") + self.scope_string if not self.dependencies: return base_scope return ( base_scope + "[" + " ".join(c.serialize() for c in self.dependencies) + "]" )
[docs] def add_dependency( self, scope: str | MutableScope, *, optional: bool | None = None, ) -> MutableScope: """ Add a scope dependency. The dependent scope relationship will be stored in the Scope and will be evident in its string representation. :param scope: The scope upon which the current scope depends :type scope: str :param optional: Mark the dependency an optional one. By default it is not. An optional scope dependency can be declined by the user without declining consent for the primary scope :type optional: bool, optional """ if optional is not None: if isinstance(scope, MutableScope): raise ValueError( "cannot use optional=... with a MutableScope object as the " "argument to add_dependency" ) warnings.warn( "Passing 'optional' to add_dependency is deprecated. " "Construct an optional MutableScope object instead.", DeprecationWarning, stacklevel=2, ) scopeobj = MutableScope(scope, optional=optional) else: if isinstance(scope, str): scopeobj = MutableScope(scope) else: scopeobj = scope self.dependencies.append(scopeobj) return self
def __repr__(self) -> str: parts: list[str] = [f"'{self.scope_string}'"] if self.optional: parts.append("optional=True") if self.dependencies: parts.append(f"dependencies={self.dependencies!r}") return "MutableScope(" + ", ".join(parts) + ")" def __str__(self) -> str: return self.serialize()
[docs] @staticmethod def scopes2str(obj: ScopeCollectionType) -> str: """ Given a scope string, a collection of scope strings, a MutableScope object, a collection of MutableScope objects, or a mixed collection of strings and Scopes, convert to a string which can be used in a request. :param obj: The object or collection to convert to a string :type obj: str, MutableScope, iterable of str or MutableScope """ return " ".join(_iter_scope_collection(obj))