1515 GlobusSDKUsageError ,
1616 IDTokenDecoder ,
1717)
18+ from globus_sdk ._internal .type_definitions import Closable
1819from globus_sdk .authorizers import GlobusAuthorizer
1920from globus_sdk .gare import GlobusAuthorizationParameters
2021from globus_sdk .scopes import AuthScopes , Scope , ScopeParser
@@ -67,6 +68,7 @@ class GlobusApp(metaclass=abc.ABCMeta):
6768 # this allows code during init call into otherwise unsafe codepaths in the app,
6869 # namely those which manipulate scope requirements
6970 _authorizer_factory : AuthorizerFactory [GlobusAuthorizer ]
71+ _token_storage : TokenStorage
7072 token_storage : ValidatingTokenStorage
7173
7274 def __init__ (
@@ -84,6 +86,7 @@ def __init__(
8486 self .app_name = app_name
8587 self .config = config
8688 self ._token_validation_error_handling_enabled = True
89+ self ._resources_to_close : list [Closable ] = []
8790
8891 self .client_id , self ._login_client = self ._resolve_client_info (
8992 app_name = self .app_name ,
@@ -96,27 +99,29 @@ def __init__(
9699
97100 # create the inner token storage object, and pick up on whether or not this
98101 # call handled creation or got a value from the outside
99- # if creation was done here, then this app "owns" the storage
100- inner_token_storage , token_storage_created_here = self ._resolve_token_storage (
102+ self ._token_storage , token_storage_created_here = self ._resolve_token_storage (
101103 app_name = self .app_name ,
102104 client_id = self .client_id ,
103105 config = self .config ,
104106 )
105- self ._token_storage = inner_token_storage
106- self ._owns_token_storage = token_storage_created_here
107107
108108 # create a consent client for token validation
109109 # this client won't be ready for immediate use, but will have the app attached
110110 # at the end of init
111111 consent_client = AuthClient (environment = config .environment )
112+ self ._resources_to_close .append (consent_client )
112113
113114 # create the requisite token storage for the app, with validation based on
114115 # the provided parameters
116+ # if the token storage was created by the app, the validating wrapper is added
117+ # to the resources to close when closed
115118 self .token_storage = self ._initialize_validating_token_storage (
116119 token_storage = self ._token_storage ,
117120 consent_client = consent_client ,
118121 scope_requirements = self ._scope_requirements ,
119122 )
123+ if token_storage_created_here :
124+ self ._resources_to_close .append (self .token_storage )
120125
121126 # setup an ID Token Decoder based on config; build one if it was not provided
122127 self ._id_token_decoder = self ._initialize_id_token_decoder (
@@ -168,6 +173,9 @@ def _resolve_client_info(
168173 abstract method: _initialize_login_client``.
169174 2. Extract the client_id from a supplied login_client.
170175
176+ If a new client is created here, it is also added to the set of resources to
177+ close when this app is closed.
178+
171179 :returns: tuple of client_id and login_client
172180 :raises: GlobusSDKUsageError if a single client ID or login client could not be
173181 definitively resolved.
@@ -195,6 +203,7 @@ def _resolve_client_info(
195203 login_client = self ._initialize_login_client (
196204 app_name , config , client_id , client_secret
197205 )
206+ self ._resources_to_close .append (login_client )
198207 return client_id , login_client
199208
200209 else :
@@ -389,11 +398,12 @@ def close(self) -> None:
389398 Close all resources currently held by the app.
390399 This does not trigger a logout.
391400 """
392- # if the app owns the token storage (meaning it was created by this app on init)
393- # then it will close the storage
394- if self ._owns_token_storage :
395- log .debug ("closing app associated token storage" )
396- self .token_storage .close ()
401+ for resource in self ._resources_to_close :
402+ log .debug (
403+ f"closing resource of type { type (resource ).__name__ } "
404+ f"for { type (self ).__name__ } (app_name={ self .app_name !r} )"
405+ )
406+ resource .close ()
397407
398408 # apps can act as context managers, and such usage calls close()
399409 def __enter__ (self ) -> Self :
0 commit comments