# HG changeset patch # User Nolan Prescott # Date 1578252839 18000 # Sun Jan 05 14:33:59 2020 -0500 # Node ID 7b9138d04c9ae13fdeabd49d70e5627348eb5c50 # Parent 0c51ed1810928c5e9b79d147a14c4ff97189342d add integration test sort of horrible, I'm not sure if these are actually good changes. Partly necessary due to the addition of threadpooling, but the feedback is poor and they're obviously fragile. diff --git a/quiescent/bootstrap.py b/quiescent/bootstrap.py --- a/quiescent/bootstrap.py +++ b/quiescent/bootstrap.py @@ -42,7 +42,7 @@ @@ -58,9 +58,9 @@ -

{{ post.date }}, {{ post.title }}

+

{{ post.date_string }}, {{ post.title }}

- {{ post.body }} + {{ post.html_body }}
@@ -76,7 +76,7 @@ {% for post in front_posts %}

{{ post.title }}

- {{ post.leader }} + {{ post.html_leader }} {% endfor %} diff --git a/quiescent/static.py b/quiescent/static.py --- a/quiescent/static.py +++ b/quiescent/static.py @@ -78,9 +78,7 @@ def render_page(self, template_name): template_file = os.path.join(self.config.template_dir, template_name) with open(template_file, encoding='utf-8') as f: - template_text = f.read() - template = Templite(template_text) - return template + return Templite(f.read()) def collect_posts(self, from_dir): ''' @@ -95,16 +93,19 @@ return post_files def find_media_directories(self, directory, media_directory): - return [os.path.join(root, dir) for root, directories, _ in os.walk(directory) - for dir in directories if dir == media_directory] + return (os.path.join(root, dir) for root, directories, _ in os.walk(directory) + for dir in directories if dir == media_directory) def copy_media(self): def copies_required(directory): - relative_dest_dir = os.path.relpath(directory, self.config.posts_dir) - out_path = os.path.join(self.config.output_dir, relative_dest_dir) - os.makedirs(out_path, exist_ok=True) - return ((os.path.join(directory, filename), out_path) - for filename in os.listdir(directory)) + try: + relative_dest_dir = os.path.relpath(directory, self.config.posts_dir) + out_path = os.path.join(self.config.output_dir, relative_dest_dir) + os.makedirs(out_path, exist_ok=True) + return ((os.path.join(directory, filename), out_path) + for filename in os.listdir(directory)) + except Exception as e: + logger.error(e) with concurrent.futures.ThreadPoolExecutor() as executor: media_dirs = self.find_media_directories(self.config.posts_dir, @@ -122,19 +123,22 @@ post = process(parse(text)) self.all_posts.append(post) except Exception as e: - logger.warning('Failed to create post: {post}\n\t{e}' - .format(post=post, e=e)) + logger.warning('Failed to create post: {name}\n\t{e}' + .format(name=filename, e=e)) self.all_posts = sorted(self.all_posts, key=lambda p: p.date_time, reverse=True) def write_generated_files(self): def write_post(post): - post_page = self.post_template.render({'post': post}) - output_tree = os.path.dirname(os.path.join(self.config.output_dir, post.path)) - # reconstitute the input tree in the output directory - os.makedirs(output_tree, exist_ok=True) - output_path = os.path.join(self.config.output_dir, post.path) - with open(output_path, 'w', encoding='utf-8') as f: - f.write(post_page) + try: + post_page = self.post_template.render({'post': post}) + output_tree = os.path.dirname(os.path.join(self.config.output_dir, post.path)) + # reconstitute the input tree in the output directory + os.makedirs(output_tree, exist_ok=True) + output_path = os.path.join(self.config.output_dir, post.path) + with open(output_path, 'w', encoding='utf-8') as f: + f.write(post_page) + except Exception as e: + logger.error(e) with concurrent.futures.ThreadPoolExecutor() as executor: for post in self.all_posts: diff --git a/quiescent/tests/golden/2020/example-post.html b/quiescent/tests/golden/2020/example-post.html new file mode 100644 --- /dev/null +++ b/quiescent/tests/golden/2020/example-post.html @@ -0,0 +1,15 @@ + + + + + + + +

2020-01-01, Example Post

+
+

This is an example.

+

This is the body of the example.

+ +
+ + diff --git a/quiescent/tests/golden/2020/media/foo.png b/quiescent/tests/golden/2020/media/foo.png new file mode 100644 diff --git a/quiescent/tests/golden/archive.html b/quiescent/tests/golden/archive.html new file mode 100644 --- /dev/null +++ b/quiescent/tests/golden/archive.html @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/quiescent/tests/golden/feed.atom b/quiescent/tests/golden/feed.atom new file mode 100644 --- /dev/null +++ b/quiescent/tests/golden/feed.atom @@ -0,0 +1,3 @@ +Example Name2020-01-05T18:31:34.424723+00:00Example Authorhttp://example.comExample Posthttp://example.com/2020/example-post.html2020-01-01T00:00:00+00:00<p>This is an example.</p> +<p>This is the body of the example.</p> + \ No newline at end of file diff --git a/quiescent/tests/golden/index.html b/quiescent/tests/golden/index.html new file mode 100644 --- /dev/null +++ b/quiescent/tests/golden/index.html @@ -0,0 +1,14 @@ + + + + + + + + +

Example Post

+

This is an example.

+ + + + diff --git a/quiescent/tests/test_integration.py b/quiescent/tests/test_integration.py new file mode 100644 --- /dev/null +++ b/quiescent/tests/test_integration.py @@ -0,0 +1,60 @@ +import unittest +import subprocess +import tempfile +import filecmp +import shlex +import os.path +import logging + +logger = logging.getLogger(__name__) + +def directories_same(dir1, dir2): + directory_compare = filecmp.dircmp(dir1, dir2) + if any([len(differences) > 0 for differences in (directory_compare.left_only, + directory_compare.right_only, + directory_compare.funny_files)]): + logger.error(f'left only: {directory_compare.left_only}\n' + f'right only: {directory_compare.right_only}') + return False + (_, mismatch, errors) = filecmp.cmpfiles(dir1, dir2, + directory_compare.common_files, + shallow=False) + + # this is terrible, atom feed contains a generation timestamp so + # it is always different. the if-clause is necessary due to the + # recursion, early checks will remove it, later will error out + # without it + if 'feed.atom' in mismatch: mismatch.remove('feed.atom') + + if any([len(e) > 0 for e in (mismatch, errors)]): + logger.error(f'MISMATCH: {mismatch}') + return False + for common_dir in directory_compare.common_dirs: + new_dir1 = os.path.join(dir1, common_dir) + new_dir2 = os.path.join(dir2, common_dir) + if not directories_same(new_dir1, new_dir2): + return False + return True + +class IntegrationTests(unittest.TestCase): + def test_construct_site(self): + with tempfile.TemporaryDirectory() as source: + subprocess.run(shlex.split('quiescent --bootstrap'), cwd=source) + os.makedirs(os.path.join(source, 'posts', '2020'), exist_ok=True) + os.makedirs(os.path.join(source, 'posts', '2020', 'media'), exist_ok=True) + with open(os.path.join(source, 'posts', '2020', 'media', 'foo.png'), 'wb') as m: + m.write(b'') + with open(os.path.join(source, 'posts', '2020', 'example-post.md'), 'w') as f: + post_contents = """title: Example Post +date: 2020-01-01 ++++ + +This is an example. + +This is the body of the example. +""" + f.write(post_contents) + subprocess.run('quiescent', cwd=source) + golden_copy = os.path.abspath(os.path.join(os.path.abspath(__file__), os.pardir, 'golden')) + built_output = os.path.join(source, 'build') + self.assertTrue(directories_same(golden_copy, built_output))