diff options
| author | 2024-04-23 00:37:58 -0400 | |
|---|---|---|
| committer | 2024-04-23 00:37:58 -0400 | |
| commit | 9b0e86a8e74768c4fe848fb5ce8d754292db4e3e (patch) | |
| tree | cfd424be8ecb68357e6e572033f08bc534bf724f /nikola/plugins/command | |
| parent | 393aa58f2c5afd51f92fd9bd4b6dfd0dc90cea41 (diff) | |
New upstream version 8.3.0.upstream/8.3.0upstream
Diffstat (limited to 'nikola/plugins/command')
| -rw-r--r-- | nikola/plugins/command/__init__.py | 2 | ||||
| -rw-r--r-- | nikola/plugins/command/auto/__init__.py | 46 | ||||
| -rw-r--r-- | nikola/plugins/command/check.py | 42 | ||||
| -rw-r--r-- | nikola/plugins/command/console.py | 2 | ||||
| -rw-r--r-- | nikola/plugins/command/default_config.py | 9 | ||||
| -rw-r--r-- | nikola/plugins/command/deploy.py | 2 | ||||
| -rw-r--r-- | nikola/plugins/command/github_deploy.py | 2 | ||||
| -rw-r--r-- | nikola/plugins/command/import_wordpress.py | 9 | ||||
| -rw-r--r-- | nikola/plugins/command/init.py | 2 | ||||
| -rw-r--r-- | nikola/plugins/command/new_page.py | 4 | ||||
| -rw-r--r-- | nikola/plugins/command/new_post.py | 8 | ||||
| -rw-r--r-- | nikola/plugins/command/orphans.py | 2 | ||||
| -rw-r--r-- | nikola/plugins/command/plugin.py | 2 | ||||
| -rw-r--r-- | nikola/plugins/command/rst2html/__init__.py | 4 | ||||
| -rw-r--r-- | nikola/plugins/command/serve.py | 2 | ||||
| -rw-r--r-- | nikola/plugins/command/status.py | 2 | ||||
| -rw-r--r-- | nikola/plugins/command/subtheme.py | 2 | ||||
| -rw-r--r-- | nikola/plugins/command/theme.py | 2 | ||||
| -rw-r--r-- | nikola/plugins/command/version.py | 2 |
19 files changed, 91 insertions, 55 deletions
diff --git a/nikola/plugins/command/__init__.py b/nikola/plugins/command/__init__.py index 6c8e81a..e5cd68a 100644 --- a/nikola/plugins/command/__init__.py +++ b/nikola/plugins/command/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina and others. +# Copyright © 2012-2024 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/command/auto/__init__.py b/nikola/plugins/command/auto/__init__.py index b13b645..d272c23 100644 --- a/nikola/plugins/command/auto/__init__.py +++ b/nikola/plugins/command/auto/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Chris Warrick, Roberto Alsina and others. +# Copyright © 2012-2024 Chris Warrick, Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -35,6 +35,7 @@ import stat import subprocess import sys import typing +import urllib.parse import webbrowser import blinker @@ -67,6 +68,17 @@ if sys.platform == 'win32': asyncio.set_event_loop(asyncio.ProactorEventLoop()) +def base_path_from_siteuri(siteuri: str) -> str: + """Extract the path part from a URI such as site['SITE_URL']. + + The path never ends with a "/". (If only "/" is intended, it is empty.) + """ + path = urllib.parse.urlsplit(siteuri).path + if path.endswith("/"): + path = path[:-1] + return path + + class CommandAuto(Command): """Automatic rebuilds for Nikola.""" @@ -239,8 +251,10 @@ class CommandAuto(Command): # Server can be disabled (Issue #1883) self.has_server = not options['no-server'] + base_path = base_path_from_siteuri(self.site.config['SITE_URL']) + if self.has_server: - loop.run_until_complete(self.set_up_server(host, port, out_folder)) + loop.run_until_complete(self.set_up_server(host, port, base_path, out_folder)) # Run an initial build so we are up-to-date. The server is running, but we are not watching yet. loop.run_until_complete(self.run_initial_rebuild()) @@ -293,9 +307,12 @@ class CommandAuto(Command): if browser: # Some browsers fail to load 0.0.0.0 (Issue #2755) if host == '0.0.0.0': - server_url = "http://127.0.0.1:{0}/".format(port) - self.logger.info("Opening {0} in the default web browser...".format(server_url)) - webbrowser.open(server_url) + browser_url = "http://127.0.0.1:{0}/{1}".format(port, base_path.lstrip("/")) + else: + # server_url always ends with a "/": + browser_url = "{0}{1}".format(server_url, base_path.lstrip("/")) + self.logger.info("Opening {0} in the default web browser...".format(browser_url)) + webbrowser.open(browser_url) # Run the event loop forever and handle shutdowns. try: @@ -320,13 +337,13 @@ class CommandAuto(Command): self.wd_observer.join() loop.close() - async def set_up_server(self, host: str, port: int, out_folder: str) -> None: + async def set_up_server(self, host: str, port: int, base_path: str, out_folder: str) -> None: """Set up aiohttp server and start it.""" webapp = web.Application() webapp.router.add_get('/livereload.js', self.serve_livereload_js) webapp.router.add_get('/robots.txt', self.serve_robots_txt) webapp.router.add_route('*', '/livereload', self.websocket_handler) - resource = IndexHtmlStaticResource(True, self.snippet, '', out_folder) + resource = IndexHtmlStaticResource(True, self.snippet, base_path, out_folder) webapp.router.register_resource(resource) webapp.on_shutdown.append(self.remove_websockets) @@ -587,13 +604,11 @@ class NikolaEventHandler: self.function = function self.loop = loop - async def on_any_event(self, event): - """Handle all file events.""" - await self.function(event) - def dispatch(self, event): """Dispatch events to handler.""" - self.loop.call_soon_threadsafe(asyncio.ensure_future, self.on_any_event(event)) + if event.event_type in {"opened", "closed"}: + return + self.loop.call_soon_threadsafe(asyncio.ensure_future, self.function(event)) class ConfigEventHandler(NikolaEventHandler): @@ -601,11 +616,10 @@ class ConfigEventHandler(NikolaEventHandler): def __init__(self, configuration_filename, function, loop): """Initialize the handler.""" + super().__init__(function, loop) self.configuration_filename = configuration_filename - self.function = function - self.loop = loop - async def on_any_event(self, event): + def dispatch(self, event): """Handle file events if they concern the configuration file.""" if event._src_path == self.configuration_filename: - await self.function(event) + super().dispatch(event) diff --git a/nikola/plugins/command/check.py b/nikola/plugins/command/check.py index f9b701b..5bcbced 100644 --- a/nikola/plugins/command/check.py +++ b/nikola/plugins/command/check.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina and others. +# Copyright © 2012-2024 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -148,6 +148,22 @@ class CommandCheck(Command): 'default': False, 'help': 'Check that remote links work.', }, + { + 'name': 'timeout', + 'long': 'timeout', + 'short': 't', + 'type': int, + 'default': 30, + 'help': 'Timeout (in seconds) for HTTP requests in remote checks.', + }, + { + 'name': 'ignore_query_strings', + 'long': 'ignore-query-strings', + 'short': 'q', + 'type': bool, + 'default': False, + 'help': 'Ignore query strings for internal links.', + } ] def _execute(self, options, args): @@ -160,8 +176,9 @@ class CommandCheck(Command): else: self.logger.level = logging.WARNING failure = False + self.timeout = options['timeout'] if options['links']: - failure |= self.scan_links(options['find_sources'], options['remote']) + failure |= self.scan_links(options['find_sources'], options['remote'], options['ignore_query_strings']) if options['files']: failure |= self.scan_files() if options['clean']: @@ -171,9 +188,10 @@ class CommandCheck(Command): existing_targets = set([]) checked_remote_targets = {} + timeout = None cache = {} - def analyze(self, fname, find_sources=False, check_remote=False): + def analyze(self, fname, find_sources=False, check_remote=False, ignore_query_strings=False): """Analyze links on a page.""" rv = False self.whitelist = [re.compile(x) for x in self.site.config['LINK_CHECK_WHITELIST']] @@ -279,19 +297,19 @@ class CommandCheck(Command): # Check the remote link works req_headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0 (Nikola)'} # I’m a real boy! - resp = requests.head(target, headers=req_headers, allow_redirects=False) + resp = requests.head(target, headers=req_headers, allow_redirects=False, timeout=self.timeout) # Retry client errors (4xx) as GET requests because many servers are broken if resp.status_code >= 400 and resp.status_code <= 499: time.sleep(0.5) - resp = requests.get(target, headers=req_headers, allow_redirects=False) + resp = requests.get(target, headers=req_headers, allow_redirects=False, timeout=self.timeout) # Follow redirects and see where they lead, redirects to errors will be reported twice if resp.status_code in [301, 302, 307, 308]: redir_status_code = resp.status_code time.sleep(0.5) # Known redirects are retested using GET because IIS servers otherwise get HEADaches - resp = requests.get(target, headers=req_headers, allow_redirects=True) + resp = requests.get(target, headers=req_headers, allow_redirects=True, timeout=self.timeout) # Permanent redirects should be updated if redir_status_code in [301, 308]: self.logger.warning("Remote link moved PERMANENTLY to \"{0}\" and should be updated in {1}: {2} [HTTP: {3}]".format(resp.url, filename, target, redir_status_code)) @@ -353,6 +371,10 @@ class CommandCheck(Command): else: target_filename_str = target_filename.decode("utf-8", errors="surrogateescape") + if ignore_query_strings and "?" in target_filename_str: + target_filename, _, _ = target_filename.rpartition("?") + target_filename_str, _, _ = target_filename_str.rpartition("?") + if any(pattern.search(target_filename_str) for pattern in self.whitelist): continue @@ -371,7 +393,7 @@ class CommandCheck(Command): self.logger.error(u"Error with: {0} {1}".format(filename, exc)) return rv - def scan_links(self, find_sources=False, check_remote=False): + def scan_links(self, find_sources=False, check_remote=False, ignore_query_strings=False): """Check links on the site.""" self.logger.debug("Checking Links:") self.logger.debug("===============\n") @@ -387,13 +409,13 @@ class CommandCheck(Command): for fname in _call_nikola_list(self.site, self.cache)[0]: if fname.startswith(output_folder): if '.html' == fname[-5:]: - if self.analyze(fname, find_sources, check_remote): + if self.analyze(fname, find_sources, check_remote, ignore_query_strings): failure = True if atom_extension == fname[-len(atom_extension):]: - if self.analyze(fname, find_sources, False): + if self.analyze(fname, find_sources, False, ignore_query_strings): failure = True if fname.endswith('sitemap.xml') or fname.endswith('sitemapindex.xml'): - if self.analyze(fname, find_sources, False): + if self.analyze(fname, find_sources, False, ignore_query_strings): failure = True if not failure: self.logger.debug("All links checked.") diff --git a/nikola/plugins/command/console.py b/nikola/plugins/command/console.py index 96fee3e..18428f3 100644 --- a/nikola/plugins/command/console.py +++ b/nikola/plugins/command/console.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Chris Warrick, Roberto Alsina and others. +# Copyright © 2012-2024 Chris Warrick, Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/command/default_config.py b/nikola/plugins/command/default_config.py index fddda26..f14c4c8 100644 --- a/nikola/plugins/command/default_config.py +++ b/nikola/plugins/command/default_config.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina and others. +# Copyright © 2012-2024 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -48,7 +48,10 @@ class CommandShowConfig(Command): def _execute(self, options=None, args=None): """Show the default configuration.""" + init_plugin = self.site.plugin_manager.get_plugin_by_name("init", "Command").plugin_object + config = init_plugin.create_configuration_to_string() + try: - print(nikola.plugins.command.init.CommandInit.create_configuration_to_string()) + print(config) except Exception: - sys.stdout.buffer.write(nikola.plugins.command.init.CommandInit.create_configuration_to_string().encode('utf-8')) + sys.stdout.buffer.write(config.encode('utf-8')) diff --git a/nikola/plugins/command/deploy.py b/nikola/plugins/command/deploy.py index 1896a7a..ddb5a64 100644 --- a/nikola/plugins/command/deploy.py +++ b/nikola/plugins/command/deploy.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina and others. +# Copyright © 2012-2024 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/command/github_deploy.py b/nikola/plugins/command/github_deploy.py index 1d3e9c0..aa2da74 100644 --- a/nikola/plugins/command/github_deploy.py +++ b/nikola/plugins/command/github_deploy.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2014-2022 Puneeth Chaganti and others. +# Copyright © 2014-2024 Puneeth Chaganti and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/command/import_wordpress.py b/nikola/plugins/command/import_wordpress.py index f3feab1..e6ec45b 100644 --- a/nikola/plugins/command/import_wordpress.py +++ b/nikola/plugins/command/import_wordpress.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina and others. +# Copyright © 2012-2024 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -66,7 +66,7 @@ def install_plugin(site, plugin_name, output_dir=None, show_install_notes=False) """Install a Nikola plugin.""" LOGGER.info("Installing plugin '{0}'".format(plugin_name)) # Get hold of the 'plugin' plugin - plugin_installer_info = site.plugin_manager.getPluginByName('plugin', 'Command') + plugin_installer_info = site.plugin_manager.get_plugin_by_name('plugin', 'Command') if plugin_installer_info is None: LOGGER.error('Internal error: cannot find the "plugin" plugin which is supposed to come with Nikola!') return False @@ -236,10 +236,9 @@ to self._find_wordpress_compiler() if self.wordpress_page_compiler is not None: return self.wordpress_page_compiler - plugin_info = self.site.plugin_manager.getPluginByName('markdown', 'PageCompiler') + plugin_info = self.site.plugin_manager.get_plugin_by_name('markdown', 'PageCompiler') if plugin_info is not None: if not plugin_info.is_activated: - self.site.plugin_manager.activatePluginByName(plugin_info.name) plugin_info.plugin_object.set_site(self.site) return plugin_info.plugin_object else: @@ -249,7 +248,7 @@ to """Find WordPress compiler plugin.""" if self.wordpress_page_compiler is not None: return - plugin_info = self.site.plugin_manager.getPluginByName('wordpress', 'PageCompiler') + plugin_info = self.site.plugin_manager.get_plugin_by_name('wordpress', 'PageCompiler') if plugin_info is not None: if not plugin_info.is_activated: self.site.plugin_manager.activatePluginByName(plugin_info.name) diff --git a/nikola/plugins/command/init.py b/nikola/plugins/command/init.py index 4607758..cf22a44 100644 --- a/nikola/plugins/command/init.py +++ b/nikola/plugins/command/init.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina and others. +# Copyright © 2012-2024 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/command/new_page.py b/nikola/plugins/command/new_page.py index 94fbc51..6587d70 100644 --- a/nikola/plugins/command/new_page.py +++ b/nikola/plugins/command/new_page.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina, Chris Warrick and others. +# Copyright © 2012-2024 Roberto Alsina, Chris Warrick and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -109,5 +109,5 @@ class CommandNewPage(Command): options['date-path'] = False # Even though stuff was split into `new_page`, it’s easier to do it # there not to duplicate the code. - p = self.site.plugin_manager.getPluginByName('new_post', 'Command').plugin_object + p = self.site.plugin_manager.get_plugin_by_name('new_post', 'Command').plugin_object return p.execute(options, args) diff --git a/nikola/plugins/command/new_post.py b/nikola/plugins/command/new_post.py index f66a188..aa96625 100644 --- a/nikola/plugins/command/new_post.py +++ b/nikola/plugins/command/new_post.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina and others. +# Copyright © 2012-2024 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -216,9 +216,7 @@ class CommandNewPost(Command): def _execute(self, options, args): """Create a new post or page.""" global LOGGER - compiler_names = [p.name for p in - self.site.plugin_manager.getPluginsOfCategory( - "PageCompiler")] + compiler_names = [p.name for p in self.site.plugin_manager.get_plugins_of_category("PageCompiler")] if len(args) > 1: print(self.help()) @@ -298,7 +296,7 @@ class CommandNewPost(Command): self.print_compilers() return - compiler_plugin = self.site.plugin_manager.getPluginByName( + compiler_plugin = self.site.plugin_manager.get_plugin_by_name( content_format, "PageCompiler").plugin_object # Guess where we should put this diff --git a/nikola/plugins/command/orphans.py b/nikola/plugins/command/orphans.py index 169cbba..bde8425 100644 --- a/nikola/plugins/command/orphans.py +++ b/nikola/plugins/command/orphans.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina, Chris Warrick and others. +# Copyright © 2012-2024 Roberto Alsina, Chris Warrick and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/command/plugin.py b/nikola/plugins/command/plugin.py index ae0dead..4fd8e8f 100644 --- a/nikola/plugins/command/plugin.py +++ b/nikola/plugins/command/plugin.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina and others. +# Copyright © 2012-2024 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/command/rst2html/__init__.py b/nikola/plugins/command/rst2html/__init__.py index 2bf329a..4fdd36f 100644 --- a/nikola/plugins/command/rst2html/__init__.py +++ b/nikola/plugins/command/rst2html/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2015-2022 Chris Warrick and others. +# Copyright © 2015-2024 Chris Warrick and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -44,7 +44,7 @@ class CommandRst2Html(Command): def _execute(self, options, args): """Compile reStructuredText to standalone HTML files.""" - compiler = self.site.plugin_manager.getPluginByName('rest', 'PageCompiler').plugin_object + compiler = self.site.plugin_manager.get_plugin_by_name('rest', 'PageCompiler').plugin_object if len(args) != 1: print("This command takes only one argument (input file name).") return 2 diff --git a/nikola/plugins/command/serve.py b/nikola/plugins/command/serve.py index cbf628c..32cd46b 100644 --- a/nikola/plugins/command/serve.py +++ b/nikola/plugins/command/serve.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina and others. +# Copyright © 2012-2024 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/command/status.py b/nikola/plugins/command/status.py index ab6fc1e..a22f173 100644 --- a/nikola/plugins/command/status.py +++ b/nikola/plugins/command/status.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina and others. +# Copyright © 2012-2024 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/command/subtheme.py b/nikola/plugins/command/subtheme.py index b5c5aff..c322336 100644 --- a/nikola/plugins/command/subtheme.py +++ b/nikola/plugins/command/subtheme.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina and others. +# Copyright © 2012-2024 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/command/theme.py b/nikola/plugins/command/theme.py index 2f99dd8..f7608b5 100644 --- a/nikola/plugins/command/theme.py +++ b/nikola/plugins/command/theme.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina, Chris Warrick and others. +# Copyright © 2012-2024 Roberto Alsina, Chris Warrick and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/command/version.py b/nikola/plugins/command/version.py index 4ec8a46..bdc1357 100644 --- a/nikola/plugins/command/version.py +++ b/nikola/plugins/command/version.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2022 Roberto Alsina and others. +# Copyright © 2012-2024 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated |
