[Bf-blender-cvs] [037e761] asset-engine: Claude: more WIP work towards listing content on Cloud repository.

Bastien Montagne noreply at git.blender.org
Thu Sep 8 15:27:16 CEST 2016


Commit: 037e761f1f2cfc175665557713903919af50dfaa
Author: Bastien Montagne
Date:   Thu Sep 8 15:26:36 2016 +0200
Branches: asset-engine
https://developer.blender.org/rB037e761f1f2cfc175665557713903919af50dfaa

Claude: more WIP work towards listing content on Cloud repository.

===================================================================

M	release/scripts/startup/bl_operators/claude/__init__.py

===================================================================

diff --git a/release/scripts/startup/bl_operators/claude/__init__.py b/release/scripts/startup/bl_operators/claude/__init__.py
index 2205c02..b5e14b1 100644
--- a/release/scripts/startup/bl_operators/claude/__init__.py
+++ b/release/scripts/startup/bl_operators/claude/__init__.py
@@ -61,11 +61,14 @@ import binascii
 import hashlib
 import json
 import os
+import pathlib
 import stat
 import struct
 import time
 import random
 
+from collections import OrderedDict
+
 import pillarsdk
 
 REQUIRED_ROLES_FOR_CLAUDE = {'subscriber', 'demo'}
@@ -73,6 +76,67 @@ REQUIRED_ROLES_FOR_CLAUDE = {'subscriber', 'demo'}
 
 ##########
 # Helpers.
+class SpecialFolderNode(pillarsdk.Node):
+    pass
+
+
+class UpNode(SpecialFolderNode):
+    def __init__(self):
+        super().__init__()
+        self['_id'] = 'UP'
+        self['node_type'] = 'UP'
+        self['name'] = ".."
+
+
+class ProjectNode(SpecialFolderNode):
+    def __init__(self, project):
+        super().__init__()
+
+        assert isinstance(project, pillarsdk.Project), "wrong type for project: %r" % type(project)
+
+        self.merge(project.to_dict())
+        self['node_type'] = 'PROJECT'
+
+
+class ClaudeRepository:
+    def __init__(self):
+        self.path_map = {}  # Mapping names->uuid of Cloud nodes (so that user gets friendly 'named' paths in browser).
+        self.curr_path = pillar.CloudPath("/")  # Using node names.
+        self.curr_path_real = pillar.CloudPath("/")  # Using node uuid's.
+        self.pending_path = []  # Defined when we get a path from browser (e.g. user input) that we don't know of...
+
+        self.nodes = OrderedDict()  # uuid's to nodes mapping, for currently browsed area...
+        self.is_ready = False
+
+    def check_dir_do(self, root_path, do_change, do_update_intern):
+        if self.curr_path == root_path:
+            return True, root_path
+        parts = root_path.parts
+        if do_update_intern:
+            self.pending_path = []
+            self.is_ready = False
+            self.nodes.clear()
+        if parts and parts[0] == "/":
+            nids = [parts[0]]
+            paths = self.path_map
+            for i, p in enumerate(parts[1:]):
+                nid, paths = paths.get(p, (None, None))
+                if nid is None:
+                    if do_update_intern:
+                        self.pending_path = parts[i + 1:]
+                        self.curr_path = pillar.CloudPath("/".join(parts[:i + 1]))
+                        self.curr_path_real = pillar.CloudPath("/".join(nids))
+                    break
+                else:
+                    nids.append(nid)
+            return True, root_path
+        elif do_change:
+            if do_update_intern:
+                self.curr_path = pillar.CloudPath("/")
+                self.curr_path_real = pillar.CloudPath("/")
+            return True, pillar.CloudPath("/")
+        else:
+            return False, root_path
 
 
 #############
@@ -82,13 +146,12 @@ class ClaudeJob:
     def async_looper(func):
         def wrapper(self, *args, **kwargs):
             loop = self.loop
-            assert(not self.loop.is_running())
+            assert(not loop.is_running())
             print("proceed....")
             ret = func(self, *args, **kwargs)
             if not self.evt_cancel.is_set():
                 print("kickstep")
                 # This forces loop to only do 'one step', and return (hopefully!) very soon.
-                # Note: both calls below work essentially the same way, we could also use call_later with 0.1ms delay...
                 #~ loop.stop()
                 loop.call_soon(loop.stop)
                 loop.run_forever()
@@ -97,16 +160,33 @@ class ClaudeJob:
             return ret
         return wrapper
 
+    def add_task(self, coro):
+        task = asyncio.ensure_future(coro)
+        self._tasks.append(task)
+        return task
+
+    def remove_task(self, task):
+        self._tasks.remove(task)
+        return None
+
     def cancel(self):
         print("Cancelling ", self)
         self.evt_cancel.set()
+        for task in self._tasks:
+            task.cancel()
+        self._tasks[:] = []
+        self.status = {'VALID'}
         assert(not self.loop.is_running())
+        self.loop.call_soon(self.loop.stop)
+        self.loop.run_forever()
 
     def __init__(self, job_id):
         self.job_id = job_id
         self.status = {'VALID'}
         self.progress = 0.0
 
+        self._tasks = []
+
         self.evt_cancel = threading.Event()
         self.loop = asyncio.get_event_loop()
 
@@ -155,7 +235,7 @@ class ClaudeJobCheckCredentials(ClaudeJob):
 
     @ClaudeJob.async_looper
     def start(self):
