Skip to content

Commit

Permalink
v1.2.0 (#55)
Browse files Browse the repository at this point in the history
* Implicit read for markdown files

* Update README

* Raise error on bad file type
  • Loading branch information
domvwt authored Jun 28, 2021
1 parent 8db6c60 commit 0d9ecd6
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 58 deletions.
11 changes: 0 additions & 11 deletions MANIFEST.in

This file was deleted.

13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ esparto
[![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)

## Introduction

## Introduction
`esparto` is a simple HTML and PDF document generator for Python.
The library takes a fully Pythonic approach to defining documents,
allowing iterative building and modification of the page and its contents.
`esparto` is especially good at:


### Example Use Cases
* Automated MI reporting
* Collating and sharing data visualisation
* Collating and sharing data visualisations
* ML model performance and evaluation documents
* Designing simple web pages

Expand All @@ -26,7 +27,7 @@ allowing iterative building and modification of the page and its contents.
* Output self-contained HTML and PDF files
* Responsive layout from [Bootstrap](https://getbootstrap.com/)
* No CSS or HTML required
* Automatic conversion for:
* Implicit conversion for:
* Markdown
* Images
* Pandas DataFrames
Expand All @@ -48,7 +49,6 @@ pip install weasyprint


## Dependencies

* [python](https://python.org/) >= 3.6
* [jinja2](https://palletsprojects.com/p/jinja/)
* [markdown](https://python-markdown.github.io/)
Expand Down Expand Up @@ -76,7 +76,7 @@ page = es.Page(title="Research")

# Add or update content
# Keys are used as titles
page["Introduction"]["Part One"]["Item A"] = "lorem ipsum"
page["Introduction"]["Part One"]["Item A"] = "./text/content.md"
page["Introduction"]["Part One"]["Item B"] = "./pictures/image1.jpg"

# Add content without a title
Expand Down Expand Up @@ -119,7 +119,6 @@ page.save_pdf("my-page.pdf")


## Example Output

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

Expand Down
4 changes: 2 additions & 2 deletions esparto/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
# Add or update content
# Keys are used as titles
page["Introduction"]["Part One"]["Item A"] = "lorem ipsum"
page["Introduction"]["Part One"]["Item A"] = "./text/content.md"
page["Introduction"]["Part One"]["Item B"] = "./pictures/image1.jpg"
# Add content without a title
Expand Down Expand Up @@ -87,7 +87,7 @@

__author__ = """Dominic Thorn"""
__email__ = "[email protected]"
__version__ = "1.1.0"
__version__ = "1.2.0"

_MODULE_PATH: _Path = _Path(__file__).parent.absolute()

Expand Down
22 changes: 18 additions & 4 deletions esparto/_adaptors.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from functools import singledispatch
from mimetypes import guess_type
from pathlib import Path

from esparto import _INSTALLED_MODULES
from esparto._content import (
Expand All @@ -22,7 +23,7 @@ def content_adaptor(content: Content) -> Content:
content (Any): Any content to be added to the document.
Returns:
Content: Approriately wrapped content.
Content: Appropriately wrapped content.
"""
if not issubclass(type(content), Content):
Expand All @@ -32,13 +33,26 @@ def content_adaptor(content: Content) -> Content:

@content_adaptor.register(str)
def content_adaptor_core(content: str) -> Content:
"""Convert markdown or image to Markdown or Image content."""
"""Convert text or image to Markdown or Image content."""
guess = guess_type(content)
if guess and "image" in str(guess[0]):
return Image(content)
if guess and isinstance(guess[0], str):
file_type = guess[0].split("/")[0]
if file_type == "image":
return Image(content)
elif file_type == "text":
content = Path(content).read_text()
else:
raise TypeError(f"{content}: {file_type}")
return Markdown(content)


@content_adaptor.register(Path)
def content_adaptor_path(content: Path) -> Content:
"""Convert text or image path to Markdown or Image content."""
content_str = str(content)
return content_adaptor_core(content_str)


# Function only available if Pandas is installed.
if "pandas" in _INSTALLED_MODULES:
from pandas.core.frame import DataFrame # type: ignore
Expand Down
14 changes: 13 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "esparto"
version = "1.1.0"
version = "1.2.0"
description = "Simple HTML and PDF document generator for Python."
authors = ["Dominic Thorn <[email protected]>"]
license = "MIT"
Expand Down Expand Up @@ -54,6 +54,7 @@ kaleido = "^0.2.1,!=0.2.1.post1"
sklearn = "^0.0"
shap = "^0.39.0"
zipp = "^3.4.1"
types-Markdown = "^3.3.0"

[tool.poetry.extras]
extras = ["beautifulsoup4", "weasyprint"]
Expand Down
25 changes: 0 additions & 25 deletions setup.cfg

This file was deleted.

1 change: 1 addition & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
adaptor_list = [
("this is markdown", co.Markdown),
(_irises_path, co.Image),
(Path(_irises_path), co.Image),
]

if _EXTRAS:
Expand Down
4 changes: 0 additions & 4 deletions tests/resources/iris-virginica.jpg:Zone.Identifier

This file was deleted.

26 changes: 25 additions & 1 deletion tests/test_adaptors.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from inspect import getmembers, isfunction, signature
from pathlib import Path, PosixPath

import pytest

import esparto._adaptors as ad
from esparto._content import Content
from esparto._content import Content, Markdown
from tests.conftest import _EXTRAS, adaptor_list


Expand All @@ -20,6 +21,9 @@ def test_all_adaptors_covered(adaptor_list_fn):
adaptor_types.remove(Content) # Can't use abstract base class in a test
if _EXTRAS:
adaptor_types.remove(ad.BokehObject) # Can't use abstract base class in a test
if PosixPath in test_classes:
test_classes.remove(PosixPath)
test_classes = adaptor_types | {Path}
adaptor_types.remove(None)
missing = adaptor_types.difference(test_classes)
assert not missing, missing
Expand All @@ -31,6 +35,26 @@ def test_adaptor_text(input_, expected):
assert isinstance(output, expected)


def test_adapator_textfile(tmp_path):
d = tmp_path / "sub"
d.mkdir()
p = d / "hello.exe"
CONTENT = "# This is some Markdown content"
p.write_text(CONTENT)
with pytest.raises(TypeError):
ad.content_adaptor(Path(p))


def test_adapator_bad_file(tmp_path):
d = tmp_path / "sub"
d.mkdir()
p = d / "hello.txt"
CONTENT = "# This is some Markdown content"
p.write_text(CONTENT)
assert ad.content_adaptor(Path(p)) == Markdown(CONTENT)
assert ad.content_adaptor(str(p)) == Markdown(CONTENT)


def test_incorrect_content_rejected():
class FakeClass:
def __call__(self):
Expand Down
3 changes: 1 addition & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ commands =

[testenv:codequal]
basepython = python
allowlist_externals = mypy
deps =
black
flake8
mypy
pytest # needed for type stubs
commands =
black --check esparto tests
flake8 esparto tests
Expand Down

0 comments on commit 0d9ecd6

Please sign in to comment.