Exemplo n.º 1
0
    def test_convert(self):

        self.maxDiff = None

        pages_yaml_old = """
        pages:
        - ['index.md', 'Home']
        - ['user-guide/writing-your-docs.md', 'User Guide']
        - ['user-guide/styling-your-docs.md', 'User Guide']
        - ['about/license.md', 'About', 'License']
        - ['about/release-notes.md', 'About']
        - ['about/contributing.md', 'About', 'Contributing']
        - ['help/contributing.md', 'Help', 'Contributing']
        - ['support.md']
        - ['cli.md', 'CLI Guide']
        """

        pages_yaml_new = """
        pages:
        - Home: index.md
        - User Guide:
            - user-guide/writing-your-docs.md
            - user-guide/styling-your-docs.md
        - About:
            - License: about/license.md
            - about/release-notes.md
            - Contributing: about/contributing.md
        - Help:
            - Contributing: help/contributing.md
        - support.md
        - CLI Guide: cli.md
        """
        self.assertEqual(
            legacy.pages_compat_shim(utils.yaml_load(pages_yaml_old)['pages']),
            utils.yaml_load(pages_yaml_new)['pages'])
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    def test_yaml_load(self):
        try:
            from collections import OrderedDict
        except ImportError:
            # Don't test if can't import OrderdDict
            # Exception can be removed when Py26 support is removed
            return

        yaml_text = dedent('''
            test:
                key1: 1
                key2: 2
                key3: 3
                key4: 4
                key5: 5
                key5: 6
                key3: 7
        ''')

        self.assertEqual(
            utils.yaml_load(yaml_text),
            OrderedDict([('test', OrderedDict([('key1', 1), ('key2', 2),
                                               ('key3', 7), ('key4', 4),
                                               ('key5', 6)]))])
        )
Exemplo n.º 4
0
    def __load_page_config_file(self, file):
        config = yaml_load(file)

        root_docs_dir = self.__get_root_docs_dir()
        root_repo_url = self.config.get('repo_url')
        root_edit_uri = self.config.get('edit_uri', '')

        page_docs_dir = self.__get_page_docs_dir()
        page_repo_url = config.get('repo_url', root_repo_url)
        page_edit_uri = config.get(
            'edit_uri', root_edit_uri.replace(root_docs_dir, page_docs_dir))

        # ensure a well-formed edit_uri
        if page_edit_uri:
            if not page_edit_uri.startswith(('?', '#')) \
              and not page_repo_url.endswith('/'):
                page_repo_url += '/'
            if not page_edit_uri.endswith('/'):
                page_edit_uri += '/'

        config['docs_dir'] = page_docs_dir
        config['edit_uri'] = page_edit_uri
        config['repo_url'] = page_repo_url

        return config
Exemplo n.º 5
0
    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)
                if theme_config is None:
                    theme_config = {}
        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)
Exemplo n.º 6
0
 def load_file(self, config_file):
     try:
         return self.load_dict(utils.yaml_load(config_file))
     except YAMLError as e:
         # MkDocs knows and understands ConfigurationErrors
         raise exceptions.ConfigurationError(
             "MkDocs encountered an error parsing the configuration file: {}".format(e)
         )
Exemplo n.º 7
0
 def load_file(self, config_file):
     try:
         return self.load_dict(utils.yaml_load(config_file))
     except YAMLError as e:
         # MkDocs knows and understands ConfigurationErrors
         raise exceptions.ConfigurationError(
             "MkDocs encountered as error parsing the configuration file: {}".format(e)
         )
Exemplo n.º 8
0
 def load_file(self, config_file):
     """ Load config options from the open file descriptor of a YAML file. """
     try:
         return self.load_dict(utils.yaml_load(config_file))
     except YAMLError as e:
         # MkDocs knows and understands ConfigurationErrors
         raise exceptions.ConfigurationError(
             f"MkDocs encountered an error parsing the configuration file: {e}"
         )
Exemplo n.º 9
0
    def test_convert_no_home(self):

        self.maxDiff = None

        pages_yaml_old = """
        pages:
        - ['index.md']
        - ['about.md', 'About']
        """

        pages_yaml_new = """
        pages:
        - index.md
        - About: about.md
        """
        self.assertEqual(
            legacy.pages_compat_shim(utils.yaml_load(pages_yaml_old)['pages']),
            utils.yaml_load(pages_yaml_new)['pages'])
