Ejemplo n.º 1
0
 def __CastKey(self, values):
   """Cast input values to Key() class using encoded string or tuple list."""
   if not len(values) % 2:
     return datastore_types.Key.from_path(_app=self.__app, *values)
   elif len(values) == 1 and isinstance(values[0], basestring):
     return datastore_types.Key(values[0])
   else:
     self.__CastError('KEY', values,
                      'requires an even number of operands '
                      'or a single encoded string')
Ejemplo n.º 2
0
def GetOrInsert(key, kindName=None, parent=None, **kwargs):
    """
		Either creates a new entity with the given key, or returns the existing one.

		Its guaranteed that there is no race-condition here; it will never overwrite an
		previously created entity. Extra keyword arguments passed to this function will be
		used to populate the entity if it has to be created; otherwise they are ignored.

		:param key: The key which will be fetched or created. \
		If key is a string, it will be used as the name for the new entity, therefore the \
		collectionName is required in this case.
		:type key: server.db.Key | String
		:param kindName: The data kind to use for that entity. Ignored if key is a db.Key.
		:type kindName: str

		:param parent: The parent entity of the entity.
		:type parent: db.Key or None

		:returns: Returns the wanted Entity.
		:rtype: server.db.Entity
	"""
    def txn(key, kwargs):
        try:
            res = datastore.Get(key)
        except datastore_errors.EntityNotFoundError:
            res = Entity(kind=key.kind(),
                         parent=key.parent(),
                         name=key.name(),
                         id=key.id())
            for k, v in kwargs.items():
                res[k] = v
            datastore.Put(res)
        return (res)

    if not isinstance(key, datastore_types.Key):
        try:
            key = datastore_types.Key(encoded=key)
        except:
            assert kindName
            key = datastore_types.Key.from_path(kindName, key, parent=parent)
    if datastore.IsInTransaction():
        return txn(key, kwargs)

    return datastore.RunInTransaction(txn, key, kwargs)
Ejemplo n.º 3
0
def decodeStringKey(value):
    # first try to decode the whole string as one key
    try:
        key = datastore_types.Key(value)
        return encode(key)
    except BadKeyError as e:
        # check for the case of two keys split by a '_'
        if re.search('^' + key_regex + '_' + key_regex + '$', value):
            keys = value.split('_ah')
            return encode(keys[0]) + '_' + encode('ah' + keys[1])
        # check for the case of one key and one string split by a '_'
        if re.search('^' + key_regex + '_[^\s]+$', value):
            strings = value.split('_')
            # one key and one string
            if len(strings) == 2:
                return encode(strings[0]) + '_' + encode(strings[1])
            # one key (which includes a '_') and one string
            elif len(strings) == 3:
                return encode('_'.join(strings[0:2])) + '_' + encode(
                    strings[2])
        raise Exception('bad key string: ' + str(value), e)
