1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """
18 Struct Member Definitions
19 =========================
20
21 This module exactly describes the struct member definitions used by
22 the svnmailer. All those definitions are pooled in the L{typemap} dict, which
23 can be supplied as-is to L{typedstruct.members}.
24
25 The following types are defined by this module:
26 - C{unicode}: see L{UnicodeDescriptor}
27 - C{string}: see L{StringDescriptor}
28 - C{int}: see L{IntegerDescriptor}
29 - C{bool}: see L{BooleanDescriptor}
30 - C{humanbool}: see L{HumanBooleanDescriptor}
31 - C{regex}: see L{RegexDescriptor}
32 - C{token}: see L{TokenDescriptor}
33 - C{tokenlist}: see L{TokenlistDescriptor}
34 - C{filename}: see L{FilenameDescriptor}
35 - C{unicommand}: see L{CommandlineDescriptor}
36 - C{quotedstr} : see L{QuotedstringDescriptor}
37 - C{stdin}: see L{StdinDescriptor}
38 - C{mailaction}: see L{MailactionDescriptor}
39
40 @var typemap: The type mapping dict (C{{<name>: <class>}})
41 @type typemap: C{svnmailer.util.ReadOnlyDict}
42 """
43 __author__ = "André Malo"
44 __docformat__ = "epytext en"
45 __all__ = ['typemap']
46
47
48 from svnmailer import typedstruct, util
49
50
51
53 """ This method is not supported """
54 pass
55
56
58 """ Base class for svnmailer descriptors """
59
60 - def __init__(self, name, private, param = None):
61 """ Initialization """
62 super(BaseDescriptor, self).__init__(name, private, param or {})
63 self.MAP = bool(self.param.get('map'))
64 self.SUBST = bool(self.param.get('subst'))
65
66
73
74
76 """ Substitute the value if it's activated """
77 if self.SUBST and value is not None:
78 value = self.doSubstitute(value, subst, arg)
79
80 return value
81
82
83 - def premap(self, value, mapper, arg):
84 """ Premap the value if it's activated """
85 if self.MAP and value is not None:
86 value = self.doPremap(value, mapper, arg)
87
88 return value
89
90
91 - def postmap(self, value, mapper, arg):
92 """ Postmap the value if it's activated """
93 if self.MAP and value is not None:
94 value = self.doPostmap(value, mapper, arg)
95
96 return value
97
98
100 """ Returns the charset """
101 return (arg and arg["encoding"]) or 'us-ascii'
102
103
105 """ Returns the file system charset """
106 return arg and arg["path_encoding"]
107
108
109 - def doPremap(self, value, mapper, arg):
110 """ abstract method
111
112 @param value: The value to premap
113 @type value: any
114
115 @param mapper: The mapper function
116 @type mapper: C{function}
117
118 @param arg: The argument used for struct initialization
119 @type arg: any
120 """
121 raise NotSupportedError()
122
123
137
138
140 """ abstract method
141
142 @param value: The value to substitute
143 @type value: any
144
145 @param subst: The substitution dictionary
146 @type subst: C{dict}
147
148 @param arg: The argument used for struct initialization
149 @type arg: any
150
151 @return: The substituted value
152 @rtype: any
153 """
154 raise NotSupportedError()
155
156
157 - def doPostmap(self, value, mapper, arg):
158 """ abstract method
159
160 @param value: The value to premap
161 @type value: any
162
163 @param mapper: The mapper function
164 @type mapper: C{function}
165
166 @param arg: The argument used for struct initialization
167 @type arg: any
168 """
169 raise NotSupportedError()
170
171
173 """ Base class for premap only descriptors """
174
175 - def doPremap(self, value, mapper, arg):
176 """ Maps the value """
177 return mapper(value)
178
179
180 - def doPostmap(self, value, mapper, arg):
181 """ Passes through """
182 return value
183
184
185 -class BasePostmapDescriptor(BaseDescriptor):
186 """ Base class for postmap only descriptors """
187
188 - def doPremap(self, value, mapper, arg):
189 """ Passes through """
190 return value
191
192
194 """ Unicode object storage """
195
213
214
216 """ Substitutes the value """
217 return util.substitute(value, subst)
218
219
220 - def doPostmap(self, value, mapper, arg):
221 """ Maps the value
222
223 @exception TypeError: The mapped value is neither C{str} nor
224 C{unicode}
225 @exception UnicodeError: The mapped value is a string and cannot
226 be interpreted as the specified charset
227 """
228 return self.transform(mapper(value), arg)
229
230
232 """ String storage """
233
241
242
244 """ Integer storage """
245
253
254
256 """ Boolean storage """
257
261
262
264 """ Boolean storage with translater from human readable booleans
265
266 @cvar TRUE: The true words (C{tuple} of C{str})
267 @type TRUE: C{tuple}
268
269 @cvar FALSE: The false words (C{tuple} of C{str})
270 @type FALSE: C{tuple}
271
272 @ivar HUMAN: The dictionary containing true and false keys
273 @type HUMAN: C{dict}
274 """
275 TRUE = ('1', 'yes', 'on', 'true')
276 FALSE = ('', '0', 'no', 'off', 'false', 'none')
277
278 - def __init__(self, name, private, param = None):
284
285
298
299
301 """ Regex storage
302
303 @ivar FLAGS: The flags for the regex compiler
304 @type FLAGS: C{int}
305 """
306
307 - def __init__(self, name, private, param = None):
311
312
333
334
336 """ Unicode token storage """
337
338 - def __init__(self, name, private, param = None):
339 """ Initialization """
340 super(TokenDescriptor, self).__init__(name, private, param)
341
342 allowed = self.param.get('allowed')
343 if allowed:
344 self.ALLOWED = dict.fromkeys([token.lower() for token in allowed])
345 else:
346 self.ALLOWED = None
347
348
374
375
377 """ (Unicode) Tokenlist storage """
378
379 - def __init__(self, name, private, param = None):
380 """ Initialization """
381 super(TokenlistDescriptor, self).__init__(name, private, param)
382
383 allowed = self.param.get('allowed')
384 if allowed:
385 self.ALLOWED = dict.fromkeys([token.lower() for token in allowed])
386 else:
387 self.ALLOWED = None
388
389
420
421
423 """ Substitutes the items """
424 return tuple([util.substitute(token, subst) for token in value])
425
426
427 - def doPostmap(self, value, mapper, arg):
428 """ Maps the items """
429 value = tuple([mapper(token) for token in value])
430
431 if self.ALLOWED:
432 for token in value:
433 if not self.ALLOWED.has_key(token.lower()):
434 raise ValueError(
435 "Supplied token %r is not allowed" % token
436 )
437
438 return value
439
440
442 """ Filename storage """
443
460 value = RecodedFilename(value)
461 else:
462 raise TypeError(
463 "Supplied value must be string or unicode, not %r" %
464 type(value).__name__
465 )
466
467 return value
468
469
471 """ Commandline storage """
472
502
503
505 """ Holds a quoted string """
506 import re
507 _parsed_quoted_string = (
508 re.compile(r'(?:[^"\s]\S*|"[^\\"]*(?:\\[\\"][^\\"]*)*")$'),
509 re.compile(r'\\([\\"])')
510 )
511 del re
512
514 """ Initialization and check
515
516 @param value: The value to initialize the string
517 @type value: C{str}
518
519 @exception ValueError: The string did not pass the test
520 """
521 checkre, subre = cls._parsed_quoted_string
522 if value and not checkre.match(value):
523 raise ValueError("Could not parse quoted string %r" % value)
524
525 if value.startswith('"'):
526 value = subre.sub(r'\1', value[1:-1])
527
528 return str.__new__(cls, value)
529
530
532 """ Returns the representation of the quoted string """
533 return repr(
534 '"%s"' % str(self).replace('\\', r'\\').replace('"', r'\"')
535 )
536
537
539 """ Quoted string storage """
540
557
558
560 """ Stdin storage """
561 _stdin = None
562
570
571
573 """ Mailaction container
574
575 @cvar TRUNCATE: C{truncate} token
576 @type TRUNCATE: C{str}
577
578 @cvar URLS: C{showurls} token
579 @type URLS: C{str}
580
581 @cvar SPLIT: C{split} token
582 @type SPLIT: C{str}
583
584 @cvar REVPROP: C{revprop-changes} token
585 @type REVPROP: C{str}
586
587 @cvar LOCKS: C{locks} token
588 @type LOCKS: C{str}
589
590 @ivar maxbytes: maximum number of bytes
591 @type maxbytes: C{int}
592
593 @ivar mode: basic mode (C{truncate}, C{showurls}, C{split})
594 @type mode: C{str}
595
596 @ivar truncate: truncate submode
597 @type truncate: C{bool}
598
599 @ivar drop: drop submode or C{None}
600 @type drop: C{int}
601
602 @ivar scope: additional scopes (C{revprop-changes}, C{locks})
603 @type scope: C{tuple}
604 """
605 maxbytes = 0
606 mode = None
607 truncate = False
608 drop = None
609 scope = ()
610
611 TRUNCATE = "truncate"
612 URLS = "showurls"
613 SPLIT = "split"
614
615 REVPROP = "revprop-changes"
616 LOCKS = "locks"
617
619 """ Initialization
620
621 @param action: The action as string
622 @type action: C{str}
623 """
624 _msg = "Can't parse action string %r" % (action,)
625
626 action = action.split()
627 if len(action) < 2:
628 raise ValueError(_msg)
629
630 self.maxbytes = int(action[0])
631 tokens = action[1].lower().split('/')
632
633 self.mode = tokens.pop(0).lower()
634 if self.mode not in (self.TRUNCATE, self.URLS, self.SPLIT):
635 raise ValueError(_msg)
636
637 if tokens and tokens[0].lower() == self.TRUNCATE:
638 if self.mode not in (self.URLS, self.SPLIT):
639 raise ValueError(_msg)
640 self.truncate = True
641 tokens.pop(0)
642
643 if tokens:
644 if self.mode != self.SPLIT:
645 raise ValueError(_msg)
646 self.drop = int(tokens.pop(0))
647
648 if tokens:
649 raise ValueError(_msg)
650
651 sdict = {}
652 for token in action[2:]:
653 if token.lower() not in (self.REVPROP, self.LOCKS):
654 raise ValueError(_msg)
655 sdict[token.lower()] = None
656 self.scope = tuple(sdict.keys())
657
658
660 """ String representation of the object
661
662 @return: The representation
663 @rtype: C{str}
664 """
665 result = "%d %s" % (self.maxbytes, self.mode)
666 if self.truncate:
667 result = "%s/truncate" % result
668 if self.drop:
669 result = "%s/%d" % (result, self.drop)
670 if self.scope:
671 scopes = list(self.scope)
672 scopes.sort()
673 result = " ".join([result] + scopes)
674
675 return result
676
677
679 """ Mail action parsing and storage """
680
696
697
698
699 typemap = util.ReadOnlyDict({
700 'unicode' : UnicodeDescriptor,
701 'string' : StringDescriptor,
702 'int' : IntegerDescriptor,
703 'bool' : BooleanDescriptor,
704 'humanbool' : HumanBooleanDescriptor,
705 'regex' : RegexDescriptor,
706 'token' : TokenDescriptor,
707 'tokenlist' : TokenlistDescriptor,
708 'filename' : FilenameDescriptor,
709 'unicommand': CommandlineDescriptor,
710 'quotedstr' : QuotedstringDescriptor,
711 'stdin' : StdinDescriptor,
712 'mailaction': MailactionDescriptor,
713 })
714