From 5787fdf67de861fb846b6509602e46e2859da1c3 Mon Sep 17 00:00:00 2001 From: Alex Price Date: Wed, 23 Apr 2014 12:12:54 +0100 Subject: [PATCH 1/2] PEP8 formatted all py files --- collections.py | 776 +++++++++++++++++++++++++------------------------ conn.py | 163 ++++++----- parse.py | 118 ++++---- qtypes.py | 312 +++++++++++--------- 4 files changed, 732 insertions(+), 637 deletions(-) diff --git a/collections.py b/collections.py index 5d2e514..7c0519c 100644 --- a/collections.py +++ b/collections.py @@ -3,409 +3,429 @@ from qtypes import TranslateType, q_str from UserDict import DictMixin -#NOTE: Dealing with the impedance mismatch between Q symbols, chars and char lists and Python strings is a major pain-point -CHAR_CODE=10 +# NOTE: Dealing with the impedance mismatch between Q symbols, chars and +# char lists and Python strings is a major pain-point +CHAR_CODE = 10 + class q_list(list): - def __init__(self,l=[],code=None): - super(q_list,self).__init__(l) - if 0 == len(self): - self.type=parser.code_dict[0] - else: - if code: - self.type=parser.code_dict[code] - elif isinstance(l,q_str): - self.type=parser.code_dict[CHAR_CODE] - else: - self.type=self._determine_iter_type(l) - if self.type.code == 0: - self = _recurse_collections(self) - - @staticmethod - def convert_sequence(val): - if isinstance(val,q_str) and not val.is_char: - return q_list(val) - elif (not (isinstance(val,str) or isinstance(val,q_list) or isinstance(val,q_dict) or isinstance(val,table))) and ('__iter__' in dir(val) or '__getitem__' in dir(val)): - return q_list(val) - else: - return val - - @staticmethod - def _determine_iter_type(l,reeval=False): - if (not reeval) and 'type' in dir(l): - return l.type - tc=map(lambda x:parser.type(x).list_code,l) - for code in tc[1:]: - if tc[0] != code: - return parser.types['list'] - return parser.code_dict[tc[0]] - - def _determine_type(self): - self.type=self._determine_iter_type(self,True) - - def __getslice__(self,i,j): - return q_list(super(q_list,self).__getslice__(i,j)) - - @staticmethod - def _add_list_helper(type,y): - if type.list_code > 0 and q_list._determine_iter_type(y).code != type.code: - return parser.types['list'] - else: - return type - def __setitem__(self,i,y): - super(q_list,self).__setitem__(i,_recurse_collections(y)) - self.type = self._add_list_helper(self.type,[y]) + def __init__(self, l=[], code=None): + super(q_list, self).__init__(l) + if 0 == len(self): + self.type = parser.code_dict[0] + else: + if code: + self.type = parser.code_dict[code] + elif isinstance(l, q_str): + self.type = parser.code_dict[CHAR_CODE] + else: + self.type = self._determine_iter_type(l) + if self.type.code == 0: + self = _recurse_collections(self) + + @staticmethod + def convert_sequence(val): + if isinstance(val, q_str) and not val.is_char: + return q_list(val) + elif (not (isinstance(val, str) or isinstance(val, q_list) or isinstance(val, q_dict) or isinstance(val, table))) and ('__iter__' in dir(val) or '__getitem__' in dir(val)): + return q_list(val) + else: + return val + + @staticmethod + def _determine_iter_type(l, reeval=False): + if (not reeval) and 'type' in dir(l): + return l.type + tc = map(lambda x: parser.type(x).list_code, l) + for code in tc[1:]: + if tc[0] != code: + return parser.types['list'] + return parser.code_dict[tc[0]] + + def _determine_type(self): + self.type = self._determine_iter_type(self, True) + + def __getslice__(self, i, j): + return q_list(super(q_list, self).__getslice__(i, j)) + + @staticmethod + def _add_list_helper(type, y): + if type.list_code > 0 and q_list._determine_iter_type(y).code != type.code: + return parser.types['list'] + else: + return type + + def __setitem__(self, i, y): + super(q_list, self).__setitem__(i, _recurse_collections(y)) + self.type = self._add_list_helper(self.type, [y]) - def __setslice__(self,i,j,y): - super(q_list,self).__setslice__(i,j,_recurse_collections(y)) - self.type = self._add_list_helper(self.type,y) + def __setslice__(self, i, j, y): + super(q_list, self).__setslice__(i, j, _recurse_collections(y)) + self.type = self._add_list_helper(self.type, y) - def __delitem__(self,y): - super(q_list,self).__delitem__(y) - self._determine_type() + def __delitem__(self, y): + super(q_list, self).__delitem__(y) + self._determine_type() - def __delslice__(self,i,y): - super(q_list,self).__delslice__(i,y) - self._determine_type() + def __delslice__(self, i, y): + super(q_list, self).__delslice__(i, y) + self._determine_type() - def __mul__(self,n): - return q_list(super(q_list,self).__rmul__(n),code=self.type.code) + def __mul__(self, n): + return q_list(super(q_list, self).__rmul__(n), code=self.type.code) - def __rmul__(self,n): return self.__mul__(n) + def __rmul__(self, n): + return self.__mul__(n) - def __add__(self,y): - if self.type.code == self._determine_iter_type(y): - return q_list(super(q_list,self).__add__(_recurse_collections(y)),code=self.type.code) - else: - return q_list(super(q_list,self).__add__(_recurse_collections(y))) - - def __radd__(self,y): return self.__add__(y) - def __iadd__(self,y): return self.__add__(y) - - def append(self,x): - self[len(self):len(self)] = [_recurse_collections(x)] - - def extend(self,x): - self[len(self):len(self)] = _recurse_collections(x) - - def insert(self,i,x): - self[i:i] = [_recurse_collections(x)] - - def pop(self,i=None): - if i is None: - i = len(self) - 1 - x = self[i] - del self[i] - return x - - def remove(self,x): - del self[self.index(x)] - - @staticmethod - def _write(val,message): - return val._write_self(message) - - def _write_self(self,message): - message.fromstring(parser.write_byte(0)+parser.write_integer(len(self))) - for el in self: - if self.type.code != 0: - message.fromstring(self.type.write_data(el)) - else: - message.fromstring(parser.write(el)) - return message - - @staticmethod - def _read(reader,tcode,endianness,offset,bytes): - (n, offset) = parser.read_integer(endianness,offset+1,bytes) - val = q_list([]) - if n == 0: return (val,offset) - for i in range(0, n): - (item,offset) = reader(endianness,offset,bytes) - val.append(item) - if tcode is CHAR_CODE: - return (q_str(''.join(val)),offset) - else: - val._determine_type() - return (val,offset) - -class q_dict(object,DictMixin): - def __init__(self,arg=None,**kwargs): - self._keys=q_list() - self._values=q_list() - if getattr(arg,"keys",False) and getattr(arg,"values",False): - self._keys.extend(arg.keys()) - self._values.extend(arg.values()) - elif getattr(arg,"iteritems",False): - for (k,v) in arg.iteritems(): - self._keys.append(k) - self._values.append(v) - elif getattr(arg,"items",False): - for (k,v) in arg.items(): - self._keys.append(k) - self._values.append(v) - elif arg: - for (k,v) in arg: - self._keys.append(k) - self._values.append(v) - else: - self._keys.extend(kwargs.keys()) - self._values.extend(kwargs.values()) - - def keys(self): - return list(self._keys) - - def values(self): - return list(self._values) - - def __getitem__(self,i): - try: - return self._values[self._keys.index(i)] - except ValueError: - raise KeyError(i) - - def __setitem__(self,i,y): - try: - self._values[self._keys.index(i)]=y - except ValueError: - self._keys.append(i) - self._values.append(y) - - def __delitem__(self,i): - try: - p = self._keys.index(i) - del self.keys[p] - del self.keys[p] - except ValueError: - raise KeyError(i) - - def __contains__(self,i): - return i in self._keys - - def __iter__(self): - return iter(self._keys) - - def iteritems(self): - return izip(iter(self._keys),iter(self._values)) - - def __repr__(self): - return "{" + ", ".join([repr(self._keys[x])+": " + repr(self._values[x]) for x in xrange(0,len(self._keys))]) + "}" - - @staticmethod - def _smallest_diff_key(a,b): - return min([k for k in a if a.get(k) != b.get(k)]) - - def __cmp__(self,other): - if len(self) != len(other): - return cmp(len(self),len(other)) - self_diff = self._smallest_diff_key(self,other) - other_diff = self._smallest_diff_key(other,self) - if self_diff != other_diff: - return cmp(self_diff,other_diff) - return cmp(self[self_diff],other[other_diff]) - - @staticmethod - def _read(endianness,offset,bytes): - (keys,offset) = parser.read(endianness,offset,bytes) - (values,offset) = parser.read(endianness,offset,bytes) - dictionary=q_dict() - dictionary._keys=keys - dictionary._values=values - if isinstance(keys,table) and isinstance(values,table): - return (table(dictionary),offset) - else: - return (dictionary,offset) + def __add__(self, y): + if self.type.code == self._determine_iter_type(y): + return q_list(super(q_list, self).__add__(_recurse_collections(y)), code=self.type.code) + else: + return q_list(super(q_list, self).__add__(_recurse_collections(y))) + + def __radd__(self, y): + return self.__add__(y) + + def __iadd__(self, y): + return self.__add__(y) + + def append(self, x): + self[len(self):len(self)] = [_recurse_collections(x)] + + def extend(self, x): + self[len(self):len(self)] = _recurse_collections(x) + + def insert(self, i, x): + self[i:i] = [_recurse_collections(x)] + + def pop(self, i=None): + if i is None: + i = len(self) - 1 + x = self[i] + del self[i] + return x + + def remove(self, x): + del self[self.index(x)] + + @staticmethod + def _write(val, message): + return val._write_self(message) + + def _write_self(self, message): + message.fromstring(parser.write_byte(0) + + parser.write_integer(len(self))) + for el in self: + if self.type.code != 0: + message.fromstring(self.type.write_data(el)) + else: + message.fromstring(parser.write(el)) + return message + + @staticmethod + def _read(reader, tcode, endianness, offset, bytes): + (n, offset) = parser.read_integer(endianness, offset + 1, bytes) + val = q_list([]) + if n == 0: + return (val, offset) + for i in range(0, n): + (item, offset) = reader(endianness, offset, bytes) + val.append(item) + if tcode is CHAR_CODE: + return (q_str(''.join(val)), offset) + else: + val._determine_type() + return (val, offset) + + +class q_dict(object, DictMixin): + + def __init__(self, arg=None, **kwargs): + self._keys = q_list() + self._values = q_list() + if getattr(arg, "keys", False) and getattr(arg, "values", False): + self._keys.extend(arg.keys()) + self._values.extend(arg.values()) + elif getattr(arg, "iteritems", False): + for (k, v) in arg.iteritems(): + self._keys.append(k) + self._values.append(v) + elif getattr(arg, "items", False): + for (k, v) in arg.items(): + self._keys.append(k) + self._values.append(v) + elif arg: + for (k, v) in arg: + self._keys.append(k) + self._values.append(v) + else: + self._keys.extend(kwargs.keys()) + self._values.extend(kwargs.values()) + + def keys(self): + return list(self._keys) + + def values(self): + return list(self._values) + + def __getitem__(self, i): + try: + return self._values[self._keys.index(i)] + except ValueError: + raise KeyError(i) + + def __setitem__(self, i, y): + try: + self._values[self._keys.index(i)] = y + except ValueError: + self._keys.append(i) + self._values.append(y) + + def __delitem__(self, i): + try: + p = self._keys.index(i) + del self.keys[p] + del self.keys[p] + except ValueError: + raise KeyError(i) + + def __contains__(self, i): + return i in self._keys + + def __iter__(self): + return iter(self._keys) + + def iteritems(self): + return izip(iter(self._keys), iter(self._values)) + + def __repr__(self): + return "{" + ", ".join([repr(self._keys[x]) + ": " + repr(self._values[x]) for x in xrange(0, len(self._keys))]) + "}" + + @staticmethod + def _smallest_diff_key(a, b): + return min([k for k in a if a.get(k) != b.get(k)]) + + def __cmp__(self, other): + if len(self) != len(other): + return cmp(len(self), len(other)) + self_diff = self._smallest_diff_key(self, other) + other_diff = self._smallest_diff_key(other, self) + if self_diff != other_diff: + return cmp(self_diff, other_diff) + return cmp(self[self_diff], other[other_diff]) + + @staticmethod + def _read(endianness, offset, bytes): + (keys, offset) = parser.read(endianness, offset, bytes) + (values, offset) = parser.read(endianness, offset, bytes) + dictionary = q_dict() + dictionary._keys = keys + dictionary._values = values + if isinstance(keys, table) and isinstance(values, table): + return (table(dictionary), offset) + else: + return (dictionary, offset) + + @staticmethod + def _write(val, message): + if isinstance(val, table): + return parser.write(val._data._values, parser.write(val._data._keys, message)) + return parser.write(val.values(), parser.write(val.keys(), message)) - @staticmethod - def _write(val,message): - if isinstance(val,table): - return parser.write(val._data._values,parser.write(val._data._keys,message)) - return parser.write(val.values(),parser.write(val.keys(),message)) class flip(q_dict): - @staticmethod - def _read(endianness,offset,bytes): - (dictionary,offset) = parser.read(endianness,offset+1,bytes) - return (table(flip(dictionary)),offset) + @staticmethod + def _read(endianness, offset, bytes): + (dictionary, offset) = parser.read(endianness, offset + 1, bytes) + return (table(flip(dictionary)), offset) + + @staticmethod + def _write(val, message): + if isinstance(val, table): + val = val._data + message.fromstring(parser.write_byte(0) + parser.write_byte(99)) + return q_dict._write(val, message) - @staticmethod - def _write(val,message): - if isinstance(val,table): - val=val._data - message.fromstring(parser.write_byte(0)+parser.write_byte(99)) - return q_dict._write(val,message) class table(object): - def __init__(self,val,keys=[]): - if isinstance(val,flip): - self._data=val - self._type=flip - elif (isinstance(val,q_dict) and isinstance(val._keys,table) and isinstance(val._values,table)): - self._data=val - self._type=q_dict - elif 0 < len(keys): - self._data = q_dict() - self._data._keys = table(izip(keys,[val[x] for x in keys])) - non_keys = list(set(val.keys()).difference(keys)) - self._data._values = table(izip(non_keys,[val[x] for x in non_keys])) - self._type=q_dict - else: - self._data=flip(val) - self._type=flip - - def __eq__(self,other): - if sorted(self.cols()) != sorted(other.cols()): - return False - if len(self) != len(other): - return False - for col in self.cols: - if self[col] != other[col]: - return False - return True - - def __ne__(self,other): - return not self == other - - def __len__(self): - if self._type==flip: - return len(self[self.cols()[0]]) - else: - return len(self._data._keys) - def cols(self): - if self._type==flip: - return self._data.keys() - else: - return self._data._keys.cols() + self._data._values.cols() + def __init__(self, val, keys=[]): + if isinstance(val, flip): + self._data = val + self._type = flip + elif (isinstance(val, q_dict) and isinstance(val._keys, table) and isinstance(val._values, table)): + self._data = val + self._type = q_dict + elif 0 < len(keys): + self._data = q_dict() + self._data._keys = table(izip(keys, [val[x] for x in keys])) + non_keys = list(set(val.keys()).difference(keys)) + self._data._values = table( + izip(non_keys, [val[x] for x in non_keys])) + self._type = q_dict + else: + self._data = flip(val) + self._type = flip + + def __eq__(self, other): + if sorted(self.cols()) != sorted(other.cols()): + return False + if len(self) != len(other): + return False + for col in self.cols: + if self[col] != other[col]: + return False + return True + + def __ne__(self, other): + return not self == other + + def __len__(self): + if self._type == flip: + return len(self[self.cols()[0]]) + else: + return len(self._data._keys) - def keys(self): - if self._type==flip: - raise ValueError - else: - return self._data._keys + def cols(self): + if self._type == flip: + return self._data.keys() + else: + return self._data._keys.cols() + self._data._values.cols() - def values(self): - if self._type==flip: - raise ValueError - else: - return self._data._values - - @staticmethod - def _validate_row(val,row): - kfunc = getattr(row,"cols",getattr(row,"keys",False)) - if kfunc: - return sorted(val.cols()) == sorted(kfunc()) - if len(val.cols()) > 1: - if len(val.cols()) != len(row): - return False - else: - if getattr(row,"__len__",False): - return False - return True - - def __getitem__(self,key): - if self._type==flip: - if isinstance(key,int): - return q_dict(izip(self.cols(),[self._data[c][key] for c in self.cols()])) - elif isinstance(key,slice): - return table(flip(q_dict(izip(self.cols(),[self._data[c][key] for c in self.cols()])))) - else: - return self._data[key] - else: - if not self._validate_row(self.keys(),key): - raise KeyError - return self._data._values[self._data._keys.index(key)] - - def __setitem__(self,key,value): - if self._type==flip: - if isinstance(key,int) or isinstance(key,slice): - if not self._validate_row(self,value): - raise ValueError - kfunc = getattr(value,"cols",getattr(value,"keys",False)) + def keys(self): + if self._type == flip: + raise ValueError + else: + return self._data._keys + + def values(self): + if self._type == flip: + raise ValueError + else: + return self._data._values + + @staticmethod + def _validate_row(val, row): + kfunc = getattr(row, "cols", getattr(row, "keys", False)) if kfunc: - for vk in kfunc(): - self._data[vk][key] = value[vk] + return sorted(val.cols()) == sorted(kfunc()) + if len(val.cols()) > 1: + if len(val.cols()) != len(row): + return False else: - for i, vk in enumerate(self.cols()): - self._data[vk][key] = value[i] - else: - if len(value) != len(self._data[key]): - raise ValueError - self._data[key] = value - else: - if not self._validate_row(self.keys(),key): - raise KeyError - self._data._values[self._data._keys.index(key)] = value - - def __delitem__(self,key): - if self._type==flip: - if isinstance(key,int) or isinstance(key,slice): - for c in self.cols(): - del self._data[c][key] - else: - del self._data[key] - else: - if not self._validate_row(self.keys(),key): - raise KeyError - del self._data._values[self._data._keys.index(key)] - del self._data._keys[self._data._keys.index(key)] - - def index(self,val,start=0,stop=None,raise_miss=True): - if getattr(val,"keys",False): - cols = val.keys() - elif not getattr(val,"__len__",False): - cols = [self.cols()[0]] - val = dict([(cols[0],val)]) - else: - cols = self.cols()[0:len(val)] - val = dict(izip(cols,val)) - for i in xrange(start,stop or len(self)): - row = self[i] - match = True - for col in cols: - if row[col] != val[col]: - match = False - if match: - return i - if raise_miss: - raise ValueError - else: - return None + if getattr(row, "__len__", False): + return False + return True + + def __getitem__(self, key): + if self._type == flip: + if isinstance(key, int): + return q_dict(izip(self.cols(), [self._data[c][key] for c in self.cols()])) + elif isinstance(key, slice): + return table(flip(q_dict(izip(self.cols(), [self._data[c][key] for c in self.cols()])))) + else: + return self._data[key] + else: + if not self._validate_row(self.keys(), key): + raise KeyError + return self._data._values[self._data._keys.index(key)] + + def __setitem__(self, key, value): + if self._type == flip: + if isinstance(key, int) or isinstance(key, slice): + if not self._validate_row(self, value): + raise ValueError + kfunc = getattr(value, "cols", getattr(value, "keys", False)) + if kfunc: + for vk in kfunc(): + self._data[vk][key] = value[vk] + else: + for i, vk in enumerate(self.cols()): + self._data[vk][key] = value[i] + else: + if len(value) != len(self._data[key]): + raise ValueError + self._data[key] = value + else: + if not self._validate_row(self.keys(), key): + raise KeyError + self._data._values[self._data._keys.index(key)] = value + + def __delitem__(self, key): + if self._type == flip: + if isinstance(key, int) or isinstance(key, slice): + for c in self.cols(): + del self._data[c][key] + else: + del self._data[key] + else: + if not self._validate_row(self.keys(), key): + raise KeyError + del self._data._values[self._data._keys.index(key)] + del self._data._keys[self._data._keys.index(key)] + + def index(self, val, start=0, stop=None, raise_miss=True): + if getattr(val, "keys", False): + cols = val.keys() + elif not getattr(val, "__len__", False): + cols = [self.cols()[0]] + val = dict([(cols[0], val)]) + else: + cols = self.cols()[0:len(val)] + val = dict(izip(cols, val)) + for i in xrange(start, stop or len(self)): + row = self[i] + match = True + for col in cols: + if row[col] != val[col]: + match = False + if match: + return i + if raise_miss: + raise ValueError + else: + return None - def __iter__(self): - if self._type == flip: - for i in xrange(0,len(self)): - yield self[i] - else: - for i in xrange(0,len(self._data._values)): - yield self._data._values[i] + def __iter__(self): + if self._type == flip: + for i in xrange(0, len(self)): + yield self[i] + else: + for i in xrange(0, len(self._data._values)): + yield self._data._values[i] + + def __contains__(self, item): + if self._type == flip: + return None != self.index(item, raise_miss=False) + else: + if not self._validate_row(self.keys(), item): + raise KeyError + return None != self._data._keys.index(item, raise_miss=False) - def __contains__(self,item): - if self._type == flip: - return None != self.index(item,raise_miss=False) - else: - if not self._validate_row(self.keys(),item): - raise KeyError - return None != self._data._keys.index(item,raise_miss=False) def _unknown_collection(x): - return '__iter__' in dir(x) and not (isinstance(x,q_list) or isinstance(x,q_dict) or isinstance(x,table)) + return '__iter__' in dir(x) and not (isinstance(x, q_list) or isinstance(x, q_dict) or isinstance(x, table)) + def _recurse_collections(c): - if not _unknown_collection(c): - return c - if isinstance(c,dict): - return q_dict(c) - elif isinstance(c,list): - for (i,e) in enumerate(c): - if _unknown_collection(e): - c[i] = _recurse_collections(e) - return q_list(c) - else: - raise ValueError("Unknown collection type: " + str(type(c))) - -parser.types['dict'] = TranslateType(q_dict,99,overwrite_write=q_dict._write,overwrite_read=q_dict._read) -parser.types['flip'] = TranslateType(flip,98,overwrite_write=flip._write,overwrite_read=flip._read) -parser.types['list'] = TranslateType(q_list,0,overwrite_write=q_list._write,overwrite_read=q_list._read) + if not _unknown_collection(c): + return c + if isinstance(c, dict): + return q_dict(c) + elif isinstance(c, list): + for (i, e) in enumerate(c): + if _unknown_collection(e): + c[i] = _recurse_collections(e) + return q_list(c) + else: + raise ValueError("Unknown collection type: " + str(type(c))) + +parser.types['dict'] = TranslateType( + q_dict, 99, overwrite_write=q_dict._write, overwrite_read=q_dict._read) +parser.types['flip'] = TranslateType( + flip, 98, overwrite_write=flip._write, overwrite_read=flip._read) +parser.types['list'] = TranslateType( + q_list, 0, overwrite_write=q_list._write, overwrite_read=q_list._read) parser.types['table'] = TranslateType(table) diff --git a/conn.py b/conn.py index 9d69fe6..100cf2b 100644 --- a/conn.py +++ b/conn.py @@ -8,83 +8,92 @@ _parser.update_types() + class conn(object): - - SYNC=True - ASYNC=False - RECONNECT_ATTEMPTS = 5 # Number of reconnect attempts to make before throwing exception - RECONNECT_WAIT = 5000 # Milliseconds to wait between reconnect attempts - MAX_MSG_QUERY_LENGTH = 1024 # Maximum number of characters from query to return in exception message - MAX_MSG_LIST_LENGTH = 100 # Maximum length of a data list specified in a query before it is summarized in exception message - def __init__(self, host='localhost', port=5000, user=''): - self.host=host - self.port=port - self.user=user - self.sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.connect() - - def close(self): - self.sock.close() - - def connect(self, attempts=1): - # This for loop doesn't make sense, if there's an exception it'll just quit - for attempt in range(attempts): - try: - self.sock.connect((self.host,self.port)) - login = array.array('b',self.user + '\0') #null terminated signed char array (bytes) - self.sock.send(login.tostring()) - result = self.sock.recv(1) #blocking recv - if not result: - raise Exception("access denied") - except: - raise Exception ('unable to connect to host') - - def __call__(self, *args): - if len(args): - args=list(args) - if isinstance(args[0], str): - args[0]=q_str(args[0]) - if len(args) == 1: - args=args[0] - self._send(conn.SYNC,args) - return self._receive() - - def _send(self, sync, query): - if sync: - message = array.array('b', [0,1,0,0]) # 1 for synchronous requests - else: - message = array.array('b', [0,0,0,0]) # 1 for synchronous requests - message.fromstring(_parser.write_integer(0)) # reserve space for message length - message = _parser.write(query,message) - message[4:8] = _parser.write_integer(len(message)) - self.last_outgoing=message - self.sock.send(message) + SYNC = True + ASYNC = False + # Number of reconnect attempts to make before throwing exception + RECONNECT_ATTEMPTS = 5 + RECONNECT_WAIT = 5000 # Milliseconds to wait between reconnect attempts + # Maximum number of characters from query to return in exception message + MAX_MSG_QUERY_LENGTH = 1024 + # Maximum length of a data list specified in a query before it is + # summarized in exception message + MAX_MSG_LIST_LENGTH = 100 + + def __init__(self, host='localhost', port=5000, user=''): + self.host = host + self.port = port + self.user = user + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.connect() + + def close(self): + self.sock.close() + + def connect(self, attempts=1): + # This for loop doesn't make sense, if there's an exception it'll just + # quit + for attempt in range(attempts): + try: + self.sock.connect((self.host, self.port)) + # null terminated signed char array (bytes) + login = array.array('b', self.user + '\0') + self.sock.send(login.tostring()) + result = self.sock.recv(1) # blocking recv + if not result: + raise Exception("access denied") + except: + raise Exception('unable to connect to host') + + def __call__(self, *args): + if len(args): + args = list(args) + if isinstance(args[0], str): + args[0] = q_str(args[0]) + if len(args) == 1: + args = args[0] + self._send(conn.SYNC, args) + return self._receive() + + def _send(self, sync, query): + if sync: + # 1 for synchronous requests + message = array.array('b', [0, 1, 0, 0]) + else: + # 1 for synchronous requests + message = array.array('b', [0, 0, 0, 0]) + # reserve space for message length + message.fromstring(_parser.write_integer(0)) + message = _parser.write(query, message) + message[4:8] = _parser.write_integer(len(message)) + self.last_outgoing = message + self.sock.send(message) + + def _receive(self): + """read the response from the server""" + header = self.sock.recv(8) + # Endianness of byte doesn't matter when determining endianness + endianness = lambda x: x + if not _parser.read_byte(endianness, 0, header)[0] == 1: + endianness = '>'.__add__ + (data_size, self.offset) = _parser.read_integer(endianness, 4, header) + + bytes = self._recv_size(data_size - 8) + # ensure that it reads all the data + if _parser.read_byte(endianness, 0, bytes)[0] == -128: + (val, self.offset) = _parser.read_symbol(endianness, 1, bytes) + raise Exception(val) + (val, self.offset) = _parser.read(endianness, 0, bytes) + return val - def _receive(self): - """read the response from the server""" - header = self.sock.recv(8) - #Endianness of byte doesn't matter when determining endianness - endianness = lambda x:x - if not _parser.read_byte(endianness,0,header)[0] == 1: - endianness = '>'.__add__ - (data_size,self.offset) = _parser.read_integer(endianness,4,header) - - bytes = self._recv_size(data_size - 8) - #ensure that it reads all the data - if _parser.read_byte(endianness,0,bytes)[0] == -128 : - (val,self.offset) = _parser.read_symbol(endianness,1,bytes) - raise Exception(val) - (val,self.offset) = _parser.read(endianness,0,bytes) - return val - - def _recv_size(self, size): - """read size bytes from the socket.""" - data=cStringIO.StringIO() - recv_size=min(size,8192) - while data.tell() 0 and t < 98: - return self.types['list'].overwrite_read(self.code_dict[t].read_data,t,endianness,offset,bytes) - elif t is 0: - return self.types['list'].overwrite_read(self.read,t,endianness,offset,bytes) - else: - (v,offset) = self.read_byte(endianness,offset,bytes) - if t == 101 and v == 0: return (None,offset) - else: return ("func",len(bytes)) - - def write(self,val,message=None): - if message is None: message = array.array('b') - val = self.types['list'].type.convert_sequence(val) - t = self.type(val) - if t.code is 0: - t_code = val.type.list_code - else: - t_code = t.code - message.fromstring(parser.write_byte(t_code)) - return t.write_data(val,message) + + def __init__(self, types): + self.types = types + # Defines order of type code lookup (important for types like q_str + # that are sub_types of a type already used for translation) + self.type_order = [ + 'char', 'symbol', 'month', 'date', 'minute', 'second', 'time', 'datetime', + 'int', 'long', 'float', 'bool', 'real', 'short', 'byte', 'dict', 'flip', 'table'] + + def update_types(self): + self.read_byte = types['byte'].read_data + self.write_byte = types['byte'].write_data + self.read_integer = types['int'].read_data + self.write_integer = types['int'].write_data + self.read_symbol = types['symbol'].read_data + self.write_symbol = types['symbol'].write_data + + self._type_dict = dict( + map(lambda x: (x.type, x), self.types.itervalues())) + self._type_preferences = [(x.type, x) + for x in map(self.types.get, self.type_order)] + self.code_dict = dict( + map(lambda x: (x.list_code, x), self.types.itervalues())) + + def type(self, x): + if isinstance(x, q_none): + return self.code_dict[x.code] + if isinstance(x, list) or (isinstance(x, q_str) and not x.is_char): + return self.types['list'] + if isinstance(x, self.types['table'].type): + return self.type(x._data) + t = self._type_dict.get(type(x)) + if t: + return t + for (inherited_type, t) in self._type_preferences: + if isinstance(x, inherited_type): + return t + return TranslateType() + + def read(self, endianness, offset, bytes): + (t, offset) = self.read_byte(endianness, offset, bytes) + if t < 0 or t == 98 or t == 99: + return self.code_dict[abs(t)].read_data(endianness, offset, bytes) + elif t > 0 and t < 98: + return self.types['list'].overwrite_read(self.code_dict[t].read_data, t, endianness, offset, bytes) + elif t is 0: + return self.types['list'].overwrite_read(self.read, t, endianness, offset, bytes) + else: + (v, offset) = self.read_byte(endianness, offset, bytes) + if t == 101 and v == 0: + return (None, offset) + else: + return ("func", len(bytes)) + + def write(self, val, message=None): + if message is None: + message = array.array('b') + val = self.types['list'].type.convert_sequence(val) + t = self.type(val) + if t.code is 0: + t_code = val.type.list_code + else: + t_code = t.code + message.fromstring(parser.write_byte(t_code)) + return t.write_data(val, message) parser = Parser(types) diff --git a/qtypes.py b/qtypes.py index 34e0e65..853d299 100644 --- a/qtypes.py +++ b/qtypes.py @@ -4,8 +4,8 @@ from datetime import date, time, datetime, timedelta # Begin Time Translation Stuff -_Y2KDAYS = date(2000,1,1).toordinal() -_Y2KDATETIME = datetime(2000,1,1) +_Y2KDAYS = date(2000, 1, 1).toordinal() +_Y2KDATETIME = datetime(2000, 1, 1) _MILLISECONDS_PER_HOUR = int(3.6e6) _MILLISECONDS_PER_MINUTE = 60000 @@ -14,166 +14,218 @@ _SECONDS_PER_DAY = 86400.0 _MICROSECONDS_PER_DAY = _SECONDS_PER_DAY * 1e6 + class q_none(object): - def __init__(self,code): - self.code = code - def __str__(self): return "Null" - def __repr__(self): return "" + + def __init__(self, code): + self.code = code + + def __str__(self): + return "Null" + + def __repr__(self): + return "" + class specials(object): - def __init__(self,pos_inf_q,pos_inf_py,neg_inf_q,neg_inf_py,null_q,null_py): - self.pos_inf_q=pos_inf_q - self.neg_inf_q=neg_inf_q - self.null_q=null_q - self.pos_inf_py=pos_inf_py - self.neg_inf_py=neg_inf_py - self.null_py=null_py - - @staticmethod - def _swapper(pos_inf_1,pos_inf_2,neg_inf_1,neg_inf_2,null_1,null_2,func,x): - if x == pos_inf_1: return pos_inf_2 - elif x == neg_inf_1: return neg_inf_2 - elif (x == null_1) or x != x: return null_2 - else: return func(x) - - def read(self,func): - return lambda x: self._swapper(self.pos_inf_q,self.pos_inf_py,self.neg_inf_q,self.neg_inf_py,self.null_q,self.null_py,func,x) - - def write(self,func): - return lambda x: self._swapper(self.pos_inf_py,self.pos_inf_q,self.neg_inf_py,self.neg_inf_q,self.null_py,self.null_q,func,x) + + def __init__(self, pos_inf_q, pos_inf_py, neg_inf_q, neg_inf_py, null_q, null_py): + self.pos_inf_q = pos_inf_q + self.neg_inf_q = neg_inf_q + self.null_q = null_q + self.pos_inf_py = pos_inf_py + self.neg_inf_py = neg_inf_py + self.null_py = null_py + + @staticmethod + def _swapper(pos_inf_1, pos_inf_2, neg_inf_1, neg_inf_2, null_1, null_2, func, x): + if x == pos_inf_1: + return pos_inf_2 + elif x == neg_inf_1: + return neg_inf_2 + elif (x == null_1) or x != x: + return null_2 + else: + return func(x) + + def read(self, func): + return lambda x: self._swapper(self.pos_inf_q, self.pos_inf_py, self.neg_inf_q, self.neg_inf_py, self.null_q, self.null_py, func, x) + + def write(self, func): + return lambda x: self._swapper(self.pos_inf_py, self.pos_inf_q, self.neg_inf_py, self.neg_inf_q, self.null_py, self.null_q, func, x) + class month(date): - @classmethod - def from_int(cls,x): - m = x + 24000 - return cls(m / 12,(m%12)+1,1) - @classmethod - def from_date(cls,x): - return cls(x.year,x.month,1) + @classmethod + def from_int(cls, x): + m = x + 24000 + return cls(m / 12, (m % 12) + 1, 1) + + @classmethod + def from_date(cls, x): + return cls(x.year, x.month, 1) + + def __int__(self): + return (self.year * 12 + self.month - 1) - 24000 - def __int__(self): - return (self.year * 12 + self.month - 1) - 24000 class minute(time): - @classmethod - def from_int(cls,x): - return cls(x/60,x%60) - @classmethod - def from_time(cls,x): - return cls(x.hour,x.minute) + @classmethod + def from_int(cls, x): + return cls(x / 60, x % 60) + + @classmethod + def from_time(cls, x): + return cls(x.hour, x.minute) + + def __int__(self): + return (self.hour * 60 + self.minute) - def __int__(self): - return (self.hour * 60 + self.minute) class second(time): - @classmethod - def from_int(cls,x): - return cls(x/3600,(x/60)%60,x%60) - - @classmethod - def from_time(cls,x): - return cls(x.hour,x.minute,x.second) - - def __int__(self): - return (self.hour * 3600 + self.minute * 60 + self.second) - -shandlers={} -shandlers['short']=specials(32767,32767,-32767,-32767,-32768,q_none(5)) -shandlers['int']=specials(2147483647,2147483647,-2147483647,-2147483647,-2147483648,q_none(6)) -shandlers['long']=specials(9223372036854775807,9223372036854775807,-9223372036854775807,-9223372036854775807,-9223372036854775808,q_none(7)) -shandlers['date']=specials(2147483647,date.max,-2147483647,date.min,-2147483648,q_none(14)) -shandlers['month']=specials(2147483647,month.from_date(date.max),-2147483647,month.from_date(date.min),-2147483648,q_none(13)) -shandlers['datetime']=specials(float('inf'),datetime.max,float('-inf'),datetime.min,float('nan'),q_none(15)) -shandlers['time']=specials(2147483647,time.max,-2147483647,time.min,-2147483648,q_none(19)) -shandlers['minute']=specials(2147483647,minute.from_time(time.max),-2147483647,minute.from_time(time.min),-2147483648,q_none(17)) -shandlers['second']=specials(2147483647,second.from_time(time.max),-2147483647,second.from_time(time.min),-2147483648,q_none(18)) + + @classmethod + def from_int(cls, x): + return cls(x / 3600, (x / 60) % 60, x % 60) + + @classmethod + def from_time(cls, x): + return cls(x.hour, x.minute, x.second) + + def __int__(self): + return (self.hour * 3600 + self.minute * 60 + self.second) + +shandlers = {} +shandlers['short'] = specials(32767, 32767, -32767, -32767, -32768, q_none(5)) +shandlers['int'] = specials( + 2147483647, 2147483647, -2147483647, -2147483647, -2147483648, q_none(6)) +shandlers['long'] = specials(9223372036854775807, 9223372036854775807, - + 9223372036854775807, -9223372036854775807, -9223372036854775808, q_none(7)) +shandlers['date'] = specials( + 2147483647, date.max, -2147483647, date.min, -2147483648, q_none(14)) +shandlers['month'] = specials(2147483647, month.from_date( + date.max), -2147483647, month.from_date(date.min), -2147483648, q_none(13)) +shandlers['datetime'] = specials( + float('inf'), datetime.max, float('-inf'), datetime.min, float('nan'), q_none(15)) +shandlers['time'] = specials( + 2147483647, time.max, -2147483647, time.min, -2147483648, q_none(19)) +shandlers['minute'] = specials(2147483647, minute.from_time( + time.max), -2147483647, minute.from_time(time.min), -2147483648, q_none(17)) +shandlers['second'] = specials(2147483647, second.from_time( + time.max), -2147483647, second.from_time(time.min), -2147483648, q_none(18)) + def read_time(val): - return time(val/_MILLISECONDS_PER_HOUR,(val/_MILLISECONDS_PER_MINUTE)%60,(val/1000)%60,microsecond=1000*(val%1000)) + return time(val / _MILLISECONDS_PER_HOUR, (val / _MILLISECONDS_PER_MINUTE) % 60, (val / 1000) % 60, microsecond=1000 * (val % 1000)) + def write_time(val): - return _MILLISECONDS_PER_HOUR*val.hour + _MILLISECONDS_PER_MINUTE*val.minute + 1000*val.second + val.microsecond/1000 + return _MILLISECONDS_PER_HOUR * val.hour + _MILLISECONDS_PER_MINUTE * val.minute + 1000 * val.second + val.microsecond / 1000 + def read_date(val): - return date.fromordinal(val + _Y2KDAYS) - + return date.fromordinal(val + _Y2KDAYS) + + def write_date(val): - return val.toordinal() - _Y2KDAYS + return val.toordinal() - _Y2KDAYS + def read_datetime(val): - return timedelta(milliseconds=val*_MILLISECONDS_PER_DAY) + _Y2KDATETIME + return timedelta(milliseconds=val * _MILLISECONDS_PER_DAY) + _Y2KDATETIME + def write_datetime(val): - delta = val - _Y2KDATETIME - return delta.days + (delta.seconds / _SECONDS_PER_DAY) + (delta.microseconds / _MICROSECONDS_PER_DAY) + delta = val - _Y2KDATETIME + return delta.days + (delta.seconds / _SECONDS_PER_DAY) + (delta.microseconds / _MICROSECONDS_PER_DAY) # End Time Translation Stuff -def read_symbol(endianness,offset,bytes): - end = bytes.find("\0",offset) - return (bytes[offset:end],end+1) -def write_symbol(val,message): - message.fromstring(val + struct.pack('b',0)) - return message +def read_symbol(endianness, offset, bytes): + end = bytes.find("\0", offset) + return (bytes[offset:end], end + 1) + + +def write_symbol(val, message): + message.fromstring(val + struct.pack('b', 0)) + return message + class q_str(str): - def __new__(cls,s,is_char=False): - if is_char: s = s[0] - s=super(q_str,cls).__new__(cls,s) - s.is_char=is_char - return s + + def __new__(cls, s, is_char=False): + if is_char: + s = s[0] + s = super(q_str, cls).__new__(cls, s) + s.is_char = is_char + return s + class TranslateType(object): - def __init__(self,type=type(None),code=-128,format='x',offset=1,additional_read=None,additional_write=None,overwrite_read=None,overwrite_write=None): - self.type=type - if code > 0 and code < 20: - self.code=-code - else: - self.code=code - self.list_code=code - self.format=format - self.offset=offset - self.additional_read=additional_read - self.additional_write=additional_write - self.overwrite_read=overwrite_read - self.overwrite_write=overwrite_write - - def read_data(self,endianness,offset,bytes): - if self.overwrite_read: - return self.overwrite_read(endianness,offset,bytes) - else: - val = struct.unpack(endianness(self.format),bytes[offset:offset+self.offset])[0] - if self.additional_read: - val = self.additional_read(val) - return (val,offset+self.offset) - - def write_data(self,val,message=None): - if message is None: message = array.array('b') - if self.overwrite_write: - return self.overwrite_write(val,message) - else: - if self.additional_write: - val = self.additional_write(val) - message.fromstring(struct.pack('>'+self.format,val)) - return message + + def __init__(self, type=type(None), code=-128, format='x', offset=1, additional_read=None, additional_write=None, overwrite_read=None, overwrite_write=None): + self.type = type + if code > 0 and code < 20: + self.code = -code + else: + self.code = code + self.list_code = code + self.format = format + self.offset = offset + self.additional_read = additional_read + self.additional_write = additional_write + self.overwrite_read = overwrite_read + self.overwrite_write = overwrite_write + + def read_data(self, endianness, offset, bytes): + if self.overwrite_read: + return self.overwrite_read(endianness, offset, bytes) + else: + val = struct.unpack(endianness(self.format), + bytes[offset:offset + self.offset])[0] + if self.additional_read: + val = self.additional_read(val) + return (val, offset + self.offset) + + def write_data(self, val, message=None): + if message is None: + message = array.array('b') + if self.overwrite_write: + return self.overwrite_write(val, message) + else: + if self.additional_write: + val = self.additional_write(val) + message.fromstring(struct.pack('>' + self.format, val)) + return message types = {} -types['bool'] = TranslateType(bool,1,'b',1) -types['byte'] = TranslateType(code=4,format='b',offset=1) -types['int'] = TranslateType(int,6,'i',4,additional_read=shandlers['int'].read(lambda x:x),additional_write=shandlers['int'].write(lambda x:x)) -types['short'] = TranslateType(code=5,format='h',offset=2,additional_read=shandlers['short'].read(lambda x:x),additional_write=shandlers['short'].write(lambda x:x)) -types['float'] = TranslateType(float,9,'d',8) -types['real'] = TranslateType(code=8,format='f',offset=4) -types['long'] = TranslateType(long,7,'q',8,additional_read=shandlers['long'].read(lambda x:x),additional_write=shandlers['long'].write(lambda x:x)) -types['char'] = TranslateType(q_str,10,'c',1,additional_read=lambda x: q_str(x,True)) -types['symbol'] = TranslateType(str,11,'b',None,overwrite_read=read_symbol,overwrite_write = write_symbol) -types['month'] = TranslateType(month,13,'i',4,additional_write=shandlers['month'].write(int),additional_read=shandlers['month'].read(month.from_int)) -types['date'] = TranslateType(date,14,'i',4,additional_write=shandlers['date'].write(write_date),additional_read=shandlers['date'].read(read_date)) -types['datetime'] = TranslateType(datetime,15,'d',8,additional_write=shandlers['datetime'].write(write_datetime),additional_read=shandlers['datetime'].read(read_datetime)) -types['minute'] = TranslateType(minute,17,'i',4,additional_write=shandlers['minute'].write(int),additional_read=shandlers['minute'].read(minute.from_int)) -types['second'] = TranslateType(second,18,'i',4,additional_write=shandlers['second'].write(int),additional_read=shandlers['second'].read(second.from_int)) -types['time'] = TranslateType(time,19,'i',4,additional_write=shandlers['time'].write(write_time),additional_read=shandlers['time'].read(read_time)) +types['bool'] = TranslateType(bool, 1, 'b', 1) +types['byte'] = TranslateType(code=4, format='b', offset=1) +types['int'] = TranslateType(int, 6, 'i', 4, additional_read=shandlers['int'].read( + lambda x: x), additional_write=shandlers['int'].write(lambda x: x)) +types['short'] = TranslateType(code=5, format='h', offset=2, additional_read=shandlers[ + 'short'].read(lambda x: x), additional_write=shandlers['short'].write(lambda x: x)) +types['float'] = TranslateType(float, 9, 'd', 8) +types['real'] = TranslateType(code=8, format='f', offset=4) +types['long'] = TranslateType(long, 7, 'q', 8, additional_read=shandlers['long'].read( + lambda x: x), additional_write=shandlers['long'].write(lambda x: x)) +types['char'] = TranslateType( + q_str, 10, 'c', 1, additional_read=lambda x: q_str(x, True)) +types['symbol'] = TranslateType( + str, 11, 'b', None, overwrite_read=read_symbol, overwrite_write=write_symbol) +types['month'] = TranslateType(month, 13, 'i', 4, additional_write=shandlers['month'].write( + int), additional_read=shandlers['month'].read(month.from_int)) +types['date'] = TranslateType(date, 14, 'i', 4, additional_write=shandlers['date'].write( + write_date), additional_read=shandlers['date'].read(read_date)) +types['datetime'] = TranslateType(datetime, 15, 'd', 8, additional_write=shandlers['datetime'].write( + write_datetime), additional_read=shandlers['datetime'].read(read_datetime)) +types['minute'] = TranslateType(minute, 17, 'i', 4, additional_write=shandlers[ + 'minute'].write(int), additional_read=shandlers['minute'].read(minute.from_int)) +types['second'] = TranslateType(second, 18, 'i', 4, additional_write=shandlers[ + 'second'].write(int), additional_read=shandlers['second'].read(second.from_int)) +types['time'] = TranslateType(time, 19, 'i', 4, additional_write=shandlers['time'].write( + write_time), additional_read=shandlers['time'].read(read_time)) From 9e41cb41bcd584fb737f95314ca9c2894772672a Mon Sep 17 00:00:00 2001 From: Alex Price Date: Wed, 23 Apr 2014 12:13:58 +0100 Subject: [PATCH 2/2] Added git ignore file --- .gitignore | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6106029 --- /dev/null +++ b/.gitignore @@ -0,0 +1,57 @@ +.DS_store +*.sw[op] + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +bin/ +build/ +develop-eggs/ +dist/ +eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.cache +nosetests.xml +coverage.xml + +# Translations +*.mo + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# Rope +.ropeproject + +# Django stuff: +*.log +*.pot + +# Sphinx documentation +docs/_build/ +