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

Release/0.13.0rc2 #103

Merged
merged 20 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
49b1c5e
Merge pull request #94 from globus/production
sirosen Jul 24, 2023
a2bf486
Enforce doc build requirements; add Read the Docs config
kurtmckee Aug 17, 2023
73c9d41
Merge pull request #95 from globus/fix-read-the-docs-builds
kurtmckee Aug 17, 2023
532c132
Update the black pre-commit hook URL
kurtmckee Sep 11, 2023
7c78c5b
Merge pull request #96 from globus/update-black-pre-commit-url
kurtmckee Sep 11, 2023
9df3f58
[pre-commit.ci] pre-commit autoupdate
pre-commit-ci[bot] Sep 12, 2023
1635be9
Merge pull request #97 from globus/pre-commit-ci-update-config
sirosen Sep 12, 2023
2b3895c
Drop Python 3.7 support; escalate test warnings to errors
kurtmckee Sep 15, 2023
4ab8a36
Merge pull request #98 from globus/drop-python-3.7
kurtmckee Sep 15, 2023
d181734
[pre-commit.ci] pre-commit autoupdate
pre-commit-ci[bot] Sep 19, 2023
aef11c9
Merge pull request #99 from globus/pre-commit-ci-update-config
kurtmckee Sep 19, 2023
4896cdd
[pre-commit.ci] pre-commit autoupdate
pre-commit-ci[bot] Sep 26, 2023
1021136
Merge pull request #100 from globus/pre-commit-ci-update-config
kurtmckee Sep 26, 2023
8012078
[pre-commit.ci] pre-commit autoupdate
pre-commit-ci[bot] Oct 3, 2023
3985fb0
Merge pull request #101 from globus/pre-commit-ci-update-config
kurtmckee Oct 3, 2023
4040055
Support Python 3.12; update min. Flask; fix test suite
kurtmckee Oct 3, 2023
30755c8
Merge pull request #102 from globus/fix-test-suite
kurtmckee Oct 3, 2023
972d01b
Resolve a slightly-reworded Python 3.12 deprecation warning
kurtmckee Oct 6, 2023
ee55a47
Update project metadata
kurtmckee Oct 6, 2023
835aed2
Add Python 3.12 testing to CI
kurtmckee Oct 6, 2023
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
17 changes: 11 additions & 6 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
id: "setup-python"
uses: "actions/setup-python@v4"
with:
python-version: "3.11"
python-version: "3.12"
cache: "pip"
cache-dependency-path: |
.github/workflows/ci.yaml
Expand Down Expand Up @@ -107,34 +107,39 @@ jobs:
os:
- name: "Linux"
value: "ubuntu-latest"
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
python-version:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
tox-extras: [""]

include:
# Test Windows.
- os:
name: "Windows"
value: "windows-latest"
python-version: "3.11"
python-version: "3.12"
tox-extras: ""

# Test Mac.
- os:
name: "Mac"
value: "macos-latest"
python-version: "3.11"
python-version: "3.12"
tox-extras: ""

# Test minimum dependencies.
- os:
name: "Linux"
value: "ubuntu-latest"
python-version: "3.7"
python-version: "3.8"
tox-extras: "-minimum_flask"
- os:
name: "Linux"
value: "ubuntu-latest"
python-version: "3.11"
python-version: "3.12"
tox-extras: "-minimum_flask"

steps:
Expand Down
11 changes: 9 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,15 @@ repos:
hooks:
- id: alphabetize-codeowners

- repo: https://github.com/psf/black
rev: 23.7.0
# Enforce Python 3.8+ idioms.
- repo: https://github.com/asottile/pyupgrade
rev: v3.14.0
hooks:
- id: pyupgrade
args: [--py38-plus]

- repo: https://github.com/psf/black-pre-commit-mirror
rev: 23.9.1
hooks:
- id: black

Expand Down
13 changes: 13 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: 2

build:
os: "ubuntu-22.04"
tools:
python: "3.11"

sphinx:
configuration: "docs/source/conf.py"

python:
install:
- requirements: "docs/requirements.txt"
21 changes: 21 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,27 @@ Unreleased changes are documented in files in the `changelog.d`_ directory.

.. scriv-insert-here

.. _changelog-0.13.0rc2:

0.13.0rc2 — 2023-10-06
======================

Python support
--------------

- Support Python 3.12.
- Drop support for Python 3.7.

Development
-----------

- Remove unused dependencies.

Dependencies
------------

