Skip to content

Commit

Permalink
Merge branch 'main' into feat-Tree.dump
Browse files Browse the repository at this point in the history
  • Loading branch information
phorward authored Jan 23, 2025
2 parents a77c997 + 91ba86a commit a9708f3
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 43 deletions.
8 changes: 5 additions & 3 deletions src/viur/core/bones/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1299,7 +1299,7 @@ def setBoneValue(self,
the value is valid. If the value is invalid, no modification occurs. The function supports appending values to
bones with multiple=True and setting or appending language-specific values for bones that support languages.
"""
assert not (bool(self.languages) ^ bool(language)), "Language is required or not supported"
assert not (bool(self.languages) ^ bool(language)), f"language is required or not supported on {boneName!r}"
assert not append or self.multiple, "Can't append - bone is not multiple"

if not append and self.multiple:
Expand Down Expand Up @@ -1447,14 +1447,14 @@ def structure(self) -> dict:
ret = {
"descr": self.descr,
"type": self.type,
"required": self.required,
"required": self.required and not self.readOnly,
"params": self.params,
"visible": self.visible,
"readonly": self.readOnly,
"unique": self.unique.method.value if self.unique else False,
"languages": self.languages,
"emptyvalue": self.getEmptyValue(),
"indexed": self.indexed
"indexed": self.indexed,
}

# Provide a defaultvalue, if it's not a function.
Expand All @@ -1470,6 +1470,8 @@ def structure(self) -> dict:
}
else:
ret["multiple"] = self.multiple

# Provide compute information
if self.compute:
ret["compute"] = {
"method": self.compute.interval.method.name
Expand Down
75 changes: 39 additions & 36 deletions src/viur/core/modules/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,31 @@ class FileLeafSkel(TreeSkel):
}
)

@classmethod
def _inject_serving_url(cls, skel: SkeletonInstance) -> None:
"""Inject the serving url for public image files into a FileSkel"""
if (
skel["public"]
and skel["mimetype"]
and skel["mimetype"].startswith("image/")
and not skel["serving_url"]
):
bucket = File.get_bucket(skel["dlkey"])
filename = f"/gs/{bucket.name}/{skel['dlkey']}/source/{skel['name']}"

# Trying this on local development server will raise a
# `google.appengine.runtime.apiproxy_errors.RPCFailedError`
if conf.instance.is_dev_server:
logging.warning(f"Can't inject serving_url for {filename!r} on local development server")
return

try:
skel["serving_url"] = images.get_serving_url(None, secure_url=True, filename=filename)

except Exception as e:
logging.warning(f"Failed to create serving_url for {filename!r} with exception {e!r}")
logging.exception(e)

def preProcessBlobLocks(self, locks):
"""
Ensure that our dlkey is locked even if we don't have a filebone here
Expand All @@ -401,16 +426,21 @@ def preProcessBlobLocks(self, locks):
return locks

@classmethod
def refresh(cls, skelValues):
super().refresh(skelValues)
def refresh(cls, skel):
super().refresh(skel)
if conf.viur2import_blobsource:
importData = importBlobFromViur2(skelValues["dlkey"], skelValues["name"])
importData = importBlobFromViur2(skel["dlkey"], skel["name"])
if importData:
if not skelValues["downloadUrl"]:
skelValues["downloadUrl"] = importData
skelValues["pendingparententry"] = None
if not skel["downloadUrl"]:
skel["downloadUrl"] = importData
skel["pendingparententry"] = None

conf.main_app.file.inject_serving_url(skelValues)
cls._inject_serving_url(skel)

@classmethod
def write(cls, skel, **kwargs):
cls._inject_serving_url(skel)
return super().write(skel, **kwargs)


class FileNodeSkel(TreeSkel):
Expand Down Expand Up @@ -524,7 +554,7 @@ def create_internal_serving_url(
This is needed to hide requests to Google as they are internally be routed, and can be the result of a
legal requirement like GDPR.
:param serving_url: Is the original serving URL as generated from inject_serving_url()
:param serving_url: Is the original serving URL as generated from FileLeafSkel._inject_serving_url()
:param size: Optional size setting
:param filename: Optonal filename setting
:param options: Additional options parameter-pass through to /file/serve
Expand Down Expand Up @@ -734,6 +764,7 @@ def write(
:param public: True if the file should be publicly accessible.
:return: Returns the key of the file object written. This can be associated e.g. with a FileBone.
"""
# logging.info(f"{filename=} {mimetype=} {width=} {height=} {public=}")
if not File.is_valid_filename(filename):
raise ValueError(f"{filename=} is invalid")

Expand Down Expand Up @@ -1167,8 +1198,6 @@ def add(self, skelType: SkelType, node: db.Key | int | str | None = None, *args,
skel["weak"] = rootNode is None
skel["crc32c_checksum"] = base64.b64decode(blob.crc32c).hex()
skel["md5_checksum"] = base64.b64decode(blob.md5_hash).hex()
self.inject_serving_url(skel)

skel.write()

# Add updated download-URL as the auto-generated isn't valid yet
Expand Down Expand Up @@ -1249,8 +1278,6 @@ def onEdit(self, skelType: SkelType, skel: SkeletonInstance):
bucket.copy_blob(old_blob, bucket, new_path, if_generation_match=0)
bucket.delete_blob(old_path)

self.inject_serving_url(skel)

def mark_for_deletion(self, dlkey: str) -> None:
"""
Adds a marker to the datastore that the file specified as *dlkey* can be deleted.
Expand All @@ -1273,30 +1300,6 @@ def mark_for_deletion(self, dlkey: str) -> None:

db.Put(fileObj)

def inject_serving_url(self, skel: SkeletonInstance) -> None:
"""Inject the serving url for public image files into a FileSkel"""
if (
skel["public"]
and skel["mimetype"]
and skel["mimetype"].startswith("image/")
and not skel["serving_url"]
):
bucket = File.get_bucket(skel["dlkey"])
filename = f"/gs/{bucket.name}/{skel['dlkey']}/source/{skel['name']}"

# Trying this on local development server will raise a
# `google.appengine.runtime.apiproxy_errors.RPCFailedError`
if conf.instance.is_dev_server:
logging.warning(f"Can't inject serving_url for {filename!r} on local development server")
return

try:
skel["serving_url"] = images.get_serving_url(None, secure_url=True, filename=filename)

except Exception as e:
logging.warning(f"Failed to create serving_url for {filename!r} with exception {e!r}")
logging.exception(e)


@PeriodicTask(interval=datetime.timedelta(hours=4))
def startCheckForUnreferencedBlobs():
Expand Down
4 changes: 4 additions & 0 deletions src/viur/core/prototypes/singleton.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ def editSkel(self, *args, **kwargs) -> SkeletonInstance:

## External exposed functions

@exposed
def index(self):
return self.view()

@exposed
@skey
def preview(self, *args, **kwargs) -> t.Any:
Expand Down
2 changes: 1 addition & 1 deletion src/viur/core/prototypes/skelmodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __load_indexes_from_file() -> dict[str, list]:
with open(os.path.join(conf.instance.project_base_path, "index.yaml"), "r") as file:
indexes = yaml.safe_load(file)
indexes = indexes.get("indexes", [])
for index in indexes:
for index in indexes or ():
index["properties"] = [_property["name"] for _property in index["properties"]]
indexes_dict.setdefault(index["kind"], []).append(index)

Expand Down
14 changes: 14 additions & 0 deletions src/viur/core/prototypes/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,20 @@ def pathToKey(self, key: db.Key):

## External exposed functions

@exposed
def index(self, skelType: SkelType = "node", parententry: t.Optional[db.Key | int | str] = None, **kwargs):
if not parententry:
repos = self.getAvailableRootNodes(**kwargs)
match len(repos):
case 0:
raise errors.Unauthorized()
case 1:
parententry = repos[0]["key"]
case _:
raise errors.NotAcceptable(f"Missing required parameter {'parententry'!r}")

return self.list(skelType=skelType, parententry=parententry, **kwargs)

@exposed
def listRootNodes(self, *args, **kwargs) -> t.Any:
"""
Expand Down
6 changes: 3 additions & 3 deletions src/viur/core/skeleton.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class MetaBaseSkel(type):
"clone",
"cursor",
"delete",
"patch",
"errors",
"fromClient",
"fromDB",
"get",
Expand All @@ -65,6 +65,7 @@ class MetaBaseSkel(type):
"limit",
"orderby",
"orderdir",
"patch",
"postDeletedHandler",
"postSavedHandler",
"preProcessBlobLocks",
Expand Down Expand Up @@ -1760,8 +1761,7 @@ class RefSkel(RelSkel):
@classmethod
def fromSkel(cls, kindName: str, *args: list[str]) -> t.Type[RefSkel]:
"""
Creates a relSkel from a skeleton-class using only the bones explicitly named
in \*args
Creates a ``RefSkel`` from a skeleton-class using only the bones explicitly named in ``args``.
:param args: List of bone names we'll adapt
:return: A new instance of RefSkel
Expand Down

0 comments on commit a9708f3

Please sign in to comment.