<commit_before>from __future__ import absolute_import

import os
from sc2reader import utils
from sc2reader import readers
from sc2reader import data
from sc2reader import exceptions
from sc2reader.replay import Replay
from collections import defaultdict

class SC2Reader(object):

    default_options = dict(
        # General use
        verbose=False,
        debug=False,

        # Related to the SC2Reader class only
        register_defaults=True,

        # Related to creating new replay objects
        autoplay=True,
        load_events=True,

        # Related to passing paths into load_replay(s)
        directory='',

        # Related to passing a directory to load_replays
        depth=-1,
        exclude=[],
        followlinks=False
    )

    def __init__(self, **options):
        self.reset()

        if options.get('register_defaults',None):
            self.register_defaults()

        self.configure(**options)


    def load_replays(self, replay_collection, options=None, **new_options):
        options = options or utils.merged_dict(self.options, new_options)

        # Get the directory and hide it from nested calls
        directory = options.get('directory','')
        if 'directory' in options: del options['directory']

        if isinstance(replay_collection, basestring):
            full_path = os.path.join(directory, replay_collection)
            for replay_path in utils.get_replay_files(full_path, **options):
                with open(replay_path) as replay_file:
                    yield self.load_replay(replay_file, options=options)

        else:
            for replay_file in replay_collection:
                if isinstance(replay_file, basestring):
                    full_path = os.path.join(directory, replay_file)
                    if os.path.isdir(full_path):
                        for replay in self.load_replays(full_path, options=options):
                            yield replay
                    else:
                        yield self.load_replay(full_path, options=options)

                else:
                    yield self.load_replay(replay_file, options=options)

    def load_replay(self, replay_file, options=None, **new_options):
        options = options or utils.merged_dict(self.options, new_options)
        load_events = options.get('load_events',True)
        autoplay = options.get('autoplay',True)


        if isinstance(replay_file, basestring):
            location = os.path.join(options.get('directory',''), replay_file)
            with open(location, 'rb') as replay_file:
                return self.load_replay(replay_file, options=options)

        if options['verbose']:
            print replay_file.name

        replay = Replay(replay_file, **options)

        for data_file in ('replay.initData',
                          'replay.details',
                          'replay.attributes.events',
                          'replay.message.events',):
            reader = self.get_reader(data_file, replay)
            replay.read_data(data_file, reader)

        replay.load_details()
        replay.load_players()

        if load_events:
            for data_file in ('replay.game.events',):
                reader = self.get_reader(data_file, replay)
                replay.read_data(data_file, reader)

            replay.load_events(self.get_datapack(replay))

            if autoplay:
                replay.listeners = self.get_listeners(replay)
                replay.start()

        return replay


    def get_reader(self, data_file, replay):
        for callback, reader in self.registered_readers[data_file]:
            if callback(replay):
                return reader

    def get_datapack(self, replay):
        for callback, datapack in self.registered_datapacks:
            if callback(replay):
                return datapack
        return None

    def get_listeners(self, replay):
        listeners = defaultdict(list)
        for event_class in self.registered_listeners.keys():
            for callback, listener in self.registered_listeners[event_class]:
                if callback(replay):
                    listeners[event_class].append(listener)
        return listeners


    def register_listener(self, event_class, listener, callback=lambda r: True):
        self.registered_listeners[event_class].append((callback, listener))

    def register_reader(self, data_file, reader, callback=lambda r: True):
        self.registered_readers[data_file].insert(0,(callback, reader))

    def register_datapack(self, datapack, callback=lambda r: True):
        self.registered_datapacks.insert(0,(callback, datapack))


    def register_defaults(self):
        self.register_default_readers()
        self.register_default_datapacks()
        self.register_default_listeners()

    def register_default_readers(self):
        self.register_reader('replay.details', readers.DetailsReader_Base())
        self.register_reader('replay.initData', readers.InitDataReader_Base())
        self.register_reader('replay.message.events', readers.MessageEventsReader_Base())
        self.register_reader('replay.attributes.events', readers.AttributesEventsReader_Base(), lambda r: r.build <  17326)
        self.register_reader('replay.attributes.events', readers.AttributesEventsReader_17326(), lambda r: r.build >= 17326)
        self.register_reader('replay.game.events', readers.GameEventsReader_Base(), lambda r: r.build <  16561)
        self.register_reader('replay.game.events', readers.GameEventsReader_16561(), lambda r: 16561 <= r.build < 18574)
        self.register_reader('replay.game.events', readers.GameEventsReader_18574(), lambda r: 18574 <= r.build < 19595)
        self.register_reader('replay.game.events', readers.GameEventsReader_19595(), lambda r: 19595 <= r.build)

    def register_default_datapacks(self):
        self.register_datapack(data.Data_16561, lambda r: 16561 <= r.build < 17326)
        self.register_datapack(data.Data_17326, lambda r: 17326 <= r.build < 18317)
        self.register_datapack(data.Data_18317, lambda r: 18317 <= r.build < 19595)
        self.register_datapack(data.Data_19595, lambda r: 19595 <= r.build)

    def register_default_listeners(self):
        #self.register_listener(Event, PrintEventListener())
        pass

    def configure(self, **new_options):
        self.options.update(new_options)

    def reset(self):
        self.options = utils.AttributeDict(self.default_options)
        self.registered_readers = defaultdict(list)
        self.registered_datapacks = list()
        self.registered_listeners = defaultdict(list)

