annotate multimerge.py @ 120:1f7967aa0133

Improve and add comments.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 18 Oct 2016 15:05:55 +0300
parents f671602635b7
children 4500fbf91294
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
1 #!/usr/bin/python
3
1e254756d0a5 Our code is UTF-8 Unicode.
Matti Hamalainen <ccr@tnsp.org>
parents: 2
diff changeset
2 # coding=utf-8
2
34c3a08a4a37 Copyright, etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 1
diff changeset
3 ###
36
2d7767f0fb67 Remove version.
Matti Hamalainen <ccr@tnsp.org>
parents: 35
diff changeset
4 ### Google Calendar MultiMerge
80
4bed40e35fae Fix copyright and add information about license.
Matti Hamalainen <ccr@tnsp.org>
parents: 78
diff changeset
5 ### Programmed and designed by Matti 'ccr' Hämäläinen <ccr@tnsp.org>
4bed40e35fae Fix copyright and add information about license.
Matti Hamalainen <ccr@tnsp.org>
parents: 78
diff changeset
6 ### (C) Copyright 2016 Tecnic Software productions (TNSP)
4bed40e35fae Fix copyright and add information about license.
Matti Hamalainen <ccr@tnsp.org>
parents: 78
diff changeset
7 ###
4bed40e35fae Fix copyright and add information about license.
Matti Hamalainen <ccr@tnsp.org>
parents: 78
diff changeset
8 ### For license information, see file "COPYING".
2
34c3a08a4a37 Copyright, etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 1
diff changeset
9 ###
34c3a08a4a37 Copyright, etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 1
diff changeset
10 ### Python 2.7 <= x < 3 required! Please refer to
34c3a08a4a37 Copyright, etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 1
diff changeset
11 ### README.txt for information on other depencies.
34c3a08a4a37 Copyright, etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 1
diff changeset
12 ###
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
13 import os
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
14 import sys
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
15 import signal
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
16 import re
45
035be8a9e982 Force reading of configuration in Unicode UTF-8.
Matti Hamalainen <ccr@tnsp.org>
parents: 44
diff changeset
17 import codecs
62
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
18 import math
73
b3f8621f1a25 Change how the target calendar settings work a bit. Also implement display
Matti Hamalainen <ccr@tnsp.org>
parents: 72
diff changeset
19 import time
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
20 from subprocess import Popen, PIPE
14
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
21
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
22 import smtplib
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
23 from email.mime.text import MIMEText
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
24
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
25 import httplib2
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
26 import ConfigParser
20
1f0e79d1766e Cosmetic.
Matti Hamalainen <ccr@tnsp.org>
parents: 19
diff changeset
27
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
28 import oauth2client
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
29 from oauth2client import client
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
30 from oauth2client import tools
4
ad1e3184c8e3 Add missing import.
Matti Hamalainen <ccr@tnsp.org>
parents: 3
diff changeset
31 from oauth2client import file
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
32 from googleapiclient import discovery
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
33
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
34
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
35 ###
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
36 ### Misc. helper functions, etc
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
37 ###
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
38
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
39 ## List of event tuple fields that should NOT be compared for equality
66
b08d159e35c7 Sanitize gcm_no_compare_fields[]
Matti Hamalainen <ccr@tnsp.org>
parents: 65
diff changeset
40 gcm_no_compare_fields = [
b08d159e35c7 Sanitize gcm_no_compare_fields[]
Matti Hamalainen <ccr@tnsp.org>
parents: 65
diff changeset
41 "id", "iCalUID", "etag", "sequence", "gcm_cal_id",
72
1ab40033bb87 Add 'creator' to event equality comparision excluded fields.
Matti Hamalainen <ccr@tnsp.org>
parents: 71
diff changeset
42 "created", "updated", "htmlLink", "organizer", "creator",
66
b08d159e35c7 Sanitize gcm_no_compare_fields[]
Matti Hamalainen <ccr@tnsp.org>
parents: 65
diff changeset
43 ]
b08d159e35c7 Sanitize gcm_no_compare_fields[]
Matti Hamalainen <ccr@tnsp.org>
parents: 65
diff changeset
44
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
45 ## List of logging levels from lowest to highest
76
a63cc3633adb Put log levels array into its own global variable.
Matti Hamalainen <ccr@tnsp.org>
parents: 75
diff changeset
46 gcm_log_levels = ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"]
a63cc3633adb Put log levels array into its own global variable.
Matti Hamalainen <ccr@tnsp.org>
parents: 75
diff changeset
47
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
48
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
49 def gcm_get_log_level():
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
50 return gcm_log_levels.index(cfg.logging_level)
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
51
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
52
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
53 ## Wrapper for print() that does not break when redirecting stdin/out
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
54 ## because of piped output not having a defined encoding. We default
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
55 ## to UTF-8 encoding in output here.
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
56 def gcm_print(smsg):
47
a8fdecd4be61 Fixes to Unicode handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 46
diff changeset
57 gcm_msgbuf.append(smsg)
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
58 if sys.stdout.encoding != None:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
59 print(smsg.encode(sys.stdout.encoding))
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
60 else:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
61 print(smsg.encode("UTF-8"))
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
62
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
63
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
64 ## Fatal error handler
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
65 def gcm_fatal(smsg):
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
66 gcm_print(u"ERROR: "+ smsg)
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
67 if cfg.email_ok and cfg.email != "off":
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
68 ## If e-mail is not "off", send e-mail
14
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
69 msg = MIMEText(("\n".join(gcm_msgbuf)).encode("UTF-8"), "plain")
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
70 msg.set_charset("UTF-8")
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
71 msg["Subject"] = cfg.email_subject
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
72 msg["From"] = cfg.email_sender
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
73 msg["To"] = ",".join(cfg.email_to)
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
74 gcm_print("Sending mail to {0} from {1}, subj: {2} ..".format(";".join(cfg.email_to), cfg.email_sender, cfg.email_subject))
14
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
75 try:
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
76 # Act based on email mode
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
77 if cfg.email == "smtp":
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
78 gcm_print("Using SMTP server {0}, login {1}".format(cfg.email_smtp_server, cfg.email_smtp_user))
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
79 server = smtplib.SMTP(cfg.email_smtp_server)
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
80 if gcm_check_debug(4):
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
81 server.set_debuglevel(10)
95
b5cc76f18256 Fix e-mail sending and implement basic TLS support for outgoing SMTP.
Matti Hamalainen <ccr@tnsp.org>
parents: 93
diff changeset
82
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
83 if cfg.email_smtp_tls:
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
84 server.starttls()
95
b5cc76f18256 Fix e-mail sending and implement basic TLS support for outgoing SMTP.
Matti Hamalainen <ccr@tnsp.org>
parents: 93
diff changeset
85
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
86 server.login(cfg.email_smtp_user, cfg.email_smtp_password)
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
87 server.sendmail(cfg.email_sender, cfg.email_to, msg.as_string())
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
88 server.quit()
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
89 elif cfg.email == "sendmail":
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
90 gcm_print("Using sendmail {0}".format(cfg.email_sendmail))
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
91 p = Popen([cfg.email_sendmail, "-t", "-oi"], stdin=PIPE)
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
92 p.communicate(msg.as_string())
70
d5e3ca4b609d Improve error handling when e-mail sending fails.
Matti Hamalainen <ccr@tnsp.org>
parents: 68
diff changeset
93 except Exception as e:
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
94 gcm_print(u"FATAL: Oh noes, e-mail sending failed: {0}".format(str(e)))
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
95 sys.exit(1)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
96
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
97
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
98 ## Debug messages
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
99 def gcm_check_debug(level):
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
100 return cfg.debug and gcm_get_log_level() >= level
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
101
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
102 def gcm_debug(level, smsg):
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
103 if gcm_check_debug(level):
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
104 gcm_print(u"DBG: {0}".format(smsg))
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
105 else:
47
a8fdecd4be61 Fixes to Unicode handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 46
diff changeset
106 gcm_msgbuf.append(u"DBG: {0}".format(smsg))
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
107
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
108
24
1bce0c6a673c Comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 23
diff changeset
109 ## Handler for SIGINT signals
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
110 def gcm_signal_handler(signal, frame):
54
86d3a8eddbd7 Unicodeify.
Matti Hamalainen <ccr@tnsp.org>
parents: 53
diff changeset
111 gcm_print(u"\nQuitting due to SIGINT / Ctrl+C!")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
112 sys.exit(0)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
113
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
114
24
1bce0c6a673c Comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 23
diff changeset
115 ## Function for handling Google API credentials
99
4b84bb5bb8b5 Make credential_file and secret_file arguments to gcm_get_credentials().
Matti Hamalainen <ccr@tnsp.org>
parents: 98
diff changeset
116 def gcm_get_credentials(mcfg, credential_file, secret_file):
42
ac949d2b268a Add some error handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 41
diff changeset
117 try:
99
4b84bb5bb8b5 Make credential_file and secret_file arguments to gcm_get_credentials().
Matti Hamalainen <ccr@tnsp.org>
parents: 98
diff changeset
118 store = oauth2client.file.Storage(credential_file)
42
ac949d2b268a Add some error handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 41
diff changeset
119 except Exception as e:
99
4b84bb5bb8b5 Make credential_file and secret_file arguments to gcm_get_credentials().
Matti Hamalainen <ccr@tnsp.org>
parents: 98
diff changeset
120 gcm_fatal(u"Failed to read credential file:\n{0}\n\nERROR: {1}\n".format(credential_file, str(e)))
42
ac949d2b268a Add some error handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 41
diff changeset
121
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
122 credentials = store.get()
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
123 if not credentials or credentials.invalid:
42
ac949d2b268a Add some error handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 41
diff changeset
124 try:
99
4b84bb5bb8b5 Make credential_file and secret_file arguments to gcm_get_credentials().
Matti Hamalainen <ccr@tnsp.org>
parents: 98
diff changeset
125 flow = client.flow_from_clientsecrets(secret_file, mcfg.scope)
42
ac949d2b268a Add some error handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 41
diff changeset
126 except Exception as e:
99
4b84bb5bb8b5 Make credential_file and secret_file arguments to gcm_get_credentials().
Matti Hamalainen <ccr@tnsp.org>
parents: 98
diff changeset
127 gcm_fatal(u"Failed to fetch client secret:\n{0}\n\nERROR: {1}\n".format(secret_file, str(e)))
42
ac949d2b268a Add some error handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 41
diff changeset
128
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
129 flow.user_agent = mcfg.app_name
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
130 credentials = tools.run_flow(flow, store, mcfg)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
131 if not credentials or credentials.invalid:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
132 gcm_fatal(u"Failed to authenticate / invalid credentials.")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
133 return credentials
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
134
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
135
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
136 ## Dump/print a given list of events for debugging purposes
103
fc361e368630 Improve gcm_dump_events() further by changing show parameter to a lambda
Matti Hamalainen <ccr@tnsp.org>
parents: 102
diff changeset
137 def gcm_dump_events(events, show):
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
138 for event in events:
103
fc361e368630 Improve gcm_dump_events() further by changing show parameter to a lambda
Matti Hamalainen <ccr@tnsp.org>
parents: 102
diff changeset
139 if show == None or show(event):
101
b5c381f9b51f Improve gcm_dump_events() to optionally show all events (deleted/cancelled).
Matti Hamalainen <ccr@tnsp.org>
parents: 100
diff changeset
140 ev_start = event["start"].get("dateTime", event["start"].get("date")) if "start" in event else "?"
b5c381f9b51f Improve gcm_dump_events() to optionally show all events (deleted/cancelled).
Matti Hamalainen <ccr@tnsp.org>
parents: 100
diff changeset
141 ev_end = event["end"].get("dateTime", event["end"].get("date")) if "end" in event else "?"
b5c381f9b51f Improve gcm_dump_events() to optionally show all events (deleted/cancelled).
Matti Hamalainen <ccr@tnsp.org>
parents: 100
diff changeset
142 summary = event["summary"] if "summary" in event else "?"
b5c381f9b51f Improve gcm_dump_events() to optionally show all events (deleted/cancelled).
Matti Hamalainen <ccr@tnsp.org>
parents: 100
diff changeset
143 status = "*" if event["status"] != u"cancelled" else "!"
104
f6274227114b Make debug/error messages more consistent.
Matti Hamalainen <ccr@tnsp.org>
parents: 103
diff changeset
144 gcm_print(u"[{0}] {1:25} - {2:25} : {3} [{4}] [{5}]".format(status, ev_start, ev_end, summary, event["iCalUID"], event["id"]))
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
145
56
597875ef885b Better debug prints.
Matti Hamalainen <ccr@tnsp.org>
parents: 55
diff changeset
146
597875ef885b Better debug prints.
Matti Hamalainen <ccr@tnsp.org>
parents: 55
diff changeset
147 ## Generate gcm IDs for given list of events
111
8b773358ad47 Use "id" field in source calendar events gcm_id generation, and "iCalUID" for the target calendar.
Matti Hamalainen <ccr@tnsp.org>
parents: 110
diff changeset
148 def gcm_generate_ids(events, calendar_id, sep, field):
26
1267d61f6224 Add function for generating unique internal IDs.
Matti Hamalainen <ccr@tnsp.org>
parents: 25
diff changeset
149 if not events:
1267d61f6224 Add function for generating unique internal IDs.
Matti Hamalainen <ccr@tnsp.org>
parents: 25
diff changeset
150 return events
1267d61f6224 Add function for generating unique internal IDs.
Matti Hamalainen <ccr@tnsp.org>
parents: 25
diff changeset
151
111
8b773358ad47 Use "id" field in source calendar events gcm_id generation, and "iCalUID" for the target calendar.
Matti Hamalainen <ccr@tnsp.org>
parents: 110
diff changeset
152 for event in events:
8b773358ad47 Use "id" field in source calendar events gcm_id generation, and "iCalUID" for the target calendar.
Matti Hamalainen <ccr@tnsp.org>
parents: 110
diff changeset
153 event["gcm_cal_id"] = calendar_id
8b773358ad47 Use "id" field in source calendar events gcm_id generation, and "iCalUID" for the target calendar.
Matti Hamalainen <ccr@tnsp.org>
parents: 110
diff changeset
154 event["gcm_id"] = calendar_id + sep + event[field]
26
1267d61f6224 Add function for generating unique internal IDs.
Matti Hamalainen <ccr@tnsp.org>
parents: 25
diff changeset
155
1267d61f6224 Add function for generating unique internal IDs.
Matti Hamalainen <ccr@tnsp.org>
parents: 25
diff changeset
156 return events
1267d61f6224 Add function for generating unique internal IDs.
Matti Hamalainen <ccr@tnsp.org>
parents: 25
diff changeset
157
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
158
53
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
159 ## Find event by its gcm_id from given list or return None if not found
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
160 def gcm_get_event_by_gcm_id(list, id):
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
161 for event in list:
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
162 if event["gcm_id"] == id:
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
163 return event
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
164 return None
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
165
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
166
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
167 ## Compare two given events for equality (except for excluded list of fields)
53
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
168 def gcm_compare_events(ev1, ev2):
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
169 for field in ev1:
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
170 if not field in gcm_no_compare_fields and ev1[field] != ev2[field]:
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
171 return False
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
172 return True
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
173
63
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
174
110
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
175 ## Fetch events for given calendar
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
176 def gcm_fetch_events(calendarId, showDeleted):
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
177 events = []
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
178 ev_token = None
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
179 while True:
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
180 try:
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
181 result = service.events().list(
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
182 calendarId=calendarId,
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
183 showDeleted=showDeleted,
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
184 singleEvents=False,
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
185 pageToken=ev_token,
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
186 ).execute()
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
187 except Exception as e:
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
188 gcm_fatal(u"Failed to fetch calendar events for {0}:\n\nERROR: {1}\n".format(calendarId, str(e)))
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
189
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
190 events.extend(result.get("items", []))
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
191 ev_token = result.get("nextPageToken")
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
192 if not ev_token:
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
193 break
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
194
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
195 return events
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
196
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
197
67
c582522d2dcc Add a comment.
Matti Hamalainen <ccr@tnsp.org>
parents: 66
diff changeset
198 ###
c582522d2dcc Add a comment.
Matti Hamalainen <ccr@tnsp.org>
parents: 66
diff changeset
199 ### Class for parsing and manipulating RGB colors
c582522d2dcc Add a comment.
Matti Hamalainen <ccr@tnsp.org>
parents: 66
diff changeset
200 ###
62
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
201 class GCMColor():
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
202 def __init__(self, src = None):
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
203 if src == None:
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
204 self.r = self.g = self.b = 0
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
205 elif isinstance(src, basestring):
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
206 if len(src) == 6:
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
207 self.r = int(src[0:2], 16)
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
208 self.g = int(src[2:4], 16)
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
209 self.b = int(src[4:6], 16)
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
210 elif len(src) == 7 and src[0] == "#":
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
211 self.r = int(src[1:3], 16)
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
212 self.g = int(src[3:5], 16)
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
213 self.b = int(src[6:7], 16)
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
214 else:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
215 gcm_fatal(u"Expected hex-triplet string for GCMColor() initializer: {0}".format(src))
62
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
216 elif isinstance(src, GCMColor):
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
217 self.r = src.r
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
218 self.g = src.g
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
219 self.b = src.b
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
220 else:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
221 gcm_fatal(u"Invalid initializer for GCMColor() object.")
62
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
222
106
205767356d2c Add two helper functions to GCMColor class.
Matti Hamalainen <ccr@tnsp.org>
parents: 105
diff changeset
223 def to_hexrgb():
205767356d2c Add two helper functions to GCMColor class.
Matti Hamalainen <ccr@tnsp.org>
parents: 105
diff changeset
224 return "{0:02X}{1:02X}{2:02X}".format(self.r, self.g, self.b)
205767356d2c Add two helper functions to GCMColor class.
Matti Hamalainen <ccr@tnsp.org>
parents: 105
diff changeset
225
205767356d2c Add two helper functions to GCMColor class.
Matti Hamalainen <ccr@tnsp.org>
parents: 105
diff changeset
226 def to_hexrgb_lc():
205767356d2c Add two helper functions to GCMColor class.
Matti Hamalainen <ccr@tnsp.org>
parents: 105
diff changeset
227 return "{0:02x}{1:02x}{2:02x}".format(self.r, self.g, self.b)
205767356d2c Add two helper functions to GCMColor class.
Matti Hamalainen <ccr@tnsp.org>
parents: 105
diff changeset
228
62
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
229 def delta(self, other):
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
230 ctmp = GCMColor()
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
231 ctmp.r = other.r - self.r
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
232 ctmp.g = other.g - self.g
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
233 ctmp.b = other.b - self.b
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
234 return ctmp
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
235
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
236 def dist(self, other):
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
237 ctmp = self.delta(other)
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
238 return math.sqrt(ctmp.r * ctmp.r + ctmp.g * ctmp.g + ctmp.b * ctmp.b)
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
239
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
240
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
241 def gcm_find_nearest_color(colors, cfind, maxdist):
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
242 c_fg = GCMColor(cfind["foreground"])
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
243 c_bg = GCMColor(cfind["background"])
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
244
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
245 bdist_fg = 99999999999
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
246 bdist_bg = 99999999999
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
247 best_fit = None
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
248 for id, col in colors.iteritems():
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
249 dist_fg = GCMColor(col["foreground"]).dist(c_fg)
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
250 dist_bg = GCMColor(col["background"]).dist(c_bg)
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
251 if dist_fg <= bdist_fg and dist_bg <= bdist_bg:
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
252 best_fit = id
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
253 bdist_fg = dist_fg
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
254 bdist_bg = dist_bg
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
255
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
256 if bdist_fg <= maxdist and bdist_bg <= maxdist:
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
257 return best_fit
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
258 else:
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
259 return None
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
260
53
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
261
24
1bce0c6a673c Comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 23
diff changeset
262 ##
1bce0c6a673c Comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 23
diff changeset
263 ## Class for handling configuration / settings
1bce0c6a673c Comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 23
diff changeset
264 ##
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
265 class GCMSettings(dict):
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
266 def __init__(self):
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
267 self.m_data = {}
92
a348dfa6b132 Rename a variable/class member.
Matti Hamalainen <ccr@tnsp.org>
parents: 89
diff changeset
268 self.m_settable = {}
5
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
269 self.m_validate = {}
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
270 self.m_translate = {}
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
271
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
272 def __getattr__(self, name):
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
273 if name in self.m_data:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
274 return self.m_data[name]
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
275 else:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
276 gcm_fatal(u"GCMSettings.__getattr__(): No such attribute '"+ name +"'.")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
277
5
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
278 def mvalidate(self, name, value):
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
279 if name in self.m_validate and self.m_validate[name]:
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
280 if not self.m_validate[name](value):
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
281 gcm_fatal(u"GCMSettings.mvalidate(): Invalid value for attribute '{0}': {1}".format(name, value))
5
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
282
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
283 def mtranslate(self, name, value):
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
284 if name in self.m_translate and self.m_translate[name]:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
285 return self.m_translate[name](value)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
286 else:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
287 return value
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
288
92
a348dfa6b132 Rename a variable/class member.
Matti Hamalainen <ccr@tnsp.org>
parents: 89
diff changeset
289 def mdef(self, name, settable, validate, translate, value):
5
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
290 self.mvalidate(name, value)
92
a348dfa6b132 Rename a variable/class member.
Matti Hamalainen <ccr@tnsp.org>
parents: 89
diff changeset
291 self.m_settable[name] = settable
5
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
292 self.m_validate[name] = validate
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
293 self.m_translate[name] = translate
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
294 self.m_data[name] = self.mtranslate(name, value)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
295
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
296 def mset(self, name, value):
5
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
297 self.mvalidate(name, value)
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
298 if name in self.m_data:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
299 self.m_data[name] = self.mtranslate(name, value)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
300 else:
43
a331209e24fc Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 42
diff changeset
301 gcm_fatal(u"GCMSettings.mset(): No such attribute '"+ name +"'.")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
302
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
303 def mget(self, name):
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
304 if name in self.m_data:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
305 return self.m_data[name]
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
306 else:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
307 return None
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
308
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
309 def mread(self, cfg_parser, sect):
92
a348dfa6b132 Rename a variable/class member.
Matti Hamalainen <ccr@tnsp.org>
parents: 89
diff changeset
310 for name in self.m_settable:
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
311 if cfg_parser.has_option(sect, name):
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
312 value = cfg_parser.get(sect, name)
6
ee6bf617f839 Implement configuration file reading.
Matti Hamalainen <ccr@tnsp.org>
parents: 5
diff changeset
313 self.mset(name, value)
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
314 gcm_debug(4, u"{0} -> '{1}' == {2}".format(name, value, self.mget(name)))
6
ee6bf617f839 Implement configuration file reading.
Matti Hamalainen <ccr@tnsp.org>
parents: 5
diff changeset
315
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
316 def is_str(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
317 return isinstance(mvalue, basestring)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
318
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
319 def is_string(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
320 return mvalue == None or self.is_str(mvalue)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
321
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
322 def is_log_level(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
323 if not self.is_str(mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
324 return False
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
325 else:
76
a63cc3633adb Put log levels array into its own global variable.
Matti Hamalainen <ccr@tnsp.org>
parents: 75
diff changeset
326 return mvalue.upper() in gcm_log_levels
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
327
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
328 def trans_log_level(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
329 return mvalue.upper()
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
330
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
331 def is_email_state(self, mvalue):
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
332 if not self.is_str(mvalue):
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
333 return False
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
334 else:
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
335 return mvalue.lower() in [u"off", u"sendmail", u"smtp"]
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
336
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
337 def trans_email_state(self, mvalue):
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
338 return mvalue.lower()
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
339
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
340 def is_filename(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
341 if not self.is_str(mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
342 return False
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
343 else:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
344 return re.match("^[a-z0-9][a-z0-9\.\_\-]+$", mvalue, flags=re.IGNORECASE)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
345
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
346 def trans_bool(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
347 if self.is_str(mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
348 if re.match("^\s*(true|1|on|yes)\s*$", mvalue, re.IGNORECASE):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
349 mvalue = True
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
350 elif re.match("^\s*(false|0|off|no)\s*$", mvalue, re.IGNORECASE):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
351 mvalue = False
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
352 else:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
353 return None
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
354 return mvalue
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
355
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
356 def is_bool(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
357 mval = self.trans_bool(mvalue)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
358 if not isinstance(mval, bool):
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
359 gcm_fatal(u"GCMSettings.is_bool(): Invalid boolean value '{0}', should be true|false|1|0|on|off|yes|no.".format(mvalue))
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
360 else:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
361 return True
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
362
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
363 def trans_list(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
364 morig = mvalue
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
365 if self.is_str(mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
366 mvalue = re.split("\s*,\s*", mvalue, flags=re.IGNORECASE)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
367 if not isinstance(mvalue, list):
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
368 gcm_fatal(u"GCMSettings.trans_list(): Could not parse list '{0}'.".format(mvalue))
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
369 elif not isinstance(mvalue, list):
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
370 gcm_fatal(u"GCMSettings.trans_list(): Invalid value '{0}'.".format(mvalue))
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
371 return mvalue
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
372
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
373 def is_list(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
374 return self.trans_list(mvalue)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
375
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
376 def is_email(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
377 if not self.is_string(mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
378 return False
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
379 else:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
380 return re.match("^.*?\s+<[a-z0-9]+[a-z0-9\.\+\-]*\@[a-z0-9]+[a-z0-9\.\-]+>\s*$|[a-z0-9]+[a-z0-9\.\+\-]*\@[a-z0-9]+[a-z0-9\.\-]+", mvalue, flags=re.IGNORECASE)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
381
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
382 def trans_email_list(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
383 if mvalue == None:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
384 return mvalue
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
385 else:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
386 return self.trans_list(mvalue.strip())
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
387
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
388 def is_email_list(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
389 mvalue = self.trans_email_list(mvalue)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
390 if mvalue != None:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
391 for email in mvalue:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
392 if not self.is_email(email):
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
393 gcm_fatal(u"Invalid e-mail address '{0}' in list {1}.".format(email, ", ".join(mvalue)))
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
394 return True
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
395
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
396
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
397 ###
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
398 ### Main program starts
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
399 ###
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
400 gcm_msgbuf = []
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
401 signal.signal(signal.SIGINT, gcm_signal_handler)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
402
87
c3f8af496f46 Add "execution time elapsed" metering.
Matti Hamalainen <ccr@tnsp.org>
parents: 86
diff changeset
403 gcm_bench_start = time.time()
c3f8af496f46 Add "execution time elapsed" metering.
Matti Hamalainen <ccr@tnsp.org>
parents: 86
diff changeset
404
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
405
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
406 ## Define all the settings
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
407 cfg_section = "gcm"
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
408 cfg = GCMSettings()
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
409
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
410 cfg.mdef("debug", True, cfg.is_bool, cfg.trans_bool, False)
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
411
14
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
412 cfg.mdef("email_ok", False, None, None, False)
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
413 cfg.mdef("email", True, cfg.is_email_state, cfg.trans_email_state, u"off")
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
414
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
415 cfg.mdef("email_to", True, cfg.is_email_list, cfg.trans_email_list, None)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
416 cfg.mdef("email_sender", True, cfg.is_email, None, None)
49
cc30383f5f0d More Unicode fixes.
Matti Hamalainen <ccr@tnsp.org>
parents: 47
diff changeset
417 cfg.mdef("email_subject", True, cfg.is_string, None, u"Google Calendar MultiMerge status")
95
b5cc76f18256 Fix e-mail sending and implement basic TLS support for outgoing SMTP.
Matti Hamalainen <ccr@tnsp.org>
parents: 93
diff changeset
418
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
419 cfg.mdef("email_sendmail", True, cfg.is_string, None, "/usr/sbin/sendmail")
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
420 cfg.mdef("email_smtp_tls", True, cfg.is_bool, cfg.trans_bool, False)
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
421 cfg.mdef("email_smtp_server", True, cfg.is_string, None, None)
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
422 cfg.mdef("email_smtp_user", True, cfg.is_string, None, None)
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
423 cfg.mdef("email_smtp_password", True, cfg.is_string, None, None)
14
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
424
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
425 cfg.mdef("src_regex", True, cfg.is_string, None, u"^R:\s*(.*?)\s*\(\s*(.+?)\s*\)\s*$")
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
426 cfg.mdef("src_regmap", False, cfg.is_list, cfg.trans_list, [1, 2])
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
427 cfg.mdef("src_regmap_len", False, None, None, len(cfg.src_regmap))
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
428
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
429 cfg.mdef("dst_name", True, cfg.is_string, None, None)
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
430 cfg.mdef("dst_regex", True, cfg.is_string, None, None)
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
431 cfg.mdef("dst_id", True, cfg.is_string, None, None)
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
432
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
433 cfg.mdef("noauth_local_webserver", False, None, None, True)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
434 #cfg.mdef("auth_host_name", False, None, None, "localhost")
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
435 #cfg.mdef("auth_host_port", False, None, None, [8080, 8090])
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
436 cfg.mdef("logging_level", True, cfg.is_log_level, cfg.trans_log_level, "ERROR")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
437
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
438 # No need to touch these
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
439 cfg.mdef("app_name", False, None, None, "Google Calendar MultiMerge")
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
440 cfg.mdef("scope", False, None, None, "https://www.googleapis.com/auth/calendar")
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
441 #cfg.mdef("scope", False, None, None, "https://www.googleapis.com/auth/calendar.readonly")
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
442 cfg.mdef("secret_file", True, cfg.is_filename, None, "client_secret.json")
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
443 cfg.mdef("credential_file", True, cfg.is_filename, None, "client_credentials.json")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
444
6
ee6bf617f839 Implement configuration file reading.
Matti Hamalainen <ccr@tnsp.org>
parents: 5
diff changeset
445
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
446 ## Check if we have arguments
89
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
447 if len(sys.argv) <= 1:
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
448 gcm_fatal(u"No configuration file specified.\nUsage: {0} <configfile>".format(sys.argv[0]))
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
449
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
450
6
ee6bf617f839 Implement configuration file reading.
Matti Hamalainen <ccr@tnsp.org>
parents: 5
diff changeset
451 ## Read, parse and validate configuration file
89
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
452 gcm_debug(3, u"Reading configuration from '{0}'.".format(sys.argv[1]))
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
453 try:
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
454 cfg_parser = ConfigParser.RawConfigParser()
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
455 cfg_parser.readfp(codecs.open(sys.argv[1], "r", "UTF-8"))
89
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
456 except Exception as e:
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
457 gcm_fatal(u"Failed to read configuration file '{0}': {1}".format(sys.argv[1], str(e)))
6
ee6bf617f839 Implement configuration file reading.
Matti Hamalainen <ccr@tnsp.org>
parents: 5
diff changeset
458
89
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
459 # Check that the required section exists
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
460 if not cfg_parser.has_section(cfg_section):
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
461 gcm_fatal(u"Invalid configuration, missing '{0}' section.".format(cfg_section))
7
f2ecfb3e04ee Check that the required section exists in configuration.
Matti Hamalainen <ccr@tnsp.org>
parents: 6
diff changeset
462
89
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
463 # Debug setting is a special case, we need to get it
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
464 # set before everything else, so do it here ..
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
465 if cfg_parser.has_option(cfg_section, "debug"):
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
466 cfg.mset("debug", cfg_parser.get(cfg_section, "debug"))
10
b237b96602ad We need to handle "debug" setting before other settings, so we need a
Matti Hamalainen <ccr@tnsp.org>
parents: 9
diff changeset
467
89
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
468 # Parse the settings and validate
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
469 cfg.mread(cfg_parser, cfg_section)
6
ee6bf617f839 Implement configuration file reading.
Matti Hamalainen <ccr@tnsp.org>
parents: 5
diff changeset
470
8
8367463fe94d Post-validate some settings.
Matti Hamalainen <ccr@tnsp.org>
parents: 7
diff changeset
471
8367463fe94d Post-validate some settings.
Matti Hamalainen <ccr@tnsp.org>
parents: 7
diff changeset
472 ## Validate settings
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
473 if cfg.email != "off":
14
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
474 if cfg.email_subject == None or len(cfg.email_subject) == 0:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
475 gcm_fatal(u"E-mail enabled but email_subject not set.")
14
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
476 elif cfg.email_sender == None:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
477 gcm_fatal(u"E-mail enabled but email_sender not set.")
14
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
478 elif cfg.email_to == None:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
479 gcm_fatal(u"E-mail enabled but email_to not set.")
14
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
480 else:
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
481 cfg.mset("email_ok", True)
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
482
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
483
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
484 if len(cfg.src_regmap) != cfg.src_regmap_len:
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
485 gcm_fatal(u"Setting src_regmap list must be {0} items.".format(cfg.src_regmap_len))
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
486 else:
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
487 # Force to integers
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
488 try:
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
489 cfg.src_regmap = map(lambda x: int(x), cfg.src_regmap)
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
490 except Exception as e:
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
491 gcm_fatal(u"Invalid src_regmap: {0}".format(str(e)))
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
492
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
493
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
494 if not cfg.dst_regex and not cfg.dst_id:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
495 gcm_fatal(u"Target calendar ID or name required, but not set.")
8
8367463fe94d Post-validate some settings.
Matti Hamalainen <ccr@tnsp.org>
parents: 7
diff changeset
496
8367463fe94d Post-validate some settings.
Matti Hamalainen <ccr@tnsp.org>
parents: 7
diff changeset
497
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
498 ## Initialize and authorize API connection
99
4b84bb5bb8b5 Make credential_file and secret_file arguments to gcm_get_credentials().
Matti Hamalainen <ccr@tnsp.org>
parents: 98
diff changeset
499 credentials = gcm_get_credentials(cfg, cfg.credential_file, cfg.secret_file)
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
500 http = credentials.authorize(httplib2.Http())
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
501 service = discovery.build("calendar", "v3", http=http)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
502
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
503
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
504 ## Fetch complete calendar list
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
505 gcm_debug(3, u"Fetching available calendars ..")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
506 calendars = []
19
095209b1ded3 Rename some variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 18
diff changeset
507 cal_token = None
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
508 while True:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
509 # We want everything except deleted and hidden calendars
109
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
510 try:
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
511 result = service.calendarList().list(
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
512 showHidden=False,
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
513 showDeleted=False,
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
514 pageToken=cal_token
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
515 ).execute()
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
516 except Exception as e:
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
517 gcm_fatal(u"Failed to fetch calendar list:\n\nERROR: {0}\n".format(str(e)))
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
518
17
4168dde804ae Rename some variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 14
diff changeset
519 calendars.extend(result.get("items", []))
19
095209b1ded3 Rename some variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 18
diff changeset
520 cal_token = result.get("nextPageToken")
095209b1ded3 Rename some variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 18
diff changeset
521 if not cal_token:
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
522 break
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
523
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
524 if len(calendars) == 0:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
525 gcm_fatal(u"No calendars found?")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
526
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
527 gcm_debug(3, u"{0} calendars total found.".format(len(calendars)))
50
f8618bae162a Improve debug messages and comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 49
diff changeset
528
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
529
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
530 ## Filter desired SOURCE calendars based on specified regexp
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
531 src_re = re.compile(cfg.src_regex, re.UNICODE)
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
532 dst_re = re.compile(cfg.dst_regex, re.UNICODE)
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
533 src_calendars = []
60
37705c4a35e1 Show target calendar information in debug mode.
Matti Hamalainen <ccr@tnsp.org>
parents: 59
diff changeset
534 dst_calendar = None
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
535 for calendar in calendars:
51
54644b29a9a3 Match also summaryOverride attribute against the source calendar regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 50
diff changeset
536 if u"summary" in calendar:
50
f8618bae162a Improve debug messages and comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 49
diff changeset
537 # Find destination calendar ID if not set
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
538 if not cfg.dst_id and dst_re.match(calendar["summary"]):
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
539 cfg.mset("dst_id", calendar["id"])
60
37705c4a35e1 Show target calendar information in debug mode.
Matti Hamalainen <ccr@tnsp.org>
parents: 59
diff changeset
540 dst_calendar = calendar
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
541 elif cfg.dst_id and calendar["id"] == cfg.dst_id:
86
d9e799a27ceb Make cfg.dest_id actually work.
Matti Hamalainen <ccr@tnsp.org>
parents: 85
diff changeset
542 dst_calendar = calendar
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
543
51
54644b29a9a3 Match also summaryOverride attribute against the source calendar regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 50
diff changeset
544 # If summary or summaryOverride match the regexp, add calendar
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
545 mre = src_re.match(calendar["summary"])
52
b87dbc887f63 Simplify.
Matti Hamalainen <ccr@tnsp.org>
parents: 51
diff changeset
546 if not mre and u"summaryOverride" in calendar:
114
591cc558bbcd Use summaryOverride field as summary for calendars where it is being matched
Matti Hamalainen <ccr@tnsp.org>
parents: 113
diff changeset
547 mre = src_re.match(calendar["summaryOverride"])
591cc558bbcd Use summaryOverride field as summary for calendars where it is being matched
Matti Hamalainen <ccr@tnsp.org>
parents: 113
diff changeset
548 calendar["summary"] = calendar["summaryOverride"]
52
b87dbc887f63 Simplify.
Matti Hamalainen <ccr@tnsp.org>
parents: 51
diff changeset
549
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
550 if mre:
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
551 calendar["gcm_title"] = mre.group(cfg.src_regmap[0])
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
552 calendar["gcm_id"] = mre.group(cfg.src_regmap[1])
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
553 src_calendars.append(calendar)
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
554
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
555 gcm_debug(3, u"{0} source calendars found.".format(len(src_calendars)))
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
556
50
f8618bae162a Improve debug messages and comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 49
diff changeset
557
f8618bae162a Improve debug messages and comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 49
diff changeset
558 ## Check if we have destination calendar ID
60
37705c4a35e1 Show target calendar information in debug mode.
Matti Hamalainen <ccr@tnsp.org>
parents: 59
diff changeset
559 if not dst_calendar:
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
560 gcm_fatal(u"Could not find target/destination calendar ID for '"+ cfg.dst_name +"'.")
60
37705c4a35e1 Show target calendar information in debug mode.
Matti Hamalainen <ccr@tnsp.org>
parents: 59
diff changeset
561 else:
93
46c1a3b6135a Cosmetic.
Matti Hamalainen <ccr@tnsp.org>
parents: 92
diff changeset
562 gcm_debug(3, u"Target calendar '{0}' [ ID: {1} ]".format(dst_calendar["summary"], dst_calendar["id"]))
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
563
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
564
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
565 ## Fetch calendar colors data
62
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
566 try:
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
567 colors = service.colors().get().execute()
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
568 except Exception as e:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
569 gcm_fatal(u"Failed to fetch calendar color settings:\n\n{0}".format(str(e)))
62
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
570
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
571
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
572 ## Now, fetch and collect events from source calendars
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
573 gcm_debug(3, u"Fetching calendar events .. ")
19
095209b1ded3 Rename some variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 18
diff changeset
574 src_events = []
11
fcdee7c04ed8 Implement fetching of source events.
Matti Hamalainen <ccr@tnsp.org>
parents: 10
diff changeset
575 for calendar in src_calendars:
97
524915af5e87 Cosmetics.
Matti Hamalainen <ccr@tnsp.org>
parents: 95
diff changeset
576 gcm_debug(4, u"- {0} ({1})".format(calendar["id"], calendar["summary"]))
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
577
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
578 # Find matching color from the source calendar for the event, if one has been set
62
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
579 c_found = None
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
580 if "colorId" in calendar and calendar["colorId"] in colors["calendar"]:
97
524915af5e87 Cosmetics.
Matti Hamalainen <ccr@tnsp.org>
parents: 95
diff changeset
581 gcm_debug(4, u" Calendar color: {0}".format(colors["calendar"][calendar["colorId"]]))
62
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
582 c_found = gcm_find_nearest_color(colors["event"], colors["calendar"][calendar["colorId"]], 100)
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
583 if c_found:
97
524915af5e87 Cosmetics.
Matti Hamalainen <ccr@tnsp.org>
parents: 95
diff changeset
584 gcm_debug(4, u" Found nearest event color ID: {0}, {1}".format(c_found, colors["event"][c_found]))
62
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
585 else:
97
524915af5e87 Cosmetics.
Matti Hamalainen <ccr@tnsp.org>
parents: 95
diff changeset
586 gcm_debug(4, u" No matching event color found!")
62
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
587
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
588 # Fetch and add events, if any, to main source events list
111
8b773358ad47 Use "id" field in source calendar events gcm_id generation, and "iCalUID" for the target calendar.
Matti Hamalainen <ccr@tnsp.org>
parents: 110
diff changeset
589 events = gcm_generate_ids(gcm_fetch_events(calendar["id"], False), calendar["id"], "___", "id")
11
fcdee7c04ed8 Implement fetching of source events.
Matti Hamalainen <ccr@tnsp.org>
parents: 10
diff changeset
590 if events:
31
6becdaa5c45f Set event colors (just sequentially now) based on which source calendar they belong to.
Matti Hamalainen <ccr@tnsp.org>
parents: 30
diff changeset
591 for event in events:
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
592 # Set summary and color for existing events
102
7ab6beb4c709 Only generate summaries and colors for non-deleted/cancelled events.
Matti Hamalainen <ccr@tnsp.org>
parents: 101
diff changeset
593 if event["status"] != u"cancelled":
7ab6beb4c709 Only generate summaries and colors for non-deleted/cancelled events.
Matti Hamalainen <ccr@tnsp.org>
parents: 101
diff changeset
594 if c_found != None:
7ab6beb4c709 Only generate summaries and colors for non-deleted/cancelled events.
Matti Hamalainen <ccr@tnsp.org>
parents: 101
diff changeset
595 event["colorId"] = c_found
7ab6beb4c709 Only generate summaries and colors for non-deleted/cancelled events.
Matti Hamalainen <ccr@tnsp.org>
parents: 101
diff changeset
596 event["summary"] = u"[{1}] {0}".format(event["summary"], calendar["gcm_id"])
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
597
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
598 # Add to list of source events
21
f392d495c5b6 We need to extend a list, not append to it.
Matti Hamalainen <ccr@tnsp.org>
parents: 20
diff changeset
599 src_events.extend(events)
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
600 if gcm_check_debug(4):
103
fc361e368630 Improve gcm_dump_events() further by changing show parameter to a lambda
Matti Hamalainen <ccr@tnsp.org>
parents: 102
diff changeset
601 gcm_dump_events(events, (lambda ev: ev["status"] != u"cancelled"))
11
fcdee7c04ed8 Implement fetching of source events.
Matti Hamalainen <ccr@tnsp.org>
parents: 10
diff changeset
602
fcdee7c04ed8 Implement fetching of source events.
Matti Hamalainen <ccr@tnsp.org>
parents: 10
diff changeset
603
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
604 ## Fetch current events from the target
84
16edb168daa1 No need to display target calendar ID twice.
Matti Hamalainen <ccr@tnsp.org>
parents: 81
diff changeset
605 gcm_debug(3, u"Fetching current target calendar events.")
111
8b773358ad47 Use "id" field in source calendar events gcm_id generation, and "iCalUID" for the target calendar.
Matti Hamalainen <ccr@tnsp.org>
parents: 110
diff changeset
606 dst_events = gcm_generate_ids(gcm_fetch_events(cfg.dst_id, True), "", "", "iCalUID")
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
607 gcm_debug(3, u"Found {0} event(s).".format(len(dst_events)))
58
87fda54f935c Cleanup.
Matti Hamalainen <ccr@tnsp.org>
parents: 57
diff changeset
608
13
dd240a7ad913 Fetch current events in destination calendar.
Matti Hamalainen <ccr@tnsp.org>
parents: 11
diff changeset
609
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
610 ## Start populating/updating events ..
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
611 gcm_debug(3, u"Re-merging events to target calendar ..")
55
5b78f62b7de7 More work on merging stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 54
diff changeset
612 dst_ids = frozenset(map(lambda x: x["gcm_id"], dst_events))
5b78f62b7de7 More work on merging stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 54
diff changeset
613 src_ids = frozenset(map(lambda x: x["gcm_id"], src_events))
27
824c3e5c6757 Work on event merging.
Matti Hamalainen <ccr@tnsp.org>
parents: 26
diff changeset
614
81
ce02c0c00e64 Add debug information about how many events were new, updated or unchanged.
Matti Hamalainen <ccr@tnsp.org>
parents: 80
diff changeset
615 evn_new = evn_updated = evn_unchanged = 0
ce02c0c00e64 Add debug information about how many events were new, updated or unchanged.
Matti Hamalainen <ccr@tnsp.org>
parents: 80
diff changeset
616
27
824c3e5c6757 Work on event merging.
Matti Hamalainen <ccr@tnsp.org>
parents: 26
diff changeset
617 for event in src_events:
824c3e5c6757 Work on event merging.
Matti Hamalainen <ccr@tnsp.org>
parents: 26
diff changeset
618 # Does the event exist already in the target?
55
5b78f62b7de7 More work on merging stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 54
diff changeset
619 if event["gcm_id"] in dst_ids:
39
693db3f8cbe5 Begin importing event comparision stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 38
diff changeset
620 # Check if event NEEDS updating .. aka compare data
104
f6274227114b Make debug/error messages more consistent.
Matti Hamalainen <ccr@tnsp.org>
parents: 103
diff changeset
621 gcm_debug(4, u"Event {0} [{1}] exists, checking ..".format(event["id"], event["gcm_id"]))
53
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
622 d_event = gcm_get_event_by_gcm_id(dst_events, event["gcm_id"])
55
5b78f62b7de7 More work on merging stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 54
diff changeset
623 if not gcm_compare_events(event, d_event):
57
1c2cf6170219 Comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 56
diff changeset
624 # Seems we need to update
104
f6274227114b Make debug/error messages more consistent.
Matti Hamalainen <ccr@tnsp.org>
parents: 103
diff changeset
625 gcm_debug(4, u"Updating event {0} [{1}]".format(event["id"], event["gcm_id"]))
39
693db3f8cbe5 Begin importing event comparision stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 38
diff changeset
626 try:
55
5b78f62b7de7 More work on merging stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 54
diff changeset
627 event.pop("sequence", None)
63
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
628 event.pop("id", None)
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
629 event["iCalUID"] = event["gcm_id"]
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
630 new_event = service.events().update(calendarId=cfg.dst_id, eventId=d_event["id"], body=event).execute()
105
481cfea49e19 Update counters only per successful operation.
Matti Hamalainen <ccr@tnsp.org>
parents: 104
diff changeset
631 evn_updated += 1
39
693db3f8cbe5 Begin importing event comparision stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 38
diff changeset
632 except Exception as e:
104
f6274227114b Make debug/error messages more consistent.
Matti Hamalainen <ccr@tnsp.org>
parents: 103
diff changeset
633 gcm_fatal(u"Failed to update event {0} [{1}]:\n\n{2}\n\nERROR: {3}\n".format(event["id"], event["gcm_id"], event, str(e)))
39
693db3f8cbe5 Begin importing event comparision stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 38
diff changeset
634 else:
81
ce02c0c00e64 Add debug information about how many events were new, updated or unchanged.
Matti Hamalainen <ccr@tnsp.org>
parents: 80
diff changeset
635 evn_unchanged += 1
104
f6274227114b Make debug/error messages more consistent.
Matti Hamalainen <ccr@tnsp.org>
parents: 103
diff changeset
636 gcm_debug(4, u"No need to update event {0} [{1}]".format(event["id"], event["gcm_id"]))
f6274227114b Make debug/error messages more consistent.
Matti Hamalainen <ccr@tnsp.org>
parents: 103
diff changeset
637 elif event["status"] != u"cancelled":
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
638 # Event does not seem to exist. Insert new event.
104
f6274227114b Make debug/error messages more consistent.
Matti Hamalainen <ccr@tnsp.org>
parents: 103
diff changeset
639 gcm_debug(4, u"Inserting new event {0} [{1}]".format(event["id"], event["gcm_id"]))
63
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
640 event.pop("id", None)
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
641 event["iCalUID"] = event["gcm_id"] # Replace Google generated ID with our own
34
125c4cbca3ad Event merging work.
Matti Hamalainen <ccr@tnsp.org>
parents: 33
diff changeset
642 try:
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
643 new_event = service.events().insert(calendarId=cfg.dst_id, body=event).execute()
105
481cfea49e19 Update counters only per successful operation.
Matti Hamalainen <ccr@tnsp.org>
parents: 104
diff changeset
644 evn_new += 1
34
125c4cbca3ad Event merging work.
Matti Hamalainen <ccr@tnsp.org>
parents: 33
diff changeset
645 except Exception as e:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
646 gcm_fatal(u"Failed to insert new event:\n\n{0}\n\nERROR: {1}\n".format(event, str(e)))
63
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
647
81
ce02c0c00e64 Add debug information about how many events were new, updated or unchanged.
Matti Hamalainen <ccr@tnsp.org>
parents: 80
diff changeset
648 gcm_debug(3, "{0} new events, {1} updated, {2} unchanged.".format(evn_new, evn_updated, evn_unchanged))
ce02c0c00e64 Add debug information about how many events were new, updated or unchanged.
Matti Hamalainen <ccr@tnsp.org>
parents: 80
diff changeset
649
34
125c4cbca3ad Event merging work.
Matti Hamalainen <ccr@tnsp.org>
parents: 33
diff changeset
650
125c4cbca3ad Event merging work.
Matti Hamalainen <ccr@tnsp.org>
parents: 33
diff changeset
651 ## Remove "stale" events
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
652 gcm_debug(3, u"Purging stale events ..")
85
da09a3b1edaa Count and report number of purged events.
Matti Hamalainen <ccr@tnsp.org>
parents: 84
diff changeset
653 evn_purged = 0
38
54405de302d0 Attempt to delete stale events. Still needs a check for already deleted
Matti Hamalainen <ccr@tnsp.org>
parents: 37
diff changeset
654 for event in dst_events:
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
655 gcm_debug(4, u"Checking event {0}".format(event["gcm_id"]))
55
5b78f62b7de7 More work on merging stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 54
diff changeset
656 if not event["gcm_id"] in src_ids and event["status"] != u"cancelled":
104
f6274227114b Make debug/error messages more consistent.
Matti Hamalainen <ccr@tnsp.org>
parents: 103
diff changeset
657 gcm_debug(4, u"Deleting event {0} [{1}]".format(event["id"], event["gcm_id"]))
85
da09a3b1edaa Count and report number of purged events.
Matti Hamalainen <ccr@tnsp.org>
parents: 84
diff changeset
658 evn_purged += 1
63
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
659 try:
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
660 service.events().delete(calendarId=cfg.dst_id, eventId=event["id"]).execute()
63
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
661 except Exception as e:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
662 gcm_fatal(u"Failed to delete stale event:\n{0}\n\nERROR: {1}\n".format(event, str(e)))
38
54405de302d0 Attempt to delete stale events. Still needs a check for already deleted
Matti Hamalainen <ccr@tnsp.org>
parents: 37
diff changeset
663
85
da09a3b1edaa Count and report number of purged events.
Matti Hamalainen <ccr@tnsp.org>
parents: 84
diff changeset
664 gcm_debug(3, "{0} events purged.".format(evn_purged))
da09a3b1edaa Count and report number of purged events.
Matti Hamalainen <ccr@tnsp.org>
parents: 84
diff changeset
665
da09a3b1edaa Count and report number of purged events.
Matti Hamalainen <ccr@tnsp.org>
parents: 84
diff changeset
666
75
ee05430f1a4d Update comment.
Matti Hamalainen <ccr@tnsp.org>
parents: 73
diff changeset
667 ##
ee05430f1a4d Update comment.
Matti Hamalainen <ccr@tnsp.org>
parents: 73
diff changeset
668 ## Finally, update the calendar name with timestamp
ee05430f1a4d Update comment.
Matti Hamalainen <ccr@tnsp.org>
parents: 73
diff changeset
669 ##
73
b3f8621f1a25 Change how the target calendar settings work a bit. Also implement display
Matti Hamalainen <ccr@tnsp.org>
parents: 72
diff changeset
670 t_time = time.localtime()
b3f8621f1a25 Change how the target calendar settings work a bit. Also implement display
Matti Hamalainen <ccr@tnsp.org>
parents: 72
diff changeset
671 t_str = time.strftime("%d.%m.%Y %H:%M", t_time)
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
672 gcm_debug(3, u"Updating target calendar name timestamp {0}".format(t_str))
73
b3f8621f1a25 Change how the target calendar settings work a bit. Also implement display
Matti Hamalainen <ccr@tnsp.org>
parents: 72
diff changeset
673
b3f8621f1a25 Change how the target calendar settings work a bit. Also implement display
Matti Hamalainen <ccr@tnsp.org>
parents: 72
diff changeset
674 try:
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
675 dst_calendar["summary"] = cfg.dst_name.format(t_str)
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
676 new_calendar = service.calendars().update(calendarId=cfg.dst_id, body=dst_calendar).execute()
73
b3f8621f1a25 Change how the target calendar settings work a bit. Also implement display
Matti Hamalainen <ccr@tnsp.org>
parents: 72
diff changeset
677 except Exception as e:
b3f8621f1a25 Change how the target calendar settings work a bit. Also implement display
Matti Hamalainen <ccr@tnsp.org>
parents: 72
diff changeset
678 gcm_fatal(u"Failed to update target calendar:\n{0}\n\nERROR: {1}\n".format(dst_calendar, str(e)))
b3f8621f1a25 Change how the target calendar settings work a bit. Also implement display
Matti Hamalainen <ccr@tnsp.org>
parents: 72
diff changeset
679
27
824c3e5c6757 Work on event merging.
Matti Hamalainen <ccr@tnsp.org>
parents: 26
diff changeset
680
87
c3f8af496f46 Add "execution time elapsed" metering.
Matti Hamalainen <ccr@tnsp.org>
parents: 86
diff changeset
681 gcm_bench_end = time.time()
c3f8af496f46 Add "execution time elapsed" metering.
Matti Hamalainen <ccr@tnsp.org>
parents: 86
diff changeset
682 gcm_bench_elapsed = gcm_bench_end - gcm_bench_start
c3f8af496f46 Add "execution time elapsed" metering.
Matti Hamalainen <ccr@tnsp.org>
parents: 86
diff changeset
683
c3f8af496f46 Add "execution time elapsed" metering.
Matti Hamalainen <ccr@tnsp.org>
parents: 86
diff changeset
684 gcm_debug(3, u"Finished. {0} seconds elapsed.".format(gcm_bench_elapsed))