diff --git a/pype/ftrack/actions/action_delivery.py b/pype/ftrack/actions/action_delivery.py
index 22fb15198b..e698c371e1 100644
--- a/pype/ftrack/actions/action_delivery.py
+++ b/pype/ftrack/actions/action_delivery.py
@@ -1,9 +1,12 @@
import os
import copy
import shutil
+import collections
+import string
import clique
from bson.objectid import ObjectId
+
from avalon import pipeline
from avalon.vendor import filelink
from avalon.tools.libraryloader.io_nonsingleton import DbConnector
@@ -162,10 +165,17 @@ class Delivery(BaseAction):
"type": "label"
})
+ items.append({
+ "type": "label",
+ "value": (
+ "NOTE: It is possible to replace `root` key in anatomy."
+ )
+ })
+
items.append({
"type": "text",
"name": "__location_path__",
- "empty_text": "Type location path here..."
+ "empty_text": "Type location path here...(Optional)"
})
items.append(item_splitter)
@@ -199,6 +209,8 @@ class Delivery(BaseAction):
if "values" not in event["data"]:
return
+ self.report_items = collections.defaultdict(list)
+
values = event["data"]["values"]
skipped = values.pop("__skipped__")
if skipped:
@@ -214,7 +226,10 @@ class Delivery(BaseAction):
component_names.append(key)
if not component_names:
- return None
+ return {
+ "success": True,
+ "message": "Not selected components to deliver."
+ }
location_path = os.path.normpath(location_path.strip())
if location_path and not os.path.exists(location_path):
@@ -236,14 +251,24 @@ class Delivery(BaseAction):
parent = asset["parent"]
parent_mongo_id = parent["custom_attributes"].get(CustAttrIdKey)
- if not parent_mongo_id:
- # TODO log error (much better)
- self.log.warning((
- "Seems like entity <{}> is not synchronized to avalon"
- ).format(parent["name"]))
- continue
+ if parent_mongo_id:
+ parent_mongo_id = ObjectId(parent_mongo_id)
+ else:
+ asset_ent = self.db_con.find_one({
+ "type": "asset",
+ "data.ftrackId": parent["id"]
+ })
+ if not asset_ent:
+ ent_path = "/".join(
+ [ent["name"] for ent in parent["link"]]
+ )
+ msg = "Not synchronized entities to avalon"
+ self.report_items[msg].append(ent_path)
+ self.log.warning("{} <{}>".format(msg, ent_path))
+ continue
+
+ parent_mongo_id = asset_ent["_id"]
- parent_mongo_id = ObjectId(parent_mongo_id)
subset_ent = self.db_con.find_one({
"type": "subset",
"parent": parent_mongo_id,
@@ -283,6 +308,50 @@ class Delivery(BaseAction):
else:
anatomy_data["root"] = pipeline.registered_root()
+ anatomy_filled = anatomy.format(anatomy_data)
+ test_path = (
+ anatomy_filled
+ .get("delivery", {})
+ .get(anatomy_name)
+ )
+
+ if not test_path:
+ msg = (
+ "Missing keys in Representation's context"
+ " for anatomy template \"{}\"."
+ ).format(anatomy_name)
+
+ all_anatomies = anatomy.format_all(anatomy_data)
+ result = None
+ for anatomies in all_anatomies.values():
+ for key, temp in anatomies.get("delivery", {}).items():
+ if key != anatomy_name:
+ continue
+
+ result = temp
+ break
+
+ # TODO log error! - missing keys in anatomy
+ if result:
+ missing_keys = [
+ key[1] for key in string.Formatter().parse(result)
+ if key[1] is not None
+ ]
+ else:
+ missing_keys = ["unknown"]
+
+ keys = ", ".join(missing_keys)
+ sub_msg = (
+ "Representation: {}
- Missing keys: \"{}\"
"
+ ).format(str(repre["_id"]), keys)
+ self.report_items[msg].append(sub_msg)
+ self.log.warning(
+ "{} Representation: \"{}\" Filled: <{}>".format(
+ msg, str(repre["_id"]), str(result)
+ )
+ )
+ continue
+
# Get source repre path
repre_path = self.path_from_represenation(repre)
# TODO add backup solution where root of path from component
@@ -300,17 +369,13 @@ class Delivery(BaseAction):
self.db_con.uninstall()
- return True
+ return self.report()
def process_single_file(
self, repre_path, anatomy, anatomy_name, anatomy_data
):
anatomy_filled = anatomy.format(anatomy_data)
- delivery_path = anatomy_filled.get("delivery", {}).get(anatomy_name)
- if not delivery_path:
- # TODO log error! - missing keys in anatomy
- return
-
+ delivery_path = anatomy_filled["delivery"][anatomy_name]
delivery_folder = os.path.dirname(delivery_path)
if not os.path.exists(delivery_folder):
os.makedirs(delivery_folder)
@@ -321,9 +386,6 @@ class Delivery(BaseAction):
self, repre_path, anatomy, anatomy_name, anatomy_data
):
dir_path, file_name = os.path.split(repre_path)
- if not os.path.exists(dir_path):
- # TODO log if folder don't exist
- return
base_name, ext = os.path.splitext(file_name)
file_name_items = None
@@ -334,7 +396,9 @@ class Delivery(BaseAction):
file_name_items = base_name.split("%")
if not file_name_items:
- # TODO log if file does not exists
+ msg = "Source file was not found"
+ self.report_items[msg].append(repre_path)
+ self.log.warning("{} <{}>".format(msg, repre_path))
return
src_collections, remainder = clique.assemble(os.listdir(dir_path))
@@ -352,15 +416,15 @@ class Delivery(BaseAction):
if src_collection is None:
# TODO log error!
+ msg = "Source collection of files was not found"
+ self.report_items[msg].append(repre_path)
+ self.log.warning("{} <{}>".format(msg, repre_path))
return
anatomy_data["frame"] = "<>"
anatomy_filled = anatomy.format(anatomy_data)
- delivery_path = anatomy_filled.get("delivery", {}).get(anatomy_name)
- if not delivery_path:
- # TODO log error! - missing keys in anatomy
- return
+ delivery_path = anatomy_filled["delivery"][anatomy_name]
delivery_folder = os.path.dirname(delivery_path)
dst_head, dst_tail = delivery_path.split("<>")
dst_padding = src_collection.padding
@@ -418,6 +482,40 @@ class Delivery(BaseAction):
except OSError:
shutil.copyfile(src_path, dst_path)
+ def report(self):
+ items = []
+ title = "Delivery report"
+ for msg, _items in self.report_items.items():
+ if not _items:
+ continue
+
+ if items:
+ items.append({"type": "label", "value": "---"})
+
+ items.append({
+ "type": "label",
+ "value": "# {}".format(msg)
+ })
+ if isinstance(_items, str):
+ _items = [_items]
+ items.append({
+ "type": "label",
+ "value": '
{}
'.format("