__defaultSC2Reader = SC2Reader()

register_datapack = __defaultSC2Reader.register_datapack
register_listener = __defaultSC2Reader.register_listener
register_reader = __defaultSC2Reader.register_reader

get_listeners = __defaultSC2Reader.get_listeners
get_datapack = __defaultSC2Reader.get_datapack
get_reader = __defaultSC2Reader.get_reader

load_replay = __defaultSC2Reader.load_replay
load_replays = __defaultSC2Reader.load_replays

configure = __defaultSC2Reader.configure
reset = __defaultSC2Reader.reset<commit_msg>There are no default listeners.<commit_after>from __future__ import absolute_import

import os
from sc2reader import utils
from sc2reader import readers
from sc2reader import data
from sc2reader import exceptions
from sc2reader.replay import Replay
from collections import defaultdict

class SC2Reader(object):

    default_options = dict(
        # General use
        verbose=False,
        debug=False,

        # Related to the SC2Reader class only
        register_defaults=True,

        # Related to creating new replay objects
        autoplay=True,
        load_events=True,

        # Related to passing paths into load_replay(s)
        directory='',

        # Related to passing a directory to load_replays
        depth=-1,
        exclude=[],
        followlinks=False
    )

    def __init__(self, **options):
        self.reset()

        if options.get('register_defaults',None):
            self.register_defaults()

        self.configure(**options)


    def load_replays(self, replay_collection, options=None, **new_options):
        options = options or utils.merged_dict(self.options, new_options)

        # Get the directory and hide it from nested calls
        directory = options.get('directory','')
        if 'directory' in options: del options['directory']

        if isinstance(replay_collection, basestring):
            full_path = os.path.join(directory, replay_collection)
            for replay_path in utils.get_replay_files(full_path, **options):
                with open(replay_path) as replay_file:
                    yield self.load_replay(replay_file, options=options)

        else:
            for replay_file in replay_collection:
                if isinstance(replay_file, basestring):
                    full_path = os.path.join(directory, replay_file)
                    if os.path.isdir(full_path):
                        for replay in self.load_replays(full_path, options=options):
                            yield replay
                    else:
                        yield self.load_replay(full_path, options=options)

                else:
                    yield self.load_replay(replay_file, options=options)

    def load_replay(self, replay_file, options=None, **new_options):
        options = options or utils.merged_dict(self.options, new_options)
        load_events = options.get('load_events',True)
        autoplay = options.get('autoplay',True)


        if isinstance(replay_file, basestring):
            location = os.path.join(options.get('directory',''), replay_file)
            with open(location, 'rb') as replay_file:
                return self.load_replay(replay_file, options=options)

        if options['verbose']:
            print replay_file.name

        replay = Replay(replay_file, **options)

        for data_file in ('replay.initData',
                          'replay.details',
                          'replay.attributes.events',
                          'replay.message.events',):
            reader = self.get_reader(data_file, replay)
            replay.read_data(data_file, reader)

        replay.load_details()
        replay.load_players()

        if load_events:
            for data_file in ('replay.game.events',):
                reader = self.get_reader(data_file, replay)
                replay.read_data(data_file, reader)

            replay.load_events(self.get_datapack(replay))

            if autoplay:
                replay.listeners = self.get_listeners(replay)
                replay.start()

        return replay


    def get_reader(self, data_file, replay):
        for callback, reader in self.registered_readers[data_file]:
            if callback(replay):
                return reader

    def get_datapack(self, replay):
        for callback, datapack in self.registered_datapacks:
            if callback(replay):
                return datapack
        return None

    def get_listeners(self, replay):
        listeners = defaultdict(list)
        for event_class in self.registered_listeners.keys():
            for callback, listener in self.registered_listeners[event_class]:
                if callback(replay):
                    listeners[event_class].append(listener)
        return listeners


    def register_listener(self, event_class, listener, callback=lambda r: True):
        self.registered_listeners[event_class].append((callback, listener))

    def register_reader(self, data_file, reader, callback=lambda r: True):
        self.registered_readers[data_file].insert(0,(callback, reader))

    def register_datapack(self, datapack, callback=lambda r: True):
        self.registered_datapacks.insert(0,(callback, datapack))


    def register_defaults(self):
        self.register_default_readers()
        self.register_default_datapacks()

    def register_default_readers(self):
        self.register_reader('replay.details', readers.DetailsReader_Base())
        self.register_reader('replay.initData', readers.InitDataReader_Base())
        self.register_reader('replay.message.events', readers.MessageEventsReader_Base())
        self.register_reader('replay.attributes.events', readers.AttributesEventsReader_Base(), lambda r: r.build <  17326)
        self.register_reader('replay.attributes.events', readers.AttributesEventsReader_17326(), lambda r: r.build >= 17326)
        self.register_reader('replay.game.events', readers.GameEventsReader_Base(), lambda r: r.build <  16561)
        self.register_reader('replay.game.events', readers.GameEventsReader_16561(), lambda r: 16561 <= r.build < 18574)
        self.register_reader('replay.game.events', readers.GameEventsReader_18574(), lambda r: 18574 <= r.build < 19595)
        self.register_reader('replay.game.events', readers.GameEventsReader_19595(), lambda r: 19595 <= r.build)

    def register_default_datapacks(self):
        self.register_datapack(data.Data_16561, lambda r: 16561 <= r.build < 17326)
        self.register_datapack(data.Data_17326, lambda r: 17326 <= r.build < 18317)
        self.register_datapack(data.Data_18317, lambda r: 18317 <= r.build < 19595)
        self.register_datapack(data.Data_19595, lambda r: 19595 <= r.build)


    def configure(self, **new_options):
        self.options.update(new_options)

    def reset(self):
        self.options = utils.AttributeDict(self.default_options)
        self.registered_readers = defaultdict(list)
        self.registered_datapacks = list()
        self.registered_listeners = defaultdict(list)

__defaultSC2Reader = SC2Reader()

register_datapack = __defaultSC2Reader.register_datapack
register_listener = __defaultSC2Reader.register_listener
register_reader = __defaultSC2Reader.register_reader

get_listeners = __defaultSC2Reader.get_listeners
get_datapack = __defaultSC2Reader.get_datapack
get_reader = __defaultSC2Reader.get_reader

load_replay = __defaultSC2Reader.load_replay
load_replays = __defaultSC2Reader.load_replays

configure = __defaultSC2Reader.configure
reset = __defaultSC2Reader.reset
{'fraction_non_alphanumeric': 0.08962397512015832, 'fraction_numerical': 0.019366694939214023, 'mean_word_length': 2.8199244060475164, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 5, 'https://': 0, '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': '5862028', 'n_tokens_mistral': 4247, 'n_tokens_neox': 3896, 'n_words': 813}