Filters
Filters are used in template rendering. They are defined in filters.py
and
can be used in the template files.
datatable
Read data from a file, using pandas.read_csv() and make it to json so
js can handle it and render it with <DataTable />
-
Args:
path
(PathLike): The path to the data file.*args
(Any): Additional positional arguments to pass to pandas.read_csv().ncols
(Union[int, Iterable], optional): Either the number of columns to select or an iterable of column indices or names. Defaults to None.nrows
(Union[int, Iterable], optional): Either the number of rows to select or an iterable of row indices. Defaults to None.double_precision
(int, optional): The precision for double numbers. See also pandas.DataFrame.to_json(). Defaults to 4.excluded
(set, optional): A set of column names to exclude from the resulting DataFrame. Defaults to None.**kwargs
(Any): Additional keyword arguments to pass to pandas.read_csv().- Note that
sep
is set to"\t"
instead of,
by default.
-
Returns:
str
: A JSON format of the data. -
Examples:
<DataTable data="{{ '/path/to/data.tsv' | datatable: nrows=10) }}" />
<DataTable data="{{ '/path/to/data.tsv' | datatable: nrows=10, excluded={'col1', 'col2'}) }}" />
render_job
Generate the svelte
components for a job.
-
Args:
job
(Mapping[str, Any]): The job object used to render the template.report_file
(str): Absolute path to a report file or relative tojob.outdir
h
(int): The starting level of the headers
-
Examples:
A json should be defined at
<job.outdir>/report.json
for the report structure:{ "h1": { "h2": { "h3": { "ui": [ { "kind": "datatable", "src": "data.tsv" }, # more components ] } } } }
The
h2
andh3
are optional. You can set them to#xxx
to letpipen-report
to ignore them. Sameh2
s are also supported. You can use#<suffiex>
to make them different. For example,Heading2#1
andHeading2#2
to have twoh2
with the same name under the sameh1
.For details of
ui
and components, see following sections.
render_ui
Render a set of components with a certain ui
layout.
In the report.json
file, under h3
, you should specify a dict with ui
keys, which defined a large set of components. Supported ui
s are:
flat
: The components will be rendered sequentially.tabs
: The components will be rendered as tabs. Each component should be withkind
"tab"
. If not specified,kind = "tab"
will be added automatically.table_of_images
: The components will be rendered as a table of images. Each component should be withkind
"table_image"
. If not specified,kind = "image"
will be added automatically. You can specify the number of columns liketable_of_images:3
. The default number of columns is 2.accordion
: The components will be rendered as an accordion. Each component should be withkind
"accordion"
. If not specified,kind = "accordion"
will be added automatically.
This can also be used as a filter in the template files by passing a json object and the ui
:
-
Args:
contents
(List[Mapping[str, Any]]): The contents of components to render.ui
(str): Theui
layout to render.job
(Mapping[str, Any]): The job object used to render the template.level
(int): The indent level of the components. Defaults to 0.
UI: flat
A flat
ui will render the components sequentially.
<Component1 />
<Component2 />
<Component3 />
<!-- ... -->
UI: tabs
A tabs
ui will render the components as tabs. See also the Tabs
component of carbon-components-svelte
.
<Tabs>
<Tab label="Component1" />
<Tab label="Component2" />
<Tab title="Component3" />
<svelte:fragment>
<TabContent>
<ui of Component1 />
</TabContent>
<TabContent>
<ui of Component2 />
</TabContent>
<TabContent>
<ui of Component3 />
</TabContent>
</svelte:fragment>
</Tabs>
See also Component: `tab
for how each component is rendered.
UI: table_of_images
A table_of_images
ui will render the components as a table of images.
<div class="pipen-report-table-of-images" style="grid-template-columns: repeat(2, auto); ">
<div>
<!-- A tab_image component -->
<Descr title="Image 2" class="pipen-report-table-image-descr">This is a description about the image.</Descr>
<Image src="placeholder.png"
class="pipen-report-table-image"
width={ 526 }
height={ 360 } />
<!-- end of tab_image component -->
</div>
<div>
<Descr title="Image 3" class="pipen-report-table-image-descr">This is a description about the image.</Descr>
<Image src="placeholder.png"
class="pipen-report-table-image"
width={ 526 }
height={ 360 } />
</div>
</div>
See also Component: table_image
for how each component is rendered.
UI: accordion
A accordion
ui will render the components as an accordion. See also the Accordion
component of carbon-components-svelte
.
<Accordion>
<AccordionItem title="title of Component1">
<ui of Component1 />
</AccordionItem>
<AccordionItem title="title of Component2">
<ui of Component2 />
</AccordionItem>
<AccordionItem title="title of Component3">
<ui of Component3 />
</AccordionItem>
</Accordion>
See also Component: accordion
for how each component is rendered.
render_component
Each component of the ui
should be rendered with this filter.
-
Args:
component
(Mapping[str, Any]): The component to render.job
(Mapping[str, Any]): The job object used to render the template.level
(int): The indent level of the components. Defaults to 0.
Component: accordion
Full configuration of an accordion
item:
{
"kind": "accordion", # When under an `accordion` ui, this can be omitted
"title": "title of the accordion",
"ui": "flat", # The ui of the components under this accordion item
"contents": [ ... ] # The components to render under this accordion item using the `ui`
}
This will be rendered as:
<AccordionItem title="title of the accordion">
<ui of the components under this accordion item using the `ui` />
</AccordionItem>
Component: descr
Full configuration of a descr
component:
{
"kind": "descr",
"title": "title of the descr", # or use key `name`
"content": "The description content", # or use key `descr`
}
This will be rendered as:
<Descr title="title of the descr">The description content</Descr>
Component: error
Full configuration of an error
component:
{
"kind": "error",
"content": "The error content",
"kind_": "warning", # use the warning style by default
# more props passed to InlineNotification
}
This will be rendered as:
<InlineNotification kind="warning">The error content</InlineNotification>
See also the InlineNotification
component of carbon-components-svelte
.
Component: list
Render a list of items. Full configuration of a list
component:
{
"kind": "list",
"items": [
"item1",
"item2",
"item3",
# ...
],
"ordered": False, # Whether to render an ordered list (OrderedList)
}
This will be rendered as:
<UnorderedList>
<ListItem>item1</ListItem>
<ListItem>item2</ListItem>
<ListItem>item3</ListItem>
<!-- ... -->
</UnorderedList>
Component: table
Render a data table. Full configuration of a table
component:
{
"kind": "table",
# Arguments passed to pandas.read_csv()
# See datatable filter for details
# If path is not specified, `src` will be used
"data": {},
# The path to the data file
# You can set to False, so that download the datafile is disabled
# If so, you need to set path in `data` to let the datatable filter to read the data
"src": "/path/to/data.tsv",
# Other arguments passed to DataTable
}
This will be rendered as:
<DataTable data={ [ ... ] } />
See also the DataTable
component of carbon-components-svelte
.
Component: image
Render an image. Full configuration of an image
component:
{
"kind": "image",
"src": "/path/to/image.png", # The path to the image file
"width": 526, # The width of the image
"height": 360, # The height of the image
# Other arguments passed to Image
}
This will be rendered as:
<Image src="/path/to/image.png" width={ 526 } height={ 360 } />
The width
and height
are optional. If not specified, the size will be obtained from the image file using pillow
. This is useful for the loading placeholder to have the same size as the image.
Component: table_image
Render a table of images. Full configuration of a table_image
component:
{
"kind": "table_image",
"src": "/path/to/image.png", # The path to the image file
"name": "Image 1", # The name of the image
"descr": "This is a description about the image.", # The description of the image
# Other arguments passed to Image
}
This will be rendered as:
<div>
<Descr title="Image 1" class="pipen-report-table-image-descr">
This is a description about the image.
</Descr>
<Image src="placeholder.png"
class="pipen-report-table-image"
width={ 526 }
height={ 360 } />
</div>
Component: tab
Render a tab. Full configuration of a tab
component:
{
"kind": "tab",
"label": "label of the tab", # or use key `name` or `title`
"ui": "flat", # The ui of the components under this tab
"contents": [ ... ] # The components to render under this tab using the `ui`
}
This will be rendered as a tuple of Tab
and TabContent
:
<Tab label="label of the tab" />
<!-- and -->
<TabContent>
<ui of the components under this tab using the `ui` />
</TabContent>
See also the Tabs
component of carbon-components-svelte
.
Component: tag
You can also directly use a tag
(<tag ... />
) as a component. Full configuration of a tag
component:
{
"kind": "tag",
"tag": "tag-name", # The tag name
# Other attributes passed to the tag
}
This will be rendered as:
<tag-name ... />
Attention
To build the report using the above filters, you need to import the components in the template files manually:
<script>
import { Descr, Image, DataTable } from "$libs";
import { Accordion, AccordionItem, Tabs, Tab, TabContent } from "$ccs";
// import more if needed, e.g InlineNotification, OrderedList, UnorderedList, ListItem, etc
</script>
{{ job | render_job }}
Registering new component renderer
pipen-report
allows you to register new component renderer. For example, you can register a new component renderer for my-component
:
from pipen_report.filters import register_component, _tag
@register_component("my-component", "mycomp")
def _render_my_component(args, job, level):
"""Render my-component
Args:
args should be a dict with the following keys:
- kind: The kind of the component, "my-component" or "mycomp" in this case
- arg1: ... # The arguments passed to the component
- arg2: ...
- ...
job: The job object used to render the template
level: The indent level of the component
"""
# Rendered as
# <div>This is my component</div>
return _tag("div", slot="This is my component", _level=level)
When the above component renderer is registered, my-component
can be used in the report.json
file:
{
"h1": {
"h2": {
"h3": {
"ui": [
{
"kind": "my-component",
"arg1": "value1",
"arg2": "value2"
}
]
}
}
}
}
Or in the dict passed to the render_component
filter:
{{ {"kind": "my-component", "arg1": "value1", "arg2": "value2"} | render_component }}
Registering new ui renderer
ui
is a layout of components, which defines how the set of components are rendered.
pipen-report
allows you to register new ui renderer. For example, you can register a new ui renderer for grid
:
from pipen_report.filters import register_ui, render_component, _tag
@register_ui("grid")
def _render_my_ui(contents, job, level):
"""Render grid ui
Args:
contents: The contents of components to render
job: The job object used to render the template
level: The indent level of the components
"""
return _tag(
"div",
slot="\n".join(
_tag("div", slot=render_component(c, job, 2), _level=1)
for c in contents
),
_level=level,
style="display: grid; grid-template-columns: repeat(2, auto); "
)
This will render a grid
ui as:
<div style="display: grid; grid-template-columns: repeat(2, auto); ">
<div>
<Component1 />
</div>
<div>
<Component2 />
</div>
</div>
When the above ui renderer is registered, grid
can be used in the report.json
file:
{
"h1": {
"h2": {
"h3": {
"grid": [
{
"kind": "<component>",
...
},
{
"kind": "<component>",
...
}
]
}
}
}
}
Or in the dict passed to the render_ui
filter:
{{ [ { "kind": "<component>", ... }, { "kind": "<component>", ... } ] | render_ui: "grid" }}
You can also pass extra arguments to the ui renderer. In the above example, for example, we can
pass the number of columns to the grid
ui, by registering the renderer as:
@register_ui("grid")
def _render_my_ui(contents, job, level, arg: str | None = None):
"""Render grid ui
The `arg` should be the residual of the ui name after the first `:`.
For example, `grid:3` will pass `arg="3"` to the renderer.
"""
arg = arg or "2"
ncol = int(arg)
return _tag(
"div",
slot="\n".join(
_tag("div", slot=render_component(c, job, 2), _level=1)
for c in contents
),
_level=level,
style=f"display: grid; grid-template-columns: repeat({ncol}, auto); "
)