Beispiel #1
0
    def get_bitbucket_url(self, docroot, filename, source_suffix='.rst'):
        repo_url = self.project.repo
        if 'bitbucket' not in repo_url:
            return ''
        if not docroot:
            return ''

        # Normalize /docroot/
        docroot = '/' + docroot.strip('/') + '/'

        user, repo = get_bitbucket_username_repo(repo_url)
        if not user and not repo:
            return ''

        if not filename:
            # If there isn't a filename, we don't need a suffix
            source_suffix = ''

        return BITBUCKET_URL.format(
            user=user,
            repo=repo,
            version=self.commit_name,
            docroot=docroot,
            path=filename,
            source_suffix=source_suffix,
        )
Beispiel #2
0
    def setup_webhook(self, project):
        """Set up Bitbucket project webhook for project

        :param project: project to set up webhook for
        :type project: Project
        :returns: boolean based on webhook set up success, and requests Response object
        :rtype: (Bool, Response)
        """
        session = self.get_session()
        owner, repo = build_utils.get_bitbucket_username_repo(url=project.repo)
        data = json.dumps({
            'description': 'Read the Docs ({domain})'.format(domain=settings.PRODUCTION_DOMAIN),
            'url': 'https://{domain}/bitbucket'.format(domain=settings.PRODUCTION_DOMAIN),
            'active': True,
            'events': ['repo:push'],
        })
        try:
            resp = session.post(
                ('https://api.bitbucket.org/2.0/repositories/{owner}/{repo}/hooks'
                 .format(owner=owner, repo=repo)),
                data=data,
                headers={'content-type': 'application/json'}
            )
            if resp.status_code == 201:
                log.info('Bitbucket webhook creation successful for project: %s',
                         project)
                return (True, resp)
        except RequestException:
            log.error('Bitbucket webhook creation failed for project: %s',
                      project, exc_info=True)
        else:
            log.error('Bitbucket webhook creation failed for project: %s',
                      project)
            return (False, resp)
    def setup_webhook(self, project, integration=None):
        """
        Set up Bitbucket project webhook for project.

        :param project: project to set up webhook for
        :type project: Project
        :param integration: Integration for the project
        :type integration: Integration
        :returns: boolean based on webhook set up success, and requests Response object
        :rtype: (Bool, Response)
        """
        session = self.get_session()
        owner, repo = build_utils.get_bitbucket_username_repo(url=project.repo)
        url = f'https://api.bitbucket.org/2.0/repositories/{owner}/{repo}/hooks'
        if not integration:
            integration, _ = Integration.objects.get_or_create(
                project=project,
                integration_type=Integration.BITBUCKET_WEBHOOK,
            )
        data = self.get_webhook_data(project, integration)
        resp = None
        log.bind(
            project_slug=project.slug,
            integration_id=integration.pk,
            url=url,
        )

        try:
            resp = session.post(
                url,
                data=data,
                headers={'content-type': 'application/json'},
            )
            if resp.status_code == 201:
                recv_data = resp.json()
                integration.provider_data = recv_data
                integration.save()
                log.debug(
                    'Bitbucket webhook creation successful for project.', )
                return (True, resp)

            if resp.status_code in [401, 403, 404]:
                log.info(
                    'Bitbucket project does not exist or user does not have permissions.',
                )
            else:
                try:
                    debug_data = resp.json()
                except ValueError:
                    debug_data = resp.content
                log.warning(
                    'Bitbucket webhook creation failed.',
                    debug_data=debug_data,
                )

        # Catch exceptions with request or deserializing JSON
        except (RequestException, ValueError):
            log.exception('Bitbucket webhook creation failed for project.')

        return (False, resp)
Beispiel #4
0
    def get_commit_url(self):
        """Return the commit URL."""
        repo_url = self.project.repo
        if self.is_external:
            if 'github' in repo_url:
                user, repo = get_github_username_repo(repo_url)
                if not user and not repo:
                    return ''

                return GITHUB_PULL_REQUEST_COMMIT_URL.format(
                    user=user,
                    repo=repo,
                    number=self.get_version_name(),
                    commit=self.commit
                )
            if 'gitlab' in repo_url:
                user, repo = get_gitlab_username_repo(repo_url)
                if not user and not repo:
                    return ''

                return GITLAB_MERGE_REQUEST_COMMIT_URL.format(
                    user=user,
                    repo=repo,
                    number=self.get_version_name(),
                    commit=self.commit
                )
            # TODO: Add External Version Commit URL for BitBucket.
        else:
            if 'github' in repo_url:
                user, repo = get_github_username_repo(repo_url)
                if not user and not repo:
                    return ''

                return GITHUB_COMMIT_URL.format(
                    user=user,
                    repo=repo,
                    commit=self.commit
                )
            if 'gitlab' in repo_url:
                user, repo = get_gitlab_username_repo(repo_url)
                if not user and not repo:
                    return ''

                return GITLAB_COMMIT_URL.format(
                    user=user,
                    repo=repo,
                    commit=self.commit
                )
            if 'bitbucket' in repo_url:
                user, repo = get_bitbucket_username_repo(repo_url)
                if not user and not repo:
                    return ''

                return BITBUCKET_COMMIT_URL.format(
                    user=user,
                    repo=repo,
                    commit=self.commit
                )

        return None
