abstract IO for easier testing in the future
This commit is contained in:
parent
fc4f2fd7a7
commit
a524db1722
5 changed files with 119 additions and 29 deletions
|
@ -5,6 +5,8 @@ from pathlib import Path
|
||||||
from app import utils
|
from app import utils
|
||||||
from app.config import Configurator
|
from app.config import Configurator
|
||||||
from app.converter.wordpress_markdown import WordpressMarkdownConverter
|
from app.converter.wordpress_markdown import WordpressMarkdownConverter
|
||||||
|
from app.io.reader import FileReader
|
||||||
|
from app.io.writer import FileWriter
|
||||||
|
|
||||||
|
|
||||||
class Converter:
|
class Converter:
|
||||||
|
@ -44,7 +46,11 @@ class Converter:
|
||||||
_, _, files = next(os.walk(source_path))
|
_, _, files = next(os.walk(source_path))
|
||||||
for file in files:
|
for file in files:
|
||||||
source_abs_path = source_path / Path(file)
|
source_abs_path = source_path / Path(file)
|
||||||
|
|
||||||
|
file_reader = FileReader(str(source_abs_path))
|
||||||
|
file_writer = FileWriter(output_path.joinpath(source_abs_path.name))
|
||||||
|
|
||||||
self.markdown_converter.convert_jekyll_to_hugo(
|
self.markdown_converter.convert_jekyll_to_hugo(
|
||||||
source_abs_path,
|
file_reader,
|
||||||
output_path,
|
file_writer,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from bs4 import BeautifulSoup, Tag
|
from bs4 import BeautifulSoup, Tag
|
||||||
|
|
||||||
from app import utils
|
from app import utils
|
||||||
from app.config import Configurator
|
from app.config import Configurator
|
||||||
|
from app.io.reader import IoReader
|
||||||
|
from app.io.writer import IoWriter
|
||||||
from app.utils import key_error_silence
|
from app.utils import key_error_silence
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,53 +106,46 @@ class WordpressMarkdownConverter:
|
||||||
|
|
||||||
return "\n".join(fixed_lines)
|
return "\n".join(fixed_lines)
|
||||||
|
|
||||||
def read_jekyll_post(self, path: Path):
|
def read_jekyll_post(self, reader: IoReader):
|
||||||
"""
|
"""
|
||||||
Read a Jekyll post from the specified path
|
Read a Jekyll post from the reader.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
path : Path
|
reader : IoReader
|
||||||
The path to the Jekyll post
|
The IoReader instance for reading.
|
||||||
"""
|
"""
|
||||||
# read source
|
# read source
|
||||||
with open(path, "r") as fh:
|
return reader.read()
|
||||||
contents = fh.read()
|
|
||||||
return contents
|
|
||||||
|
|
||||||
def write_hugo_post(self, output_path, post_header: dict, post_content: str):
|
def write_hugo_post(self, writer: IoWriter, post_header: dict, post_content: str):
|
||||||
"""
|
"""
|
||||||
Write a Hugo post to the specified path
|
Write a Hugo post to the specified writer.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
output_path : Path
|
writer : IoWriter
|
||||||
The path to the Hugo post
|
The IoWriter instance for writing.
|
||||||
post_header : dict
|
post_header : dict
|
||||||
The post header
|
The post header
|
||||||
post_content : str
|
post_content : str
|
||||||
The post content
|
The post content
|
||||||
"""
|
"""
|
||||||
# ensure that output path exists
|
data = ["---\n", yaml.dump(post_header), "---\n", post_content]
|
||||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
writer.write("".join(data))
|
||||||
|
|
||||||
with open(output_path, "w") as fo:
|
def convert_jekyll_to_hugo(self, reader: IoReader, writer: IoWriter):
|
||||||
header = ["---\n", yaml.dump(post_header), "---\n"]
|
|
||||||
fo.writelines(header)
|
|
||||||
fo.write(post_content)
|
|
||||||
|
|
||||||
def convert_jekyll_to_hugo(self, jekyll_post_path: Path, hugo_post_output: Path):
|
|
||||||
"""
|
"""
|
||||||
Convert a Jekyll post to a Hugo post
|
Convert a Jekyll post to a Hugo post
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
jekyll_post_path : Path
|
reader : IoReader
|
||||||
The path to the Jekyll post
|
The IoReader instance for reading.
|
||||||
hugo_post_output : Path
|
writer : IoWriter
|
||||||
The path to the Hugo post
|
The IoWriter instance for writing.
|
||||||
"""
|
"""
|
||||||
contents = self.read_jekyll_post(jekyll_post_path)
|
contents = self.read_jekyll_post(reader)
|
||||||
|
|
||||||
# fix header
|
# fix header
|
||||||
header = yaml.safe_load(contents.split("---")[1])
|
header = yaml.safe_load(contents.split("---")[1])
|
||||||
|
@ -162,7 +155,7 @@ class WordpressMarkdownConverter:
|
||||||
fixed_post_content = self.convert_post_content(post_content)
|
fixed_post_content = self.convert_post_content(post_content)
|
||||||
|
|
||||||
self.write_hugo_post(
|
self.write_hugo_post(
|
||||||
hugo_post_output.joinpath(jekyll_post_path.name),
|
writer,
|
||||||
fixed_header,
|
fixed_header,
|
||||||
fixed_post_content,
|
fixed_post_content,
|
||||||
)
|
)
|
||||||
|
|
0
app/io/__init__.py
Normal file
0
app/io/__init__.py
Normal file
39
app/io/reader.py
Normal file
39
app/io/reader.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
from abc import ABCMeta, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class IoReader(metaclass=ABCMeta):
|
||||||
|
"""
|
||||||
|
Abstract class for reading posts.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def read(self) -> str:
|
||||||
|
"""
|
||||||
|
Reads a post.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class StringReader(IoReader):
|
||||||
|
"""
|
||||||
|
Reads a post from a string.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, content: str):
|
||||||
|
self._content = content
|
||||||
|
|
||||||
|
def read(self) -> str:
|
||||||
|
return self._content
|
||||||
|
|
||||||
|
|
||||||
|
class FileReader(IoReader):
|
||||||
|
"""
|
||||||
|
Reads a post from a local file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, file_path: str):
|
||||||
|
self._file_path = file_path
|
||||||
|
|
||||||
|
def read(self) -> str:
|
||||||
|
with open(self._file_path, "r") as file:
|
||||||
|
return file.read()
|
52
app/io/writer.py
Normal file
52
app/io/writer.py
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
from abc import abstractmethod, ABCMeta
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Callable
|
||||||
|
from app import utils
|
||||||
|
|
||||||
|
|
||||||
|
class IoWriter(metaclass=ABCMeta):
|
||||||
|
"""
|
||||||
|
Abstract class for writing posts.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def write(self, data: str):
|
||||||
|
"""
|
||||||
|
Write a post
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
data: str
|
||||||
|
The post data to write
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class FileWriter(IoWriter):
|
||||||
|
"""
|
||||||
|
Writes a post to a file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, output_path: Path):
|
||||||
|
utils.guard_against_none(output_path, "output_path")
|
||||||
|
|
||||||
|
self.output_path = output_path
|
||||||
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
def write(self, data: str):
|
||||||
|
with open(self.output_path, "w") as fo:
|
||||||
|
fo.write(data)
|
||||||
|
|
||||||
|
|
||||||
|
class CallbackWriter(IoWriter):
|
||||||
|
"""
|
||||||
|
Writes a post to a string.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, callback: Callable[[str], None]):
|
||||||
|
utils.guard_against_none(callback, "callback")
|
||||||
|
|
||||||
|
self.callback = callback
|
||||||
|
|
||||||
|
def write(self, data: str):
|
||||||
|
self.callback(data)
|
Loading…
Reference in a new issue