1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """
20 Internal module providing name escaping functionality.
21
22 This module implements some of public interface for the
23 pybaz_ package. But for convenience reasons the author prefers
24 to store this code in a file separate from ``__init__.py``.
25
26 .. _pybaz: pybaz-module.html
27
28 This module is strictly internal and should never be used.
29 """
30
31 __all__ = ['name_escape', 'name_unescape']
32
33 import errors
34
35
36
37 __space_escape_table = { '\t': 'tab', '\n': 'nl', '\v': 'U+B',
38 '\f': 'np', '\r': 'cr', ' ': 'sp' }
39
41 table = {}
42 for N in range(256):
43 C = chr(N)
44 if C in __space_escape_table: val = '\\(%s)' % __space_escape_table[C]
45 elif N < 32 or N > 127: val = '\\(U+%X)' % N
46 elif C in '\\': val = '\\'+C
47 else: val = C
48 table[C] = val
49 return table
50
51 __name_escape_table = __make_name_escape_table()
52
53 __space_unescape_table = {}
54 for k, v in __space_escape_table.items(): __space_unescape_table[v] = k
55
56
57
58
60 """Escape a file name using the Arch syntax.
61
62 :arg name: unescaped file name.
63 :type name: str
64 :return: escaped file name.
65 :rtype: str
66 """
67 return ''.join([__name_escape_table[C] for C in name])
68
69
71 """Unescape a file name using the Arch syntax.
72
73 :arg name: escaped file name.
74 :type name: str
75 :return: unescaped file name.
76 :rtype: str
77 :raise errors.IllegalEscapeSequence: the syntax of ``name`` is incorrect.
78 """
79 result = []
80 after_backslash = 'after_backslash'
81 in_brackets = 'in_brackets'
82 state = None
83 escape = None
84 for C in name:
85 if state is None:
86 if C != '\\':
87 result.append(C)
88 continue
89 else:
90 state = after_backslash
91 continue
92 elif state is after_backslash:
93 if C == '(':
94 escape = []
95 state = in_brackets
96 continue
97 elif C in '\\"':
98 state = None
99 result.append(C)
100 continue
101 else:
102 raise errors.IllegalEscapeSequence(name)
103 elif state is in_brackets:
104 if C != ')':
105 escape.append(C)
106 continue
107 else:
108 state = None
109 if len(escape) < 2:
110 raise errors.IllegalEscapeSequence(name)
111 escape_str = ''.join(escape)
112 escape = None
113 if escape_str[0:2] in ('U+', 'u+'):
114 try:
115 code = int(escape_str[2:], 16)
116 except ValueError:
117 raise errors.IllegalEscapeSequence(name)
118 if code > 255:
119 raise errors.IllegalEscapeSequence(name)
120 result.append(chr(code))
121 continue
122 else:
123 escape_str = escape_str.lower()
124 try:
125 result.append(__space_unescape_table[escape_str])
126 except KeyError:
127 raise errors.IllegalEscapeSequence(name)
128 continue
129 else:
130 raise AssertionError, "The programmer is on crack!"
131 if state is not None:
132 raise errors.IllegalEscapeSequence(name)
133 else:
134 return ''.join(result)
135