import os import logging from urlparse import urljoin import six from pelican import signals from pelican.utils import pelican_open if not six.PY3: from codecs import open logger = logging.getLogger(__name__) source_files = [] PROCESS = ['articles', 'pages', 'drafts'] def link_source_files(generator): """ Processes each article/page object and formulates copy from and copy to destinations, as well as adding a source file URL as an attribute. """ # Get all attributes from the generator that are articles or pages posts = [ getattr(generator, attr, None) for attr in PROCESS if getattr(generator, attr, None) is not None] # Work on each item for post in posts[0]: if not 'SHOW_SOURCE_ON_SIDEBAR' in generator.settings and \ not 'SHOW_SOURCE_IN_SECTION' in generator.settings: return # Only try this when specified in metadata or SHOW_SOURCE_ALL_POSTS # override is present in settings if 'SHOW_SOURCE_ALL_POSTS' in generator.settings or \ 'show_source' in post.metadata: # Source file name can be optionally set in config show_source_filename = generator.settings.get( 'SHOW_SOURCE_FILENAME', '{}.txt'.format(post.slug) ) try: # Get the full path to the original source file source_out = os.path.join( post.settings['OUTPUT_PATH'], post.save_as ) # Get the path to the original source file source_out_path = os.path.split(source_out)[0] # Create 'copy to' destination for writing later copy_to = os.path.join( source_out_path, show_source_filename ) # Add file to published path source_url = urljoin( post.save_as, show_source_filename ) except Exception: return # Format post source dict & populate out = dict() out['copy_raw_from'] = post.source_path out['copy_raw_to'] = copy_to logger.debug('Linked %s to %s', post.source_path, copy_to) source_files.append(out) # Also add the source path to the post as an attribute for tpls post.show_source_url = source_url def _copy_from_to(from_file, to_file): """ A very rough and ready copy from / to function. """ with pelican_open(from_file) as text_in: encoding = 'utf-8' with open(to_file, 'w', encoding=encoding) as text_out: text_out.write(text_in) logger.info('Writing %s', to_file) def write_source_files(*args, **kwargs): """ Called by the `page_writer_finalized` signal to process source files. """ for source in source_files: _copy_from_to(source['copy_raw_from'], source['copy_raw_to']) def register(): """ Calls the shots, based on signals """ signals.article_generator_finalized.connect(link_source_files) signals.page_generator_finalized.connect(link_source_files) signals.page_writer_finalized.connect(write_source_files)