"""
Functions to import from various other static site generators
"""
# Refactoring idea: make this into its own sub-package and use a plugin system
import abc
import os
import shutil
import yaml
from .exceptions import UnableToImport
from .model import ABC
[docs]class Importer(ABC):
"""
Base class for all importers
:param site:
Site object for the destination
:param src_path:
Path to the thing to import
"""
def __init__(self, site, src_path):
self.site = site
self.src_path = src_path
[docs] @abc.abstractmethod
def run(self):
raise NotImplementedError
[docs] def ensure_directories(self):
for _dir in ('media', 'templates', 'pages', 'posts'):
path = os.path.join(self.site.site_path, _dir)
if not os.path.exists(path):
os.mkdir(path)
elif not os.path.isdir(path):
raise UnableToImport(
'{} exists but is not a directory'.format(path)
)
[docs]class Posty1Importer(Importer):
"""
Importer to pull from a Posty 1.x site
"""
[docs] def run(self):
self.ensure_directories()
self.import_media()
self.import_templates()
self.import_pages()
self.import_posts()
[docs] def import_media(self):
self._copy_files('_media', 'media')
[docs] def import_templates(self):
self._copy_files('_templates', 'templates')
[docs] def import_pages(self):
src_dir = os.path.join(self.src_path, '_pages')
dst_dir = os.path.join(self.site.site_path, 'pages')
for page in os.listdir(src_dir):
src_file = os.path.join(src_dir, page)
dst_file = os.path.join(dst_dir, page)
new_page = self._convert_page(open(src_file).read())
with open(dst_file, 'w') as fh:
fh.write(new_page)
[docs] def import_posts(self):
src_dir = os.path.join(self.src_path, '_posts')
dst_dir = os.path.join(self.site.site_path, 'posts')
for post in os.listdir(src_dir):
src_file = os.path.join(src_dir, post)
dst_file = os.path.join(dst_dir, post)
new_post = self._convert_post(open(src_file).read())
with open(dst_file, 'w') as fh:
fh.write(new_post)
def _copy_files(self, src, dst):
"""
Copy all the files in ``src_dir`` into ``dst_dir``. Each given dir
should be relative to the source/destination sites
:param src:
Relative path to copy files from in the source Posty 1 site
:param dst:
Relative path to copy files to in the destination Posty 2 site
"""
src_dir = os.path.join(self.src_path, src)
dst_dir = os.path.join(self.site.site_path, dst)
for _file in os.listdir(src_dir):
src_path = os.path.join(src_dir, _file)
dst_path = os.path.join(dst_dir, _file)
print("Copying {} to {}".format(src_path, dst_path))
if os.path.isfile(src_path):
shutil.copy(src_path, dst_path)
elif os.path.isdir(src_path):
shutil.copytree(src_path, dst_path)
else:
print((" Looks like {} isn't a file nor dir, "
"not copying.").format(src_path))
def _convert_page(self, old_page):
"""
Converts an old Posty 1.x page into a new-style one. Notably just
throws away any existing `url`
"""
old_page = old_page.replace("\r\n", "\n")
docs = old_page.split("---\n")
new_page = ''
meta = yaml.load(docs[1])
if 'url' in meta.keys():
del meta['url']
new_page += yaml.dump(meta, default_flow_style=False)
new_page += "---\n"
new_page += docs[2]
return new_page
def _convert_post(self, old_post):
"""
Converts an old Posty post (a string) into a new-style post with a
blurb and updated metadata. Returns a string containing the three YAML
documents.
:param old_post:
A string containing the contents of an old post file
"""
old_post = old_post.replace("\r\n", "\n")
docs = old_post.split("---\n")
new_post = ''
# Convert the metadata
meta = yaml.load(docs[1])
meta.setdefault('tags', [])
new_post += yaml.dump(meta, default_flow_style=False)
# Create a blurb out of the first paragraph
body = docs[2].strip().split("\n\n")
blurb = body[0]
rest_of_post = "\n\n".join(body[1:])
new_post += "---\n"
new_post += blurb
# Drop in the rest of the post
new_post += "\n---\n"
new_post += rest_of_post
return new_post