Beispiel #5
0
    def get_config_params(self):
        """Get configuration parameters to be rendered into the conf file."""
        # TODO this should be handled better in the theme
        conf_py_path = os.path.join(os.path.sep,
                                    self.version.get_conf_py_path(),
                                    '')
        remote_version = self.version.commit_name

        github_user, github_repo = version_utils.get_github_username_repo(
            url=self.project.repo)
        github_version_is_editable = (self.version.type == 'branch')
        display_github = github_user is not None

        bitbucket_user, bitbucket_repo = version_utils.get_bitbucket_username_repo(
            url=self.project.repo)
        bitbucket_version_is_editable = (self.version.type == 'branch')
        display_bitbucket = bitbucket_user is not None

        # Avoid hitting database and API if using Docker build environment
        if getattr(settings, 'DONT_HIT_API', False):
            versions = self.project.active_versions()
            downloads = self.version.get_downloads(pretty=True)
        else:
            versions = self.project.api_versions()
            downloads = api.version(self.version.pk).get()['downloads']

        data = {
            'current_version': self.version.verbose_name,
            'project': self.project,
            'settings': settings,
            'static_path': SPHINX_STATIC_DIR,
            'template_path': SPHINX_TEMPLATE_DIR,
            'conf_py_path': conf_py_path,
            'api_host': getattr(settings, 'PUBLIC_API_URL', 'https://readthedocs.org'),
            'commit': self.project.vcs_repo(self.version.slug).commit,
            'versions': versions,
            'downloads': downloads,

            # GitHub
            'github_user': github_user,
            'github_repo': github_repo,
            'github_version': remote_version,
            'github_version_is_editable': github_version_is_editable,
            'display_github': display_github,

            # BitBucket
            'bitbucket_user': bitbucket_user,
            'bitbucket_repo': bitbucket_repo,
            'bitbucket_version': remote_version,
            'bitbucket_version_is_editable': bitbucket_version_is_editable,
            'display_bitbucket': display_bitbucket,
        }

        finalize_sphinx_context_data.send(
            sender=self.__class__,
            build_env=self.build_env,
            data=data,
        )

        return data
    def get_provider_data(self, project, integration):
        """
        Gets provider data from BitBucket Webhooks API.

        :param project: project
        :type project: Project
        :param integration: Integration for the project
        :type integration: Integration
        :returns: Dictionary containing provider data from the API or None
        :rtype: dict
        """

        if integration.provider_data:
            return integration.provider_data

        session = self.get_session()
        owner, repo = build_utils.get_bitbucket_username_repo(url=project.repo)
        url = f'https://api.bitbucket.org/2.0/repositories/{owner}/{repo}/hooks'

        rtd_webhook_url = 'https://{domain}{path}'.format(
            domain=settings.PRODUCTION_DOMAIN,
            path=reverse(
                'api_webhook',
                kwargs={
                    'project_slug': project.slug,
                    'integration_pk': integration.pk,
                },
            ),
        )

        log.bind(
            project_slug=project.slug,
            integration_id=integration.pk,
            url=url,
        )
        try:
            resp = session.get(url)

            if resp.status_code == 200:
                recv_data = resp.json()

                for webhook_data in recv_data["values"]:
                    if webhook_data["url"] == rtd_webhook_url:
                        integration.provider_data = webhook_data
                        integration.save()

                        log.info(
                            'Bitbucket integration updated with provider data for project.',
                        )
                        break
            else:
                log.info(
                    'Bitbucket project does not exist or user does not have permissions.',
                )

        except Exception:
            log.exception('Bitbucket webhook Listing failed for project.', )

        return integration.provider_data
Beispiel #7
0
def add_bitbucket_webhook(session, project):
    owner, repo = build_utils.get_bitbucket_username_repo(url=project.repo)
    data = {"type": "POST", "url": "https://{domain}/bitbucket".format(domain=settings.PRODUCTION_DOMAIN)}
    resp = session.post(
        "https://api.bitbucket.org/1.0/repositories/{owner}/{repo}/services".format(owner=owner, repo=repo), data=data
    )
    log.info("Creating BitBucket webhook response code: {code}".format(code=resp.status_code))
    return resp
    def setup_webhook(self, project):
        """
        Set up Bitbucket project webhook for project.

        :param project: project to set up webhook for
        :type project: Project
        :returns: boolean based on webhook set up success, and requests Response object
        :rtype: (Bool, Response)
        """
        session = self.get_session()
        owner, repo = build_utils.get_bitbucket_username_repo(url=project.repo)
        integration, _ = Integration.objects.get_or_create(
            project=project,
            integration_type=Integration.BITBUCKET_WEBHOOK,
        )
        data = self.get_webhook_data(project, integration)
        resp = None
        try:
            resp = session.post(
                (
                    'https://api.bitbucket.org/2.0/repositories/{owner}/{repo}/hooks'
                    .format(owner=owner, repo=repo)
                ),
                data=data,
                headers={'content-type': 'application/json'},
            )
            if resp.status_code == 201:
                recv_data = resp.json()
                integration.provider_data = recv_data
                integration.save()
                log.info(
                    'Bitbucket webhook creation successful for project: %s',
                    project,
                )
                return (True, resp)
        # Catch exceptions with request or deserializing JSON
        except (RequestException, ValueError):
            log.exception(
                'Bitbucket webhook creation failed for project: %s',
                project,
            )
        else:
            log.error(
                'Bitbucket webhook creation failed for project: %s',
                project,
            )
            try:
                log.debug(
                    'Bitbucket webhook creation failure response: %s',
                    resp.json(),
                )
            except ValueError:
                pass
            return (False, resp)
    def setup_webhook(self, project):
        """
        Set up Bitbucket project webhook for project.

        :param project: project to set up webhook for
        :type project: Project
        :returns: boolean based on webhook set up success, and requests Response object
        :rtype: (Bool, Response)
        """
        session = self.get_session()
        owner, repo = build_utils.get_bitbucket_username_repo(url=project.repo)
        integration, _ = Integration.objects.get_or_create(
            project=project,
            integration_type=Integration.BITBUCKET_WEBHOOK,
        )
        data = self.get_webhook_data(project, integration)
        resp = None
        try:
            resp = session.post(
                (
                    'https://api.bitbucket.org/2.0/repositories/{owner}/{repo}/hooks'
                    .format(owner=owner, repo=repo)
                ),
                data=data,
                headers={'content-type': 'application/json'},
            )
            if resp.status_code == 201:
                recv_data = resp.json()
                integration.provider_data = recv_data
                integration.save()
                log.info(
                    'Bitbucket webhook creation successful for project: %s',
                    project,
                )
                return (True, resp)
        # Catch exceptions with request or deserializing JSON
        except (RequestException, ValueError):
            log.exception(
                'Bitbucket webhook creation failed for project: %s',
                project,
            )
        else:
            log.error(
                'Bitbucket webhook creation failed for project: %s',
                project,
            )
            try:
                log.debug(
                    'Bitbucket webhook creation failure response: %s',
                    resp.json(),
                )
            except ValueError:
                pass
            return (False, resp)
