def has_package_conf(repository, package, directory="", keep=False):
    """Check if there is a Sphinx conf.py inside of a Rez package.

    Args:
        repository (str):
            The URL pointing to a git repository that contains `package`
            somewhere inside of it.
        package (str):
            The name of the Rez packge to find within `repository`.
        directory (str, optional):
            Part of checking for a conf.py file involves cloning the
            given `repository` to disk. If a root folder is given, the
            repository will be cloned as a child of this directory. If
            no folder is given, a temporary directory is chosen for the
            user. Default: "".
        keep (bool, optional):
            If False, delete temporary directories once they are no
            If longer needed. True, don't delete them. Default is False.

    Returns:
        bool: If a conf.py was found.

    """
    repository = _get_repository(repository, directory=directory, keep=keep)

    for path in _iter_package_files(repository.working_dir):
        name = packages_.get_developer_package(os.path.dirname(path)).name

        if name == package:
            return bool(conf_manager.get_conf_file(os.path.dirname(path)))

    return False
Esempio n. 2
0
def fix_intersphinx_mapping(  # pylint: disable=too-many-arguments
        package, sphinx_files_must_exist, excluded_packages):
    """Replace or add the ``intersphinx_mapping`` attribute to a user's conf.py Sphinx file.

    Args:
        package (:class:`rez.developer_package.DeveloperPackage`):
            The Rez package to modify with a new, updated intersphinx mapping.
        sphinx_files_must_exist (bool, optional):
            If True and the "conf.py" files doesn't exist, raise an
            exception. If False and the file doesn't exist, don't error
            If and just keep moving. Default is False.
        excluded_packages (iter[str]):
            The names of Rez packages to ignore. Any intersphinx
            key/value pair that matches any of the names given to this
            parameter will be ignored. This parameter supports glob matching.

    Raises:
        :class:`.exceptions.SphinxFileMissing`:
            If `sphinx_files_must_exist` but the source package has no
            documentation.

    Returns:
        bool: If False, no fix was applied. If True, at least one file on-disk was changed.

    """
    root = os.path.dirname(package.filepath)

    if sphinx_files_must_exist and _is_conf_file_missing(root):
        raise exceptions.SphinxFileMissing(
            "conf.py is missing. Either set sphinx_files_must_exist to False "
            "or create a conf.py to continue.")

    try:
        missing = get_missing_intersphinx_mappings(
            package, sphinx_files_must_exist=False)
    except exceptions.SphinxFileMissing:
        raise exceptions.SphinxFileMissing(
            'Package "{package.name}" has no conf.py file. '
            "Please create it and re-run this command.".format(
                package=package))

    missing = {
        name: item
        for name, item in missing.items() if not any(
            fnmatch.fnmatch(name, pattern) for pattern in excluded_packages)
    }

    if not missing:
        return False

    conf_file = conf_manager.get_conf_file(root)
    links = get_existing_intersphinx_links(root)
    links.update(missing)

    sphinx_helper.replace_intersphinx_mapping(links, conf_file)

    return True
    def run(cls, package, context):
        """Find a documentation for the Rez package.

        Args:
            package (:class:`rez.packages_.DeveloperPackage`):
                The Rez package that may or may not need documentation.
            context (:class:`.Context`):
                A data instance that knows whether `package` has a
                Python package. If there's no Python package, this
                checker is cancelled.

        Returns:
            list[:class:`.Description`]:
                If no issues are found, return an empty list. Otherwise,
                return one description of each found issue.

        """
        if not _has_context_python_package(context):
            return []

        root = finder.get_package_root(package)

        if conf_manager.get_conf_file(root):
            return []  # pragma: no cover

        summary = "No documentation found"
        full = [
            summary,
            "Consider adding documentation to your Python package.",
            "Reference: https://www.sphinx-doc.org/en/master/usage/quickstart.html",
        ]
        code = base_checker.Code(short_name="E", long_name=cls.get_long_code())
        location = message_description.Location(path=root,
                                                row=0,
                                                column=0,
                                                text="")

        return [
            message_description.Description([summary],
                                            location,
                                            code=code,
                                            full=full),
        ]
Esempio n. 4
0
def get_existing_intersphinx_links(directory):
    """Find the intersphinx information that's already written on-disk.

    Args:
        directory (str):
            The root directory of the Rez package. It's assumed that
            this directory has documentation written for it.

    Raises:
        EnvironmentError:
            If a conf.py was found but its ``intersphinx_mapping`` attribute is invalid.

    Returns:
        dict[str, tuple[str, NoneType]]:
            Each intersphinx label and the URL + target location.

    """
    conf_file = conf_manager.get_conf_file(directory)

    if not conf_file:
        _LOGGER.debug(
            'Directory "%s" has no Sphinx conf.py file was found. '
            "Returning an empty dict.",
            directory,
        )
        return dict()

    module = conf_manager.import_conf_file(conf_file)

    if hasattr(module, "intersphinx_mapping"):
        mapping = module.intersphinx_mapping or dict()

        if not isinstance(mapping, collections.MutableMapping):
            raise EnvironmentError(
                'conf.py "{conf_file}" has an intersphinx_mapping but it is not a dict.'
                .format(conf_file=conf_file))

        return mapping

    return dict()
Esempio n. 5
0
def _is_conf_file_missing(directory):
    """bool: Check if a Sphinx conf.py can be found starting at `directory` Rez package."""
    return not conf_manager.get_conf_file(directory)
Esempio n. 6
0
def has_documentation(package):
    """Check if the given Rez package has documentation already.

    The logic for this function is bit involved.

    There are 2 "categories" of Rez packages

    - source Rez packages (packages that haven't been built/installed/released yet).
    - built/installed/released packages.

    Built Rez packages may not actually have documentation installed
    with the package. So if documentation is missing, you have to
    check the repository that the package came from to be totally
    sure. You can clone the repository and check it locally or check
    the repository remotely (doing it remotely is much faster but is
    also more complex).

    Source Rez packages however contain 100% of the package
    definition plus its documentation configuration files. So
    we only need to query for files on-disk to figure out if
    documentation is missing this function is given a source Rez
    package.

    Args:
        package (:class:`rez.packages_.Package`):
            The Rez package to check for existing documentation.

    Raises:
        :class:`exceptions.NoGitRepository`:
            If a repository URL was found but the remote repository
            could not be reached.

    Returns:
        str: A generic message saying that the package already has documentation.

    """
    if not inspection.is_built_package(package):
        root = finder.get_package_root(package)

        if conf_manager.get_conf_file(root):
            return True

    repository = rez_git.get_repository_url(package)

    if not repository:
        raise exceptions.NoGitRepository(
            package,
            finder.get_package_root(package),
            "A built Rez package was found but it has no git repository.",
        )

    keep = _is_keep_temporary_files_enabled()
    directory = _get_temporary_directory()

    remote_file = git_link.has_package_conf(repository,
                                            package.name,
                                            directory=directory,
                                            keep=keep)

    if remote_file:
        return True

    return False