Package: rico
rico: rich content to HTML as easy as Doc(df, plot)ricois a Python package for creating HTML documents from rich content: dataframes, plots, images, markdown etc. It provides a high-level, easy-to-use API with reasonable defaults, as well as low-level access for better control.Usericoif you want to create an HTML document from objects created in a Python script.Withricoyou canavoid:Writing data to intermediate files or a database from a script.Loading data into a Jupyter notebook from intermediate files or a database.Using nbconvert or similar tools for creating HTML files.More on the topic:Pass pandas dataframe to notebook via nbconvert.Could Papermill pass an in-memory dataframe to a notebook?Installationpipinstallricoricohas no dependencies other than the standard Python packages.For Markdown support:installmarkdown-it-py,or installPython Markdown,or set your own Markdown renderer usingrico.set_config.DeprecatedOptional additional dependencies were required to support the following content types:Plots (rico[altair],rico[pyplot],rico[seaborn]).Markdown (rico[markdown]).Therico[complete]extra incudes all the dependencies above.They are no longer needed and will be removed in version 0.4.0.User guideTo get started withrico, take a look at the self-explanatoryexampleswith resulting HTML documents. The user guide contains a slightly more detailed explanation.Basic usagericoprovides both declarative and imperative style interfaces.Declarative style:importpandasaspdimportricodf=pd.DataFrame({"x":[2,7,4,1,2,6,8,4,7],"y":[1,9,2,8,3,7,4,6,5],},index=pd.Index(list("AAABBBCCC")),)plot=df.plot.scatter(x="x",y="y")doc=rico.Doc("Hello, World!",df,plot,title="My doc")Imperative style:doc=rico.Doc(title="My doc")doc.append("Hello, World!",df,plot)Also imperative style:doc=rico.Doc(title="My doc")doc.append("Hello, World!")doc.append(df)doc.append(plot)Mix-and-match:doc=rico.Doc("Hello, World!",df,title="My doc")doc.append(plot)SerializationSerialize the document to HTML usingstr(doc):withopen("doc.html","w")asf:f.write(str(doc))Implicit serialization:withopen("doc.html","w")asf:print(doc,file=f)Internally,str(doc)callsdoc.serialize()with default parameter values. Calldoc.serialize(indent=True)to indent the HTML element tree visually:withopen("doc.html","w")asf:f.write(doc.serialize(indent=True))Set custom whitespace for indentation using thespaceparameter:withopen("doc.html","w")asf:f.write(doc.serialize(indent=True,space="    "))Remove unnecessary whitespace by settingstriptoTrue:withopen("doc.html","w")asf:f.write(doc.serialize(strip=True))Control the default behavior ofstr(doc)anddoc.serialize()using the global optionsindent_html,indent_space, andstrip_html:withopen("doc.html","w")asf,rico.config_context(indent_html=True):f.write(str(doc))The default option values are:indent_html = False,indent_space = "  ",strip_html = False.Rich content typesricoautomatically recognizes the following content types:ricocontent classes (subclasses ofrico.ContentBase).Matplotlib Pyplot Plots.Dataframes and other types withIPython rich representation methods.Text.Use specific classes for plots and texts to change the default behavior:doc=rico.Doc(rico.Text("Hello, World!",mono=True),# The default value is False.df,rico.Plot(plot,format="png",bbox_inches="tight"),# The default value is "svg".title="My doc",)The following code gives the same result as the code above:doc=rico.Doc(title="My doc")doc.append_text("Hello, World!",mono=True)doc.append(df)doc.append_plot(plot,format="png",bbox_inches="tight")Some options can be set in the global configuration:withrico.config_context(text_mono=True,image_format="png"):doc=rico.Doc("Hello, World!",df,plot,title="My doc")Use specific classes and methods for other content types:Images:ImageorDoc.append_image.Code:CodeorDoc.append_code.Markdown*:MarkdownorDoc.append_markdown.HTML tag:TagorDoc.append_tag.Raw HTML:HTMLorDoc.append_html.*Installmarkdown-it-pyormarkdown, or define a custom Markdown renderer with themarkdown_rendererglobal option to useMarkdownorDoc.append_markdown.For example:doc=rico.Doc(rico.Markdown("## Dataframe"),df,rico.Tag("h2","Plot"),# An alternative way to add a header.plot,rico.HTML("<h2>Code</h2>"),# Another way to add a header.rico.Code("print('Hello, World!')"),title="My doc",)The following code gives the same result as the code above:doc=rico.Doc(title="My doc")doc.append_markdown("## Dataframe")doc.append(df)doc.append_tag("h2","Plot")doc.append(plot)doc.append_html("<h2>Code</h2>")doc.append_code("print('Hello, World!')")Check the docstrings for details.Serialize content to HTML usingstr(object)orobject.serialize():obj=rico.Tag("p","Hello, World!")print(obj)# <div><p>Hello, World!</p></div>print(obj.serialize(indent=True,space="    "))# <div>#     <p>Hello, World!</p># </div>Bootstrap, HTML classes and document layoutBy default,Bootstrapstyles are included in the document. Change the default behavior using thebootstrapparameter:doc=rico.Doc("Hello, World!",bootstrap="full")Setbootstrapto"css"(default) to include only CSS.Setbootstrapto"full"to include both the CSS and JS.Setbootstrapto"none"to not include Bootstrap*.*Keep in mind thatricorelies on Bootstrap classes and styles. For example:Themonoandwrapparameters of theTextclass use Bootstrap'sfont-monospaceandfont-monospaceclasses.rico's dataframe style definition uses Bootstrap variables.Each content element is wrapped in a<div>container. Specify the element's container class using theclass_parameter:print(rico.Tag("p","Hello, World!",class_="col"))# <div class="col"><p>Hello, World!</p></div>All elements' containers in the document are also wrapped in a<div>container. Specify the document's container class using theclass_parameter:doc=rico.Doc("Hello, World!",class_="container-fluid")Define the document layout using Bootstrap andDivclass:doc=rico.Doc(rico.Div(rico.Obj(df,class_="col"),rico.Obj(plot,class_="col"),class_="row row-cols-auto",))The code above creates a document with two columns, one with a dataframe and another with a plot. TheObjis a magic class which automatically determines the content type in the same way thatDocandDoc.appenddo.Another example:importaltairasaltdoc=rico.Doc(rico.Tag("h2","Dataframes"),rico.Div(rico.Obj(rico.Tag("h3","A"),df.loc["A",:],class_="col"),rico.Obj(rico.Tag("h3","B"),df.loc["B",:],class_="col"),rico.Obj(rico.Tag("h3","C"),df.loc["C",:],class_="col"),class_="row row-cols-auto",),rico.Tag("h2","Plots"),rico.Div(rico.Obj(rico.Tag("h3","A"),alt.Chart(df.loc["A",:]).mark_point().encode(x="x",y="y"),class_="col",),rico.Obj(rico.Tag("h3","B"),alt.Chart(df.loc["B",:]).mark_point().encode(x="x",y="y"),class_="col",),rico.Obj(rico.Tag("h3","C"),alt.Chart(df.loc["C",:]).mark_point().encode(x="x",y="y"),class_="col",),class_="row row-cols-auto",),title="Grid system",)The following code gives the same result as the code above:doc=rico.Doc(title="Grid system")doc.append_tag("h2","Dataframes")div1=rico.Div(class_="row row-cols-auto")doc.append(div1)forname,dataindf.groupby(df.index):div1.append(rico.Tag("h3",name),data,class_="col")doc.append_tag("h2","Plots")div2=rico.Div(class_="row row-cols-auto")doc.append(div2)forname,dataindf.groupby(df.index):div2.append(rico.Tag("h3",name),alt.Chart(data).mark_point().encode(x="x",y="y"),class_="col",)More on Bootstrap layout and grid system:BreakpointsContainersGrid systemColumnsStyles and scriptsBy default,ricoincludes the following styles in the document:Bootstrap CSS. Change the default behavior using thebootstrapparameter of theDocclass.Dataframe style. Change it by setting thedataframe_styleglobal option.Exclude dataframe style from the document by settingdataframe_styleto"":withrico.config_context(dataframe_style=""):doc=rico.Doc(df)Include custom styles and scripts using theStyleandScriptclasses:dark_theme="https://cdn.jsdelivr.net/npm/bootswatch@5/dist/darkly/bootstrap.min.css"jquery="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"doc=rico.Doc(rico.Text("Click me",class_="click"),extra_styles=(rico.Style(src=dark_theme),rico.Style(".click {color: yellow;}"),),extra_scripts=(rico.Script(src=jquery),rico.Script("$('p').on('click', function() {alert('Hello, World!');})",defer=True,),),)Thedeferparameter adds thedeferattribute to the<script>tag if thesrcparameter is used. Otherwise, if thetextparameter is used, the script is placed in the footer of the document.By default, external styles and scripts are included as file links. This means that these files must be available when someone opens the document. Include the contents of these files in the document using theinlineparameter:doc=rico.Doc(rico.Text("Click me",class_="click"),extra_styles=(rico.Style(src=dark_theme,inline=True),rico.Style(".click {color: yellow;}"),),extra_scripts=(rico.Script(src=jquery,inline=True),rico.Script("$('p').on('click', function() {alert('Hello, World!');})",defer=True,),),)In the example above, the Bootstrap styles are still included as a link. Use the global optionsinline_stylesandinline_scriptsto include the contents of the style and script files in the document:withrico.config_context(inline_styles=True,inline_scripts=True):doc=rico.Doc(rico.Text("Click me",class_="click"),extra_styles=(rico.Style(src=dark_theme),rico.Style(".click {color: yellow;}"),),extra_scripts=(rico.Script(src=jquery),rico.Script("$('p').on('click', function() {alert('Hello, World!');})",defer=True,),),)Keep in mind that style and script files can contain links to other external resources.ricodoesn't parse or change them, even if theinlineparameter or theinline_stylesandinline_scriptsglobal options are set toTrue. As a result:These resurces should be availble when someone opens an HTML document created byrico.Links with relative paths to external resources will not work.For example,Bootstrap Icons CSScontains linkes to fonts with relative paths:url("./fonts/bootstrap-icons.woff2?1fa40e8900654d2863d011707b9fb6f2"). Including this CSS file with theinlineparameter set toTruewill make these links invalid.Global configurationUse global configuration to:Get or set default parameter values.Get or set document properties.Get or set a markdown renderer method.The following global options define the default parameter values:Global optionParameterClasses, methods, functionsindent_htmlindentobj.serialize,serialize_htmlindent_spacespaceobj.serialize,serialize_htmlstrip_htmlstripobj.serialize,serialize_htmltext_monomonoText,obj.append_texttext_wrapwrapText,obj.append_textimage_formatformatPlot,obj.append_plotinline_stylesinlineStyleinline_scriptsinlineScriptThe following global options define document properties:meta_charsetdefines a documentcharsetmetadata. Set it to""to disable.meta_viewportdefines a documentviewportmetadata. Set it to""to disable.bootstrap_cssdefines a link to the Bootstrap CSS file.bootstrap_jsdefines a link to the Bootstrap JS file.dataframe_styledefines a dataframe style. Set it to""to disable.Themarkdown_rendererglobal option defines a callable that converts Markdown to HTML. It should accept a Markdown string as the first argument and return HTML as a string. The default value is defined as follows:If themarkdown_itmodule can be imported, then the default value ismarkdown_it.MarkdownIt().render.Otherwise, if themarkdownmodule can be imported, then the default value ismarkdown.markdown.Otherwise, the default value isNone. In this case, callingrico.Markdownorobj.append_markdownwill throw an error.Get a dictionary with global options usingget_configwithout parameters:global_config=rico.get_config()print(global_config["indent_html"])# FalseGet a global option value usingget_configwith the option name as a parameter:print(rico.get_config("indent_html"))# FalseSet a global option value usingset_config:rico.set_config(indent_html=True)print(rico.get_config("indent_html"))# Truerico.set_config(indent_html=False)Set a global option value within a context usingconfig_context:withrico.config_context(indent_html=True):print(rico.get_config("indent_html"))# Trueprint(rico.get_config("indent_html"))# FalseLow-level controlInternally,ricouses the standardxml.etree.ElementTreemodule:Every content object (Tag,Text,Divetc.) has acontainerattribute of typexml.etree.ElementTree.Element. The value is a<div>container element.Docobjects has additional attributeshtml,head, andbodyof typexml.etree.ElementTree.Element. They represent the<html>,<head>, and<body>elements, respectively.Access these attributes and usexml.etree.ElementTreeAPI to gain low-level control over the document and its elements.Also,ricoprovides the following functions for working withxml.etree.ElementTree.Elementobjects:parse_htmlparses HTML from a string.indent_htmlindents an HTML element tree visually.strip_htmlremoves unnecessary whitespace.serialize_htmlserializesxml.etree.ElementTree.Elementobject.Check the docstrings for details.AlternativesUseJupyter Notebookfor interactive computing.Usenbconvertorpapermillif you're processing data and creating objects for a document in a Jupyter notebook.UseQuartoif you prefer R Markdown style notebooks and a variety of output formats.Usexml.etree.ElementTree,lxml,Yattag, orAiriumif you need low-level control.RoadmapSupport math equations withMathJaxand/orKaTeX.Support PDF content.Create docs withMkDocsandMaterial for MkDocs.