-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAres.py
More file actions
354 lines (298 loc) · 13.8 KB
/
Ares.py
File metadata and controls
354 lines (298 loc) · 13.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
""" Report Interface
This module will be used to produce the final report
It will link the HTML generation with the Javascript and Graphs parts
Users will be able to create bespoke reports from this wrapper using the standard HTML functions from the
module LibReportHTML. There is no need in this section to write HTML string, this class will only struture the
component and allow users to change them.
Any new HTML component should be written in the module LibReportHtml.py
The Report Class will contain only information about formatting in order to produce the final String
report in the function html()
In Ares there is no Javascript and CSS module integrated.
Basically as long as your version of Jquery, NVD3 and D3 are recent enought to support the fragments of HTML and
javascript defined in the different classes. It is possible to test the different features in the AresWrapper module.
QUESTION: Should we call the html() function in the wrapper or should we let the user call it ?
"""
# TODO: To use it to replace the redondant functions calls
# TODO: implement a decorator to wrap the current part in the functions
import inspect
import AresHtml
import AresGraph
htmlFactory = None # This is the factory with all the alias and HTML classes
# the below global variables are only used locally to generate the secondary pages and Ajax calls
LOCAL_DIRECTORY, LOCAL_STATIC_PATH, LOCAL_CSSFILES, LOCALJSFILES = None, None, None, None
def mapHtmlItems():
""" Map the aliases to the HTML objects """
htmlObjs = {}
for name, obj in inspect.getmembers(AresHtml):
if inspect.isclass(obj) and obj.alias is not None:
htmlObjs[obj.alias] = obj
return htmlObjs
def htmlLocalHeader(directory, report, statisPath, cssFiles, javascriptFiles):
""" Add the header to the report when we are producing a text file - namely local run """
global LOCAL_DIRECTORY, LOCAL_STATIC_PATH, LOCAL_CSSFILES, LOCALJSFILES
LOCAL_DIRECTORY, LOCAL_STATIC_PATH, LOCAL_CSSFILES, LOCALJSFILES = directory, statisPath, cssFiles, javascriptFiles
htmlFile = open(r"%s\%s.html" % (directory, report), "w")
htmlFile.write('<!DOCTYPE html>\n')
htmlFile.write('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr"> \n')
htmlFile.write('<head>\n')
htmlFile.write('%s<meta charset="utf-8">\n' % AresHtml.INDENT)
htmlFile.write('%s<meta http-equiv="X-UA-Compatible" content="IE=edge">\n' % AresHtml.INDENT)
htmlFile.write('%s<meta name="viewport" content="width=device-width, initial-scale=1">\n' % AresHtml.INDENT)
htmlFile.write('%s<title>Local HTML Report</title>\n' % AresHtml.INDENT)
for style in cssFiles:
htmlFile.write('%s<link rel="stylesheet" href="%scss/%s" type="text/css">\n' % (AresHtml.INDENT, statisPath, style))
for javascript in javascriptFiles:
htmlFile.write('%s<script src="%sjs/%s"></script>\n' % (AresHtml.INDENT, statisPath, javascript))
htmlFile.write('</head>\n')
htmlFile.write('<body><div class="container">\n\n')
return htmlFile
def htmlLocalFooter(htmlFile):
""" Close all the HTML report and close the input text File - namely locally """
htmlFile.write('\n</div>\n</body>\n')
htmlFile.write('</html>\n')
htmlFile.close()
class Report(object):
"""
Ares Interface
Main module to link the user reports and the HTML and Graph modules.
"""
def __init__(self):
"""
"""
global htmlFactory
# Internal variable that should not be used directly
# Those variable will drive the report generation
self.__countItems = 0
self.__content, self.__jsGraph, self.navTitle = [], [], []
self.__htmlItems, self.jsOnLoad = {}, {}
if htmlFactory is None:
htmlFactory = mapHtmlItems()
#for name, htmlCls in htmlFactory.items():
# print(name)
def container(self):
"""
"""
def structure(self):
return self.content
def item(self, itemId):
""" Return the HTML object """
return self.__htmlItems[itemId]
def div(self, value):
"""
Return the object ID to help on getting the object back. In any time during the
report generation. THis ID is not supposed to change and it will be the
"""
htmlObject = AresHtml.Div(self.__countItems, value)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def list(self, values):
""" """
htmlObject = AresHtml.List(self.__countItems, values)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def table(self, cols, values):
""" """
htmlObject = AresHtml.Table(self.__countItems, cols, values)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def dropDown(self, title, values):
""" """
htmlObject = AresHtml.DropDown(self.__countItems, title, values)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def dropZone(self):
""" """
htmlObject = AresHtml.DropZone(self.__countItems)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def textArea(self):
""" """
htmlObject = AresHtml.TextArea(self.__countItems)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def select(self, values):
""" """
htmlObject = AresHtml.Select(self.__countItems, values)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def container(self, htmlObj):
""" """
del self.__content[self.__content.index(htmlObj.htmlId)] # Is not defined in the root structure
htmlObject = AresHtml.Container(self.__countItems, htmlObj)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def grid(self, htmlObjLeft, htmlObjRight):
""" """
del self.__content[self.__content.index(htmlObjLeft.htmlId)] # Is not defined in the root structure
del self.__content[self.__content.index(htmlObjRight.htmlId)] # Is not defined in the root structure
htmlObject = AresHtml.Split(self.__countItems, htmlObjLeft, htmlObjRight)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def button(self, value, cssCls=None):
htmlObject = AresHtml.Button(self.__countItems, value, cssCls=cssCls)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def input(self, name, value):
""" """
htmlObject = AresHtml.Input(self.__countItems, name, value)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def text(self, value, cssCls=None):
""" """
htmlObject = AresHtml.Text(self.__countItems, value, cssCls=cssCls)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def code(self, value, cssCls=None):
""" """
htmlObject = AresHtml.Code(self.__countItems, value, cssCls=cssCls)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def paragraph(self, value, textObjsList=None, cssCls=None):
""" """
if textObjsList is not None:
for textObj in textObjsList:
del self.__content[self.__content.index(textObj.htmlId)] # Is not defined in the root structure
htmlObject = AresHtml.Paragraph(self.__countItems, value, textObjsList, cssCls=cssCls)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def title(self, dim, value, cssCls=None):
""" """
htmlObject = AresHtml.Title(self.__countItems, dim, value, cssCls=cssCls)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
self.navTitle.append(htmlObject)
return htmlObject.htmlId
def pieChart(self, values, width=960, height=500, cssCls=None):
""" Construct a Pie Chart in the HTML page """
graphContainer = AresHtml.Graph(self.__countItems, width, height, cssCls=cssCls)
self.__htmlItems[graphContainer.htmlId] = graphContainer
self.__content.append(graphContainer.htmlId)
self.__countItems += 1
graphObject = AresGraph.Donut(graphContainer.htmlId, values)
self.__jsGraph.append(graphObject)
return graphContainer.htmlId
def cloudChart(self, values, width=960, height=500, cssCls=None):
""" Construct a Pie Chart in the HTML page """
graphContainer = AresHtml.Graph(self.__countItems, width, height, cssCls=cssCls)
self.__htmlItems[graphContainer.htmlId] = graphContainer
self.__content.append(graphContainer.htmlId)
self.__countItems += 1
graphObject = AresGraph.WordCloud(graphContainer.htmlId, values)
self.__jsGraph.append(graphObject)
return graphContainer.htmlId
def tree(self, cols, values, width=960, height=500, cssCls=None):
""" """
graphContainer = AresHtml.Graph(self.__countItems, width, height, withSgv=False, cssCls=cssCls)
self.__htmlItems[graphContainer.htmlId] = graphContainer
self.__content.append(graphContainer.htmlId)
self.__countItems += 1
graphObject = AresGraph.IndentedTree(graphContainer.htmlId, cols, values)
self.__jsGraph.append(graphObject)
return graphContainer.htmlId
def comboLineBar(self, values, width=960, height=500, cssCls=None):
""" Construct a Pie Chart in the HTML page """
graphContainer = AresHtml.Graph(self.__countItems, width, height, cssCls=cssCls)
self.__htmlItems[graphContainer.htmlId] = graphContainer
self.__content.append(graphContainer.htmlId)
self.__countItems += 1
graphObject = AresGraph.ComboLineBar(graphContainer.htmlId, values)
self.__jsGraph.append(graphObject)
return graphContainer.htmlId
def anchor(self, value, link, structure, localPath, cssCls=None):
""" Add an anchor HTML tag to the report """
if localPath is not None:
# There is a child and we need to produce the sub Report attached to it
#
childReport = structure[link].replace(".py", "")
htmlPage = htmlLocalHeader(LOCAL_DIRECTORY, childReport, LOCAL_STATIC_PATH, LOCAL_CSSFILES, LOCALJSFILES)
htmlPage.write(__import__(childReport).report(Report(), localPath=LOCAL_DIRECTORY))
htmlLocalFooter(htmlPage)
link = "%s.html" % childReport
htmlObject = AresHtml.A(self.__countItems, value, link, cssCls=cssCls)
self.__htmlItems[htmlObject.htmlId] = htmlObject
self.__content.append(htmlObject.htmlId)
self.__countItems += 1
return htmlObject.htmlId
def html(self, localPath, title=None, menu=True):
""" Main function used to generate the report
"""
# TODO: add the menu
results, jsResults = [], []
results.append('<script>')
for jsOnLoad in self.jsOnLoad.keys():
results.append(jsOnLoad)
results.append('</script>')
if menu:
results.append('<div class="page-wrapper">')
results.append('%s<div class="doc-wrapper">' % AresHtml.INDENT)
results.append('%s%s<div class="container">' % (AresHtml.INDENT, AresHtml.INDENT))
results.append('%s%s<div class="doc-body">' % (AresHtml.INDENT, AresHtml.INDENT))
results.append('%s%s%s<div class="doc-sidebar hidden-xs">' % (AresHtml.INDENT, AresHtml.INDENT, AresHtml.INDENT))
results.append('%s%s%s%s<nav id="doc-nav">' % (AresHtml.INDENT, AresHtml.INDENT, AresHtml.INDENT, AresHtml.INDENT))
results.append('%s%s%s%s%s<ul id="doc-menu" class="nav doc-menu" data-apy="affix">' % (AresHtml.INDENT, AresHtml.INDENT, AresHtml.INDENT, AresHtml.INDENT, AresHtml.INDENT))
for section in self.navTitle:
#subItems = self.navBar[section]
results.append('<li><a href="%s">%s</a></li>' % (section.htmlId, section.val))
#if subItems:
# jsResults.append('<ul class="nav doc-sub-menu">')
# for subItems in subItems:
# jsResults.append('<li><a href="%s">%s</a></li>')
# jsResults.append('</ul>')
results.append("</ul></nav></div>")
if title is not None:
titleObj = AresHtml.Title(self.__countItems, 1, title)
results.append(titleObj.html())
results.append('</div></div></div></div>')
for htmlId in self.__content:
results.append(self.__htmlItems[htmlId].html())
if self.__htmlItems[htmlId].jsEvent is not None:
for fnc, fncDef in self.__htmlItems[htmlId].jsEvent:
if fnc in ['drop', 'dragover']:
jsResults.append('%s.bind("%s", function (event){' % (self.__htmlItems[htmlId].jsRef(), fnc))
jsResults.append(fncDef)
jsResults.append('});\n')
else:
jsResults.append('%s.%s(function(){' % (self.__htmlItems[htmlId].jsRef(), fnc))
jsResults.append(fncDef)
jsResults.append('});\n')
if self.__jsGraph:
jsResults.append("nv.addGraph(function() {\n")
for jsgraphs in self.__jsGraph:
jsResults.append(jsgraphs.js(localPath))
jsResults.append("\n\n")
jsResults.append("});\n")
# Section dedicated to write all the extra Javascript callback functions
# This will allow the page to be interactive
results.append("<script>")
results.extend(jsResults)
results.append("</script>\n")
return "\n".join(results)