-        self.check_task = asyncio.ensure_future(self.check())
+        self.check_task = self.add_task(self.check())
         self.progress = 0.0
         self.status = {'VALID', 'RUNNING'}
 
@@ -163,24 +243,25 @@ class ClaudeJobCheckCredentials(ClaudeJob):
     def update(self):
         self.status = {'VALID', 'RUNNING'}
         user_id = ...
+
+        self.progress += 0.05
+        if (self.progress > 1.0):
+            self.progress = 0.0
+
         print("Updating credential status, ", self.check_task, " | Done: ", self.check_task.done() if self.check_task else "")
         if self.check_task is not None:
             if not self.check_task.done():
                 return ...
             print("Cred check finished, we should have cloud access...")
             user_id = self.check_task.result()
-            print(user_id)
-            self.check_task = None
+            self.check_task = self.remove_task(self.check_task)
             self.progress = 1.0
 
         if self.check_task is None:
+            self.progress = 1.0
             self.status = {'VALID'}
         return user_id
 
-    def cancel(self):
-        super().cancel()
-        self.status = {'VALID'}
-
     def __init__(self, job_id):
         super().__init__(job_id)
 
@@ -191,21 +272,38 @@ class ClaudeJobCheckCredentials(ClaudeJob):
 
 class ClaudeJobList(ClaudeJob):
     @staticmethod
-    async def ls(node):
-        print("we should be listing Cloud content from Node ", node, "...")
-        await asyncio.sleep(1)
+    async def ls(repo):
+        print("we should be listing Cloud content from %s..." % repo.curr_path_real)
+
+        project_uuid = repo.curr_path_real.project_uuid
+        node_uuid = repo.curr_path_real.node_uuid
+
+        if node_uuid:
+            # Query for sub-nodes of this node.
+            print("Getting subnodes for parent node %r" % node_uuid)
+            children = await pillar.get_nodes(parent_node_uuid=node_uuid, node_type='group_texture')
+            print(children)
+        elif project_uuid:
+            # Query for top-level nodes.
+            print("Getting subnodes for project node %r" % project_uuid)
+            children = await pillar.get_nodes(project_uuid=project_uuid, parent_node_uuid='', node_type='group_texture')
+            print(children)
+        else:
+            # Query for projects
+            print("No node UUID and no project UUID, listing available projects")
+            children = await pillar.get_texture_projects()
+            print(children)
 
-        return ["..", "a", "b"]
+        repo.pending_path = []
+        repo.is_ready = True
 
     @ClaudeJob.async_looper
-    def start(self):
-        self.nbr = 0
-        self.tot = 0
-        self.ls_task = asyncio.ensure_future(self.ls(self.curr_node))
+    def start(self, user_id):
+        self.ls_task = self.add_task(self.ls(self.repo))
         self.status = {'VALID', 'RUNNING'}
 
     @ClaudeJob.async_looper
-    def update(self, user_id, dirs):
+    def update(self, user_id):
         self.status = {'VALID', 'RUNNING'}
 
         if user_id is None:
@@ -217,31 +315,32 @@ class ClaudeJobList(ClaudeJob):
             print("Awaiting a valid user ID...")
             return
 
+        self.progress += 0.05
+        if (self.progress > 1.0):
+            self.progress = 0.0
+
         if self.ls_task is not None:
-            if not self.ls_task.done():
-                dirs[:] = [".."]
-                return
-            print("ls finished, we should have our children nodes now!")
-            dirs[:] = self.ls_task.result()
-            print(dirs)
-            self.ls_task = None
-
-        self.progress = self.nbr / self.tot if self.tot else 0.0
+            if self.ls_task.done():
+                print("ls finished, we should have our children nodes now!")
+                self.ls_task = self.remove_task(self.ls_task)
+
         if self.ls_task is None:
+            self.progress = 1.0
             self.status = {'VALID'}
 
     def cancel(self):
-        print("CANCELLING...")
+        if self.ls_task:
+            self.ls_task.cancel()
         super().cancel()
-        self.status = {'VALID'}
 
-    def __init__(self, job_id, user_id, curr_node):
+    def __init__(self, job_id, user_id, repo):
         super().__init__(job_id)
-        self.curr_node = curr_node
+        self.repo = repo
+        self.curr_path = repo.curr_path_real
 
         self.ls_task = None
 
-        self.start()
+        self.start(user_id)
 
 
 """
@@ -322,20 +421,12 @@ class AssetEngineClaude(AssetEngine):
         self.job_id_check_credentials = ...
         self.check_credentials()
 
-        self.reset()
+        self.repo = ClaudeRepository()
 
     def __del__(self):
         pass
 
     ########## Various helpers ##########
-    def reset(self):
-        print("Claude Reset!")
-        self.jobs = {jid: j for jid, j in self.jobs.items() if jid == self.job_id_check_credentials}
-        self.root = ""
-        self.dirs = []
-
-        self.sortedfiltered = []
-
     def check_credentials(self):
         if self.job_id_check_credentials is None:
             return self.user_id
@@ -418,7 +509,7 @@ class AssetEngineClaude(AssetEngine):
             if 'RUNNING' in job.status:
                 nbr_jobs += 1
                 progress += job.progress
-        return progress / nbr_jobs if nbr_jobs else 0.0
+        return (progress / nbr_jobs) if nbr_jobs else 0.0
 
     def kill(self, job_id):
         if job_id:
@@ -429,27 +520,32 @@ class AssetEngineCl

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list