splaq
Coder
I am working on an app right now that is basically google calendar in your system tray, I'm running into the issue in the build_calendar_list() method. I'll post the code below, but everything works the way I would expect until I choose a calendar from my list of calendars. When I choose a calendar I expect to get back the calendar id of the chosen calendar. But I only ever get back the the id for the last item in the list. That's a very basic idea of the program and the problem.. Here is the code..
I believe what's going on is that for whatever reason the lambda function in my build_calendar_list() method is causing all of my id's to default to the last item in the list of calendars. If that's the case then what can I do to correct that? The idea is to be able to choose a calendar and get a quick view of events for that calendar or add an event etc.
Python:
from __future__ import print_function
import datetime
import os.path
import pprint
import sys
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from PIL import Image
from pystray import Icon as icon, Menu as menu, MenuItem as item
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/calendar']
class MyCalendar:
def __init__(self):
"""Shows basic usage of the Google Calendar API.
Prints the start and name of the next 10 events on the user's calendar.
"""
self.creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
self.creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not self.creds or not self.creds.valid:
if self.creds and self.creds.expired and self.creds.refresh_token:
self.creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
self.creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(self.creds.to_json())
try:
# Call the Calendar API
self.service = build('calendar', 'v3', credentials=self.creds)
self.cal_id = None
self.cal_list = self.build_calendar_list()
print(dir(self.cal_list[0]))
except HttpError as error:
print('An error occurred: %s' % error)
# def get_events(self):
# now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
# events_result = self.service.events().list(calendarId=self.get_cal_id(), timeMin=now,
# maxResults=10, singleEvents=True,
# orderBy='startTime').execute()
# events = events_result.get('items', [])
# if not events:
# print('No upcoming events found.')
# return
# # Prints the start and name of the next 10 events
# for event in events:
# start = event['start'].get('dateTime', event['start'].get('date'))
# print(start, event['summary'])
def set_cal_id(self, cal_id):
self.cal_id = cal_id
print(self.cal_id)
# return self.cal_id
def get_cal_id(self):
return self.cal_id
def tray_icon(self):
image = Image.open("icon.ico")
return image
def good_bye(self, icon):
print("Later Tater!")
icon.visible = False
icon.stop()
def create_tray(self):
'''
Create the tray icon & menu
'''
menu_items = tuple(self.cal_list)
icon(
'TrayCalendar',
icon=self.tray_icon(),
menu=menu(
item(
'Quit',
self.good_bye,
),
item(
'Calendar List',
menu(
lambda: (item for item in menu_items)
),
),
),
).run()
def build_calendar_list(self):
'''
Build the list of calendars in the users Google Calendar
'''
cal_list = []
calendarlist = self.service.calendarList().list().execute()
for k in calendarlist.get('items', tuple()):
cal_list.append(
## ISSUE:
## All k['id'] come back as the last item in the list.
## IE. All lambda: self.set_cal_id(k['id']) => lambda: self.set_cal_id('addressbook#[email protected]')
## 0 understanding as to why.
(item(k["summary"], lambda *args: self.set_cal_id(k['id'])))
)
return cal_list
if __name__ == '__main__':
my_cal = MyCalendar()
my_cal.create_tray()
I believe what's going on is that for whatever reason the lambda function in my build_calendar_list() method is causing all of my id's to default to the last item in the list of calendars. If that's the case then what can I do to correct that? The idea is to be able to choose a calendar and get a quick view of events for that calendar or add an event etc.