@@ -145,6 +145,32 @@ def logout(origin: Origin):
145145 print (f"Not logged in to { origin } ." , file = stderr )
146146
147147
148+ def logout_all ():
149+ """
150+ Remove **all** locally-saved credentials.
151+
152+ Equivalent to calling :func:`logout` on all origins found in the secrets
153+ file.
154+ """
155+ with config .write_lock ():
156+ secrets = config .load (config .SECRETS )
157+
158+ sections = [
159+ (section , _parse_section (section ))
160+ for section in secrets
161+ if _parse_section (section ) ]
162+
163+ if sections :
164+ for section , origin in sections :
165+ del secrets [section ]
166+ print (f"Credentials for { origin } removed from { config .SECRETS } ." , file = stderr )
167+ print (f"Logged out of { origin } ." , file = stderr )
168+
169+ config .save (secrets , config .SECRETS )
170+ else :
171+ print (f"Not logged in to any remotes." , file = stderr )
172+
173+
148174def current_user (origin : Origin ) -> Optional [User ]:
149175 """
150176 Information about the currently logged in user for *origin*, if any.
@@ -237,3 +263,12 @@ def _config_section(origin: Origin) -> str:
237263 if origin == "https://nextstrain.org" :
238264 return CONFIG_SECTION
239265 return f"{ CONFIG_SECTION } { origin } "
266+
267+
268+ def _parse_section (section : str ) -> Optional [Origin ]:
269+ if section == CONFIG_SECTION :
270+ return Origin ("https://nextstrain.org" )
271+ elif section .startswith (CONFIG_SECTION + " " ):
272+ return Origin (section .split (" " , 1 )[1 ])
273+ else :
274+ return None
0 commit comments