Coverage for src/artemis_sg/app_creds.py: 71%

27 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-10-12 06:30 -0700

1"""artemis_sg.app_creds 

2 

3Obtains Google API Application Credentials.""" 

4 

5import os.path 

6 

7from google.auth.exceptions import RefreshError 

8from google.auth.transport.requests import Request 

9from google.oauth2.credentials import Credentials 

10from google_auth_oauthlib.flow import InstalledAppFlow 

11 

12from artemis_sg.config import CFG 

13 

14app_token = CFG["google"]["docs"]["api_creds_token"] 

15google_credentials = CFG["google"]["docs"]["api_creds_file"] 

16 

17 

18def app_creds(app_token_filename: str = app_token) -> str: 

19 """Obtain Google API application credentials. 

20 

21 Check given `app_token_filename` for valid credentials. If they don't 

22 exist or are not valid, then use 

23 `google_auth_oauthlib.flow.InstalledAppFlow` to let the user manually 

24 approve the credential request. When successful, the credentials are saved 

25 to the given `app_token_filename` and returned. 

26 

27 :param app_token_filename: 

28 The filename used to inspect and save the credentials in (default is 

29 app_creds_token.json). In practice this would not be set, but is given 

30 here as a parameter for unittesting purposes. 

31 :returns: a json string of the credentials 

32 """ 

33 

34 scopes = ( 

35 "https://www.googleapis.com/auth/spreadsheets.readonly", 

36 "https://www.googleapis.com/auth/presentations", 

37 ) 

38 creds = None 

39 # The file `app_token_filename` stores the user's access and refresh tokens, and is 

40 # created automatically when the authorization flow completes for the first 

41 # time. 

42 

43 if os.path.exists(app_token_filename): 

44 creds = Credentials.from_authorized_user_file(app_token_filename, scopes) 

45 # If there are no (valid) credentials available, let the user log in. 

46 if not creds or not creds.valid: 

47 if creds and creds.expired and creds.refresh_token: 47 ↛ 48line 47 didn't jump to line 48, because the condition on line 47 was never true

48 try: 

49 creds.refresh(Request()) 

50 except RefreshError: 

51 flow = InstalledAppFlow.from_client_secrets_file( 

52 google_credentials, scopes 

53 ) 

54 creds = flow.run_local_server(port=0) 

55 else: 

56 flow = InstalledAppFlow.from_client_secrets_file(google_credentials, scopes) 

57 creds = flow.run_local_server(port=0) 

58 # Save the credentials for the next run 

59 _write_token_file(app_token_filename, creds) 

60 

61 return creds 

62 

63 

64def _write_token_file(filename: str, creds: str): 

65 with open(filename, "w", encoding="utf-8") as token: 

66 token.write(creds.to_json())