- attachment:msgfile.py of MsgFile
Attachment 'msgfile.py'
Download 1 from roundup.date import Interval, Date
2
3 def join(lol):
4 '''Flattens a list of lists into a list'''
5 if lol == []:
6 return []
7 return reduce(lambda x,y: x+y, lol)
8
9 def msgfile_reactor(db, cl, issue_id, oldvals):
10 '''Ensure that each file is always connected to a message
11 '''
12
13
14 #
15 # Figure out which files and messages have been added
16 #
17 messages = cl.get(issue_id, "messages")
18 files = cl.get(issue_id, "files")
19 if oldvals and oldvals.has_key("files"):
20 added_files = [id for id in files if not id in oldvals["files"]]
21 elif not oldvals:
22 added_files = files
23 else:
24 added_files = []
25
26 if oldvals and oldvals.has_key("messages"):
27 added_msgs = [id for id in messages if not id in oldvals["messages"]]
28 removed_msgs = [id for id in oldvals["messages"] if not id in messages]
29 elif not oldvals:
30 added_msgs = messages
31 removed_msgs = []
32 else:
33 added_msgs = []
34 removed_msgs = []
35
36
37 #
38 # Make sure that each file is attached to a message
39 #
40
41 # Workaround for the web frontend (which allows only
42 # one file per message):
43 # If the user attaches only one file and no message and
44 # the last message is from the same user and less than
45 # 5 minutes old, we attach the new file to that message.
46 if added_msgs == [] and messages != None and \
47 len(messages) > 0 and len(added_files) == 1 and \
48 (Date(".") - db.msg.get(messages[-1], "date")) < Interval("0:05"):
49 db.msg.set(messages[-1], files=db.msg.get(messages[-1], "files")+added_files)
50
51 # Otherwise we create a new message and attach all files
52 # without message to that new message
53 else:
54 referenced = join([db.msg.get(id, "files") for id in added_msgs])
55 to_add = [id for id in added_files if not id in referenced]
56 if to_add:
57 msg = db.msg.create(
58 author = db.file.get(to_add[0], "creator"),
59 date = db.file.get(to_add[0], "creation"),
60 content = "[attached files]",
61 files = to_add)
62 messages.append(msg)
63 cl.set(issue_id, messages=messages)
64
65
66 #
67 # If a message has been detached, detach its files as well
68 #
69 for msg_id in removed_msgs:
70 for file_id in db.msg.get(msg_id, "files"):
71 files.remove(file_id)
72
73
74 # The following code physically removes the file,
75 # if no other messages refer to it
76 #if len(db.msg.find(files=file_id)) == 1:
77 # db.file.destroy(file_id)
78
79 # Optionally we also physically remove the message,
80 # if it is not attached to any other issue
81 if not cl.find(messages=msg_id):
82 pass
83 #db.msg.destroy(msg_id)
84
85 if files != cl.get(issue_id, "files"):
86 cl.set(issue_id, files=files)
87
88
89
90 def msgfile_auditor(db, cl, issue_id, newdata):
91 '''Do not allow direct removal of a file without its message
92 '''
93
94 if newdata.has_key("files") and issue_id:
95 if newdata.has_key("messages"):
96 messages = newdata["messages"]
97 else:
98 messages = cl.get(issue_id, "messages")
99
100 files = cl.get(issue_id, "files")
101 if newdata["files"]:
102 removed_files = [id for id in files if not id in newdata["files"]]
103 else:
104 removed_files = files
105 referenced = join([db.msg.get(id, "files") for id in messages])
106
107 for file_id in removed_files:
108 if file_id in referenced:
109 raise ValueError, "Cannot remove file alone - remove message instead."
110
111
112
113 def init(db):
114 db.issue.react('set', msgfile_reactor)
115 db.issue.react('create', msgfile_reactor)
116 db.issue.audit('set', msgfile_auditor)
117
118 # vim: set filetype=python ts=4 sw=4 et si
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.