def test_custom_pagination_pattern_last_page(self): from pelican.paginator import PaginationRule settings = get_settings() settings['PAGINATION_PATTERNS'] = [ PaginationRule(*r) for r in [ (1, '/{url}1/', '{base_name}/1/index.html'), (2, '/{url}{number}/', '{base_name}/{number}/index.html'), (-1, '/{url}', '{base_name}/index.html'), ] ] self.page_kwargs['metadata']['author'] = Author('Blogger', settings) object_list = [ Article(**self.page_kwargs), Article(**self.page_kwargs), Article(**self.page_kwargs) ] paginator = Paginator('blog/index.html', '//blog.my.site/', object_list, settings, 1) # The URL *has to* stay absolute (with // in the front), so verify that page1 = paginator.page(1) self.assertEqual(page1.save_as, 'blog/1/index.html') self.assertEqual(page1.url, '//blog.my.site/1/') page2 = paginator.page(2) self.assertEqual(page2.save_as, 'blog/2/index.html') self.assertEqual(page2.url, '//blog.my.site/2/') page3 = paginator.page(3) self.assertEqual(page3.save_as, 'blog/index.html') self.assertEqual(page3.url, '//blog.my.site/')
def test_save_as_preservation(self): settings = get_settings() # fix up pagination rules from pelican.paginator import PaginationRule pagination_rules = [ PaginationRule(*r) for r in settings.get( 'PAGINATION_PATTERNS', DEFAULT_CONFIG['PAGINATION_PATTERNS'], ) ] settings['PAGINATION_PATTERNS'] = sorted( pagination_rules, key=lambda r: r[0], ) object_list = [ Article(**self.page_kwargs), Article(**self.page_kwargs) ] paginator = Paginator('foobar.foo', object_list, settings) page = paginator.page(1) self.assertEqual(page.save_as, 'foobar.foo')
def test_custom_pagination_pattern(self): from pelican.paginator import PaginationRule settings = get_settings() settings['PAGINATION_PATTERNS'] = [ PaginationRule(*r) for r in [(1, '/{url}', '{base_name}/index.html'), (2, '/{url}{number}/', '{base_name}/{number}/index.html')] ] self.page_kwargs['metadata']['author'] = Author('Blogger', settings) object_list = [ Article(**self.page_kwargs), Article(**self.page_kwargs) ] paginator = Paginator('blog/index.html', '//blog.my.site/', object_list, settings, 1) page1 = paginator.page(1) self.assertEqual(page1.save_as, 'blog/index.html') self.assertEqual(page1.url, '//blog.my.site/') page2 = paginator.page(2) self.assertEqual(page2.save_as, 'blog/2/index.html') self.assertEqual(page2.url, '//blog.my.site/2/')
def configure_settings(settings): """Provide optimizations, error checking, and warnings for the given settings. Also, specify the log messages to be ignored. """ if 'PATH' not in settings or not os.path.isdir(settings['PATH']): raise Exception('You need to specify a path containing the content' ' (see pelican --help for more information)') # specify the log messages to be ignored log_filter = settings.get('LOG_FILTER', DEFAULT_CONFIG['LOG_FILTER']) LimitFilter._ignore.update(set(log_filter)) # lookup the theme in "pelican/themes" if the given one doesn't exist if not os.path.isdir(settings['THEME']): theme_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'themes', settings['THEME']) if os.path.exists(theme_path): settings['THEME'] = theme_path else: 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']: if key in settings: settings[key] = settings[key].lower() # set defaults for Jinja environment settings = get_jinja_environment(settings) # standardize strings to lists for key in ['LOCALE']: if key in settings and isinstance(settings[key], six.string_types): settings[key] = [settings[key]] # check settings that must be a particular type for key, types in [ ('OUTPUT_SOURCES_EXTENSION', six.string_types), ('FILENAME_METADATA', six.string_types), ]: if key in settings and not isinstance(settings[key], types): value = settings.pop(key) logger.warn( 'Detected misconfigured %s (%s), ' 'falling back to the default (%s)', key, value, DEFAULT_CONFIG[key]) # try to set the different locales, fallback on the default. locales = settings.get('LOCALE', DEFAULT_CONFIG['LOCALE']) for locale_ in locales: try: locale.setlocale(locale.LC_ALL, str(locale_)) break # break if it is successful except locale.Error: pass else: logger.warning( "Locale could not be set. Check the LOCALE setting, ensuring it " "is valid and available on your system.") if ('SITEURL' in settings): # If SITEURL has a trailing slash, remove it and provide a warning siteurl = settings['SITEURL'] if (siteurl.endswith('/')): settings['SITEURL'] = siteurl[:-1] logger.warning("Removed extraneous trailing slash from SITEURL.") # If SITEURL is defined but FEED_DOMAIN isn't, # set FEED_DOMAIN to SITEURL if 'FEED_DOMAIN' not in settings: settings['FEED_DOMAIN'] = settings['SITEURL'] # check content caching layer and warn of incompatibilities if settings.get('CACHE_CONTENT', False) and \ settings.get('CONTENT_CACHING_LAYER', '') == 'generator' and \ settings.get('WITH_FUTURE_DATES', False): logger.warning( "WITH_FUTURE_DATES conflicts with CONTENT_CACHING_LAYER " "set to 'generator', use 'reader' layer instead") # Warn if feeds are generated with both SITEURL & FEED_DOMAIN undefined feed_keys = [ 'FEED_ATOM', 'FEED_RSS', 'FEED_ALL_ATOM', 'FEED_ALL_RSS', 'CATEGORY_FEED_ATOM', 'CATEGORY_FEED_RSS', 'AUTHOR_FEED_ATOM', 'AUTHOR_FEED_RSS', 'TAG_FEED_ATOM', 'TAG_FEED_RSS', 'TRANSLATION_FEED_ATOM', 'TRANSLATION_FEED_RSS', ] if any(settings.get(k) for k in feed_keys): if not settings.get('SITEURL'): logger.warning('Feeds generated without SITEURL set properly may' ' not be valid') if 'TIMEZONE' not in settings: logger.warning( 'No timezone information specified in the settings. Assuming' ' your timezone is UTC for feed generation. Check ' 'http://docs.getpelican.com/en/latest/settings.html#timezone ' 'for more information') # fix up pagination rules from pelican.paginator import PaginationRule pagination_rules = [ PaginationRule(*r) for r in settings.get( 'PAGINATION_PATTERNS', DEFAULT_CONFIG['PAGINATION_PATTERNS'], ) ] settings['PAGINATION_PATTERNS'] = sorted( pagination_rules, key=lambda r: r[0], ) # Save people from accidentally setting a string rather than a list path_keys = ( 'ARTICLE_EXCLUDES', 'DEFAULT_METADATA', 'DIRECT_TEMPLATES', 'THEME_TEMPLATES_OVERRIDES', 'FILES_TO_COPY', 'IGNORE_FILES', 'PAGINATED_DIRECT_TEMPLATES', 'PLUGINS', 'STATIC_EXCLUDES', 'STATIC_PATHS', 'THEME_STATIC_PATHS', 'ARTICLE_PATHS', 'PAGE_PATHS', ) for PATH_KEY in filter(lambda k: k in settings, path_keys): if isinstance(settings[PATH_KEY], six.string_types): logger.warning( "Detected misconfiguration with %s setting " "(must be a list), falling back to the default", PATH_KEY) settings[PATH_KEY] = DEFAULT_CONFIG[PATH_KEY] # Add {PAGE,ARTICLE}_PATHS to {ARTICLE,PAGE}_EXCLUDES mutually_exclusive = ('ARTICLE', 'PAGE') for type_1, type_2 in [mutually_exclusive, mutually_exclusive[::-1]]: try: includes = settings[type_1 + '_PATHS'] excludes = settings[type_2 + '_EXCLUDES'] for path in includes: if path not in excludes: excludes.append(path) except KeyError: continue # setting not specified, nothing to do return settings
def configure_settings(settings): """Provide optimizations, error checking, and warnings for the given settings. Also, specify the log messages to be ignored. """ if not 'PATH' in settings or not os.path.isdir(settings['PATH']): raise Exception('You need to specify a path containing the content' ' (see pelican --help for more information)') # specify the log messages to be ignored LimitFilter.ignore.update( set(settings.get('LOG_FILTER', DEFAULT_CONFIG['LOG_FILTER']))) # lookup the theme in "pelican/themes" if the given one doesn't exist if not os.path.isdir(settings['THEME']): theme_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'themes', settings['THEME']) if os.path.exists(theme_path): settings['THEME'] = theme_path else: 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', ]: if key in settings: settings[key] = settings[key].lower() # standardize strings to lists for key in [ 'LOCALE', ]: if key in settings and isinstance(settings[key], six.string_types): settings[key] = [settings[key]] # check settings that must be a particular type for key, types in [ ('OUTPUT_SOURCES_EXTENSION', six.string_types), ('FILENAME_METADATA', six.string_types), ]: if key in settings and not isinstance(settings[key], types): value = settings.pop(key) logger.warn('Detected misconfigured {} ({}), ' 'falling back to the default ({})'.format( key, value, DEFAULT_CONFIG[key])) # try to set the different locales, fallback on the default. locales = settings.get('LOCALE', DEFAULT_CONFIG['LOCALE']) for locale_ in locales: try: locale.setlocale(locale.LC_ALL, str(locale_)) break # break if it is successful except locale.Error: pass else: logger.warning("LOCALE option doesn't contain a correct value") if ('SITEURL' in settings): # If SITEURL has a trailing slash, remove it and provide a warning siteurl = settings['SITEURL'] if (siteurl.endswith('/')): settings['SITEURL'] = siteurl[:-1] logger.warning("Removed extraneous trailing slash from SITEURL.") # If SITEURL is defined but FEED_DOMAIN isn't, # set FEED_DOMAIN to SITEURL if not 'FEED_DOMAIN' in settings: settings['FEED_DOMAIN'] = settings['SITEURL'] # check content caching layer and warn of incompatibilities if (settings.get('CACHE_CONTENT', False) and settings.get('CONTENT_CACHING_LAYER', '') == 'generator' and settings.get('WITH_FUTURE_DATES', DEFAULT_CONFIG['WITH_FUTURE_DATES'])): logger.warning('WITH_FUTURE_DATES conflicts with ' "CONTENT_CACHING_LAYER set to 'generator', " "use 'reader' layer instead") # Warn if feeds are generated with both SITEURL & FEED_DOMAIN undefined feed_keys = [ 'FEED_ATOM', 'FEED_RSS', 'FEED_ALL_ATOM', 'FEED_ALL_RSS', 'CATEGORY_FEED_ATOM', 'CATEGORY_FEED_RSS', 'AUTHOR_FEED_ATOM', 'AUTHOR_FEED_RSS', 'TAG_FEED_ATOM', 'TAG_FEED_RSS', 'TRANSLATION_FEED_ATOM', 'TRANSLATION_FEED_RSS', ] if any(settings.get(k) for k in feed_keys): if not settings.get('SITEURL'): logger.warning('Feeds generated without SITEURL set properly may' ' not be valid') if not 'TIMEZONE' in settings: logger.warning( 'No timezone information specified in the settings. Assuming' ' your timezone is UTC for feed generation. Check ' 'http://docs.getpelican.com/en/latest/settings.html#timezone ' 'for more information') # fix up pagination rules from pelican.paginator import PaginationRule pagination_rules = [ PaginationRule(*r) for r in settings.get( 'PAGINATION_PATTERNS', DEFAULT_CONFIG['PAGINATION_PATTERNS'], ) ] settings['PAGINATION_PATTERNS'] = sorted( pagination_rules, key=lambda r: r[0], ) # Save people from accidentally setting a string rather than a list path_keys = ( 'ARTICLE_EXCLUDES', 'DEFAULT_METADATA', 'DIRECT_TEMPLATES', 'EXTRA_TEMPLATES_PATHS', 'FILES_TO_COPY', 'IGNORE_FILES', 'JINJA_EXTENSIONS', 'PAGINATED_DIRECT_TEMPLATES', 'PLUGINS', 'STATIC_PATHS', 'THEME_STATIC_PATHS', ) for PATH_KEY in filter(lambda k: k in settings, path_keys): if isinstance(settings[PATH_KEY], six.string_types): logger.warning("Detected misconfiguration with %s setting " "(must be a list), falling back to the default" % PATH_KEY) settings[PATH_KEY] = DEFAULT_CONFIG[PATH_KEY] for old, new, doc in [ ('LESS_GENERATOR', 'the Webassets plugin', None), ('FILES_TO_COPY', 'STATIC_PATHS and EXTRA_PATH_METADATA', 'https://github.com/getpelican/pelican/blob/master/docs/settings.rst#path-metadata' ), ]: if old in settings: message = 'The {} setting has been removed in favor of {}'.format( old, new) if doc: message += ', see {} for details'.format(doc) logger.warning(message) return settings