Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move all scope parsing to 'experimental' #752

Merged
merged 18 commits into from
Aug 3, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ repos:
rev: v2.2.4
hooks:
- id: codespell
args: ["--ignore-regex", "https://[^\\s]*"]

# custom local hooks
- repo: local
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* Introduce an experimental Globus Auth scope parser in
``globus_sdk.experimental.scope_parser``.
Full usage is documented in the SDK Experimental docs. (:pr:`NUMBER`)
1 change: 1 addition & 0 deletions docs/experimental/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ Globus SDK Experimental Components
:caption: Contents
:maxdepth: 1

scope_parser
35 changes: 35 additions & 0 deletions docs/experimental/scope_parser.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.. _experimental_scope_parser:

Scope Parser
============

.. currentmodule:: globus_sdk.experimental.scope_parser

This component defines a ``Scope`` object and exposes use of a parser which can
parse scope strings into trees of ``Scope`` objects.
It should be regarded as very similar to the existing ``MutableScope`` object in
``globus_sdk.scopes``. Key differences from ``MutableScope``:

- ``Scope.parse`` is available, for parsing scopes from strings
- The Globus SDK does not support using ``Scope`` in all of the locations where
``MutableScope`` is supported -- Scope objects must be stringified for use
- ``Scope`` objects define a ``__contains__`` method, allowing one to check if one scope
properly contains another

.. note::

The scope trees produced by parsing represent prospective consent structures as
would be produced by a single authentication flow in Auth. No external APIs (e.g.,
the Get Consents API) are used to validate or mutate the data.

Reference
---------

.. autoclass:: Scope
:members:
:member-order: bysource
:special-members:

.. autoclass:: ScopeParseError

.. autoclass:: ScopeCycleError
6 changes: 0 additions & 6 deletions src/globus_sdk/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

if t.TYPE_CHECKING:
from globus_sdk.scopes import MutableScope
from globus_sdk.scopes.scope_definition import Scope

# these types are aliases meant for internal use
IntLike = t.Union[int, str]
Expand All @@ -21,15 +20,10 @@

ScopeCollectionType = t.Union[
str,
"Scope",
"MutableScope",
t.Iterable[str],
t.Iterable["Scope"],
t.Iterable["MutableScope"],
t.Iterable[t.Union[str, "Scope", "MutableScope"]],
t.Iterable[t.Union[str, "Scope"]],
t.Iterable[t.Union[str, "MutableScope"]],
t.Iterable[t.Union["Scope", "MutableScope"]],
]


Expand Down
8 changes: 8 additions & 0 deletions src/globus_sdk/experimental/scope_parser/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from .errors import ScopeCycleError, ScopeParseError
from .scope_definition import Scope

__all__ = (
"Scope",
"ScopeParseError",
"ScopeCycleError",
)
62 changes: 62 additions & 0 deletions src/globus_sdk/experimental/scope_parser/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import sys
import timeit
import warnings

from ._parser import parse_scope_graph
kurtmckee marked this conversation as resolved.
Show resolved Hide resolved

warnings.warn(
"This is a test module for scope parsing. It is not intended for public use.",
stacklevel=1,
)


def timeit_test() -> None:
for scope_depth, num_iterations in (
(10, 1000),
(100, 1000),
(1000, 1000),
(2000, 100),
(3000, 100),
(4000, 100),
(5000, 100),
):
setup = f"""\
from globus_sdk.experimental.scope_parser import Scope
big_scope = ""
for i in range({scope_depth}):
big_scope += f"foo{{i}}["
big_scope += "bar"
for _ in range({scope_depth}):
big_scope += "]"
"""

time_taken = timeit.timeit(
"Scope.deserialize(big_scope)", setup=setup, number=num_iterations
)
average = time_taken / num_iterations
print(f"{num_iterations} runs, {scope_depth} depth, avg time taken: {average}")


def parse_test(scope_string: str) -> None:
parsed_graph = parse_scope_graph(sys.argv[1])
print(
"top level scopes:",
", ".join([name for name, _optional in parsed_graph.top_level_scopes]),
)
print(parsed_graph)


def main():
if len(sys.argv) < 2 or sys.argv[1] in ("-h", "--help"):
print("This script supports two usage patterns:")
print(" python -m globus_sdk.experimental.scope_parser SCOPE_STRING")
print(" python -m globus_sdk.experimental.scope_parser --timeit")
sys.exit(0)

if sys.argv[1] == "--timeit":
timeit_test()
else:
parse_test(sys.argv[1])


main()
kurtmckee marked this conversation as resolved.
Show resolved Hide resolved
Loading
Loading