Skip to content

Commit

Permalink
fix: change document methods and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
vberlier committed Feb 21, 2021
1 parent 49e8996 commit 8879b90
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 14 deletions.
49 changes: 35 additions & 14 deletions lectern/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

from dataclasses import InitVar, dataclass, field
from pathlib import Path
from typing import MutableMapping, Optional
from typing import Any, Dict, Literal, MutableMapping, Optional, Tuple, overload

from beet import Context, DataPack, ResourcePack
from beet import Context, DataPack, File, ResourcePack
from beet.core.utils import FileSystemPath, extra_field

from .directive import Directive, get_builtin_directives
Expand All @@ -20,6 +20,9 @@ class Document:
"""Class representing a lectern document."""

ctx: InitVar[Optional[Context]] = None
text: InitVar[Optional[str]] = None
markdown: InitVar[Optional[str]] = None
files: InitVar[Optional[FileSystemPath]] = None

assets: ResourcePack = field(default_factory=ResourcePack)
data: DataPack = field(default_factory=DataPack)
Expand All @@ -38,34 +41,53 @@ class Document:
default_factory=MarkdownSerializer
)

def __post_init__(self, ctx: Optional[Context]):
def __post_init__(
self,
ctx: Optional[Context],
text: Optional[str] = None,
markdown: Optional[str] = None,
files: Optional[FileSystemPath] = None,
):
if ctx:
self.assets = ctx.assets
self.data = ctx.data
if text:
self.add_text(text)
if markdown:
self.add_markdown(markdown, files)

def add_text(self, source: str):
"""Extract pack fragments from plain text."""
assets, data = self.text_extractor.extract(source, self.directives)

self.assets.merge(assets)
self.data.merge(data)

def add_markdown(self, source: str, files: Optional[FileSystemPath] = None):
"""Extract pack fragments from markdown."""
assets, data = self.markdown_extractor.extract(source, self.directives, files)

self.assets.merge(assets)
self.data.merge(data)

def serialize(self, as_text: bool = False) -> str:
"""Serialize the inner data pack and the resource pack."""
return (
self.text_serializer.serialize(self.assets, self.data)
if as_text
else self.markdown_serializer.serialize_and_emit_files(
self.assets, self.data
)[0]
def get_text(self) -> str:
"""Turn the data pack and the resource pack into text."""
return self.text_serializer.serialize(self.assets, self.data)

@overload
def get_markdown(
self, emit_files: Literal[True]
) -> Tuple[str, Dict[str, File[Any, Any]]]:
...

@overload
def get_markdown(self, emit_files: Literal[False] = False) -> str:
...

def get_markdown(self, emit_files: bool = False):
"""Turn the data pack and the resource pack into markdown."""
data, files = self.markdown_serializer.serialize_and_emit_files(
self.assets, self.data
)
return (data, files) if emit_files else data

def save(self, path: FileSystemPath, files: Optional[FileSystemPath] = None):
"""Save the serialized document at the specified location."""
Expand All @@ -84,5 +106,4 @@ def save(self, path: FileSystemPath, files: Optional[FileSystemPath] = None):
data = self.text_serializer.serialize(self.assets, self.data)

path.parent.mkdir(parents=True, exist_ok=True)

path.write_text(data)
72 changes: 72 additions & 0 deletions tests/test_document.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import pytest
from beet import DataPack, Function, ResourcePack

from lectern import Document, InvalidFragment


def test_empty():
assert Document() == Document()
assert Document().data == DataPack()
assert Document().assets == ResourcePack()
assert Document().get_text() == ""
assert Document().get_markdown() == ""
assert Document().get_markdown(emit_files=True) == ("", {})


def test_data_pack():
pack = DataPack()
doc = Document(data=pack)
assert doc.data is pack


def test_resource_pack():
pack = ResourcePack()
doc = Document(assets=pack)
assert doc.assets is pack


def test_text_basic():
source = "@function demo:foo\nsay hello\n"
assert source in Document(text=source).get_text()


def test_text_function():
pack = DataPack()
pack["demo:foo"] = Function(["say foo"])

doc = Document(data=pack)
doc.add_text("@function demo:bar\nsay bar\n")

assert pack.functions == {
"demo:foo": Function(["say foo"]),
"demo:bar": Function(["say bar"]),
}


def test_text_tricky():
doc = Document(
text="some preamble\n\n"
"@function demo:foo\n"
"say foo\n"
"@other_thing hello world\n"
"say after\n"
" @function not taken into account\n"
"say next\n"
"@function demo:bar\n"
"say bar\n"
)
assert len(doc.data.functions) == 2


def test_missing_argument():
with pytest.raises(
InvalidFragment, match="Missing directive argument 'full_name'."
):
Document(text="@function\nsay hello")


def test_extra_argument():
with pytest.raises(
InvalidFragment, match="Unexpected directive argument 'banana'."
):
Document(text="@function demo:foo banana\nsay hello")

0 comments on commit 8879b90

Please sign in to comment.