diff --git a/google/api_handler.py b/google/api_handler.py index f2aed65..074c1a2 100644 --- a/google/api_handler.py +++ b/google/api_handler.py @@ -1,4 +1,4 @@ -# Copyright 2019-2020 cj-wong +# Copyright 2019-2021 cj-wong # Copyright 2018 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,13 +37,17 @@ class ExpiredCredentials(RuntimeError): """Credentials were expired.""" + def __init__(self): + """Initialize the error with a message.""" super().__init__('Credentials expired') def authorize() -> service_account.Credentials: - """Adapted from Google's example: - https://developers.google.com/calendar/quickstart/python + """Authorize the connection to the Google API. + + Adapted from Google's example: + https://developers.google.com/calendar/quickstart/python See NOTICE for attribution. diff --git a/google/calendar.py b/google/calendar.py index 22a9d58..b8ae270 100644 --- a/google/calendar.py +++ b/google/calendar.py @@ -1,4 +1,4 @@ -# Copyright 2019-2020 cj-wong +# Copyright 2019-2021 cj-wong # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ def get_tab(entry: str) -> Union[str, None]: - """Gets a tab given an `entry`, if it exists in `config.TAB_NAMES`. + """Get a tab given its name, if it exists in `config.TAB_NAMES`. Args: entry (str): the name of an entry @@ -47,22 +47,24 @@ def get_tab(entry: str) -> Union[str, None]: class TabNotFound(ValueError): """The tab name wasn't found in the configuration. Ignore it.""" + pass class Calendar: - """Class for managing calendar. + """Class for managing Google Calendar. Attributes: interface (Resource): an interface created from credentials; used to retrieve calendars and entries per calendar """ + def __init__(self, credentials: service_account.Credentials) -> None: - """Initialize the Calendar interface. + """Initialize the Google Calendar interface. Args: - credentials (service_account.Credentials): for Google APIs + credentials (service_account.Credentials): creds for Google APIs """ self.interface = build( @@ -72,8 +74,9 @@ def __init__(self, credentials: service_account.Credentials) -> None: ) def get_calendar_ids(self) -> Dict[str, str]: - """Gets IDs for calendars configured in config.yaml. They will - be used for retrieving entries/events per calendar. + """Get IDs for calendars configured in config.yaml. + + The IDs will be used for retrieving entries/events per calendar. Returns: Dict[str, str]: {calendar name: calendar id} @@ -91,9 +94,9 @@ def get_calendar_ids(self) -> Dict[str, str]: return cals def get_entries(self, cal_name: str, cal_id: str) -> Dict[str, int]: - """Gets entries in a calendar given `cal_id` from yesterday - until today. We are interested in events that have elapsed - from then and now. + """Get entries in a calendar given `cal_id` from yesterday until today. + + We are interested in events that have elapsed from then and now. Args: cal_name (str): the name (summary) of the calendar diff --git a/google/sheets.py b/google/sheets.py index bdc06e0..f361b2e 100644 --- a/google/sheets.py +++ b/google/sheets.py @@ -1,4 +1,4 @@ -# Copyright 2019-2020 cj-wong +# Copyright 2019-2021 cj-wong # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -27,11 +27,11 @@ def get_yesterday_cell(start: Dict[str, Union[str, int]]) -> str: - """Retrieve the cell representing yesterday, given the starting - cell and its characteristics. Note that if the cell isn't valid, - `AttributeError` ,`TypeError`, or `ValueError` may be raised, - from attempted string slicing (e.g. `cell[:col_end]`) and type-casts - (e.g. `int(cell[col_end:])`). + """Retrieve the cell location representing yesterday. + + The cell location can be determined given the starting cell location and + year and month offsets. Note that if the cell isn't valid, AttributeError + or TypeError may be raised, albeit indirectly. Args: start (Dict[str, Union[str, int]]): the characteristics of @@ -41,6 +41,10 @@ def get_yesterday_cell(start: Dict[str, Union[str, int]]) -> str: Returns: str: the cell in spreadsheet format, e.g. 'A1' + Raises: + AttributeError: if any intermediary values are None + TypeError: slicing or casting on None + """ cell = start['cell'] first = pendulum.datetime(start['year'], start['month'], 1, tz='local') @@ -64,13 +68,14 @@ def get_yesterday_cell(start: Dict[str, Union[str, int]]) -> str: class Sheets: - """Class for manging sheets. + """Class for Google Sheets. Attributes: interface (Resource): an interface created from credentials; used to retrieve spreadsheets and their sheets """ + def __init__(self, credentials) -> None: """Initialize the Sheets interface. @@ -85,8 +90,9 @@ def __init__(self, credentials) -> None: ).spreadsheets() def get_tab_cells(self) -> Dict[str, str]: - """For all valid tabs, get the cell representing yesterday so - the hours can be recorded there. + """Get the cell representing yesterday to be written with hours. + + If the cell is invalid, nothing will be written. Returns: Dict[str, str]: {tab name: syntax for yesterday's cell} @@ -108,13 +114,12 @@ def get_tab_cells(self) -> Dict[str, str]: return tab_cells def input_hours(self, tab_hours: Dict[str, int]) -> None: - """Inputs hours given `tab_hours` into their respective sheets. + """Input hours into their respective sheets. Args: tab_hours (Dict[str, int]): {tab name: hours} """ - values = self.interface.values() tab_cells = self.get_tab_cells() diff --git a/main.py b/main.py index 12889e9..f1b946e 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,4 @@ -# Copyright 2019-2020 cj-wong +# Copyright 2019-2021 cj-wong # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -22,8 +22,9 @@ def main() -> None: - """This function runs everything: authorizes the connection, - reads calendars, and writes to spreadsheet if records were found. + """Run everything: authorization, calendar reads, spreadsheet writes. + + The spreadsheet is only written if events in the calendar are found. """ creds = google.api_handler.authorize() @@ -32,8 +33,7 @@ def main() -> None: calendars = calendar_api.get_calendar_ids() if not calendars: LOGGER.error( - 'No calendars were found matching any in your configuration' - ) + 'No calendars were found matching any in your configuration') return for cal_name, cal_id in calendars.items(): tab_hours = calendar_api.get_entries(cal_name, cal_id)