예제 #1
0
def preprocessJsonObject(o):
    """
		Add support for Keys, Datetime, Bytes and db.Entities in deferred tasks.
		This is not a subclass of json.JSONEncoder anymore, as db.Entites are a subclass of dict, which
		is always handled from the json module itself.
	"""
    if isinstance(o, db.KeyClass):
        return {".__key__": db.encodeKey(o)}
    elif isinstance(o, datetime):
        return {
            ".__datetime__":
            o.astimezone(pytz.UTC).strftime("d.%m.%Y %H:%M:%S")
        }
    elif isinstance(o, bytes):
        return {".__bytes__": base64.b64encode(o).decode("ASCII")}
    elif isinstance(o, db.Entity):
        return {
            ".__entity__": preprocessJsonObject(dict(o)),
            ".__ekey__": db.encodeKey(o.key) if o.key else None
        }
    elif isinstance(o, dict):
        return {
            preprocessJsonObject(k): preprocessJsonObject(v)
            for k, v in o.items()
        }
    elif isinstance(o, (list, tuple, set)):
        return [preprocessJsonObject(x) for x in o]
    else:
        return o
예제 #2
0
	def default(self, o: Any) -> Any:
		if isinstance(o, translate):
			return str(o)
		elif isinstance(o, datetime):
			return o.isoformat()
		elif isinstance(o, db.Key):
			return db.encodeKey(o)
		return json.JSONEncoder.default(self, o)
예제 #3
0
 def default(self, o: Any) -> Any:
     if isinstance(o, db.KeyClass):
         return {".__key__": db.encodeKey(o)}
     elif isinstance(o, datetime):
         return {
             ".__datetime__":
             o.astimezone(pytz.UTC).strftime("d.%m.%Y %H:%M:%S")
         }
     elif isinstance(o, bytes):
         return {".__bytes__": base64.b64encode(o).decode("ASCII")}
     return json.JSONEncoder.default(self, o)
예제 #4
0
    def renderSingleBoneValue(self, value, bone, skel, key):
        """
		Renders the value of a bone.

		This function is used by :func:`collectSkelData`.
		It can be overridden and super-called from a custom renderer.

		:param bone: The bone which value should be rendered.
		:type bone: Any bone that inherits from :class:`server.bones.base.baseBone`.

		:return: A dict containing the rendered attributes.
		:rtype: dict
		"""
        if bone.type == "date" or bone.type.startswith("date."):
            if value:
                if bone.date and bone.time:
                    return value.strftime("%d.%m.%Y %H:%M:%S")
                elif bone.date:
                    return value.strftime("%d.%m.%Y")

                return value.strftime("%H:%M:%S")
        elif isinstance(bone, bones.relationalBone):
            if isinstance(value, dict):
                return {
                    "dest":
                    self.renderSkelValues(value["dest"],
                                          injectDownloadURL=isinstance(
                                              bone, bones.fileBone)),
                    "rel":
                    self.renderSkelValues(value["rel"],
                                          injectDownloadURL=isinstance(
                                              bone, bones.fileBone))
                    if value["rel"] else None,
                }
        elif isinstance(bone, bones.recordBone):
            return self.renderSkelValues(value)
        elif isinstance(bone, bones.keyBone):
            return db.encodeKey(value) if value else None
        else:
            return value
        return None
예제 #5
0
    def initializeUpload(self,
                         fileName: str,
                         mimeType: str,
                         node: Union[str, None],
                         size: Union[int, None] = None) -> Tuple[str, str]:
        """
		Internal helper that registers a new upload. Will create the pending fileSkel entry (needed to remove any
		started uploads from GCS if that file isn't used) and creates a resumable (and signed) uploadURL for that.
		:param fileName: Name of the file that will be uploaded
		:param mimeType: Mimetype of said file
		:param node: If set (to a string-key representation of a file-node) the upload will be written to this directory
		:param size: The *exact* filesize we're accepting in Bytes. Used to enforce a filesize limit by getUploadURL
		:return: Str-Key of the new file-leaf entry, the signed upload-url
		"""
        global bucket
        fileName = sanitizeFileName(fileName)
        targetKey = utils.generateRandomString()
        blob = bucket.blob("%s/source/%s" % (targetKey, fileName))
        uploadUrl = blob.create_resumable_upload_session(content_type=mimeType,
                                                         size=size,
                                                         timeout=60)
        # Create a corresponding file-lock object early, otherwise we would have to ensure that the file-lock object
        # the user creates matches the file he had uploaded
        fileSkel = self.addSkel("leaf")
        fileSkel["name"] = "pending"
        fileSkel["size"] = 0
        fileSkel["mimetype"] = "application/octetstream"
        fileSkel["dlkey"] = targetKey
        fileSkel["parentdir"] = None
        fileSkel["pendingparententry"] = db.keyHelper(
            node,
            self.addSkel("node").kindName) if node else None
        fileSkel["pending"] = True
        fileSkel["weak"] = True
        fileSkel["width"] = 0
        fileSkel["height"] = 0
        fileSkel.toDB()
        # Mark that entry dirty as we might never receive an add
        utils.markFileForDeletion(targetKey)
        return db.encodeKey(fileSkel["key"]), uploadUrl
