<commit_before>import json
from twisted.words.protocols import irc
from twisted.internet import protocol, task, endpoints
from twisted.spread import pb
import sys
from collections import deque
from twisted.python import log

class RemoteProtocol(pb.Referenceable):
    def __init__(self, protocol):
        self.protocol = protocol

    def remote_msg(self, user, message):
        self.protocol.msg(user, message)

    def remote_join(self, channel, key):
        self.protocol.join(channel, key)

    def remote_leave(self, channel, reason):
        self.protocol.leave(channel, reason)

class NanoBotProtocol(object, irc.IRCClient):
    ping_delay = 180

    def __init__(self, reactor, server, bot):
        self._reactor = reactor
        self.server = server
        self.bot = bot

    @property
    def channels(self):
        return self.server.channels
    
    def connectionMade(self):
        irc.IRCClient.connectionMade(self)
        log.msg("Connected to %s" % self.server.hostname)
        
    def signedOn(self):
        irc.IRCClient.signedOn(self)
        for channel in self.channels:
            if 'key' in channel:
                self.join(channel['name'].encode(self.server.encoding),
                          channel['key'].encode(self.server.encoding))
            else:
                self.join(channel['name'].encode(self.server.encoding))

    def connectionLost(self, reason):
        log.msg("Connection to %s lost" % self.server.hostname)
        irc.IRCClient.connectionLost(self, reason)

    def privmsg(self, user, channel, message):
        irc.IRCClient.privmsg(self, user, channel, message)
        ref = RemoteProtocol(self)
        fmt = 'PRIVMSG %s :' % (user,)
        max_len = self._safeMaximumLineLength(fmt) - len(fmt) - 50
        if channel == self.nickname:
            self.bot.api.callRemote("handlePrivateMessage", ref, user, channel,
                                    message, self.server.encoding, max_len)
        else:
            self.bot.api.callRemote("handlePublicMessage", ref, user, channel,
                                    message, self.server.encoding, max_len)

class ServerConnection(protocol.ReconnectingClientFactory):
    protocol = NanoBotProtocol
    def __init__(self, reactor, network_config, bot):
        self._reactor = reactor
        self.bot = bot
        self.network_config = network_config

    def buildProtocol(self, addr):
        protocol = self.protocol(self._reactor, server=self, bot=self.bot)
        if self.bot.nickname:
            protocol.nickname = self.bot.nickname.encode(self.encoding)
        if self.bot.realname:
            protocol.realname = self.bot.realname.encode(self.encoding)
        return protocol

    @property
    def channels(self):
        return self.network_config.get('channels', dict())

    @property
    def name(self):
        return self.network_config['name']

    @property
    def hostname(self):
        return self.network_config['hostname']

    @property
    def port(self):
        return int(self.network_config.get('port', 6667))

    @property
    def is_ssl(self):
        return bool(self.network_config.get('ssl', False))

    @property
    def encoding(self):
        return self.network_config.get('encoding', 'utf-8')

    def connect(self):
        if self.is_ssl:
            self._reactor.connectSSL(self.hostname.encode(self.encoding),
                                     self.port, self)
        else:
            self._reactor.connectTCP(self.hostname.encode(self.encoding),
                                     self.port, self)


class ApiProxy(pb.Root):
    def __init__(self):
        self.app = None
        self.queue = deque()
        self.running = False

    def callRemote(self, *args, **kwargs):
        self.queue.append((args, kwargs))
        self.run()

    def run(self):
        if not self.running:
            log.msg("Scheduling")
            self.running = True
            task.coiterate(iter(self))


    def __iter__(self):
        while True:
            if not self.app or not self.queue:
                log.msg("Pausing execution")
                self.running = False
                break
            else:
                args, kwargs = self.queue.popleft()
                d = self.app.callRemote(*args, **kwargs)
                d.addErrback(log.err)
                yield d


    def remote_register(self, app):
        log.msg("Got registration request for %s" % str(app))
        self.app = app
        self.run()

class ProcessProtocol(protocol.ProcessProtocol):
    def __init__(self, api):
        self.api = api
        self.logs = []

    def errReceived(self, data):
        self.logs.append(data)

    def processExited(self, status):
        log.msg("Process exited with status code %s" % status)
        log.msg("".join(self.logs))
        return self.bot.reconnect_app()


class NanoBot(object):
    app = None
    exiting = False

    def __init__(self, reactor, config_filename):
        self._network = None
        self._proc = None
        self._reactor = reactor
        self._config_filename = config_filename
        self.connections = dict()
        with open(config_filename) as f:
            self.config = json.load(f)
        log.startLogging(open(self.core_config["log_file"], "a"))
        self.api = ApiProxy()
        self.endpoint = endpoints.serverFromString(self._reactor,
                                                   str(self.core_config["masterEndpoint"]))


    def run(self):
        factory = pb.PBServerFactory(self.api)<commit_msg>Fix bug where lack of reference causes bot to be unable to restart app<commit_after>import json
from twisted.words.protocols import irc
from twisted.internet import protocol, task, endpoints
from twisted.spread import pb
import sys
from collections import deque
from twisted.python import log