Exemplo n.º 10
0
    def test_unicode_yaml(self):

        yaml_src = dedent('''
            key: value
            key2:
              - value
            ''')

        config = utils.yaml_load(yaml_src)
        self.assertTrue(isinstance(config['key'], utils.text_type))
        self.assertTrue(isinstance(config['key2'][0], utils.text_type))
Exemplo n.º 11
0
    def test_normal_nav(self):
        nav = yaml_load(textwrap.dedent('''\
            - Home: index.md
            - getting-started.md
            - User Guide:
                - Overview: user-guide/index.md
                - Installation: user-guide/installation.md
        ''').encode())

        option = config_options.Nav()
        self.assertEqual(option.validate(nav), nav)
        self.assertEqual(option.warnings, [])
    def test_unicode_yaml(self):

        yaml_src = dedent(
            '''
            key: value
            key2:
              - value
            '''
        ).encode('utf-8')

        config = utils.yaml_load(yaml_src)
        self.assertTrue(isinstance(config['key'], str))
        self.assertTrue(isinstance(config['key2'][0], str))
Exemplo n.º 13
0
    def test_unicode_yaml(self):

        yaml_src = dedent(
            '''
            key: value
            key2:
              - value
            '''
        )

        config = utils.yaml_load(yaml_src)
        self.assertTrue(isinstance(config['key'], utils.text_type))
        self.assertTrue(isinstance(config['key2'][0], utils.text_type))
Exemplo n.º 14
0
    def merge(self):
        self.temp_docs_dir = TemporaryDirectory("", "docs_")

        aliases = list(
            filter(
                lambda docs_dir: len(docs_dir) > 0,
                map(lambda docs_dir: docs_dir[0], self.docs_dirs),
            ))
        if len(aliases) != len(set(aliases)):
            log.critical(
                "[mkdocs-monorepo] You cannot have duplicated site names. " +
                "Current registered site names in the monorepository: {}".
                format(", ".join(aliases)))
            raise SystemExit(1)

        for alias, docs_dir in self.docs_dirs:
            if len(alias) == 0:
                source_dir = docs_dir
                dest_dir = self.temp_docs_dir.name
            else:
                with open(os.path.join(docs_dir, "mkdocs.yml"), "rb") as f:
                    navYaml = yaml_load(f)
                sub_docs_dir = navYaml.get("docs_dir", "docs")

                source_dir = os.path.join(docs_dir, "docs")
                split_alias = alias.split("/")
                dest_dir = os.path.join(self.temp_docs_dir.name, *split_alias)

            if os.path.exists(source_dir):
                copy_tree(source_dir, dest_dir)
                for file_abs_path in Path(source_dir).rglob('*.md'):
                    file_abs_path = str(
                        file_abs_path)  # python 3.5 compatibility
                    if os.path.isfile(file_abs_path):
                        file_rel_path = os.path.relpath(
                            file_abs_path, source_dir)
                        dest = join(dest_dir, file_rel_path)
                        self.files_source_dir[dest] = file_abs_path

            else:
                log.critical("[mkdocs-monorepo] The {} path is not valid. ".
                             format(source_dir) +
                             "Please update your 'nav' with a valid path.")
                raise SystemExit(1)

        return str(self.temp_docs_dir.name)
Exemplo n.º 15
0
    def test_env_var_in_yaml(self):

        yaml_src = dedent('''
            key1: !ENV VARNAME
            key2: !ENV UNDEFINED
            key3: !ENV [UNDEFINED, default]
            key4: !ENV [UNDEFINED, VARNAME, default]
            key5: !ENV BOOLVAR
            ''')
        config = utils.yaml_load(yaml_src)
        self.assertIsInstance(config['key1'], str)
        self.assertEqual(config['key1'], 'Hello, World!')
        self.assertIsNone(config['key2'])
        self.assertIsInstance(config['key3'], str)
        self.assertEqual(config['key3'], 'default')
        self.assertIsInstance(config['key4'], str)
        self.assertEqual(config['key4'], 'Hello, World!')
        self.assertIs(config['key5'], False)
 def test_yaml_inheritance(self, tdir):
     expected = {
         'foo': 'bar',
         'baz': {
             'sub1': 'replaced',
             'sub2': 2,
             'sub3': 'new'
         },
         'deep1': {
             'deep2-1': {
                 'deep3-1': 'replaced',
                 'deep3-2': 'bar'
             },
             'deep2-2': 'baz'
         }
     }
     with open(os.path.join(tdir, 'base.yml')) as fd:
         result = utils.yaml_load(fd)
     self.assertEqual(result, expected)
