Skip to content

Commit

Permalink
v3.0.0 (#90)
Browse files Browse the repository at this point in the history
- API
    - Page now accepts `max_width` and `output_options` arguments
    - Content classes no longer accept `width` or `height` arguments
- New Features
    - Output rendering options can now be configured at page level
    - Additional markdown features recognised
- Fixes
    - JavaScript is now placed at end of page so HTML is loaded first
- Page Style
    - Removed unnecessary indentation
    - Tables now render in minimal, clean style
    - Improvements to sizing and centring of plots
    - Cleaned up unnecessary HTML and CSS
    - Majority of CSS attributes moved to `esparto.css`
- Dependencies
    - Pillow is now optional
    - BeautifulSoup4 is now required
    - Upper version limits removed from all
- Other
    - Type hints implemented with ~100% coverage
  • Loading branch information
domvwt authored Feb 23, 2022
1 parent 5e27471 commit 245b1e5
Show file tree
Hide file tree
Showing 47 changed files with 6,897 additions and 7,983 deletions.
2 changes: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[flake8]
max-line-length = 120
exclude = scratch.*, docs/
exclude = scratch.py, docs/
ignore =
W503, # line break before binary operator
E203, # whitespace before ':'
Expand Down
9 changes: 4 additions & 5 deletions .github/workflows/lint-and-test.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Lint and Test Python Library
name: tests

on:
push:
Expand Down Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest coverage
python -m pip install flake8 pytest coverage html5lib
python -m pip install .
- name: Lint with flake8
run: |
Expand All @@ -46,11 +46,10 @@ jobs:
coverage run --append --source esparto -m pytest
- name: Install optional dependencies
run: |
python -m pip install ipython pandas matplotlib bokeh plotly kaleido "weasyprint<53" beautifulsoup4 html5lib
- name: Test full install with pytest
python -m pip install ipython pandas matplotlib bokeh plotly kaleido "weasyprint<53" html5lib
- name: Test full install with pytest
run: |
coverage run --append --source esparto -m pytest
- name: Upload coverage to codecov.io
run: |
bash <(curl -s https://codecov.io/bash)
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ esparto-doc.html
esparto-quick.html
esparto-doc.pdf
docs/examples/*.html
/*.html
/*.pdf

# IDE files
.vscode
Expand Down Expand Up @@ -113,3 +115,5 @@ ENV/

# mypy
.mypy_cache/
.markdownlint.json
my-report.html
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ repos:
language: system
entry: poetry run mypy
types: [python]
exclude: tests/
- id: version
name: Version
language: system
Expand Down
22 changes: 0 additions & 22 deletions .travis.yml

This file was deleted.

4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ lint: ## check style with flake8
flake8 esparto tests

mypy: ## check type hints
mypy esparto tests
mypy esparto --strict

isort: ## sort imports
isort esparto tests
isort esparto tests --profile black

cqa: format isort lint mypy ## run all cqa tools

Expand Down
127 changes: 80 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,98 +3,131 @@ esparto

[![image](https://img.shields.io/pypi/v/esparto.svg)](https://pypi.python.org/pypi/esparto)
[![PyPI pyversions](https://img.shields.io/pypi/pyversions/esparto.svg)](https://pypi.python.org/pypi/esparto/)
[![Build Status](https://travis-ci.com/domvwt/esparto.svg?branch=main)](https://travis-ci.com/domvwt/esparto)
![Build Status](https://github.com/domvwt/esparto/actions/workflows/lint-and-test.yml/badge.svg)
[![codecov](https://codecov.io/gh/domvwt/esparto/branch/main/graph/badge.svg?token=35J8NZCUYC)](https://codecov.io/gh/domvwt/esparto)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=domvwt_esparto&metric=alert_status)](https://sonarcloud.io/dashboard?id=domvwt_esparto)
![PyPI - Downloads](https://img.shields.io/pypi/dm/esparto)

Introduction
------------

## Introduction
**esparto** is a Python package for building shareable reports with content
from popular data analysis libraries.
With just a few lines of code, **esparto** turns DataFrames, plots, and
Markdown into an interactive webpage or PDF document.
**esparto** is a Python library for building data driven reports with content
from popular analytics packages. The project takes a straightforward approach
to document design; with a focus on usability, portability, and extensiblity.

Documents produced by **esparto** are completely portable - no backend server
is required - and entirely customisable using CSS and Jinja templating.
All content dependencies are declared inline or loaded via a CDN, meaning your
reports can be shared by email, hosted on a standard http server, or made
available as static pages as-is.
Creating a report is as simple as instantiating a Page object and 'adding' content
in the form of DataFrames, plots, and markdown text. Documents can be built interactively
in a notebook environment, and the results shared as a self-contained HTML
page or PDF file.

Further customisation of the output is possible by passing a CSS stylesheet,
changing the [Jinja](Jinja) template, or declaring additional element styles within
the code. The responsive [Bootstrap](Bootstrap) grid ensures documents adapt to
any viewing device.

Basic Usage
-----------

## Basic Usage
```python
import esparto as es

# Do some analysis
pandas_dataframe = ...
plotly_figure = ...

# Create a Page object
page = es.Page(title="My Report")
page["Data Analysis"] = (pandas_dataframe, plotly_figure)

# Add content
page["Data Analysis"]["Plot"] = plotly_figure
page["Data Analysis"]["Data"] = pandas_dataframe

# Save to HTML or PDF
page.save_html("my-report.html")
page.save_pdf("my-report.pdf")

```

Main Features
-------------

## Main Features
* Automatic and adaptive layout
* Customisable with CSS or Jinja
* Jupyter Notebook friendly
* Output as HTML or PDF
* Built-in adaptors for:
* Markdown
* Images
* [Pandas DataFrames][Pandas]
* [Matplotlib][Matplotlib]
* [Bokeh][Bokeh]
* [Plotly][Plotly]
- Interactive document design with Jupyter Notebooks
- Share as self-contained HTML or PDF
- Customise with CSS and Jinja
- Responsive Bootstrap grid layout
- Content adaptors for:
- [Markdown][Markdown]
- [Images][Pillow]
- [Pandas DataFrames][Pandas]
- [Matplotlib][Matplotlib]
- [Bokeh][Bokeh]
- [Plotly][Plotly]

Installation
------------

## Installation
**esparto** is available from [PyPI][PyPI] and [Conda][Conda]:

```bash
pip install esparto
```

```bash
conda install esparto -c conda-forge
```

If PDF output is required, [Weasyprint](https://weasyprint.org/) must also be installed.
Dependencies
------------

- [python](https://python.org/) >= 3.6
- [jinja2](https://palletsprojects.com/p/jinja/)
- [markdown](https://python-markdown.github.io/)
- [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/)
- [PyYAML](https://pyyaml.org/)

## Dependencies
* [python](https://python.org/) >= 3.6
* [jinja2](https://palletsprojects.com/p/jinja/)
* [markdown](https://python-markdown.github.io/)
* [Pillow](https://python-pillow.org/)
* [PyYAML](https://pyyaml.org/)
* [weasyprint](https://weasyprint.org/) _(optional - required for PDF output)_
#### Optional

- [Pillow](https://python-pillow.org/) *(for image content)*
- [weasyprint](https://weasyprint.org/) *(for PDF output)*

License
-------

## License
[MIT](https://opensource.org/licenses/MIT)

Documentation
-------------

Documentation and examples are available at
[domvwt.github.io/esparto/](https://domvwt.github.io/esparto/).

## Documentation
Full documentation and examples are available at [domvwt.github.io/esparto/](https://domvwt.github.io/esparto/).
Contributions, Issues, and Requests
-----------------------------------

## Contributions, Issues, and Requests
All feedback and contributions are welcome - please raise an issue or pull request on [GitHub][GitHub].
Feedback and contributions are welcome - please raise an issue or pull request
on [GitHub][GitHub].

Examples
--------

## Examples
Iris Report - [Webpage](https://domvwt.github.io/esparto/examples/iris-report.html) |
[PDF](https://domvwt.github.io/esparto/examples/iris-report.pdf)

Bokeh and Plotly - [Webpage](https://domvwt.github.io/esparto/examples/interactive-plots.html) |
[PDF](https://domvwt.github.io/esparto/examples/interactive-plots.pdf)

<br>

<p width=100%>
<img width=80% src="https://github.com/domvwt/esparto/blob/fdc0e787c0bc013d16667773e82e21c647b71d91/docs/images/iris-report-compressed.png?raw=true" alt="example page" style="border-radius:0.5%;">
<img width=100% src="https://github.com/domvwt/esparto/blob/1857f1d7411f12c37c96f8f5d60ff7012071851f/docs/images/iris-report-compressed.png?raw=true" alt="example page" style="border-radius:0.5%;">
</p>

<!-- Links -->
<!-- * Links -->
[PyPI]: https://pypi.org/project/esparto/
[Conda]: https://anaconda.org/conda-forge/esparto
[Bootstrap]: https://getbootstrap.com/docs/4.6/getting-started/introduction/
[Bootstrap]: https://getbootstrap.com/
[Jinja]: https://jinja.palletsprojects.com/
[Markdown]: https://www.markdownguide.org/
[Pillow]: https://python-pillow.org/
[Pandas]: https://pandas.pydata.org/
[Matplotlib]: https://matplotlib.org/
[Bokeh]: https://docs.bokeh.org/en/latest/index.html
[Bokeh]: https://bokeh.org/
[Plotly]: https://plotly.com/
[GitHub]: https://github.com/domvwt/esparto
Binary file modified devdocs/classes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
68 changes: 44 additions & 24 deletions docs/02-user-guide/quick-start.md
Original file line number Diff line number Diff line change
@@ -1,77 +1,97 @@
# Quick Start

## Create a Page

```python
import esparto as es

page = es.Page(title="Page Title")
page[0] = "Page Content"
page["Section Title"] += "Some text"
page["Section Title"] += "More text"

page.tree()
```

```
{'Page Title': [{'Section 0': [{'Row 0': [{'Column 0': ['Markdown']}]}]}]}
{'Page Title': [{'Section Title': [{'Row 0': [{'Column 0': ['Markdown']}]},
{'Row 1': [{'Column 0': ['Markdown']}]}]}]}
```

## Add Content

### Define Rows and Columns

```python
page = es.Page("Page Title")
page["Section One"]["Row One"]["Column One"] = "Some content"
page["Section One"]["Row One"]["Column Two"] = "More content"
page.tree()
page["Section Title"]["Row Title"][0] = "Some content"
page["Section Title"]["Row Title"][1] = "More content"
```

```
{'Page Title': [{'Section One': [{'Row One': [{'Column One': ['Markdown']},
{'Column Two': ['Markdown']}]}]}]}
{'Page Title': [{'Section Title': [{'Row Title': [{'Column 0': ['Markdown']},
{'Column 1': ['Markdown']}]}]}]}
```

### Define multiple Columns as a tuple of dicts
### Define multiple Columns

```python
page = es.Page("Page Title")
page["Section One"]["Row One"] = (
{"Column One": "Some content"},
page["Section Title"]["Row Title"] = (
{"Column Title": "Some content"},
{"Column Two": "More content"}
)
page.tree()
```

```
{'Page Title': [{'Section One': [{'Row One': [{'Column One': ['Markdown']},
{'Column Two': ['Markdown']}]}]}]}
{'Page Title': [{'Section Title': [{'Row Title': [{'Column Title': ['Markdown']},
{'Column Two': ['Markdown']}]}]}]}
```

## Update Content

### Access existing content via Indexing or as Attributes

```python
page["Section One"]["Row One"]["Column One"] = image_01
page.section_one.row_one.column_two = image_02
page.section_one.tree()
page["Section Title"]["Row Title"]["Column Title"] = image_01
page.section_title.row_title.column_two = image_02
```

```
{'Page Title': [{'Section One': [{'Row One': [{'Column One': ['Image']},
{'Column Two': ['Image']}]}]}]}
{'Page Title': [{'Section Title': [{'Row Title': [{'Column Title': ['Image']},
{'Column Two': ['Image']}]}]}]}
```

## Delete Content

### Delete the last Column

```python
del page.section_one.row_one[-1]
del page.section_title.row_title[-1]
```

```
{'Page Title': [{'Section One': [{'Row One': [{'Column One': ['Image']}]}]}]}
{'Page Title': [{'Section Title': [{'Row Title': [{'Column Title': ['Image']}]}]}]}
```

### Delete a named Column

```python
del page.section_one.row_one.column_two
del page.section_title.row_title.column_two
page.tree()
```

```
{'Page Title': [{'Section One': [{'Row One': [{'Column One': ['Image']}]}]}]}
{'Page Title': [{'Section Title': [{'Row Title': [{'Column Title': ['Image']}]}]}]}
```

## Save the Document

### As a webpage

```python
my_page.save_html("my-esparto-doc.html")
```

### As a PDF

```python
my_page.save_pdf("my-esparto-doc.pdf")
```
Expand Down
Loading

0 comments on commit 245b1e5

Please sign in to comment.