3 """Useful utilities for backend classes."""
5 import email.utils as _email_utils
6 import os.path as _os_path
7 import subprocess as _subprocess
11 _MSWINDOWS = _sys.platform == 'win32'
12 _POSIX = not _MSWINDOWS
15 def invoke(args, stdin=None, stdout=_subprocess.PIPE, stderr=_subprocess.PIPE,
18 expect should be a tuple of allowed exit codes.
22 q = _subprocess.Popen(args, stdin=_subprocess.PIPE,
23 stdout=stdout, stderr=stderr)
25 assert _MSWINDOWS == True, 'invalid platform'
26 # win32 don't have os.execvp() so run the command in a shell
27 q = _subprocess.Popen(args, stdin=_subprocess.PIPE,
28 stdout=stdout, stderr=stderr, shell=True)
30 raise ValueError([args, e])
31 stdout,stderr = q.communicate(input=stdin)
33 if status not in expect:
34 raise ValueError([args, status, stdout, stderr])
35 return status, stdout, stderr
38 """Recursively split a path into elements.
44 >>> splitpath(os.path.join('a', 'b', 'c'))
46 >>> splitpath(os.path.join('.', 'a', 'b', 'c'))
49 path = _os_path.normpath(path)
52 dirname,basename = _os_path.split(path)
53 elements.insert(0,basename)
54 if dirname in ['', '.']:
57 return tuple(elements)
59 def strip_email(*args):
60 """Remove email addresses from a series of names.
65 >>> strip_email('J Doe')
67 >>> strip_email('J Doe <jdoe@a.com>')
69 >>> strip_email('J Doe <jdoe@a.com>', 'JJJ Smith <jjjs@a.com>')
70 ['J Doe', 'JJJ Smith']
73 for i,arg in enumerate(args):
76 author,addr = _email_utils.parseaddr(arg)
82 def reverse_aliases(aliases):
83 """Reverse an `aliases` dict.
85 Input: key: canonical name, value: list of aliases
86 Output: key: alias, value: canonical name
92 ... 'J Doe <jdoe@a.com>':['Johnny <jdoe@b.edu>', 'J'],
93 ... 'JJJ Smith <jjjs@a.com>':['Jingly <jjjs@b.edu>'],
94 ... None:['Anonymous <a@a.com>'],
96 >>> r = reverse_aliases(aliases)
97 >>> for item in sorted(r.items()):
99 ('Anonymous <a@a.com>', None)
100 ('J', 'J Doe <jdoe@a.com>')
101 ('Jingly <jjjs@b.edu>', 'JJJ Smith <jjjs@a.com>')
102 ('Johnny <jdoe@b.edu>', 'J Doe <jdoe@a.com>')
105 for canonical_name,_aliases in aliases.items():
106 for alias in _aliases:
107 output[alias] = canonical_name
110 def replace_aliases(authors, with_email=True, aliases=None):
111 """Consolidate and sort `authors`.
113 Make the replacements listed in the `aliases` dict (key: canonical
114 name, value: list of aliases). If `aliases` is ``None``, default
118 ... 'J Doe <jdoe@a.com>':['Johnny <jdoe@b.edu>'],
119 ... 'JJJ Smith <jjjs@a.com>':['Jingly <jjjs@b.edu>'],
120 ... None:['Anonymous <a@a.com>'],
123 ... 'JJJ Smith <jjjs@a.com>', 'Johnny <jdoe@b.edu>',
124 ... 'Jingly <jjjs@b.edu>', 'J Doe <jdoe@a.com>', 'Anonymous <a@a.com>']
125 >>> replace_aliases(authors, with_email=True, aliases=aliases)
126 ['J Doe <jdoe@a.com>', 'JJJ Smith <jjjs@a.com>']
127 >>> replace_aliases(authors, with_email=False, aliases=aliases)
128 ['J Doe', 'JJJ Smith']
132 rev_aliases = reverse_aliases(aliases)
133 for i,author in enumerate(authors):
134 if author in rev_aliases:
135 authors[i] = rev_aliases[author]
136 authors = sorted(list(set(authors)))
139 if with_email == False:
140 authors = strip_email(*authors)