1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import codecs
20 import os.path
21
22 from timelinelib.canvas.data.exceptions import TimelineIOError
23 from timelinelib.wxgui.utils import register_unlock_function
24 from timelinelib.general.encodings import to_unicode
25
26
28 """
29 Write to path in such a way that the contents of path is only modified
30 correctly or not modified at all.
31
32 In some extremely rare cases the contents of path might be incorrect, but
33 in those cases the correct content is always present in another dbfile.
34 """
35 def raise_error(specific_msg, cause_exception):
36 err_general = _("Unable to save timeline data to '%s'. File left unmodified.") % path
37 err_template = "%s\n\n%%s\n\n%%s" % err_general
38 raise TimelineIOError(err_template % (to_unicode(specific_msg), to_unicode(cause_exception)))
39 tmp_path = create_non_exising_path(path, "tmp")
40 backup_path = create_non_exising_path(path, "bak")
41
42 try:
43 if encoding is None:
44 dbfile = open(tmp_path, "wb")
45 else:
46 dbfile = codecs.open(tmp_path, "w", encoding)
47 try:
48 try:
49 write_fn(dbfile)
50 except Exception as e:
51 raise_error(_("Unable to write timeline data."), e)
52 finally:
53 dbfile.close()
54 except IOError as e:
55 raise_error(_("Unable to write to temporary dbfile '%s'.") % tmp_path, e)
56
57 if os.path.exists(path):
58 try:
59 os.rename(path, backup_path)
60 except Exception as e:
61 raise_error(_("Unable to take backup to '%s'.") % backup_path, e)
62
63 try:
64 os.rename(tmp_path, path)
65 except Exception as e:
66 raise_error(_("Unable to rename temporary dbfile '%s' to original.") % tmp_path, e)
67
68 if os.path.exists(backup_path):
69 try:
70 os.remove(backup_path)
71 except Exception as e:
72 raise_error(_("Unable to delete backup dbfile '%s'.") % backup_path, e)
73
74
76 i = 1
77 while True:
78 new_path = "%s.%s%i" % (base, suffix, i)
79 if os.path.exists(new_path):
80 i += 1
81 else:
82 return new_path
83
84
85 -def safe_locking(controller, edit_function, exception_handler=None):
98