diff --git a/docs/faq.rst b/docs/faq.rst index bb9377e6..bf468c51 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -224,3 +224,8 @@ every time, so a ``rsync`` based upload will transfer them even if their content hasn't changed. A simple solution is to make ``rsync`` use the ``--checksum`` option, which will make it compare the file checksums in a much faster way than Pelican would. + +When only several specific output files are of interest (e.g. when +working on some specific page or the theme templates), the +`WRITE_SELECTED` option may help, see +:ref:`writing_only_selected_content`. diff --git a/docs/settings.rst b/docs/settings.rst index 9599ee10..8d8f9a16 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -179,6 +179,10 @@ Setting name (default value) `CHECK_MODIFIED_METHOD` (``mtime``) Controls how files are checked for modifications. `LOAD_CONTENT_CACHE` (``True``) If ``True``, load unmodified content from cache. `GZIP_CACHE` (``True``) If ``True``, use gzip to (de)compress the cache files. +`WRITE_SELECTED` (``[]``) If this list is not empty, **only** output files with their paths + in this list are written. Paths should be either relative to the current + working directory of Pelican or absolute. For possible use cases see + :ref:`writing_only_selected_content`. =============================================================================== ===================================================================== .. [#] Default is the system locale. @@ -774,6 +778,21 @@ written, so the modification times of the ``*.html`` files always change. Therefore, ``rsync`` based upload may benefit from the ``--checksum`` option. +.. _writing_only_selected_content: + +Writing only selected content +============================= + +When one article or page or the theme is being worked on it is often +desirable to display selected output files as soon as possible. In +such cases generating and writing all output is often unnecessary. +These selected output files can be given as output paths in the +`WRITE_SELECTED` list and **only** those files will be written. This +list can be also specified on the command-line using the +``--write-selected`` option which accepts a comma separated list +of output file paths. By default the list is empty so all output is +written. + Example settings ================ diff --git a/pelican/__init__.py b/pelican/__init__.py index b6bfe326..1ed98fc3 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -264,6 +264,10 @@ def parse_arguments(): parser.add_argument('-f', '--full-rebuild', action='store_true', dest='full_rebuild', help='Rebuild everything by not loading from cache') + parser.add_argument('-w', '--write-selected', type=str, + dest='selected_paths', default=None, + help='Comma separated list of selected paths to write') + return parser.parse_args() @@ -281,6 +285,8 @@ def get_config(args): config['DELETE_OUTPUT_DIRECTORY'] = args.delete_outputdir if args.full_rebuild: config['LOAD_CONTENT_CACHE'] = False + if args.selected_paths: + config['WRITE_SELECTED'] = args.selected_paths.split(',') # argparse returns bytes in Py2. There is no definite answer as to which # encoding argparse (or sys.argv) uses. diff --git a/pelican/settings.py b/pelican/settings.py index baf2a497..7615c25c 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -125,6 +125,7 @@ DEFAULT_CONFIG = { 'GZIP_CACHE': True, 'CHECK_MODIFIED_METHOD': 'mtime', 'LOAD_CONTENT_CACHE': True, + 'WRITE_SELECTED': [], } PYGMENTS_RST_OPTIONS = None @@ -200,6 +201,12 @@ def configure_settings(settings): raise Exception("Could not find the theme %s" % settings['THEME']) + # make paths selected for writing absolute if necessary + settings['WRITE_SELECTED'] = [ + os.path.abspath(path) for path in + settings.get('WRITE_SELECTED', DEFAULT_CONFIG['WRITE_SELECTED']) + ] + # standardize strings to lowercase strings for key in [ 'DEFAULT_LANG', diff --git a/pelican/tests/test_pelican.py b/pelican/tests/test_pelican.py index 974986cd..294cf399 100644 --- a/pelican/tests/test_pelican.py +++ b/pelican/tests/test_pelican.py @@ -138,3 +138,26 @@ class TestPelican(LoggedTestCase): for file in ['a_stylesheet', 'a_template']: self.assertTrue(os.path.exists(os.path.join(theme_output, file))) + + def test_write_only_selected(self): + """Test that only the selected files are written""" + settings = read_settings(path=None, override={ + 'PATH': INPUT_PATH, + 'OUTPUT_PATH': self.temp_path, + 'CACHE_DIRECTORY': self.temp_cache, + 'WRITE_SELECTED': [ + os.path.join(self.temp_path, 'oh-yeah.html'), + os.path.join(self.temp_path, 'categories.html'), + ], + 'LOCALE': locale.normalize('en_US'), + }) + pelican = Pelican(settings=settings) + logger = logging.getLogger() + orig_level = logger.getEffectiveLevel() + logger.setLevel(logging.INFO) + mute(True)(pelican.run)() + logger.setLevel(orig_level) + self.assertLogCountEqual( + count=2, + msg="writing .*", + level=logging.INFO) diff --git a/pelican/utils.py b/pelican/utils.py index 8c416921..cd942fd5 100644 --- a/pelican/utils.py +++ b/pelican/utils.py @@ -658,3 +658,17 @@ class FileStampDataCacher(FileDataCacher): if stamp != self._get_file_stamp(filename): return default return data + + +def is_selected_for_writing(settings, path): + '''Check whether path is selected for writing + according to the WRITE_SELECTED list + + If WRITE_SELECTED is an empty list (default), + any path is selected for writing. + ''' + if settings['WRITE_SELECTED']: + return path in settings['WRITE_SELECTED'] + else: + return True + diff --git a/pelican/writers.py b/pelican/writers.py index 19e36e39..a92feee4 100644 --- a/pelican/writers.py +++ b/pelican/writers.py @@ -16,7 +16,8 @@ from feedgenerator import Atom1Feed, Rss201rev2Feed from jinja2 import Markup from pelican.paginator import Paginator -from pelican.utils import get_relative_path, path_to_url, set_date_tzinfo +from pelican.utils import (get_relative_path, path_to_url, set_date_tzinfo, + is_selected_for_writing) from pelican import signals logger = logging.getLogger(__name__) @@ -92,6 +93,8 @@ class Writer(object): :param path: the path to output. :param feed_type: the feed type to use (atom or rss) """ + if not is_selected_for_writing(self.settings, path): + return old_locale = locale.setlocale(locale.LC_ALL) locale.setlocale(locale.LC_ALL, str('C')) try: @@ -140,7 +143,9 @@ class Writer(object): :param **kwargs: additional variables to pass to the templates """ - if name is False or name == "": + if name is False or name == "" or\ + not is_selected_for_writing(self.settings,\ + os.path.join(self.output_path, name)): return elif not name: # other stuff, just return for now