Beispiel #10
0
    def get_config_params(self):
        """Get configuration parameters to be rendered into the conf file."""
        # TODO this should be handled better in the theme
        conf_py_path = os.path.join(os.path.sep,
                                    self.version.get_conf_py_path(),
                                    '')
        remote_version = self.version.commit_name

        github_user, github_repo = version_utils.get_github_username_repo(
            url=self.project.repo)
        github_version_is_editable = (self.version.type == 'branch')
        display_github = github_user is not None

        bitbucket_user, bitbucket_repo = version_utils.get_bitbucket_username_repo(
            url=self.project.repo)
        bitbucket_version_is_editable = (self.version.type == 'branch')
        display_bitbucket = bitbucket_user is not None

        # Avoid hitting database and API if using Docker build environment
        if getattr(settings, 'DONT_HIT_API', False):
            versions = self.project.active_versions()
            downloads = self.version.get_downloads(pretty=True)
        else:
            versions = self.project.api_versions()
            downloads = api.version(self.version.pk).get()['downloads']

        return {
            'current_version': self.version.verbose_name,
            'project': self.project,
            'settings': settings,
            'static_path': SPHINX_STATIC_DIR,
            'template_path': SPHINX_TEMPLATE_DIR,
            'conf_py_path': conf_py_path,
            'api_host': getattr(settings, 'PUBLIC_API_URL', 'https://readthedocs.org'),
            'commit': self.project.vcs_repo(self.version.slug).commit,
            'versions': versions,
            'downloads': downloads,

            # GitHub
            'github_user': github_user,
            'github_repo': github_repo,
            'github_version': remote_version,
            'github_version_is_editable': github_version_is_editable,
            'display_github': display_github,

            # BitBucket
            'bitbucket_user': bitbucket_user,
            'bitbucket_repo': bitbucket_repo,
            'bitbucket_version': remote_version,
            'bitbucket_version_is_editable': bitbucket_version_is_editable,
            'display_bitbucket': display_bitbucket,
        }
Beispiel #11
0
def add_bitbucket_webhook(session, project):
    owner, repo = build_utils.get_bitbucket_username_repo(url=project.repo)
    data = {
        'type': 'POST',
        'url': 'https://{domain}/bitbucket'.format(domain=settings.PRODUCTION_DOMAIN),
    }
    resp = session.post(
        'https://api.bitbucket.org/1.0/repositories/{owner}/{repo}/services'.format(
            owner=owner, repo=repo
        ),
        data=data,
    )
    log.info("Creating BitBucket webhook response code: {code}".format(code=resp.status_code))
    return resp
Beispiel #12
0
def handle_project_import(sender, **kwargs):
    """
    Add post-commit hook on project import.
    """

    project = sender
    request = kwargs.get('request')

    for provider in ['github', 'bitbucket']:
        if provider in project.repo:
            session = oauth_utils.get_oauth_session(user=request.user, provider=provider)
            if not session:
                break
            if provider == 'github':
                try:
                    owner, repo = build_utils.get_github_username_repo(url=project.repo)
                    data = json.dumps({
                        'name': 'readthedocs',
                        'active': True,
                        'config': {'url': 'https://{domain}/github'.format(domain=settings.PRODUCTION_DOMAIN)}
                    })
                    resp = session.post(
                        'https://api.github.com/repos/{owner}/{repo}/hooks'.format(owner=owner, repo=repo),
                        data=data,
                        headers={'content-type': 'application/json'}
                    )
                    log.info("Creating GitHub webhook response code: {code}".format(code=resp.status_code))
                    if resp.status_code == 201:
                        messages.success(request, _('GitHub webhook activated'))
                except:
                    log.exception('GitHub Hook creation failed', exc_info=True)
            elif provider == 'bitbucket':
                try:
                    owner, repo = build_utils.get_bitbucket_username_repo(url=project.repo)
                    data = {
                        'type': 'POST',
                        'url': 'https://{domain}/bitbucket'.format(domain=settings.PRODUCTION_DOMAIN),
                    }
                    resp = session.post(
                        'https://api.bitbucket.org/1.0/repositories/{owner}/{repo}/services'.format(owner=owner, repo=repo),
                        data=data,
                    )
                    log.info("Creating BitBucket webhook response code: {code}".format(code=resp.status_code))
                    if resp.status_code == 200:
                        messages.success(request, _('BitBucket webhook activated'))
                except:
                    log.exception('BitBucket Hook creation failed', exc_info=True)