Exemplo n.º 17
0
    def read(self):
        if not self.absNavPath.endswith("/mkdocs.yml"):
            log.critical(
                "[mkdocs-monorepo] The included file path {} does not point to a mkdocs.yml"
                .format(self.absNavPath))
            raise SystemExit(1)

        if not self.absNavPath.startswith(self.rootDir):
            log.critical(
                "[mkdocs-monorepo] The mkdocs file {} is outside of the current directory. "
                .format(self.absNavPath) +
                "Please move the file and try again.")
            raise SystemExit(1)

        try:
            with open(self.absNavPath, 'rb') as f:
                self.navYaml = yaml_load(f)
        except OSError:
            log.critical(
                "[mkdocs-monorepo] The file path {} does not exist, ".format(
                    self.absNavPath) + "is not valid YAML, " +
                "or does not contain a valid 'site_name' and 'nav' keys.")
            raise SystemExit(1)

        if self.navYaml and 'site_name' not in self.navYaml:
            log.critical(
                "[mkdocs-monorepo] The file path {} does not contain a valid 'site_name' key "
                .format(self.absNavPath) +
                "in the YAML file. Please include it to indicate where your documentation "
                + "should be moved to.")
            raise SystemExit(1)

        if self.navYaml and 'nav' not in self.navYaml:
            log.critical(
                "[mkdocs-monorepo] The file path {} ".format(self.absNavPath) +
                "does not contain a valid 'nav' key in the YAML file. " +
                "Please include it to indicate how your documentation should be presented in the navigation."
            )
            raise SystemExit(1)

        return self
Exemplo n.º 18
0
def load_config(config_file=None, **kwargs):

    options = dict((k, v) for k, v in kwargs.items() if v is not None)

    if config_file is None:
        config_file = 'mkdocs.yml'
        if os.path.exists(config_file):
            config_file = open(config_file, 'rb')
        else:
            raise ConfigurationError(
                "Config file '{0}' does not exist.".format(config_file))

    options['config'] = config_file

    user_config = utils.yaml_load(config_file)

    if not isinstance(user_config, dict):
        raise ConfigurationError(
            "The mkdocs.yml file is invalid. For more information see: "
            "http://www.mkdocs.org/user-guide/configuration/ ({0})".format(
                user_config))

    user_config.update(options)
    return validate_config(user_config)
Exemplo n.º 19
0
def load_config(config_file=None, **kwargs):

    options = dict((k, v) for k, v in kwargs.items() if v is not None)

    if config_file is None:
        config_file = 'mkdocs.yml'
        if os.path.exists(config_file):
            config_file = open(config_file, 'rb')
        else:
            raise ConfigurationError(
                "Config file '{0}' does not exist.".format(config_file))

    options['config'] = config_file

    user_config = utils.yaml_load(config_file)

    if not isinstance(user_config, dict):
        raise ConfigurationError(
            "The mkdocs.yml file is invalid. For more information see: "
            "http://www.mkdocs.org/user-guide/configuration/ ({0})".format(
                user_config))

    user_config.update(options)
    return validate_config(user_config)
