]> git.decadent.org.uk Git - dak.git/blob - daklib/textutils.py
Add by-hash support
[dak.git] / daklib / textutils.py
1 #!/usr/bin/env python
2 # vim:set et ts=4 sw=4:
3
4 """Text utility functions
5
6 @contact: Debian FTP Master <ftpmaster@debian.org>
7 @copyright: 2000, 2001, 2002, 2003, 2004, 2005, 2006  James Troup <james@nocrew.org>
8 @license: GNU General Public License version 2 or later
9 """
10
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 2 of the License, or
14 # (at your option) any later version.
15
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 # GNU General Public License for more details.
20
21 # You should have received a copy of the GNU General Public License
22 # along with this program; if not, write to the Free Software
23 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
25 import email.Header
26
27 from dak_exceptions import *
28 from regexes import re_parse_maintainer
29
30 ################################################################################
31
32 def force_to_utf8(s):
33     """
34     Forces a string to UTF-8.  If the string isn't already UTF-8,
35     it's assumed to be ISO-8859-1.
36     """
37     if isinstance(s, unicode):
38         return s
39     try:
40         unicode(s, 'utf-8')
41         return s
42     except UnicodeError:
43         latin1_s = unicode(s,'iso8859-1')
44         return latin1_s.encode('utf-8')
45
46 def rfc2047_encode(s):
47     """
48     Encodes a (header) string per RFC2047 if necessary.  If the
49     string is neither ASCII nor UTF-8, it's assumed to be ISO-8859-1.
50     """
51     for enc in ['ascii', 'utf-8', 'iso-8859-1']:
52         try:
53             h = email.Header.Header(s, enc, 998)
54             return str(h)
55         except UnicodeError:
56             pass
57
58     # If we get here, we're boned beyond belief
59     return ''
60
61 ################################################################################
62
63 # <Culus> 'The standard sucks, but my tool is supposed to interoperate
64 #          with it. I know - I'll fix the suckage and make things
65 #          incompatible!'
66
67 def fix_maintainer(maintainer):
68     """
69     Parses a Maintainer or Changed-By field and returns:
70       1. an RFC822 compatible version,
71       2. an RFC2047 compatible version,
72       3. the name
73       4. the email
74
75     The name is forced to UTF-8 for both 1. and 3..  If the name field
76     contains '.' or ',' (as allowed by Debian policy), 1. and 2. are
77     switched to 'email (name)' format.
78
79     """
80     maintainer = maintainer.strip()
81     if not maintainer:
82         return ('', '', '', '')
83
84     if maintainer.find("<") == -1:
85         email = maintainer
86         name = ""
87     elif (maintainer[0] == "<" and maintainer[-1:] == ">"):
88         email = maintainer[1:-1]
89         name = ""
90     else:
91         m = re_parse_maintainer.match(maintainer)
92         if not m:
93             raise ParseMaintError("Doesn't parse as a valid Maintainer field.")
94         name = m.group(1)
95         email = m.group(2)
96
97     # Get an RFC2047 compliant version of the name
98     rfc2047_name = rfc2047_encode(name)
99
100     # Force the name to be UTF-8
101     name = force_to_utf8(name)
102
103     if name.find(',') != -1 or name.find('.') != -1:
104         rfc822_maint = "%s (%s)" % (email, name)
105         rfc2047_maint = "%s (%s)" % (email, rfc2047_name)
106     else:
107         rfc822_maint = "%s <%s>" % (name, email)
108         rfc2047_maint = "%s <%s>" % (rfc2047_name, email)
109
110     if email.find("@") == -1 and email.find("buildd_") != 0:
111         raise ParseMaintError("No @ found in email address part.")
112
113     return (rfc822_maint, rfc2047_maint, name, email)
114
115 ################################################################################
116
117 def split_uploaders(field):
118     import re
119     for u in re.sub(">[ ]*,", ">\t", field).split("\t"):
120         yield u.strip()