Beispiel #13
0
    def get_commit_url(self):
        """Return the commit URL."""
        repo_url = self.project.repo
        if self.is_external:
            if 'github' in repo_url:
                user, repo = get_github_username_repo(repo_url)
                if not user and not repo:
                    return ''

                repo = repo.rstrip('/')
                return GITHUB_PULL_REQUEST_COMMIT_URL.format(
                    user=user,
                    repo=repo,
                    number=self.version.verbose_name,
                    commit=self.commit)
            # TODO: Add External Version Commit URL for other Git Providers
        else:
            if 'github' in repo_url:
                user, repo = get_github_username_repo(repo_url)
                if not user and not repo:
                    return ''

                repo = repo.rstrip('/')
                return GITHUB_COMMIT_URL.format(user=user,
                                                repo=repo,
                                                commit=self.commit)
            if 'gitlab' in repo_url:
                user, repo = get_gitlab_username_repo(repo_url)
                if not user and not repo:
                    return ''

                repo = repo.rstrip('/')
                return GITLAB_COMMIT_URL.format(user=user,
                                                repo=repo,
                                                commit=self.commit)
            if 'bitbucket' in repo_url:
                user, repo = get_bitbucket_username_repo(repo_url)
                if not user and not repo:
                    return ''

                repo = repo.rstrip('/')
                return BITBUCKET_COMMIT_URL.format(user=user,
                                                   repo=repo,
                                                   commit=self.commit)

        return None
Beispiel #14
0
    def setup_webhook(self, project):
        """Set up Bitbucket project webhook for project

        :param project: project to set up webhook for
        :type project: Project
        :returns: boolean based on webhook set up success, and requests Response object
        :rtype: (Bool, Response)
        """
        session = self.get_session()
        owner, repo = build_utils.get_bitbucket_username_repo(url=project.repo)
        data = json.dumps({
            'description':
            'Read the Docs ({domain})'.format(
                domain=settings.PRODUCTION_DOMAIN),
            'url':
            'https://{domain}{path}'.format(
                domain=settings.PRODUCTION_DOMAIN,
                path=reverse('api_webhook_bitbucket',
                             kwargs={'project_slug': project.slug})),
            'active':
            True,
            'events': ['repo:push'],
        })
        try:
            resp = session.post((
                'https://api.bitbucket.org/2.0/repositories/{owner}/{repo}/hooks'
                .format(owner=owner, repo=repo)),
                                data=data,
                                headers={'content-type': 'application/json'})
            if resp.status_code == 201:
                log.info(
                    'Bitbucket webhook creation successful for project: %s',
                    project)
                return (True, resp)
        except RequestException:
            log.error('Bitbucket webhook creation failed for project: %s',
                      project,
                      exc_info=True)
        else:
            log.error('Bitbucket webhook creation failed for project: %s',
                      project)
            log.debug('Bitbucket webhook creation failure response: %s',
                      dict(resp))
            return (False, resp)
Beispiel #15
0
    def get_config_params(self):
        """Get configuration parameters to be rendered into the conf file."""
        # TODO this should be handled better in the theme
        conf_py_path = os.path.join(
            os.path.sep,
            os.path.dirname(
                os.path.relpath(
                    self.config_file,
                    self.project.checkout_path(self.version.slug),
                ), ),
            '',
        )
        remote_version = self.version.commit_name

        github_user, github_repo = version_utils.get_github_username_repo(
            url=self.project.repo, )
        github_version_is_editable = (self.version.type == 'branch')
        display_github = github_user is not None

        bitbucket_user, bitbucket_repo = version_utils.get_bitbucket_username_repo(  # noqa
            url=self.project.repo, )
        bitbucket_version_is_editable = (self.version.type == 'branch')
        display_bitbucket = bitbucket_user is not None

        gitlab_user, gitlab_repo = version_utils.get_gitlab_username_repo(
            url=self.project.repo, )
        gitlab_version_is_editable = (self.version.type == 'branch')
        display_gitlab = gitlab_user is not None

        # Avoid hitting database and API if using Docker build environment
        if getattr(settings, 'DONT_HIT_API', False):
            versions = self.project.active_versions()
            downloads = self.version.get_downloads(pretty=True)
        else:
            versions = self.project.api_versions()
            downloads = api.version(self.version.pk).get()['downloads']

        data = {
            'html_theme':
            'sphinx_rtd_theme',
            'html_theme_import':
            'sphinx_rtd_theme',
            'current_version':
            self.version.verbose_name,
            'project':
            self.project,
            'version':
            self.version,
            'settings':
            settings,
            'conf_py_path':
            conf_py_path,
            'api_host':
            getattr(
                settings,
                'PUBLIC_API_URL',
                'https://readthedocs.org',
            ),
            'commit':
            self.project.vcs_repo(self.version.slug).commit,
            'versions':
            versions,
            'downloads':
            downloads,

            # GitHub
            'github_user':
            github_user,
            'github_repo':
            github_repo,
            'github_version':
            remote_version,
            'github_version_is_editable':
            github_version_is_editable,
            'display_github':
            display_github,

            # BitBucket
            'bitbucket_user':
            bitbucket_user,
            'bitbucket_repo':
            bitbucket_repo,
            'bitbucket_version':
            remote_version,
            'bitbucket_version_is_editable':
            bitbucket_version_is_editable,
            'display_bitbucket':
            display_bitbucket,

            # GitLab
            'gitlab_user':
            gitlab_user,
            'gitlab_repo':
            gitlab_repo,
            'gitlab_version':
            remote_version,
            'gitlab_version_is_editable':
            gitlab_version_is_editable,
            'display_gitlab':
            display_gitlab,

            # Features
            'dont_overwrite_sphinx_context':
            self.project.has_feature(Feature.DONT_OVERWRITE_SPHINX_CONTEXT, ),
        }

        finalize_sphinx_context_data.send(
            sender=self.__class__,
            build_env=self.build_env,
            data=data,
        )

        return data
