def convert(self, instance=None, value=None, insert=False, update=False): '''Converts the basic type with the str operation, which we can do an eval() on.''' from homer.core.types import blob value = self.validate(value) if update and not insert: assert isinstance(instance, Model), "We only accept Model instances for inserts or updates" value = quote(value) properties = fields(instance, CqlProperty) key = properties.get("id") if "id" in properties else instance.default[0] id = key.convert(instance, instance.id) arguments = {"name":self.name, "value":value, "keyspace":instance.keyspace, "kind":instance.kind(), "id":id} q = "UPDATE {keyspace}.{kind} {ttl} SET {name}={value} WHERE id={id}" if self.expire: query = q.format(ttl="USING TTL %s" % self.expire, **arguments) else: query = q.format(ttl="", **arguments) return query else: if isinstance(value, basestring): return quote(value) if isinstance(value, bool): value = quote("true") if value else quote("false") return value if isinstance(value, blob): return repr(value) val = self.type(value) return str(val)
def convert(self, instance, value, insert=False, update=False): '''References are stored as serialized Key objects in the datastore''' assert isinstance(value, Model), "You can only use the Reference descriptor with Models" value = self.validate(value) properties = fields(value, CqlProperty) key = properties.get("id") if "id" in properties else value.default[0] id = key.convert(value, value.id) pointer = { "keyspace" : value.keyspace, "kind" : value.kind(), "id" : id } value = yaml.dump(pointer) #Serialize it with YAML and then quote it. value = quote(value) if update and not insert: arguments = { "name":self.name, "value":value, "id":id, "keyspace":instance.keyspace, "kind":instance.kind(), } q = "UPDATE {keyspace}.{kind} {ttl} SET {name}={value} WHERE id={id}" if self.expire: query = q.format(ttl="USING TTL %s" % self.expire, **arguments) else: query = q.format(ttl="", **arguments) return query else: return value
def convert(self, instance, value, insert=False, update=False): '''Yields the datastore representation of its value''' value = self.validate(value) value = repr(value) value = quote(value) if update and not insert: assert isinstance(instance, Model), "We only accept Model instances for inserts or updates" properties = fields(instance, CqlProperty) key = properties.get("id") if "id" in properties else instance.default[0] id = key.convert(instance, instance.id) arguments = {"name":self.name, "value":value, "keyspace":instance.keyspace, "kind":instance.kind(), "id":id} q = "UPDATE {keyspace}.{kind} {ttl} SET {name}={value} WHERE id={id}" if self.expire: query = q.format(ttl="USING TTL %s" % self.expire, **arguments) else: query = q.format(ttl="", **arguments) return query else: return value
def create(self): '''Creates the Keyspace and Model for self.keyspace and Model''' from homer.core.models import CqlProperty if Schema.contains(self.model): print("{model} has already been created before".format(model=self.model)) return # MAKE THE KEYSPACE q = """CREATE KEYSPACE IF NOT EXISTS {keyspace} WITH REPLICATION = {replication} AND DURABLE_WRITES = {durable};""" config = settings() replication = config.get("strategy", None) durable = config.get("durable", True) if not replication: raise ConfigurationError("No replication strategy specified.") replication = '{' + ', '.join([quote(k) + ':' + quote(v) for k,v in replication.items()]) + '}' print("GOT REPLICATION CONFIGURATION: " + replication) keyspace = self.model.keyspace durable = str(durable).lower() q = q.format(keyspace=keyspace, replication=replication, durable=durable) try: print("Creating keyspace: {0}".format(q)) CqlQuery(query=q).execute() except Exception as e: logging.exception(e) # raise e # FIND ALL THE CQLPROPERTY DESCRIPTORS FROM THIS MODEL. properties = fields(self.model, CqlProperty) # BUILD THE CQL3 QUERY FOR MAKING THE TABLE. id, type = False, None columns = [] keys = [] for name, property in properties.items(): if name == "id": id = True type = property.ctype else: fragment = "{0} {1}".format(name, property.ctype) columns.append(fragment) if property.key: keys.append(name) # CONSTRUCT THE QUERY STRING FOR CREATING TABLES. q = """ CREATE TABLE IF NOT EXISTS {keyspace}.{kind} ( {key} {columns} {keys} ); """ assert id, "Every Model must have an id property" if keys: keys = sorted(keys) keys.insert(0, "id") columns.append("{0} {1}".format("id", type)) keys = ", PRIMARY KEY(" + ",".join(keys) + ")" key = "" else: keys = "" key = "id {type} PRIMARY KEY,".format(type=type) values = {"columns" : ",".join(sorted(columns))} values["key"] = key values["keys"] = keys values["kind"] = self.model.kind() values["keyspace"] = self.model.keyspace values["type"] = type query = q.format(**values) try: print("Creating Table for Model with Query: " + query) CqlQuery(query=query).execute() except Exception as e: logging.exception(e) raise e # BUILD INDEXES, FOR EACH INDEXABLE PROPERTY. q = "CREATE INDEX IF NOT EXISTS {name} ON {keyspace}.{kind}({name});" for name, property in properties.items(): if name == "id": continue if property.indexed() and not property.key: query = q.format(name=name, keyspace=self.model.keyspace, kind=self.model.kind()) try: CqlQuery(query=query).execute() except Exception as e: logging.exception(e) raise e # If everything goes well, mark this model as created by adding it to the global schema cache. Schema.add(self.model)