From 901374cbd75292493648854e40484d6ab3c4ad61 Mon Sep 17 00:00:00 2001 From: Roberto Alsina Date: Sat, 15 Aug 2015 10:34:55 -0300 Subject: [PATCH 1/6] keep disabled compilers state --- nikola/nikola.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nikola/nikola.py b/nikola/nikola.py index d9c96c94ee..2360d4d781 100644 --- a/nikola/nikola.py +++ b/nikola/nikola.py @@ -735,19 +735,19 @@ def __init__(self, **config): # And put them in "bad compilers" pp_exts = set([os.path.splitext(x[0])[1] for x in self.config['post_pages']]) self.config['COMPILERS'] = {} - bad_compilers = set([]) + self.disabled_compilers = set([]) for k, v in compilers.items(): if pp_exts.intersection(v): self.config['COMPILERS'][k] = sorted(list(v)) else: - bad_compilers.add(k) + self.disabled_compilers.add(k) self.plugin_manager.getPluginLocator().setPluginPlaces(places) self.plugin_manager.locatePlugins() bad_candidates = set([]) for p in self.plugin_manager._candidates: # Remove compilers we don't use - if p[-1].name in bad_compilers: + if p[-1].name in self.disabled_compilers: bad_candidates.add(p) utils.LOGGER.debug('Not loading unneeded compiler {}', p[-1].name) # Remove blacklisted plugins @@ -755,7 +755,7 @@ def __init__(self, **config): bad_candidates.add(p) utils.LOGGER.debug('Not loading disabled plugin {}', p[-1].name) # Remove compiler extensions we don't need - if p[-1].details.has_option('Nikola', 'compiler') and p[-1].details.get('Nikola', 'compiler') in bad_compilers: + if p[-1].details.has_option('Nikola', 'compiler') and p[-1].details.get('Nikola', 'compiler') in self.disabled_compilers: bad_candidates.add(p) utils.LOGGER.debug('Not loading comopiler extension {}', p[-1].name) self.plugin_manager._candidates = list(set(self.plugin_manager._candidates) - bad_candidates) From 473fd1b290f734b9460f2c0371b25d22681782ae Mon Sep 17 00:00:00 2001 From: Roberto Alsina Date: Sat, 15 Aug 2015 10:51:36 -0300 Subject: [PATCH 2/6] recfactor print_compilers and filter_post_pages into the plugin class --- nikola/plugins/command/new_post.py | 212 +++++++++++++++-------------- 1 file changed, 108 insertions(+), 104 deletions(-) diff --git a/nikola/plugins/command/new_post.py b/nikola/plugins/command/new_post.py index 7c99827780..8ae7551d5c 100644 --- a/nikola/plugins/command/new_post.py +++ b/nikola/plugins/command/new_post.py @@ -46,103 +46,6 @@ LOGGER = POSTLOGGER -def filter_post_pages(compiler, is_post, compilers, post_pages, compiler_objs, compilers_raw): - """Return the correct entry from post_pages. - - Information based on: - * selected compilers - * available compilers - * post/page status - """ - # First throw away all the post_pages with the wrong is_post - filtered = [entry for entry in post_pages if entry[3] == is_post] - - # These are the extensions supported by the required format - extensions = compilers.get(compiler) - if extensions is None: - if compiler in compiler_objs: - LOGGER.error("There is a {0} compiler available, but it's not set in your COMPILERS option.".format(compiler)) - LOGGER.info("Read more: {0}".format(COMPILERS_DOC_LINK)) - else: - LOGGER.error('Unknown format {0}'.format(compiler)) - print_compilers(compilers_raw, post_pages, compiler_objs) - return False - - # Throw away the post_pages with the wrong extensions - filtered = [entry for entry in filtered if any([ext in entry[0] for ext in - extensions])] - - if not filtered: - type_name = "post" if is_post else "page" - LOGGER.error("Can't find a way, using your configuration, to create " - "a {0} in format {1}. You may want to tweak " - "COMPILERS or {2}S in conf.py".format( - type_name, compiler, type_name.upper())) - LOGGER.info("Read more: {0}".format(COMPILERS_DOC_LINK)) - - return False - return filtered[0] - - -def print_compilers(compilers_raw, post_pages, compiler_objs): - """List all available compilers in a human-friendly format. - - :param compilers_raw: The compilers dict, mapping compiler names to tuples of extensions - :param post_pages: The post_pages structure - :param compilers_objs: Compiler objects - """ - # We use compilers_raw, because the normal dict can contain - # garbage coming from the translation candidate implementation. - # Entries are in format: (name, extensions, used_in_post_pages) - parsed_compilers = {'used': [], 'unused': [], 'disabled': []} - - for compiler_name, compiler_obj in compiler_objs.items(): - fname = compiler_obj.friendly_name or compiler_name - if compiler_name not in compilers_raw: - parsed_compilers['disabled'].append((compiler_name, fname, (), False)) - else: - # stolen from filter_post_pages - extensions = compilers_raw[compiler_name] - filtered = [entry for entry in post_pages if any( - [ext in entry[0] for ext in extensions])] - if filtered: - parsed_compilers['used'].append((compiler_name, fname, extensions, True)) - else: - parsed_compilers['unused'].append((compiler_name, fname, extensions, False)) - - # Sort compilers alphabetically by name, just so it’s prettier (and - # deterministic) - parsed_compilers['used'].sort(key=operator.itemgetter(0)) - parsed_compilers['unused'].sort(key=operator.itemgetter(0)) - parsed_compilers['disabled'].sort(key=operator.itemgetter(0)) - - # We also group the compilers by status for readability. - parsed_list = parsed_compilers['used'] + parsed_compilers['unused'] + parsed_compilers['disabled'] - - print("Available input formats:\n") - - name_width = max([len(i[0]) for i in parsed_list] + [4]) # 4 == len('NAME') - fname_width = max([len(i[1]) for i in parsed_list] + [11]) # 11 == len('DESCRIPTION') - - print((' {0:<' + str(name_width) + '} {1:<' + str(fname_width) + '} EXTENSIONS\n').format('NAME', 'DESCRIPTION')) - - for name, fname, extensions, used in parsed_list: - flag = ' ' if used else '!' - flag = flag if extensions else '~' - - extensions = ', '.join(extensions) if extensions else '(disabled: not in COMPILERS)' - - print(('{flag}{name:<' + str(name_width) + '} {fname:<' + str(fname_width) + '} {extensions}').format(flag=flag, name=name, fname=fname, extensions=extensions)) - - print(""" -More compilers are available in the Plugins Index. - -Compilers marked with ! and ~ require additional configuration: - ! not in the PAGES/POSTS tuples (unused) - ~ not in the COMPILERS dict (disabled) -Read more: {0}""".format(COMPILERS_DOC_LINK)) - - def get_default_compiler(is_post, compilers, post_pages): """Given compilers and post_pages, return a reasonable default compiler for this kind of post/page.""" # First throw away all the post_pages with the wrong is_post @@ -333,7 +236,7 @@ def _execute(self, options, args): wants_available = options['available-formats'] if wants_available: - print_compilers(self.site.config['_COMPILERS_RAW'], self.site.config['post_pages'], self.site.compilers) + self.print_compilers() return if is_page: @@ -360,17 +263,13 @@ def _execute(self, options, args): if content_format not in compiler_names: LOGGER.error("Unknown {0} format {1}, maybe you need to install a plugin?".format(content_type, content_format)) - print_compilers(self.site.config['_COMPILERS_RAW'], self.site.config['post_pages'], self.site.compilers) + self.print_compilers() return compiler_plugin = self.site.plugin_manager.getPluginByName( content_format, "PageCompiler").plugin_object # Guess where we should put this - entry = filter_post_pages(content_format, is_post, - self.site.config['COMPILERS'], - self.site.config['post_pages'], - self.site.compilers, - self.site.config['_COMPILERS_RAW']) + entry = self.filter_post_pages(content_format, is_post) if entry is False: return 1 @@ -497,3 +396,108 @@ def _execute(self, options, args): subprocess.call(to_run) else: LOGGER.error('$EDITOR not set, cannot edit the post. Please do it manually.') + + def filter_post_pages(self, compiler, is_post): + """Return the correct entry from post_pages. + + Information based on: + * selected compilers + * available compilers + * post/page status + """ + compilers = self.site.config['COMPILERS'] + post_pages = self.site.config['post_pages'] + compiler_objs = self.site.compilers + compilers_raw = self.site.config['_COMPILERS_RAW'] + + # First throw away all the post_pages with the wrong is_post + filtered = [entry for entry in post_pages if entry[3] == is_post] + + # These are the extensions supported by the required format + extensions = compilers.get(compiler) + if extensions is None: + if compiler in compiler_objs: + LOGGER.error("There is a {0} compiler available, but it's not set in your COMPILERS option.".format(compiler)) + LOGGER.info("Read more: {0}".format(COMPILERS_DOC_LINK)) + else: + LOGGER.error('Unknown format {0}'.format(compiler)) + self.print_compilers() + return False + + # Throw away the post_pages with the wrong extensions + filtered = [entry for entry in filtered if any([ext in entry[0] for ext in + extensions])] + + if not filtered: + type_name = "post" if is_post else "page" + LOGGER.error("Can't find a way, using your configuration, to create " + "a {0} in format {1}. You may want to tweak " + "COMPILERS or {2}S in conf.py".format( + type_name, compiler, type_name.upper())) + LOGGER.info("Read more: {0}".format(COMPILERS_DOC_LINK)) + + return False + return filtered[0] + + def print_compilers(self): + """List all available compilers in a human-friendly format. + + :param compilers_raw: The compilers dict, mapping compiler names to tuples of extensions + :param post_pages: The post_pages structure + :param compilers_objs: Compiler objects + """ + # We use compilers_raw, because the normal dict can contain + # garbage coming from the translation candidate implementation. + # Entries are in format: (name, extensions, used_in_post_pages) + + compilers_raw = self.site.config['_COMPILERS_RAW'] + post_pages = self.site.config['post_pages'] + compiler_objs = self.site.compilers + + parsed_compilers = {'used': [], 'unused': [], 'disabled': []} + + for compiler_name, compiler_obj in compiler_objs.items(): + fname = compiler_obj.friendly_name or compiler_name + if compiler_name not in compilers_raw: + parsed_compilers['disabled'].append((compiler_name, fname, (), False)) + else: + # stolen from filter_post_pages + extensions = compilers_raw[compiler_name] + filtered = [entry for entry in post_pages if any( + [ext in entry[0] for ext in extensions])] + if filtered: + parsed_compilers['used'].append((compiler_name, fname, extensions, True)) + else: + parsed_compilers['unused'].append((compiler_name, fname, extensions, False)) + + # Sort compilers alphabetically by name, just so it’s prettier (and + # deterministic) + parsed_compilers['used'].sort(key=operator.itemgetter(0)) + parsed_compilers['unused'].sort(key=operator.itemgetter(0)) + parsed_compilers['disabled'].sort(key=operator.itemgetter(0)) + + # We also group the compilers by status for readability. + parsed_list = parsed_compilers['used'] + parsed_compilers['unused'] + parsed_compilers['disabled'] + + print("Available input formats:\n") + + name_width = max([len(i[0]) for i in parsed_list] + [4]) # 4 == len('NAME') + fname_width = max([len(i[1]) for i in parsed_list] + [11]) # 11 == len('DESCRIPTION') + + print((' {0:<' + str(name_width) + '} {1:<' + str(fname_width) + '} EXTENSIONS\n').format('NAME', 'DESCRIPTION')) + + for name, fname, extensions, used in parsed_list: + flag = ' ' if used else '!' + flag = flag if extensions else '~' + + extensions = ', '.join(extensions) if extensions else '(disabled: not in COMPILERS)' + + print(('{flag}{name:<' + str(name_width) + '} {fname:<' + str(fname_width) + '} {extensions}').format(flag=flag, name=name, fname=fname, extensions=extensions)) + + print(""" + More compilers are available in the Plugins Index. + + Compilers marked with ! and ~ require additional configuration: + ! not in the PAGES/POSTS tuples (unused) + ~ not in the COMPILERS dict (disabled) + Read more: {0}""".format(COMPILERS_DOC_LINK)) From b36cca263253541a0fb6f3b147d8e7276140aceb Mon Sep 17 00:00:00 2001 From: Roberto Alsina Date: Sat, 15 Aug 2015 12:00:55 -0300 Subject: [PATCH 3/6] Make print_compilers simpler --- nikola/nikola.py | 8 ++-- nikola/plugins/command/new_post.py | 69 ++++++++++++++++++------------ 2 files changed, 47 insertions(+), 30 deletions(-) diff --git a/nikola/nikola.py b/nikola/nikola.py index 2360d4d781..caea7d1245 100644 --- a/nikola/nikola.py +++ b/nikola/nikola.py @@ -735,20 +735,22 @@ def __init__(self, **config): # And put them in "bad compilers" pp_exts = set([os.path.splitext(x[0])[1] for x in self.config['post_pages']]) self.config['COMPILERS'] = {} - self.disabled_compilers = set([]) + self.disabled_compilers = {} + bad_compilers = set([]) for k, v in compilers.items(): if pp_exts.intersection(v): self.config['COMPILERS'][k] = sorted(list(v)) else: - self.disabled_compilers.add(k) + bad_compilers.add(k) self.plugin_manager.getPluginLocator().setPluginPlaces(places) self.plugin_manager.locatePlugins() bad_candidates = set([]) for p in self.plugin_manager._candidates: # Remove compilers we don't use - if p[-1].name in self.disabled_compilers: + if p[-1].name in bad_compilers: bad_candidates.add(p) + self.disabled_compilers[p[-1].name] = p utils.LOGGER.debug('Not loading unneeded compiler {}', p[-1].name) # Remove blacklisted plugins if p[-1].name in self.config['DISABLED_PLUGINS']: diff --git a/nikola/plugins/command/new_post.py b/nikola/plugins/command/new_post.py index 8ae7551d5c..74f41f19ef 100644 --- a/nikola/plugins/command/new_post.py +++ b/nikola/plugins/command/new_post.py @@ -408,7 +408,6 @@ def filter_post_pages(self, compiler, is_post): compilers = self.site.config['COMPILERS'] post_pages = self.site.config['post_pages'] compiler_objs = self.site.compilers - compilers_raw = self.site.config['_COMPILERS_RAW'] # First throw away all the post_pages with the wrong is_post filtered = [entry for entry in post_pages if entry[3] == is_post] @@ -431,9 +430,9 @@ def filter_post_pages(self, compiler, is_post): if not filtered: type_name = "post" if is_post else "page" LOGGER.error("Can't find a way, using your configuration, to create " - "a {0} in format {1}. You may want to tweak " - "COMPILERS or {2}S in conf.py".format( - type_name, compiler, type_name.upper())) + "a {0} in format {1}. You may want to tweak " + "COMPILERS or {2}S in conf.py".format( + type_name, compiler, type_name.upper())) LOGGER.info("Read more: {0}".format(COMPILERS_DOC_LINK)) return False @@ -451,33 +450,49 @@ def print_compilers(self): # Entries are in format: (name, extensions, used_in_post_pages) compilers_raw = self.site.config['_COMPILERS_RAW'] - post_pages = self.site.config['post_pages'] - compiler_objs = self.site.compilers - parsed_compilers = {'used': [], 'unused': [], 'disabled': []} - - for compiler_name, compiler_obj in compiler_objs.items(): - fname = compiler_obj.friendly_name or compiler_name - if compiler_name not in compilers_raw: - parsed_compilers['disabled'].append((compiler_name, fname, (), False)) + used_compilers = [] + unused_compilers = [] + disabled_compilers = [] + + for name, plugin in self.site.compilers.items(): + if name in compilers_raw: + used_compilers.append([ + name, + plugin.friendly_name or name, + compilers_raw[name], + True + ]) + else: + disabled_compilers.append([ + name, + plugin.friendly_name or name, + (), + False + ]) + + for name in self.site.disabled_compilers: + if name in compilers_raw: + unused_compilers.append([ + name, + name, + compilers_raw[name], + False + ]) else: - # stolen from filter_post_pages - extensions = compilers_raw[compiler_name] - filtered = [entry for entry in post_pages if any( - [ext in entry[0] for ext in extensions])] - if filtered: - parsed_compilers['used'].append((compiler_name, fname, extensions, True)) - else: - parsed_compilers['unused'].append((compiler_name, fname, extensions, False)) - - # Sort compilers alphabetically by name, just so it’s prettier (and - # deterministic) - parsed_compilers['used'].sort(key=operator.itemgetter(0)) - parsed_compilers['unused'].sort(key=operator.itemgetter(0)) - parsed_compilers['disabled'].sort(key=operator.itemgetter(0)) + disabled_compilers.append([ + name, + name, + (), + False + ]) + + used_compilers.sort(key=operator.itemgetter(0)) + unused_compilers.sort(key=operator.itemgetter(0)) + disabled_compilers.sort(key=operator.itemgetter(0)) # We also group the compilers by status for readability. - parsed_list = parsed_compilers['used'] + parsed_compilers['unused'] + parsed_compilers['disabled'] + parsed_list = used_compilers + unused_compilers + disabled_compilers print("Available input formats:\n") From a39f3cb85177913318351e8fe872d27414626b07 Mon Sep 17 00:00:00 2001 From: Roberto Alsina Date: Sat, 15 Aug 2015 15:07:37 -0300 Subject: [PATCH 4/6] remove old docs --- nikola/plugins/command/new_post.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/nikola/plugins/command/new_post.py b/nikola/plugins/command/new_post.py index 74f41f19ef..d5906e8113 100644 --- a/nikola/plugins/command/new_post.py +++ b/nikola/plugins/command/new_post.py @@ -440,10 +440,6 @@ def filter_post_pages(self, compiler, is_post): def print_compilers(self): """List all available compilers in a human-friendly format. - - :param compilers_raw: The compilers dict, mapping compiler names to tuples of extensions - :param post_pages: The post_pages structure - :param compilers_objs: Compiler objects """ # We use compilers_raw, because the normal dict can contain # garbage coming from the translation candidate implementation. From 30ad9f44e94a64d14574873d661aa510f7dd7b95 Mon Sep 17 00:00:00 2001 From: Roberto Alsina Date: Sat, 15 Aug 2015 16:12:35 -0300 Subject: [PATCH 5/6] pep257 --- nikola/plugins/command/new_post.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nikola/plugins/command/new_post.py b/nikola/plugins/command/new_post.py index d5906e8113..d7ebd5b0cb 100644 --- a/nikola/plugins/command/new_post.py +++ b/nikola/plugins/command/new_post.py @@ -439,8 +439,7 @@ def filter_post_pages(self, compiler, is_post): return filtered[0] def print_compilers(self): - """List all available compilers in a human-friendly format. - """ + """List all available compilers in a human-friendly format.""" # We use compilers_raw, because the normal dict can contain # garbage coming from the translation candidate implementation. # Entries are in format: (name, extensions, used_in_post_pages) From 6e2eaa50db96c6c66e59095a90a14923f889762d Mon Sep 17 00:00:00 2001 From: Roberto Alsina Date: Sat, 15 Aug 2015 16:13:12 -0300 Subject: [PATCH 6/6] updated changelog --- CHANGES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.txt b/CHANGES.txt index 99b8b5ee10..e74b2ddb77 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,6 +4,7 @@ New in Master Bugfixes -------- +* Refactor new_post to match lazy plugin loading (Issue #1943) * Make Nikola startup faster by not loading useless plugins (Issue #1825) * Ignore sliced multibyte characters when reading metadata for sitemaps * Fix NameError caused by failed import in auto plugin.