def post_validation(self, config, key_name): theme_config = config[key_name] if not theme_config['name'] and 'custom_dir' not in theme_config: raise ValidationError( "At least one of 'theme.name' or 'theme.custom_dir' must be defined." ) # Ensure custom_dir is an absolute path if 'custom_dir' in theme_config and not os.path.isabs( theme_config['custom_dir']): config_dir = os.path.dirname(config.config_file_path) theme_config['custom_dir'] = os.path.join( config_dir, theme_config['custom_dir']) if 'custom_dir' in theme_config and not os.path.isdir( theme_config['custom_dir']): raise ValidationError( "The path set in {name}.custom_dir ('{path}') does not exist.". format(path=theme_config['custom_dir'], name=key_name)) if 'locale' in theme_config and not isinstance(theme_config['locale'], str): raise ValidationError("'{name}.locale' must be a string.".format( name=theme_config['name'])) config[key_name] = theme.Theme(**theme_config)
def load_plugin(self, name, config): if not isinstance(name, str): raise ValidationError(f"'{name}' is not a valid plugin name.") if name not in self.installed_plugins: raise ValidationError(f'The "{name}" plugin is not installed') config = config or {} # Users may define a null (None) config if not isinstance(config, dict): raise ValidationError( f"Invalid config options for the '{name}' plugin.") Plugin = self.installed_plugins[name].load() if not issubclass(Plugin, plugins.BasePlugin): raise ValidationError('{}.{} must be a subclass of {}.{}'.format( Plugin.__module__, Plugin.__name__, plugins.BasePlugin.__module__, plugins.BasePlugin.__name__)) plugin = Plugin() errors, warnings = plugin.load_config(config, self.config_file_path) self.warnings.extend(warnings) errors_message = '\n'.join(f"Plugin '{name}' value: '{x}'. Error: {y}" for x, y in errors) if errors_message: raise ValidationError(errors_message) return plugin
def run_validation(self, value): if not isinstance(value, (list, tuple)): raise ValidationError('Invalid Markdown Extensions configuration') extensions = [] for item in value: if isinstance(item, dict): if len(item) > 1: raise ValidationError( 'Invalid Markdown Extensions configuration') ext, cfg = item.popitem() extensions.append(ext) if cfg is None: continue if not isinstance(cfg, dict): raise ValidationError( 'Invalid config options for Markdown ' "Extension '{}'.".format(ext)) self.configdata[ext] = cfg elif isinstance(item, str): extensions.append(item) else: raise ValidationError( 'Invalid Markdown Extensions configuration') extensions = utils.reduce_list(self.builtins + extensions) # Confirm that Markdown considers extensions to be valid try: markdown.Markdown(extensions=extensions, extension_configs=self.configdata) except Exception as e: raise ValidationError(e.args[0]) return extensions
def post_validation(self, config, key_name): theme_config = config[key_name] # TODO: Remove when theme_dir is fully deprecated. if config['theme_dir'] is not None: if 'custom_dir' not in theme_config: # Only pass in 'theme_dir' if it is set and 'custom_dir' is not set. theme_config['custom_dir'] = config['theme_dir'] if not any(['theme' in c for c in config.user_configs]): # If the user did not define a theme, but did define theme_dir, then remove default set in validate. theme_config['name'] = None if not theme_config['name'] and 'custom_dir' not in theme_config: raise ValidationError( "At least one of 'theme.name' or 'theme.custom_dir' must be defined." ) # Ensure custom_dir is an absolute path if 'custom_dir' in theme_config and not os.path.isabs( theme_config['custom_dir']): config_dir = os.path.dirname(config.config_file_path) theme_config['custom_dir'] = os.path.join( config_dir, theme_config['custom_dir']) if 'custom_dir' in theme_config and not os.path.isdir( theme_config['custom_dir']): raise ValidationError( "The path set in {name}.custom_dir ('{path}') does not exist.". format(path=theme_config['custom_dir'], name=self.name)) config[key_name] = theme.Theme(**theme_config)
def run_validation(self, value): if not isinstance(value, dict): raise ValidationError( "Expected a dict, got {0}".format(type(value))) if len(value) == 0: return config_types = set(type(l) for l in value) if not config_types.issubset({str}): raise ValidationError("Invalid config. {0} {1}".format( config_types, {str} )) if 'repos_prefix' not in value: value['repos_prefix'] = "" if 'default_url_template' not in value: value['default_url_template'] = "" if 'github_url_template' not in value: value['github_url_template'] = "" if 'repos_file' not in value: raise ValidationError("Undefined repos_file") if not os.path.exists(value['repos_file']): raise ValidationError("repos_file do not exist") return value
def run_validation(self, value): themes = utils.get_theme_names() # These themes have been moved to the mkdocs-bootstrap and # mkdocs-bootswatch packages. At some point we wont depend on # these by default. moved_themes = [ 'bootstrap', 'amelia', 'cerulean', 'cosmo', 'cyborg', 'flatly', 'journal', 'readable', 'simplex', 'slate', 'spacelab', 'united', 'yeti' ] if value in themes: return value elif value in moved_themes: raise ValidationError( ("The theme '{0}' is no longer included in MkDocs by default " "and must be installed with pip. See http://www.mkdocs.org" "/about/release-notes/#add-support-for-installable-themes" "for more details").format(value)) raise ValidationError( "Unrecognised theme '{0}'. The available installed themes " "are: {1}".format(value, ', '.join(themes)))
def run_validation(self, value): if not isinstance(value, (list, tuple, dict)): raise ValidationError('Invalid Markdown Extensions configuration') extensions = [] if isinstance(value, dict): for ext, cfg in value.items(): self.validate_ext_cfg(ext, cfg) extensions.append(ext) else: for item in value: if isinstance(item, dict): if len(item) > 1: raise ValidationError( 'Invalid Markdown Extensions configuration') ext, cfg = item.popitem() self.validate_ext_cfg(ext, cfg) extensions.append(ext) elif isinstance(item, str): extensions.append(item) else: raise ValidationError( 'Invalid Markdown Extensions configuration') extensions = utils.reduce_list(self.builtins + extensions) # Confirm that Markdown considers extensions to be valid try: markdown.Markdown(extensions=extensions, extension_configs=self.configdata) except Exception as e: raise ValidationError(e.args[0]) return extensions
def _load_theme_config(self, name): """ Recursively load theme and any parent themes. """ theme_dir = utils.get_theme_dir(name) self.dirs.append(theme_dir) try: file_path = os.path.join(theme_dir, 'mkdocs_theme.yml') with open(file_path, 'rb') as f: theme_config = utils.yaml_load(f) except IOError as e: log.debug(e) raise ValidationError( "The theme '{0}' does not appear to have a configuration file. " "Please upgrade to a current version of the theme.".format(name) ) log.debug("Loaded theme configuration for '%s' from '%s': %s", name, file_path, theme_config) parent_theme = theme_config.pop('extends', None) if parent_theme: themes = utils.get_theme_names() if parent_theme not in themes: raise ValidationError( "The theme '{0}' inherits from '{1}', which does not appear to be installed. " "The available installed themes are: {2}".format(name, parent_theme, ', '.join(themes)) ) self._load_theme_config(parent_theme) self.static_templates.update(theme_config.pop('static_templates', [])) self._vars.update(theme_config)
def validate_ext_cfg(self, ext, cfg): if not isinstance(ext, str): raise ValidationError(f"'{ext}' is not a valid Markdown Extension name.") if not cfg: return if not isinstance(cfg, dict): raise ValidationError(f"Invalid config options for Markdown Extension '{ext}'.") self.configdata[ext] = cfg
def _validate_nav_item(self, value): if isinstance(value, str): pass elif isinstance(value, dict): if len(value) != 1: raise ValidationError(f"Expected nav item to be a dict of size 1, got {self._repr_item(value)}") for subnav in value.values(): self.run_validation(subnav, top=False) else: raise ValidationError(f"Expected nav item to be a string or dict, got {self._repr_item(value)}")
def post_validation(self, config, key_name): # Validate that the docs_dir and site_dir don't contain the # other as this will lead to copying back and forth on each # and eventually make a deep nested mess. if config['docs_dir'].startswith(config['site_dir']): raise ValidationError( "The 'docs_dir' can't be within the 'site_dir'.") elif config['site_dir'].startswith(config['docs_dir']): raise ValidationError( "The 'site_dir' can't be within the 'docs_dir'.")
def run_validation(self, value): try: parsed_url = six.moves.urllib.parse.urlparse(value) except (AttributeError, TypeError): raise ValidationError("Unable to parse the URL.") if parsed_url.scheme: return value raise ValidationError( "The URL isn't valid, it should include the http:// (scheme)")
def run_validation(self, value): if value is None: if self.required: raise ValidationError("Required configuration not provided.") else: return () if not isinstance(value, Sequence): raise ValidationError(f'Expected a sequence of mappings, but a ' f'{type(value)} was given.') return [self.item_config.validate(item) for item in value]
def run_validation(self, value): if value is None: if self.required: raise ValidationError("Required configuration not provided.") else: return () if not isinstance(value, Sequence): raise ValidationError('Expected a sequence of mappings, but a %s ' 'was given.' % type(value)) result = [] for item in value: result.append(self.item_config.validate(item)) return result
def run_validation(self, value): if not isinstance(value, list): raise ValidationError(f"Expected a list, got {type(value)}") if len(value) == 0: return config_types = {type(item) for item in value} if config_types.issubset({str, dict}): return value raise ValidationError("Invalid pages config. {} {}".format( config_types, {str, dict}))
def run_validation(self, value): if not isinstance(value, list): raise ValidationError(f"Expected a list, got {type(value)}") if len(value) == 0: return paths = [] for path in value: if self.config_dir and not os.path.isabs(path): path = os.path.join(self.config_dir, path) if not os.path.exists(path): raise ValidationError(f"The path {path} does not exist.") path = os.path.abspath(path) paths.append(path) return paths
def run_validation(self, value): if not isinstance(value, list): raise ValidationError("Expected a list, got {0}".format( type(value))) if len(value) == 0: return config_types = set(type(l) for l in value) if config_types.issubset({utils.text_type, dict, str}): return value raise ValidationError("Invalid pages config. {0} {1}".format( config_types, {utils.text_type, dict}))
def run_validation(self, value): value = super(FilesystemObject, self).run_validation(value) if self.exists and not self.existence_test(value): raise ValidationError( "The path {path} isn't an existing {name}.".format( path=value, name=self.name)) return os.path.abspath(value)
def run_validation(self, value): try: host, port = value.rsplit(':', 1) except Exception: raise ValidationError("Must be a string of format 'IP:PORT'") try: port = int(port) except Exception: raise ValidationError("'{0}' is not a valid port".format(port)) class Address(namedtuple('Address', 'host port')): def __str__(self): return '{0}:{1}'.format(self.host, self.port) return Address(host, port)
def run_validation(self, value): if isinstance(value, list): return value else: raise ValidationError("Expected a list, got {0}".format( type(value)))
def run_validation(self, value): if value == '': return value try: parsed_url = urlsplit(value) except (AttributeError, TypeError): raise ValidationError("Unable to parse the URL.") if parsed_url.scheme and parsed_url.netloc: if self.is_dir and not parsed_url.path.endswith('/'): parsed_url = parsed_url._replace(path=f'{parsed_url.path}/') return urlunsplit(parsed_url) raise ValidationError( "The URL isn't valid, it should include the http:// (scheme)")
def post_validation(self, config, key_name): host = config[key_name].host if key_name == 'dev_addr' and host in ['0.0.0.0', '::']: raise ValidationError(( "The MkDocs' server is intended for development purposes only. " "Therefore, '{}' is not a supported IP address. Please use a " "third party production-ready server instead.").format(host))
def run_validation(self, value): themes = utils.get_theme_names() if value in themes: # These themes have been moved to the mkdocs-bootstrap and # mkdocs-bootswatch packages. At some point we wont depend on # these by default. moved_themes = [ 'bootstrap', 'amelia', 'cerulean', 'cosmo', 'cyborg', 'flatly', 'journal', 'readable', 'simplex', 'slate', 'spacelab', 'united', 'yeti' ] if value not in moved_themes: return value self.warnings.append( ("The theme '{0}' will be removed in an upcoming MkDocs " "release. See http://www.mkdocs.org/about/release-notes/ " "for more details").format(value)) return value raise ValidationError( "Unrecognised theme '{0}'. The available installed themes" "are: ".format(value, ', '.join(themes)))
def run_validation(self, value): if value not in self.choices: msg = f"Expected one of: {self.choices} but received: {value}" else: return value raise ValidationError(msg)
def run_validation(self, value): value = super().run_validation(value) if self.config_dir and not os.path.isabs(value): value = os.path.join(self.config_dir, value) if self.exists and not self.existence_test(value): raise ValidationError( f"The path {value} isn't an existing {self.name}.") return os.path.abspath(value)
def post_validation(self, config, key_name): # Validate that the dir is not the parent dir of the config file. if os.path.dirname(config['config_file_path']) == config[key_name]: raise ValidationError( ("The '{0}' should not be the parent directory of the config " "file. Use a child directory instead so that the config file " "is a sibling of the config file.").format(key_name))
def run_validation(self, value): value = super(Dir, self).run_validation(value) if self.exists and not os.path.isdir(value): raise ValidationError("The path {0} doesn't exist".format(value)) return os.path.abspath(value)
def run_validation(self, value): if value not in self.choices: msg = ("Expected one of: {} but received: {}".format( self.choices, value)) else: return value raise ValidationError(msg)
def post_validation(self, config, key_name): if not config[key_name]: return try: config[key_name]['repos_info'] = self.parse_repos_info(config[key_name]['repos_file']) except IOError as e: raise ValidationError('Unable to read repos_file', e)
def run_validation(self, value): if not isinstance(value, (list, tuple, dict)): raise ValidationError('Invalid Plugins configuration. Expected a list or dict.') plgins = plugins.PluginCollection() if isinstance(value, dict): for name, cfg in value.items(): plgins[name] = self.load_plugin(name, cfg) else: for item in value: if isinstance(item, dict): if len(item) > 1: raise ValidationError('Invalid Plugins configuration') name, cfg = item.popitem() item = name else: cfg = {} plgins[item] = self.load_plugin(item, cfg) return plgins