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)] |