- Raise the minimum Flask version to 2.3.0, which dropped support for Python 3.7.

.. _changelog-0.13.0rc1:

0.13.0rc1 — 2023-07-24
Expand Down
3 changes: 2 additions & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
sphinx_material
sphinx==7.2.1
sphinx_material==0.0.35
28 changes: 15 additions & 13 deletions globus_action_provider_tools/authentication.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import logging
from time import time
from typing import FrozenSet, Iterable, List, Optional, Union, cast
Expand Down Expand Up @@ -26,7 +28,7 @@ def identity_principal(id_: str) -> str:
return f"urn:globus:auth:identity:{id_}"


class AuthState(object):
class AuthState:
# Cache for introspection operations, max lifetime: 30 seconds
introspect_cache: TTLCache = TTLCache(maxsize=100, ttl=30)

Expand All @@ -42,7 +44,7 @@ def __init__(
auth_client: ConfidentialAppAuthClient,
bearer_token: str,
expected_scopes: Iterable[str],
expected_audience: Optional[str] = None,
expected_audience: str | None = None,
) -> None:
self.auth_client = auth_client
self.bearer_token = bearer_token
Expand All @@ -56,10 +58,10 @@ def __init__(
self.expected_audience = auth_client.client_id
else:
self.expected_audience = expected_audience
self.errors: List[Exception] = []
self._groups_client: Optional[GroupsClient] = None
self.errors: list[Exception] = []
self._groups_client: GroupsClient | None = None

def introspect_token(self) -> Optional[GlobusHTTPResponse]:
def introspect_token(self) -> GlobusHTTPResponse | None:
# There are cases where a null or empty string bearer token are present as a
# placeholder
if self.bearer_token is None:
Expand Down Expand Up @@ -103,26 +105,26 @@ def introspect_token(self) -> Optional[GlobusHTTPResponse]:
return resp

@property
def effective_identity(self) -> Optional[str]:
def effective_identity(self) -> str | None:
tkn_details = self.introspect_token()
if tkn_details is None:
return None
effective = identity_principal(tkn_details["sub"])
return effective

@property
def identities(self) -> FrozenSet[str]:
def identities(self) -> frozenset[str]:
tkn_details = self.introspect_token()
if tkn_details is None:
return frozenset()
return frozenset(map(identity_principal, tkn_details["identity_set"]))

@property
def principals(self) -> FrozenSet[str]:
def principals(self) -> frozenset[str]:
return self.identities.union(self.groups)

@property # type: ignore
def groups(self) -> FrozenSet[str]:
def groups(self) -> frozenset[str]:
try:
groups_client = self._get_groups_client()
except (GlobusAPIError, KeyError, ValueError) as err:
Expand Down Expand Up @@ -163,7 +165,7 @@ def groups(self) -> FrozenSet[str]:
return groups_set

@property
def dependent_tokens_cache_id(self) -> Optional[str]:
def dependent_tokens_cache_id(self) -> str | None:
tkn_details = self.introspect_token()
if tkn_details is None:
return None
Expand Down Expand Up @@ -200,7 +202,7 @@ def get_authorizer_for_scope(
scope: str,
bypass_dependent_token_cache=False,
required_authorizer_expiration_time: int = 60,
) -> Optional[Union[RefreshTokenAuthorizer, AccessTokenAuthorizer]]:
) -> RefreshTokenAuthorizer | AccessTokenAuthorizer | None:
"""Retrieve a Globus SDK authorizer for use in accessing a further Globus Auth registered
service / "resource server". This authorizer can be passed to any Globus SDK
Client class for use in accessing the Client's service.
Expand Down Expand Up @@ -353,7 +355,7 @@ def __init__(
client_id: str,
client_secret: str,
expected_scopes: Iterable[str],
expected_audience: Optional[str] = None,
expected_audience: str | None = None,
) -> None:
self.auth_client = ConfidentialAppAuthClient(client_id, client_secret)
self.default_expected_scopes = frozenset(expected_scopes)
Expand All @@ -364,7 +366,7 @@ def __init__(
self.expected_audience = expected_audience

def check_token(
self, access_token: str, expected_scopes: Iterable[str] = None
self, access_token: str, expected_scopes: Iterable[str] | None = None
) -> AuthState:
if expected_scopes is None:
expected_scopes = self.default_expected_scopes
Expand Down
4 changes: 2 additions & 2 deletions globus_action_provider_tools/authorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def authorize_action_access_or_404(status: ActionStatus, auth_state: AuthState)
AuthenticationError.
"""
if status.monitor_by is None:
allowed_set = set([status.creator_id])
allowed_set = {status.creator_id}
else:
allowed_set = set(chain([status.creator_id], status.monitor_by))

