From 5da01ed85487d964bb879bc6c3f9a2dd26e339c3 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 10 Jan 2019 15:48:14 +0100 Subject: [PATCH 1/3] Silos are loading also from assets. Catch exception when hierarchy doesn't exist --- launcher/control.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/launcher/control.py b/launcher/control.py index 06fac49..c40529a 100644 --- a/launcher/control.py +++ b/launcher/control.py @@ -283,7 +283,12 @@ def on_project_changed(self, index): apps = lib.get_apps(project) self._registered_actions[:] = actions + apps - silos = io.distinct("silo") + silos = [s['name'] for s in io.find({"type": "asset", "silo": None})] + silos_old = io.distinct("silo") + for silo in silos_old: + if silo not in silos and silo is not None: + silos.append(silo) + self._model.push([ dict({ "name": silo, @@ -359,7 +364,8 @@ def on_asset_changed(self, index): # TODO(marcus): These are going to be accessible # from database, not from the environment. asset = io.find_one({"_id": frame["asset"]}) - api.Session["AVALON_HIERARCHY"] = asset["data"]["hierarchy"] + if "hierarchy" in asset["data"]: + api.Session["AVALON_HIERARCHY"] = asset["data"]["hierarchy"] frame["environment"].update({ "asset_%s" % key: value From df51eb99c4d97796c26e9f74aca7f3597e917dbb Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 10 Jan 2019 17:59:01 +0100 Subject: [PATCH 2/3] launcher is hierarchical and can handle with silo, need more implementation (in way of visualParent) --- launcher/control.py | 222 +++++++++++++++++++++++++++++++++----------- 1 file changed, 167 insertions(+), 55 deletions(-) diff --git a/launcher/control.py b/launcher/control.py index c40529a..65bf87e 100644 --- a/launcher/control.py +++ b/launcher/control.py @@ -186,18 +186,24 @@ def command(self, command): @Slot(QtCore.QModelIndex) def push(self, index): name = model.data(index, "name") - self.breadcrumbs.append(name) - level = len(self.breadcrumbs) - handler = { - 1: self.on_project_changed, - 2: self.on_silo_changed, - 3: self.on_asset_changed, - 4: self.on_task_changed - }[level] + frame = self.current_frame() + + # If nothing is set as current frame we are at selecting projects + handler = self.on_project_changed + if frame: + handler = { + "project": self.on_asset_changed, + "silo": self.on_asset_changed, + "asset": self.on_asset_changed + }[frame["type"]] + if "tasks" in frame and name in frame["tasks"]: + handler = self.on_task_changed handler(index) + self.breadcrumbs.append(self.current_frame()["name"]) + # Push the compatible applications actions = self.collect_compatible_actions(self._registered_actions) self._actions.push(actions) @@ -218,9 +224,12 @@ def pop(self, index=None): steps = len(self.breadcrumbs) - index - 1 for i in range(steps): - self._frames.pop() - self._model.pop() - self._actions.pop() + try: + self._frames.pop() + self._model.pop() + self._actions.pop() + except IndexError: + pass if not self.breadcrumbs: self.popped.emit() @@ -249,9 +258,6 @@ def init(self): if project["data"].get("visible", True) # Discard hidden projects ]) - frame = {"environment": {}} - self._frames[:] = [frame] - # Discover all registered actions discovered_actions = api.discover(api.Action) self._registered_actions[:] = discovered_actions @@ -271,13 +277,10 @@ def on_project_changed(self, index): # Establish a connection to the project database self.log("Connecting to %s" % name, level=INFO) - frame = self.current_frame() project = io.find_one({"type": "project"}) assert project is not None, "This is a bug" - frame["config"] = project["config"] - # Get available project actions and the application actions actions = api.discover(api.Action) apps = lib.get_apps(project) @@ -288,7 +291,6 @@ def on_project_changed(self, index): for silo in silos_old: if silo not in silos and silo is not None: silos.append(silo) - self._model.push([ dict({ "name": silo, @@ -297,8 +299,9 @@ def on_project_changed(self, index): for silo in sorted(silos) ]) + frame = project frame["project"] = project["_id"] - frame["environment"]["project"] = name + frame["environment"] = {"project": name} frame["environment"].update({ "project_%s" % key: str(value) for key, value in project["data"].items() @@ -307,53 +310,98 @@ def on_project_changed(self, index): self._frames.append(frame) self.pushed.emit(name) + def get_recursive_label(self, id, label): + for doc in self.docs: + if doc["_id"] == id: + label = "{0} / {1}".format(doc["name"], label) + + if "visualParent" in doc["data"]: + label = self.get_recursive_label( + doc["data"]["visualParent"], label + ) + + return label + def on_silo_changed(self, index): name = model.data(index, "name") api.Session["AVALON_SILO"] = name frame = self.current_frame() - self._model.push([ - dict({ - "_id": doc["_id"], - "name": doc["name"], - "icon": DEFAULTS["icon"]["asset"], - }, **doc["data"]) - for doc in sorted( - io.find({ - "type": "asset", - "parent": frame["project"], - "silo": name - }), - - # Hard-sort by group - # TODO(marcus): Sorting should really happen in - # the model, via e.g. a Proxy. - key=lambda item: ( - # Sort by group - item["data"].get( - "group", - - # Put items without a - # group at the top - "0"), - - # Sort inner items by name - item["name"] - ) + self.docs = sorted( + io.find({ + "type": "asset", + "parent": frame["project"], + "silo": name + }), + # Hard-sort by group + # TODO(marcus): Sorting should really happen in + # the model, via e.g. a Proxy. + key=lambda item: ( + # Sort by group + item["data"].get( + "group", + + # Put items without a + # group at the top + "0"), + + # Sort inner items by name + item["name"] ) - + ) + valid_docs = [] + for doc in self.docs: # Discard hidden items - if doc["data"].get("visible", True) - ]) + if not doc["data"].get("visible", True): + continue + + if "visualParent" not in doc["data"]: + valid_docs.append( + dict( + { + "_id": doc["_id"], + "name": doc["name"], + "icon": DEFAULTS["icon"]["asset"] + }, + **doc["data"] + ) + ) + else: + data = dict( + { + "_id": doc["_id"], + "name": doc["name"], + "icon": DEFAULTS["icon"]["asset"] + }, + **doc["data"] + ) + data["label"] = self.get_recursive_label( + doc["data"]["visualParent"], + doc["name"] + ) + valid_docs.append(data) + + self._model.push(valid_docs) frame["environment"]["silo"] = name + frame["data"]["label"] = name + frame["type"] = "silo" self._frames.append(frame) self.pushed.emit(name) def on_asset_changed(self, index): name = model.data(index, "name") + entity = io.find_one({ + "type": "asset", + "name": name + }) + # Backwards compatible way + if entity is None: + self.on_silo_changed(index) + return + api.Session["AVALON_ASSET"] = name frame = self.current_frame() @@ -361,12 +409,38 @@ def on_asset_changed(self, index): frame["asset"] = model.data(index, "_id") frame["environment"]["asset"] = name + if entity["silo"] is None: + api.Session["AVALON_SILO"] = name + frame["environment"]["silo"] = name + id = entity["_id"] + frame["asset"] = id + # # below is 'Future way' to find docs!!!!! + # docs = io.find({"type": "asset", "data.visualParent": id}) + docs = io.find({"type": "asset", "parent": frame["project"], "silo": entity['name']}) + else: + docs = io.find({"type": "asset", "data.visualParent": entity["_id"]}) + + self.docs = sorted( + docs, + key=lambda item: ( + # Sort by group + item["data"].get( + "group", + + # Put items without a + # group at the top + "0"), + + # Sort inner items by name + item["name"] + ) + ) # TODO(marcus): These are going to be accessible # from database, not from the environment. asset = io.find_one({"_id": frame["asset"]}) if "hierarchy" in asset["data"]: api.Session["AVALON_HIERARCHY"] = asset["data"]["hierarchy"] - + frame.update(asset) frame["environment"].update({ "asset_%s" % key: value for key, value in asset["data"].items() @@ -393,7 +467,43 @@ def on_asset_changed(self, index): if "icon" not in task: task['icon'] = DEFAULTS['icon']['task'] - self._model.push(sorted(tasks, key=lambda t: t["name"])) + sorted_tasks = [] + for task in sorted(tasks, key=lambda t: t["name"]): + task["group"] = "Tasks" + sorted_tasks.append(task) + + frame["tasks"] = [task["name"] for task in sorted_tasks] + + valid_docs = [] + for doc in self.docs: + if "visualParent" not in doc["data"]: + continue + + if entity["silo"] is None: + if doc["data"]["visualParent"] is None: + valid_docs.append( + dict( + { + "_id": doc["_id"], + "name": doc["name"], + "icon": DEFAULTS["icon"]["asset"] + }, + **doc["data"] + ) + ) + elif doc["data"]["visualParent"] == asset["_id"]: + valid_docs.append( + dict( + { + "_id": doc["_id"], + "name": doc["name"], + "icon": DEFAULTS["icon"]["asset"] + }, + **doc["data"] + ) + ) + + self._model.push(valid_docs + sorted_tasks) self._frames.append(frame) self.pushed.emit(name) @@ -403,11 +513,13 @@ def on_task_changed(self, index): api.Session["AVALON_TASK"] = name frame = self.current_frame() - self._model.push([]) - + frame["name"] = name frame["environment"]["task"] = name + frame["data"]["label"] = name + frame["type"] = "task" self._frames.append(frame) + self._model.push([]) self.pushed.emit(name) @Slot(QtCore.QModelIndex) @@ -474,11 +586,11 @@ def collect_compatible_actions(self, actions): compatible = [] for Action in actions: frame = self.current_frame() - # Build a session from current frame session = {"AVALON_{}".format(key.upper()): value for key, value in frame.get("environment", {}).items()} session["AVALON_PROJECTS"] = api.registered_root() + if not Action().is_compatible(session): continue From 2320f0dc060382a20eb5e8cd0b37ea38eaedbd07 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 11 Jan 2019 14:50:25 +0100 Subject: [PATCH 3/3] reverse commit - launcher can handle with new silo structure --- launcher/control.py | 232 ++++++++++++-------------------------------- 1 file changed, 63 insertions(+), 169 deletions(-) diff --git a/launcher/control.py b/launcher/control.py index 65bf87e..24ae81b 100644 --- a/launcher/control.py +++ b/launcher/control.py @@ -186,24 +186,18 @@ def command(self, command): @Slot(QtCore.QModelIndex) def push(self, index): name = model.data(index, "name") + self.breadcrumbs.append(name) - frame = self.current_frame() - - # If nothing is set as current frame we are at selecting projects - handler = self.on_project_changed - if frame: - handler = { - "project": self.on_asset_changed, - "silo": self.on_asset_changed, - "asset": self.on_asset_changed - }[frame["type"]] - if "tasks" in frame and name in frame["tasks"]: - handler = self.on_task_changed + level = len(self.breadcrumbs) + handler = { + 1: self.on_project_changed, + 2: self.on_silo_changed, + 3: self.on_asset_changed, + 4: self.on_task_changed + }[level] handler(index) - self.breadcrumbs.append(self.current_frame()["name"]) - # Push the compatible applications actions = self.collect_compatible_actions(self._registered_actions) self._actions.push(actions) @@ -224,12 +218,9 @@ def pop(self, index=None): steps = len(self.breadcrumbs) - index - 1 for i in range(steps): - try: - self._frames.pop() - self._model.pop() - self._actions.pop() - except IndexError: - pass + self._frames.pop() + self._model.pop() + self._actions.pop() if not self.breadcrumbs: self.popped.emit() @@ -258,6 +249,9 @@ def init(self): if project["data"].get("visible", True) # Discard hidden projects ]) + frame = {"environment": {}} + self._frames[:] = [frame] + # Discover all registered actions discovered_actions = api.discover(api.Action) self._registered_actions[:] = discovered_actions @@ -277,10 +271,13 @@ def on_project_changed(self, index): # Establish a connection to the project database self.log("Connecting to %s" % name, level=INFO) + frame = self.current_frame() project = io.find_one({"type": "project"}) assert project is not None, "This is a bug" + frame["config"] = project["config"] + # Get available project actions and the application actions actions = api.discover(api.Action) apps = lib.get_apps(project) @@ -291,6 +288,14 @@ def on_project_changed(self, index): for silo in silos_old: if silo not in silos and silo is not None: silos.append(silo) + + self._model.push([ + dict({ + "name": silo, + "icon": DEFAULTS["icon"]["silo"], + }) + for silo in sorted(silos) + ]) self._model.push([ dict({ "name": silo, @@ -299,9 +304,8 @@ def on_project_changed(self, index): for silo in sorted(silos) ]) - frame = project frame["project"] = project["_id"] - frame["environment"] = {"project": name} + frame["environment"]["project"] = name frame["environment"].update({ "project_%s" % key: str(value) for key, value in project["data"].items() @@ -310,98 +314,53 @@ def on_project_changed(self, index): self._frames.append(frame) self.pushed.emit(name) - def get_recursive_label(self, id, label): - for doc in self.docs: - if doc["_id"] == id: - label = "{0} / {1}".format(doc["name"], label) - - if "visualParent" in doc["data"]: - label = self.get_recursive_label( - doc["data"]["visualParent"], label - ) - - return label - def on_silo_changed(self, index): name = model.data(index, "name") api.Session["AVALON_SILO"] = name frame = self.current_frame() - self.docs = sorted( - io.find({ - "type": "asset", - "parent": frame["project"], - "silo": name - }), - # Hard-sort by group - # TODO(marcus): Sorting should really happen in - # the model, via e.g. a Proxy. - key=lambda item: ( - # Sort by group - item["data"].get( - "group", - - # Put items without a - # group at the top - "0"), - - # Sort inner items by name - item["name"] - ) - ) - valid_docs = [] - for doc in self.docs: - # Discard hidden items - if not doc["data"].get("visible", True): - continue - - if "visualParent" not in doc["data"]: - valid_docs.append( - dict( - { - "_id": doc["_id"], - "name": doc["name"], - "icon": DEFAULTS["icon"]["asset"] - }, - **doc["data"] - ) - ) - else: - data = dict( - { - "_id": doc["_id"], - "name": doc["name"], - "icon": DEFAULTS["icon"]["asset"] - }, - **doc["data"] - ) - data["label"] = self.get_recursive_label( - doc["data"]["visualParent"], - doc["name"] + self._model.push([ + dict({ + "_id": doc["_id"], + "name": doc["name"], + "icon": DEFAULTS["icon"]["asset"], + }, **doc["data"]) + for doc in sorted( + io.find({ + "type": "asset", + "parent": frame["project"], + "silo": name + }), + + # Hard-sort by group + # TODO(marcus): Sorting should really happen in + # the model, via e.g. a Proxy. + key=lambda item: ( + # Sort by group + item["data"].get( + "group", + + # Put items without a + # group at the top + "0"), + + # Sort inner items by name + item["name"] ) - valid_docs.append(data) + ) - self._model.push(valid_docs) + # Discard hidden items + if doc["data"].get("visible", True) + ]) frame["environment"]["silo"] = name - frame["data"]["label"] = name - frame["type"] = "silo" self._frames.append(frame) self.pushed.emit(name) def on_asset_changed(self, index): name = model.data(index, "name") - entity = io.find_one({ - "type": "asset", - "name": name - }) - # Backwards compatible way - if entity is None: - self.on_silo_changed(index) - return - api.Session["AVALON_ASSET"] = name frame = self.current_frame() @@ -409,38 +368,11 @@ def on_asset_changed(self, index): frame["asset"] = model.data(index, "_id") frame["environment"]["asset"] = name - if entity["silo"] is None: - api.Session["AVALON_SILO"] = name - frame["environment"]["silo"] = name - id = entity["_id"] - frame["asset"] = id - # # below is 'Future way' to find docs!!!!! - # docs = io.find({"type": "asset", "data.visualParent": id}) - docs = io.find({"type": "asset", "parent": frame["project"], "silo": entity['name']}) - else: - docs = io.find({"type": "asset", "data.visualParent": entity["_id"]}) - - self.docs = sorted( - docs, - key=lambda item: ( - # Sort by group - item["data"].get( - "group", - - # Put items without a - # group at the top - "0"), - - # Sort inner items by name - item["name"] - ) - ) # TODO(marcus): These are going to be accessible # from database, not from the environment. asset = io.find_one({"_id": frame["asset"]}) - if "hierarchy" in asset["data"]: - api.Session["AVALON_HIERARCHY"] = asset["data"]["hierarchy"] - frame.update(asset) + api.Session["AVALON_HIERARCHY"] = asset["data"]["hierarchy"] + frame["environment"].update({ "asset_%s" % key: value for key, value in asset["data"].items() @@ -467,43 +399,7 @@ def on_asset_changed(self, index): if "icon" not in task: task['icon'] = DEFAULTS['icon']['task'] - sorted_tasks = [] - for task in sorted(tasks, key=lambda t: t["name"]): - task["group"] = "Tasks" - sorted_tasks.append(task) - - frame["tasks"] = [task["name"] for task in sorted_tasks] - - valid_docs = [] - for doc in self.docs: - if "visualParent" not in doc["data"]: - continue - - if entity["silo"] is None: - if doc["data"]["visualParent"] is None: - valid_docs.append( - dict( - { - "_id": doc["_id"], - "name": doc["name"], - "icon": DEFAULTS["icon"]["asset"] - }, - **doc["data"] - ) - ) - elif doc["data"]["visualParent"] == asset["_id"]: - valid_docs.append( - dict( - { - "_id": doc["_id"], - "name": doc["name"], - "icon": DEFAULTS["icon"]["asset"] - }, - **doc["data"] - ) - ) - - self._model.push(valid_docs + sorted_tasks) + self._model.push(sorted(tasks, key=lambda t: t["name"])) self._frames.append(frame) self.pushed.emit(name) @@ -513,13 +409,11 @@ def on_task_changed(self, index): api.Session["AVALON_TASK"] = name frame = self.current_frame() - frame["name"] = name + self._model.push([]) + frame["environment"]["task"] = name - frame["data"]["label"] = name - frame["type"] = "task" self._frames.append(frame) - self._model.push([]) self.pushed.emit(name) @Slot(QtCore.QModelIndex) @@ -586,11 +480,11 @@ def collect_compatible_actions(self, actions): compatible = [] for Action in actions: frame = self.current_frame() + # Build a session from current frame session = {"AVALON_{}".format(key.upper()): value for key, value in frame.get("environment", {}).items()} session["AVALON_PROJECTS"] = api.registered_root() - if not Action().is_compatible(session): continue