#! /usr/bin/env python # encoding: utf-8 # hhaim, 2014 (IL) base on WAF book """ call 'waf --targets=waf.pdf' or use 'waf list' to see the targets available """ VERSION='0.0.1' APPNAME='wafdocs' import os, re, shutil import sys import shlex import subprocess import json import re from waflib import Logs top = '.' out = 'build' sphinx_version = None try: from HTMLParser import HTMLParser except: from html.parser import HTMLParser class CTocNode: def __init__ (self): self.name="root" self.level=1; # 1,2,3,4 self.link=None; self.parent=None self.childs=[]; # link to CTocNode def get_link (self): if self.link==None: name=self.name l=name.split('.'); l=l[-1].lower() s=''; for c in l: if c.isalpha() or c.isspace(): s+=c return '#_'+'_'.join(s.lower().split()); else: return '#'+self.link def add_new_child (self,name,level,link): n=CTocNode(); n.name=name; n.link=link n.level=level; n.parent=self; self.childs.append(n); return n def to_json_childs (self): l=[] for obj in self.childs: l.append(obj.to_json()); return (l); def to_open (self): if self.level <3: return True else: return False def to_json (self): d={"text" : self.name, "link" : self.get_link(), "state" : { "opened" : self.to_open() } } if len(self.childs)>0 : d["children"]= self.to_json_childs() return d class TocHTMLParser(HTMLParser): def __init__ (self): HTMLParser.__init__(self); self.state=0; self.root=CTocNode() self.root.parent=self.root self.level=2; self.attrs=None self.d={}; self.last_level=1 self.set_level(1,self.root) def set_level (self,level,node): assert(node!=None); assert(isinstance(node,CTocNode)==True); self.d[str(level)]=node # in case we change from high to low level remove the higher level if level<self.last_level: for l in range(level+1,self.last_level+1): self.d.pop(str(l),None) def _get_level (self,level): k=str(level) if k in self.d: n=self.d[k] assert(n!=None); return n else: return None def get_level (self,level): for l in range(level,0,-1): n=self._get_level(l) if n != None: return n assert(0); def is_header (self,tag): if len(tag)==2 and tag[0]=='h' and tag[1].isdigit() and (int(tag[1])>1): return (True); def handle_starttag(self, tag, attrs): if self.is_header (tag): self.attrs=attrs self.state=True; self.level=int(tag[1]); def handle_endtag(self, tag): if self.is_header (tag): self.state=False; def get_id (self): if self.attrs: for obj in self.attrs: if obj[0]=='id': return obj[1] else: return None def handle_data(self, data): if self.state: level=self.level cnode=self.get_level(level-1) n=cnode.add_new_child(data,level,self.get_id()); assert(n!=None); self.set_level(level,n) self.last_level=level def dump_as_json (self): return json.dumps(self.root.to_json_childs(), sort_keys=False, indent=4) def create_toc_json (input_file,output_file): f = open (input_file) l=f.readlines() f.close(); html_input = ''.join(l) parser = TocHTMLParser() parser.feed(html_input); f = open (output_file,'w') f.write(parser.dump_as_json()); f.close(); re_xi = re.compile('''^(include|image)::([^.]*.(asciidoc|\\{PIC\\}))\[''', re.M) def ascii_doc_scan(self): p = self.inputs[0].parent node_lst = [self.inputs[0]] seen = [] depnodes = [] while node_lst: nd = node_lst.pop(0) if nd in seen: continue seen.append(nd) code = nd.read() for m in re_xi.finditer(code): name = m.group(2) if m.group(3) == '{PIC}': ext = '.eps' if self.generator.rule.rfind('A2X') > 0: ext = '.png' k = p.find_resource(name.replace('{PIC}', ext)) if k: depnodes.append(k) else: k = p.find_resource(name) if k: depnodes.append(k) node_lst.append(k) return [depnodes, ()] def scansize(self): name = 'image::%s\\{PIC\\}\\[.*,(width|height)=(\\d+)' % self.inputs[0].name[:-4] re_src = re.compile(name) lst = self.inputs[0].parent.get_src().ant_glob('*.txt') for x in lst: m = re_src.search(x.read()) if m: val = str(int(1.6 * int(m.group(2)))) if m.group(1) == 'width': w = val h = "800" else: w = "800" h = val ext = self.inputs[0].name[-3:] if ext == 'eps': code = '-geometry %sx%s' % (w, h) elif ext == 'dia': if m.group(1) == 'width': h = '' else: w = '' code = '--size %sx%s' % (w, h) else: code = '-Gsize="%s,%s"' % (w, h) break else: return ([], '') return ([], code) def options(opt): opt.add_option('--exe', action='store_true', default=False, help='Execute the program after it is compiled') opt.add_option('--performance', action='store_true', help='Build a performance report based on google analytics') opt.add_option('--performance-detailed',action='store_true',help='print detailed test results (date,time, build id and results) to csv file named _detailed_table.csv.') def configure(conf): search_path = '~/.local/bin /usr/local/bin/ /usr/bin' conf.find_program('asciidoc', path_list=search_path, var='ASCIIDOC') conf.find_program('sphinx-build', path_list=search_path, var='SPHINX') conf.find_program('source-highlight', path_list=search_path, var='SRC_HIGHLIGHT') conf.find_program('dblatex', path_list=search_path, var='DBLATEX') conf.find_program('a2x', path_list=search_path, var='A2X') pass; def convert_to_pdf(task): input_file = task.outputs[0].abspath() out_dir = task.outputs[0].parent.get_bld().abspath() return os.system('a2x --no-xmllint %s -f pdf -d article %s -D %s ' %('-v' if Log.verbose else '', task.inputs[0].abspath(),out_dir ) ) TOC_HEAD = """ <body class="book"> <div id="toc-section"> <div id="toctitle"> <img class="trex_logo" src="images/trex_logo_toc.png"/> Table of Contents </div> <div id="toggle"> <img src="images/icons/toggle.png" title="click to toggle table of contents"/> </div> <div id="toc"> <div id="nav-tree"> </div> </div> </div> <div id="content-section"> <!-- load the theme CSS file --> <link href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" rel="stylesheet"/> <link href="https://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" rel="stylesheet" /> <!-- include the jQuery library --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js"> </script> <!-- include the jQuery UI library --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"> </script> <!-- include the minified jstree source --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"> </script> <!-- Hide TOC on mobile --> <script> // Hide TOC when it is mobile checkMobile(); // Hide TOC by default if it is mobile function checkMobile(){ if(isMobileDevice()){ hideTOC(); } } // Check it it it is running on mobile device function isMobileDevice() { if( navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/iPhone|iPad|iPod/i) || navigator.userAgent.match(/Opera Mini/i) || navigator.userAgent.match(/IEMobile/i) || navigator.userAgent.match(/iPhone|iPad|iPod/i) ) { return true; } else { return false; } } // Hide TOC - for the first time in mobile function hideTOC(){ $("#toc").hide(); $("#toctitle").hide(); // Show the show/hide button $("#toggle").css("right", "-40px"); // Fil width $("body").css("margin-left", "50px"); } </script> <div id="content-section-inner"> """ TOC_END = """ </div> <!-- End Of Inner Content Section --> </div> <!-- End of Content Section --> </body> <style type="text/css"> #toc { margin-bottom: 2.5em; } #toctitle { color: #527bbd; font-size: 1.1em; font-weight: bold; margin-top: 1.0em; margin-bottom: 0.1em; } @media screen { body { margin-left: 20em; } #toc { position: fixed; top: 51px; left: 0; bottom: 0; width: 18em; padding-bottom: 1.5em; margin: 0; overflow-x: auto !important; overflow-y: auto !important; border-right: solid 2px #cfcfcf; background-color: #FAFAFA; white-space: nowrap; } #toctitle { font-size: 17px !important; color: #4d4d4d !important; margin-top: 0px; height: 36px; line-height: 36px; background-color: #e4e2e2; padding: 8px 0px 7px 45px; white-space: nowrap; left: 0px; display: block; position: fixed; z-index: 100; width: 245px; top: 0px; overflow: hidden; } #toc .toclevel1 { margin-top: 0.5em; } #toc .toclevel2 { margin-top: 0.25em; display: list-item; color: #aaaaaa; } } /* Custom for Nave Tree */ #nav-tree{ margin-left: 10px !important; } #nav-tree ul > li { color: #000 !important; } .jstree-wholerow.jstree-wholerow-clicked { background-image: url('images/icons/selected_tab_bg.png'); background-repeat: repeat-x; color: #fff !important; text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); } /* For side bar */ .ui-resizable-e{ height: 100%; width: 4px !important; position: fixed !important; top: 0px !important; cursor: e-resize !important; background: url('images/splitbar.png') repeat scroll right center transparent !important; } .jstree-default .jstree-themeicon{ display: none !important; } .jstree-anchor { font-size: 12px !important; color: #91A501 !important; } .jstree-clicked{ color: white !important; } #toggle { position: fixed; top: 14px; left: 10px; z-index: 210; width: 24px; } #toggle img { opacity:0.3; } #toggle img:hover { opacity:0.9; } .trex_logo{ top: 6px; position: relative; } html{ overflow: hidden; } body{ margin-right: 0px !important; margin-top: 0px !important; margin-bottom: 0px !important; } #toc-section{ position: absolute; z-index: 200; } #content-section{ overflow: auto; } #content-section-inner{ max-width: 50em; } </style> <script> $(document).ready(function(){ var isOpen = true; // Initialize NavTree initializeNavTree(); // Drag TOC left and right initResizable(); // Toggle TOC whe clicking on the menu icon toggleTOC(); // Handle Mobile - close TOC checkMobile(); function initializeNavTree() { // TOC tree options var toc_tree = $('#nav-tree'); var toc_tree_options = { 'core' : { "animation" :false, "themes" : { "stripes" : false }, 'data' : { "url" : "./input_replace_me.json", "dataType" : "json" // needed only if you do not supply JSON headers } } , "plugins" : [ "wholerow" ] }; $('#nav-tree').jstree(toc_tree_options) ; toc_tree.on("changed.jstree", function (e, data) { window.location.href = data.instance.get_selected(true)[0].original.link; }); } function initResizable() { var toc = $("#toc"); var body = $("body"); // On resize $("#toc").resizable({ resize: function(e, ui) { resized(); }, handles: 'e' }); // On zoom changed $(window).resize(function() { if(isOpen){ resized(); } }); // Do it for the first time var tocWidth = $(toc).outerWidth(); var windowHeight = $(window).height(); $(".ui-resizable-e").css({"right":$(window).width()-parseInt(tocWidth)+"px"}); $("#toctitle").css({"width":parseInt(tocWidth)-45+"px"}); $("#toc-section").css({"height":windowHeight + "px"}); $("#content-section").css({"height":windowHeight + "px"}); } function resized(){ var body = $("body"); var tocWidth = $(toc).outerWidth(); var windowHeight = $(window).height(); body.css({"marginLeft":parseInt(tocWidth)+20+"px"}); $(".ui-resizable-e").css({"right":$(window).width()-parseInt(tocWidth)+"px"}); $("#toctitle").css({"width":parseInt(tocWidth)-45+"px"}); $("#toc-section").css({"height":windowHeight + "px"}); $("#content-section").css({"height":windowHeight + "px"}); } function toggleTOC(){ $( "#toggle" ).click(function() { if ( isOpen ) { // Close it closTOC(); } else { // Open it openTOC(); } // Toggle status isOpen = !isOpen; }); } // Close TOC by default if it is mobile function checkMobile(){ if(isMobileDevice()){ isOpen=false; $(".ui-resizable-e").hide(); } } // Check it it it is running on mobile device function isMobileDevice() { if( navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/iPhone|iPad|iPod/i) || navigator.userAgent.match(/Opera Mini/i) || navigator.userAgent.match(/IEMobile/i) || navigator.userAgent.match(/iPhone|iPad|iPod/i) ) { return true; } else { return false; } } // Close TOC function closTOC(){ $("#toc").hide("slide", 500); $("#toctitle").hide("slide", 500); if(!isMobileDevice()){ $(".ui-resizable-e").hide("slide", 500); } // Show the show/hide button $("#toggle").css("right", "-40px"); // Fil width $("body").animate({"margin-left": "50px"}, 500); } // Open TOC function openTOC(){ $("#toc").show("slide", 500); $("#toctitle").show("slide", 500); if(!isMobileDevice()){ $(".ui-resizable-e").show("slide", 500); } // Show the show/hide button $("#toggle").css("right", "15px"); // Minimize page width $("body").animate({"margin-left": $(toc).outerWidth()+20+"px"}, 500); } }); </script> """ def do_replace (input_file,contents,look,str_replaced): if contents.count(look)!=1 : raise Exception('Cannot find {0} in file {1} '.format(look,input_file)) return contents.replace(look, str_replaced) def toc_fixup_file (input_file, out_file, json_file_name ): file = open(input_file) contents = file.read() contents = do_replace(input_file,contents,'<body class="book">', TOC_HEAD); contents = do_replace(input_file,contents,'</body>', TOC_END) contents = do_replace(input_file,contents,'input_replace_me.json', json_file_name) file = open(out_file,'w') file.write(contents) file.close(); def convert_to_html_toc_book(task): input_file = task.inputs[0].abspath() json_out_file = os.path.splitext(task.outputs[0].abspath())[0]+'.json' tmp = os.path.splitext(task.outputs[0].abspath())[0]+'.tmp' json_out_file_short = os.path.splitext(task.outputs[0].name)[0]+'.json' cmd='{0} -a stylesheet={1} -a icons=true -a docinfo -d book -o {2} {3}'.format( task.env['ASCIIDOC'][0], task.inputs[1].abspath(), tmp, task.inputs[0].abspath()); res= os.system( cmd ) if res !=0 : return (1) create_toc_json(tmp,json_out_file) toc_fixup_file(tmp,task.outputs[0].abspath(),json_out_file_short); return os.system('rm {0}'.format(tmp)); def convert_to_pdf_book(task): input_file = task.outputs[0].abspath() out_dir = task.outputs[0].parent.get_bld().abspath() return os.system('a2x --no-xmllint %s -f pdf -d book %s -D %s ' %('-v' if Logs.verbose else '', task.inputs[0].abspath(),out_dir ) ) def ensure_dir(f): if not os.path.exists(f): os.makedirs(f) def my_copy(task): input_file=task.outputs[0].abspath() out_dir=task.outputs[0].parent.get_bld().abspath() ensure_dir(out_dir) shutil.copy2(input_file, out_dir+ os.sep+task.outputs[0].name) return (0) def do_visio(bld): for x in bld.path.ant_glob('visio\\*.vsd'): tg = bld(rule='${VIS} -i ${SRC} -o ${TGT} ', source=x, target=x.change_ext('.png')) def get_sphinx_version(sphinx_path): try: global sphinx_version if not sphinx_version: sphinx_version_regexp = '^Sphinx \(sphinx-build\) (\d+)\.(\d+)\.\d+$' cmd = '%s %s --version' % (sys.executable, sphinx_path) output = subprocess.check_output(shlex.split(cmd), universal_newlines = True) for line in output.splitlines(): ver = re.match(sphinx_version_regexp, line) if ver: sphinx_version = float('%s.%s' % (ver.group(1), ver.group(2))) return sphinx_version except Exception as e: print('Error getting Sphinx version: %s' % e) def get_trex_core_git(): trex_core_git_path = os.path.abspath(os.path.join(os.getcwd(), os.pardir)) if not os.path.isdir(trex_core_git_path): trex_core_git_path = os.getenv('TREX_CORE_GIT', None) return trex_core_git_path def parse_hlt_args(task): trex_core_git_path = get_trex_core_git() if not trex_core_git_path: return 1 hltapi_path = os.path.abspath(os.path.join(trex_core_git_path, 'scripts', 'automation', 'trex_control_plane', 'stl', 'trex_stl_lib', 'trex_stl_hltapi.py')) header = ['[options="header",cols="<.^1,^.^1,9<.^e"]', '|=================', '^| Argument | Default ^| Comment'] footer = ['|=================\n'] hlt_asciidoc = [] category_regexp = '^(\S+)_kwargs = {$' comment_line_regexp = '^\s*#\s*(.+)$' arg_line_regexp = "^\s*'([^']+)':\s*'?([^,']+)'?,\s*#?\s*(.+)?$" if not os.path.exists(hltapi_path): raise Exception('Could not find hltapi file: %s' % hltapi_path) with open(hltapi_path) as f: in_args = False for line in f.read().splitlines(): if not in_args: if line.startswith('import'): break category_line = re.match(category_regexp, line) if category_line: hlt_asciidoc.append('\n===== %s\n' % category_line.group(1)) hlt_asciidoc += header in_args = True continue comment_line = re.match(comment_line_regexp, line) if comment_line: hlt_asciidoc.append('3+^.^s| %s' % comment_line.group(1).replace('|', '\|')) continue arg_line = re.match(arg_line_regexp, line) if arg_line: arg, default, comment = arg_line.groups() hlt_asciidoc.append('| %s | %s | %s' % (arg, default, comment.replace('|', '\|') if comment else '')) continue if line == '}': hlt_asciidoc += footer in_args = False if not len(hlt_asciidoc): raise Exception('Parsing of hltapi args failed') with open('build/hlt_args.asciidoc', 'w') as f: f.write('\n'.join(hlt_asciidoc)) return 0 def build_cp_docs (task): out_dir = task.outputs[0].abspath() export_path = os.path.join(os.getcwd(), 'build', 'cp_docs') trex_core_git_path = get_trex_core_git() if not trex_core_git_path: # there exists a default directory or the desired ENV variable. return 1 trex_core_docs_path = os.path.abspath(os.path.join(trex_core_git_path, 'scripts', 'automation', 'trex_control_plane', 'doc')) sphinx_version = get_sphinx_version(task.env['SPHINX'][0]) if not sphinx_version: return 1 if sphinx_version < 1.3: additional_args = '-D html_theme=default' else: additional_args = '' build_doc_cmd = "{pyt} {sph} {add} {ver} -W -b {bld} {src} {dst}".format( pyt= sys.executable, sph= task.env['SPHINX'][0], add= additional_args, ver= '' if Logs.verbose else '-q', bld= "html", src= ".", dst= out_dir) if Logs.verbose: print(build_doc_cmd) try: return subprocess.call(shlex.split(build_doc_cmd), cwd = trex_core_docs_path) except OSError as e: print('Failed command: %s\nError: %s' % (build_doc_cmd, e)) return 1 def build_stl_cp_docs (task): out_dir = task.outputs[0].abspath() export_path = os.path.join(os.getcwd(), 'build', 'cp_stl_docs') trex_core_git_path = get_trex_core_git() if not trex_core_git_path: # there exists a default directory or the desired ENV variable. return 1 trex_core_docs_path = os.path.abspath(os.path.join(trex_core_git_path, 'scripts', 'automation', 'trex_control_plane', 'doc_stl')) sphinx_version = get_sphinx_version(task.env['SPHINX'][0]) if not sphinx_version: return 1 if sphinx_version < 1.3: additional_args = '-D html_theme=default' else: additional_args = '' build_doc_cmd = "{pyt} {sph} {add} {ver} -W -b {bld} {src} {dst}".format( pyt= sys.executable, sph= task.env['SPHINX'][0], add= additional_args, ver= '' if Logs.verbose else '-q', bld= "html", src= ".", dst= out_dir) if Logs.verbose: print(build_doc_cmd) try: return subprocess.call(shlex.split(build_doc_cmd), cwd = trex_core_docs_path) except OSError as e: print('Failed command: %s\nError: %s' % (build_doc_cmd, e)) return 1 def build_cp(bld,dir,root,callback): export_path = os.path.join(os.getcwd(), 'build', dir) trex_core_git_path = get_trex_core_git() if not trex_core_git_path: # there exists a default directory or the desired ENV variable. raise NameError("Environment variable 'TREX_CORE_GIT' is not defined.") trex_core_docs_path = os.path.join(trex_core_git_path, 'scripts', 'automation', 'trex_control_plane', root, 'index.rst') bld(rule=callback,target = dir) def create_analytic_report(task): try: import AnalyticsWebReport as analytics if task.generator.bld.options.performance_detailed: analytics.main(verbose = Logs.verbose,detailed_test_stats='yes') else: analytics.main(verbose = Logs.verbose) except Exception as e: raise Exception('Error importing or using AnalyticsWebReport script: %s' % e) def build(bld): bld(rule=my_copy, target='symbols.lang') for x in bld.path.ant_glob('images\\**\**.png'): bld(rule=my_copy, target=x) bld.add_group() for x in bld.path.ant_glob('yaml\\**\**.yaml'): bld(rule=my_copy, target=x) bld.add_group() for x in bld.path.ant_glob('video\\**\**.mp4'): bld(rule=my_copy, target=x) bld.add_group() for x in bld.path.ant_glob('images\\**\**.jpg'): bld(rule=my_copy, target=x) bld.add_group() if bld.options.performance or bld.options.performance_detailed: bld(rule=create_analytic_report) bld.add_group() bld(rule=convert_to_html_toc_book, source='trex_analytics.asciidoc waf.css', target='trex_analytics.html',scan=ascii_doc_scan); return bld(rule=my_copy, target='my_chart.js') build_cp(bld,'hlt_args.asciidoc','stl/trex_stl_lib', parse_hlt_args) bld.add_group() # separator, the documents may require any of the pictures from above if os.path.exists('build/hlt_args.asciidoc'): bld.add_manual_dependency( bld.path.find_node('trex_stateless.asciidoc'), b'build/hlt_args.asciidoc') bld(rule='${ASCIIDOC} -f ../backends/deckjs/deckjs.conf -o ${TGT} ${SRC[0].abspath()}', source='trex_config.asciidoc ', target='trex_config_guide.html', scan=ascii_doc_scan) bld(rule='${ASCIIDOC} -f ../backends/deckjs/deckjs.conf -o ${TGT} ${SRC[0].abspath()}', source='trex_preso.asciidoc ', target='trex_preso.html', scan=ascii_doc_scan) bld(rule='${ASCIIDOC} -a stylesheet=${SRC[1].abspath()} -a icons=true -a max-width=55em -o ${TGT} ${SRC[0].abspath()}', source='release_notes.asciidoc waf.css', target='release_notes.html', scan=ascii_doc_scan) bld(rule='${ASCIIDOC} -a docinfo -a stylesheet=${SRC[1].abspath()} -a icons=true -a toc2 -a max-width=55em -d book -o ${TGT} ${SRC[0].abspath()}', source='draft_trex_stateless.asciidoc waf.css', target='draft_trex_stateless.html', scan=ascii_doc_scan) bld(rule='${ASCIIDOC} -a docinfo -a stylesheet=${SRC[1].abspath()} -a icons=true -a toc2 -a max-width=55em -d book -o ${TGT} ${SRC[0].abspath()}', source='draft_trex_stateless_moved1.asciidoc waf.css', target='draft_trex_stateless1.html', scan=ascii_doc_scan) bld(rule=convert_to_pdf_book,source='trex_book.asciidoc waf.css', target='trex_book.pdf', scan=ascii_doc_scan) bld(rule=convert_to_pdf_book,source='trex_stateless.asciidoc waf.css', target='trex_stateless.pdf', scan=ascii_doc_scan) bld(rule=convert_to_pdf_book,source='draft_trex_stateless.asciidoc waf.css', target='draft_trex_stateless.pdf', scan=ascii_doc_scan) bld(rule=convert_to_pdf_book,source='trex_vm_manual.asciidoc waf.css', target='trex_vm_manual.pdf', scan=ascii_doc_scan) bld(rule=convert_to_pdf_book,source='trex_control_plane_peek.asciidoc waf.css', target='trex_control_plane_peek.pdf', scan=ascii_doc_scan) bld(rule=convert_to_pdf_book, source='trex_control_plane_design_phase1.asciidoc waf.css', target='trex_control_plane_design_phase1.pdf', scan=ascii_doc_scan) # with nice TOC bld(rule=convert_to_html_toc_book, source='trex_vm_manual.asciidoc waf.css', target='trex_vm_manual.html',scan=ascii_doc_scan) bld(rule=convert_to_html_toc_book, source='trex_stateless.asciidoc waf.css', target='trex_stateless.html',scan=ascii_doc_scan); bld(rule=convert_to_html_toc_book, source='trex_stateless_bench.asciidoc waf.css', target='trex_stateless_bench.html',scan=ascii_doc_scan); bld(rule=convert_to_html_toc_book, source='trex_book.asciidoc waf.css', target='trex_manual.html',scan=ascii_doc_scan); bld(rule=convert_to_html_toc_book, source='trex_faq.asciidoc waf.css', target='trex_faq.html',scan=ascii_doc_scan); bld(rule=convert_to_html_toc_book, source='trex_rpc_server_spec.asciidoc waf.css', target='trex_rpc_server_spec.html',scan=ascii_doc_scan); bld(rule=convert_to_html_toc_book, source='trex_scapy_rpc_server.asciidoc waf.css', target='trex_scapy_rpc_server.html',scan=ascii_doc_scan); bld(rule=convert_to_html_toc_book, source='trex-analytics-howto.asciidoc waf.css', target='trex-analytics-howto.html',scan=ascii_doc_scan); bld(rule='${ASCIIDOC} -a stylesheet=${SRC[1].abspath()} -a icons=true -a toc2 -a max-width=55em -o ${TGT} ${SRC[0].abspath()}', source='vm_doc.asciidoc waf.css', target='vm_doc.html', scan=ascii_doc_scan) bld(rule='${ASCIIDOC} -a stylesheet=${SRC[1].abspath()} -a icons=true -a toc2 -a max-width=55em -o ${TGT} ${SRC[0].abspath()}', source='packet_builder_yaml.asciidoc waf.css', target='packet_builder_yaml.html', scan=ascii_doc_scan) bld(rule='${ASCIIDOC} -a stylesheet=${SRC[1].abspath()} -a icons=true -a toc2 -a max-width=55em -o ${TGT} ${SRC[0].abspath()}', source='trex_control_plane_design_phase1.asciidoc waf.css', target='trex_control_plane_design_phase1.html', scan=ascii_doc_scan) bld(rule='${ASCIIDOC} -a stylesheet=${SRC[1].abspath()} -a icons=true -a toc2 -a max-width=55em -o ${TGT} ${SRC[0].abspath()}', source='trex_control_plane_peek.asciidoc waf.css', target='trex_control_plane_peek.html', scan=ascii_doc_scan) bld(rule='${ASCIIDOC} -a stylesheet=${SRC[1].abspath()} -a icons=true -a toc2 -a max-width=55em -o ${TGT} ${SRC[0].abspath()}', source='trex_console.asciidoc waf.css', target='trex_console.html', scan=ascii_doc_scan) bld(rule='${ASCIIDOC} -a stylesheet=${SRC[1].abspath()} -a icons=true -a max-width=55em -o ${TGT} ${SRC[0].abspath()}', source='trex_index.asciidoc waf.css', target='index.html', scan=ascii_doc_scan) build_cp(bld,'cp_docs','doc',build_cp_docs) build_cp(bld,'cp_stl_docs','doc_stl',build_stl_cp_docs) class Env(object): @staticmethod def get_env(name) : s= os.environ.get(name); if s == None: print("You should define $",name) raise Exception("Env error"); return (s); @staticmethod def get_release_path () : s= Env().get_env('TREX_LOCAL_PUBLISH_PATH'); s +=get_build_num ()+"/" return s; @staticmethod def get_remote_release_path () : s= Env().get_env('TREX_REMOTE_PUBLISH_PATH'); return s; @staticmethod def get_local_web_server () : s= Env().get_env('TREX_WEB_SERVER'); return s; # extral web @staticmethod def get_trex_ex_web_key() : s= Env().get_env('TREX_EX_WEB_KEY'); return s; @staticmethod def get_trex_ex_web_path() : s= Env().get_env('TREX_EX_WEB_PATH'); return s; @staticmethod def get_trex_ex_web_user() : s= Env().get_env('TREX_EX_WEB_USER'); return s; @staticmethod def get_trex_ex_web_srv() : s= Env().get_env('TREX_EX_WEB_SRV'); return s; @staticmethod def get_trex_core() : s= Env().get_env('TREX_CORE_GIT'); return s; def release(bld): # copy all the files to our web server core_dir = Env().get_trex_core() release_dir = core_dir +"/scripts/doc/"; os.system('mkdir -p '+release_dir) os.system('cp -rv build/release_notes.* '+ release_dir) def rsync_int(bld, src, dst): cmd = 'rsync -av --del --rsh=ssh build/{src} {host}:{dir}/{dst}'.format( src = src, host = Env().get_local_web_server(), dir = Env().get_remote_release_path() + '../doc', dst = dst) ret = os.system(cmd) if ret: bld.fatal("cmd '%s' exited with return status: %s" % (cmd, ret)) def rsync_ext(bld, src, dst): cmd = 'rsync -avz --del -e "ssh -i {key}" --rsync-path=/usr/bin/rsync build/{src} {user}@{host}:{dir}/doc/{dst}'.format( key = Env().get_trex_ex_web_key(), src = src, user = Env().get_trex_ex_web_user(), host = Env().get_trex_ex_web_srv(), dir = Env().get_trex_ex_web_path(), dst = dst) ret = os.system(cmd) if ret: bld.fatal("cmd '%s' exited with return status: %s" % (cmd, ret)) def publish(bld): # copy all the files to internal web server rsync_int(bld, '', '') def publish_ext(bld): # copy all the files to external web server rsync_ext(bld, '', '') def publish_perf(bld): # copy performance files to internal and external servers rsync_int(bld, 'trex_analytics.html', '') rsync_ext(bld, 'trex_analytics.html', '') rsync_int(bld, 'trex_analytics.json', '') rsync_ext(bld, 'trex_analytics.json', '') rsync_int(bld, 'images/*_latest_test_*', 'images/') rsync_ext(bld, 'images/*_latest_test_*', 'images/') rsync_int(bld, 'images/*_trend_graph.*', 'images/') rsync_ext(bld, 'images/*_trend_graph.*', 'images/') rsync_int(bld, 'images/*_trend_stats.*', 'images/') rsync_ext(bld, 'images/*_trend_stats.*', 'images/') rsync_int(bld, 'images/_detailed_table.csv', 'images/') rsync_ext(bld, 'images/_detailed_table.csv', 'images/') rsync_int(bld, 'images/_comparison.png', 'images/') rsync_ext(bld, 'images/_comparison.png', 'images/') rsync_int(bld, 'images/_comparison_stats_table.csv', 'images/') rsync_ext(bld, 'images/_comparison_stats_table.csv', 'images/') def publish_test(bld): # copy all the files to our web server remote_dir = "%s:%s" % ( Env().get_local_web_server(), Env().get_remote_release_path ()+'../test/') os.system('rsync -av --del --rsh=ssh build/ %s' % (remote_dir)) def publish_both(bld): publish(bld) publish_ext(bld) def test(bld): # copy all the files to our web server toc_fixup_file ('build/trex_stateless.tmp', 'build/trex_stateless.html', 'trex_stateless.json')