Ejemplo n.º 4
0
    def mergeExternalFilter(self, filters):
        """
			Safely merges filters according to the data model.

			Its only valid to call this function if the query has been created using
			:func:`server.skeleton.Skeleton.all`.

			Its safe to pass filters received from an external source (a user);
			unknown/invalid filters will be ignored, so the query-object is kept in a
			valid state even when processing malformed data.

			If complex queries are needed (e.g. filter by relations), this function
			shall also be used.

			See also :func:`server.db.Query.filter` for simple filters.

			:param filters: A dictionary of attributes and filter pairs.
			:type filters: dict

			:returns: Returns the query itself for chaining.
			:rtype: server.db.Query
		"""
        from server.bones import baseBone, relationalBone
        if "id" in filters:
            self.datastoreQuery = None
            logging.error(
                "Filtering by id is no longer supported. Use key instead.")
            return self
        if self.srcSkel is None:
            raise NotImplementedError(
                "This query has not been created using skel.all()")
        if self.datastoreQuery is None:  #This query is allready unsatifiable and adding more constrains to this wont change this
            return (self)
        skel = self.srcSkel
        if skel.searchIndex and "search" in filters:  #We perform a Search via Google API - all other parameters are ignored
            try:
                searchRes = search.Index(name=skel.searchIndex).search(
                    query=search.Query(query_string=filters["search"],
                                       options=search.QueryOptions(limit=25)))
            except search.QueryError:  #We cant parse the query, treat it as verbatim
                qstr = u"\"%s\"" % filters["search"].replace(u"\"", u"")
                try:
                    searchRes = search.Index(name=skel.searchIndex).search(
                        query=search.Query(query_string=qstr,
                                           options=search.QueryOptions(
                                               limit=25)))
                except search.QueryError:  # Still cant parse it
                    searchRes = []
            tmpRes = [
                datastore_types.Key(encoded=x.doc_id[2:]) for x in searchRes
            ]
            if tmpRes:
                filters = []
                for x in tmpRes:
                    filters.append(
                        datastore.Query(
                            self.getKind(),
                            {"%s =" % datastore_types.KEY_SPECIAL_PROPERTY: x
                             }))
                self.datastoreQuery = datastore.MultiQuery(filters, ())
            else:
                self.datastoreQuery = None
            return (self)
        #bones = [ (getattr( skel, key ), key) for key in dir( skel ) if not "__" in key and isinstance( getattr( skel, key ) , baseBone ) ]
        bones = [(y, x) for x, y in skel.items()]
        try:
            #First, filter non-relational bones
            for bone, key in [
                    x for x in bones if not isinstance(x[0], relationalBone)
            ]:
                bone.buildDBFilter(key, skel, self, filters)
            #Second, process orderings of non-relational bones
            for bone, key in [
                    x for x in bones if not isinstance(x[0], relationalBone)
            ]:
                bone.buildDBSort(key, skel, self, filters)
            #Now filter relational bones
            for bone, key in [
                    x for x in bones if isinstance(x[0], relationalBone)
            ]:
                bone.buildDBFilter(key, skel, self, filters)
            #finally process orderings of relational bones
            for bone, key in [
                    x for x in bones if isinstance(x[0], relationalBone)
            ]:
                bone.buildDBSort(key, skel, self, filters)
        except RuntimeError as e:
            logging.exception(e)
            self.datastoreQuery = None
            return (self)
        if "search" in filters and filters["search"]:
            if isinstance(filters["search"], list):
                taglist = [
                    "".join([
                        y for y in unicode(x).lower()
                        if y in conf["viur.searchValidChars"]
                    ]) for x in filters["search"]
                ]
            else:
                taglist = [
                    "".join([
                        y for y in unicode(x).lower()
                        if y in conf["viur.searchValidChars"]
                    ]) for x in unicode(filters["search"]).split(" ")
                ]
            assert not isinstance(
                self.datastoreQuery, datastore.MultiQuery
            ), "Searching using viur-tags is not possible on a query that already uses an IN-filter!"
            origFilter = self.datastoreQuery
            queries = []
            for tag in taglist[:30]:  #Limit to max 30 keywords
                q = datastore.Query(kind=origFilter.__kind)
                q["viur_tags"] = tag
                queries.append(q)
            self.datastoreQuery = datastore.MultiQuery(queries,
                                                       origFilter.__orderings)
            for k, v in origFilter.items():
                self.datastoreQuery[k] = v
        if "cursor" in filters and filters[
                "cursor"] and filters["cursor"].lower() != "none":
            self.cursor(filters["cursor"])
        if "amount" in filters and str(filters["amount"]).isdigit() and int(
                filters["amount"]) > 0 and int(filters["amount"]) <= 100:
            self.limit(int(filters["amount"]))
        if "postProcessSearchFilter" in dir(skel):
            skel.postProcessSearchFilter(self, filters)
        return (self)
 def parse(self, value):
     return datastore_types.Key(value)
Ejemplo n.º 6
0
 def to_old_key(self):
     return datastore_types.Key(encoded=self.urlsafe())