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
예제 #3
0
    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
예제 #4
0
    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)
예제 #5
0
    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
예제 #6
0
    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
예제 #8
0
파일: theme.py 프로젝트: ryffine/mkdocs
    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)
예제 #9
0
 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
예제 #10
0
 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)}")
예제 #11
0
    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'.")
예제 #12
0
    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]
예제 #14
0
    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}))
예제 #16
0
 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
예제 #17
0
    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}))
예제 #18
0
 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)
예제 #19
0
    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)
예제 #20
0
    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)")
예제 #22
0
 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))
예제 #23
0
    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)
예제 #25
0
 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)
예제 #26
0
    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))
예제 #27
0
    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)
예제 #28
0
    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)
예제 #29
0
    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)
예제 #30
0
 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