Best Python code snippet using ATX
starboard.py
Source:starboard.py  
1from rich.console import Console2from rich.layout import Layout3from rich.panel import Panel4from rich.align import Align5from rich.padding import Padding6from rich.table import Table7from rich.prompt import Prompt8from rich import box9from user import User10import requests11import psutil12from datetime import datetime13import random14import time15import json16import sys17import re1819__VERSION__ = "2.6"2021# adjust console size with your own values before using22console = Console(height=66)  # full size: height: 66, width: 240 (ASUS VE248)232425class Dashboard:2627    def __init__(self):28        self.boot_time = datetime.fromtimestamp(psutil.boot_time()).replace(microsecond=0)29        self.pattern_open, self.pattern_inprogress, self.pattern_closed = re_patterns()30        self.daily_data = None31        self.general_data = None32        self.notes_data = None33        self.score_prio = str()34        self.score_total = str()35        self.layout = None36        self.layout_config()3738    def render_board(self):39        self.update_data()40        console.clear()41        console.print(self.layout)4243    def update_data(self):44        time_1 = self.get_data('daily')45        time_2 = self.get_data('general')46        time_3 = self.get_notes()47        self.get_score()4849        self.render_header()50        self.render_table_daily()51        self.render_table_general()52        self.render_notes()53        self.render_footer(time_1 + time_2 + time_3)5455    # initialize dashboard56    def layout_config(self):57        self.layout = Layout()58        self.layout.split_column(59            Layout(name='top', size=3),60            Layout(name='content'),61            Layout(name='bottom', size=3),62        )6364        self.layout['top'].split_row(65            Layout(name='top_left'),66            Layout(name='top_mid'),67            Layout(name='top_right'),68        )6970        self.layout['content'].split_column(71            Layout(name='content_top'),72            Layout(name='content_bottom'),73        )74        self.layout['content_top'].split_row(75            Layout(name='left'),76            Layout(name='right'),77        )78        self.layout['left'].split_column(79            Layout(name='left_upper', size=11),80            Layout(name='left_lower'),81        )82        DAILY = r'''ââââââ   âââââ  ââ ââ      ââ    ââ 83ââ   ââ ââ   ââ ââ ââ       ââ  ââ  84ââ   ââ âââââââ ââ ââ        ââââ   85ââ   ââ ââ   ââ ââ ââ         ââ    86ââââââ  ââ   ââ ââ âââââââ    ââ    '''87        self.layout['left_upper'].update(88            Align(Padding(Panel(DAILY, box=box.SQUARE, style='white', border_style='black'), (4, 0, 0, 0)),89                  align='center'))9091        self.layout['right'].split_column(92            Layout(name='right_upper', size=11),93            Layout(name='right_lower'),94        )95        GENERAL = r''' ââââââ  âââââââ âââ    ââ âââââââ ââââââ   âââââ  ââ96ââ       ââ      ââââ   ââ ââ      ââ   ââ ââ   ââ ââ    97ââ   âââ âââââ   ââ ââ  ââ âââââ   ââââââ  âââââââ ââ    98ââ    ââ ââ      ââ  ââ ââ ââ      ââ   ââ ââ   ââ ââ     99 ââââââ  âââââââ ââ   ââââ âââââââ ââ   ââ ââ   ââ âââââââ'''100        self.layout['right_upper'].update(101            Align(Padding(Panel(GENERAL, box=box.SQUARE, style='white', border_style='black'), (4, 0, 0, 0)),102                  align='center'))103104        self.layout['content_bottom'].split_column(105            Layout(name='content_bottom_title', size=8),106            Layout(name='content_bottom_notes'),107        )108        NOTES = r'''109 _   _  ___ _____ _____ ____  110| \ | |/ _ |_   _| ____/ ___| 111|  \| | | | || | |  _| \___ \ 112| |\  | |_| || | | |___ ___) |113|_| \_|\___/ |_| |_____|____/ 114            115'''116        self.layout['content_bottom_title'].update(117            Align(Panel(NOTES,118                        box=box.SQUARE,119                        border_style='black'120                        ),121                  align='center'122                  )123        )124125        self.layout['bottom'].split_row(126            Layout(name='bottom_left'),127            Layout(name='bottom_mid'),128            Layout(name='bottom_right'),129        )130131    def render_header(self):132        self.layout['top_left'].update(Align(Panel(self.score_prio,133                                                   box=box.SQUARE),134                                             align='center'))135        self.layout['top_mid'].update(Align(Panel(self.gen_logo(),136                                                  box=box.SQUARE,137                                                  style='black'),138                                            align='center'))139        self.layout['top_right'].update(Align(Panel(self.score_total,140                                                    box=box.SQUARE),141                                              align='center'))142143    def gen_logo(self):144        """145        Returns STARBOARD written logo with letters in randomized colors.146        Selects from 15 terminal standard colors (excluding black).147        """148        COLORS = ['red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white',149                  'bright_black', 'bright_red', 'bright_green', 'bright_yellow', 'bright_blue', 'bright_magenta',150                  'bright_cyan', 'bright_white']151        logo = list('STARBOARD')152        for letter in logo:153            i = logo.index(letter)154            logo = logo[:i] + [f'[{random.choice(COLORS)}]{letter}'] + logo[i + 1:]155        return ' '.join(logo)156157    def render_table_daily(self):158        table = Table(box=box.SQUARE,159                      leading=True, highlight=False,160                      header_style='black on white',161                      style='black')162        for column in self.daily_data['row_0']:163            table.add_column(column, justify='center')164        # check that the table contains rows below the header row165        if len(self.daily_data) > 1:166            for i in range(1, len(self.daily_data)):167                # format fields from row based on content168                # is status cell matches pattern_inprogress, highlight text169                if self.pattern_inprogress.match(self.daily_data[f'row_{i}'][3]):170                    task_num = "[bright_white]" + self.daily_data[f'row_{i}'][0]171                    description = "[bright_white]" + self.daily_data[f'row_{i}'][1]172                elif self.pattern_closed.match(self.daily_data[f'row_{i}'][3]):173                    task_num = "[dim]" + self.daily_data[f'row_{i}'][0]174                    description = "[dim]" + self.daily_data[f'row_{i}'][1]175                # if status cell matches pattern_open or no pattern, no changes to format176                else:177                    task_num = self.daily_data[f'row_{i}'][0]178                    description = self.daily_data[f'row_{i}'][1]179180                # format prio cell181                prio = self.format_prio(self.daily_data[f'row_{i}'][2], self.daily_data[f'row_{i}'][3])182183                table.add_row(184                    task_num,185                    description,186                    prio,187                    self.convert_status_code(self.daily_data[f'row_{i}'][3]),188                )189        else:190            table.add_row(None, '[purple]No task available', None, None)191192        self.layout['left_lower'].update(Align(table, align='center', vertical='top'))193194    def render_table_general(self):195        table = Table(box=box.SQUARE,196                      leading=True, highlight=False,197                      header_style='black on white',198                      style='black')199        for column in self.general_data['row_0']:200            table.add_column(column, justify='center')201        # check that the table contains rows below the header row202        if len(self.general_data) > 1:203            for i in range(1, len(self.general_data)):204                # format fields from row based on content205                # is status cell matches pattern_inprogress, highlight text206                if self.pattern_inprogress.match(self.general_data[f'row_{i}'][3]):207                    task_num = "[bright_white]" + self.general_data[f'row_{i}'][0]208                    description = "[bright_white]" + self.general_data[f'row_{i}'][1]209                elif self.pattern_closed.match(self.general_data[f'row_{i}'][3]):210                    task_num = "[dim]" + self.general_data[f'row_{i}'][0]211                    description = "[dim]" + self.general_data[f'row_{i}'][1]212                # if status cell matches pattern_open or no pattern, no changes to format213                else:214                    task_num = self.general_data[f'row_{i}'][0]215                    description = self.general_data[f'row_{i}'][1]216217                # format prio cell218                prio = self.format_prio(self.general_data[f'row_{i}'][2], self.general_data[f'row_{i}'][3])219220                table.add_row(221                    task_num,222                    description,223                    prio,224                    self.convert_status_code(self.general_data[f'row_{i}'][3]),225                )226        else:227            table.add_row(None, '[purple]No task available', None, None)228229        self.layout['right_lower'].update(Align(table, align='center'))230231    def render_notes(self):232        """233        Updates the table in the layout object based on the notes_data attribute.234235        Use get_notes() to update the data before updating the table.236        """237        table = Table(box=box.SQUARE,238                      highlight=False,239                      show_header=False,240                      border_style='black',241                      )242        table.add_column('notes', justify='center')  # omitted243        if len(self.notes_data) > 0 and self.notes_data[f'row_0'][0] != '':244            for i in range(0, len(self.notes_data)):245                table.add_row(self.notes_data[f'row_{i}'][0])246                # do not print a divider after the last row247                if i == len(self.notes_data) - 1:248                    break249                table.add_row('[dim]ââ' * 10)250251        self.layout['content_bottom_notes'].update(Align(table, align='center'))252253    def render_footer(self, _time: float):254        self.layout['bottom_left'].update(255            Align(256                Panel(f'Uptime: {datetime.now().replace(microsecond=0) - self.boot_time}',257                      box=box.SQUARE),258                align='center'))259        self.layout['bottom_mid'].update(260            Align(261                Panel(262                    f'Updated at [bright_cyan]{datetime.now().strftime("%H:%M:%S")}[/bright_cyan] in [cyan]{_time:.2f}[/cyan]s',263                    box=box.SQUARE),264                align='center'))265        self.layout['bottom_right'].update(266            Align(267                Panel(f'v{__VERSION__}', box=box.SQUARE, style='bright_black'), align='center'))268269    def get_data(self, _type=None):270        """271        Refreshes the data data from Notion API into the dashboard object and272        returns the update time.273274        Refreshes the daily or general task table data and275        corresponding dashboard element depending on the argument provided.276        """277        time_start = time.time()278        if _type == 'daily':279            url = f"https://api.notion.com/v1/blocks/{User.daily_block_id}/children?page_size=100"280        elif _type == 'general':281            url = f"https://api.notion.com/v1/blocks/{User.general_block_id}/children?page_size=100"282        else:283            print('"type" argument has to be one of ["daily", "general"]')284            sys.exit(1)285286        headers = {287            "Accept": "application/json",288            "Notion-Version": "2022-02-22",289            "Authorization": User.access_token,290        }291292        response = requests.request("GET", url, headers=headers)293294        _json = json.loads(response.text)295        table_rows = _json['results']296        table_content = {}297        for i in range(0, len(table_rows), 1):298            row = table_rows[i]['table_row']['cells']299            table_content[f'row_{i}'] = []300            for cell in row:301                table_content[f'row_{i}'].append(cell[0]['plain_text'])302        if _type == 'daily':303            self.daily_data = table_content304        elif _type == 'general':305            self.general_data = table_content306        time_end = time.time()307        return time_end - time_start308309    def get_notes(self):310        """311        Refreshes the notes data from Notion API in the dashboard object and312        returns the update time313        """314        time_start = time.time()315        url = f"https://api.notion.com/v1/blocks/{User.notes_block_id}/children?page_size=100"316317        headers = {318            "Accept": "application/json",319            "Notion-Version": "2022-02-22",320            "Authorization": User.access_token,321        }322323        response = requests.request("GET", url, headers=headers)324325        _json = json.loads(response.text)326        table_rows = _json['results']327        table_content = {}328        for i in range(0, len(table_rows), 1):329            row = table_rows[i]['table_row']['cells']330            table_content[f'row_{i}'] = []331            # check for empty table332            if len(row[0]) == 0:333                table_content[f'row_{i}'].append('[bright_black]Nothing here to see')334                break335            for cell in row:336                table_content[f'row_{i}'].append(cell[0]['plain_text'])337        self.notes_data = table_content338        time_end = time.time()339        return time_end - time_start340341    def get_score(self):342        # total score343        opened = 0344        closed = 0345        # get daily346        for i in range(1, len(self.daily_data), 1):347            if bool(self.pattern_closed.match(self.daily_data[f'row_{i}'][3])):348                closed += 1349            else:350                opened += 1351        # get general352        for i in range(1, len(self.general_data), 1):353            if bool(self.pattern_closed.match(self.general_data[f'row_{i}'][3])):354                closed += 1355            else:356                opened += 1357        n_total = opened + closed358        if closed == n_total:359            self.score_total = '[bright_green]                ALL DONE                '360        else:361            self.score_total = str(gen_progress_bar(closed, n_total))362363        # prio score364        opened = 0365        closed = 0366        # get daily prio 1's367        for i in range(1, len(self.daily_data), 1):368            if self.daily_data[f'row_{i}'][2] == '1':369                if bool(self.pattern_closed.match(self.daily_data[f'row_{i}'][3])):370                    closed += 1371                else:372                    opened += 1373        # get general prio 1's374        for i in range(1, len(self.general_data), 1):375            if self.general_data[f'row_{i}'][2] == '1':376                if bool(self.pattern_closed.match(self.general_data[f'row_{i}'][3])):377                    closed += 1378                else:379                    opened += 1380381        if opened == 0:382            self.score_prio = 'PRIO [bright_green]ALL DONE'383        else:384            self.score_prio = str(gen_progress_bar(closed, opened + closed, length=10, prefix='PRIO'))385386    def convert_status_code(self, status_field):387        """388        Converts status codes received from Notion (Status column field) to full code + color if matched with pattern.389        If no pattern is matched, code will be output dimmed.390391        :return:392        Full colored status code according to matched pattern.393        """394        if self.pattern_open.match(status_field):395            return "[bright_yellow]open"396        elif self.pattern_inprogress.match(status_field):397            return "[bright_magenta]in progress"398        elif self.pattern_closed.match(status_field):399            return "[green]closed"400        else:401            return "[dim]" + status_field402403    def format_prio(self, prio_field, row_status):404        """405        Converts Notion prio codes (Prio column field) color.406        If none of [1, 2, 3] field will be output dimmed.407408        :return:409        Colored prio code.410        """411        # format based on status code412        # open413        if self.pattern_open.match(row_status):414            # if prio == 1, then red number (prio in column index 2)415            if prio_field == '1':416                prio = '[red]1'417            # else normal number color418            else:419                prio = prio_field420        # in progress421        if self.pattern_inprogress.match(row_status):422            # if prio == 1, then bright red number423            if prio_field == '1':424                prio = '[bright_magenta]1'425            # else bright white number color426            else:427                prio = "[bright_white]" + prio_field428        # closed429        elif self.pattern_closed.match(row_status):430            # if prio == 1, then dim red number431            if prio_field == '1':432                prio = "[dim][red]1"433            # else dim (white) number color434            else:435                prio = "[dim]" + prio_field436        return prio437438439def gen_progress_bar(iteration, total, prefix='', suffix='', decimals=1, length=40, fill='â'):440    # https://stackoverflow.com/questions/3173320/text-progress-bar-in-terminal-with-block-characters441    percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))442    filledLength = int(length * iteration // total)443    bar = fill * filledLength + '-' * (length - filledLength)444    return f'\r{prefix} |{bar}| {percent}% {suffix}'445446447def re_patterns():448    """449    Compiles and returns regex patterns for matching of status codes450    """451    pattern_open = re.compile(r"[o|O]p?e?n?\Z")452    pattern_inprogress = re.compile(r"[i|I]n?\s?[p|P]r?o?g?r?e?s?s?\Z")453    pattern_closed = re.compile(r"[c|C]l?o?s?e?d?\Z")454    return pattern_open, pattern_inprogress, pattern_closed455456457def connection_error():458    console.clear()459    console.rule('[red]ERROR')460    console.print("ConnectionError: Failed to establish a new connection.")461    console.rule()462    console.print('retry in 30s')463    time.sleep(30)464    sys.exit()465466467def usr_interrupt():468    console.clear()469    _input = Prompt.ask('Refresh or exit?', console=console, choices=['r', 'e'], default='r')470    if _input == 'e':471        sys.exit(0)472    else:
...KPI_CSV_Report.py
Source:KPI_CSV_Report.py  
1# usr/bin/Python2# -*- coding:utf-8 -*-34import re5import os6import csv7import time8from collections import OrderedDict91011# pattern to clean up the original log12pattern_line_URL = "(?i)OpenInternalII,\s+\d*,\s+URL:(.*)"13pattern_line_AutoTest = "(?i)\[Plugin\s+Auto\s+Test\](.*)"14pattern_line_open = "(?i)\s*(VOCommonPlayerImpl::open,\s+\d*,\s+\[Open\]\s+call\s+open\s+\@)"15pattern_line_render = "(?i)\s*(gonna\s+to\s+be\s+rendered)"16pattern_line_seek = "(?i)\s*(VOCommonPlayerImpl::SetPosition,\s+\d*,\s+\[SEEK\])"17pattern_line_switch = "(?i)\s*(voOSMediaPlayer::CommitSelection)"18pattern_line_AdaptiveStream = "(?i)\s*(\[Video\]\s+size\s+changed\s+\@)"19pattern_line_Pause = "(?i)\s*(Pause\s+Use\s+time:)"20pattern_line_Resume = "(?i)\s*(\[start\]\s+playback\s+start\s+\@)"2122# pattern to parse the target data23pattern_Open = "(?i)\s*(open,\s+\d*,\s+\[Open\]\s+call\s+open)\s+\@\s+(\d*)"24pattern_Complete = "(?i)\s*(\[Audio\]\s+gonna\s+to\s+be\s+rendered\s+\@)\s+(\d*)"25pattern_Seek = "(?i)\s*(\[SEEK\]\s+\@)\s+(\d*)"26pattern_SeekComplete = "(?i)(\[SEEK\]\s+\@).*?(\[Audio\]\s+gonna\s+to\s+be\s+rendered\s+\@)\s+(\d*)"27pattern_SetAudio = "(?i)(\[Commit\s+selected\s+audio\s+\d*\s+\]\s+\@)\s+(\d*)"28pattern_SetAComplete = "(?i)(\[Commit\s+selected\s+audio\s+\d*\s+\]\s+\@).*?(\[Audio\]\s+gonna\s+to\s+be\s+rendered\s+\@)\s+(\d*)"29pattern_AdaptiveStart = "(?i)(\[Video\]\s+gonna\s+to\s+be\s+rendered\s+\@)\s+(\d*)"30pattern_AdaptiveEnd = "(?i)(\[Video\]\s+gonna\s+to\s+be\s+rendered\s+\@).*?(\[Video\]\s+size\s+changed\s+\@)\s+(\d*)"31pattern_Pause = "(?i)(Pause\s+Use\s+time):(\d*)"32pattern_ResumeStart = "(?i)(\[start\]\s+playback\s+start\s+\@)\s+(\d*)"33pattern_ResumeEnd = "(?i)\s*(\[Audio\]\s+gonna\s+to\s+be\s+rendered\s+\@)\s+(\d*)"3435# -*- No event called "[Commit selected subtitle]" within log -2014/08/1236pattern_SetSubtitle = "(?i)\s*(\[Commit\s+selected\s+subtitle\s+\d+\s+\]\s+\@)\s+(\d*)"37pattern_SetSComplete = "(?i)(\[Commit\s+selected\s+subtitle\s+\d*\s+]\s+\@).*?(\[Audio\]\s+gonna\s+to\s+be\s+rendered\s+\@)\s+(\d*)"3839ScenarioCol = "Test Scenario"40clipName = "Clip Name"41TimeCol = "Performance Test Result"4243scenarios_log_list = [44    "Play Live TV",45    "Zapping Live TV",46    "Play VOD",47    "Seek in VOD",48    "Set Audio in VOD",49    "Set Subtitle in VOD",50    "Play VOD from bookmark",51    "Set Audio in NTS",52    "Set Subtitle in NTS",53    "Adaptive Stream Show"54]5556scenarios_list = [57    "Play Live TV",58    "Zapping Live TV",59    "Play VOD",60    "Seek in VOD-Forward",61    "Seek in VOD-Backward",62    "Set Audio in VOD",63    "Set Subtitle in VOD",64    "Play VOD from bookmark",65    "Set Audio in NTS",66    "Set Subtitle in NTS",67    "Adaptive Stream Show",68    "Pause in VOD",69    "Play after Pause in VOD"70]7172def sortFile(originalLog, newLog):73    """74    To generate a new log based on original log per the latter maybe too big to cause error75    NB: This is function cost much time in order to shorten the log size76    """77    fs = open(originalLog, 'rb')78    try:79        if os.path.exists(newLog):80            fs1 = open(newLog, 'a+b')81        else:82            fs1 = open(newLog, 'wb')83    except Exception as e:84        print("**********", e)8586    while True:87        line = fs.readline()88        if not line:89            break90        else:91            p = re.compile(pattern_line_URL + "|" + pattern_line_open + "|" + pattern_line_render + "|" + pattern_line_seek + "|" + pattern_line_switch + "|" + pattern_line_AdaptiveStream + "|" + pattern_line_Pause + "|" + pattern_line_Resume)92            result = p.search(line)93            if result:94                # print line95                fs1.write(line)96            else:97                continue98    fs.close()99    fs1.close()100101def updateFile(newLog, updatedLog):102    """103    To reverse the order of these 2 lines:104    15:19:09.037 @@@VOLOG, ... cosmpengnwrap.cpp, COSMPEngnWrap::Open, 459, [Open] @ 350015264105    15: 19:09.057 @@@VOLOG, ... voAdaptiveStreamingController::OpenInternalII, 480, URL:http://10.2.68.24/ericsson/UTC/11/index.m3u8106    """107    try:108        fsi = open(updatedLog, 'wb')109        fso = open(newLog, 'rb')110    except Exception as e:111        print("**********", e)112113    t_line = ""114    sid = 0115    while True:116        line = fso.readline()117        if not line:118            break119        else:120            p1 = re.compile(pattern_line_open)121            p2 = re.compile(pattern_line_URL)122123            result1 = p1.search(line)124            result2 = p2.search(line)125            if result1:126                t_line = line127                continue128            elif result2:129                fsi.write("[Plugin Auto Test]" + scenarios_log_list[sid] + os.linesep)130                fsi.write(line + t_line)131                t_line = ""132                sid += 1133            else:134                fsi.write(line)135    fso.close()136    fsi.close()137138def segmentLog_URL(logfile):139    """140    Put the test data (as value) and test clip (as key) into a dictionary141    """142    segment_mark = pattern_line_URL143    tempList = []144    logDict = OrderedDict([])145    fs = open(logfile)146    increment = 0147148    for line in reversed(fs.readlines()):149        tempList.append(line)150        result = re.search(segment_mark, line)151        if result:152            tempList.reverse()153            dictKey = result.group(1)154            if dictKey in list(logDict.keys()):155                increment += 1156                dictKey = dictKey + "^" + str(increment)157            logDict[dictKey] = tempList158            tempList = []159        else:160            continue161    # print logDict162    fs.close()163    mitems = list(logDict.items())164    mitems.reverse()165    return OrderedDict(mitems)166167def getClips():168    dict = segmentLog_URL('KPI_log_1')169    clip_list = []170    mitems = list(dict.items())171172    inc = 0173    for ky in list(OrderedDict(mitems).keys()):174        if inc == 3:175            # The test clip is used for the 2 seek operation in scenario: 'Seek in VOD'176            clip_list.append(ky.split("^")[0])177        elif inc == (len(scenarios_log_list) - 1):178            clip_list.append(ky.split("^")[0])179            clip_list.append(ky.split("^")[0])180        clip_list.append(ky.split("^")[0])181        inc += 1182183    return clip_list184185def segmentLog_SC(logfile):186    """187    Put the test data (as value) and test scenario (as key) into a dictionary188    """189    segment_mark = pattern_line_AutoTest190    tempList = []191    logDict = OrderedDict([])192    fs = open(logfile)193194    for line in reversed(fs.readlines()):195        tempList.append(line)196        result = re.search(segment_mark, line)197        if result:198            tempList.reverse()199            dictKey = result.group(1)200            logDict[dictKey] = tempList201            tempList = []202        else:203            continue204    # print logDict205    fs.close()206    mitems = list(logDict.items())207    mitems.reverse()208    return OrderedDict(mitems)209210# Get the target data211def get_list():212    result_list = []213    for k, v in list(segmentLog_SC('KPI_log_1').items()):214        # print k, v215        if str(k) in scenarios_log_list[0]:216            result1 = re.search(pattern_Open, str(v))217            result2 = re.search(pattern_Complete, str(v))218            if result1 and result2:219                # print result1.groups()220                # print result2.groups()221                # print int(result2.groups()[-1]) - int(result1.groups()[-1])222                result_list.append(int(result2.groups()[-1]) - int(result1.groups()[-1]))223            else:224                result_list.append(None)225                result_list.append(None)226227        elif str(k) in scenarios_log_list[1]:228            result1 = re.search(pattern_Open, str(v))229            result2 = re.search(pattern_Complete, str(v))230            if result1 and result2:231                # print result1.groups()232                # print result2.groups()233                # print int(result2.groups()[-1]) - int(result1.groups()[-1])234                result_list.append(int(result2.groups()[-1]) - int(result1.groups()[-1]))235            else:236                result_list.append(None)237238        elif str(k) in scenarios_log_list[2]:239            result1 = re.search(pattern_Open, str(v))240            result2 = re.search(pattern_Complete, str(v))241            if result1 and result2:242                # print result1.groups()243                # print result2.groups()244                # print int(result2.groups()[-1]) - int(result1.groups()[-1])245                result_list.append(int(result2.groups()[-1]) - int(result1.groups()[-1]))246            else:247                result_list.append(None)248249        elif str(k) in scenarios_log_list[3]:250            result1 = re.findall(pattern_Seek, str(v))251            result2 = re.findall(pattern_SeekComplete, str(v), re.S)252            if result1 and result2:253                # print result1254                # print result2255                # print int(result2[0][-1]) - int(result1[0][-1])256                # print int(result2[1][-1]) - int(result1[1][-1])257                result_list.append(int(result2[0][-1]) - int(result1[0][-1]))258                result_list.append(int(result2[1][-1]) - int(result1[1][-1]))259            else:260                result_list.append(None)261                result_list.append(None)262263        elif str(k) in scenarios_log_list[4]:264            result1 = re.search(pattern_SetAudio, str(v))265            result2 = re.search(pattern_SetAComplete, str(v))266            if result1 and result2:267                # print result1.groups()268                # print result2.groups()269                # print int(result2.groups()[-1]) - int(result1.groups()[-1])270                result_list.append(int(result2.groups()[-1]) - int(result1.groups()[-1]))271            else:272                result_list.append(None)273274        elif str(k) in scenarios_log_list[5]:275            result1 = re.search(pattern_SetSubtitle, str(v))276            result2 = re.search(pattern_SetSComplete, str(v))277            if result1 and result2:278                # print result1.groups()279                # print result2.groups()280                # print int(result2.groups()[-1]) - int(result1.groups()[-1])281                result_list.append(int(result2.groups()[-1]) - int(result1.groups()[-1]))282            else:283                result_list.append(None)284285        elif str(k) in scenarios_log_list[6]:286            result1 = re.search(pattern_Seek, str(v))287            result2 = re.search(pattern_SeekComplete, str(v), re.S)288            if result1 and result2:289                # print result1.groups()290                # print result2.groups()291                # print int(result2.groups()[-1]) - int(result1.groups()[-1])292                result_list.append(int(result2.groups()[-1]) - int(result1.groups()[-1]))293            else:294                result_list.append(None)295296        elif str(k) in scenarios_log_list[7]:297            result1 = re.search(pattern_SetAudio, str(v))298            result2 = re.search(pattern_SetAComplete, str(v), re.S)299            if result1 and result2:300                # print result1.groups()301                # print result2.groups()302                # print int(result2.groups()[-1]) - int(result1.groups()[-1])303                result_list.append(int(result2.groups()[-1]) - int(result1.groups()[-1]))304            else:305                result_list.append(None)306307        elif str(k) in scenarios_log_list[8]:308            result1 = re.search(pattern_SetSubtitle, str(v))309            result2 = re.search(pattern_SetSComplete, str(v))310            if result1 and result2:311                # print result1.groups()312                # print result2.groups()313                # print int(result2.groups()[-1]) - int(result1.groups()[-1])314                result_list.append(int(result2.groups()[-1]) - int(result1.groups()[-1]))315            else:316                result_list.append(None)317318        else:319            result1 = re.search(pattern_AdaptiveStart, str(v))320            result2 = re.search(pattern_AdaptiveEnd, str(v), re.S)321            if result1 and result2:322                # print result1.groups()[-1]323                # print result2.groups()[-1]324                # print int(result2.groups()[-1]) - int(result1.groups()[-1])325                result_list.append(int(result2.groups()[-1]) - int(result1.groups()[-1]))326            else:327                result_list.append(None)328329            result1 = re.search(pattern_Pause, str(v))330            result2 = re.findall(pattern_ResumeStart, str(v))331            result3 = re.findall(pattern_ResumeEnd, str(v))332            if result1 and result2 and result3:333                # print result1.groups()[-1]334                # print result2.groups()[-1]335                # print result3.groups()[-1]336                # print int(result2[0][-1]) - int(result1[0][-1])337                # print int(result2[1][-1]) - int(result1[1][-1])338                result_list.append(int(result1.groups()[-1]))339                result_list.append(int(result3[1][-1]) - int(result2[1][-1]))340            else:341                result_list.append(None)342                result_list.append(None)343344    return result_list345346def getCurTime():347    mtime = time.strftime("%Y%m%d%H%M%S", time.localtime())348    return mtime349350def get_report(original_log, kpi_result):351352    # Update the log353    updateFile('KPI_log', 'KPI_log_1')354355    # Get the results: scenarios (as scenarios_list), test clips, time records356    clips = getClips()357    records = get_list()358359    res_list = []360    res_list.append(scenarios_list)361    res_list.append(clips)362    res_list.append(records)363    # print res_list364365    res_list = list(map(list, list(zip(*res_list))))366    # print res_list367368    # write result to CSV file369    new_dir = "temp/" + kpi_result[1] + "/" + getCurTime()370    os.makedirs(new_dir)371    csv_name = new_dir + "/" + str(kpi_result[0]) + "_KPI.csv"372    csvfile = file(csv_name, 'wb')373    writer = csv.writer(csvfile)374    writer.writerow([ScenarioCol] + [clipName] + [TimeCol])375376    for i in res_list:377        writer.writerow(i)378379    csvfile.close()380381    # delete the temporary log after report is generated382    os.remove("KPI_log")383384# if __name__ == "__main__":385#386#     # from KPI_UITest import executeTest_IE387#     # executeTest_IE()388#389    # logfile1 = "C:/ProgramData/VisualOn/BrowserPlugin/volog.log"390    # get_report(logfile1, ["Chrome", "3.13.0.7028"])
...html.py
Source:html.py  
1def wrap(div, content):2    return div + content + "</div>"3def size(width, height):4    return [dim("width", width), dim("height", height)]5def div(attributes):6    return "<div " + " ".join(attributes) + ">"7def style(elements):8    return 'style="' + ";".join(elements) + '"'9def dim(label, value, unit="px"):10    return "{}:{}{}".format(label, value, unit)11def add_style(style_attributes, content):12    return wrap(div([style(style_attributes)]), content)13import re14def format(html):15    nice = ""16    pattern_open = "<\w*\s+[^>]*\s*>"17    pattern_close = "</\w*>"18    pattern = "({}|{})".format(pattern_open, pattern_close)19    divs = re.split(pattern, html)20    divs = [re.sub("\n", "", d) for d in divs]21    divs = [ d for d in divs if re.search("[^\s]", d)]22    divs = [re.sub("^\s*|\s*$", "", d) for d in divs]23    indentations = 024    for d in divs:25        if is_close(d):26            indentations -= 127        nice += indent(d, indentations) + "\n"28        if is_open(d):29            indentations += 130    return nice31def is_open(div):32    return "<div" in div33def is_close(div):34    return "</" in div35def indent(text, levels):36    indentation = ""37    for i in range(levels):38        indentation += "    "...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
