show_source.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import os
  2. import logging
  3. from urlparse import urljoin
  4. import six
  5. from pelican import signals
  6. from pelican.utils import pelican_open
  7. if not six.PY3:
  8. from codecs import open
  9. logger = logging.getLogger(__name__)
  10. source_files = []
  11. PROCESS = ['articles', 'pages', 'drafts']
  12. def link_source_files(generator):
  13. """
  14. Processes each article/page object and formulates copy from and copy
  15. to destinations, as well as adding a source file URL as an attribute.
  16. """
  17. # Get all attributes from the generator that are articles or pages
  18. posts = [
  19. getattr(generator, attr, None) for attr in PROCESS
  20. if getattr(generator, attr, None) is not None]
  21. # Work on each item
  22. for post in posts[0]:
  23. if not 'SHOW_SOURCE_ON_SIDEBAR' in generator.settings and \
  24. not 'SHOW_SOURCE_IN_SECTION' in generator.settings:
  25. return
  26. # Only try this when specified in metadata or SHOW_SOURCE_ALL_POSTS
  27. # override is present in settings
  28. if 'SHOW_SOURCE_ALL_POSTS' in generator.settings or \
  29. 'show_source' in post.metadata:
  30. # Source file name can be optionally set in config
  31. show_source_filename = generator.settings.get(
  32. 'SHOW_SOURCE_FILENAME', '{}.txt'.format(post.slug)
  33. )
  34. try:
  35. # Get the full path to the original source file
  36. source_out = os.path.join(
  37. post.settings['OUTPUT_PATH'], post.save_as
  38. )
  39. # Get the path to the original source file
  40. source_out_path = os.path.split(source_out)[0]
  41. # Create 'copy to' destination for writing later
  42. copy_to = os.path.join(
  43. source_out_path, show_source_filename
  44. )
  45. # Add file to published path
  46. source_url = urljoin(
  47. post.save_as, show_source_filename
  48. )
  49. except Exception:
  50. return
  51. # Format post source dict & populate
  52. out = dict()
  53. out['copy_raw_from'] = post.source_path
  54. out['copy_raw_to'] = copy_to
  55. logger.debug('Linked %s to %s', post.source_path, copy_to)
  56. source_files.append(out)
  57. # Also add the source path to the post as an attribute for tpls
  58. post.show_source_url = source_url
  59. def _copy_from_to(from_file, to_file):
  60. """
  61. A very rough and ready copy from / to function.
  62. """
  63. with pelican_open(from_file) as text_in:
  64. encoding = 'utf-8'
  65. with open(to_file, 'w', encoding=encoding) as text_out:
  66. text_out.write(text_in)
  67. logger.info('Writing %s', to_file)
  68. def write_source_files(*args, **kwargs):
  69. """
  70. Called by the `page_writer_finalized` signal to process source files.
  71. """
  72. for source in source_files:
  73. _copy_from_to(source['copy_raw_from'], source['copy_raw_to'])
  74. def register():
  75. """
  76. Calls the shots, based on signals
  77. """
  78. signals.article_generator_finalized.connect(link_source_files)
  79. signals.page_generator_finalized.connect(link_source_files)
  80. signals.page_writer_finalized.connect(write_source_files)