Expand All @@ -40,7 +40,7 @@ def authorize_action_management_or_404(
AuthenticationError.
"""
if status.manage_by is None:
allowed_set = set([status.creator_id])
allowed_set = {status.creator_id}
else:
allowed_set = set(chain([status.creator_id], status.manage_by))

Expand Down
12 changes: 7 additions & 5 deletions globus_action_provider_tools/flask/api_helpers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import logging
from typing import List, Optional

Expand Down Expand Up @@ -105,15 +107,15 @@ def add_action_routes_to_blueprint(
blueprint: flask.Blueprint,
client_id: str,
client_secret: str,
client_name: Optional[str],
client_name: str | None,
provider_description: ActionProviderDescription,
action_run_callback: ActionRunCallback,
action_status_callback: ActionStatusCallback,
action_cancel_callback: ActionCancelCallback,
action_release_callback: ActionReleaseCallback,
action_log_callback: Optional[ActionLogCallback] = None,
additional_scopes: Optional[List[str]] = None,
action_enumeration_callback: ActionEnumerationCallback = None,
action_log_callback: ActionLogCallback | None = None,
additional_scopes: list[str] | None = None,
action_enumeration_callback: ActionEnumerationCallback | None = None,
) -> None:
"""
Add routes to a Flask Blueprint to implement the required operations of the Action
Expand Down Expand Up @@ -296,7 +298,7 @@ def action_log(action_id: str) -> ViewReturn:
def action_enumeration():
auth_state = check_token(request, checker)

valid_statuses = set(e.name.casefold() for e in ActionStatusValue)
valid_statuses = {e.name.casefold() for e in ActionStatusValue}
statuses = parse_query_args(
request,
arg_name="status",
Expand Down
10 changes: 5 additions & 5 deletions globus_action_provider_tools/flask/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ def parse_query_args(
*,
arg_name: str,
default_value: str = "",
valid_vals: Set[str] = None,
) -> Set[str]:
valid_vals: set[str] | None = None,
) -> set[str]:
"""
Helper function to parse a query arg "arg_name" and return a validated
(according to the values supplied in "valid_vals"), usable set of
Expand Down Expand Up @@ -188,7 +188,7 @@ def get_input_body_validator(


def json_schema_input_validation(
action_input: Dict[str, Any], validator: jsonschema.Validator
action_input: dict[str, Any], validator: jsonschema.Validator
) -> None:
"""
Use a created JSON Validator to verify the input body of an incoming
Expand All @@ -201,7 +201,7 @@ def json_schema_input_validation(


def pydantic_input_validation(
action_input: Dict[str, Any], validator: Type[BaseModel]
action_input: dict[str, Any], validator: type[BaseModel]
) -> None:
"""
Validate input using the pydantic model itself. Raises a BadActionRequest
Expand All @@ -218,7 +218,7 @@ def pydantic_input_validation(
except ImportError:
# Flask < 2.2: Use the deprecated JSON encoder interface.
json_provider_available = False
JsonProvider: Optional["DefaultJSONProvider"] = None
JsonProvider: DefaultJSONProvider | None = None
else:
# Flask >= 2.2: Use the new JSON provider interface.
json_provider_available = True
Expand Down
6 changes: 3 additions & 3 deletions globus_action_provider_tools/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
"ActionRequest": "action_request.yaml",
"ActionStatus": "action_status.yaml",
}
_validator_map: Dict[str, jsonschema.Validator] = {}
_validator_map: Dict[str, jsonschema.protocols.Validator] = {}

HERE: Path = Path(__file__).parent
for schema_name, yaml_file in _schema_to_file_map.items():
with open(HERE / yaml_file, "r", encoding="utf-8") as specfile:
with open(HERE / yaml_file, encoding="utf-8") as specfile:
schema = yaml.safe_load(specfile)
validator_cls = jsonschema.validators.validator_for(schema)
_validator_map[schema_name] = validator_cls(schema)
Expand Down Expand Up @@ -43,7 +43,7 @@ def request_validator(request: ValidationRequest) -> ValidationResult:


def validate_data(
data: Dict[str, Any], validator: jsonschema.Validator
data: Dict[str, Any], validator: jsonschema.protocols.Validator
) -> ValidationResult:
error_messages = []
for error in validator.iter_errors(data):
Expand Down
Loading