3 """Items common to both the client and server
8 from . import error as _error
11 _ENCODE_REGEXP = _re.compile(
12 '(' + '|'.join(['%', '\r', '\n']) + ')')
13 _DECODE_REGEXP = _re.compile('(%[0-9A-F]{2})')
14 _REQUEST_REGEXP = _re.compile('^(\w+)( *)(.*)\Z')
20 >>> encode('It grew by 5%!\n')
23 return _ENCODE_REGEXP.sub(
24 lambda x : to_hex(x.group()), string)
29 >>> decode('%22Look out!%22%0AWhere%3F')
32 return _DECODE_REGEXP.sub(
33 lambda x : from_hex(x.group()), string)
43 return chr(int(code[1:], 16))
53 return '%{:02X}'.format(ord(char))
56 class Request (object):
59 http://www.gnupg.org/documentation/manuals/assuan/Client-requests.html
61 >>> r = Request(command='BYE')
64 >>> r = Request(command='OPTION', parameters='testing at 5%')
66 'OPTION testing at 5%25'
67 >>> r.from_string('BYE')
70 >>> print(r.parameters)
72 >>> r.from_string('OPTION testing at 5%25')
75 >>> print(r.parameters)
77 >>> r.from_string(' invalid')
78 Traceback (most recent call last):
80 pyassuan.error.AssuanError: 170 Invalid request
81 >>> r.from_string('in-valid')
82 Traceback (most recent call last):
84 pyassuan.error.AssuanError: 170 Invalid request
86 def __init__(self, command=None, parameters=None):
87 self.command = command
88 self.parameters = parameters
92 return '{} {}'.format(self.command, encode(self.parameters))
95 def from_string(self, string):
96 if len(string) > 1000: # TODO: byte-vs-str and newlines?
97 raise _error.AssuanError(message='Line too long')
98 match = _REQUEST_REGEXP.match(string)
100 raise _error.AssuanError(message='Invalid request')
101 self.command = match.group(1)
104 self.parameters = decode(match.group(3))
106 raise _error.AssuanError(message='Invalid request')
108 self.parameters = None
111 class Response (object):
114 http://www.gnupg.org/documentation/manuals/assuan/Server-responses.html
116 >>> r = Response(type='OK')
119 >>> r = Response(type='ERR', parameters='1 General error')
121 'ERR 1 General error'
122 >>> r.from_string('OK')
125 >>> print(r.parameters)
127 >>> r.from_string('ERR 1 General error')
130 >>> print(r.parameters)
132 >>> r.from_string(' invalid')
133 Traceback (most recent call last):
135 pyassuan.error.AssuanError: 76 Invalid response
136 >>> r.from_string('in-valid')
137 Traceback (most recent call last):
139 pyassuan.error.AssuanError: 76 Invalid response
150 def __init__(self, type=None, parameters=None):
152 self.parameters = parameters
156 return '{} {}'.format(self.type, encode(self.parameters))
159 def from_string(self, string):
160 if len(string) > 1000: # TODO: byte-vs-str and newlines?
161 raise _error.AssuanError(message='Line too long')
163 type = self.types[string[0]]
165 raise _error.AssuanError(message='Invalid response')
167 if type == 'D': # data
168 self.parameters = decode(string[2:])
169 elif type == '#': # comment
170 self.parameters = decode(string[2:])
172 match = _REQUEST_REGEXP.match(string)
174 raise _error.AssuanError(message='Invalid request')
177 self.parameters = decode(match.group(3))
179 raise _error.AssuanError(message='Invalid request')
181 self.parameters = None
184 def error_response(error):
187 >>> from pyassuan.error import AssuanError
188 >>> error = AssuanError(1)
189 >>> response = error_response(error)
193 return Response(type='ERR', parameters=str(error))