[TIC-Core] Show all pkg in "advanced". Force filter out "-devel"
[archive/20170607/tools/tic-core.git] / tic / parser / view_parser.py
1 import logging
2 import requests
3 import re
4 from operator import itemgetter
5 from tic.utils.rpmmisc import meetRequireVersion
6
7
8 def make_view_data(pkg_group):
9     logger = logging.getLogger(__name__)
10     
11     def _select_provide_rpm(capability, require):
12         provide_list = []
13         if require.get('ver') is not None:
14             for provide in capability:
15                 ver_data = provide['data']
16                 if not ver_data.get('ver'):
17                     ver_data = pkg_dict.get(provide['name']).get('version')
18                 if meetRequireVersion(require, ver_data):
19                     provide_list.append(provide)
20         else:
21             provide_list = capability
22             
23         result = []
24         for provide in provide_list:
25             result.append(pkg_dict[provide['name']])
26             
27         return result
28     
29     def set_meta_require(meta_info):
30         meta_nodes = meta_info.get('nodes')
31         children = set()
32         for child_meta in meta_nodes:
33             set_meta_require(child_meta)
34             children.add(child_meta['metaname'])
35         
36         duplicate = set()
37         pkg_info = pkg_dict[meta_info['metaname']]
38         for dep_tag in ['requires', 'recommends', 'suggests']:
39             if pkg_info.get(dep_tag):
40                 for req in pkg_info.get(dep_tag):
41                     targets = []
42                     if req['name'] in provides:
43                         targets = _select_provide_rpm(provides[req['name']], req)
44                     elif req['name'] in files:
45                         for fname in files[req['name']]:
46                             targets.append(pkg_dict.get(fname))
47                     elif req['name'] in pkg_dict:
48                         targets.append(pkg_dict.get(req['name']))
49                     else:
50                         # the dependent package does not exist.
51                         pass
52                         
53                     for pkg in targets:
54                         # The meta-pkg of the other group are excluded.
55                         if pkg['name'] not in duplicate:
56                             refer_count[pkg['id']] += 1
57                             duplicate.add(pkg['name'])
58
59                             if pkg.get('meta'):
60                                 if not pkg['name'] in children:
61                                     meta_nodes.append(make_linked_meta_node(pkg['name'], pkg['summary']))
62                             else:
63                                 meta_nodes.append(make_node(pkg, meta_info.get('category')))
64         # Added 'zz' to non meta-package because they are to be listed last
65         meta_nodes = sorted(meta_nodes, key = lambda k: 'aa'+k['metaname'] if 'metaname' in k else 'zz'+k['text'])
66         meta_info['nodes'] = meta_nodes
67
68         if meta_info['metaname'] =='building-blocks-sub2-Preset_iot-examples-3_RPI3_headless_devboard':
69             print(pkg_info)
70     def make_node(pkg_info, category=None):
71         n = dict(text=pkg_info['name'], nodes=[])
72         if category: n['category'] = category
73         return n
74     def make_meta_node(pkgname, viewtext):
75         return dict(text=viewtext, metaname=pkgname, nodes=[])
76     def make_linked_meta_node(pkgname, viewtext):
77         return dict(text='<i>'+viewtext+'</i>', metaname=pkgname, nodes=[])
78     def is_blank_ui_meta_node(pkgname):
79         return (pkgname[-8:-2] == '__UI__')
80     def handle_ui_meta_node(tag, node):
81         node['selectable'] = False
82         node['hideCheckbox'] = True
83         if tag == 'BR' or tag == 'br':
84             node['text'] = ''
85         elif tag == 'HR' or tag == 'hr':
86             node['text'] = '<hr style="margin-bottom: 0px; margin-top: 0px; border-style: inset; border-width: 3px" />'
87         elif tag == 'SD' or tag == 'sd':
88             node['text'] = ''
89             node['backColor'] = '#101010'
90         elif tag == 'SM' or tag == 'sm':
91             # Keep the summary text
92             node['text'] = node['text']
93         elif tag == 'HT' or tag == 'ht':
94             # Keep the summary (TODO: verify the usage of HTML tags.)
95             node['text'] = node['text'] # Do we need conversion?
96         else:
97             node['text'] = ''
98         return node
99     def handle_description(node):
100         if 'metaname' in node:
101             name = node['metaname']
102             pkg_info = pkg_dict[name]
103             desc = pkg_info.get('description')
104             if desc[0:10] == '__KS_URL__':
105                 logger.info("Processing "+name+" for its description: "+pkg_info.get('description'))
106                 # Extract URL from __KS_URL__
107                 ksURL = desc[11:].splitlines()[0].strip()
108                 # Omit the first line with __KS_URL__ from showing.
109                 pkg_info['description'] = desc[len(desc.splitlines(True)[0]):]
110
111                 # Search for filename if directory is given
112                 # e.g., Convert http://a.com/a/ to https://a.com/a/blahblah.ks
113                 # Works for file-indexing html
114                 if ksURL[-3:].lower() != ".ks":
115                     if ksURL[-1:] != "/":
116                         ksURL += "/"
117                     r = requests.get(ksURL)
118                     m = re.search('>([^<]*\\.ks)\\s*<', r.text)
119                     if not m.group(1):
120                         m = re.search('"([^"]*\\.ks)\\s*"', r.text)
121                         if not m.group(1):
122                             m = re.search("'([^']*\\.ks)\\s*'", r.text)
123                             if not m.group(1):
124                                 node['icon'] = 'glyphicon glyphicon-remove-sign'
125                                 node['tooltip'] = 'Cannot find image base from' + ksURL
126                                 return node
127                     ksURL += m.group(1)
128                 node['tooltip'] = 'Image base from '+ksURL
129                 node['ks'] = ksURL
130             elif desc[0:10] == '__EXPAND__':
131                 # Omit the first line with __EXPAND__ from showing.
132                 pkg_info['description'] = desc[len(desc.splitlines(True)[0]):]
133                 node['state'] = { 'expanded': True }
134         return node
135
136     # view_data for tree view on web-ui
137     view_data = []
138     # temporary dictionary for referencing meta
139     view_ref = {}
140     
141     if not pkg_group:
142         return view_data
143       
144     pkg_dict = pkg_group['pkg_dict']
145     provides = pkg_group['provides']
146     files = pkg_group['files']
147     refer_count = [0] * len(pkg_dict)
148     
149     # sort meta-pkg by pkt_name in ascending order
150     meta_info = pkg_group.get('meta_info')
151     meta_info['root'] = sorted(meta_info['root'], key=itemgetter(0))
152     meta_info['sub1'] = sorted(meta_info['sub1'], key=itemgetter(0))
153     meta_info['sub2'] = sorted(meta_info['sub2'], key=itemgetter(0))
154     
155     # make category rpms
156     category_dict = {}
157     if meta_info.get('category'):
158         for category in meta_info['category']:
159             c_rpm = pkg_dict[category[0]]
160             if hasattr(c_rpm.get('suggests'), '__iter__'):
161                 for suggest in c_rpm.get('suggests'):
162                     category_dict[suggest['name']] = category[1]
163             else:
164                 logger.info(c_rpm.get('suggests'))
165                 logger.info(c_rpm.get('name'))
166
167     
168     # make tree of meta
169     for root in meta_info['root']:
170         root_node = make_meta_node(root[0], root[1])
171         view_ref[root[0]] = root_node
172         if root[0] in category_dict:
173             root_node['category'] = category_dict[root[0]]
174         if is_blank_ui_meta_node(root[0]):
175             name = root[0]
176             sub1_node = handle_ui_meta_node(name[-2:], root_node)
177         root_node = handle_description(root_node)
178         view_data.append(root_node)
179         
180     for sub1 in meta_info['sub1']:
181         sub1_node = make_meta_node(sub1[0], sub1[2])
182         view_ref[sub1[0]] = sub1_node
183         if is_blank_ui_meta_node(sub1[0]):
184             name = sub1[0]
185             sub1_node = handle_ui_meta_node(name[-2:], sub1_node)
186         sub1_node = handle_description(sub1_node)
187         # search root
188         if sub1[1] in view_ref:
189             # add to root node
190             if 'category' in view_ref[sub1[1]] and view_ref[sub1[1]]['category']:
191                 sub1_node['category'] = view_ref[sub1[1]]['category']
192             view_ref[sub1[1]]['nodes'].append(sub1_node)
193         else:
194             # If root-meta does not exist, sub1 is added to top-level
195             view_data.append(sub1_node)
196             
197     for sub2 in meta_info['sub2']:
198         sub2_node = make_meta_node(sub2[0], sub2[3])
199         view_ref[sub2[0]] = sub2_node
200         if is_blank_ui_meta_node(sub2[0]):
201             name = sub2[0]
202             sub1_node = handle_ui_meta_node(name[-2:], sub2_node)
203         sub2_node = handle_description(sub2_node)
204         # search sub1
205         if sub2[2] in view_ref:
206             if 'category' in view_ref[sub2[2]] and view_ref[sub2[2]]['category']:
207                 sub2_node['category'] = view_ref[sub2[2]]['category']
208             view_ref[sub2[2]]['nodes'].append(sub2_node)
209         # search root    
210         elif sub2[1] in view_ref: 
211             if view_ref[sub2[1]]['category']:
212                 sub2_node['category'] = view_ref[sub2[1]]['category']
213             # If sub1-meta does not exist, sub2 is added to child of root-meta
214             view_ref[sub2[1]]['nodes'].append(sub2_node)
215         else:
216             # If root-meta/sub1-meta does not exist, sub1 is added to top-level
217             view_data.append(sub2_node)
218     
219     # configure meta dependency tree (requires)
220     for meta_pkg in view_data:
221         set_meta_require(meta_pkg)
222         
223     #The remaining rpms are grouped into a MISC tree
224     misc_info = {}
225     misc_info['text'] = 'Advanced (individual packages)'
226     misc_info['nodes'] = []
227     for k, v in pkg_dict.iteritems():
228         # Add ALL non-block packages
229         if v['name'][0:15] != 'building-blocks':
230             misc_info['nodes'].append(make_node(v))
231     misc_info['nodes'] = sorted(misc_info['nodes'], key = lambda k: k['metaname'] if 'metaname' in k else k['text'])
232
233     view_data.append(misc_info)
234     logger.info('meta: %d, misc: %d', len(view_ref), len(misc_info['nodes']))
235     return view_data