annotate multimerge.py @ 131:654b28ca9f39

Minor fix.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 11 Nov 2019 13:47:39 +0200
parents b33e3884182b
children 16404eaf35df
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>
130
b33e3884182b Update copyright years.
Matti Hamalainen <ccr@tnsp.org>
parents: 129
diff changeset
6 ### (C) Copyright 2016-2017 Tecnic Software productions (TNSP)
80
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
129
31e3100b5ed9 Add timestamps to messages.
Matti Hamalainen <ccr@tnsp.org>
parents: 127
diff changeset
53 ## Return a formatted timestamp string
31e3100b5ed9 Add timestamps to messages.
Matti Hamalainen <ccr@tnsp.org>
parents: 127
diff changeset
54 def gcm_timestamp(stamp):
31e3100b5ed9 Add timestamps to messages.
Matti Hamalainen <ccr@tnsp.org>
parents: 127
diff changeset
55 return time.strftime("%Y-%m-%d %H:%M:%S", stamp)
31e3100b5ed9 Add timestamps to messages.
Matti Hamalainen <ccr@tnsp.org>
parents: 127
diff changeset
56 #.decode(locale.getlocale()[1])
31e3100b5ed9 Add timestamps to messages.
Matti Hamalainen <ccr@tnsp.org>
parents: 127
diff changeset
57
31e3100b5ed9 Add timestamps to messages.
Matti Hamalainen <ccr@tnsp.org>
parents: 127
diff changeset
58
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
59 ## Wrapper for print() that does not break when redirecting stdin/out
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
60 ## because of piped output not having a defined encoding. We default
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
61 ## to UTF-8 encoding in output here.
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
62 def gcm_print(smsg):
47
a8fdecd4be61 Fixes to Unicode handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 46
diff changeset
63 gcm_msgbuf.append(smsg)
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
64 if sys.stdout.encoding != None:
129
31e3100b5ed9 Add timestamps to messages.
Matti Hamalainen <ccr@tnsp.org>
parents: 127
diff changeset
65 rsmsg = smsg.encode(sys.stdout.encoding)
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
66 else:
129
31e3100b5ed9 Add timestamps to messages.
Matti Hamalainen <ccr@tnsp.org>
parents: 127
diff changeset
67 rsmsg = smsg.encode("UTF-8")
31e3100b5ed9 Add timestamps to messages.
Matti Hamalainen <ccr@tnsp.org>
parents: 127
diff changeset
68
31e3100b5ed9 Add timestamps to messages.
Matti Hamalainen <ccr@tnsp.org>
parents: 127
diff changeset
69 print("{0} | {1}".format(gcm_timestamp(time.localtime()), rsmsg))
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
70
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
71
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
72 ## Fatal error handler
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
73 def gcm_fatal(smsg):
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
74 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
75 if cfg.email_ok and cfg.email != "off":
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
76 ## 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
77 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
78 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
79 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
80 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
81 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
82 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
83 try:
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
84 # 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
85 if cfg.email == "smtp":
127
bb8b455218ec Improve comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 124
diff changeset
86 # Connect via SMTP
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
87 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
88 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
89 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
90 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
91
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
92 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
93 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
94
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
95 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
96 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
97 server.quit()
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
98 elif cfg.email == "sendmail":
127
bb8b455218ec Improve comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 124
diff changeset
99 # Use local sendmail
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
100 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
101 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
102 p.communicate(msg.as_string())
70
d5e3ca4b609d Improve error handling when e-mail sending fails.
Matti Hamalainen <ccr@tnsp.org>
parents: 68
diff changeset
103 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
104 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
105 sys.exit(1)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
106
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
107
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
108 ## Debug messages
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
109 def gcm_check_debug(level):
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
110 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
111
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
112 def gcm_debug(level, smsg):
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
113 if gcm_check_debug(level):
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
114 gcm_print(u"DBG: {0}".format(smsg))
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
115 else:
47
a8fdecd4be61 Fixes to Unicode handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 46
diff changeset
116 gcm_msgbuf.append(u"DBG: {0}".format(smsg))
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
117
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
118
24
1bce0c6a673c Comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 23
diff changeset
119 ## Handler for SIGINT signals
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
120 def gcm_signal_handler(signal, frame):
54
86d3a8eddbd7 Unicodeify.
Matti Hamalainen <ccr@tnsp.org>
parents: 53
diff changeset
121 gcm_print(u"\nQuitting due to SIGINT / Ctrl+C!")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
122 sys.exit(0)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
123
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
124
24
1bce0c6a673c Comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 23
diff changeset
125 ## 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
126 def gcm_get_credentials(mcfg, credential_file, secret_file):
42
ac949d2b268a Add some error handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 41
diff changeset
127 try:
99
4b84bb5bb8b5 Make credential_file and secret_file arguments to gcm_get_credentials().
Matti Hamalainen <ccr@tnsp.org>
parents: 98
diff changeset
128 store = oauth2client.file.Storage(credential_file)
42
ac949d2b268a Add some error handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 41
diff changeset
129 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
130 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
131
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
132 credentials = store.get()
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
133 if not credentials or credentials.invalid:
42
ac949d2b268a Add some error handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 41
diff changeset
134 try:
99
4b84bb5bb8b5 Make credential_file and secret_file arguments to gcm_get_credentials().
Matti Hamalainen <ccr@tnsp.org>
parents: 98
diff changeset
135 flow = client.flow_from_clientsecrets(secret_file, mcfg.scope)
42
ac949d2b268a Add some error handling.
Matti Hamalainen <ccr@tnsp.org>
parents: 41
diff changeset
136 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
137 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
138
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
139 flow.user_agent = mcfg.app_name
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
140 credentials = tools.run_flow(flow, store, mcfg)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
141 if not credentials or credentials.invalid:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
142 gcm_fatal(u"Failed to authenticate / invalid credentials.")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
143 return credentials
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
144
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
145
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
146 ## 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
147 def gcm_dump_events(events, show):
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
148 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
149 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
150 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
151 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
152 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
153 status = "*" if event["status"] != u"cancelled" else "!"
104
f6274227114b Make debug/error messages more consistent.
Matti Hamalainen <ccr@tnsp.org>
parents: 103
diff changeset
154 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
155
56
597875ef885b Better debug prints.
Matti Hamalainen <ccr@tnsp.org>
parents: 55
diff changeset
156
597875ef885b Better debug prints.
Matti Hamalainen <ccr@tnsp.org>
parents: 55
diff changeset
157 ## 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
158 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
159 if not events:
1267d61f6224 Add function for generating unique internal IDs.
Matti Hamalainen <ccr@tnsp.org>
parents: 25
diff changeset
160 return events
1267d61f6224 Add function for generating unique internal IDs.
Matti Hamalainen <ccr@tnsp.org>
parents: 25
diff changeset
161
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
162 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
163 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
164 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
165
1267d61f6224 Add function for generating unique internal IDs.
Matti Hamalainen <ccr@tnsp.org>
parents: 25
diff changeset
166 return events
1267d61f6224 Add function for generating unique internal IDs.
Matti Hamalainen <ccr@tnsp.org>
parents: 25
diff changeset
167
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
168
53
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
169 ## 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
170 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
171 for event in list:
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
172 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
173 return event
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
174 return None
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
175
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
176
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
177 ## 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
178 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
179 for field in ev1:
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
180 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
181 return False
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
182 return True
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
183
63
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
184
110
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
185 ## 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
186 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
187 events = []
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
188 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
189 while True:
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
190 try:
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
191 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
192 calendarId=calendarId,
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
193 showDeleted=showDeleted,
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
194 singleEvents=False,
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
195 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
196 ).execute()
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
197 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
198 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
199
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
200 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
201 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
202 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
203 break
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
204
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
205 return events
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
206
c6771a596d77 Add gcm_fetch_events() function that properly implements chained event list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 109
diff changeset
207
67
c582522d2dcc Add a comment.
Matti Hamalainen <ccr@tnsp.org>
parents: 66
diff changeset
208 ###
c582522d2dcc Add a comment.
Matti Hamalainen <ccr@tnsp.org>
parents: 66
diff changeset
209 ### Class for parsing and manipulating RGB colors
c582522d2dcc Add a comment.
Matti Hamalainen <ccr@tnsp.org>
parents: 66
diff changeset
210 ###
62
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
211 class GCMColor():
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
212 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
213 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
214 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
215 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
216 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
217 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
218 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
219 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
220 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
221 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
222 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
223 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
224 else:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
225 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
226 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
227 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
228 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
229 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
230 else:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
231 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
232
106
205767356d2c Add two helper functions to GCMColor class.
Matti Hamalainen <ccr@tnsp.org>
parents: 105
diff changeset
233 def to_hexrgb():
205767356d2c Add two helper functions to GCMColor class.
Matti Hamalainen <ccr@tnsp.org>
parents: 105
diff changeset
234 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
235
205767356d2c Add two helper functions to GCMColor class.
Matti Hamalainen <ccr@tnsp.org>
parents: 105
diff changeset
236 def to_hexrgb_lc():
205767356d2c Add two helper functions to GCMColor class.
Matti Hamalainen <ccr@tnsp.org>
parents: 105
diff changeset
237 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
238
62
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
239 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
240 ctmp = GCMColor()
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
241 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
242 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
243 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
244 return ctmp
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
245
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
246 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
247 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
248 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
249
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
250
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
251 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
252 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
253 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
254
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
255 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
256 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
257 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
258 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
259 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
260 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
261 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
262 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
263 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
264 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
265
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
266 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
267 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
268 else:
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
269 return None
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
270
53
ea62e0ed05ae Initial implementation of event comparision amd generally more clever about
Matti Hamalainen <ccr@tnsp.org>
parents: 52
diff changeset
271
24
1bce0c6a673c Comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 23
diff changeset
272 ##
1bce0c6a673c Comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 23
diff changeset
273 ## Class for handling configuration / settings
1bce0c6a673c Comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 23
diff changeset
274 ##
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
275 class GCMSettings(dict):
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
276 def __init__(self):
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
277 self.m_data = {}
92
a348dfa6b132 Rename a variable/class member.
Matti Hamalainen <ccr@tnsp.org>
parents: 89
diff changeset
278 self.m_settable = {}
5
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
279 self.m_validate = {}
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
280 self.m_translate = {}
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
281
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
282 def __getattr__(self, name):
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
283 if name in self.m_data:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
284 return self.m_data[name]
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
285 else:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
286 gcm_fatal(u"GCMSettings.__getattr__(): No such attribute '"+ name +"'.")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
287
5
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
288 def mvalidate(self, name, value):
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
289 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
290 if not self.m_validate[name](value):
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
291 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
292
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
293 def mtranslate(self, name, value):
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
294 if name in self.m_translate and self.m_translate[name]:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
295 return self.m_translate[name](value)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
296 else:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
297 return value
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
298
92
a348dfa6b132 Rename a variable/class member.
Matti Hamalainen <ccr@tnsp.org>
parents: 89
diff changeset
299 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
300 self.mvalidate(name, value)
92
a348dfa6b132 Rename a variable/class member.
Matti Hamalainen <ccr@tnsp.org>
parents: 89
diff changeset
301 self.m_settable[name] = settable
5
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
302 self.m_validate[name] = validate
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
303 self.m_translate[name] = translate
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
304 self.m_data[name] = self.mtranslate(name, value)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
305
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
306 def mset(self, name, value):
5
9d4152f32223 Add some code for settings validation.
Matti Hamalainen <ccr@tnsp.org>
parents: 4
diff changeset
307 self.mvalidate(name, value)
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
308 if name in self.m_data:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
309 self.m_data[name] = self.mtranslate(name, value)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
310 else:
43
a331209e24fc Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 42
diff changeset
311 gcm_fatal(u"GCMSettings.mset(): No such attribute '"+ name +"'.")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
312
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
313 def mget(self, name):
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
314 if name in self.m_data:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
315 return self.m_data[name]
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
316 else:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
317 return None
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
318
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
319 def mread(self, cfg_parser, sect):
92
a348dfa6b132 Rename a variable/class member.
Matti Hamalainen <ccr@tnsp.org>
parents: 89
diff changeset
320 for name in self.m_settable:
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
321 if cfg_parser.has_option(sect, name):
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
322 value = cfg_parser.get(sect, name)
6
ee6bf617f839 Implement configuration file reading.
Matti Hamalainen <ccr@tnsp.org>
parents: 5
diff changeset
323 self.mset(name, value)
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
324 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
325
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
326 def is_str(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
327 return isinstance(mvalue, basestring)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
328
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
329 def is_string(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
330 return mvalue == None or self.is_str(mvalue)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
331
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
332 def is_log_level(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
333 if not self.is_str(mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
334 return False
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
335 else:
76
a63cc3633adb Put log levels array into its own global variable.
Matti Hamalainen <ccr@tnsp.org>
parents: 75
diff changeset
336 return mvalue.upper() in gcm_log_levels
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
337
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
338 def trans_log_level(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
339 return mvalue.upper()
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
340
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
341 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
342 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
343 return False
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
344 else:
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
345 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
346
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
347 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
348 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
349
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
350 def is_filename(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
351 if not self.is_str(mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
352 return False
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
353 else:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
354 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
355
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
356 def trans_bool(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
357 if self.is_str(mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
358 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
359 mvalue = True
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
360 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
361 mvalue = False
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
362 else:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
363 return None
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
364 return mvalue
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
365
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
366 def is_bool(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
367 mval = self.trans_bool(mvalue)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
368 if not isinstance(mval, bool):
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
369 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
370 else:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
371 return True
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 trans_list(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
374 morig = mvalue
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
375 if self.is_str(mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
376 mvalue = re.split("\s*,\s*", mvalue, flags=re.IGNORECASE)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
377 if not isinstance(mvalue, list):
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
378 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
379 elif not isinstance(mvalue, list):
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
380 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
381 return mvalue
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
382
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
383 def is_list(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
384 return self.trans_list(mvalue)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
385
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
386 def is_email(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
387 if not self.is_string(mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
388 return False
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
389 else:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
390 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
391
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
392 def trans_email_list(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
393 if mvalue == None:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
394 return mvalue
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
395 else:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
396 return self.trans_list(mvalue.strip())
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
397
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
398 def is_email_list(self, mvalue):
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
399 mvalue = self.trans_email_list(mvalue)
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
400 if mvalue != None:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
401 for email in mvalue:
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
402 if not self.is_email(email):
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
403 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
404 return True
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
405
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
406
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
407 ###
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
408 ### Main program starts
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
409 ###
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
410 gcm_msgbuf = []
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
411 signal.signal(signal.SIGINT, gcm_signal_handler)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
412
87
c3f8af496f46 Add "execution time elapsed" metering.
Matti Hamalainen <ccr@tnsp.org>
parents: 86
diff changeset
413 gcm_bench_start = time.time()
c3f8af496f46 Add "execution time elapsed" metering.
Matti Hamalainen <ccr@tnsp.org>
parents: 86
diff changeset
414
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
415
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
416 ## Define all the settings
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
417 cfg_section = "gcm"
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
418 cfg = GCMSettings()
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
419
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
420 cfg.mdef("debug", True, cfg.is_bool, cfg.trans_bool, False)
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
421
14
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
422 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
423 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
424
23
ff47f8088ef9 Make things more OO.
Matti Hamalainen <ccr@tnsp.org>
parents: 22
diff changeset
425 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
426 cfg.mdef("email_sender", True, cfg.is_email, None, None)
49
cc30383f5f0d More Unicode fixes.
Matti Hamalainen <ccr@tnsp.org>
parents: 47
diff changeset
427 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
428
113
f45115bfb17a Implement sendmail mail sending support. Various e-mail related settings have also
Matti Hamalainen <ccr@tnsp.org>
parents: 111
diff changeset
429 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
430 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
431 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
432 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
433 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
434
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
435 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
436 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
437 cfg.mdef("src_regmap_len", False, None, None, len(cfg.src_regmap))
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
438
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
439 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
440 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
441 cfg.mdef("dst_id", True, cfg.is_string, None, None)
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
442
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
443 cfg.mdef("noauth_local_webserver", False, None, None, True)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
444 #cfg.mdef("auth_host_name", False, None, None, "localhost")
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
445 #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
446 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
447
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
448 # No need to touch these
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
449 cfg.mdef("app_name", False, None, None, "Google Calendar MultiMerge")
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
450 cfg.mdef("scope", False, None, None, "https://www.googleapis.com/auth/calendar")
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
451 #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
452 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
453 cfg.mdef("credential_file", True, cfg.is_filename, None, "client_credentials.json")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
454
6
ee6bf617f839 Implement configuration file reading.
Matti Hamalainen <ccr@tnsp.org>
parents: 5
diff changeset
455
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
456 ## Check if we have arguments
89
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
457 if len(sys.argv) <= 1:
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
458 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
459
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
460
6
ee6bf617f839 Implement configuration file reading.
Matti Hamalainen <ccr@tnsp.org>
parents: 5
diff changeset
461 ## Read, parse and validate configuration file
89
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
462 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
463 try:
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
464 cfg_parser = ConfigParser.RawConfigParser()
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
465 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
466 except Exception as e:
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
467 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
468
89
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
469 # Check that the required section exists
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
470 if not cfg_parser.has_section(cfg_section):
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
471 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
472
89
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
473 # Debug setting is a special case, we need to get it
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
474 # set before everything else, so do it here ..
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
475 if cfg_parser.has_option(cfg_section, "debug"):
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
476 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
477
89
d68acec7cb99 Require configuration file.
Matti Hamalainen <ccr@tnsp.org>
parents: 88
diff changeset
478 # Parse the settings and validate
119
f671602635b7 Rename some objects and variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 114
diff changeset
479 cfg.mread(cfg_parser, cfg_section)
6
ee6bf617f839 Implement configuration file reading.
Matti Hamalainen <ccr@tnsp.org>
parents: 5
diff changeset
480
8
8367463fe94d Post-validate some settings.
Matti Hamalainen <ccr@tnsp.org>
parents: 7
diff changeset
481
8367463fe94d Post-validate some settings.
Matti Hamalainen <ccr@tnsp.org>
parents: 7
diff changeset
482 ## 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
483 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
484 if cfg.email_subject == None or len(cfg.email_subject) == 0:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
485 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
486 elif cfg.email_sender == None:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
487 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
488 elif cfg.email_to == None:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
489 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
490 else:
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
diff changeset
491 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
492
8262efacf3fb Initial implementation of sending e-mail in fatal error cases.
Matti Hamalainen <ccr@tnsp.org>
parents: 13
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 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
495 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
496 else:
127
bb8b455218ec Improve comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 124
diff changeset
497 # Force convert values to integers
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
498 try:
124
977ecff4bd7d Use list comprehensions instead of map().
Matti Hamalainen <ccr@tnsp.org>
parents: 121
diff changeset
499 cfg.src_regmap = [int(x) for x in cfg.src_regmap]
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
500 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
501 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
502
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
503
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
504 if not cfg.dst_regex and not cfg.dst_id:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
505 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
506
8367463fe94d Post-validate some settings.
Matti Hamalainen <ccr@tnsp.org>
parents: 7
diff changeset
507
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
508 ## 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
509 credentials = gcm_get_credentials(cfg, cfg.credential_file, cfg.secret_file)
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
510 http = credentials.authorize(httplib2.Http())
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
511 service = discovery.build("calendar", "v3", http=http)
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
512
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
513
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
514 ## Fetch complete calendar list
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
515 gcm_debug(3, u"Fetching available calendars ..")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
516 calendars = []
19
095209b1ded3 Rename some variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 18
diff changeset
517 cal_token = None
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
518 while True:
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
519 # 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
520 try:
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
521 result = service.calendarList().list(
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
522 showHidden=False,
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
523 showDeleted=False,
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
524 pageToken=cal_token
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
525 ).execute()
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
526 except Exception as e:
8cf20367a372 Add exception checking to calendar list fetching.
Matti Hamalainen <ccr@tnsp.org>
parents: 108
diff changeset
527 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
528
17
4168dde804ae Rename some variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 14
diff changeset
529 calendars.extend(result.get("items", []))
19
095209b1ded3 Rename some variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 18
diff changeset
530 cal_token = result.get("nextPageToken")
095209b1ded3 Rename some variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 18
diff changeset
531 if not cal_token:
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
532 break
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
533
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
534 if len(calendars) == 0:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
535 gcm_fatal(u"No calendars found?")
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
536
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
537 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
538
1
74f172565752 Initial import.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
539
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
540 ## 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
541 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
542 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
543 src_calendars = []
60
37705c4a35e1 Show target calendar information in debug mode.
Matti Hamalainen <ccr@tnsp.org>
parents: 59
diff changeset
544 dst_calendar = None
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
545 for calendar in calendars:
51
54644b29a9a3 Match also summaryOverride attribute against the source calendar regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 50
diff changeset
546 if u"summary" in calendar:
50
f8618bae162a Improve debug messages and comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 49
diff changeset
547 # 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
548 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
549 cfg.mset("dst_id", calendar["id"])
60
37705c4a35e1 Show target calendar information in debug mode.
Matti Hamalainen <ccr@tnsp.org>
parents: 59
diff changeset
550 dst_calendar = calendar
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
551 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
552 dst_calendar = calendar
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
553
51
54644b29a9a3 Match also summaryOverride attribute against the source calendar regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 50
diff changeset
554 # 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
555 mre = src_re.match(calendar["summary"])
52
b87dbc887f63 Simplify.
Matti Hamalainen <ccr@tnsp.org>
parents: 51
diff changeset
556 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
557 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
558 calendar["summary"] = calendar["summaryOverride"]
52
b87dbc887f63 Simplify.
Matti Hamalainen <ccr@tnsp.org>
parents: 51
diff changeset
559
9
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
560 if mre:
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
561 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
562 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
563 src_calendars.append(calendar)
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
564
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
565 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
566
50
f8618bae162a Improve debug messages and comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 49
diff changeset
567
f8618bae162a Improve debug messages and comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 49
diff changeset
568 ## 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
569 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
570 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
571 else:
93
46c1a3b6135a Cosmetic.
Matti Hamalainen <ccr@tnsp.org>
parents: 92
diff changeset
572 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
573
01c933dba120 Filter source calendars based on regexp.
Matti Hamalainen <ccr@tnsp.org>
parents: 8
diff changeset
574
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
575 ## 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
576 try:
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
577 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
578 except Exception as e:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
579 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
580
4891ed8d77d5 Implement nearest matching color search via cubic distance, and use it for
Matti Hamalainen <ccr@tnsp.org>
parents: 61
diff changeset
581
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
582 ## 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
583 gcm_debug(3, u"Fetching calendar events .. ")
19
095209b1ded3 Rename some variables.
Matti Hamalainen <ccr@tnsp.org>
parents: 18
diff changeset
584 src_events = []
11
fcdee7c04ed8 Implement fetching of source events.
Matti Hamalainen <ccr@tnsp.org>
parents: 10
diff changeset
585 for calendar in src_calendars:
97
524915af5e87 Cosmetics.
Matti Hamalainen <ccr@tnsp.org>
parents: 95
diff changeset
586 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
587
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
588 # 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
589 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
590 if "colorId" in calendar and calendar["colorId"] in colors["calendar"]:
97
524915af5e87 Cosmetics.
Matti Hamalainen <ccr@tnsp.org>
parents: 95
diff changeset
591 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
592 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
593 if c_found:
97
524915af5e87 Cosmetics.
Matti Hamalainen <ccr@tnsp.org>
parents: 95
diff changeset
594 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
595 else:
97
524915af5e87 Cosmetics.
Matti Hamalainen <ccr@tnsp.org>
parents: 95
diff changeset
596 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
597
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
598 # 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
599 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
600 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
601 for event in events:
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
602 # 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
603 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
604 if c_found != None:
7ab6beb4c709 Only generate summaries and colors for non-deleted/cancelled events.
Matti Hamalainen <ccr@tnsp.org>
parents: 101
diff changeset
605 event["colorId"] = c_found
7ab6beb4c709 Only generate summaries and colors for non-deleted/cancelled events.
Matti Hamalainen <ccr@tnsp.org>
parents: 101
diff changeset
606 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
607
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
608 # 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
609 src_events.extend(events)
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
610 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
611 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
612
fcdee7c04ed8 Implement fetching of source events.
Matti Hamalainen <ccr@tnsp.org>
parents: 10
diff changeset
613
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
614 ## 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
615 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
616 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
617 gcm_debug(3, u"Found {0} event(s).".format(len(dst_events)))
58
87fda54f935c Cleanup.
Matti Hamalainen <ccr@tnsp.org>
parents: 57
diff changeset
618
13
dd240a7ad913 Fetch current events in destination calendar.
Matti Hamalainen <ccr@tnsp.org>
parents: 11
diff changeset
619
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
620 ## Start populating/updating events ..
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
621 gcm_debug(3, u"Re-merging events to target calendar ..")
124
977ecff4bd7d Use list comprehensions instead of map().
Matti Hamalainen <ccr@tnsp.org>
parents: 121
diff changeset
622 dst_ids = frozenset([x["gcm_id"] for x in dst_events])
977ecff4bd7d Use list comprehensions instead of map().
Matti Hamalainen <ccr@tnsp.org>
parents: 121
diff changeset
623 src_ids = frozenset([x["gcm_id"] for x in src_events])
27
824c3e5c6757 Work on event merging.
Matti Hamalainen <ccr@tnsp.org>
parents: 26
diff changeset
624
81
ce02c0c00e64 Add debug information about how many events were new, updated or unchanged.
Matti Hamalainen <ccr@tnsp.org>
parents: 80
diff changeset
625 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
626
27
824c3e5c6757 Work on event merging.
Matti Hamalainen <ccr@tnsp.org>
parents: 26
diff changeset
627 for event in src_events:
824c3e5c6757 Work on event merging.
Matti Hamalainen <ccr@tnsp.org>
parents: 26
diff changeset
628 # Does the event exist already in the target?
55
5b78f62b7de7 More work on merging stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 54
diff changeset
629 if event["gcm_id"] in dst_ids:
39
693db3f8cbe5 Begin importing event comparision stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 38
diff changeset
630 # 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
631 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
632 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
633 if not gcm_compare_events(event, d_event):
57
1c2cf6170219 Comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 56
diff changeset
634 # Seems we need to update
104
f6274227114b Make debug/error messages more consistent.
Matti Hamalainen <ccr@tnsp.org>
parents: 103
diff changeset
635 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
636 try:
121
4500fbf91294 More comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 120
diff changeset
637 # We need to remove the sequence and id fields, as they will be replaced by target
55
5b78f62b7de7 More work on merging stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 54
diff changeset
638 event.pop("sequence", None)
63
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
639 event.pop("id", None)
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
640 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
641 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
642 evn_updated += 1
39
693db3f8cbe5 Begin importing event comparision stuff.
Matti Hamalainen <ccr@tnsp.org>
parents: 38
diff changeset
643 except Exception as e:
104
f6274227114b Make debug/error messages more consistent.
Matti Hamalainen <ccr@tnsp.org>
parents: 103
diff changeset
644 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
645 else:
81
ce02c0c00e64 Add debug information about how many events were new, updated or unchanged.
Matti Hamalainen <ccr@tnsp.org>
parents: 80
diff changeset
646 evn_unchanged += 1
104
f6274227114b Make debug/error messages more consistent.
Matti Hamalainen <ccr@tnsp.org>
parents: 103
diff changeset
647 gcm_debug(4, u"No need to update event {0} [{1}]".format(event["id"], event["gcm_id"]))
131
654b28ca9f39 Minor fix.
Matti Hamalainen <ccr@tnsp.org>
parents: 130
diff changeset
648 elif event["status"] not in [u"cancelled", u"confirmed"]:
120
1f7967aa0133 Improve and add comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 119
diff changeset
649 # 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
650 gcm_debug(4, u"Inserting new event {0} [{1}]".format(event["id"], event["gcm_id"]))
121
4500fbf91294 More comments.
Matti Hamalainen <ccr@tnsp.org>
parents: 120
diff changeset
651 # Remove original id field, otherwise it will clash
63
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
652 event.pop("id", None)
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
653 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
654 try:
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
655 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
656 evn_new += 1
34
125c4cbca3ad Event merging work.
Matti Hamalainen <ccr@tnsp.org>
parents: 33
diff changeset
657 except Exception as e:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
658 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
659
81
ce02c0c00e64 Add debug information about how many events were new, updated or unchanged.
Matti Hamalainen <ccr@tnsp.org>
parents: 80
diff changeset
660 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
661
34
125c4cbca3ad Event merging work.
Matti Hamalainen <ccr@tnsp.org>
parents: 33
diff changeset
662
125c4cbca3ad Event merging work.
Matti Hamalainen <ccr@tnsp.org>
parents: 33
diff changeset
663 ## Remove "stale" events
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
664 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
665 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
666 for event in dst_events:
77
e5e7b6e9bd44 Implement debug levels in the main code.
Matti Hamalainen <ccr@tnsp.org>
parents: 76
diff changeset
667 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
668 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
669 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
670 evn_purged += 1
63
6e38692e341f Fixes to event merging etc.
Matti Hamalainen <ccr@tnsp.org>
parents: 62
diff changeset
671 try:
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
672 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
673 except Exception as e:
65
1eefa9b5e945 Unicodify.
Matti Hamalainen <ccr@tnsp.org>
parents: 64
diff changeset
674 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
675
85
da09a3b1edaa Count and report number of purged events.
Matti Hamalainen <ccr@tnsp.org>
parents: 84
diff changeset
676 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
677
da09a3b1edaa Count and report number of purged events.
Matti Hamalainen <ccr@tnsp.org>
parents: 84
diff changeset
678
75
ee05430f1a4d Update comment.
Matti Hamalainen <ccr@tnsp.org>
parents: 73
diff changeset
679 ##
ee05430f1a4d Update comment.
Matti Hamalainen <ccr@tnsp.org>
parents: 73
diff changeset
680 ## Finally, update the calendar name with timestamp
ee05430f1a4d Update comment.
Matti Hamalainen <ccr@tnsp.org>
parents: 73
diff changeset
681 ##
73
b3f8621f1a25 Change how the target calendar settings work a bit. Also implement display
Matti Hamalainen <ccr@tnsp.org>
parents: 72
diff changeset
682 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
683 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
684 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
685
b3f8621f1a25 Change how the target calendar settings work a bit. Also implement display
Matti Hamalainen <ccr@tnsp.org>
parents: 72
diff changeset
686 try:
98
fe3bfabf0b5f Rename settings dest_* and source_* to dst_* and src_* respectively.
Matti Hamalainen <ccr@tnsp.org>
parents: 97
diff changeset
687 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
688 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
689 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
690 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
691
27
824c3e5c6757 Work on event merging.
Matti Hamalainen <ccr@tnsp.org>
parents: 26
diff changeset
692
87
c3f8af496f46 Add "execution time elapsed" metering.
Matti Hamalainen <ccr@tnsp.org>
parents: 86
diff changeset
693 gcm_bench_end = time.time()
c3f8af496f46 Add "execution time elapsed" metering.
Matti Hamalainen <ccr@tnsp.org>
parents: 86
diff changeset
694 gcm_bench_elapsed = gcm_bench_end - gcm_bench_start
c3f8af496f46 Add "execution time elapsed" metering.
Matti Hamalainen <ccr@tnsp.org>
parents: 86
diff changeset
695
c3f8af496f46 Add "execution time elapsed" metering.
Matti Hamalainen <ccr@tnsp.org>
parents: 86
diff changeset
696 gcm_debug(3, u"Finished. {0} seconds elapsed.".format(gcm_bench_elapsed))