diff --git a/CHANGELOG.md b/CHANGELOG.md index e6f0a8f9..f83aa8ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.12.5] - 2023-09-26 +### Added +- Utility Groot: Add test cases. +### Fixed +- Tree Exporter: `tree_to_pillow` function to reference online font file instead of relative path. + ## [0.12.4] - 2023-09-25 ### Added - Utility Groot: Add groot utility functions. @@ -327,6 +333,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Utility Iterator: Tree traversal methods. - Workflow To Do App: Tree use case with to-do list implementation. +[0.12.5]: https://github.com/kayjan/bigtree/compare/0.12.4...0.12.5 [0.12.4]: https://github.com/kayjan/bigtree/compare/0.12.3...0.12.4 [0.12.3]: https://github.com/kayjan/bigtree/compare/0.12.2...0.12.3 [0.12.2]: https://github.com/kayjan/bigtree/compare/0.12.1...0.12.2 diff --git a/bigtree/__init__.py b/bigtree/__init__.py index 26902c1e..800e68b9 100644 --- a/bigtree/__init__.py +++ b/bigtree/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.12.4" +__version__ = "0.12.5" from bigtree.binarytree.construct import list_to_binarytree from bigtree.dag.construct import dataframe_to_dag, dict_to_dag, list_to_dag diff --git a/bigtree/tree/export.py b/bigtree/tree/export.py index 366cce11..796884ef 100644 --- a/bigtree/tree/export.py +++ b/bigtree/tree/export.py @@ -2,6 +2,7 @@ import collections from typing import Any, Dict, Iterable, List, Optional, Tuple, TypeVar, Union +from urllib.request import urlopen from bigtree.node.node import Node from bigtree.tree.search import find_path @@ -772,7 +773,7 @@ def tree_to_pillow( width: int = 0, height: int = 0, start_pos: Tuple[int, int] = (10, 10), - font_family: str = "assets/DejaVuSans.ttf", + font_family: str = "", font_size: int = 12, font_colour: Union[Tuple[int, int, int], str] = "black", bg_colour: Union[Tuple[int, int, int], str] = "white", @@ -808,7 +809,15 @@ def tree_to_pillow( (PIL.Image.Image) """ # Initialize font - font = ImageFont.truetype(font_family, font_size) + if not font_family: + dejavusans_url = "https://github.com/kayjan/bigtree/raw/master/assets/DejaVuSans.ttf?raw=true" + font_family = urlopen(dejavusans_url) + try: + font = ImageFont.truetype(font_family, font_size) + except OSError: + raise ValueError( + f"Font file {font_family} is not found, set `font_family` parameter to point to a valid .ttf file." + ) # Initialize text image_text = [] diff --git a/tests/constants.py b/tests/constants.py index fd376cc8..2801a395 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -144,6 +144,7 @@ class Constants: ERROR_NODE_EXPORT_PRINT_INVALID_PATH = ( "Node name or path {node_name_or_path} not found" ) + ERROR_NODE_EXPORT_PILLOW_FONT_FAMILY = "Font file {font_family} is not found, set `font_family` parameter to point to a valid .ttf file." ERROR_NODE_EXPORT_PRINT_INVALID_STYLE = "Choose one of " diff --git a/tests/tree/test_export.py b/tests/tree/test_export.py index dc6094ab..b8a1cfd5 100644 --- a/tests/tree/test_export.py +++ b/tests/tree/test_export.py @@ -979,3 +979,14 @@ def test_tree_to_pillow_kwargs(tree_node): pillow_image = tree_to_pillow(tree_node, max_depth=2, style="const_bold") if LOCAL: pillow_image.save("tests/tree_pillow_style.png") + + @staticmethod + def test_tree_to_pillow_font_family(tree_node): + font_family = "invalid.ttf" + with pytest.raises(ValueError) as exc_info: + tree_to_pillow(tree_node, font_family=font_family) + assert str( + exc_info.value + ) == Constants.ERROR_NODE_EXPORT_PILLOW_FONT_FAMILY.format( + font_family=font_family + ) diff --git a/tests/utils/test_groot.py b/tests/utils/test_groot.py new file mode 100644 index 00000000..09229f35 --- /dev/null +++ b/tests/utils/test_groot.py @@ -0,0 +1,15 @@ +import pytest + +from bigtree.utils.groot import speak_like_groot, whoami + + +def test_whoami(): + assert whoami() == "I am Groot!" + + +@pytest.mark.parametrize( + ["sentence", "expected_output"], + [("Hi!", "I am Groot!"), ("Hi there!", "I am Groot! I am Groot!")], +) +def test_speak_like_groot(sentence, expected_output): + assert speak_like_groot(sentence) == expected_output