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