Exemplo n.º 20
0
    def read(self):
        if not self.absNavPath.endswith(tuple([".yml", ".yaml"])):
            log.critical(
                "[mkdocs-monorepo] The included file path {} does not point to a .yml (or .yaml) file"
                .format(self.absNavPath))
            raise SystemExit(1)

        if not self.absNavPath.startswith(self.rootDir):
            log.critical(
                "[mkdocs-monorepo] The mkdocs file {} is outside of the current directory. "
                .format(self.absNavPath) +
                "Please move the file and try again.")
            raise SystemExit(1)

        try:
            with open(self.absNavPath, 'rb') as f:
                self.navYaml = yaml_load(f)

            # This will check if there is a `docs_dir` property on the `mkdocs.yml` file of
            # the sub folder and scaffold the `nav` property from it
            if self.navYaml and 'nav' not in self.navYaml and "docs_dir" in self.navYaml:
                docsDirPath = os.path.join(os.path.dirname(self.absNavPath),
                                           self.navYaml["docs_dir"])

                def navFromDir(path):
                    directory = {}

                    for dirname, dirnames, filenames in os.walk(path):

                        dirnames.sort()
                        filenames.sort()

                        if dirname == docsDirPath:
                            dn = os.path.basename(dirname)
                        else:
                            dn = dirname_to_title(os.path.basename(dirname))
                        directory[dn] = []

                        for dirItem in dirnames:
                            subNav = navFromDir(
                                path=os.path.join(path, dirItem))
                            if subNav:
                                directory[dn].append(subNav)

                        for fileItem in filenames:
                            fileName, fileExt = os.path.splitext(fileItem)
                            if fileExt == '.md':
                                fileTitle = get_markdown_title(fileName)
                                filePath = os.path.join(
                                    os.path.relpath(path, docsDirPath),
                                    fileItem)
                                directory[dn].append({fileTitle: filePath})

                        if len(directory[dn]) == 0 or directory[dn] == [{}]:
                            del directory[dn]

                        return directory

                navYaml = navFromDir(docsDirPath)
                if navYaml:
                    self.navYaml["nav"] = navYaml[os.path.basename(
                        docsDirPath)]

        except OSError:
            log.critical(
                "[mkdocs-monorepo] The file path {} does not exist, ".format(
                    self.absNavPath) + "is not valid YAML, " +
                "or does not contain a valid 'site_name' and 'nav' keys.")
            raise SystemExit(1)

        if self.navYaml and 'site_name' not in self.navYaml:
            log.critical(
                "[mkdocs-monorepo] The file path {} does not contain a valid 'site_name' key "
                .format(self.absNavPath) +
                "in the YAML file. Please include it to indicate where your documentation "
                + "should be moved to.")
            raise SystemExit(1)

        if self.navYaml and 'nav' not in self.navYaml:
            log.critical(
                "[mkdocs-monorepo] The file path {} ".format(self.absNavPath) +
                "does not contain a valid 'nav' key in the YAML file. " +
                "Please include it to indicate how your documentation should be presented in the navigation, "
                +
                "or include a 'docs_dir' to indicate that automatic nav generation should be used."
            )
            raise SystemExit(1)

        return self
Exemplo n.º 21
0
 def load_file(self, config_file):
     return self.load_dict(utils.yaml_load(config_file))
Exemplo n.º 22
0
 def test_yaml_inheritance_missing_parent(self, tdir):
     with open(os.path.join(tdir, 'base.yml')) as fd:
         with self.assertRaises(exceptions.ConfigurationError):
             utils.yaml_load(fd)
Exemplo n.º 23
0
 def load_file(self, config_file):
     return self.load_dict(utils.yaml_load(config_file))
Exemplo n.º 24
0
    def resolve(self, nav=None):
        if nav is None:
            nav = copy.deepcopy(self.initialNav)

        for index, item in enumerate(nav):
            if type(item) is str:
                key = None
                value = item
            elif type(item) is dict:
                key = list(item.keys())[0]
                value = list(item.values())[0]
                if type(value) is str and value.startswith(
                        WILDCARD_INCLUDE_STATEMENT):
                    root_dir = Path(self.config['config_file_path']).parent
                    mkdocs_path = value[len(WILDCARD_INCLUDE_STATEMENT):]
                    if not mkdocs_path.endswith(tuple([".yml", ".yaml"])):
                        log.critical(
                            "[mkdocs-monorepo] The wildcard include path {} does not end with .yml (or .yaml)"
                            .format(mkdocs_path))
                        raise SystemExit(1)
                    dirs = sorted(root_dir.glob(mkdocs_path))
                    if dirs:
                        value = []
                        for mkdocs_config in dirs:
                            site = {}
                            try:
                                with open(mkdocs_config, 'rb') as f:
                                    site_yaml = yaml_load(f)
                                    site_name = site_yaml["site_name"]
                                site[
                                    site_name] = f"{INCLUDE_STATEMENT}{mkdocs_config.resolve()}"
                                value.append(site)
                            except OSError:
                                log.error(
                                    f"[mkdocs-monorepo] The {mkdocs_config} path is not valid."
                                )
                            except KeyError:
                                log.critical(
                                    "[mkdocs-monorepo] The file path {} does not contain a valid 'site_name' key "
                                    .format(mkdocs_config) +
                                    "in the YAML file. Please include it to indicate where your documentation "
                                    + "should be moved to.")
                                raise SystemExit(1)
                        if not value:
                            return None
                    else:
                        return None
            else:
                key = None
                value = None

            if type(value) is str and value.startswith(INCLUDE_STATEMENT):
                nav[index] = {}
                nav[index][key] = IncludeNavLoader(
                    self.config,
                    value[len(INCLUDE_STATEMENT):]).read().getNav()

                if nav[index][key] is None:
                    return None
            elif type(value) is list:
                nav[index] = {}
                nav[index][key] = self.resolve(value)

                if nav[index][key] is None:
                    return None

        return nav