Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/galaxy/util/jstree.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:32:28 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:d30785e31577 | 1:56ad4e20f292 |
|---|---|
| 1 from __future__ import print_function | |
| 2 | |
| 3 import copy | |
| 4 import os | |
| 5 from collections import namedtuple | |
| 6 | |
| 7 import dictobj | |
| 8 | |
| 9 Path = namedtuple('Path', ('path', 'id', 'options')) | |
| 10 | |
| 11 | |
| 12 class Node(dictobj.DictionaryObject): | |
| 13 """ | |
| 14 Copyright 2012 "Grim Apps" | |
| 15 | |
| 16 Licensed under the Apache License, Version 2.0 (the "License"); | |
| 17 you may not use this file except in compliance with the License. | |
| 18 You may obtain a copy of the License at | |
| 19 | |
| 20 http://www.apache.org/licenses/LICENSE-2.0 | |
| 21 | |
| 22 Unless required by applicable law or agreed to in writing, software | |
| 23 distributed under the License is distributed on an "AS IS" BASIS, | |
| 24 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 25 See the License for the specific language governing permissions and | |
| 26 limitations under the License. | |
| 27 | |
| 28 Helper class written by William Grim - grimwm | |
| 29 Original repo: https://github.com/grimwm/py-jstree | |
| 30 Code adjusted according to the idea of Frank Blechschmidt - FraBle | |
| 31 Thank you! | |
| 32 ************************ | |
| 33 This class exists as a helper to the JSTree. Its "jsonData" method can | |
| 34 generate sub-tree JSON without putting the logic directly into the JSTree. | |
| 35 | |
| 36 This data structure is only semi-immutable. The JSTree uses a directly | |
| 37 iterative (i.e. no stack is managed) builder pattern to construct a | |
| 38 tree out of paths. Therefore, the children are not known in advance, and | |
| 39 we have to keep the children attribute mutable. | |
| 40 """ | |
| 41 | |
| 42 def __init__(self, path, oid, **kwargs): | |
| 43 """ | |
| 44 kwargs allows users to pass arbitrary information into a Node that | |
| 45 will later be output in jsonData(). It allows for more advanced | |
| 46 configuration than the default path handling that JSTree currently allows. | |
| 47 For example, users may want to pass "attr" or some other valid jsTree options. | |
| 48 | |
| 49 Example: | |
| 50 >>> node = Node('a', None) | |
| 51 >>> assert node._items == {'text': 'a', 'children': dictobj.MutableDictionaryObject({})} | |
| 52 >>> assert node.jsonData() == {'text': 'a'} | |
| 53 | |
| 54 >>> node = Node('a', 1) | |
| 55 >>> assert node._items == {'text': 'a', 'children': dictobj.MutableDictionaryObject({}), 'li_attr': dictobj.DictionaryObject({'id': 1}), 'id': 1} | |
| 56 >>> assert node.jsonData() == {'text': 'a', 'id': 1, 'li_attr': {'id': 1}} | |
| 57 | |
| 58 >>> node = Node('a', 5, icon="folder", state = {'opened': True}) | |
| 59 >>> assert node._items == {'text': 'a', 'id': 5, 'state': dictobj.DictionaryObject({'opened': True}), 'children': dictobj.MutableDictionaryObject({}), 'li_attr': dictobj.DictionaryObject({'id': 5}), 'icon': 'folder'} | |
| 60 >>> assert node.jsonData() == {'text': 'a', 'state': {'opened': True}, 'id': 5, 'li_attr': {'id': 5}, 'icon': 'folder'} | |
| 61 """ | |
| 62 super(Node, self).__init__() | |
| 63 | |
| 64 children = kwargs.get('children', {}) | |
| 65 if len([key for key in children if not isinstance(children[key], Node)]): | |
| 66 raise TypeError( | |
| 67 "One or more children were not instances of '%s'" % Node.__name__) | |
| 68 if 'children' in kwargs: | |
| 69 del kwargs['children'] | |
| 70 self._items['children'] = dictobj.MutableDictionaryObject(children) | |
| 71 | |
| 72 if oid is not None: | |
| 73 li_attr = kwargs.get('li_attr', {}) | |
| 74 li_attr['id'] = oid | |
| 75 kwargs['li_attr'] = li_attr | |
| 76 self._items['id'] = oid | |
| 77 | |
| 78 self._items.update(dictobj.DictionaryObject(**kwargs)) | |
| 79 self._items['text'] = path | |
| 80 | |
| 81 def jsonData(self): | |
| 82 children = [self.children[k].jsonData() for k in sorted(self.children)] | |
| 83 output = {} | |
| 84 for k in self._items: | |
| 85 if 'children' == k: | |
| 86 continue | |
| 87 if isinstance(self._items[k], dictobj.DictionaryObject): | |
| 88 output[k] = self._items[k].asdict() | |
| 89 else: | |
| 90 output[k] = self._items[k] | |
| 91 if len(children): | |
| 92 output['children'] = children | |
| 93 return output | |
| 94 | |
| 95 | |
| 96 class JSTree(dictobj.DictionaryObject): | |
| 97 """ | |
| 98 An immutable dictionary-like object that converts a list of "paths" | |
| 99 into a tree structure suitable for jQuery's jsTree. | |
| 100 """ | |
| 101 | |
| 102 def __init__(self, paths, **kwargs): | |
| 103 """ | |
| 104 Take a list of paths and put them into a tree. Paths with the same prefix should | |
| 105 be at the same level in the tree. | |
| 106 | |
| 107 kwargs may be standard jsTree options used at all levels in the tree. These will be outputted | |
| 108 in the JSON. | |
| 109 | |
| 110 """ | |
| 111 if len([p for p in paths if not isinstance(p, Path)]): | |
| 112 raise TypeError( | |
| 113 "All paths must be instances of '%s'" % Path.__name__) | |
| 114 | |
| 115 super(JSTree, self).__init__() | |
| 116 | |
| 117 root = Node('', None, **kwargs) | |
| 118 for path in sorted(paths): | |
| 119 curr = root | |
| 120 subpaths = path.path.split(os.path.sep) | |
| 121 for i, subpath in enumerate(subpaths): | |
| 122 if subpath not in curr.children: | |
| 123 opt = copy.deepcopy(kwargs) | |
| 124 if len(subpaths) - 1 == i: | |
| 125 oid = path.id | |
| 126 opt.update(path.options) if path.options is not None else None | |
| 127 else: | |
| 128 oid = None | |
| 129 curr.children[subpath] = Node(subpath, oid, **opt) | |
| 130 # oid = path.id if len(subpaths) - 1 == i else None | |
| 131 # curr.children[subpath] = Node(subpath, oid, **kwargs) | |
| 132 curr = curr.children[subpath] | |
| 133 self._items['_root'] = root | |
| 134 | |
| 135 def pretty(self, root=None, depth=0, spacing=2): | |
| 136 """ | |
| 137 Create a "pretty print" represenation of the tree with customized indentation at each | |
| 138 level of the tree. | |
| 139 """ | |
| 140 if root is None: | |
| 141 root = self._root | |
| 142 fmt = "%s%s/" if root.children else "%s%s" | |
| 143 s = fmt % (" " * depth * spacing, root.text) | |
| 144 for child in root.children: | |
| 145 child = root.children[child] | |
| 146 s += "\n%s" % self.pretty(child, depth + 1, spacing) | |
| 147 return s | |
| 148 | |
| 149 def jsonData(self): | |
| 150 """ | |
| 151 Returns a copy of the internal tree in a JSON-friendly format, | |
| 152 ready for consumption by jsTree. The data is represented as a | |
| 153 list of dictionaries, each of which are our internal nodes. | |
| 154 | |
| 155 """ | |
| 156 return [self._root.children[k].jsonData() for k in sorted(self._root.children)] |
