1 """Functions for escaping and unescaping strings (for URLs, filenames, etc).
2
3 The underscore escaping functions are useful when generating directory names
4 which should be reasonably human-readable, and not contain characters which are
5 likely to confuse programs (e.g. ":" doesn't work on Windows, "#" confuses
6 cmake, "=" confuses Java, [:;,] confuse anything that uses these as list item
7 separators, etc.
8
9 See also L{zeroinstall.injector.model.escape} for an older escaping scheme.
10
11 @since: 1.13
12 """
13
14 import re
15
16
17
18
20 """@rtype: str"""
21 c = m.group(0)
22 if c == '/':
23 return '__'
24 else:
25 return '_%x_' % ord(c)
26
28 """@rtype: str"""
29 c = m.group(1)
30 if c == "":
31 return "/"
32 else:
33 return chr(int(m.group(1), 16))
34
35 _troublesome_re = re.compile(r'[]\\[^_`\0-,/:-@{|}~\x7f]')
36
38 """Escape troublesome characters in 'src'.
39 The result is a valid file leaf name (i.e. does not contain / etc).
40 Letters, digits and characters > 127 are copied unmodified.
41 '/' becomes '__'. Other characters become '_code_', where code is the
42 lowercase hex value of the character in Unicode.
43 @param src: the string to escape
44 @type src: str
45 @return: the escaped string
46 @rtype: str"""
47 escaped = re.sub(_troublesome_re, _under_escape, src)
48
49
50 if escaped.startswith("."):
51 return "_2e_" + escaped[1:]
52
53 return escaped
54
55 _escaped_code_re = re.compile('_([0-9a-fA-F]*)_')
56
58 """@type escaped: str
59 @rtype: str"""
60 return _escaped_code_re.sub(_ununder_escape, escaped)
61