<commit_before>"""mergebot_poller is a utility which polls an SCM and follows commands.

mergebot_poller defines a MergebotPoller class from which other classes can
inherit and a create_poller method which allows creation of SCM pollers.
"""


import json
import time
from multiprocessing import Pipe, Queue

import requests

from mergebot_backend import db_publisher, github_helper, merge
from mergebot_backend.log_helper import get_logger

BOT_NAME = 'asfgit'
MERGEBOT_PROJ_URL = 'http://mergebot-vm.apache.org/{name}'


def create_poller(config, comm_pipe):
    """create_poller creates a poller of the type specified in the config.

    Args:
        config: A dictionary containing repository configuration.
        comm_pipe: multiprocessing Pipe with which to communicate with parent.
    Returns:
        MergebotPoller of type specified in configuration
    Raises:
        AttributeError: if passed an unsupported SCM type.
    """
    if config.scm_type == 'github':
        return GithubPoller(config, comm_pipe)
    raise AttributeError('Unsupported SCM Type: {}.'.format(config.scm_type))


class MergebotPoller(object):
    """MergebotPoller is a base class for polling SCMs.
    """

    def __init__(self, config, comm_pipe):
        self.config = config
        self.comm_pipe = comm_pipe
        self.l = get_logger(name=self.config.name, redirect_to_file=True)
        self.publisher = db_publisher.DBPublisher(name=self.config.name)
        # Instantiate the two variables used for tracking work.
        self.work_queue = Queue()
        self.known_work = {}
        # Pipe used to communicate with its merger.
        self.merger_pipe, child_pipe = Pipe()
        self.merger = merge.create_merger(config, self.work_queue, child_pipe)
        self.authorized_users = self.get_authorized_users()

    def get_authorized_users(self):
        """Fetches the users allowed to command this poller.

        Returns:
            Map of GitHub username to ASF ID of committers for this project.
        """
        groups_json = requests.get(
            'https://people.apache.org/public/public_ldap_groups.json')
        groups_json.raise_for_status()
        committers_json = requests.get(
            'https://gitbox.apache.org/setup/ghmap.json')
        committers_json.raise_for_status()
        groups = json.loads(groups_json.content)
        committers = json.loads(committers_json.content)['map']
        authorized_usernames = groups['groups'][self.config.proj_name]['roster']
        # Infra should have access in case they need to help fix things.
        authorized_usernames.extend(
            groups['groups']['infra']['roster'])

        # Build map of Github ID : ASF ID
        authorized_users = {}
        for user in authorized_usernames:<commit_msg>Fix crash in get_authorized_users (#25)<commit_after>"""mergebot_poller is a utility which polls an SCM and follows commands.

mergebot_poller defines a MergebotPoller class from which other classes can
inherit and a create_poller method which allows creation of SCM pollers.
"""


import json
import time
from multiprocessing import Pipe, Queue

import requests

from mergebot_backend import db_publisher, github_helper, merge
from mergebot_backend.log_helper import get_logger

BOT_NAME = 'asfgit'
MERGEBOT_PROJ_URL = 'http://mergebot-vm.apache.org/{name}'


def create_poller(config, comm_pipe):
    """create_poller creates a poller of the type specified in the config.

    Args:
        config: A dictionary containing repository configuration.
        comm_pipe: multiprocessing Pipe with which to communicate with parent.
    Returns:
        MergebotPoller of type specified in configuration
    Raises:
        AttributeError: if passed an unsupported SCM type.
    """
    if config.scm_type == 'github':
        return GithubPoller(config, comm_pipe)
    raise AttributeError('Unsupported SCM Type: {}.'.format(config.scm_type))


class MergebotPoller(object):
    """MergebotPoller is a base class for polling SCMs.
    """

    def __init__(self, config, comm_pipe):
        self.config = config
        self.comm_pipe = comm_pipe
        self.l = get_logger(name=self.config.name, redirect_to_file=True)
        self.publisher = db_publisher.DBPublisher(name=self.config.name)
        # Instantiate the two variables used for tracking work.
        self.work_queue = Queue()
        self.known_work = {}
        # Pipe used to communicate with its merger.
        self.merger_pipe, child_pipe = Pipe()
        self.merger = merge.create_merger(config, self.work_queue, child_pipe)
        self.authorized_users = self.get_authorized_users()

    def get_authorized_users(self):
        """Fetches the users allowed to command this poller.

        Returns:
            Map of GitHub username to ASF ID of committers for this project.
        """
        try:
            groups_json = requests.get(
                'https://people.apache.org/public/public_ldap_groups.json')
            groups_json.raise_for_status()
            committers_json = requests.get(
                'https://gitbox.apache.org/setup/ghmap.json')
            committers_json.raise_for_status()
        except Exception as e:
            self.l.error("Failed to retrieve authorized users: {err}; using old"
                         " authorized user list.".format(err=e))
            return self.authorized_users
        groups = json.loads(groups_json.content)
        committers = json.loads(committers_json.content)['map']
        authorized_usernames = groups['groups'][self.config.proj_name]['roster']
        # Infra should have access in case they need to help fix things.
        authorized_usernames.extend(
            groups['groups']['infra']['roster'])

        # Build map of Github ID : ASF ID
        authorized_users = {}
        for user in authorized_usernames:
{'fraction_non_alphanumeric': 0.08343286128646989, 'fraction_numerical': 0.0003412386964681795, 'mean_word_length': 2.998635743519782, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '955730', 'n_tokens_mistral': 1707, 'n_tokens_neox': 1650, 'n_words': 473}