Beispiel #16
0
    def get_config_params(self):
        """Get configuration parameters to be rendered into the conf file."""
        # TODO this should be handled better in the theme
        conf_py_path = os.path.join(
            os.path.sep,
            os.path.dirname(
                os.path.relpath(
                    self.config_file,
                    self.project.checkout_path(self.version.slug),
                ),
            ),
            '',
        )
        remote_version = self.version.commit_name

        github_user, github_repo = version_utils.get_github_username_repo(
            url=self.project.repo,
        )
        github_version_is_editable = (self.version.type == 'branch')
        display_github = github_user is not None

        bitbucket_user, bitbucket_repo = version_utils.get_bitbucket_username_repo(  # noqa
            url=self.project.repo,
        )
        bitbucket_version_is_editable = (self.version.type == 'branch')
        display_bitbucket = bitbucket_user is not None

        gitlab_user, gitlab_repo = version_utils.get_gitlab_username_repo(
            url=self.project.repo,
        )
        gitlab_version_is_editable = (self.version.type == 'branch')
        display_gitlab = gitlab_user is not None

        # Avoid hitting database and API if using Docker build environment
        if settings.DONT_HIT_API:
            versions = self.project.active_versions()
            downloads = self.version.get_downloads(pretty=True)
        else:
            versions = self.project.api_versions()
            downloads = api.version(self.version.pk).get()['downloads']

        data = {
            'html_theme': 'sphinx_rtd_theme',
            'html_theme_import': 'sphinx_rtd_theme',
            'current_version': self.version.verbose_name,
            'project': self.project,
            'version': self.version,
            'settings': settings,
            'conf_py_path': conf_py_path,
            'api_host': settings.PUBLIC_API_URL,
            'commit': self.project.vcs_repo(self.version.slug).commit,
            'versions': versions,
            'downloads': downloads,

            # GitHub
            'github_user': github_user,
            'github_repo': github_repo,
            'github_version': remote_version,
            'github_version_is_editable': github_version_is_editable,
            'display_github': display_github,

            # BitBucket
            'bitbucket_user': bitbucket_user,
            'bitbucket_repo': bitbucket_repo,
            'bitbucket_version': remote_version,
            'bitbucket_version_is_editable': bitbucket_version_is_editable,
            'display_bitbucket': display_bitbucket,

            # GitLab
            'gitlab_user': gitlab_user,
            'gitlab_repo': gitlab_repo,
            'gitlab_version': remote_version,
            'gitlab_version_is_editable': gitlab_version_is_editable,
            'display_gitlab': display_gitlab,

            # Features
            'dont_overwrite_sphinx_context': self.project.has_feature(
                Feature.DONT_OVERWRITE_SPHINX_CONTEXT,
            ),
            'use_pdf_latexmk': self.project.has_feature(
                Feature.USE_PDF_LATEXMK,
            ),
        }

        finalize_sphinx_context_data.send(
            sender=self.__class__,
            build_env=self.build_env,
            data=data,
        )

        return data
Beispiel #17
0
    def append_conf(self, **kwargs):
        """Modify the given ``conf.py`` file from a whitelisted user's project.
        """

        # Pull config data
        try:
            conf_py_path = self.version.get_conf_py_path()
        except ProjectImportError:
            self._write_config()
            self.create_index(extension='rst')

        project = self.version.project
        # Open file for appending.
        try:
            outfile = codecs.open(project.conf_file(self.version.slug), encoding='utf-8', mode='a')
        except IOError:
            trace = sys.exc_info()[2]
            raise ProjectImportError('Conf file not found'), None, trace
        outfile.write("\n")
        conf_py_path = self.version.get_conf_py_path()
        remote_version = self.version.get_vcs_slug()

        github_user, github_repo = version_utils.get_github_username_repo(
            url=self.version.project.repo)
        github_version_is_editable = (self.version.type == 'branch')
        display_github = github_user is not None

        bitbucket_user, bitbucket_repo = version_utils.get_bitbucket_username_repo(
            url=self.version.project.repo)
        bitbucket_version_is_editable = (self.version.type == 'branch')
        display_bitbucket = bitbucket_user is not None

        rtd_ctx = Context({
            'current_version': self.version.verbose_name,
            'project': project,
            'settings': settings,
            'static_path': STATIC_DIR,
            'template_path': TEMPLATE_DIR,
            'conf_py_path': conf_py_path,
            'api_host': getattr(settings, 'SLUMBER_API_HOST', 'https://readthedocs.org'),
            # GitHub
            'github_user': github_user,
            'github_repo': github_repo,
            'github_version': remote_version,
            'github_version_is_editable': github_version_is_editable,
            'display_github': display_github,
            # BitBucket
            'bitbucket_user': bitbucket_user,
            'bitbucket_repo': bitbucket_repo,
            'bitbucket_version': remote_version,
            'bitbucket_version_is_editable': bitbucket_version_is_editable,
            'display_bitbucket': display_bitbucket,
            'commit': self.version.project.vcs_repo(self.version.slug).commit,
        })

        # Avoid hitting database and API if using Docker build environment
        if getattr(settings, 'DONT_HIT_API', False):
            rtd_ctx['versions'] = project.active_versions()
            rtd_ctx['downloads'] = self.version.get_downloads(pretty=True)
        else:
            rtd_ctx['versions'] = project.api_versions()
            rtd_ctx['downloads'] = (api.version(self.version.pk)
                                    .get()['downloads'])

        rtd_string = template_loader.get_template('doc_builder/conf.py.tmpl').render(rtd_ctx)
        outfile.write(rtd_string)
