diff env/lib/python3.9/site-packages/galaxy/util/jstree.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/env/lib/python3.9/site-packages/galaxy/util/jstree.py	Mon Mar 22 18:12:50 2021 +0000
@@ -0,0 +1,154 @@
+import copy
+import os
+from collections import namedtuple
+
+import dictobj
+
+Path = namedtuple('Path', ('path', 'id', 'options'))
+
+
+class Node(dictobj.DictionaryObject):
+  """
+  Copyright 2012 "Grim Apps"
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+  Helper class written by William Grim - grimwm
+  Original repo: https://github.com/grimwm/py-jstree
+  Code adjusted according to the idea of Frank Blechschmidt - FraBle
+  Thank you!
+  ************************
+  This class exists as a helper to the JSTree.  Its "jsonData" method can
+  generate sub-tree JSON without putting the logic directly into the JSTree.
+
+  This data structure is only semi-immutable.  The JSTree uses a directly
+  iterative (i.e. no stack is managed) builder pattern to construct a
+  tree out of paths.  Therefore, the children are not known in advance, and
+  we have to keep the children attribute mutable.
+  """
+
+  def __init__(self, path, oid, **kwargs):
+    """
+    kwargs allows users to pass arbitrary information into a Node that
+    will later be output in jsonData().  It allows for more advanced
+    configuration than the default path handling that JSTree currently allows.
+    For example, users may want to pass "attr" or some other valid jsTree options.
+
+    Example:
+      >>> node = Node('a', None)
+      >>> assert node._items == {'text': 'a', 'children': dictobj.MutableDictionaryObject({})}
+      >>> assert node.jsonData() == {'text': 'a'}
+
+      >>> node = Node('a', 1)
+      >>> assert node._items == {'text': 'a', 'children': dictobj.MutableDictionaryObject({}), 'li_attr': dictobj.DictionaryObject({'id': 1}), 'id': 1}
+      >>> assert node.jsonData() == {'text': 'a', 'id': 1, 'li_attr': {'id': 1}}
+
+      >>> node = Node('a', 5, icon="folder", state = {'opened': True})
+      >>> assert node._items == {'text': 'a', 'id': 5, 'state': dictobj.DictionaryObject({'opened': True}), 'children': dictobj.MutableDictionaryObject({}), 'li_attr': dictobj.DictionaryObject({'id': 5}), 'icon': 'folder'}
+      >>> assert node.jsonData() == {'text': 'a', 'state': {'opened': True}, 'id': 5, 'li_attr': {'id': 5}, 'icon': 'folder'}
+    """
+    super().__init__()
+
+    children = kwargs.get('children', {})
+    if len([key for key in children if not isinstance(children[key], Node)]):
+      raise TypeError(
+        "One or more children were not instances of '%s'" % Node.__name__)
+    if 'children' in kwargs:
+      del kwargs['children']
+    self._items['children'] = dictobj.MutableDictionaryObject(children)
+
+    if oid is not None:
+      li_attr = kwargs.get('li_attr', {})
+      li_attr['id'] = oid
+      kwargs['li_attr'] = li_attr
+      self._items['id'] = oid
+
+    self._items.update(dictobj.DictionaryObject(**kwargs))
+    self._items['text'] = path
+
+  def jsonData(self):
+    children = [self.children[k].jsonData() for k in sorted(self.children)]
+    output = {}
+    for k in self._items:
+      if 'children' == k:
+        continue
+      if isinstance(self._items[k], dictobj.DictionaryObject):
+        output[k] = self._items[k].asdict()
+      else:
+        output[k] = self._items[k]
+    if len(children):
+      output['children'] = children
+    return output
+
+
+class JSTree(dictobj.DictionaryObject):
+  """
+  An immutable dictionary-like object that converts a list of "paths"
+  into a tree structure suitable for jQuery's jsTree.
+  """
+
+  def __init__(self, paths, **kwargs):
+    """
+    Take a list of paths and put them into a tree.  Paths with the same prefix should
+    be at the same level in the tree.
+
+    kwargs may be standard jsTree options used at all levels in the tree.  These will be outputted
+    in the JSON.
+
+    """
+    if len([p for p in paths if not isinstance(p, Path)]):
+      raise TypeError(
+        "All paths must be instances of '%s'" % Path.__name__)
+
+    super().__init__()
+
+    root = Node('', None, **kwargs)
+    for path in sorted(paths):
+      curr = root
+      subpaths = path.path.split(os.path.sep)
+      for i, subpath in enumerate(subpaths):
+        if subpath not in curr.children:
+          opt = copy.deepcopy(kwargs)
+          if len(subpaths) - 1 == i:
+            oid = path.id
+            opt.update(path.options) if path.options is not None else None
+          else:
+            oid = None
+          curr.children[subpath] = Node(subpath, oid, **opt)
+          # oid = path.id if len(subpaths) - 1 == i else None
+          # curr.children[subpath] = Node(subpath, oid, **kwargs)
+        curr = curr.children[subpath]
+    self._items['_root'] = root
+
+  def pretty(self, root=None, depth=0, spacing=2):
+    """
+    Create a "pretty print" represenation of the tree with customized indentation at each
+    level of the tree.
+    """
+    if root is None:
+      root = self._root
+    fmt = "%s%s/" if root.children else "%s%s"
+    s = fmt % (" " * depth * spacing, root.text)
+    for child in root.children:
+      child = root.children[child]
+      s += "\n%s" % self.pretty(child, depth + 1, spacing)
+    return s
+
+  def jsonData(self):
+    """
+    Returns a copy of the internal tree in a JSON-friendly format,
+    ready for consumption by jsTree.  The data is represented as a
+    list of dictionaries, each of which are our internal nodes.
+
+    """
+    return [self._root.children[k].jsonData() for k in sorted(self._root.children)]