comparison multimerge.py @ 65:1eefa9b5e945

Unicodify.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 11 Jul 2016 18:36:10 +0300
parents c4b8d934d7ab
children b08d159e35c7
comparison
equal deleted inserted replaced
64:c4b8d934d7ab 65:1eefa9b5e945
80 ## Function for handling Google API credentials 80 ## Function for handling Google API credentials
81 def gcm_get_credentials(mcfg): 81 def gcm_get_credentials(mcfg):
82 try: 82 try:
83 store = oauth2client.file.Storage(mcfg.credential_file) 83 store = oauth2client.file.Storage(mcfg.credential_file)
84 except Exception as e: 84 except Exception as e:
85 gcm_fatal("Failed to read credential file:\n{0}\n\nERROR: {1}\n".format(mcfg.credential_file, str(e))) 85 gcm_fatal(u"Failed to read credential file:\n{0}\n\nERROR: {1}\n".format(mcfg.credential_file, str(e)))
86 86
87 credentials = store.get() 87 credentials = store.get()
88 if not credentials or credentials.invalid: 88 if not credentials or credentials.invalid:
89 try: 89 try:
90 flow = client.flow_from_clientsecrets(mcfg.secret_file, mcfg.scope) 90 flow = client.flow_from_clientsecrets(mcfg.secret_file, mcfg.scope)
91 except Exception as e: 91 except Exception as e:
92 gcm_fatal("Failed to fetch client secret:\n{0}\n\nERROR: {1}\n".format(mcfg.secret_file, str(e))) 92 gcm_fatal(u"Failed to fetch client secret:\n{0}\n\nERROR: {1}\n".format(mcfg.secret_file, str(e)))
93 93
94 flow.user_agent = mcfg.app_name 94 flow.user_agent = mcfg.app_name
95 credentials = tools.run_flow(flow, store, mcfg) 95 credentials = tools.run_flow(flow, store, mcfg)
96 if not credentials or credentials.invalid: 96 if not credentials or credentials.invalid:
97 gcm_fatal("Failed to authenticate / invalid credentials.") 97 gcm_fatal(u"Failed to authenticate / invalid credentials.")
98 return credentials 98 return credentials
99 99
100 100
101 def gcm_dump_events(events): 101 def gcm_dump_events(events):
102 for event in events: 102 for event in events:
146 elif len(src) == 7 and src[0] == "#": 146 elif len(src) == 7 and src[0] == "#":
147 self.r = int(src[1:3], 16) 147 self.r = int(src[1:3], 16)
148 self.g = int(src[3:5], 16) 148 self.g = int(src[3:5], 16)
149 self.b = int(src[6:7], 16) 149 self.b = int(src[6:7], 16)
150 else: 150 else:
151 gcm_fatal("Expected hex-triplet string for GCMColor() initializer: {0}".format(src)) 151 gcm_fatal(u"Expected hex-triplet string for GCMColor() initializer: {0}".format(src))
152 elif isinstance(src, GCMColor): 152 elif isinstance(src, GCMColor):
153 self.r = src.r 153 self.r = src.r
154 self.g = src.g 154 self.g = src.g
155 self.b = src.b 155 self.b = src.b
156 else: 156 else:
157 gcm_fatal("Invalid initializer for GCMColor() object.") 157 gcm_fatal(u"Invalid initializer for GCMColor() object.")
158 158
159 def delta(self, other): 159 def delta(self, other):
160 ctmp = GCMColor() 160 ctmp = GCMColor()
161 ctmp.r = other.r - self.r 161 ctmp.r = other.r - self.r
162 ctmp.g = other.g - self.g 162 ctmp.g = other.g - self.g
201 201
202 def __getattr__(self, name): 202 def __getattr__(self, name):
203 if name in self.m_data: 203 if name in self.m_data:
204 return self.m_data[name] 204 return self.m_data[name]
205 else: 205 else:
206 gcm_fatal("GCMSettings.__getattr__(): No such attribute '"+ name +"'.") 206 gcm_fatal(u"GCMSettings.__getattr__(): No such attribute '"+ name +"'.")
207 207
208 def mvalidate(self, name, value): 208 def mvalidate(self, name, value):
209 if name in self.m_validate and self.m_validate[name]: 209 if name in self.m_validate and self.m_validate[name]:
210 if not self.m_validate[name](value): 210 if not self.m_validate[name](value):
211 gcm_fatal("GCMSettings.mvalidate(): Invalid value for attribute '{0}': {1}".format(name, value)) 211 gcm_fatal(u"GCMSettings.mvalidate(): Invalid value for attribute '{0}': {1}".format(name, value))
212 212
213 def mtranslate(self, name, value): 213 def mtranslate(self, name, value):
214 if name in self.m_translate and self.m_translate[name]: 214 if name in self.m_translate and self.m_translate[name]:
215 return self.m_translate[name](value) 215 return self.m_translate[name](value)
216 else: 216 else:
275 return mvalue 275 return mvalue
276 276
277 def is_bool(self, mvalue): 277 def is_bool(self, mvalue):
278 mval = self.trans_bool(mvalue) 278 mval = self.trans_bool(mvalue)
279 if not isinstance(mval, bool): 279 if not isinstance(mval, bool):
280 gcm_fatal("GCMSettings.is_bool(): Invalid boolean value '{0}', should be true|false|1|0|on|off|yes|no.".format(mvalue)) 280 gcm_fatal(u"GCMSettings.is_bool(): Invalid boolean value '{0}', should be true|false|1|0|on|off|yes|no.".format(mvalue))
281 else: 281 else:
282 return True 282 return True
283 283
284 def trans_list(self, mvalue): 284 def trans_list(self, mvalue):
285 morig = mvalue 285 morig = mvalue
286 if self.is_str(mvalue): 286 if self.is_str(mvalue):
287 mvalue = re.split("\s*,\s*", mvalue, flags=re.IGNORECASE) 287 mvalue = re.split("\s*,\s*", mvalue, flags=re.IGNORECASE)
288 if not isinstance(mvalue, list): 288 if not isinstance(mvalue, list):
289 gcm_fatal("GCMSettings.trans_list(): Could not parse list '{0}'.".format(mvalue)) 289 gcm_fatal(u"GCMSettings.trans_list(): Could not parse list '{0}'.".format(mvalue))
290 elif not isinstance(mvalue, list): 290 elif not isinstance(mvalue, list):
291 gcm_fatal("GCMSettings.trans_list(): Invalid value '{0}'.".format(mvalue)) 291 gcm_fatal(u"GCMSettings.trans_list(): Invalid value '{0}'.".format(mvalue))
292 return mvalue 292 return mvalue
293 293
294 def is_list(self, mvalue): 294 def is_list(self, mvalue):
295 return self.trans_list(mvalue) 295 return self.trans_list(mvalue)
296 296
309 def is_email_list(self, mvalue): 309 def is_email_list(self, mvalue):
310 mvalue = self.trans_email_list(mvalue) 310 mvalue = self.trans_email_list(mvalue)
311 if mvalue != None: 311 if mvalue != None:
312 for email in mvalue: 312 for email in mvalue:
313 if not self.is_email(email): 313 if not self.is_email(email):
314 gcm_fatal("Invalid e-mail address '{0}' in list {1}.".format(email, ", ".join(mvalue))) 314 gcm_fatal(u"Invalid e-mail address '{0}' in list {1}.".format(email, ", ".join(mvalue)))
315 return True 315 return True
316 316
317 317
318 ### 318 ###
319 ### Main program starts 319 ### Main program starts
358 gcm_debug(u"Reading configuration from '{0}'.".format(sys.argv[1])) 358 gcm_debug(u"Reading configuration from '{0}'.".format(sys.argv[1]))
359 try: 359 try:
360 cfgparser = ConfigParser.RawConfigParser() 360 cfgparser = ConfigParser.RawConfigParser()
361 cfgparser.readfp(codecs.open(sys.argv[1], "r", "UTF-8")) 361 cfgparser.readfp(codecs.open(sys.argv[1], "r", "UTF-8"))
362 except Exception as e: 362 except Exception as e:
363 gcm_fatal("Failed to read configuration file '{0}': {1}".format(sys.argv[1], str(e))) 363 gcm_fatal(u"Failed to read configuration file '{0}': {1}".format(sys.argv[1], str(e)))
364 364
365 # Check that the required section exists 365 # Check that the required section exists
366 section = "gcm" 366 section = "gcm"
367 if not cfgparser.has_section(section): 367 if not cfgparser.has_section(section):
368 gcm_fatal("Invalid configuration, missing '{0}' section.".format(section)) 368 gcm_fatal(u"Invalid configuration, missing '{0}' section.".format(section))
369 369
370 # Debug setting is a special case, we need to get it 370 # Debug setting is a special case, we need to get it
371 # set before everything else, so do it here .. 371 # set before everything else, so do it here ..
372 if cfgparser.has_option(section, "debug"): 372 if cfgparser.has_option(section, "debug"):
373 cfg.mset("debug", cfgparser.get(section, "debug")) 373 cfg.mset("debug", cfgparser.get(section, "debug"))
377 377
378 378
379 ## Validate settings 379 ## Validate settings
380 if cfg.email: 380 if cfg.email:
381 if cfg.email_subject == None or len(cfg.email_subject) == 0: 381 if cfg.email_subject == None or len(cfg.email_subject) == 0:
382 gcm_fatal("E-mail enabled but email_subject not set.") 382 gcm_fatal(u"E-mail enabled but email_subject not set.")
383 elif cfg.email_sender == None: 383 elif cfg.email_sender == None:
384 gcm_fatal("E-mail enabled but email_sender not set.") 384 gcm_fatal(u"E-mail enabled but email_sender not set.")
385 elif cfg.email_to == None: 385 elif cfg.email_to == None:
386 gcm_fatal("E-mail enabled but email_to not set.") 386 gcm_fatal(u"E-mail enabled but email_to not set.")
387 else: 387 else:
388 cfg.mset("email_ok", True) 388 cfg.mset("email_ok", True)
389 389
390 390
391 if len(cfg.source_regmap) != cfg.source_regmap_len: 391 if len(cfg.source_regmap) != cfg.source_regmap_len:
392 gcm_fatal("Setting source_regmap list must be {0} items.".format(cfg.source_regmap_len)) 392 gcm_fatal(u"Setting source_regmap list must be {0} items.".format(cfg.source_regmap_len))
393 else: 393 else:
394 # Force to integers 394 # Force to integers
395 try: 395 try:
396 cfg.source_regmap = map(lambda x: int(x), cfg.source_regmap) 396 cfg.source_regmap = map(lambda x: int(x), cfg.source_regmap)
397 except Exception as e: 397 except Exception as e:
398 gcm_fatal("Invalid source_regmap: {0}".format(str(e))) 398 gcm_fatal(u"Invalid source_regmap: {0}".format(str(e)))
399 399
400 400
401 if not cfg.dest_name and not cfg.dest_id: 401 if not cfg.dest_name and not cfg.dest_id:
402 gcm_fatal("Target calendar ID or name required, but not set.") 402 gcm_fatal(u"Target calendar ID or name required, but not set.")
403 403
404 404
405 if cfg.dest_name: 405 if cfg.dest_name:
406 cfg.mset("dest_name", cfg.mget("dest_name").strip()) 406 cfg.mset("dest_name", cfg.mget("dest_name").strip())
407 407
428 cal_token = result.get("nextPageToken") 428 cal_token = result.get("nextPageToken")
429 if not cal_token: 429 if not cal_token:
430 break 430 break
431 431
432 if len(calendars) == 0: 432 if len(calendars) == 0:
433 gcm_fatal("No calendars found?") 433 gcm_fatal(u"No calendars found?")
434 434
435 gcm_debug(u"{0} calendars total found.".format(len(calendars))) 435 gcm_debug(u"{0} calendars total found.".format(len(calendars)))
436 436
437 437
438 ## Filter desired SOURCE calendars based on specified regexp 438 ## Filter desired SOURCE calendars based on specified regexp
468 468
469 ## Fetch colors 469 ## Fetch colors
470 try: 470 try:
471 colors = service.colors().get().execute() 471 colors = service.colors().get().execute()
472 except Exception as e: 472 except Exception as e:
473 gcm_fatal("Failed to fetch calendar color settings:\n\n{0}".format(str(e))) 473 gcm_fatal(u"Failed to fetch calendar color settings:\n\n{0}".format(str(e)))
474 474
475 475
476 ## Now, we fetch and collect events 476 ## Now, we fetch and collect events
477 gcm_debug(u"Fetching calendar events .. ") 477 gcm_debug(u"Fetching calendar events .. ")
478 src_events = [] 478 src_events = []
486 # orderBy="startTime", 486 # orderBy="startTime",
487 ).execute() 487 ).execute()
488 488
489 c_found = None 489 c_found = None
490 if "colorId" in calendar and calendar["colorId"] in colors["calendar"]: 490 if "colorId" in calendar and calendar["colorId"] in colors["calendar"]:
491 gcm_debug("Calendar color: {0}".format(colors["calendar"][calendar["colorId"]])) 491 gcm_debug(u"Calendar color: {0}".format(colors["calendar"][calendar["colorId"]]))
492 c_found = gcm_find_nearest_color(colors["event"], colors["calendar"][calendar["colorId"]], 100) 492 c_found = gcm_find_nearest_color(colors["event"], colors["calendar"][calendar["colorId"]], 100)
493 if c_found: 493 if c_found:
494 gcm_debug("Found nearest event color ID: {0}, {1}".format(c_found, colors["event"][c_found])) 494 gcm_debug(u"Found nearest event color ID: {0}, {1}".format(c_found, colors["event"][c_found]))
495 else: 495 else:
496 gcm_debug("No matching event color found!") 496 gcm_debug(u"No matching event color found!")
497 497
498 # Add events, if any, to main list 498 # Add events, if any, to main list
499 events = gcm_generate_ids(result.get("items", []), calendar["id"], "___") 499 events = gcm_generate_ids(result.get("items", []), calendar["id"], "___")
500 if events: 500 if events:
501 for event in events: 501 for event in events:
537 event.pop("sequence", None) 537 event.pop("sequence", None)
538 event.pop("id", None) 538 event.pop("id", None)
539 event["iCalUID"] = event["gcm_id"] 539 event["iCalUID"] = event["gcm_id"]
540 new_event = service.events().update(calendarId=cfg.dest_id, eventId=d_event["id"], body=event).execute() 540 new_event = service.events().update(calendarId=cfg.dest_id, eventId=d_event["id"], body=event).execute()
541 except Exception as e: 541 except Exception as e:
542 gcm_fatal("Failed to update event {0}:\n\n{1}\n\nERROR: {2}\n".format(event["gcm_id"], event, str(e))) 542 gcm_fatal(u"Failed to update event {0}:\n\n{1}\n\nERROR: {2}\n".format(event["gcm_id"], event, str(e)))
543 else: 543 else:
544 gcm_debug(u"No need to update event {0} : {1}.".format(event["id"], event["gcm_id"])) 544 gcm_debug(u"No need to update event {0} : {1}.".format(event["id"], event["gcm_id"]))
545 else: 545 else:
546 ## Event does not seem to exist. Insert new event. 546 ## Event does not seem to exist. Insert new event.
547 gcm_debug(u"Inserting new event {0}".format(event["gcm_id"])) 547 gcm_debug(u"Inserting new event {0}".format(event["gcm_id"]))
548 event.pop("id", None) 548 event.pop("id", None)
549 event["iCalUID"] = event["gcm_id"] # Replace Google generated ID with our own 549 event["iCalUID"] = event["gcm_id"] # Replace Google generated ID with our own
550 try: 550 try:
551 new_event = service.events().insert(calendarId=cfg.dest_id, body=event).execute() 551 new_event = service.events().insert(calendarId=cfg.dest_id, body=event).execute()
552 except Exception as e: 552 except Exception as e:
553 gcm_fatal("Failed to insert new event:\n\n{0}\n\nERROR: {1}\n".format(event, str(e))) 553 gcm_fatal(u"Failed to insert new event:\n\n{0}\n\nERROR: {1}\n".format(event, str(e)))
554 554
555 555
556 ## Remove "stale" events 556 ## Remove "stale" events
557 gcm_debug(u"Purging stale events ..") 557 gcm_debug(u"Purging stale events ..")
558 for event in dst_events: 558 for event in dst_events:
560 if not event["gcm_id"] in src_ids and event["status"] != u"cancelled": 560 if not event["gcm_id"] in src_ids and event["status"] != u"cancelled":
561 gcm_debug(u"Deleting event {0}".format(event["gcm_id"])) 561 gcm_debug(u"Deleting event {0}".format(event["gcm_id"]))
562 try: 562 try:
563 service.events().delete(calendarId=cfg.dest_id, eventId=event["id"]).execute() 563 service.events().delete(calendarId=cfg.dest_id, eventId=event["id"]).execute()
564 except Exception as e: 564 except Exception as e:
565 gcm_fatal("Failed to delete stale event:\n{0}\n\nERROR: {1}\n".format(event, str(e))) 565 gcm_fatal(u"Failed to delete stale event:\n{0}\n\nERROR: {1}\n".format(event, str(e)))
566 566
567 567
568 gcm_debug(u"Finished.") 568 gcm_debug(u"Finished.")