Beispiel #18
0
    def get_config_params(self):
        """Get configuration parameters to be rendered into the conf file."""
        # TODO this should be handled better in the theme
        conf_py_path = os.path.join(
            os.path.sep,
            os.path.dirname(
                os.path.relpath(
                    self.config_file,
                    self.project.checkout_path(self.version.slug),
                ), ),
            '',
        )
        remote_version = self.version.commit_name

        github_user, github_repo = version_utils.get_github_username_repo(
            url=self.project.repo, )
        github_version_is_editable = (self.version.type == 'branch')
        display_github = github_user is not None

        bitbucket_user, bitbucket_repo = version_utils.get_bitbucket_username_repo(  # noqa
            url=self.project.repo, )
        bitbucket_version_is_editable = (self.version.type == 'branch')
        display_bitbucket = bitbucket_user is not None

        gitlab_user, gitlab_repo = version_utils.get_gitlab_username_repo(
            url=self.project.repo, )
        gitlab_version_is_editable = (self.version.type == 'branch')
        display_gitlab = gitlab_user is not None

        versions = []
        downloads = []
        subproject_urls = []
        # Avoid hitting database and API if using Docker build environment
        if settings.DONT_HIT_API:
            if self.project.has_feature(Feature.ALL_VERSIONS_IN_HTML_CONTEXT):
                versions = self.project.active_versions()
            else:
                versions = self.project.active_versions().filter(
                    privacy_level=PUBLIC, )
            downloads = self.version.get_downloads(pretty=True)
            subproject_urls = self.project.get_subproject_urls()
        else:
            try:
                versions = self.project.api_versions()
                if not self.project.has_feature(
                        Feature.ALL_VERSIONS_IN_HTML_CONTEXT):
                    versions = [
                        v for v in versions if v.privacy_level == PUBLIC
                    ]
                downloads = api.version(self.version.pk).get()['downloads']
                subproject_urls = self.project.get_subproject_urls()
            except ConnectionError:
                log.exception(
                    'Timeout while fetching versions/downloads/subproject_urls for Sphinx context. '
                    'project: %s version: %s',
                    self.project.slug,
                    self.version.slug,
                )

        data = {
            'html_theme':
            'sphinx_rtd_theme',
            'html_theme_import':
            'sphinx_rtd_theme',
            'current_version':
            self.version.verbose_name,
            'project':
            self.project,
            'version':
            self.version,
            'settings':
            settings,
            'conf_py_path':
            conf_py_path,
            'api_host':
            settings.PUBLIC_API_URL,
            'commit':
            self.project.vcs_repo(self.version.slug).commit,
            'versions':
            versions,
            'downloads':
            downloads,
            'subproject_urls':
            subproject_urls,

            # GitHub
            'github_user':
            github_user,
            'github_repo':
            github_repo,
            'github_version':
            remote_version,
            'github_version_is_editable':
            github_version_is_editable,
            'display_github':
            display_github,

            # BitBucket
            'bitbucket_user':
            bitbucket_user,
            'bitbucket_repo':
            bitbucket_repo,
            'bitbucket_version':
            remote_version,
            'bitbucket_version_is_editable':
            bitbucket_version_is_editable,
            'display_bitbucket':
            display_bitbucket,

            # GitLab
            'gitlab_user':
            gitlab_user,
            'gitlab_repo':
            gitlab_repo,
            'gitlab_version':
            remote_version,
            'gitlab_version_is_editable':
            gitlab_version_is_editable,
            'display_gitlab':
            display_gitlab,

            # Features
            'dont_overwrite_sphinx_context':
            self.project.has_feature(Feature.DONT_OVERWRITE_SPHINX_CONTEXT, ),
        }

        finalize_sphinx_context_data.send(
            sender=self.__class__,
            build_env=self.build_env,
            data=data,
        )

        return data
