annotate multimerge.py @ 139:23fc7cd1cd53

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