Merged Anton Batenev's report of Nicolas Alvarez' unicode-in-be-new bug
[be.git] / libbe / ui / util / user.py
1 # Copyright (C) 2009-2010 W. Trevor King <wking@drexel.edu>
2 #
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License along
14 # with this program; if not, write to the Free Software Foundation, Inc.,
15 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
17 """Tools for getting, setting, creating, and parsing the user's ID.
18
19 IDs will look like 'John Doe <jdoe@example.com>'.  Note that the
20 :mod:`libbe.storage.vcs.arch <Arch VCS backend>` *enforces* IDs with
21 this format.
22
23 Do not confuse the user IDs discussed in this module, which refer to
24 humans, with the "user IDs" discussed in :mod:`libbe.util.id`, which
25 are human-readable tags refering to objects.
26 """
27
28 try:
29     from email.utils import formataddr, parseaddr
30 except ImportErrror: # adjust to old python < 2.5
31     from email.Utils import formataddr, parseaddr
32 import os
33 import re
34 from socket import gethostname
35
36 import libbe
37 import libbe.storage.util.config
38
39 def get_fallback_username():
40     """Return a username extracted from environmental variables.
41     """
42     name = None
43     for env in ["LOGNAME", "USERNAME"]:
44         if os.environ.has_key(env):
45             name = os.environ[env]
46             break
47     assert name != None
48     return name
49
50 def get_fallback_email():
51     """Return an email address extracted from environmental variables.
52     """
53     hostname = gethostname()
54     name = get_fallback_username()
55     return "%s@%s" % (name, hostname)
56
57 def create_user_id(name, email=None):
58     """Create a user ID string from given `name` and `email` strings.
59
60     Examples
61     --------
62
63     >>> create_user_id("John Doe", "jdoe@example.com")
64     'John Doe <jdoe@example.com>'
65     >>> create_user_id("John Doe")
66     'John Doe'
67
68     See Also
69     --------
70     parse_user_id : inverse
71     """
72     assert len(name) > 0
73     if email == None or len(email) == 0:
74         return name
75     else:
76         return formataddr((name, email))
77
78 def parse_user_id(value):
79     """Parse a user ID string into `name` and `email` strings.
80
81     Examples
82     --------
83
84     >>> parse_user_id("John Doe <jdoe@example.com>")
85     ('John Doe', 'jdoe@example.com')
86     >>> parse_user_id("John Doe")
87     ('John Doe', None)
88     >>> parse_user_id("John Doe <jdoe@example.com><what?>")
89     ('John Doe', 'jdoe@example.com')
90  
91     See Also
92     --------
93     create_user_id : inverse
94     """
95     if '<' not in value:
96         return (value, None)
97     return parseaddr(value)
98
99 def get_user_id(storage=None):
100     """Return a user ID, checking a list of possible sources.
101
102     The source order is:
103
104     1. Global BE configuration.
105     2. `storage.get_user_id`, if that function is defined.
106     3. :func:`get_fallback_username` and :func:`get_fallback_email`.
107
108     Notes
109     -----
110     Sometimes the storage will keep track of the user ID (e.g. most
111     VCSs, see :meth:`libbe.storage.vcs.base.VCS.get_user_id`).  If so,
112     we prefer that ID to the fallback, since the user has likely
113     configured it directly.
114     """
115     user = libbe.storage.util.config.get_val('user')
116     if user != None:
117         return user
118     if storage != None and hasattr(storage, 'get_user_id'):
119         user = storage.get_user_id()
120         if user != None:
121             return user
122     name = get_fallback_username()
123     email = get_fallback_email()
124     user = create_user_id(name, email)
125     return user
126
127 def set_user_id(user_id):
128     """Set the user ID in a user's BE configuration.
129
130     See Also
131     --------
132     libbe.storage.util.config.set_val
133     """
134     user = libbe.storage.util.config.set_val('user', user_id)