-1

I want to access multiple google calendars from python: there is a primary calendar connected to a google account, also other (secondary) calendars can be created. Access to the secondary calendars is possible after google authorization to the primary one. I want to make changes to the secondary calendars without repeating authorization procedure every time, i.e. login once and store auth information in the class attribute. For example:

class Gcal:
    auth = None

    @classmethod
    def authorize(cls, account):
        cls.auth = auth_function()
        
    def __init__(self, calendar_name, account='user@gmail.com'):
        if not self.auth:
            self.authorize(account)
        self.calendar = self.get_cal(calendar_name)

    def get_cal(self, calendar_name):
        pass

if __name__ == '__main__':

    g1 = Gcal('1')
    g2 = Gcal('2')
    g3 = Gcal('3')
    print(g1, g2, g3)

The code above works without additional calls of auth_function(), but I'd like to know if this is a good practice of object oriented use of python? Are there side effects?

zeliboba7
  • 335
  • 1
  • 10

1 Answers1

2

The code you've shown is a little confused, because you're only passing one argument when you call Gcal (e.g. Gcal('1')), but __init__ takes two arguments.

Even if you called the constructor correctly, it wouldn't really make sense to unconditionally cache the authorization details because if a different account was passed in, you wouldn't have stored the right credentials for it. Consider:

g1 = Gcal('1', "Account one")
g4 = Gcal('4', "Account two") # different calendar on a different account

Your current code would have cached the authentication details for "Account one" and would try to use it (hopefully unsuccessfully) to get something that you were told to get from "Account two". That might fail, or it might get the wrong data!

Indeed, I seems to me like you might want to make an Account class, which can be authorized once and then used several times.

class Account:
    def __init__(self, acct_name):
        self.name = name
        self.auth = None

    def get_auth(self):
        if self.auth is None:
            self.auth = auth_function(self.name)
        return self.auth

The Gcal class would need to be updated to call account.get_auth() as needed. Then you could do:

account_one = Account("Account one")

g1 = Gcal('1', account_one)
g2 = Gcal('2', account_one)
g3 = Gcal('3', account_one)

g4 = Gcal('4', Account("Account two"))
Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • You are right about constructor call, actually there is a default argument `account='user@gmail.com'`, the code example is updated. Thank you very much for pointing out to potential problem with account switch! Indeed my implemetation will work only for one account, which can be hardcoded into `auth_function()` (this is not nice, but kind of okish for my purpose). – zeliboba7 Jan 29 '23 at 04:08