-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #752 from sirosen/add-experimental-scope-parsing
Move all scope parsing to 'experimental'
- Loading branch information
Showing
14 changed files
with
1,028 additions
and
599 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
changelog.d/20230719_164657_sirosen_add_experimental_scope_parsing.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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`) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,3 +16,4 @@ Globus SDK Experimental Components | |
:caption: Contents | ||
:maxdepth: 1 | ||
|
||
scope_parser |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
from __future__ import annotations | ||
|
||
import sys | ||
import timeit | ||
import warnings | ||
|
||
from ._parser import parse_scope_graph | ||
|
||
warnings.warn( | ||
"This is a test module for scope parsing. It is not intended for public use.", | ||
stacklevel=1, | ||
) | ||
|
||
|
||
def timeit_test() -> None: | ||
for size, num_iterations, style in ( | ||
(10, 1000, "deep"), | ||
(100, 1000, "deep"), | ||
(1000, 1000, "deep"), | ||
(2000, 100, "deep"), | ||
(3000, 100, "deep"), | ||
(4000, 100, "deep"), | ||
(5000, 100, "deep"), | ||
(5000, 1000, "wide"), | ||
(10000, 1000, "wide"), | ||
): | ||
if style == "deep": | ||
setup = f"""\ | ||
from globus_sdk.experimental.scope_parser import Scope | ||
big_scope = "" | ||
for i in range({size}): | ||
big_scope += f"foo{{i}}[" | ||
big_scope += "bar" | ||
for _ in range({size}): | ||
big_scope += "]" | ||
""" | ||
elif style == "wide": | ||
setup = f"""\ | ||
from globus_sdk.experimental.scope_parser import Scope | ||
big_scope = "" | ||
for i in range({size}): | ||
big_scope += f"foo{{i}} " | ||
""" | ||
else: | ||
raise NotImplementedError | ||
|
||
timer = timeit.Timer("Scope.parse(big_scope)", setup=setup) | ||
|
||
raw_timings = timer.repeat(repeat=5, number=num_iterations) | ||
best, worst, average, variance = _stats(raw_timings) | ||
if style == "deep": | ||
print(f"{num_iterations} runs on a deep scope, depth={size}") | ||
elif style == "wide": | ||
print(f"{num_iterations} runs on a wide scope, width={size}") | ||
else: | ||
raise NotImplementedError | ||
print(f" best={best} worst={worst} average={average} variance={variance}") | ||
print(f" normalized best={best / num_iterations}") | ||
print() | ||
print("The most informative stat over these timings is the min timing (best).") | ||
print("Normed best is best/iterations.") | ||
print( | ||
"Max timing (worst) and dispersion (variance vis-a-vis average) indicate " | ||
"how consistent the results are, but are not a report of speed." | ||
) | ||
|
||
|
||
def _stats(timing_data: list[float]) -> tuple[float, float, float, float]: | ||
best = min(timing_data) | ||
worst = max(timing_data) | ||
average = sum(timing_data) / len(timing_data) | ||
variance = sum((x - average) ** 2 for x in timing_data) / len(timing_data) | ||
return best, worst, average, variance | ||
|
||
|
||
def parse_test(scope_string: str) -> None: | ||
parsed_graph = parse_scope_graph(scope_string) | ||
print( | ||
"top level scopes:", | ||
", ".join([name for name, _optional in parsed_graph.top_level_scopes]), | ||
) | ||
print(parsed_graph) | ||
|
||
|
||
def main() -> None: | ||
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) | ||
|
||
print() | ||
if sys.argv[1] == "--timeit": | ||
timeit_test() | ||
else: | ||
parse_test(sys.argv[1]) | ||
|
||
|
||
main() |
Oops, something went wrong.