Beispiel #19
0
    def append_conf(self, **kwargs):
        """Modify the given ``conf.py`` file from a whitelisted user's project.
        """

        # Pull config data
        try:
            conf_py_path = self.version.get_conf_py_path()
        except ProjectImportError:
            master_doc = self.create_index(extension="rst")
            self._write_config(master_doc=master_doc)

        project = self.project
        # Open file for appending.
        outfile_path = project.conf_file(self.version.slug)
        try:
            outfile = codecs.open(outfile_path, encoding="utf-8", mode="a")
        except IOError:
            trace = sys.exc_info()[2]
            raise ProjectImportError("Conf file not found"), None, trace
        try:
            outfile.write("\n")
            # TODO this should be handled better in the theme
            conf_py_path = os.path.join(os.path.sep, self.version.get_conf_py_path(), "")
            remote_version = self.version.commit_name

            github_user, github_repo = version_utils.get_github_username_repo(url=self.project.repo)
            github_version_is_editable = self.version.type == "branch"
            display_github = github_user is not None

            bitbucket_user, bitbucket_repo = version_utils.get_bitbucket_username_repo(url=self.project.repo)
            bitbucket_version_is_editable = self.version.type == "branch"
            display_bitbucket = bitbucket_user is not None

            rtd_ctx = {
                "current_version": self.version.verbose_name,
                "project": project,
                "settings": settings,
                "static_path": SPHINX_STATIC_DIR,
                "template_path": SPHINX_TEMPLATE_DIR,
                "conf_py_path": conf_py_path,
                "api_host": getattr(settings, "SLUMBER_API_HOST", "https://readthedocs.org"),
                # GitHub
                "github_user": github_user,
                "github_repo": github_repo,
                "github_version": remote_version,
                "github_version_is_editable": github_version_is_editable,
                "display_github": display_github,
                # BitBucket
                "bitbucket_user": bitbucket_user,
                "bitbucket_repo": bitbucket_repo,
                "bitbucket_version": remote_version,
                "bitbucket_version_is_editable": bitbucket_version_is_editable,
                "display_bitbucket": display_bitbucket,
                "commit": self.project.vcs_repo(self.version.slug).commit,
            }

            # Avoid hitting database and API if using Docker build environment
            if getattr(settings, "DONT_HIT_API", False):
                rtd_ctx["versions"] = project.active_versions()
                rtd_ctx["downloads"] = self.version.get_downloads(pretty=True)
            else:
                rtd_ctx["versions"] = project.api_versions()
                rtd_ctx["downloads"] = api.version(self.version.pk).get()["downloads"]
            rtd_string = template_loader.get_template("doc_builder/conf.py.tmpl").render(rtd_ctx)
            outfile.write(rtd_string)
        finally:
            outfile.close()

        # Print the contents of conf.py in order to make the rendered
        # configfile visible in the build logs
        self.run("cat", os.path.basename(outfile_path), cwd=os.path.dirname(outfile_path))
Beispiel #20
0
    def get_config_params(self):
        """Get configuration parameters to be rendered into the conf file."""
        # TODO this should be handled better in the theme
        conf_py_path = os.path.join(
            os.path.sep,
            self.version.get_conf_py_path(),
            '',
        )
        remote_version = self.version.commit_name

        github_user, github_repo = version_utils.get_github_username_repo(
            url=self.project.repo)
        github_version_is_editable = (self.version.type == 'branch')
        display_github = github_user is not None

        bitbucket_user, bitbucket_repo = version_utils.get_bitbucket_username_repo(  # noqa
            url=self.project.repo)
        bitbucket_version_is_editable = (self.version.type == 'branch')
        display_bitbucket = bitbucket_user is not None

        gitlab_user, gitlab_repo = version_utils.get_gitlab_username_repo(
            url=self.project.repo)
        gitlab_version_is_editable = (self.version.type == 'branch')
        display_gitlab = gitlab_user is not None

        # Avoid hitting database and API if using Docker build environment
        if getattr(settings, 'DONT_HIT_API', False):
            versions = self.project.active_versions()
            downloads = self.version.get_downloads(pretty=True)
        else:
            versions = self.project.api_versions()
            downloads = api.version(self.version.pk).get()['downloads']

        data = {
            'current_version':
            self.version.verbose_name,
            'project':
            self.project,
            'version':
            self.version,
            'settings':
            settings,
            'static_path':
            SPHINX_STATIC_DIR,
            'template_path':
            SPHINX_TEMPLATE_DIR,
            'conf_py_path':
            conf_py_path,
            'api_host':
            getattr(
                settings,
                'PUBLIC_API_URL',
                'https://readthedocs.org',
            ),
            'commit':
            self.project.vcs_repo(self.version.slug).commit,
            'versions':
            versions,
            'downloads':
            downloads,

            # GitHub
            'github_user':
            github_user,
            'github_repo':
            github_repo,
            'github_version':
            remote_version,
            'github_version_is_editable':
            github_version_is_editable,
            'display_github':
            display_github,

            # BitBucket
            'bitbucket_user':
            bitbucket_user,
            'bitbucket_repo':
            bitbucket_repo,
            'bitbucket_version':
            remote_version,
            'bitbucket_version_is_editable':
            bitbucket_version_is_editable,
            'display_bitbucket':
            display_bitbucket,

            # GitLab
            'gitlab_user':
            gitlab_user,
            'gitlab_repo':
            gitlab_repo,
            'gitlab_version':
            remote_version,
            'gitlab_version_is_editable':
            gitlab_version_is_editable,
            'display_gitlab':
            display_gitlab,

            # Features
            'generate_json_artifacts':
            self.project.has_feature(Feature.BUILD_JSON_ARTIFACTS_WITH_HTML),
        }

        finalize_sphinx_context_data.send(
            sender=self.__class__,
            build_env=self.build_env,
            data=data,
        )

        return data
