Skip to content

Commit

Permalink
Merge pull request #67 from e10v/dev
Browse files Browse the repository at this point in the history
Several changes in args and global config
  • Loading branch information
e10v authored Jun 4, 2023
2 parents dbf071a + f43e31e commit df68a56
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 137 deletions.
10 changes: 1 addition & 9 deletions src/rico/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@
# pyright: reportUnusedImport=false
"""Rich content to HTML as easy as `Doc(df, plot)`."""

from rico._config import (
BOOTSTRAP_CSS,
BOOTSTRAP_JS,
BOOTSTRAP_VER,
DATAFRAME_STYLE,
config_context,
get_config,
set_config,
)
from rico._config import config_context, get_config, set_config
from rico._container import Div, Doc
from rico._content import (
Chart,
Expand Down
78 changes: 51 additions & 27 deletions src/rico/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,19 @@


_global_config = {
"bootstrap_css": BOOTSTRAP_CSS,
"bootstrap_js": BOOTSTRAP_JS,
"dataframe_style": DATAFRAME_STYLE,
"image_format": "svg",
"indent_html": False,
"indent_space": " ",
"strip_html": False,
"image_format": "svg",
"inline_scripts": False,
"inline_styles": False,
"bootstrap_css": BOOTSTRAP_CSS,
"bootstrap_js": "",
"dataframe_style": DATAFRAME_STYLE,
"meta_charset": "utf-8",
"meta_viewport": "width=device-width, initial-scale=1",
"strip_html": False,
"text_mono": False,
"text_wrap": False,
}


Expand All @@ -79,31 +83,41 @@ def get_config(param: str | None = None) -> Any:


def set_config(
bootstrap_css: str | None = None,
bootstrap_js: str | None = None,
dataframe_style: str | None = None,
image_format: Literal["svg", "png"] | None = None,
indent_html: bool | None = None,
indent_space: str | None = None,
strip_html: bool | None = None,
image_format: Literal["svg", "png"] | None = None,
inline_scripts: bool | None = None,
inline_styles: bool | None = None,
bootstrap_css: str | None = None,
bootstrap_js: str | None = None,
dataframe_style: str | None = None,
meta_charset: str | None = None,
meta_viewport: str | None = None,
strip_html: bool | None = None,
text_mono: bool | None = None,
text_wrap: bool | None = None,
) -> None:
"""Set global configuration.
Args:
indent_html: Indent HTML elements in serialization methods.
indent_space: Default indent space.
strip_html: Strip HTML elements in serialization methods.
image_format: Default chart image format.
inline_scripts: If True then scripts are loaded inline.
inline_styles: If True then styles are loaded inline.
bootstrap_css: A link to a bootstrap css file.
If empty then bootstrap css is not loaded.
bootstrap_js: A link to a bootstrap javascript file.
If empty then bootstrap javascript is not loaded.
dataframe_style: A dataframe table stylesheet.
If empty then it's not used.
image_format: Default chart image format.
indent_html: Indent HTML elements in serialization methods.
indent_space: Default indent space.
inline_scripts: If True then scripts are loaded inline.
inline_styles: If True then styles are loaded inline.
meta_charset: An HTML document charset.
If empty then it's not used.
meta_viewport: An HTML document viewport property.
If empty then it's not used.
strip_html: Strip HTML elements in serialization methods.
text_mono: Default value for the `mono` arg of the Text class.
text_wrap: Default value for the `wrap` arg of the Text class.
"""
for param, value in locals().items():
if value is not None:
Expand All @@ -112,31 +126,41 @@ def set_config(

@contextlib.contextmanager
def config_context(
bootstrap_css: str | None = None,
bootstrap_js: str | None = None,
dataframe_style: str | None = None,
image_format: Literal["svg", "png"] | None = None,
indent_html: bool | None = None,
indent_space: str | None = None,
strip_html: bool | None = None,
image_format: Literal["svg", "png"] | None = None,
inline_scripts: bool | None = None,
inline_styles: bool | None = None,
bootstrap_css: str | None = None,
bootstrap_js: str | None = None,
dataframe_style: str | None = None,
meta_charset: str | None = None,
meta_viewport: str | None = None,
strip_html: bool | None = None,
text_mono: bool | None = None,
text_wrap: bool | None = None,
) -> Generator[None, Any, None]:
"""Context manager for configuration.
Args:
indent_html: Indent HTML elements in serialization methods.
indent_space: Default indent space.
strip_html: Strip HTML elements in serialization methods.
image_format: Default chart image format.
inline_scripts: If True then scripts are loaded inline.
inline_styles: If True then styles are loaded inline.
bootstrap_css: A link to a bootstrap css file.
If empty then bootstrap css is not loaded.
bootstrap_js: A link to a bootstrap javascript file.
If empty then bootstrap javascript is not loaded.
dataframe_style: A dataframe table stylesheet.
If empty then it's not used.
image_format: Default chart image format.
indent_html: Indent HTML elements in serialization methods.
indent_space: Default indent space.
inline_scripts: If True then scripts are loaded inline.
inline_styles: If True then styles are loaded inline.
meta_charset: An HTML document charset.
If empty then it's not used.
meta_viewport: An HTML document viewport property.
If empty then it's not used.
strip_html: Strip HTML elements in serialization methods.
text_mono: Default value for the `mono` arg of the Text class.
text_wrap: Default value for the `wrap` arg of the Text class.
"""
new_config = locals()
old_config = get_config()
Expand Down
37 changes: 15 additions & 22 deletions src/rico/_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

if TYPE_CHECKING:
from collections.abc import Callable, Iterable
from typing import Any, Concatenate, ParamSpec
from typing import Any, Concatenate, Literal, ParamSpec

P = ParamSpec("P")

Expand Down Expand Up @@ -79,13 +79,11 @@ class Doc(Div):
body: ET.Element
container: ET.Element

def __init__( # noqa: C901
def __init__(
self,
*objects: Any,
title: str | None = None,
charset: str | None = "utf-8",
viewport: str | None = "width=device-width, initial-scale=1",
bootstrap: bool = True,
bootstrap: Literal["css", "full", "none"] = "css",
extra_styles: Iterable[rico._content.Style] = (),
extra_scripts: Iterable[rico._content.Script] = (),
class_: str | None = "container",
Expand All @@ -95,8 +93,6 @@ def __init__( # noqa: C901
Args:
*objects: The objects which are used to create a content.
title: The document title.
charset: The document charset.
viewport: The document viewport property.
bootstrap: If True then Bootstrap included to the document.
extra_styles: Extra styles to be included to the document.
extra_scripts: Extra scripts to be included to the document.
Expand All @@ -115,40 +111,37 @@ def __init__( # noqa: C901
title_element.text = title
self.head.append(title_element)

if charset is not None:
self.head.append(ET.Element("meta", charset=charset))

if viewport is not None:
global_config = rico._config.get_config()
if global_config["meta_charset"]:
self.head.append(ET.Element("meta", charset=global_config["meta_charset"]))
if global_config["meta_viewport"]:
self.head.append(ET.Element(
"meta",
name="viewport",
content=viewport,
content=global_config["meta_viewport"],
))

styles : list[rico._content.Style] = []
scripts : list[rico._content.Script] = []
global_config = rico._config.get_config()

if bootstrap:
if global_config["bootstrap_css"]:
styles.append(rico._content.Style(src=global_config["bootstrap_css"]))
if global_config["bootstrap_js"]:
scripts.append(rico._content.Script(src=global_config["bootstrap_js"]))

if bootstrap.lower() in {"css", "full"}:
styles.append(rico._content.Style(src=global_config["bootstrap_css"]))
if bootstrap.lower() == "full":
scripts.append(rico._content.Script(src=global_config["bootstrap_js"]))
if global_config["dataframe_style"]:
styles.append(rico._content.Style(text=global_config["dataframe_style"]))

styles = [*styles, *extra_styles]
scripts = [*scripts, *extra_scripts]

for style in styles:
self.head.append(style.style)
self.head.append(style.container)

for script in scripts:
if script.footer:
self.body.append(script.script)
self.body.append(script.container)
else:
self.head.append(script.script)
self.head.append(script.container)

def serialize(
self,
Expand Down
24 changes: 14 additions & 10 deletions src/rico/_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ class Text(ContentBase):
def __init__(
self,
obj: Any,
mono: bool = False,
wrap: bool = False,
mono: bool | None = None,
wrap: bool | None = None,
class_: str | None = None,
):
"""Create content from a text.
Expand All @@ -144,6 +144,12 @@ def __init__(
"""
super().__init__(class_)

global_config = rico._config.get_config()
if mono is None:
mono = global_config["text_mono"]
if wrap is None:
wrap = global_config["text_wrap"]

if not isinstance(obj, str):
obj = str(obj)

Expand Down Expand Up @@ -377,7 +383,7 @@ class Script(ContentBase):
footer (bool): Defines whether the script should be placed at a document footer,
aftert all other content.
"""
script: ET.Element
container: ET.Element
footer: bool = False

def __init__(
Expand Down Expand Up @@ -428,9 +434,8 @@ def __init__(
else:
self.footer = defer

self.script = ET.Element("script", {**attrib, **extra})
self.script.text = text
self.container = self.script
self.container = ET.Element("script", {**attrib, **extra})
self.container.text = text


class Style(ContentBase):
Expand All @@ -439,7 +444,7 @@ class Style(ContentBase):
Attributes:
style (Element): The style element.
"""
style: ET.Element
container: ET.Element

def __init__(
self,
Expand Down Expand Up @@ -487,6 +492,5 @@ def __init__(
else:
tag = "style"

self.style = ET.Element(tag, {**attrib, **extra})
self.style.text = text
self.container = self.style
self.container = ET.Element(tag, {**attrib, **extra})
self.container.text = text
6 changes: 3 additions & 3 deletions src/rico/_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ def handle_endtag(self, tag: str) -> None:
def handle_data(self, data: str) -> None:
self._builder.data(data)

def close(self) -> list[ET.Element]:
def close(self) -> tuple[ET.Element]:
super().close()
self._builder.end(self._root)
return list(self._builder.close())
return tuple(self._builder.close())


def parse_html(data: str) -> list[ET.Element]:
def parse_html(data: str) -> tuple[ET.Element]:
"""Parse an HTML document from a string.
Assign None values to boolean attributes.
Expand Down
Loading

0 comments on commit df68a56

Please sign in to comment.