class RemoteProtocol(pb.Referenceable):
    def __init__(self, protocol):
        self.protocol = protocol

    def remote_msg(self, user, message):
        self.protocol.msg(user, message)

    def remote_join(self, channel, key):
        self.protocol.join(channel, key)

    def remote_leave(self, channel, reason):
        self.protocol.leave(channel, reason)

class NanoBotProtocol(object, irc.IRCClient):
    ping_delay = 180

    def __init__(self, reactor, server, bot):
        self._reactor = reactor
        self.server = server
        self.bot = bot

    @property
    def channels(self):
        return self.server.channels
    
    def connectionMade(self):
        irc.IRCClient.connectionMade(self)
        log.msg("Connected to %s" % self.server.hostname)
        
    def signedOn(self):
        irc.IRCClient.signedOn(self)
        for channel in self.channels:
            if 'key' in channel:
                self.join(channel['name'].encode(self.server.encoding),
                          channel['key'].encode(self.server.encoding))
            else:
                self.join(channel['name'].encode(self.server.encoding))

    def connectionLost(self, reason):
        log.msg("Connection to %s lost" % self.server.hostname)
        irc.IRCClient.connectionLost(self, reason)

    def privmsg(self, user, channel, message):
        irc.IRCClient.privmsg(self, user, channel, message)
        ref = RemoteProtocol(self)
        fmt = 'PRIVMSG %s :' % (user,)
        max_len = self._safeMaximumLineLength(fmt) - len(fmt) - 50
        if channel == self.nickname:
            self.bot.api.callRemote("handlePrivateMessage", ref, user, channel,
                                    message, self.server.encoding, max_len)
        else:
            self.bot.api.callRemote("handlePublicMessage", ref, user, channel,
                                    message, self.server.encoding, max_len)

class ServerConnection(protocol.ReconnectingClientFactory):
    protocol = NanoBotProtocol
    def __init__(self, reactor, network_config, bot):
        self._reactor = reactor
        self.bot = bot
        self.network_config = network_config

    def buildProtocol(self, addr):
        protocol = self.protocol(self._reactor, server=self, bot=self.bot)
        if self.bot.nickname:
            protocol.nickname = self.bot.nickname.encode(self.encoding)
        if self.bot.realname:
            protocol.realname = self.bot.realname.encode(self.encoding)
        return protocol

    @property
    def channels(self):
        return self.network_config.get('channels', dict())

    @property
    def name(self):
        return self.network_config['name']

    @property
    def hostname(self):
        return self.network_config['hostname']

    @property
    def port(self):
        return int(self.network_config.get('port', 6667))

    @property
    def is_ssl(self):
        return bool(self.network_config.get('ssl', False))

    @property
    def encoding(self):
        return self.network_config.get('encoding', 'utf-8')

    def connect(self):
        if self.is_ssl:
            self._reactor.connectSSL(self.hostname.encode(self.encoding),
                                     self.port, self)
        else:
            self._reactor.connectTCP(self.hostname.encode(self.encoding),
                                     self.port, self)


class ApiProxy(pb.Root):
    def __init__(self):
        self.app = None
        self.queue = deque()
        self.running = False

    def callRemote(self, *args, **kwargs):
        self.queue.append((args, kwargs))
        self.run()

    def run(self):
        if not self.running:
            log.msg("Scheduling")
            self.running = True
            task.coiterate(iter(self))


    def __iter__(self):
        while True:
            if not self.app or not self.queue:
                log.msg("Pausing execution")
                self.running = False
                break
            else:
                args, kwargs = self.queue.popleft()
                d = self.app.callRemote(*args, **kwargs)
                d.addErrback(log.err)
                yield d


    def remote_register(self, app):
        log.msg("Got registration request for %s" % str(app))
        self.app = app
        self.run()

class ProcessProtocol(protocol.ProcessProtocol):
    def __init__(self, api, bot):
        self.api = api
        self.bot = bot
        self.logs = []

    def errReceived(self, data):
        self.logs.append(data)

    def processExited(self, status):
        log.msg("Process exited with status code %s" % status)
        log.msg("".join(self.logs))
        return self.bot.reconnect_app()


class NanoBot(object):
    app = None
    exiting = False

    def __init__(self, reactor, config_filename):
        self._network = None
        self._proc = None
        self._reactor = reactor
        self._config_filename = config_filename
        self.connections = dict()
        with open(config_filename) as f:
            self.config = json.load(f)
        log.startLogging(open(self.core_config["log_file"], "a"))
        self.api = ApiProxy()
        self.endpoint = endpoints.serverFromString(self._reactor,
                                                   str(self.core_config["masterEndpoint"]))


    def run(self):
        factory = pb.PBServerFactory(self.api)
{'fraction_non_alphanumeric': 0.10608354858822482, 'fraction_numerical': 0.0017814197915738844, 'mean_word_length': 2.1406993006993007, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1614162', 'n_tokens_mistral': 3225, 'n_tokens_neox': 3089, 'n_words': 701}