Source code for issues.main

"""Module containing main functions for issues management."""

import logging
from datetime import datetime

from django.conf import settings

from core.models import Contributor
from issues.providers import BitbucketProvider, GithubProvider, GitlabProvider
from updaters.main import UpdateProvider

ISSUE_TRACKER_PROVIDERS_REGISTRY = {
    "github": GithubProvider,
    "gitlab": GitlabProvider,
    "bitbucket": BitbucketProvider,
}

logger = logging.getLogger(__name__)


[docs] class IssueProvider: """Main provider class that delegates to the configured provider. :var IssueProvider.name: name of the provider to use :type IssueProvider.name: str :var IssueProvider.user: Django user instance :type IssueProvider.user: class:`django.contrib.auth.models.User` :var IssueProvider._provider_instance: instance of the issue provider :type IssueProvider._provider_instance: :class:`BaseIssueProvider` """ name = None user = None _provider_instance = None def __init__(self, user, **kwargs): """Initialize issue provider with configured provider. :param user: Django user instance :type user: class:`django.contrib.auth.models.User` """ self.name = settings.ISSUE_TRACKER_PROVIDER self.user = user self._provider_instance = self._get_provider_instance(**kwargs) def _get_provider_instance(self, **kwargs): """Get the provider instance from registry, fallback to GitHub. :var provider_class: provider class from registry :type provider_class: class :return: instance of the issue provider :rtype: :class:`BaseIssueProvider` """ provider_class = ISSUE_TRACKER_PROVIDERS_REGISTRY.get(self.name) return provider_class( self.user, issue_tracker_api_token=kwargs.get("issue_tracker_api_token") ) def __getattr__(self, name): """Delegate all method calls to the provider instance. :param name: method name to delegate :type name: str :return: method from provider instance """ return getattr(self._provider_instance, name)
# # PREPARE ISSUE def _contributor_link(handle): """Create link to contributor defined by provided Discord `handle`. :param handle: Discord handle/username :type handle: str :param contributor: contributor's model instance :type contributor: :class:`core.models.Contributor` :return: str """ try: contributor = Contributor.objects.from_handle(handle) except ValueError: contributor = None if contributor is None: return handle return f"[{handle}]({contributor.get_absolute_url()})" def _prepare_issue_body_from_contribution(contribution, profile): """Prepare the body content for a GitHub issue from provided arguments. :param contribution: contribution instance to extract data from :type contribution: :class:`core.models.Contribution` :param profile: superuser's profile instance :type profile: :class:`core.models.Profile` :var issue_body: default issue body template :type issue_body: str :var message: parsed message data from contribution URL :type message: dict :var contributor: link to contributor's page on Rewards Suite website :type contributor: str :return: str """ issue_body = "** Please provide the necessary information **" if not contribution.url: return issue_body updater = UpdateProvider(contribution.platform.name) message = updater.message_from_url(contribution.url) if message.get("success"): timestamp = datetime.strptime( message.get("timestamp"), "%Y-%m-%dT%H:%M:%S.%f%z" ).strftime("%d %b %H:%M") contributor = _contributor_link(message.get("author")) issue_body = ( f"By {contributor} on {timestamp} in [{contribution.platform.name.title()}]" f"({contribution.url}): // su: {str(profile)}\n" ) for line in message.get("contribution").split("\n"): issue_body += f"> {line}\n" return issue_body def _prepare_issue_labels_from_contribution(contribution): """Prepare labels for a GitHub issue based on contribution reward type. :param contribution: contribution instance to extract data from :type contribution: :class:`core.models.Contribution` :var labels: collection of labels to apply to the issue :type labels: list :return: list """ labels = [] if "Bug" in contribution.reward.type.name: labels.append("bug") elif "Feature" in contribution.reward.type.name: labels.append("feature") elif "Task" in contribution.reward.type.name: labels.append("task") elif "Twitter" in contribution.reward.type.name: labels.append("task") elif "Research" in contribution.reward.type.name: labels.append("research") return labels def _prepare_issue_priority_from_contribution(contribution): """Prepare priority level for a GitHub issue based on contribution reward type. :param contribution: contribution instance to extract data from :type contribution: :class:`core.models.Contribution` :return: str """ if "Bug" in contribution.reward.type.name: return "high priority" return "medium priority" def _prepare_issue_title_from_contribution(contribution): """Prepare title for a GitHub issue from contribution data. :param contribution: contribution instance to extract data from :type contribution: :class:`core.models.Contribution` :var issue_title: formatted issue title with reward type and level :type issue_title: str :return: str """ issue_title = f"[{contribution.reward.type.label}{contribution.reward.level}] " if contribution.comment: issue_title += contribution.comment return issue_title
[docs] def issue_data_for_contribution(contribution, profile): """Prepare complete issue data dictionary from a contribution. :param contribution: contribution instance to extract data from :type contribution: :class:`core.models.Contribution` :param profile: superuser's profile instance :type profile: :class:`core.models.Profile` :return: dict """ return { "issue_title": _prepare_issue_title_from_contribution(contribution), "issue_body": _prepare_issue_body_from_contribution(contribution, profile), "labels": _prepare_issue_labels_from_contribution(contribution), "priority": _prepare_issue_priority_from_contribution(contribution), }