예제 #6
0
    def renderBoneValue(self,
                        bone,
                        skel,
                        key,
                        boneValue,
                        isLanguageWrapped: bool = False):
        """
		Renders the value of a bone.

		This function is used by :func:`collectSkelData`.
		It can be overridden and super-called from a custom renderer.

		:param bone: The bone which value should be rendered.
		:type bone: Any bone that inherits from :class:`server.bones.base.baseBone`.

		:return: A dict containing the rendered attributes.
		:rtype: dict
		"""
        if bone.languages and not isLanguageWrapped:
            res = LanguageWrapper(bone.languages)
            if isinstance(boneValue, dict):
                for language in bone.languages:
                    if language in boneValue:
                        res[language] = self.renderBoneValue(
                            bone, skel, key, boneValue[language], True)
            return res
        elif bone.type == "select" or bone.type.startswith("select."):
            skelValue = boneValue
            if isinstance(skelValue, list):
                return {val: bone.values.get(val, val) for val in boneValue}
            elif skelValue in bone.values:
                return KeyValueWrapper(skelValue, bone.values[skelValue])
            return KeyValueWrapper(skelValue, str(skelValue))

        elif bone.type == "relational" or bone.type.startswith("relational."):
            if isinstance(boneValue, list):
                tmpList = []
                for k in boneValue:
                    if not k:
                        continue
                    if bone.using is not None and k["rel"]:
                        k["rel"].renderPreparation = self.renderBoneValue
                        usingData = k["rel"]
                    else:
                        usingData = None
                    k["dest"].renderPreparation = self.renderBoneValue
                    tmpList.append({"dest": k["dest"], "rel": usingData})
                return tmpList
            elif isinstance(boneValue, dict):
                if bone.using is not None and boneValue["rel"]:
                    boneValue["rel"].renderPreparation = self.renderBoneValue
                    usingData = boneValue["rel"]
                else:
                    usingData = None
                boneValue["dest"].renderPreparation = self.renderBoneValue
                return {"dest": boneValue["dest"], "rel": usingData}
        elif bone.type == "record" or bone.type.startswith("record."):
            value = boneValue
            if value:
                if bone.multiple:
                    ret = []
                    for entry in value:
                        entry.renderPreparation = self.renderBoneValue
                        ret.append(entry)
                    return ret
                value.renderPreparation = self.renderBoneValue
                return value
        elif bone.type == "password":
            return ""
        elif bone.type == "key":
            return db.encodeKey(boneValue) if boneValue else None

        else:
            return boneValue

        return None
예제 #7
0
 def listRootNodes(self, rootNodes, tpl=None, params=None):
     for rn in rootNodes:
         rn["key"] = db.encodeKey(rn["key"])
     return json.dumps(rootNodes)
예제 #8
0
    def renderBoneValue(self, bone, skel, key, boneValue):
        """
		Renders the value of a bone.

		This function is used by :func:`collectSkelData`.
		It can be overridden and super-called from a custom renderer.

		:param bone: The bone which value should be rendered.
		:type bone: Any bone that inherits from :class:`server.bones.base.baseBone`.

		:return: A dict containing the rendered attributes.
		:rtype: dict
		"""
        if bone.type == "select" or bone.type.startswith("select."):
            skelValue = boneValue
            if isinstance(skelValue, list):
                return {val: bone.values.get(val, val) for val in boneValue}
            elif skelValue in bone.values:
                return KeyValueWrapper(skelValue, bone.values[skelValue])
            return KeyValueWrapper(skelValue, str(skelValue))
        elif bone.type == "relational" or bone.type.startswith("relational."):
            if isinstance(boneValue, list):
                tmpList = []
                for k in boneValue:
                    if bone.using is None:
                        tmpList.append(self.collectSkelData(k["dest"]))
                    else:
                        #usingSkel = bone._usingSkelCache
                        if k["rel"]:
                            usingData = self.collectSkelData(k["rel"])
                        else:
                            usingData = None
                        tmpList.append({
                            "dest": self.collectSkelData(k["dest"]),
                            "rel": usingData
                        })
                return tmpList
            elif isinstance(boneValue, dict):
                if bone.using is None:
                    return self.collectSkelData(boneValue["dest"])
                else:
                    #usingSkel = bone._usingSkelCache
                    if boneValue["rel"]:
                        usingData = self.collectSkelData(boneValue["rel"])
                    else:
                        usingData = None

                    return {
                        "dest": self.collectSkelData(boneValue["dest"]),
                        "rel": usingData
                    }
        elif bone.type == "record" or bone.type.startswith("record."):
            value = boneValue
            if value:
                ret = []
                for entry in value:
                    ret.append(self.collectSkelData(entry))
                return ret
        elif bone.type == "key":
            return db.encodeKey(boneValue) if boneValue else None
        else:
            return boneValue
        return None