refactor: Move templating to separate file
This commit is contained in:
parent
e633c0335e
commit
4eb983d9e3
7 changed files with 97 additions and 41 deletions
|
@ -9,7 +9,7 @@ from papis.document import Document
|
||||||
|
|
||||||
from papis_extract import extractor, exporter
|
from papis_extract import extractor, exporter
|
||||||
from papis_extract.annotation_data import AnnotatedDocument
|
from papis_extract.annotation_data import AnnotatedDocument
|
||||||
from papis_extract.model.templating import Markdown
|
from papis_extract.templating import Markdown
|
||||||
|
|
||||||
logger = papis.logging.get_logger(__name__)
|
logger = papis.logging.get_logger(__name__)
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import math
|
import math
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Protocol
|
|
||||||
|
|
||||||
import papis.config
|
import papis.config
|
||||||
from papis.document import Document
|
from papis.document import Document
|
||||||
import chevron
|
import chevron
|
||||||
|
|
||||||
|
from papis_extract.templating import Templating
|
||||||
|
|
||||||
TEXT_SIMILARITY_MINIMUM = 0.75
|
TEXT_SIMILARITY_MINIMUM = 0.75
|
||||||
COLOR_SIMILARITY_MINIMUM = 0.833
|
COLOR_SIMILARITY_MINIMUM = 0.833
|
||||||
|
|
||||||
|
@ -32,7 +33,7 @@ class Annotation:
|
||||||
type: str = "Highlight"
|
type: str = "Highlight"
|
||||||
minimum_similarity_color: float = 1.0
|
minimum_similarity_color: float = 1.0
|
||||||
|
|
||||||
def format(self, formatting):
|
def format(self, template: Templating):
|
||||||
"""Return a formatted string of the annotation.
|
"""Return a formatted string of the annotation.
|
||||||
|
|
||||||
Given a provided formatting pattern, this method returns the annotation
|
Given a provided formatting pattern, this method returns the annotation
|
||||||
|
@ -47,7 +48,7 @@ class Annotation:
|
||||||
"tag": self.tag,
|
"tag": self.tag,
|
||||||
"type": self.type,
|
"type": self.type,
|
||||||
}
|
}
|
||||||
return chevron.render(formatting, data)
|
return chevron.render(template.string, data)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def colorname(self):
|
def colorname(self):
|
||||||
|
|
|
@ -8,7 +8,7 @@ import papis.config
|
||||||
import Levenshtein
|
import Levenshtein
|
||||||
|
|
||||||
from papis_extract.annotation_data import AnnotatedDocument
|
from papis_extract.annotation_data import AnnotatedDocument
|
||||||
from papis_extract.model.templating import Templating
|
from papis_extract.templating import Templating
|
||||||
|
|
||||||
logger = papis.logging.get_logger(__name__)
|
logger = papis.logging.get_logger(__name__)
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ def to_stdout(annots: list[AnnotatedDocument], template: Templating) -> None:
|
||||||
f"{title_decoration}\n{papis.document.describe(entry.document)}\n{title_decoration}\n"
|
f"{title_decoration}\n{papis.document.describe(entry.document)}\n{title_decoration}\n"
|
||||||
)
|
)
|
||||||
for a in entry.annotations:
|
for a in entry.annotations:
|
||||||
print(a.format(template.string))
|
print(a.format(template))
|
||||||
|
|
||||||
if entry != last:
|
if entry != last:
|
||||||
print("\n")
|
print("\n")
|
||||||
|
@ -60,7 +60,7 @@ def to_notes(
|
||||||
|
|
||||||
formatted_annotations: list[str] = []
|
formatted_annotations: list[str] = []
|
||||||
for a in entry.annotations:
|
for a in entry.annotations:
|
||||||
formatted_annotations.append(a.format(template.string))
|
formatted_annotations.append(a.format(template))
|
||||||
|
|
||||||
_add_annots_to_note(entry.document, formatted_annotations)
|
_add_annots_to_note(entry.document, formatted_annotations)
|
||||||
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
from dataclasses import dataclass
|
|
||||||
from typing import Protocol
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Templating(Protocol):
|
|
||||||
string: str
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Markdown:
|
|
||||||
string: str = (
|
|
||||||
"{{#tag}}#{{tag}}\n{{/tag}}"
|
|
||||||
"{{#quote}}> {{quote}}{{/quote}} {{#page}}[p. {{page}}]{{/page}}\n"
|
|
||||||
"{{#note}} NOTE: {{note}}{{/note}}"
|
|
||||||
)
|
|
35
papis_extract/templating.py
Normal file
35
papis_extract/templating.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Protocol
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Templating(Protocol):
|
||||||
|
header: str
|
||||||
|
string: str
|
||||||
|
footer: str
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Markdown:
|
||||||
|
header: str = ""
|
||||||
|
string: str = (
|
||||||
|
"{{#tag}}#{{tag}}\n{{/tag}}"
|
||||||
|
"{{#quote}}> {{quote}}{{/quote}} {{#page}}[p. {{page}}]{{/page}}\n"
|
||||||
|
"{{#note}} NOTE: {{note}}{{/note}}"
|
||||||
|
)
|
||||||
|
footer: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Csv:
|
||||||
|
header: str = "type, tag, page, quote, note, file"
|
||||||
|
string: str = "{{type}}, {{tag}}, {{page}}, {{quote}}, {{note}}, {{file}}"
|
||||||
|
footer: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Custom:
|
||||||
|
def __init__(self, header: str = "", string: str = "", footer: str = "") -> None:
|
||||||
|
self.header = header
|
||||||
|
self.string = string
|
||||||
|
self.footer = footer
|
|
@ -1,17 +1,20 @@
|
||||||
import pytest
|
import pytest
|
||||||
from papis_extract.annotation_data import Annotation
|
from papis_extract.annotation_data import Annotation
|
||||||
|
from papis_extract.templating import Custom
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"fmt_string,expected",
|
"fmt_string,expected",
|
||||||
[
|
[
|
||||||
("{{quote}}", "I am the text value"),
|
(Custom(string="{{quote}}"), "I am the text value"),
|
||||||
(
|
(
|
||||||
"> {{quote}}\n{{#note}}Note: {{note}}{{/note}}",
|
Custom(string="> {{quote}}\n{{#note}}Note: {{note}}{{/note}}"),
|
||||||
"> I am the text value\nNote: Whereas I represent the note",
|
"> I am the text value\nNote: Whereas I represent the note",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"{{#note}}Note: {{note}}{{/note}}{{#page}}, p. {{page}}{{/page}}",
|
Custom(
|
||||||
|
string="{{#note}}Note: {{note}}{{/note}}{{#page}}, p. {{page}}{{/page}}"
|
||||||
|
),
|
||||||
"Note: Whereas I represent the note",
|
"Note: Whereas I represent the note",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -25,13 +28,13 @@ def test_formatting(fmt_string, expected):
|
||||||
|
|
||||||
assert sut.format(fmt_string) == expected
|
assert sut.format(fmt_string) == expected
|
||||||
|
|
||||||
|
|
||||||
def test_colorname_matches_exact():
|
def test_colorname_matches_exact():
|
||||||
sut = Annotation(
|
sut = Annotation("testfile", colors=(1.0, 0.0, 0.0), minimum_similarity_color=1.0)
|
||||||
"testfile", colors=(1.0,0.0,0.0), minimum_similarity_color=1.0
|
|
||||||
)
|
|
||||||
c_name = sut.colorname
|
c_name = sut.colorname
|
||||||
assert c_name == "red"
|
assert c_name == "red"
|
||||||
|
|
||||||
|
|
||||||
# TODO inject closeness value instead of relying on default
|
# TODO inject closeness value instead of relying on default
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"color_value",
|
"color_value",
|
||||||
|
@ -44,8 +47,6 @@ def test_colorname_matches_exact():
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_matches_inexact_colorname(color_value):
|
def test_matches_inexact_colorname(color_value):
|
||||||
sut = Annotation(
|
sut = Annotation("testfile", colors=color_value, minimum_similarity_color=0.833)
|
||||||
"testfile", colors=color_value, minimum_similarity_color=0.833
|
|
||||||
)
|
|
||||||
c_name = sut.colorname
|
c_name = sut.colorname
|
||||||
assert c_name == "red"
|
assert c_name == "red"
|
||||||
|
|
|
@ -1,14 +1,49 @@
|
||||||
import chevron
|
import chevron
|
||||||
|
|
||||||
from papis_extract.annotation_data import Markdown
|
from papis_extract.templating import Markdown, Csv
|
||||||
|
|
||||||
|
|
||||||
|
def test_template_markers():
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
def test_markdown_default():
|
def test_markdown_default():
|
||||||
fmt = Markdown()
|
fmt = Markdown()
|
||||||
assert chevron.render(fmt.string, {
|
assert (
|
||||||
"file": "somefile/somewhere.pdf",
|
chevron.render(
|
||||||
"quote": "I am quote",
|
fmt.string,
|
||||||
"note": "and including note.",
|
{
|
||||||
"page": 46,
|
"file": "somefile/somewhere.pdf",
|
||||||
"tag": "important",
|
"quote": "I am quote",
|
||||||
"type": "highlight",
|
"note": "and including note.",
|
||||||
}) == "#important\n> I am quote [p. 46]\n NOTE: and including note."
|
"page": 46,
|
||||||
|
"tag": "important",
|
||||||
|
"type": "highlight",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
== "#important\n> I am quote [p. 46]\n NOTE: and including note."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_csv_string():
|
||||||
|
fmt = Csv()
|
||||||
|
assert (
|
||||||
|
chevron.render(
|
||||||
|
fmt.string,
|
||||||
|
{
|
||||||
|
"file": "somefile/somewhere.pdf",
|
||||||
|
"quote": "I am quote",
|
||||||
|
"note": "and including note.",
|
||||||
|
"page": 46,
|
||||||
|
"tag": "important",
|
||||||
|
"type": "highlight",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
== "highlight, important, 46, "
|
||||||
|
"I am quote, and including note., somefile/somewhere.pdf"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_csv_header():
|
||||||
|
fmt = Csv()
|
||||||
|
assert chevron.render(fmt.header, {}) == "type, tag, page, quote, note, file"
|
||||||
|
|
Loading…
Reference in a new issue