annotate multimerge.py @ 128:80d566c1d061

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