(Full-Example-Report)= # Full Example Report Below you can find a full example report with plenty of comments detailing the inner workings and design philosophy of `basic-report`. ## Code ```python from basic_report import Report import datetime import tempfile import numpy as np import pandas as pd import matplotlib.pylab as plt from lorem_text import lorem from pathlib import Path #----------------------------------------------------------------------------------------------------------------------- # FAKE DATA PREPARATION #----------------------------------------------------------------------------------------------------------------------- errors = ['As most of the time you can use normal HTML', 'code to manipulate your error strings', 'You could probably even add tables and such', 'But this is not yet supported on an API level'] warnings = ['This is just one single warning'] info = ['This is just one info'] # Table data # 100 rows - 5 cols of random variables columns = ['COL 1', 'COL 2', 'COL 3', 'COL 4', 'COL 5'] table = np.random.rand(100, 5) table = pd.DataFrame(table, columns=columns) table.index.name = 'Index Name' #----------------------------------------------------------------------------------------------------------------------- # CREATING THE REPORT #----------------------------------------------------------------------------------------------------------------------- def make_report(): # Calling Report() prepares everything for the main page index.html r = Report( report_dir='output_dir', report_title='Example Report', report_date=datetime.date.today(), color_mode='light', config_file=None, text_color='slate', ) # First add the big report header. You don't have to do this if you just want to add plots, etc. r.add_report_header(color='forest') # Now we want to add the error/info/warning section which provides information about all the issues encountered r.add_header('Errors / warnings / info section') r.add_text('This is what the error/warning/info section looks like if there are no things to report on') r.add_error_warning_info_section(errors=[], warnings=[], info=[]) r.add_text('And this is the section when there are things to report on') r.add_error_warning_info_section(errors=errors, warnings=warnings, info=info) # You can adjust the color of many elements, e.g., headers and subheaders. You can also use standard HTML syntax # in your text, e.g., to provide a link to an external page. You can also choose your text alignment when adding # a text element r.add_header('Columns www.google.com', color='cherry') r.add_text(lorem.paragraph(), align='left', color='cherry') r.add_header('Columns www.google.com', color='ocean') r.add_text(lorem.paragraph(), align='center', color='ocean') r.add_header('Columns www.google.com', color='earth') r.add_text(lorem.paragraph(), align='right', color='earth') # The report class supports a variety of layout functions, which can also be nested. They all follow the same # principle: # 1) Open the layouter # 2) Add layout item # 3) Close layouter # Here's a column layouter with three columns as an example: r.add_header('Columns I, II, III', color='cappuccino') r.open_columns() r.add_column() r.add_header('Column I') r.add_text(lorem.paragraph(), align='left') r.add_column() r.add_header('Column II') r.add_text(lorem.paragraph(), align='right') r.add_column() r.add_header('Column III') r.add_text(lorem.paragraph()) r.close_columns() # You might want to add a sub-section with a slightly smaller header. The level defines the width of the section # header and ranges from 12 (widest header) to 1 (smallest header, which seems almost useless). The header will # adjust to its surroundings. I.e. if you are already in a column layouter with 3 columns sub_level 1 will only span # the column it is called in. You can further reduce the level of the content by putting it in a sublevel element r.add_sub_header('Sub header of level 10', sub_level=10) r.open_sublevel(size=10) r.add_text(lorem.paragraph()) r.close_sublevel() r.add_sub_header('Sub header of level 6', sub_level=6) r.open_sublevel(size=6) r.add_text(lorem.paragraph()) r.close_sublevel() # If you want to add a table you can do that easily by calling add_table. The data can either be a pandas DataFrame # or an array-like of array-likes. You can specify an array of formatters, one for every column. Or you can pass a # single formatter that is used on every column. If you pass a pandas dataframe the index will be the first column # and the formatter is automatically set to str. This default behavior might change in the future. If you pass a # list of lists the first row represents the table headers, so the formatters won't be applied to them. # There are some additional options you can enable for the table # 1) search: Adds a search box to the table # 2) page: Only shows 10 entries at a time (can be extended to 25, 50 or 100) # 3) info: Simply adds a text to the bottom of the table highlighting how many entries are currently shown and # how many there are in total # 4) no_sort: Disables initial sorting # 5) color_negative_values: Colors values below zero in red # 6) color_positive_values: Colors values greater than zero in green # 7) full_width: Use the full page width to display the table # You can also add a caption to the table. And you can adjust the width of the table using `size` and the alignment # of the cell content using `align` r.add_header('Large Table (color=cherry)', color='cherry') fmts = ['{:.1f}'.format, '{:2.0e}'.format, str, '{}'.format, '{:5.2e}'.format] r.add_table( table, options=['search', 'page', 'info'], formatters=fmts, caption='This is an example caption of a searchable table', ) # If no options are selected all data will be shown. So if you really like long tables you can still show them on # the report page. r.add_header('Smaller Table w/ alignment (color=sunrise)', color='sunrise') r.add_table( table.iloc[:5], formatters='{:.2f}'.format, caption='Small Table', align='left', size=8, ) # Just like the column layouter the tab layouter needs to be opened and closed to work. Just like every other # layouter it will automatically tell you to close the layout environment if you forget to do it. Once the tab # layouter is open you can add individual tabs again. Everything following an add_tab method will be displayed # within this particular tab r.add_header('How to use tabs') r.open_tabs() with tempfile.TemporaryDirectory() as tmp_dir: r.add_tab('Plot 1') plt.figure(figsize=(12,8)) plt.plot(np.arange(100), np.random.rand(100)) out_file = Path(tmp_dir) / 'plot1.png' plt.savefig(out_file) r.add_image(out_file) r.add_tab('Plot 2') plt.figure(figsize=(12,8)) plt.plot(np.arange(100), np.random.rand(100)) out_file = Path(tmp_dir) / 'plot2.png' plt.savefig(out_file) r.add_image(out_file) r.close_tabs() # As detailed above, the navbar layouter works just like the tabs one with one exception: When opening the layouter # you can actually select the location of the navbar pills, i.e., left, top, or right r.add_header('How to use tabs') r.add_header('Navbars') r.open_navbar(loc='top') r.add_navbar_item('Item 1') r.add_text(lorem.paragraph(), align='left') r.add_navbar_item('Item 2') r.add_text(lorem.paragraph()) r.add_navbar_item('Item With A Long Name') r.add_text(lorem.paragraph(), align='right') r.close_navbar() r.open_navbar(loc='left', color='ocean') r.add_navbar_item('Item 1') r.add_text(lorem.paragraph(), align='left') r.add_navbar_item('Item 2') r.add_text(lorem.paragraph()) r.add_navbar_item('Item With A Long Name') r.add_text(lorem.paragraph(), align='right') r.close_navbar() r.open_navbar(loc='right', color='cherry') r.add_navbar_item('Item 1') r.add_text(lorem.paragraph(), align='left') r.add_navbar_item('Item 2') r.add_text(lorem.paragraph()) r.add_navbar_item('Item With A Long Name') r.add_text(lorem.paragraph(), align='right') r.close_navbar() # Last but not least there are the accordions. They are again following the default layouter syntax r.add_header('Accordions') r.open_accordion() r.add_accordion_item('Show Lorem') r.add_text(lorem.paragraph()) r.add_accordion_item('Show Ipsum') r.add_text(lorem.paragraph()) r.add_accordion_item('Show Dolor') r.add_text(lorem.paragraph()) r.add_accordion_item('Show Table') r.add_table(table, size=12) r.close_accordion() # You can also add new pages to the report. This will not automatically switch the reporter to the newly created # page. So calling r.add_xyz still targets your old page. You can now either change the report to the new page or # reference it via key r.add_page('page2') r['page2'].add_header('This is page 2') r.set_current_page('page2') r.add_text(lorem.paragraph()) r.add_text(lorem.paragraph(), align='left') r.add_text(lorem.paragraph(), align='right') # You can add links between pages either locally or globally. Local links will appear where you add them. They are # plain old vanilla html links. Because of the way the reporter is set up this only works calling the reporter # object and it does not work calling the keyed page as the page object does not know about the other pages. r.add_local_link_to_page('main', 'Local link to main') # Global links on the other hand are listed in a toolbar right on top of the page. They are visible for all # subpages. You also have to include main in your link list as we don't include it as a default. Global links can # be added from any page as they will be added to every page at the end. r.add_global_link_to_page('main', 'This is a global link to main') r.add_global_link_to_page('page2', 'This is a global link to subpage 2') # And let's add another page r.add_page('page3') r.add_global_link_to_page('page3', 'Page 3') r['page3'].add_table(table) # Actually write the whole report to file r.dump() if __name__ == '__main__': make_report() ```