1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """
17 Runtime settings for the svnmailer
18 ==================================
19
20 This module defines one public class, called L{Settings}. This class is the
21 storage container for all settings used by the svnmailer. L{Settings} is an
22 abstract class. There is just one method that must be implemented --
23 L{Settings.init}. This method is responsible for filling the container
24 properly. An implementor of the L{Settings} class can be found in the
25 L{svnmailer.config} module.
26
27 This module further defines the Settings subcontainers
28 L{GroupSettingsContainer}, L{GeneralSettingsContainer} and
29 L{RuntimeSettingsContainer}, but you should not instantiate them directly --
30 L{Settings} provides methods that return instances of these containers.
31 """
32 __author__ = "André Malo"
33 __docformat__ = "epytext en"
34 __all__ = ['Settings', 'modes']
35
36
37 from svnmailer import typedstruct, struct_accessors
38
39
41 """ Generic token container
42
43 @ivar valid_tokens: The valid mode tokens (str, str, ...)
44 @type valid_tokens: C{tuple}
45 """
46 valid_tokens = ()
47
49 """ Initialization """
50 self.valid_tokens = args
51 for token in self.valid_tokens:
52 setattr(self, token.encode('us-ascii'), token)
53
54 modes = _Tokens('commit', 'propchange', 'lock', 'unlock')
55 xpath = _Tokens(u'yes', u'no', u'ignore')
56 showenc = _Tokens(u'yes', u'no', u'nondefault')
57
58
60 """ Define the members of the group settings
61
62 The following members are defined:
63 - C{_name}: Name of the group
64 - C{_def_for_repos}: default for_repos regex
65 - C{_def_for_paths}: default for_paths regex
66 - C{for_repos}: Repository regex
67 - C{for_paths}: Path regex (inside the repos)
68 - C{exclude_paths}: Exclude path regex to prevent for_paths from
69 being applied
70 - C{ignore_if_other_matches}: this group will be ignored if there
71 are any other groups selected for a particular path
72 - C{show_nonmatching_paths}: How to deal with paths that are not
73 matched by the group
74 - C{commit_subject_template}: Subject template for commit mail
75 - C{propchange_subject_template}: Subject template for revpropchanges
76 - C{lock_subject_template}: Subject template for locks
77 - C{unlock_subject_template}: Subject template for unlocks
78 - C{commit_subject_prefix}: Subject prefix for commit mail
79 - C{propchange_subject_prefix}: Subject prefix for revpropchanges
80 - C{lock_subject_prefix}: Subject prefix for locks
81 - C{unlock_subject_prefix}: Subject prefix for unlocks
82 - C{max_subject_length}: Maximum subject length
83 - C{from_addr}: C{From:} address format string
84 - C{to_addr}: C{To:} address format string
85 - C{to_fake}: C{To:} non-address format string
86 - C{bcc_addr}: C{Bcc:} address format string
87 - C{reply_to_addr}: C{Reply-To:} address format string
88 - C{diff_command}: The diff command to use
89 - C{generate_diffs}: List of actions for which diffs are generated
90 - C{browser_base_url}: type and format string of the repository
91 browser base url
92 - C{custom_header}: custom header name and format template
93 - C{to_newsgroup}: The newsgroup where the notification should be
94 posted to
95 - C{long_news_action}: The action to take on huge commit postings
96 - C{long_mail_action}: The action to take on huge commit mails
97 - C{mail_transfer_encoding}: Content-Transfer-Encoding for mails
98 - C{news_transfer_encoding}: Content-Transfer-Encoding for news
99 - C{mail_type}: The mail construction type
100 - C{extract_x509_author}: Treat author as x509 subject and try to
101 extract author's real name and email address
102 - C{cia_project_name}: The project name used for CIA notifications
103 - C{cia_project_module}: The project module used for CIA
104 notifications
105 - C{cia_project_branch}: The project branch used for CIA
106 notifications
107 - C{cia_project_submodule}: The project submodule used for CIA
108 notifications
109 - C{cia_project_path}: The project path, which will be stripped from
110 the absolute node path
111 - C{apply_charset_property}: Should svnmailer:content-charset
112 properties be recognized?
113 - C{show_applied_charset}: Show the encoding of the files in the
114 diff?
115 - C{viewcvs_base_url}: (I{deprecated}, use C{browser_base_url}
116 instead) format string for the viewcvs URL
117
118 @param space: The namespace to pollute
119 @type space: C{dict}
120
121 @return: The members definition
122 @rtype: C{dict}
123 """
124 args = {
125 'space' : space,
126 'typemap' : struct_accessors.typemap,
127 'the_members': {
128 '_name' : 'unicode',
129 '_def_for_repos' : 'regex',
130 '_def_for_paths' : 'regex',
131 'for_repos' : ('regex', {'map': True}),
132 'for_paths' : ('regex', {'map': True}),
133 'exclude_paths' : ('regex', {'map': True}),
134 'ignore_if_other_matches' : 'humanbool',
135 'show_nonmatching_paths' : ('token',
136 {'map': True,
137 'allowed': xpath.valid_tokens}),
138 'commit_subject_template' : ('unicode', {'map': True}),
139 'propchange_subject_template': ('unicode', {'map': True}),
140 'lock_subject_template' : ('unicode', {'map': True}),
141 'unlock_subject_template' : ('unicode', {'map': True}),
142 'commit_subject_prefix' : ('unicode',
143 {'subst': True, 'map': True}),
144 'propchange_subject_prefix' : ('unicode',
145 {'subst': True, 'map': True}),
146 'lock_subject_prefix' : ('unicode',
147 {'subst': True, 'map': True}),
148 'unlock_subject_prefix' : ('unicode',
149 {'subst': True, 'map': True}),
150 'max_subject_length' : 'int',
151 'from_addr' : ('tokenlist',
152 {'subst': True, 'map': True}),
153 'to_addr' : ('tokenlist',
154 {'subst': True, 'map': True}),
155 'to_fake' : ('unicode',
156 {'subst': True, 'map': True}),
157 'bcc_addr' : ('tokenlist',
158 {'subst': True, 'map': True}),
159 'reply_to_addr' : ('unicode',
160 {'subst': True, 'map': True}),
161 'to_newsgroup' : ('tokenlist',
162 {'subst': True, 'map': True}),
163 'diff_command' : ('unicommand', {'map': True}),
164 'generate_diffs' : 'tokenlist',
165 'browser_base_url' : ('unicode',
166 {'subst': True, 'map': True}),
167 'long_mail_action' : ('mailaction', {'map': True}),
168 'long_news_action' : ('mailaction', {'map': True}),
169 'mail_type' : ('unicode', {'map': True}),
170 'mail_transfer_encoding' : 'unicode',
171 'news_transfer_encoding' : 'unicode',
172 'custom_header' : ('unicode',
173 {'subst': True, 'map': True}),
174 'extract_x509_author' : 'humanbool',
175 'cia_rpc_server' : ('unicode', {'map': True}),
176 'cia_project_name' : ('unicode',
177 {'subst': True, 'map': True}),
178 'cia_project_module' : ('unicode',
179 {'subst': True, 'map': True}),
180 'cia_project_branch' : ('unicode',
181 {'subst': True, 'map': True}),
182 'cia_project_submodule' : ('unicode',
183 {'subst': True, 'map': True}),
184 'cia_project_path' : ('unicode',
185 {'subst': True, 'map': True}),
186 'apply_charset_property' : 'humanbool',
187 'show_applied_charset' : ('token',
188 {'allowed': showenc.valid_tokens}),
189
190
191 'viewcvs_base_url' : ('unicode',
192 {'subst': True, 'map': True}),
193 },
194 'aliases': {
195 'suppress_if_match' : 'ignore_if_other_matches',
196 'fallback' : 'ignore_if_other_matches',
197 'reply_to' : 'reply_to_addr',
198 'x509_author' : 'extract_x509_author',
199 'charset_property' : 'apply_charset_property',
200 'truncate_subject' : 'max_subject_length',
201 'subject_length' : 'max_subject_length',
202 'diff' : 'diff_command',
203 'nonmatching_paths' : 'show_nonmatching_paths',
204 'nongroup_paths' : 'show_nonmatching_paths',
205 'show_nongroup_paths': 'show_nonmatching_paths',
206 },
207 }
208
209 return typedstruct.members(**args)
210
211
213 """ Define the members of the general settings
214
215 The following members are defined:
216 - C{diff_command}: The diff command
217 - C{sendmail_command}: The sendmail compatible command
218 - C{smtp_host}: The smtp host (C{host[:port]})
219 - C{smtp_user}: The smtp auth. user
220 - C{smtp_pass}: The smtp auth. password
221 - C{debug_all_mails_to}: All mails are sent to these addresses
222 (for debugging purposes)
223 - C{cia_rpc_server}: The XML-RPC server running the CIA tracker
224 - C{tempdir}: The directory to use for temporary files
225
226 @param space: The namespace to pollute
227 @type space: C{dict}
228
229 @return: The members definition
230 @rtype: C{dict}
231 """
232 args = {
233 'space' : space,
234 'typemap' : struct_accessors.typemap,
235 'the_members': {
236 'sendmail_command' : ('unicommand', {'map': True}),
237 'smtp_host' : ('unicode', {'map': True}),
238 'smtp_user' : ('quotedstr', {'map': True}),
239 'smtp_pass' : ('quotedstr', {'map': True}),
240 'nntp_host' : ('unicode', {'map': True}),
241 'nntp_user' : ('quotedstr', {'map': True}),
242 'nntp_pass' : ('quotedstr', {'map': True}),
243 'debug_all_mails_to': ('tokenlist', {'map': True}),
244 'tempdir' : ('filename', {'map': True}),
245
246
247 'cia_rpc_server' : ('unicode', {'map': True}),
248 'diff_command' : ('unicommand', {'map': True}),
249 },
250 'aliases' : {
251 'mail_command' : 'sendmail_command',
252 'smtp_hostname': 'smtp_host',
253 'diff' : 'diff_command',
254 },
255 }
256
257 return typedstruct.members(**args)
258
259
261 """ Define the members of the runtime settings
262
263 The following members are defined:
264 - C{_repos}: The repository object
265 - C{stdin}: The stdin, read once
266 - C{path_encoding}: The path-encoding parameter
267 - C{debug}: debug mode (True/False)
268 - C{revision}: committed revision number
269 - C{repository}: path to the repository
270 - C{config}: supplied config file name
271 - C{mode}: running mode (see L{modes})
272 - C{author}: Author of the commit or revpropchange
273 - C{propname}: Property changed (in revpropchange)
274 - C{action}: The revprop action (M, A, D)
275
276 @param space: The namespace to pollute
277 @type space: C{dict}
278
279 @return: The members definition
280 @rtype: C{dict}
281 """
282 args = {
283 'space' : space,
284 'typemap' : struct_accessors.typemap,
285 'the_members': {
286 '_repos' : None,
287 'stdin' : 'stdin',
288 'path_encoding': 'string',
289 'debug' : 'bool',
290 'revision' : 'int',
291 'repository' : 'filename',
292 'config' : 'filename',
293 'mode' : 'string',
294 'author' : 'unicode',
295 'propname' : 'unicode',
296 'action' : 'unicode',
297 },
298 'aliases' : None,
299 }
300
301 return typedstruct.members(**args)
302
303
305 """ Container for group settings
306
307 @see: L{groupMembers} for the actual member list
308 """
309 __slots__ = groupMembers(locals())
310
312 """ compare some of the attributes
313
314 @note: It uses a list of attributes that are compared if two
315 of these types are tested for equality. Keep in mind that
316 this comparision takes place, when the decision is made
317 whether a mail for more than one group should be sent more
318 than once (if the groups are not equal). All attributes, but
319 the ones returned by L{_getIgnorableMembers} are compared.
320
321 @see: L{_getIgnorableMembers}
322
323 @param other: The object compared to
324 @type other: C{GroupSettingsContainer}
325
326 @return: Are the objects equal?
327 @rtype: C{bool}
328 """
329 if type(self) != type(other):
330 return False
331
332 attrs = [name for name in self._members_
333 if name not in self._getIgnorableMembers()
334 ]
335
336 for name in attrs:
337 if getattr(self, name) != getattr(other, name):
338 return False
339
340 return True
341
342
344 """ Returns the list of member names that be ignored in comparisons
345
346 This method called by L{_compare}. Override this method to modify
347 the list.
348
349 @return: The list
350 @rtype: C{list}
351 """
352 return [
353 '_name', '_def_for_repos', '_def_for_paths',
354 'for_repos', 'for_paths', 'exclude_paths',
355 'ignore_if_other_matches', 'to_addr', 'from_addr',
356 'to_newsgroup', 'custom_header', 'cia_rpc_server',
357 'cia_project_name', 'cia_project_module', 'cia_project_branch',
358 'cia_project_submodule', 'cia_project_path',
359 ]
360
361
363 """ Container for general settings
364
365 @see: L{generalMembers} for the actual member list
366 """
367 __slots__ = generalMembers(locals())
368
369
371 """ Container for runtime settings
372
373 @see: L{runtimeMembers} for the actual member list
374 """
375 __slots__ = runtimeMembers(locals())
376
377
379 """ Settings management
380
381 @note: The C{init} method must be overridden to do the actual
382 initialization.
383
384 @ivar groups: group settings list
385 @type groups: C{list} of C{GroupSettingsContainer}
386
387 @ivar general: General settings
388 @type general: C{GeneralSettingsContainer}
389
390 @ivar runtime: Runtime settigs
391 @type runtime: C{RuntimeSettingsContainer}
392
393 @ivar debug: Debug state
394 @type debug: C{bool}
395
396 @ivar _charset_: The charset used for settings recoding
397 @type _charset_: C{str}
398
399 @ivar _maps_: The value mappers to use or C{None}
400 @type _maps_: C{dict}
401 """
402
404 """ Constructor
405
406 Don't override this one. Override C{init()} instead.
407 """
408
409 self._charset_ = 'us-ascii'
410 self._fcharset_ = None
411 self._maps_ = None
412
413 self.groups = []
414 self.general = None
415 self.runtime = None
416
417
418 self.init(*args, **kwargs)
419
420
421 self._checkInitialization()
422
423
425 """ Checks if all containers are filled """
426 if not(self.general and self.runtime and self.groups):
427 raise RuntimeError("Settings are not completely initialized")
428
429
430 - def init(self, *args, **kwargs):
431 """ Abstract initialization method """
432 raise NotImplementedError()
433
434
436 """ Returns the basic arguments for container initialization
437
438 @return: The args
439 @rtype: C{list}
440 """
441 return [
442 self._maps_,
443 {'encoding': self._charset_, 'path_encoding': self._fcharset_}
444 ]
445
446
448 """ Returns an initialized group settings container
449
450 @return: The container object
451 @rtype: C{GroupSettingsContainer}
452 """
453 return GroupSettingsContainer(*self._getArgs(), **kwargs)
454
455
457 """ Returns an initialized default group settings container
458
459 @return: The container object
460 @rtype: C{GroupSettingsContainer}
461 """
462 args = self._getArgs()
463 args[0] = None
464 return GroupSettingsContainer(*args, **kwargs)
465
466
468 """ Returns an initialized general settings container
469
470 @return: The container object
471 @rtype: C{GeneralSettingsContainer}
472 """
473 return GeneralSettingsContainer(*self._getArgs(), **kwargs)
474
475
477 """ Returns an initialized runtime settings container
478
479 Note that the runtime settings (from commandline)
480 are always assumed to be utf-8 encoded.
481
482 @return: The container object
483 @rtype: C{RuntimeSettingsContainer}
484 """
485 args = self._getArgs()
486 args[0] = None
487 args[1]["encoding"] = "utf-8"
488 return RuntimeSettingsContainer(*args, **kwargs)
489