Beispiel #21
0
    def append_conf(self, **kwargs):
        """Modify the given ``conf.py`` file from a whitelisted user's project.
        """

        # Pull config data
        try:
            conf_py_path = self.version.get_conf_py_path()
        except ProjectImportError:
            master_doc = self.create_index(extension='rst')
            self._write_config(master_doc=master_doc)

        project = self.project
        # Open file for appending.
        outfile_path = project.conf_file(self.version.slug)
        try:
            outfile = codecs.open(outfile_path, encoding='utf-8', mode='a')
        except IOError:
            trace = sys.exc_info()[2]
            raise ProjectImportError('Conf file not found'), None, trace
        try:
            outfile.write("\n")
            # TODO this should be handled better in the theme
            conf_py_path = os.path.join(os.path.sep,
                                        self.version.get_conf_py_path(), '')
            remote_version = self.version.commit_name

            github_user, github_repo = version_utils.get_github_username_repo(
                url=self.project.repo)
            github_version_is_editable = (self.version.type == 'branch')
            display_github = github_user is not None

            bitbucket_user, bitbucket_repo = version_utils.get_bitbucket_username_repo(
                url=self.project.repo)
            bitbucket_version_is_editable = (self.version.type == 'branch')
            display_bitbucket = bitbucket_user is not None

            rtd_ctx = {
                'current_version':
                self.version.verbose_name,
                'project':
                project,
                'settings':
                settings,
                'static_path':
                SPHINX_STATIC_DIR,
                'template_path':
                SPHINX_TEMPLATE_DIR,
                'conf_py_path':
                conf_py_path,
                'api_host':
                getattr(settings, 'PUBLIC_API_URL', 'https://readthedocs.org'),
                # GitHub
                'github_user':
                github_user,
                'github_repo':
                github_repo,
                'github_version':
                remote_version,
                'github_version_is_editable':
                github_version_is_editable,
                'display_github':
                display_github,
                # BitBucket
                'bitbucket_user':
                bitbucket_user,
                'bitbucket_repo':
                bitbucket_repo,
                'bitbucket_version':
                remote_version,
                'bitbucket_version_is_editable':
                bitbucket_version_is_editable,
                'display_bitbucket':
                display_bitbucket,
                'commit':
                self.project.vcs_repo(self.version.slug).commit,
            }

            # Avoid hitting database and API if using Docker build environment
            if getattr(settings, 'DONT_HIT_API', False):
                rtd_ctx['versions'] = project.active_versions()
                rtd_ctx['downloads'] = self.version.get_downloads(pretty=True)
            else:
                rtd_ctx['versions'] = project.api_versions()
                rtd_ctx['downloads'] = (api.version(
                    self.version.pk).get()['downloads'])
            rtd_string = template_loader.get_template(
                'doc_builder/conf.py.tmpl').render(rtd_ctx)
            outfile.write(rtd_string)
        finally:
            outfile.close()

        # Print the contents of conf.py in order to make the rendered
        # configfile visible in the build logs
        self.run(
            'cat',
            os.path.basename(outfile_path),
            cwd=os.path.dirname(outfile_path),
        )
Beispiel #22
0
    def append_conf(self, **kwargs):
        """Modify the given ``conf.py`` file from a whitelisted user's project.
        """

        # Pull config data
        try:
            conf_py_path = self.version.get_conf_py_path()
        except ProjectImportError:
            master_doc = self.create_index(extension='rst')
            self._write_config(master_doc=master_doc)

        project = self.project
        # Open file for appending.
        outfile_path = project.conf_file(self.version.slug)
        try:
            outfile = codecs.open(outfile_path, encoding='utf-8', mode='a')
        except IOError:
            trace = sys.exc_info()[2]
            raise ProjectImportError('Conf file not found'), None, trace
        try:
            outfile.write("\n")
            # TODO this should be handled better in the theme
            conf_py_path = os.path.join(os.path.sep,
                                        self.version.get_conf_py_path(),
                                        '')
            remote_version = self.version.commit_name

            github_user, github_repo = version_utils.get_github_username_repo(
                url=self.project.repo)
            github_version_is_editable = (self.version.type == 'branch')
            display_github = github_user is not None

            bitbucket_user, bitbucket_repo = version_utils.get_bitbucket_username_repo(
                url=self.project.repo)
            bitbucket_version_is_editable = (self.version.type == 'branch')
            display_bitbucket = bitbucket_user is not None

            rtd_ctx = {
                'current_version': self.version.verbose_name,
                'project': project,
                'settings': settings,
                'static_path': SPHINX_STATIC_DIR,
                'template_path': SPHINX_TEMPLATE_DIR,
                'conf_py_path': conf_py_path,
                'api_host': getattr(settings, 'PUBLIC_API_URL',
                                    'https://readthedocs.org'),
                # GitHub
                'github_user': github_user,
                'github_repo': github_repo,
                'github_version': remote_version,
                'github_version_is_editable': github_version_is_editable,
                'display_github': display_github,
                # BitBucket
                'bitbucket_user': bitbucket_user,
                'bitbucket_repo': bitbucket_repo,
                'bitbucket_version': remote_version,
                'bitbucket_version_is_editable': bitbucket_version_is_editable,
                'display_bitbucket': display_bitbucket,
                'commit': self.project.vcs_repo(self.version.slug).commit,
            }

            # Avoid hitting database and API if using Docker build environment
            if getattr(settings, 'DONT_HIT_API', False):
                rtd_ctx['versions'] = project.active_versions()
                rtd_ctx['downloads'] = self.version.get_downloads(pretty=True)
            else:
                rtd_ctx['versions'] = project.api_versions()
                rtd_ctx['downloads'] = (api.version(self.version.pk)
                                        .get()['downloads'])
            rtd_string = template_loader.get_template('doc_builder/conf.py.tmpl').render(rtd_ctx)
            outfile.write(rtd_string)
        finally:
            outfile.close()

        # Print the contents of conf.py in order to make the rendered
        # configfile visible in the build logs
        self.run(
            'cat', os.path.basename(outfile_path),
            cwd=os.path.dirname(outfile_path),
        )