예제 #1
0
def test_append_chapter():
    graph = ChapterGraph()

    chapter = Chapter(name='foo')
    graph.append(chapter)

    assert graph.first.chapter == chapter
    assert graph.last.chapter == chapter
예제 #2
0
def test_append_chapter_with_children():
    graph = ChapterGraph()

    chapter = Chapter(name='foo',
                      children=[Chapter(name='bar'),
                                Chapter(name='baz')])
    graph.append(chapter)

    assert graph.first.chapter == chapter
    assert graph.last.chapter == chapter.children[1]
예제 #3
0
파일: renderer.py 프로젝트: swquinn/hon
 def __init__(self, app, config=None):
     self.app = app
     self.config = config or dict(self.default_config)
     self.chapters = []
     self.chapter_graph = ChapterGraph()
예제 #4
0
파일: renderer.py 프로젝트: swquinn/hon
class Renderer(object):
    default_config = {}

    @property
    def items(self):
        """A tuple containing all of the chapters."""
        chapters = []
        for node in iter(self.chapter_graph):
            chapters.append(node.chapter)
        return tuple(chapters)

    @property
    def render_path(self):
        if 'output_dir' in self.config:
            return self.config['output_dir']
        return self.get_name()

    @property
    def name(self):
        return self.get_name()

    def __init__(self, app, config=None):
        self.app = app
        self.config = config or dict(self.default_config)
        self.chapters = []
        self.chapter_graph = ChapterGraph()

    def add_chapter(self, chapter):
        """Adds a chapter to the renderer."""
        self.chapters.append(chapter)

    def add_chapters(self, chapters):
        """Adds all chapters to a book, updating the graph."""
        for chapter in chapters:
            self.add_chapter(chapter)

    @classmethod
    def get_build_render_option(cls):
        _name = cls.get_name()

        def callback(ctx, param, value):
            from hon.cli import ScriptInfo
            state = ctx.ensure_object(ScriptInfo)
            state.build_renderers[_name] = value
            return value

        renderer_flag = '--{_name}/--no-{_name}'.format(_name=_name)
        help_text = 'Enable/Disable rendering using the {_name} renderer'.format(_name=_name)
        return click.Option(
            [renderer_flag],
            help=help_text,
            callback=callback,
            is_eager=True,
            is_flag=True,
            default=True)

    @classmethod
    def get_name(cls):
        if not cls._name:
            raise ValueError(('The renderer: {} is missing a name. Did '
                'you forget to assign the `_name` property? All renderers '
                'must have a name. E.g. "html", "pdf", etc.').format(
                cls.__name__))
        return cls._name

    def finish(self, book, context):
        self.app.logger.debug('Finishing render...')
        self.on_before_finish(book, context)
        self.on_finish(book, context)
        hon.finish_render.send(self.app, book=book, renderer=self, context=context)

    def generate_assets(self, book, context):
        """Generate assets.
        """
        self.app.logger.debug('Generating assets...')
        self.on_generate_assets(book, context)

        #:
        hon.generate_assets.send(self.app, book=book, renderer=self, context=context)

    def generate_pages(self, book, context):
        self.app.logger.debug('Generating pages...')

        # TODO: Write the README.md to file
        # TODO: Write the SUMMARY.md to file
        # TODO: Write the GLOSSARY.md to file

        for item in self.items:
            hon.before_render_page.send(self.app, book=book, renderer=self, page=item)
            self.on_render_page(item, book, context)
            hon.after_render_page.send(self.app, book=book, renderer=self, page=item)
        self.on_generate_pages(book, context)

    def init(self, book):
        self.app.logger.debug('Initializing renderer...')
        context = RenderContext(book=book, render_path=self.render_path)

        self.on_init(book, context)
        return context

    def init_chapters(self, book):
        """Use the book's summary to load the book's pages from disk."""
        self.app.logger.debug('Loading chapters from disk')

        summary_items = book.summary.all_parts
        for item in summary_items:
            if type(item) == Part:
                chapter = self.load_chapter(book, item)
                self.add_chapter(chapter)
        self.build_chapter_graph()
        return self.chapters
    
    def build_chapter_graph(self):
        self.chapter_graph = ChapterGraph()
        self.chapter_graph.extend(self.chapters)

    def load_chapter(self, book, item, parent=None):
        chapter = None
        chapter_path = os.path.abspath(os.path.join(book.path, item.source))

        if not os.path.exists(chapter_path):
            raise FileNotFoundError('File: {} not found.'.format(chapter_path))

        with open(chapter_path) as f:
            raw = f.read()
            chapter = Chapter(name=item.name, raw_text=raw, path=chapter_path, link=item.link, parent=parent)

        if not chapter:
            raise TypeError('Chapter not created')

        sub_chapters = []
        if item.children:
            for sub_item in item.children:
                sub_chapter = self.load_chapter(book, sub_item, parent=item)
                sub_chapters.append(sub_chapter)

        if sub_chapters:
            chapter.children = sub_chapters
        return chapter

    def on_before_finish(self, book, context):
        pass

    def on_finish(self, book, context):
        pass

    def on_generate_assets(self, book, context):
        pass

    def on_generate_pages(self, book, context):
        pass

    def on_init(self, book, context):
        pass

    def on_render_page(self, page, book, context):
        pass

    def render(self, book):
        """
        """
        self.app.logger.info('Rendering book: {} with: {} renderer'
            .format(book.name, self.get_name()))

        start_time = datetime.now()

        chapters = self.init_chapters(book)
        self.app.logger.debug('Successfully loaded {} chapters.'.format(len(chapters)))

        context = self.init(book)
        print()
        print()
        print('***')
        print('renderer ({}): context.data => {}'.format(self.name, context.data))
        print('***')
        print()
        print()

        #: We now preprocess for each renderer, this gives our preprocessors
        #: access to the not only the book, but also the context. [SWQ]
        for preprocessor in self.app.preprocessors:
            if preprocessor.enabled:
                self.app.logger.debug("Running the {} preprocessor.".format(preprocessor.name))
                preprocessor.run(book, self, context)

        #: After the context has been established and the preprocessors have
        #: been run, but before any of the actual rendering has commenced,
        #: trigger the "before_render" signal. This will allow more general
        #: plugins the opportunity to do some pre-render work. They can modify
        #: the context, or even make changes to the render items. [SWQ]
        hon.before_render.send(self.app, book=book, renderer=self, context=context)

        #: Run the logic for the renderer, this includes generating assets,
        #: pages, and finalizing the book's renderering.
        self.generate_assets(book, context)
        self.generate_pages(book, context)
        self.finish(book, context)

        #: After the book has been rendered, do any final clean up.
        hon.after_render.send(self.app, book=book, renderer=self, context=context)

        elapsed_time = datetime.now() - start_time
        self.app.logger.info('Finished rendering book: {} with: {} successfully in {}s!'.format(
            book.name, self.get_name(), elapsed_time))
예제 #5
0
파일: renderer.py 프로젝트: swquinn/hon
 def build_chapter_graph(self):
     self.chapter_graph = ChapterGraph()
     self.chapter_graph.extend(self.chapters)
예제 #6
0
def test_get_returns_none_for_unknown_chapter(chapters):
    graph = ChapterGraph(chapters)

    actual = graph.get(Chapter(name='Foobarbaz'))
    assert actual is None
예제 #7
0
def test_get(chapters):
    graph = ChapterGraph(chapters)

    actual = graph.get(chapters[1].children[1])
    assert actual is not None
    assert actual.chapter.name == 'Chapter 2-B'
예제 #8
0
def test_extend(chapters):
    graph = ChapterGraph()
    graph.extend(chapters)

    assert graph.first.chapter == chapters[0]
    assert graph.last.chapter == chapters[2].children[1]
예제 #9
0
def test_instantiate():
    graph = ChapterGraph()

    assert graph.first is None
    assert graph.last is None