def __setitem__(self, key, value): """ Sets given value for given primary key in the database. Additional types conversion is only done if the value is a dictionary. """ if isinstance(value, dict): # check if there are no keys that would become empty strings if not all(unicode(k) for k in value): raise KeyError('Empty keys are not allowed (%s).' % repr(value)) # EXPLAIN why the 'from_python' conversion is necessary, as there # is no straight forward way of restoring the python objects. What # about limiting the allowed keys and values to string only, an # raise exception on any other object type? flat = list(itertools.chain(*((k, utils.from_python(v)) for k,v in value.iteritems()))) args = [key] + flat self.proto.misc('put', args) # EXPLAIN why is this hack necessary? else: if isinstance(value, (list, tuple)): assert self.separator, "Separator is not set" prepared_value = self.separator.join(value) else: prepared_value = value self.proto.put(key, prepared_value)
def prepare(self): """ Returns search-ready triple: column name, operator code, expression. """ if not self.lookup in self.LOOKUP_DEFINITIONS: available_lookups = ', '.join(str(x) for x in self.LOOKUP_DEFINITIONS) raise NameError('Unknown lookup "%s". Available are: %s' % (self.lookup, available_lookups)) definitions = self.LOOKUP_DEFINITIONS[self.lookup] for definition in definitions: if definition.accepts(self.expr): try: value = definition.validate(self.expr) except ValueError, e: raise ValueError(u'Bad lookup %s__%s=%s: %s' % ( self.name, self.lookup, (self.expr if hasattr(self.expr,'__iter__') else u'"%s"'%self.expr), unicode(e))) op = definition.operator # deal with negation: it can be external ("exclude(...)") or # internal ("foo__exists=False") negate = self.negate if definition.has_custom_value: if isinstance(value, bool) and not value: # if the value is substituted and only provided to define # the expected result of a test (yes/no), we must modify # our internal negation state according to the value negate = not negate value = definition.value else: value = definition.process_value(value) if negate: op = op | TyrantProtocol.RDBQCNEGATE # boolean values are stored as integers value = utils.from_python(value) # flatten list (TC can search tokens) if hasattr(value, '__iter__'): value = ', '.join(unicode(x) for x in value) return self.name, op, value