Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(225)

Side by Side Diff: third_party/twisted_8_1/twisted/python/util.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.python.test.test_util -*-
2 # Copyright (c) 2001-2007 Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5 import os, sys, hmac, errno, new, inspect
6 try:
7 import pwd, grp
8 except ImportError:
9 pwd = grp = None
10 try:
11 from os import setgroups, getgroups
12 except ImportError:
13 setgroups = getgroups = None
14 from UserDict import UserDict
15
16
17 class InsensitiveDict:
18 """Dictionary, that has case-insensitive keys.
19
20 Normally keys are retained in their original form when queried with
21 .keys() or .items(). If initialized with preserveCase=0, keys are both
22 looked up in lowercase and returned in lowercase by .keys() and .items().
23 """
24 """
25 Modified recipe at
26 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66315 originally
27 contributed by Sami Hangaslammi.
28 """
29
30 def __init__(self, dict=None, preserve=1):
31 """Create an empty dictionary, or update from 'dict'."""
32 self.data = {}
33 self.preserve=preserve
34 if dict:
35 self.update(dict)
36
37 def __delitem__(self, key):
38 k=self._lowerOrReturn(key)
39 del self.data[k]
40
41 def _lowerOrReturn(self, key):
42 if isinstance(key, str) or isinstance(key, unicode):
43 return key.lower()
44 else:
45 return key
46
47 def __getitem__(self, key):
48 """Retrieve the value associated with 'key' (in any case)."""
49 k = self._lowerOrReturn(key)
50 return self.data[k][1]
51
52 def __setitem__(self, key, value):
53 """Associate 'value' with 'key'. If 'key' already exists, but
54 in different case, it will be replaced."""
55 k = self._lowerOrReturn(key)
56 self.data[k] = (key, value)
57
58 def has_key(self, key):
59 """Case insensitive test whether 'key' exists."""
60 k = self._lowerOrReturn(key)
61 return self.data.has_key(k)
62 __contains__=has_key
63
64 def _doPreserve(self, key):
65 if not self.preserve and (isinstance(key, str)
66 or isinstance(key, unicode)):
67 return key.lower()
68 else:
69 return key
70
71 def keys(self):
72 """List of keys in their original case."""
73 return list(self.iterkeys())
74
75 def values(self):
76 """List of values."""
77 return list(self.itervalues())
78
79 def items(self):
80 """List of (key,value) pairs."""
81 return list(self.iteritems())
82
83 def get(self, key, default=None):
84 """Retrieve value associated with 'key' or return default value
85 if 'key' doesn't exist."""
86 try:
87 return self[key]
88 except KeyError:
89 return default
90
91 def setdefault(self, key, default):
92 """If 'key' doesn't exists, associate it with the 'default' value.
93 Return value associated with 'key'."""
94 if not self.has_key(key):
95 self[key] = default
96 return self[key]
97
98 def update(self, dict):
99 """Copy (key,value) pairs from 'dict'."""
100 for k,v in dict.items():
101 self[k] = v
102
103 def __repr__(self):
104 """String representation of the dictionary."""
105 items = ", ".join([("%r: %r" % (k,v)) for k,v in self.items()])
106 return "InsensitiveDict({%s})" % items
107
108 def iterkeys(self):
109 for v in self.data.itervalues():
110 yield self._doPreserve(v[0])
111
112 def itervalues(self):
113 for v in self.data.itervalues():
114 yield v[1]
115
116 def iteritems(self):
117 for (k, v) in self.data.itervalues():
118 yield self._doPreserve(k), v
119
120 def popitem(self):
121 i=self.items()[0]
122 del self[i[0]]
123 return i
124
125 def clear(self):
126 for k in self.keys():
127 del self[k]
128
129 def copy(self):
130 return InsensitiveDict(self, self.preserve)
131
132 def __len__(self):
133 return len(self.data)
134
135 def __eq__(self, other):
136 for k,v in self.items():
137 if not (k in other) or not (other[k]==v):
138 return 0
139 return len(self)==len(other)
140
141 class OrderedDict(UserDict):
142 """A UserDict that preserves insert order whenever possible."""
143 def __init__(self, dict=None, **kwargs):
144 self._order = []
145 self.data = {}
146 if dict is not None:
147 if hasattr(dict,'keys'):
148 self.update(dict)
149 else:
150 for k,v in dict: # sequence
151 self[k] = v
152 if len(kwargs):
153 self.update(kwargs)
154 def __repr__(self):
155 return '{'+', '.join([('%r: %r' % item) for item in self.items()])+'}'
156
157 def __setitem__(self, key, value):
158 if not self.has_key(key):
159 self._order.append(key)
160 UserDict.__setitem__(self, key, value)
161
162 def copy(self):
163 return self.__class__(self)
164
165 def __delitem__(self, key):
166 UserDict.__delitem__(self, key)
167 self._order.remove(key)
168
169 def iteritems(self):
170 for item in self._order:
171 yield (item, self[item])
172
173 def items(self):
174 return list(self.iteritems())
175
176 def itervalues(self):
177 for item in self._order:
178 yield self[item]
179
180 def values(self):
181 return list(self.itervalues())
182
183 def iterkeys(self):
184 return iter(self._order)
185
186 def keys(self):
187 return list(self._order)
188
189 def popitem(self):
190 key = self._order[-1]
191 value = self[key]
192 del self[key]
193 return (key, value)
194
195 def setdefault(self, item, default):
196 if self.has_key(item):
197 return self[item]
198 self[item] = default
199 return default
200
201 def update(self, d):
202 for k, v in d.items():
203 self[k] = v
204
205 def uniquify(lst):
206 """Make the elements of a list unique by inserting them into a dictionary.
207 This must not change the order of the input lst.
208 """
209 dct = {}
210 result = []
211 for k in lst:
212 if not dct.has_key(k): result.append(k)
213 dct[k] = 1
214 return result
215
216 def padTo(n, seq, default=None):
217 """Pads a sequence out to n elements,
218
219 filling in with a default value if it is not long enough.
220
221 If the input sequence is longer than n, raises ValueError.
222
223 Details, details:
224 This returns a new list; it does not extend the original sequence.
225 The new list contains the values of the original sequence, not copies.
226 """
227
228 if len(seq) > n:
229 raise ValueError, "%d elements is more than %d." % (len(seq), n)
230
231 blank = [default] * n
232
233 blank[:len(seq)] = list(seq)
234
235 return blank
236
237 def getPluginDirs():
238 import twisted
239 systemPlugins = os.path.join(os.path.dirname(os.path.dirname(
240 os.path.abspath(twisted.__file__))), 'plugins')
241 userPlugins = os.path.expanduser("~/TwistedPlugins")
242 confPlugins = os.path.expanduser("~/.twisted")
243 allPlugins = filter(os.path.isdir, [systemPlugins, userPlugins, confPlugins] )
244 return allPlugins
245
246 def addPluginDir():
247 sys.path.extend(getPluginDirs())
248
249 def sibpath(path, sibling):
250 """Return the path to a sibling of a file in the filesystem.
251
252 This is useful in conjunction with the special __file__ attribute
253 that Python provides for modules, so modules can load associated
254 resource files.
255 """
256 return os.path.join(os.path.dirname(os.path.abspath(path)), sibling)
257
258
259 def _getpass(prompt):
260 """Helper to turn IOErrors into KeyboardInterrupts"""
261 import getpass
262 try:
263 return getpass.getpass(prompt)
264 except IOError, e:
265 if e.errno == errno.EINTR:
266 raise KeyboardInterrupt
267 raise
268 except EOFError:
269 raise KeyboardInterrupt
270
271 def getPassword(prompt = 'Password: ', confirm = 0, forceTTY = 0,
272 confirmPrompt = 'Confirm password: ',
273 mismatchMessage = "Passwords don't match."):
274 """Obtain a password by prompting or from stdin.
275
276 If stdin is a terminal, prompt for a new password, and confirm (if
277 C{confirm} is true) by asking again to make sure the user typed the same
278 thing, as keystrokes will not be echoed.
279
280 If stdin is not a terminal, and C{forceTTY} is not true, read in a line
281 and use it as the password, less the trailing newline, if any. If
282 C{forceTTY} is true, attempt to open a tty and prompt for the password
283 using it. Raise a RuntimeError if this is not possible.
284
285 @returns: C{str}
286 """
287 isaTTY = hasattr(sys.stdin, 'isatty') and sys.stdin.isatty()
288
289 old = None
290 try:
291 if not isaTTY:
292 if forceTTY:
293 try:
294 old = sys.stdin, sys.stdout
295 sys.stdin = sys.stdout = open('/dev/tty', 'r+')
296 except:
297 raise RuntimeError("Cannot obtain a TTY")
298 else:
299 password = sys.stdin.readline()
300 if password[-1] == '\n':
301 password = password[:-1]
302 return password
303
304 while 1:
305 try1 = _getpass(prompt)
306 if not confirm:
307 return try1
308 try2 = _getpass(confirmPrompt)
309 if try1 == try2:
310 return try1
311 else:
312 sys.stderr.write(mismatchMessage + "\n")
313 finally:
314 if old:
315 sys.stdin.close()
316 sys.stdin, sys.stdout = old
317
318
319 def dict(*a, **k):
320 import warnings
321 import __builtin__
322 warnings.warn('twisted.python.util.dict is deprecated. Use __builtin__.dict instead')
323 return __builtin__.dict(*a, **k)
324
325 def println(*a):
326 sys.stdout.write(' '.join(map(str, a))+'\n')
327
328 # XXX
329 # This does not belong here
330 # But where does it belong?
331
332 def str_xor(s, b):
333 return ''.join([chr(ord(c) ^ b) for c in s])
334
335 def keyed_md5(secret, challenge):
336 """Create the keyed MD5 string for the given secret and challenge."""
337 import warnings
338 warnings.warn(
339 "keyed_md5() is deprecated. Use the stdlib module hmac instead.",
340 DeprecationWarning, stacklevel=2
341 )
342 return hmac.HMAC(secret, challenge).hexdigest()
343
344 def makeStatBar(width, maxPosition, doneChar = '=', undoneChar = '-', currentCha r = '>'):
345 """Creates a function that will return a string representing a progress bar.
346 """
347 aValue = width / float(maxPosition)
348 def statBar(position, force = 0, last = ['']):
349 assert len(last) == 1, "Don't mess with the last parameter."
350 done = int(aValue * position)
351 toDo = width - done - 2
352 result = "[%s%s%s]" % (doneChar * done, currentChar, undoneChar * toDo)
353 if force:
354 last[0] = result
355 return result
356 if result == last[0]:
357 return ''
358 last[0] = result
359 return result
360
361 statBar.__doc__ = """statBar(position, force = 0) -> '[%s%s%s]'-style progre ss bar
362
363 returned string is %d characters long, and the range goes from 0..%d.
364 The 'position' argument is where the '%s' will be drawn. If force is false,
365 '' will be returned instead if the resulting progress bar is identical to th e
366 previously returned progress bar.
367 """ % (doneChar * 3, currentChar, undoneChar * 3, width, maxPosition, currentCha r)
368 return statBar
369
370 def spewer(frame, s, ignored):
371 """A trace function for sys.settrace that prints every function or method ca ll."""
372 from twisted.python import reflect
373 if frame.f_locals.has_key('self'):
374 se = frame.f_locals['self']
375 if hasattr(se, '__class__'):
376 k = reflect.qual(se.__class__)
377 else:
378 k = reflect.qual(type(se))
379 print 'method %s of %s at %s' % (
380 frame.f_code.co_name, k, id(se)
381 )
382 else:
383 print 'function %s in %s, line %s' % (
384 frame.f_code.co_name,
385 frame.f_code.co_filename,
386 frame.f_lineno)
387
388 def searchupwards(start, files=[], dirs=[]):
389 """Walk upwards from start, looking for a directory containing
390 all files and directories given as arguments::
391 >>> searchupwards('.', ['foo.txt'], ['bar', 'bam'])
392
393 If not found, return None
394 """
395 start=os.path.abspath(start)
396 parents=start.split(os.sep)
397 exists=os.path.exists; join=os.sep.join; isdir=os.path.isdir
398 while len(parents):
399 candidate=join(parents)+os.sep
400 allpresent=1
401 for f in files:
402 if not exists("%s%s" % (candidate, f)):
403 allpresent=0
404 break
405 if allpresent:
406 for d in dirs:
407 if not isdir("%s%s" % (candidate, d)):
408 allpresent=0
409 break
410 if allpresent: return candidate
411 parents.pop(-1)
412 return None
413
414
415 class LineLog:
416 """
417 A limited-size line-based log, useful for logging line-based
418 protocols such as SMTP.
419
420 When the log fills up, old entries drop off the end.
421 """
422 def __init__(self, size=10):
423 """
424 Create a new log, with size lines of storage (default 10).
425 A log size of 0 (or less) means an infinite log.
426 """
427 if size < 0:
428 size = 0
429 self.log = [None]*size
430 self.size = size
431
432 def append(self,line):
433 if self.size:
434 self.log[:-1] = self.log[1:]
435 self.log[-1] = line
436 else:
437 self.log.append(line)
438
439 def str(self):
440 return '\n'.join(filter(None,self.log))
441
442 def __getitem__(self, item):
443 return filter(None,self.log)[item]
444
445 def clear(self):
446 """Empty the log"""
447 self.log = [None]*self.size
448
449 def raises(exception, f, *args, **kwargs):
450 """Determine whether the given call raises the given exception"""
451 try:
452 f(*args, **kwargs)
453 except exception:
454 return 1
455 return 0
456
457 class IntervalDifferential:
458 """
459 Given a list of intervals, generate the amount of time to sleep between
460 \"instants\".
461
462 For example, given 7, 11 and 13, the three (infinite) sequences::
463
464 7 14 21 28 35 ...
465 11 22 33 44 ...
466 13 26 39 52 ...
467
468 will be generated, merged, and used to produce::
469
470 (7, 0) (4, 1) (2, 2) (1, 0) (7, 0) (1, 1) (4, 2) (2, 0) (5, 1) (2, 0)
471
472 New intervals may be added or removed as iteration proceeds using the
473 proper methods.
474 """
475
476 def __init__(self, intervals, default=60):
477 """
478 @type intervals: C{list} of C{int}, C{long}, or C{float} param
479 @param intervals: The intervals between instants.
480
481 @type default: C{int}, C{long}, or C{float}
482 @param default: The duration to generate if the intervals list
483 becomes empty.
484 """
485 self.intervals = intervals[:]
486 self.default = default
487
488 def __iter__(self):
489 return _IntervalDifferentialIterator(self.intervals, self.default)
490
491 class _IntervalDifferentialIterator:
492 def __init__(self, i, d):
493
494 self.intervals = [[e, e, n] for (e, n) in zip(i, range(len(i)))]
495 self.default = d
496 self.last = 0
497
498 def next(self):
499 if not self.intervals:
500 return (self.default, None)
501 last, index = self.intervals[0][0], self.intervals[0][2]
502 self.intervals[0][0] += self.intervals[0][1]
503 self.intervals.sort()
504 result = last - self.last
505 self.last = last
506 return result, index
507
508 def addInterval(self, i):
509 if self.intervals:
510 delay = self.intervals[0][0] - self.intervals[0][1]
511 self.intervals.append([delay + i, i, len(self.intervals)])
512 self.intervals.sort()
513 else:
514 self.intervals.append([i, i, 0])
515
516 def removeInterval(self, interval):
517 for i in range(len(self.intervals)):
518 if self.intervals[i][1] == interval:
519 index = self.intervals[i][2]
520 del self.intervals[i]
521 for i in self.intervals:
522 if i[2] > index:
523 i[2] -= 1
524 return
525 raise ValueError, "Specified interval not in IntervalDifferential"
526
527
528 class FancyStrMixin:
529 """
530 Set showAttributes to a sequence of strings naming attributes, OR
531 sequences of (attributeName, displayName, formatCharacter)
532 """
533 showAttributes = ()
534 def __str__(self):
535 r = ['<', hasattr(self, 'fancybasename') and self.fancybasename or self. __class__.__name__]
536 for attr in self.showAttributes:
537 if isinstance(attr, str):
538 r.append(' %s=%r' % (attr, getattr(self, attr)))
539 else:
540 r.append((' %s=' + attr[2]) % (attr[1], getattr(self, attr[0])))
541 r.append('>')
542 return ''.join(r)
543 __repr__ = __str__
544
545
546
547 class FancyEqMixin:
548 compareAttributes = ()
549 def __eq__(self, other):
550 if not self.compareAttributes:
551 return self is other
552 if isinstance(self, other.__class__):
553 return (
554 [getattr(self, name) for name in self.compareAttributes] ==
555 [getattr(other, name) for name in self.compareAttributes])
556 return NotImplemented
557
558
559 def __ne__(self, other):
560 result = self.__eq__(other)
561 if result is NotImplemented:
562 return result
563 return not result
564
565
566
567 def dsu(list, key):
568 L2 = [(key(e), i, e) for (i, e) in zip(range(len(list)), list)]
569 L2.sort()
570 return [e[2] for e in L2]
571
572 if pwd is None or grp is None or setgroups is None or getgroups is None:
573 def initgroups(uid, primaryGid):
574 """
575 Do nothing.
576
577 Underlying platform support require to manipulate groups is missing.
578 """
579 else:
580 def _setgroups_until_success(l):
581 while(1):
582 # NASTY NASTY HACK (but glibc does it so it must be okay):
583 # In case sysconfig didn't give the right answer, find the limit
584 # on max groups by just looping, trying to set fewer and fewer
585 # groups each time until it succeeds.
586 try:
587 setgroups(l)
588 except ValueError:
589 # This exception comes from python itself restricting
590 # number of groups allowed.
591 if len(l) > 1:
592 del l[-1]
593 else:
594 raise
595 except OSError, e:
596 if e.errno == errno.EINVAL and len(l) > 1:
597 # This comes from the OS saying too many groups
598 del l[-1]
599 else:
600 raise
601 else:
602 # Success, yay!
603 return
604
605 def initgroups(uid, primaryGid):
606 """
607 Initializes the group access list.
608
609 This is done by reading the group database /etc/group and using all
610 groups of which C{uid} is a member. The additional group
611 C{primaryGid} is also added to the list.
612
613 If the given user is a member of more than C{NGROUPS}, arbitrary
614 groups will be silently discarded to bring the number below that
615 limit.
616
617 @type uid: C{int}
618 @param uid: The UID for which to look up group information.
619
620 @type primaryGid: C{int} or C{NoneType}
621 @param primaryGid: If provided, an additional GID to include when
622 setting the groups.
623 """
624 try:
625 # Try to get the maximum number of groups
626 max_groups = os.sysconf("SC_NGROUPS_MAX")
627 except:
628 # No predefined limit
629 max_groups = 0
630
631 username = pwd.getpwuid(uid)[0]
632 l = []
633 if primaryGid is not None:
634 l.append(primaryGid)
635 for groupname, password, gid, userlist in grp.getgrall():
636 if username in userlist:
637 l.append(gid)
638 if len(l) == max_groups:
639 break # No more groups, ignore any more
640 try:
641 _setgroups_until_success(l)
642 except OSError, e:
643 # We might be able to remove this code now that we
644 # don't try to setgid/setuid even when not asked to.
645 if e.errno == errno.EPERM:
646 for g in getgroups():
647 if g not in l:
648 raise
649 else:
650 raise
651
652
653
654 def switchUID(uid, gid, euid=False):
655 if euid:
656 setuid = os.seteuid
657 setgid = os.setegid
658 else:
659 setuid = os.setuid
660 setgid = os.setgid
661 if gid is not None:
662 setgid(gid)
663 if uid is not None:
664 initgroups(uid, gid)
665 setuid(uid)
666
667
668 class SubclassableCStringIO(object):
669 """A wrapper around cStringIO to allow for subclassing"""
670 __csio = None
671
672 def __init__(self, *a, **kw):
673 from cStringIO import StringIO
674 self.__csio = StringIO(*a, **kw)
675
676 def __iter__(self):
677 return self.__csio.__iter__()
678
679 def next(self):
680 return self.__csio.next()
681
682 def close(self):
683 return self.__csio.close()
684
685 def isatty(self):
686 return self.__csio.isatty()
687
688 def seek(self, pos, mode=0):
689 return self.__csio.seek(pos, mode)
690
691 def tell(self):
692 return self.__csio.tell()
693
694 def read(self, n=-1):
695 return self.__csio.read(n)
696
697 def readline(self, length=None):
698 return self.__csio.readline(length)
699
700 def readlines(self, sizehint=0):
701 return self.__csio.readlines(sizehint)
702
703 def truncate(self, size=None):
704 return self.__csio.truncate(size)
705
706 def write(self, s):
707 return self.__csio.write(s)
708
709 def writelines(self, list):
710 return self.__csio.writelines(list)
711
712 def flush(self):
713 return self.__csio.flush()
714
715 def getvalue(self):
716 return self.__csio.getvalue()
717
718 def moduleMovedForSplit(origModuleName, newModuleName, moduleDesc,
719 projectName, projectURL, globDict):
720 from twisted.python import reflect
721 modoc = """
722 %(moduleDesc)s
723
724 This module is DEPRECATED. It has been split off into a third party
725 package, Twisted %(projectName)s. Please see %(projectURL)s.
726
727 This is just a place-holder that imports from the third-party %(projectName)s
728 package for backwards compatibility. To use it, you need to install
729 that package.
730 """ % {'moduleDesc': moduleDesc,
731 'projectName': projectName,
732 'projectURL': projectURL}
733
734 #origModule = reflect.namedModule(origModuleName)
735 try:
736 newModule = reflect.namedModule(newModuleName)
737 except ImportError:
738 raise ImportError("You need to have the Twisted %s "
739 "package installed to use %s. "
740 "See %s."
741 % (projectName, origModuleName, projectURL))
742
743 # Populate the old module with the new module's contents
744 for k,v in vars(newModule).items():
745 globDict[k] = v
746 globDict['__doc__'] = modoc
747 import warnings
748 warnings.warn("%s has moved to %s. See %s." % (origModuleName, newModuleName ,
749 projectURL),
750 DeprecationWarning, stacklevel=3)
751 return
752
753
754 def untilConcludes(f, *a, **kw):
755 while True:
756 try:
757 return f(*a, **kw)
758 except (IOError, OSError), e:
759 if e.args[0] == errno.EINTR:
760 continue
761 raise
762
763 # A value about twice as large as any Python int, to which negative values
764 # from id() will be added, moving them into a range which should begin just
765 # above where positive values from id() leave off.
766 _HUGEINT = (sys.maxint + 1L) * 2L
767 def unsignedID(obj):
768 """
769 Return the id of an object as an unsigned number so that its hex
770 representation makes sense
771 """
772 rval = id(obj)
773 if rval < 0:
774 rval += _HUGEINT
775 return rval
776
777 def mergeFunctionMetadata(f, g):
778 """
779 Overwrite C{g}'s name and docstring with values from C{f}. Update
780 C{g}'s instance dictionary with C{f}'s.
781
782 To use this function safely you must use the return value. In Python 2.3,
783 L{mergeFunctionMetadata} will create a new function. In later versions of
784 Python, C{g} will be mutated and returned.
785
786 @return: A function that has C{g}'s behavior and metadata merged from
787 C{f}.
788 """
789 try:
790 g.__name__ = f.__name__
791 except TypeError:
792 try:
793 merged = new.function(
794 g.func_code, g.func_globals,
795 f.__name__, inspect.getargspec(g)[-1],
796 g.func_closure)
797 except TypeError:
798 pass
799 else:
800 merged = g
801 try:
802 merged.__doc__ = f.__doc__
803 except (TypeError, AttributeError):
804 pass
805 try:
806 merged.__dict__.update(g.__dict__)
807 merged.__dict__.update(f.__dict__)
808 except (TypeError, AttributeError):
809 pass
810 merged.__module__ = f.__module__
811 return merged
812
813
814 def nameToLabel(mname):
815 """
816 Convert a string like a variable name into a slightly more human-friendly
817 string with spaces and capitalized letters.
818
819 @type mname: C{str}
820 @param mname: The name to convert to a label. This must be a string
821 which could be used as a Python identifier. Strings which do not take
822 this form will result in unpredictable behavior.
823
824 @rtype: C{str}
825 """
826 labelList = []
827 word = ''
828 lastWasUpper = False
829 for letter in mname:
830 if letter.isupper() == lastWasUpper:
831 # Continuing a word.
832 word += letter
833 else:
834 # breaking a word OR beginning a word
835 if lastWasUpper:
836 # could be either
837 if len(word) == 1:
838 # keep going
839 word += letter
840 else:
841 # acronym
842 # we're processing the lowercase letter after the acronym-th en-capital
843 lastWord = word[:-1]
844 firstLetter = word[-1]
845 labelList.append(lastWord)
846 word = firstLetter + letter
847 else:
848 # definitely breaking: lower to upper
849 labelList.append(word)
850 word = letter
851 lastWasUpper = letter.isupper()
852 if labelList:
853 labelList[0] = labelList[0].capitalize()
854 else:
855 return mname.capitalize()
856 labelList.append(word)
857 return ' '.join(labelList)
858
859
860
861 def uidFromString(uidString):
862 """
863 Convert a user identifier, as a string, into an integer UID.
864
865 @type uid: C{str}
866 @param uid: A string giving the base-ten representation of a UID or the
867 name of a user which can be converted to a UID via L{pwd.getpwnam}.
868
869 @rtype: C{int}
870 @return: The integer UID corresponding to the given string.
871
872 @raise ValueError: If the user name is supplied and L{pwd} is not
873 available.
874 """
875 try:
876 return int(uidString)
877 except ValueError:
878 if pwd is None:
879 raise
880 return pwd.getpwnam(uidString)[2]
881
882
883
884 def gidFromString(gidString):
885 """
886 Convert a group identifier, as a string, into an integer GID.
887
888 @type uid: C{str}
889 @param uid: A string giving the base-ten representation of a GID or the
890 name of a group which can be converted to a GID via L{grp.getgrnam}.
891
892 @rtype: C{int}
893 @return: The integer GID corresponding to the given string.
894
895 @raise ValueError: If the group name is supplied and L{grp} is not
896 available.
897 """
898 try:
899 return int(gidString)
900 except ValueError:
901 if grp is None:
902 raise
903 return grp.getgrnam(gidString)[2]
904
905
906
907 __all__ = [
908 "uniquify", "padTo", "getPluginDirs", "addPluginDir", "sibpath",
909 "getPassword", "dict", "println", "keyed_md5", "makeStatBar",
910 "OrderedDict", "InsensitiveDict", "spewer", "searchupwards", "LineLog",
911 "raises", "IntervalDifferential", "FancyStrMixin", "FancyEqMixin",
912 "dsu", "switchUID", "SubclassableCStringIO", "moduleMovedForSplit",
913 "unsignedID", "mergeFunctionMetadata", "nameToLabel", "uidFromString",
914 "gidFromString",
915 ]
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/python/usage.py ('k') | third_party/twisted_8_1/twisted/python/versions.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698