<commit_before># AGAGD Models Imports
import agagd_core.models as agagd_models

# DJango Imports
import django_tables2 as tables

# AGAGD Column Imports
from agagd_core.tables.core import ChapterColumn
from django.core.exceptions import ObjectDoesNotExist
from django.urls import reverse
from django.utils.safestring import mark_safe

# Base Bootstrap Column Attributes
default_bootstrap_column_attrs = {
    "th": {"class": "d-none d-lg-table-cell d-xl-table-cell"},
    "td": {"class": "d-none d-lg-table-cell d-xl-table-cell"},
}

# Base Bootstrap Column Header Attributes
default_bootstrap_header_column_attrs = {
    "class": "table",
    "thead": {"class": "thead-dark"},
    "th": {"scope": "col"},
}

# Column for the Winner of the Game
class LinkFullMembersNameColumn(tables.Column):
    def __init__(
        self,
        color="W",
        viewname=None,
        urlconf=None,
        args=None,
        kwargs=None,
        current_app=None,
        attrs=None,
        **extra,
    ):
        super().__init__(
            attrs=attrs,
            linkify=dict(
                viewname=viewname,
                urlconf=urlconf,
                args=args,
                kwargs=kwargs,
                current_app=current_app,
            ),
            **extra,
        )
        self.color = color

    def render(self, value, record):
        if record["result"] == self.color:
            self.attrs["td"] = {"class": "winner"}
        elif record["result"] != self.color:
            self.attrs["td"] = {"class": "runner-up"}

        try:
            member_name_and_id = agagd_models.Member.objects.get(member_id=value)
            value = f"{member_name_and_id.full_name} ({value})"
        except ObjectDoesNotExist:
            value = None

        return value

# Basic table which is use as as base for many of the game layouts.
class GamesTable(tables.Table):
    game_date = tables.Column(
        verbose_name="Date", attrs=default_bootstrap_column_attrs, orderable=False
    )
    handicap = tables.Column(attrs=default_bootstrap_column_attrs, orderable=False)
    pin_player_1 = LinkFullMembersNameColumn(
        color="W",
        viewname="players_profile",
        verbose_name="White",
        kwargs={"player_id": tables.A("pin_player_1")},
        orderable=False,
    )
    pin_player_2 = LinkFullMembersNameColumn(
        color="B",
        viewname="players_profile",
        verbose_name="Black",
        kwargs={"player_id": tables.A("pin_player_2")},
        orderable=False,
    )
    tournament_code = tables.LinkColumn(
        verbose_name="Tournament",
        viewname="tournament_detail",
        kwargs={"code": tables.A("tournament_code")},
        orderable=False,
    )

    class Meta:
        model = agagd_models.Game
        fields = (
            "game_date",
            "handicap",
            "pin_player_1",
            "pin_player_2",
            "tournament_code",
        )
        sequence = fields
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"

class PlayersInformationTable(tables.Table):
    full_name = tables.Column()
    member_id = tables.Column()
    status = tables.Column()
    rating = tables.Column()
    renewal_due = tables.Column()

    class Meta:
        template_name = "beta.player_profile_information.html"

class PlayersOpponentTable(tables.Table):
    opponent = tables.Column(
        orderable=False,
        linkify={
            "viewname": "players_profile",
            "args": [tables.A("opponent.member_id")],
        },
    )
    total = tables.Column(orderable=False, verbose_name="Games")
    won = tables.Column(orderable=False, verbose_name="Won", default=0)
    lost = tables.Column(orderable=False, verbose_name="Lost")
    ratio = tables.Column(
        verbose_name="Rate", default=0, empty_values=(-1,), orderable=False
    )

    def render_ratio(self, record):
        ratio = record["won"] / record["total"]

        return f"{ratio:.2f}"

    class Meta:
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"

class TournamentsTable(tables.Table):
    tournament_date = tables.Column(
        verbose_name="Date", attrs=default_bootstrap_column_attrs, orderable=False
    )
    description = tables.LinkColumn(
        "tournament_detail",
        verbose_name="Name",
        kwargs={"code": tables.A("tournament_code")},
        orderable=False,
    )
    total_players = tables.Column(
        verbose_name="# Players", attrs=default_bootstrap_column_attrs, orderable=False
    )
    elab_date = tables.Column(
        verbose_name="Rated", attrs=default_bootstrap_column_attrs, orderable=False
    )

    class Meta:
        model = agagd_models.Tournament
        fields = ("tournament_date", "description", "total_players", "elab_date")
        sequence = fields
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"

class PlayersTournamentTable(tables.Table):
    tournament = tables.LinkColumn(
        "tournament_detail", kwargs={"code": tables.A("tournament.pk")}, orderable=False
    )
    date = tables.Column(orderable=False, default="Unknown")
    won = tables.Column(orderable=False, verbose_name="Won", default=0)
    lost = tables.Column(orderable=False, verbose_name="Lost", default=0)

    class Meta:
        fields = ("date", "tournament", "won", "lost")
        sequence = fields
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"

class SearchResultsTable(tables.Table):
    member_id = tables.LinkColumn(
        "member_detail", kwargs={"member_id": tables.A("member_id")}
    )
    chapter_id = ChapterColumn(verbose_name="Chapter")
    players__rating = tables.Column(verbose_name="Rating")
    country = tables.LinkColumn(
        "country_detail", kwargs={"country_name": tables.A("country")}
    )
    full_name = tables.LinkColumn(
        "member_detail", kwargs={"member_id": tables.A("member_id")}
    )

    class Meta:
        model = agagd_models.Member
        fields = ("full_name", "state", "players__rating", "renewal_due", "country")
        sequence = (
            "full_name",
            "players__rating",
            "chapter_id",
            "country",
            "state",
            "renewal_due",
            "member_id",
        )
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"

class Top10DanTable(tables.Table):
    pin_player = tables.Column(
        orderable=False,
        linkify={
            "viewname": "players_profile",
            "args": [tables.A("pin_player.member_id")],
        },
    )
    sigma = tables.Column(orderable=False)
    rating = tables.Column(orderable=False)

    def render_pin_player(self, value):
        try:
            member_name_and_id = agagd_models.Member.objects.values(
                "full_name", "member_id"
            ).get(member_id=value.member_id)
            value = f"{value}"
        except ObjectDoesNotExist:
            value = None

        return value

    class Meta:
        model = agagd_models.Players
        fields = ("pin_player", "sigma", "rating")
        sequence = fields
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"

class Top10KyuTable(tables.Table):
    pin_player = tables.Column(
        orderable=False,
        linkify={
            "viewname": "players_profile",
            "args": [tables.A("pin_player.member_id")],
        },
    )
    sigma = tables.Column(orderable=False)
    rating = tables.Column(orderable=False)

    def render_pin_player(self, value):
        try:
            member_name_and_id = agagd_models.Member.objects.values(
                "full_name", "member_id"
            ).get(member_id=value.member_id)
            value = f"{value}"
        except ObjectDoesNotExist:
            value = None

        return value

    class Meta:
        model = agagd_models.Players
        fields = ("pin_player", "sigma", "rating")
        sequence = fields
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"
<commit_msg>Reordering of tables.<commit_after># AGAGD Models Imports
import agagd_core.models as agagd_models

# DJango Imports
import django_tables2 as tables

# AGAGD Column Imports
from agagd_core.tables.core import ChapterColumn
from django.core.exceptions import ObjectDoesNotExist
from django.urls import reverse
from django.utils.safestring import mark_safe

# Base Bootstrap Column Attributes
default_bootstrap_column_attrs = {
    "th": {"class": "d-none d-lg-table-cell d-xl-table-cell"},
    "td": {"class": "d-none d-lg-table-cell d-xl-table-cell"},
}

# Base Bootstrap Column Header Attributes
default_bootstrap_header_column_attrs = {
    "class": "table",
    "thead": {"class": "thead-dark"},
    "th": {"scope": "col"},
}

# Column for the Winner of the Game
class LinkFullMembersNameColumn(tables.Column):
    def __init__(
        self,
        color="W",
        viewname=None,
        urlconf=None,
        args=None,
        kwargs=None,
        current_app=None,
        attrs=None,
        **extra,
    ):
        super().__init__(
            attrs=attrs,
            linkify=dict(
                viewname=viewname,
                urlconf=urlconf,
                args=args,
                kwargs=kwargs,
                current_app=current_app,
            ),
            **extra,
        )
        self.color = color

    def render(self, value, record):
        if record["result"] == self.color:
            self.attrs["td"] = {"class": "winner"}
        elif record["result"] != self.color:
            self.attrs["td"] = {"class": "runner-up"}

        try:
            member_name_and_id = agagd_models.Member.objects.get(member_id=value)
            value = f"{member_name_and_id.full_name} ({value})"
        except ObjectDoesNotExist:
            value = None

        return value

# Basic table which is use as as base for many of the game layouts.
class GamesTable(tables.Table):
    game_date = tables.Column(
        verbose_name="Date", attrs=default_bootstrap_column_attrs, orderable=False
    )
    handicap = tables.Column(attrs=default_bootstrap_column_attrs, orderable=False)
    pin_player_1 = LinkFullMembersNameColumn(
        color="W",
        viewname="players_profile",
        verbose_name="White",
        kwargs={"player_id": tables.A("pin_player_1")},
        orderable=False,
    )
    pin_player_2 = LinkFullMembersNameColumn(
        color="B",
        viewname="players_profile",
        verbose_name="Black",
        kwargs={"player_id": tables.A("pin_player_2")},
        orderable=False,
    )
    tournament_code = tables.LinkColumn(
        verbose_name="Tournament",
        viewname="tournament_detail",
        kwargs={"code": tables.A("tournament_code")},
        orderable=False,
    )

    class Meta:
        model = agagd_models.Game
        fields = (
            "pin_player_1",
            "pin_player_2",
            "tournament_code",
            "handicap",
            "game_date",
        )
        sequence = fields
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"

class PlayersInformationTable(tables.Table):
    full_name = tables.Column()
    member_id = tables.Column()
    status = tables.Column()
    rating = tables.Column()
    renewal_due = tables.Column()

    class Meta:
        template_name = "beta.player_profile_information.html"

class PlayersOpponentTable(tables.Table):
    opponent = tables.Column(
        orderable=False,
        linkify={
            "viewname": "players_profile",
            "args": [tables.A("opponent.member_id")],
        },
    )
    total = tables.Column(orderable=False, verbose_name="Games")
    won = tables.Column(orderable=False, verbose_name="Won", default=0)
    lost = tables.Column(orderable=False, verbose_name="Lost")
    ratio = tables.Column(
        verbose_name="Rate", default=0, empty_values=(-1,), orderable=False
    )

    def render_ratio(self, record):
        ratio = record["won"] / record["total"]

        return f"{ratio:.2f}"

    class Meta:
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"

class TournamentsTable(tables.Table):
    tournament_date = tables.Column(verbose_name="Date", orderable=False)
    description = tables.LinkColumn(
        "tournament_detail",
        verbose_name="Name",
        kwargs={"code": tables.A("tournament_code")},
        orderable=False,
    )
    total_players = tables.Column(
        verbose_name="# Players", attrs=default_bootstrap_column_attrs, orderable=False
    )
    elab_date = tables.Column(verbose_name="Rated", orderable=False)

    class Meta:
        model = agagd_models.Tournament
        fields = ("description", "total_players", "tournament_date", "elab_date")
        sequence = fields
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"

class PlayersTournamentTable(tables.Table):
    tournament = tables.LinkColumn(
        "tournament_detail", kwargs={"code": tables.A("tournament.pk")}, orderable=False
    )
    date = tables.Column(orderable=False, default="Unknown")
    won = tables.Column(orderable=False, verbose_name="Won", default=0)
    lost = tables.Column(orderable=False, verbose_name="Lost", default=0)

    class Meta:
        fields = ("date", "tournament", "won", "lost")
        sequence = fields
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"

class SearchResultsTable(tables.Table):
    member_id = tables.LinkColumn(
        "member_detail", kwargs={"member_id": tables.A("member_id")}
    )
    chapter_id = ChapterColumn(verbose_name="Chapter")
    players__rating = tables.Column(verbose_name="Rating")
    country = tables.LinkColumn(
        "country_detail", kwargs={"country_name": tables.A("country")}
    )
    full_name = tables.LinkColumn(
        "member_detail", kwargs={"member_id": tables.A("member_id")}
    )

    class Meta:
        model = agagd_models.Member
        fields = ("full_name", "state", "players__rating", "renewal_due", "country")
        sequence = (
            "full_name",
            "players__rating",
            "chapter_id",
            "country",
            "state",
            "renewal_due",
            "member_id",
        )
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"

class Top10DanTable(tables.Table):
    pin_player = tables.Column(
        orderable=False,
        linkify={
            "viewname": "players_profile",
            "args": [tables.A("pin_player.member_id")],
        },
    )
    sigma = tables.Column(orderable=False)
    rating = tables.Column(orderable=False)

    def render_pin_player(self, value):
        try:
            member_name_and_id = agagd_models.Member.objects.values(
                "full_name", "member_id"
            ).get(member_id=value.member_id)
            value = f"{value}"
        except ObjectDoesNotExist:
            value = None

        return value

    class Meta:
        model = agagd_models.Players
        fields = ("pin_player", "sigma", "rating")
        sequence = fields
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"

class Top10KyuTable(tables.Table):
    pin_player = tables.Column(
        orderable=False,
        linkify={
            "viewname": "players_profile",
            "args": [tables.A("pin_player.member_id")],
        },
    )
    sigma = tables.Column(orderable=False)
    rating = tables.Column(orderable=False)

    def render_pin_player(self, value):
        try:
            member_name_and_id = agagd_models.Member.objects.values(
                "full_name", "member_id"
            ).get(member_id=value.member_id)
            value = f"{value}"
        except ObjectDoesNotExist:
            value = None

        return value

    class Meta:
        model = agagd_models.Players
        fields = ("pin_player", "sigma", "rating")
        sequence = fields
        attrs = default_bootstrap_header_column_attrs
        template_name = "django_tables2/bootstrap4.html"
<|endoftext|>


<commit_before>#! /usr/bin/env python
# --*-- coding:utf-8 --*--

import os
import sys
sys.path.append(os.path.split(os.path.abspath(sys.path[0]))[0])

#  构造跳转数据
import string
from random import randint
from config.setting import *
from ext.util import *

class Constructor(object):

    def __init__(self):
        self.transactionidList = list()
        self.datacount = 0
        self.logger = getLogger()

    @property
    def setClickConv(self):
        for runtime in range(cycletimes):
            for data in offer_aff_combination:
                offer_id, aff_id = data
                t = string.Template(click_url_template)
                click_url = t.substitute({"offerid":offer_id, "affid":aff_id})
                try:
                    r = requests.get(click_url, headers=headers, allow_redirects=False)
                    if r.status_code != 302:
                        self.logger.error('send click data get a error response code: [{0}]'.format(r.status_code))
                        sys.exit()
                    else:
                        self.datacount += 1
                        self.logger.info('imitate click data success')
                except Exception as ex:
                    traceback.print_exc()
                else:
                    jumpaddress = r.text
                    transaction_id = get_clickid(jumpaddress)
                    self.transactionidList.append(transaction_id)
                    t = string.Template(conv_url_template)
                    conv_url = t.substitute({"transactionid":transaction_id})
                    time.sleep(randint(1,3))
                    if randint(1,5) % 2 == 0:  # 0.4% percent to mock conversion data
                        try:
                            r = requests.get(conv_url)
                            if r.text == 'success=true;conversioned':
                                self.datacount += 1
                                self.logger.info('imitate conversion data success')
                            else:
                                pass
                        except Exception as ex:
                            self.logger.error('set conv data failed')
                    else:
                        pass

    @property
    def getTranasctionId(self):
        self.logger.info('set click and conversion data begin')
        self.setClickConv
        self.logger.info('set click and conversion data end')
        return self.datacount, self.transactionidList

if __name__ == '__main__':
    pass<commit_msg>update conv percent to 100%<commit_after>#! /usr/bin/env python
# --*-- coding:utf-8 --*--

import os
import sys
sys.path.append(os.path.split(os.path.abspath(sys.path[0]))[0])

#  构造跳转数据
import string
from random import randint
from config.setting import *
from ext.util import *

class Constructor(object):

    def __init__(self):
        self.transactionidList = list()
        self.datacount = 0
        self.logger = getLogger()

    @property
    def setClickConv(self):
        for runtime in range(cycletimes):
            for data in offer_aff_combination:
                offer_id, aff_id = data
                t = string.Template(click_url_template)
                click_url = t.substitute({"offerid":offer_id, "affid":aff_id})
                try:
                    r = requests.get(click_url, headers=headers, allow_redirects=False)
                    if r.status_code != 302:
                        self.logger.error('send click data get a error response code: [{0}]'.format(r.status_code))
                        sys.exit()
                    else:
                        self.datacount += 1
                        self.logger.info('imitate click data success')
                except Exception as ex:
                    traceback.print_exc()
                else:
                    jumpaddress = r.text
                    transaction_id = get_clickid(jumpaddress)
                    self.transactionidList.append(transaction_id)
                    t = string.Template(conv_url_template)
                    conv_url = t.substitute({"transactionid":transaction_id})
                    time.sleep(randint(1,3))
                    if randint(2,2) % 2 == 0:  # 100% percent to mock conversion data
                        try:
                            r = requests.get(conv_url)
                            if r.text == 'success=true;conversioned':
                                self.datacount += 1
                                self.logger.info('imitate conversion data success')
                            else:
                                pass
                        except Exception as ex:
                            self.logger.error('set conv data failed')
                    else:
                        pass

    @property
    def getTranasctionId(self):
        self.logger.info('set click and conversion data begin')
        self.setClickConv
        self.logger.info('set click and conversion data end')
        return self.datacount, self.transactionidList

if __name__ == '__main__':
    pass<|endoftext|>


<commit_before>import unittest

import numpy as np

from neo.rawio.neuralynxrawio import NeuralynxRawIO
from neo.rawio.neuralynxrawio import NlxHeader
from neo.rawio.neuralynxrawio import NcsBlocksFactory
from neo.rawio.neuralynxrawio import NcsBlocks
from neo.test.rawiotest.common_rawio_test import BaseTestRawIO

import logging

logging.getLogger().setLevel(logging.INFO)

class TestNeuralynxRawIO(BaseTestRawIO, unittest.TestCase, ):
    rawioclass = NeuralynxRawIO
    entities_to_test = [
        # 'Cheetah_v4.0.2/original_data',
        'Cheetah_v5.5.1/original_data',
        'Cheetah_v5.6.3/original_data',
        'Cheetah_v5.7.4/original_data',
        'Cheetah_v6.3.2/incomplete_blocks']
    files_to_download = [
        'Cheetah_v4.0.2/original_data/CSC14_trunc.Ncs',
        'Cheetah_v5.5.1/original_data/CheetahLogFile.txt',
        'Cheetah_v5.5.1/original_data/CheetahLostADRecords.txt',
        'Cheetah_v5.5.1/original_data/Events.nev',
        'Cheetah_v5.5.1/original_data/STet3a.nse',
        'Cheetah_v5.5.1/original_data/STet3b.nse',
        'Cheetah_v5.5.1/original_data/Tet3a.ncs',
        'Cheetah_v5.5.1/original_data/Tet3b.ncs',
        'Cheetah_v5.5.1/plain_data/STet3a.txt',
        'Cheetah_v5.5.1/plain_data/STet3b.txt',
        'Cheetah_v5.5.1/plain_data/Tet3a.txt',
        'Cheetah_v5.5.1/plain_data/Tet3b.txt',
        'Cheetah_v5.5.1/plain_data/Events.txt',
        'Cheetah_v5.5.1/README.txt',
        'Cheetah_v5.6.3/original_data/CheetahLogFile.txt',
        'Cheetah_v5.6.3/original_data/CheetahLostADRecords.txt',
        'Cheetah_v5.6.3/original_data/Events.nev',
        'Cheetah_v5.6.3/original_data/CSC1.ncs',
        'Cheetah_v5.6.3/original_data/CSC2.ncs',
        'Cheetah_v5.6.3/original_data/TT1.ntt',
        'Cheetah_v5.6.3/original_data/TT2.ntt',
        'Cheetah_v5.6.3/original_data/VT1.nvt',
        'Cheetah_v5.6.3/plain_data/Events.txt',
        'Cheetah_v5.6.3/plain_data/CSC1.txt',
        'Cheetah_v5.6.3/plain_data/CSC2.txt',
        'Cheetah_v5.6.3/plain_data/TT1.txt',
        'Cheetah_v5.6.3/plain_data/TT2.txt',
        'Cheetah_v5.7.4/original_data/CSC1.ncs',
        'Cheetah_v5.7.4/original_data/CSC2.ncs',
        'Cheetah_v5.7.4/original_data/CSC3.ncs',
        'Cheetah_v5.7.4/original_data/CSC4.ncs',
        'Cheetah_v5.7.4/original_data/CSC5.ncs',
        'Cheetah_v5.7.4/original_data/Events.nev',
        'Cheetah_v5.7.4/plain_data/CSC1.txt',
        'Cheetah_v5.7.4/plain_data/CSC2.txt',
        'Cheetah_v5.7.4/plain_data/CSC3.txt',
        'Cheetah_v5.7.4/plain_data/CSC4.txt',
        'Cheetah_v5.7.4/plain_data/CSC5.txt',
        'Cheetah_v5.7.4/plain_data/Events.txt',
        'Cheetah_v5.7.4/README.txt',
        'Cheetah_v6.3.2/incomplete_blocks/CSC1_reduced.ncs',
        'Cheetah_v6.3.2/incomplete_blocks/Events.nev',
        'Cheetah_v6.3.2/incomplete_blocks/README.txt']

    def test_read_ncs_files_sideeffects(self):

        # Test Cheetah 5.5.1, which is DigitalLynxSX and has two blocks of records
        # with a fairly large gap.
        rawio = NeuralynxRawIO(self.get_filename_path('Cheetah_v5.5.1/original_data'))
        rawio.parse_header()
        self.assertEqual(rawio._nb_segment, 2)
        # test values here from direct inspection of .ncs files
        self.assertListEqual(rawio._timestamp_limits,[(26122557633, 26162525633),
                                                      (26366360633, 26379704633)])
        self.assertListEqual(rawio._sigs_length,[1278976, 427008])
        self.assertListEqual(rawio._sigs_t_stop,[26162.525633, 26379.704633])
        self.assertListEqual(rawio._sigs_t_start,[26122.557633, 26366.360633])
        self.assertEqual(len(rawio._sigs_memmap),2)  # check only that there are 2 memmaps

class TestNcsRecordingType(TestNeuralynxRawIO, unittest.TestCase):
    """
    Test of decoding of NlxHeader for type of recording.
    """

    ncsTypeTestFiles = [
        ('Cheetah_v4.0.2/original_data/CSC14_trunc.Ncs', 'PRE4'),
        ('Cheetah_v5.5.1/original_data/STet3a.nse', 'DIGITALLYNXSX'),
        ('Cheetah_v5.5.1/original_data/Tet3a.ncs', 'DIGITALLYNXSX'),
        ('Cheetah_v5.6.3/original_data/CSC1.ncs', 'DIGITALLYNXSX'),
        ('Cheetah_v5.6.3/original_data/TT1.ntt', 'DIGITALLYNXSX'),
        ('Cheetah_v5.7.4/original_data/CSC1.ncs', 'DIGITALLYNXSX'),
        ('Cheetah_v6.3.2/incomplete_blocks/CSC1_reduced.ncs', 'DIGITALLYNXSX')]

    def test_recording_types(self):

        for typeTest in self.ncsTypeTestFiles:

            filename = self.get_filename_path(typeTest[0])
            hdr = NlxHeader.buildForFile(filename)
            self.assertEqual(hdr.typeOfRecording(), typeTest[1])

class TestNcsBlocksFactory(TestNeuralynxRawIO, unittest.TestCase):
    """
    Test building NcsBlocks for files of different revisions.
    """

    def test_ncsblocks_partial(self):
        filename = self.get_filename_path('Cheetah_v6.3.2/incomplete_blocks/CSC1_reduced.ncs')
        data0 = np.memmap(filename, dtype=NeuralynxRawIO._ncs_dtype, mode='r',
                           offset=NlxHeader.HEADER_SIZE)
        self.assertEqual(data0.shape[0],6690)
        self.assertEqual(data0['timestamp'][6689],8515800549) # timestamp of last record

        hdr = NlxHeader.buildForFile(filename)
        nb = NcsBlocksFactory.buildForNcsFile(data0, hdr)
        self.assertEqual(nb.sampFreqUsed, 32009.05084744305)
        self.assertEqual(nb.microsPerSampUsed, 31.241163781021083)
        self.assertEqual(len(nb.startBlocks), 1)
        self.assertEqual(nb.startBlocks[0], 0)
        self.assertEqual(len(nb.endBlocks), 1)
        self.assertEqual(nb.endBlocks[0], 6689)

    def testBuildGivenActualFrequency(self):

        # Test early files where the frequency listed in the header is
        # floor(1e6/(actual number of microseconds between samples)
        filename = self.get_filename_path('Cheetah_v4.0.2/original_data/CSC14_trunc.Ncs')
        data0 = np.memmap(filename, dtype=NeuralynxRawIO._ncs_dtype, mode='r',
                           offset=NlxHeader.HEADER_SIZE)
        ncsBlocks = NcsBlocks()
        ncsBlocks.sampFreqUsed = 1/35e-6
        ncsBlocks.microsPerSampUsed = 35
        ncsBlocks = NcsBlocksFactory._buildGivenActualFrequency(data0, ncsBlocks.sampFreqUsed, 27789)
        self.assertEqual(len(ncsBlocks.startBlocks), 1)
        self.assertEqual(ncsBlocks.startBlocks[0], 0)
        self.assertEqual(len(ncsBlocks.endBlocks), 1)
        self.assertEqual(ncsBlocks.endBlocks[0], 9)

    def testBuildUsingHeaderAndScanning(self):

        # Test early files where the frequency listed in the header is
        # floor(1e6/(actual number of microseconds between samples)
        filename = self.get_filename_path('Cheetah_v4.0.2/original_data/CSC14_trunc.Ncs')
        hdr = NlxHeader.buildForFile(filename)
        data0 = np.memmap(filename, dtype=NeuralynxRawIO._ncs_dtype, mode='r',
                           offset=NlxHeader.HEADER_SIZE)
        nb = NcsBlocksFactory.buildForNcsFile(data0, hdr)

        self.assertEqual(nb.sampFreqUsed, 1/35e-6)
        self.assertEqual(nb.microsPerSampUsed, 35)
        self.assertEqual(len(nb.startBlocks), 1)
        self.assertEqual(nb.startBlocks[0], 0)
        self.assertEqual(len(nb.endBlocks), 1)
        self.assertEqual(nb.endBlocks[0], 9)

        # test Cheetah 5.5.1, which is DigitalLynxSX and has two blocks of records
        # with a fairly large gap
        filename = self.get_filename_path('Cheetah_v5.5.1/original_data/Tet3a.ncs')
        hdr = NlxHeader.buildForFile(filename)
        data0 = np.memmap(filename, dtype=NeuralynxRawIO._ncs_dtype, mode='r',
                           offset=NlxHeader.HEADER_SIZE)
        nb = NcsBlocksFactory.buildForNcsFile(data0, hdr)
        self.assertEqual(nb.sampFreqUsed, 32000)
        self.assertEqual(nb.microsPerSampUsed, 31.25)
        self.assertEqual(len(nb.startBlocks), 2)
        self.assertEqual(nb.startBlocks[0], 0)
        self.assertEqual(nb.startBlocks[1], 2498)
        self.assertEqual(len(nb.endBlocks), 2)
        self.assertEqual(nb.endBlocks[0], 2497)
        self.assertEqual(nb.endBlocks[1], 3331)

if __name__ == "__main__":
    unittest.main()
<commit_msg>Tests of raw io for incomplete records multiple block case.<commit_after>import unittest

import numpy as np

from neo.rawio.neuralynxrawio import NeuralynxRawIO
from neo.rawio.neuralynxrawio import NlxHeader
from neo.rawio.neuralynxrawio import NcsBlocksFactory
from neo.rawio.neuralynxrawio import NcsBlocks
from neo.test.rawiotest.common_rawio_test import BaseTestRawIO

import logging

logging.getLogger().setLevel(logging.INFO)

class TestNeuralynxRawIO(BaseTestRawIO, unittest.TestCase, ):
    rawioclass = NeuralynxRawIO
    entities_to_test = [
        # 'Cheetah_v4.0.2/original_data',
        'Cheetah_v5.5.1/original_data',
        'Cheetah_v5.6.3/original_data',
        'Cheetah_v5.7.4/original_data',
        'Cheetah_v6.3.2/incomplete_blocks']
    files_to_download = [
        'Cheetah_v4.0.2/original_data/CSC14_trunc.Ncs',
        'Cheetah_v5.5.1/original_data/CheetahLogFile.txt',
        'Cheetah_v5.5.1/original_data/CheetahLostADRecords.txt',
        'Cheetah_v5.5.1/original_data/Events.nev',
        'Cheetah_v5.5.1/original_data/STet3a.nse',
        'Cheetah_v5.5.1/original_data/STet3b.nse',
        'Cheetah_v5.5.1/original_data/Tet3a.ncs',
        'Cheetah_v5.5.1/original_data/Tet3b.ncs',
        'Cheetah_v5.5.1/plain_data/STet3a.txt',
        'Cheetah_v5.5.1/plain_data/STet3b.txt',
        'Cheetah_v5.5.1/plain_data/Tet3a.txt',
        'Cheetah_v5.5.1/plain_data/Tet3b.txt',
        'Cheetah_v5.5.1/plain_data/Events.txt',
        'Cheetah_v5.5.1/README.txt',
        'Cheetah_v5.6.3/original_data/CheetahLogFile.txt',
        'Cheetah_v5.6.3/original_data/CheetahLostADRecords.txt',
        'Cheetah_v5.6.3/original_data/Events.nev',
        'Cheetah_v5.6.3/original_data/CSC1.ncs',
        'Cheetah_v5.6.3/original_data/CSC2.ncs',
        'Cheetah_v5.6.3/original_data/TT1.ntt',
        'Cheetah_v5.6.3/original_data/TT2.ntt',
        'Cheetah_v5.6.3/original_data/VT1.nvt',
        'Cheetah_v5.6.3/plain_data/Events.txt',
        'Cheetah_v5.6.3/plain_data/CSC1.txt',
        'Cheetah_v5.6.3/plain_data/CSC2.txt',
        'Cheetah_v5.6.3/plain_data/TT1.txt',
        'Cheetah_v5.6.3/plain_data/TT2.txt',
        'Cheetah_v5.7.4/original_data/CSC1.ncs',
        'Cheetah_v5.7.4/original_data/CSC2.ncs',
        'Cheetah_v5.7.4/original_data/CSC3.ncs',
        'Cheetah_v5.7.4/original_data/CSC4.ncs',
        'Cheetah_v5.7.4/original_data/CSC5.ncs',
        'Cheetah_v5.7.4/original_data/Events.nev',
        'Cheetah_v5.7.4/plain_data/CSC1.txt',
        'Cheetah_v5.7.4/plain_data/CSC2.txt',
        'Cheetah_v5.7.4/plain_data/CSC3.txt',
        'Cheetah_v5.7.4/plain_data/CSC4.txt',
        'Cheetah_v5.7.4/plain_data/CSC5.txt',
        'Cheetah_v5.7.4/plain_data/Events.txt',
        'Cheetah_v5.7.4/README.txt',
        'Cheetah_v6.3.2/incomplete_blocks/CSC1_reduced.ncs',
        'Cheetah_v6.3.2/incomplete_blocks/Events.nev',
        'Cheetah_v6.3.2/incomplete_blocks/README.txt']

    def test_read_ncs_files_sideeffects(self):

        # Test Cheetah 5.5.1, which is DigitalLynxSX and has two blocks of records
        # with a fairly large gap.
        rawio = NeuralynxRawIO(self.get_filename_path('Cheetah_v5.5.1/original_data'))
        rawio.parse_header()
        # test values here from direct inspection of .ncs files
        self.assertEqual(rawio._nb_segment, 2)
        self.assertListEqual(rawio._timestamp_limits,[(26122557633, 26162525633),
                                                      (26366360633, 26379704633)])
        self.assertListEqual(rawio._sigs_length,[1278976, 427008])
        self.assertListEqual(rawio._sigs_t_stop,[26162.525633, 26379.704633])
        self.assertListEqual(rawio._sigs_t_start,[26122.557633, 26366.360633])
        self.assertEqual(len(rawio._sigs_memmap),2)  # check only that there are 2 memmaps

        # Test Cheetah 6.3.2, the incomplete_blocks test. This is a DigitalLynxSX with
        # three blocks of records. Gaps are on the order of 16 ms or so.
        rawio = NeuralynxRawIO(self.get_filename_path('Cheetah_v6.3.2/incomplete_blocks'))
        rawio.parse_header()
        # test values here from direct inspection of .ncs file
        self.assertEqual(rawio._nb_segment, 3)
        self.assertListEqual(rawio._timestamp_limits,[(8408806811, 8427831990),
                                                      (8427832053, 8487768498),
                                                      (8487768561, 8515816549)])
        self.assertListEqual(rawio._sigs_length,[608806, 1917967, 897536])
        self.assertListEqual(rawio._sigs_t_stop,[8427.831990, 8487.768498, 8515.816549])
        self.assertListEqual(rawio._sigs_t_start,[8408.806811, 8427.832053, 8487.768561])
        self.assertEqual(len(rawio._sigs_memmap),3)  # check only that there are 3 memmaps

class TestNcsRecordingType(TestNeuralynxRawIO, unittest.TestCase):
    """
    Test of decoding of NlxHeader for type of recording.
    """

    ncsTypeTestFiles = [
        ('Cheetah_v4.0.2/original_data/CSC14_trunc.Ncs', 'PRE4'),
        ('Cheetah_v5.5.1/original_data/STet3a.nse', 'DIGITALLYNXSX'),
        ('Cheetah_v5.5.1/original_data/Tet3a.ncs', 'DIGITALLYNXSX'),
        ('Cheetah_v5.6.3/original_data/CSC1.ncs', 'DIGITALLYNXSX'),
        ('Cheetah_v5.6.3/original_data/TT1.ntt', 'DIGITALLYNXSX'),
        ('Cheetah_v5.7.4/original_data/CSC1.ncs', 'DIGITALLYNXSX'),
        ('Cheetah_v6.3.2/incomplete_blocks/CSC1_reduced.ncs', 'DIGITALLYNXSX')]

    def test_recording_types(self):

        for typeTest in self.ncsTypeTestFiles:

            filename = self.get_filename_path(typeTest[0])
            hdr = NlxHeader.buildForFile(filename)
            self.assertEqual(hdr.typeOfRecording(), typeTest[1])

class TestNcsBlocksFactory(TestNeuralynxRawIO, unittest.TestCase):
    """
    Test building NcsBlocks for files of different revisions.
    """

    def test_ncsblocks_partial(self):
        filename = self.get_filename_path('Cheetah_v6.3.2/incomplete_blocks/CSC1_reduced.ncs')
        data0 = np.memmap(filename, dtype=NeuralynxRawIO._ncs_dtype, mode='r',
                           offset=NlxHeader.HEADER_SIZE)
        self.assertEqual(data0.shape[0],6690)
        self.assertEqual(data0['timestamp'][6689],8515800549) # timestamp of last record

        hdr = NlxHeader.buildForFile(filename)
        nb = NcsBlocksFactory.buildForNcsFile(data0, hdr)
        self.assertEqual(nb.sampFreqUsed, 32000.012813673042)
        self.assertEqual(nb.microsPerSampUsed, 31.249987486652431)
        self.assertListEqual(nb.startBlocks, [0, 1190, 4937])
        self.assertListEqual(nb.endBlocks, [1189, 4936, 6689])

    def testBuildGivenActualFrequency(self):

        # Test early files where the frequency listed in the header is
        # floor(1e6/(actual number of microseconds between samples)
        filename = self.get_filename_path('Cheetah_v4.0.2/original_data/CSC14_trunc.Ncs')
        data0 = np.memmap(filename, dtype=NeuralynxRawIO._ncs_dtype, mode='r',
                           offset=NlxHeader.HEADER_SIZE)
        ncsBlocks = NcsBlocks()
        ncsBlocks.sampFreqUsed = 1/35e-6
        ncsBlocks.microsPerSampUsed = 35
        ncsBlocks = NcsBlocksFactory._buildGivenActualFrequency(data0, ncsBlocks.sampFreqUsed, 27789)
        self.assertEqual(len(ncsBlocks.startBlocks), 1)
        self.assertEqual(ncsBlocks.startBlocks[0], 0)
        self.assertEqual(len(ncsBlocks.endBlocks), 1)
        self.assertEqual(ncsBlocks.endBlocks[0], 9)

    def testBuildUsingHeaderAndScanning(self):

        # Test early files where the frequency listed in the header is
        # floor(1e6/(actual number of microseconds between samples)
        filename = self.get_filename_path('Cheetah_v4.0.2/original_data/CSC14_trunc.Ncs')
        hdr = NlxHeader.buildForFile(filename)
        data0 = np.memmap(filename, dtype=NeuralynxRawIO._ncs_dtype, mode='r',
                           offset=NlxHeader.HEADER_SIZE)
        nb = NcsBlocksFactory.buildForNcsFile(data0, hdr)

        self.assertEqual(nb.sampFreqUsed, 1/35e-6)
        self.assertEqual(nb.microsPerSampUsed, 35)
        self.assertEqual(len(nb.startBlocks), 1)
        self.assertEqual(nb.startBlocks[0], 0)
        self.assertEqual(len(nb.endBlocks), 1)
        self.assertEqual(nb.endBlocks[0], 9)

        # test Cheetah 5.5.1, which is DigitalLynxSX and has two blocks of records
        # with a fairly large gap
        filename = self.get_filename_path('Cheetah_v5.5.1/original_data/Tet3a.ncs')
        hdr = NlxHeader.buildForFile(filename)
        data0 = np.memmap(filename, dtype=NeuralynxRawIO._ncs_dtype, mode='r',
                           offset=NlxHeader.HEADER_SIZE)
        nb = NcsBlocksFactory.buildForNcsFile(data0, hdr)
        self.assertEqual(nb.sampFreqUsed, 32000)
        self.assertEqual(nb.microsPerSampUsed, 31.25)
        self.assertEqual(len(nb.startBlocks), 2)
        self.assertEqual(nb.startBlocks[0], 0)
        self.assertEqual(nb.startBlocks[1], 2498)
        self.assertEqual(len(nb.endBlocks), 2)
        self.assertEqual(nb.endBlocks[0], 2497)
        self.assertEqual(nb.endBlocks[1], 3331)

if __name__ == "__main__":
    unittest.main()
<|endoftext|>


<commit_before>import re
from functools import wraps
import json

from django import template
from django.utils.safestring import mark_for_escaping

register = template.Library()

@register.filter
def form_index(form):
    """
    The id of the root 'form' element in a formset is the form's 'prefix'
    without the '-' preceding the index of the form. So, for instance, in a case
    where the form's 'id' field has the field name:
        prefix-2-id
    the 'form' element's id would be:
        prefix2
    and the form's index is '2'
    """
    matches = re.search(r'\-(\d+)$', form.prefix)
    if not matches:
        raise Exception("Form with invalid prefix passed to templatetag")
    return int(matches.group(1))

@register.filter
def strip_parent_name(nested_name, parent_name):
    if nested_name.find(parent_name + " ") == 0:
        return nested_name[len(parent_name)+1:]
    else:
        return nested_name
strip_parent_name.is_safe = True

# These tags are defined in grappelli.templatetags.grp_tags. The issue is that
# they are wrapped in mark_safe(), so we can't use them reliably inside of
# attributes.

@register.filter
def json_encode(data):
    return mark_for_escaping(json.dumps(data))

def json_else_list_tag(f):
    """
    Decorator. Registers function as a simple_tag.
    Try: Return value of the decorated function json encoded.
    Except: Return []
    """
    @wraps(f)
    def inner(model_admin):
        try:
            return mark_for_escaping(json.dumps(f(model_admin)))
        except:
            return []
    return register.simple_tag(inner)

@json_else_list_tag
def get_safe_related_lookup_fields_fk(model_admin):
    return model_admin.related_lookup_fields.get("fk", [])

@json_else_list_tag
def get_safe_related_lookup_fields_m2m(model_admin):
    return model_admin.related_lookup_fields.get("m2m", [])

@json_else_list_tag
def get_safe_related_lookup_fields_generic(model_admin):
    return model_admin.related_lookup_fields.get("generic", [])

# AUTOCOMPLETES

@json_else_list_tag
def get_safe_autocomplete_lookup_fields_fk(model_admin):
    return model_admin.autocomplete_lookup_fields.get("fk", [])

@json_else_list_tag
def get_safe_autocomplete_lookup_fields_m2m(model_admin):
    return model_admin.autocomplete_lookup_fields.get("m2m", [])

@json_else_list_tag
def get_safe_autocomplete_lookup_fields_generic(model_admin):
    return model_admin.autocomplete_lookup_fields.get("generic", [])

@register.filter
def formsetsort(formset, arg):
    """
    Takes a list of formset dicts, returns that list sorted by the sortable field.
    """
    if arg:
        sorted_list = []
        for item in formset:
            position = item.form[arg].data
            if position and position != "-1":
                sorted_list.append((int(position), item))
        sorted_list.sort()
        sorted_list = [item[1] for item in sorted_list]
        for item in formset:
            position = item.form[arg].data
            if not position or position == "-1":
                sorted_list.append(item)
    else:
        sorted_list = formset
    return sorted_list
<commit_msg>Actually escape json_else_list templatetag.<commit_after>import re
from functools import wraps
import json

from django import template
from django.utils.safestring import mark_for_escaping, mark_safe
from django.utils.html import escape

register = template.Library()

@register.filter
def form_index(form):
    """
    The id of the root 'form' element in a formset is the form's 'prefix'
    without the '-' preceding the index of the form. So, for instance, in a case
    where the form's 'id' field has the field name:
        prefix-2-id
    the 'form' element's id would be:
        prefix2
    and the form's index is '2'
    """
    matches = re.search(r'\-(\d+)$', form.prefix)
    if not matches:
        raise Exception("Form with invalid prefix passed to templatetag")
    return int(matches.group(1))

@register.filter
def strip_parent_name(nested_name, parent_name):
    if nested_name.find(parent_name + " ") == 0:
        return nested_name[len(parent_name)+1:]
    else:
        return nested_name
strip_parent_name.is_safe = True

# These tags are defined in grappelli.templatetags.grp_tags. The issue is that
# they are wrapped in mark_safe(), so we can't use them reliably inside of
# attributes.

@register.filter
def json_encode(data):
    return mark_for_escaping(json.dumps(data))

def json_else_list_tag(f):
    """
    Decorator. Registers function as a simple_tag.
    Try: Return value of the decorated function json encoded.
    Except: Return []
    """
    @wraps(f)
    def inner(model_admin):
        try:
            return mark_safe(escape(json.dumps(f(model_admin))))
        except:
            return []
    return register.simple_tag(inner)

@json_else_list_tag
def get_safe_related_lookup_fields_fk(model_admin):
    return model_admin.related_lookup_fields.get("fk", [])

@json_else_list_tag
def get_safe_related_lookup_fields_m2m(model_admin):
    return model_admin.related_lookup_fields.get("m2m", [])

@json_else_list_tag
def get_safe_related_lookup_fields_generic(model_admin):
    return model_admin.related_lookup_fields.get("generic", [])

# AUTOCOMPLETES

@json_else_list_tag
def get_safe_autocomplete_lookup_fields_fk(model_admin):
    return model_admin.autocomplete_lookup_fields.get("fk", [])

@json_else_list_tag
def get_safe_autocomplete_lookup_fields_m2m(model_admin):
    return model_admin.autocomplete_lookup_fields.get("m2m", [])

@json_else_list_tag
def get_safe_autocomplete_lookup_fields_generic(model_admin):
    return model_admin.autocomplete_lookup_fields.get("generic", [])

@register.filter
def formsetsort(formset, arg):
    """
    Takes a list of formset dicts, returns that list sorted by the sortable field.
    """
    if arg:
        sorted_list = []
        for item in formset:
            position = item.form[arg].data
            if position and position != "-1":
                sorted_list.append((int(position), item))
        sorted_list.sort()
        sorted_list = [item[1] for item in sorted_list]
        for item in formset:
            position = item.form[arg].data
            if not position or position == "-1":
                sorted_list.append(item)
    else:
        sorted_list = formset
    return sorted_list
<|endoftext|>


<commit_before>from ..grammar_parsing.parse_grammar import parse_grammar_file
from ..grammar_parsing.production import *
from ..grammar_parsing.production_part import *

from collections import defaultdict
from itertools import chain
from typing import Dict, List, Optional, Tuple

# TODO: Parameters most be processed prior to line generation so lifting can occur.
# TODO: Need to handle special tokens such as NAME, CLASS, and NUMBER.

# Three levels:
#
#   1. Rules that are superclasses of other rules (through aliasing).
#   2. Rules that are superclasses only of productions.
#   3. Productions.
#
# Classes in (1) must be written first, then (2), then (3).

Param = Tuple[str, Optional[str]]

def generate_from_grammar_file(grammar_filename: str, output_filename: str):
    text = ASTNodeGenerator(grammar_filename).generate_text()
    with open(output_filename, 'w') as of:
        of.write(text)

class Arg:
    def __init__(self, name: Optional[str], type_: Optional[str], wrappers=None):
        self.name = name
        self.type = type_
        if wrappers:
            self.wrappers = wrappers
        else:
            self.wrappers = []

class ASTNodeGenerator:
    BASE_AST_CLASS_NAME = 'AST'

    def __init__(self, filename: str):
        self.tree = None
        self.parsed_rules = parse_grammar_file(filename)
        self.build_rule_tree(self.parsed_rules)
        for rule, production_list in self.parsed_rules.items():
            if len(production_list) == 1:
                self.make_ast_node_class_from_single_production(rule, production_list[0])
            else:
                self.make_ast_node_classes_from_production_list(rule, production_list)

    def generate_text(self) -> str:
        # Add the header.
        lines = [
            "# This module was automatically generated.",
            "",
            "from typing import List, Optional",
            "",
            "",
        ]
        # Set the depths of the nodes to accommodate parameters. Repeat until no updates are performed.
        # TODO: How likely is it that this will repeat many times? Should a fix-point be computed differently?
        needs_update = True
        while needs_update:
            needs_update = False
            queue = [self.tree.root]
            while queue:
                node = queue.pop(0)
                new_depth = max(chain([node.depth], (parent.depth + 1 for parent in node.parents)))
                new_depth = max(chain([new_depth], (self.tree[param].depth + 1 for param in node.params)))
                if new_depth > node.depth:
                    node.depth = new_depth
                    needs_update = True
                queue += node.children
        # Organize nodes by depth in the tree without including duplicates.
        tiers = defaultdict(set)
        queue = [self.tree.root]
        while queue:
            node = queue.pop(0)
            tiers[node.depth].add(node)
            queue += node.children
        # Iterating by tier, add nodes' lines.
        for depth in sorted(tiers.keys()):
            tier = tiers[depth]
            for node in tier:
                lines += node.lines
                lines += ["", ""]
        # Remove extra blank line at the end and return.
        del(lines[-1])
        return '\n'.join(lines)

    class ClassTree:
        def __init__(self):
            self._nodes = {}
            root = ASTNodeGenerator.ClassTreeNode(ASTNodeGenerator.BASE_AST_CLASS_NAME)
            root.lines = [
                'class ' + root.name + ':',
                '    pass'
            ]
            self._nodes[ASTNodeGenerator.BASE_AST_CLASS_NAME] = root
            self.root = root

        def __getitem__(self, item):
            return self._nodes[item]

        def __setitem__(self, key, value):
            if key in self._nodes:
                raise RuntimeError  # TODO: Replace with custom error.
            self._nodes[key] = value

        def add(self, child_name: str, parent_name: str):
            if child_name in self._nodes:
                raise RuntimeError  # TODO: Replace with custom error.
            if parent_name not in self._nodes:
                raise RuntimeError  # TODO: Replace with custom error.
            parent_node = self[parent_name]
            child_node = ASTNodeGenerator.ClassTreeNode(child_name)
            child_node.parents.append(parent_node)
            parent_node.children.append(child_node)
            child_node.depth = parent_node.depth + 1
            self[child_name] = child_node

        def add_to_root(self, child_name: str):
            self.add(child_name, self.root.name)

    class ClassTreeNode:
        def __init__(self, name: str):
            self.name = name
            self.parents = []
            self.children = []
            self.lines = []
            self.depth = 0
            self.params = []

        def __repr__(self):
            return self.name

    def build_rule_tree(self, parsed_rules: Dict[str, List[Production]]):
        self.tree = ASTNodeGenerator.ClassTree()

        rules = set()                   # All rules.
        aliases = defaultdict(list)     # Map: aliased-rule -> [parent rules]
        productions = {}                # Map: prod-name -> parent rule

        for rule, production_list in parsed_rules.items():
            rules.add(rule)
            solo = False
            if len(production_list) == 1:
                solo = True
            for production in production_list:
                if isinstance(production, RuleAliasProduction):
                    aliases[production.name].append(rule)
                elif isinstance(production, NamedProduction):
                    if not solo:
                        productions[production.name] = rule
                else:
                    raise RuntimeError  # TODO: Replace with custom class.

        for rule in rules:
            self.tree.add_to_root(rule)
        for alias, parents in aliases.items():
            node = self.tree[alias]
            node.parents = []
            for parent in parents:
                parent_node = self.tree[parent]
                node.parents.append(parent_node)
                parent_node.children.append(node)
            node.depth = max(parent.depth for parent in node.parents)
        for production, parent in productions.items():
            self.tree.add(production, parent)

    def make_ast_node_class_from_single_production(self, rule: str, production: Production):
        if isinstance(production, RuleAliasProduction):
            # This was handled in pre-processing.
            return
        elif isinstance(production, NamedProduction):
            self.make_ast_node_class(rule, production.parts)
        else:
            raise RuntimeError  # TODO: Replace with custom error.

    def make_ast_node_classes_from_production_list(self, rule: str, production_list: List[Production]):
        # Make the base class for these productions to inherit from.
        self.make_ast_node_class(rule, [])
        # Now create each child class.
        for production in production_list:
            if isinstance(production, NamedProduction):
                class_name = production.name
                self.make_ast_node_class(class_name, production.parts)

    def make_ast_node_class(self, class_rule_name: str, parts: List[ProductionPart]):
        node = self.tree[class_rule_name]
        lines = node.lines
        class_name = self.convert_name_to_class_name(class_rule_name)
        superclasses = ', '.join([self.convert_name_to_class_name(parent.name) for parent in node.parents])

        has_args = False
        params = [('self', None)]
        for part in parts:
            arg = self.get_arg_from_production_part(part)
            if arg is None or arg.name is None:
                continue
            if arg.type is None:
                arg_type = None
            else:
                has_args = True
                node.params.append(arg.type)
                arg_type = self.convert_name_to_class_name(arg.type)
                for wrapper in reversed(arg.wrappers):
                    arg_type = wrapper + '[' + arg_type + ']'
            pair = (arg.name, arg_type)
            params.append(pair)

        def param_to_str(param: Param) -> str:
            param_name, param_type = param
            return param_name if param_type is None else param_name + ": " + self.convert_name_to_class_name(param_type)

        joined_params = ', '.join(map(param_to_str, params))
        lines.append(f"class {class_name}({superclasses}):")
        if has_args:
            lines.append(f"    def __init__({joined_params}):")
            for name in (name for name, _ in params if name != 'self'):
                lines.append(f"        self.{name} = {name}")
        else:
            lines.append(f"    pass")

    def get_arg_from_production_part(self, part: ProductionPart) -> Optional[Arg]:
            if isinstance(part, LiteralPart):
                return None
            elif isinstance(part, SpecialPart):
                return None
            elif isinstance(part, RulePart):
                return Arg(None, part.name)
            elif isinstance(part, RepeatPart):
                part_arg = self.get_arg_from_production_part(part.part)
                if part_arg is None:
                    return None
                arg = Arg(part_arg.name, part_arg.type, part_arg.wrappers)
                arg.wrappers.append('List')
                return arg
            elif isinstance(part, SeparatedRepeatPart):
                part_arg = self.get_arg_from_production_part(part.rule)
                if part_arg is None:
                    return None
                arg = Arg(part_arg.name, part_arg.type, part_arg.wrappers)
                arg.wrappers.append('List')
                return arg
            elif isinstance(part, OptionPart):
                part_arg = self.get_arg_from_production_part(part.part)
                if part_arg is None:
                    return None
                arg = Arg(part_arg.name, part_arg.type, part_arg.wrappers)
                arg.wrappers.append('Optional')
                return arg
            elif isinstance(part, ParameterPart):
                part_arg = self.get_arg_from_production_part(part.part)
                if part_arg is None:
                    return Arg(part.name, None)
                return Arg(part.name, part_arg.type, part_arg.wrappers)
            elif isinstance(part, LiftedParameterPart):
                ...
            else:
                raise RuntimeError(f"Unexpected production part type: {type(part)}")  # TODO: Replace with custom error.

    @staticmethod
    def convert_name_to_class_name(name: str) -> str:
        if name[0].isupper():
            return name
        return ''.join(map(lambda s: s.title(), name.split('_')))
<commit_msg>Revise parameter handling in node generation<commit_after>from ..grammar_parsing.parse_grammar import parse_grammar_file
from ..grammar_parsing.production import *
from ..grammar_parsing.production_part import *

from collections import defaultdict
from itertools import chain
from typing import Dict, List, Optional, Tuple

# TODO: Parameters most be processed prior to line generation so lifting can occur.
# TODO: Need to handle special tokens such as NAME, CLASS, and NUMBER.

# Three levels:
#
#   1. Rules that are superclasses of other rules (through aliasing).
#   2. Rules that are superclasses only of productions.
#   3. Productions.
#
# Classes in (1) must be written first, then (2), then (3).

Param = Tuple[str, Optional[str], Optional[str]]

def generate_from_grammar_file(grammar_filename: str, output_filename: str):
    text = ASTNodeGenerator(grammar_filename).generate_text()
    with open(output_filename, 'w') as of:
        of.write(text)

class Arg:
    def __init__(self, name: Optional[str], type_: Optional[str], wrappers=None):
        self.name = name
        self.type = type_
        if wrappers:
            self.wrappers = wrappers
        else:
            self.wrappers = []

class ASTNodeGenerator:
    BASE_AST_CLASS_NAME = 'AST'

    def __init__(self, filename: str):
        self.tree = None
        self.parsed_rules = parse_grammar_file(filename)
        self.build_rule_tree(self.parsed_rules)
        for rule, production_list in self.parsed_rules.items():
            if len(production_list) == 1:
                self.make_ast_node_class_from_single_production(rule, production_list[0])
            else:
                self.make_ast_node_classes_from_production_list(rule, production_list)

    def generate_text(self) -> str:
        # Add the header.
        lines = [
            "# This module was automatically generated.",
            "",
            "from typing import List, Optional",
            "",
            "",
        ]
        # Set the depths of the nodes to accommodate parameters. Repeat until no updates are performed.
        # TODO: How likely is it that this will repeat many times? Should a fix-point be computed differently?
        needs_update = True
        while needs_update:
            needs_update = False
            queue = [self.tree.root]
            while queue:
                node = queue.pop(0)
                new_depth = max(chain([node.depth], (parent.depth + 1 for parent in node.parents)))
                new_depth = max(chain([new_depth],
                                      (self.tree[param].depth + 1
                                       for _, param, _ in node.params if param is not None)))
                if new_depth > node.depth:
                    node.depth = new_depth
                    needs_update = True
                queue += node.children
        # Organize nodes by depth in the tree without including duplicates.
        tiers = defaultdict(set)
        queue = [self.tree.root]
        while queue:
            node = queue.pop(0)
            tiers[node.depth].add(node)
            queue += node.children
        # Iterating by tier, add nodes' lines.
        for depth in sorted(tiers.keys()):
            tier = tiers[depth]
            for node in tier:
                lines += node.lines
                lines += ["", ""]
        # Remove extra blank line at the end and return.
        del(lines[-1])
        return '\n'.join(lines)

    class ClassTree:
        def __init__(self):
            self._nodes = {}
            root = ASTNodeGenerator.ClassTreeNode(ASTNodeGenerator.BASE_AST_CLASS_NAME)
            root.lines = [
                'class ' + root.name + ':',
                '    pass'
            ]
            self._nodes[ASTNodeGenerator.BASE_AST_CLASS_NAME] = root
            self.root = root

        def __getitem__(self, item):
            return self._nodes[item]

        def __setitem__(self, key, value):
            if key in self._nodes:
                raise RuntimeError  # TODO: Replace with custom error.
            self._nodes[key] = value

        def add(self, child_name: str, parent_name: str):
            if child_name in self._nodes:
                raise RuntimeError  # TODO: Replace with custom error.
            if parent_name not in self._nodes:
                raise RuntimeError  # TODO: Replace with custom error.
            parent_node = self[parent_name]
            child_node = ASTNodeGenerator.ClassTreeNode(child_name)
            child_node.parents.append(parent_node)
            parent_node.children.append(child_node)
            child_node.depth = parent_node.depth + 1
            self[child_name] = child_node

        def add_to_root(self, child_name: str):
            self.add(child_name, self.root.name)

    class ClassTreeNode:
        def __init__(self, name: str):
            self.name = name
            self.parents: List[ASTNodeGenerator.ClassTreeNode] = []
            self.children: List[ASTNodeGenerator.ClassTreeNode] = []
            self.lines: List[str] = []
            self.params: List[Param] = []
            self.depth = 0

        def __repr__(self):
            return self.name

    def build_rule_tree(self, parsed_rules: Dict[str, List[Production]]):
        self.tree = ASTNodeGenerator.ClassTree()

        rules = set()                   # All rules.
        aliases = defaultdict(list)     # Map: aliased-rule -> [parent rules]
        productions = {}                # Map: prod-name -> parent rule

        for rule, production_list in parsed_rules.items():
            rules.add(rule)
            solo = False
            if len(production_list) == 1:
                solo = True
            for production in production_list:
                if isinstance(production, RuleAliasProduction):
                    aliases[production.name].append(rule)
                elif isinstance(production, NamedProduction):
                    if not solo:
                        productions[production.name] = rule
                else:
                    raise RuntimeError  # TODO: Replace with custom class.

        for rule in rules:
            self.tree.add_to_root(self.convert_name_to_class_name(rule))
        for alias, parents in aliases.items():
            node = self.tree[self.convert_name_to_class_name(alias)]
            node.parents = []
            for parent in parents:
                parent_node = self.tree[self.convert_name_to_class_name(parent)]
                node.parents.append(parent_node)
                parent_node.children.append(node)
            node.depth = max(parent.depth for parent in node.parents)
        for production, parent in productions.items():
            self.tree.add(self.convert_name_to_class_name(production), self.convert_name_to_class_name(parent))

    def make_ast_node_class_from_single_production(self, rule: str, production: Production):
        if isinstance(production, RuleAliasProduction):
            # This was handled in pre-processing.
            return
        elif isinstance(production, NamedProduction):
            class_name = self.convert_name_to_class_name(rule)
            self.process_parameters(class_name, production.parts)
            self.make_ast_node_class(class_name)
        else:
            raise RuntimeError  # TODO: Replace with custom error.

    def make_ast_node_classes_from_production_list(self, rule: str, production_list: List[Production]):
        # Make the base class for these productions to inherit from.
        self.make_ast_node_class(self.convert_name_to_class_name(rule))
        # Now create each child class.
        for production in production_list:
            if isinstance(production, NamedProduction):
                class_name = self.convert_name_to_class_name(production.name)
                self.process_parameters(class_name, production.parts)
                self.make_ast_node_class(class_name)
            elif isinstance(production, RuleAliasProduction):
                continue
            else:
                raise RuntimeError  # TODO: Replace with custom error.

    def process_parameters(self, class_name: str, parts: List[ProductionPart]):
        node = self.tree[class_name]
        for part in parts:
            arg = self.get_arg_from_production_part(part)
            if arg is None or arg.name is None:
                continue
            if arg.type is None:
                param = (arg.name, None, None)
            else:
                base_arg_type = self.convert_name_to_class_name(arg.type)
                arg_type = base_arg_type
                for wrapper in reversed(arg.wrappers):
                    arg_type = wrapper + '[' + base_arg_type + ']'
                param = (arg.name, base_arg_type, arg_type)
            node.params.append(param)

    def make_ast_node_class(self, class_name: str):
        node = self.tree[class_name]
        lines = node.lines
        superclasses = ', '.join([parent.name for parent in node.parents])

        def param_to_str(param: Param) -> str:
            param_name, _, param_type = param
            return param_name if param_type is None else param_name + ": " + self.convert_name_to_class_name(param_type)

        has_params = len(node.params) > 0
        params = [('self', None, None)] + node.params

        lines.append(f"class {class_name}({superclasses}):")
        if has_params:
            joined_params = ', '.join(map(param_to_str, params))
            lines.append(f"    def __init__({joined_params}):")
            for name in (name for name, _, _ in params if name != 'self'):
                lines.append(f"        self.{name} = {name}")
        else:
            lines.append(f"    pass")

    def get_arg_from_production_part(self, part: ProductionPart) -> Optional[Arg]:
            if isinstance(part, LiteralPart):
                return None
            elif isinstance(part, SpecialPart):
                return None
            elif isinstance(part, RulePart):
                return Arg(None, part.name)
            elif isinstance(part, RepeatPart):
                part_arg = self.get_arg_from_production_part(part.part)
                if part_arg is None:
                    return None
                arg = Arg(part_arg.name, part_arg.type, part_arg.wrappers)
                arg.wrappers.append('List')
                return arg
            elif isinstance(part, SeparatedRepeatPart):
                part_arg = self.get_arg_from_production_part(part.rule)
                if part_arg is None:
                    return None
                arg = Arg(part_arg.name, part_arg.type, part_arg.wrappers)
                arg.wrappers.append('List')
                return arg
            elif isinstance(part, OptionPart):
                part_arg = self.get_arg_from_production_part(part.part)
                if part_arg is None:
                    return None
                arg = Arg(part_arg.name, part_arg.type, part_arg.wrappers)
                arg.wrappers.append('Optional')
                return arg
            elif isinstance(part, ParameterPart):
                part_arg = self.get_arg_from_production_part(part.part)
                if part_arg is None:
                    return Arg(part.name, None)
                return Arg(part.name, part_arg.type, part_arg.wrappers)
            elif isinstance(part, LiftedParameterPart):
                ...
            else:
                raise RuntimeError(f"Unexpected production part type: {type(part)}")  # TODO: Replace with custom error.

    @staticmethod
    def convert_name_to_class_name(name: str) -> str:
        if name[0].isupper():
            return name
        return ''.join(map(lambda s: s.title(), name.split('_')))
<|endoftext|>


<commit_before>import discord
from discord.ext import commands

import os, random, re, typing, traceback, logging

class Misc(commands.Cog):

    def __init__(self, bot: commands.Bot):
        self._bot = bot
        self._res_path = 'res/'
        self._spongebob_regex = re.compile(r'<@!?(\d+)>|<@&(\d+)>|<#(\d+)>')
        self._autism = message.guild.get_role(557816089296502784)

    @commands.Cog.listener()
    async def on_command_error(self, ctx: commands.Context, error: discord.DiscordException):
        logging.debug('Misc error by {}: {}'.format(ctx.author, error))
        ignored = (commands.CommandNotFound)
        error = getattr(error, 'original', error)

        if isinstance(error, ignored):
            return

        if await self._bot.is_owner(ctx.author):
            traceback.print_exc()
            await ctx.send('You messed up, but I forgive you {}'.format(ctx.author.mention))
            return

        if isinstance(error, commands.NotOwner):
            await ctx.invoke(self.disobedience, ctx.author, 'treason with the power of a trillion suns')
        elif isinstance(error, commands.CommandOnCooldown):
            await ctx.invoke(self.disobedience, ctx.author, 'spamming a command')
        elif isinstance(error, commands.UserInputError):
            await ctx.invoke(self.disobedience, ctx.author, 'incompetence')
        else:
            logging.error('Something fatal ocurred')

    @commands.command()
    async def spongecase(self,
                   ctx: commands.Context,
                   member: typing.Optional[discord.Member]=None,
                   distance: typing.Optional[int]=0,
                   *,
                   message=None):
        logging.info('Spongecase {} {} {}'.format(member, distance, message))
        if message is not None:
            spongecased_message = self._spongecaseify(message)

            spongecased_being = member if member is not None else ctx.author
            await ctx.send('{}: {}'.format(spongecased_being.mention, self._spongecaseify(message)))
        elif member is not None:
            await ctx.invoke(self.spongecase_last_message, member, distance)
        else:
            await ctx.invoke(self.disobedience, ctx.author, 'incompetence')
        logging.info('Done spongecase')

    @commands.command(hidden=True)
    async def spongecase_last_message(self, ctx: commands.Context, member: discord.Member, distance: int):
        message_count = 0
        async for message in ctx.channel.history(limit=200):
            if message.author == member:
                if message_count >= distance:
                    await ctx.invoke(self.spongecase, member=member, message=message.content)
                    break
                else:
                    message_count += 1
        else:
            await ctx.invoke(self.disobedience, ctx.author, 'incompetence')

    @commands.command(aliases=['dildo', 'whale'])
    async def trout(self, ctx: commands.Context, member: discord.Member):
        logging.info('Trout {} by {}'.format(member, ctx.author))
        await ctx.message.delete()
        if await self._bot.is_owner(member) or member.bot:
            await ctx.invoke(self.disobedience, member, 'disobedience')
        else:
            if ctx.invoked_with in ['trout']:
                await ctx.send('{} gets slapped in the face with a {}'.format(member.mention, ctx.invoked_with))
            elif ctx.invoked_with in ['dildo']:
                await ctx.send('{} gets a {} shoved up their ass'.format(member.mention, ctx.invoked_with))
            elif ctx.invoked_with in ['whale']:
                await ctx.send('{} gets smushed by a giant {}'.format(member.mention, ctx.invoked_with))
        logging.info('Done trouting')

    # Owner only commands

    @commands.command()
    @commands.is_owner()
    async def smite(self, ctx: commands.Context, member: discord.Member):
        logging.info('Smite {}'.format(member))
        await ctx.message.delete()
        await ctx.invoke(self.disobedience, member, 'it was the way of the Steins;Gate')

    @commands.command()
    @commands.is_owner()
    async def disobedience(self, ctx: commands.Context, member: discord.Member, reason: str):
        await ctx.send('{} smites {} for {}'.format(self._bot.user.mention, member.mention, reason))

    # Listeners

    @commands.Cog.listener()
    async def on_message(self, message: discord.Message):
        logging.info('Author: {}; Content: {}'.format(message.author, message.content))
        # Ignore anything from a bot
        if message.author.bot:
            return

        channel = message.channel
        # Get mad
        if message.mention_everyone:
            file_list = os.listdir(self._res_path)
            selected_reaction = random.choice(file_list)
            await message.author.add_roles(self._autism)
            condemn = '{} joins the {} gang for tagging too many people'.format( \
		message.author.mention, self._autism.mention)
            await channel.send(content=condemn, file=discord.File(self._res_path + selected_reaction))

    # Helper methods
    def _spongecaseify(self, message):
        response_words = []
        for word in message.split(' '):
            if not self._spongebob_regex.search(word):
                spongecased_word = self._spongecase_word(word)
                while len(word) > 1 and (spongecased_word.islower() or spongecased_word.isupper()):
                    spongecased_word = self._spongecase_word(word)
                response_words.append(spongecased_word)
            else:
                response_words.append(word)
        return ' '.join(response_words)

    def _spongecase_word(self, word):
        spongecased_word = ''
        wlen = len(word)
        count = wlen // 2
        for i in range(wlen):
            if random.random() < count / (wlen - i):
                spongecased_word += word[i].lower()
                count -= 1
            else:
                spongecased_word += word[i].upper()
        return spongecased_word

def setup(bot: commands.Bot):
    logging.info('Setting up Misc extension')
    bot.add_cog(Misc(bot))
    logging.info('Done setting up Misc extension')
<commit_msg>changed message<commit_after>import discord
from discord.ext import commands

import os, random, re, typing, traceback, logging

class Misc(commands.Cog):

    def __init__(self, bot: commands.Bot):
        self._bot = bot
        self._res_path = 'res/'
        self._spongebob_regex = re.compile(r'<@!?(\d+)>|<@&(\d+)>|<#(\d+)>')

    @commands.Cog.listener()
    async def on_command_error(self, ctx: commands.Context, error: discord.DiscordException):
        logging.debug('Misc error by {}: {}'.format(ctx.author, error))
        ignored = (commands.CommandNotFound)
        error = getattr(error, 'original', error)

        if isinstance(error, ignored):
            return

        if await self._bot.is_owner(ctx.author):
            traceback.print_exc()
            await ctx.send('You messed up, but I forgive you {}'.format(ctx.author.mention))
            return

        if isinstance(error, commands.NotOwner):
            await ctx.invoke(self.disobedience, ctx.author, 'treason with the power of a trillion suns')
        elif isinstance(error, commands.CommandOnCooldown):
            await ctx.invoke(self.disobedience, ctx.author, 'spamming a command')
        elif isinstance(error, commands.UserInputError):
            await ctx.invoke(self.disobedience, ctx.author, 'incompetence')
        else:
            logging.error('Something fatal ocurred')

    @commands.command()
    async def spongecase(self,
                   ctx: commands.Context,
                   member: typing.Optional[discord.Member]=None,
                   distance: typing.Optional[int]=0,
                   *,
                   message=None):
        logging.info('Spongecase {} {} {}'.format(member, distance, message))
        if message is not None:
            spongecased_message = self._spongecaseify(message)

            spongecased_being = member if member is not None else ctx.author
            await ctx.send('{}: {}'.format(spongecased_being.mention, self._spongecaseify(message)))
        elif member is not None:
            await ctx.invoke(self.spongecase_last_message, member, distance)
        else:
            await ctx.invoke(self.disobedience, ctx.author, 'incompetence')
        logging.info('Done spongecase')

    @commands.command(hidden=True)
    async def spongecase_last_message(self, ctx: commands.Context, member: discord.Member, distance: int):
        message_count = 0
        async for message in ctx.channel.history(limit=200):
            if message.author == member:
                if message_count >= distance:
                    await ctx.invoke(self.spongecase, member=member, message=message.content)
                    break
                else:
                    message_count += 1
        else:
            await ctx.invoke(self.disobedience, ctx.author, 'incompetence')

    @commands.command(aliases=['dildo', 'whale'])
    async def trout(self, ctx: commands.Context, member: discord.Member):
        logging.info('Trout {} by {}'.format(member, ctx.author))
        await ctx.message.delete()
        if await self._bot.is_owner(member) or member.bot:
            await ctx.invoke(self.disobedience, member, 'disobedience')
        else:
            if ctx.invoked_with in ['trout']:
                await ctx.send('{} gets slapped in the face with a {}'.format(member.mention, ctx.invoked_with))
            elif ctx.invoked_with in ['dildo']:
                await ctx.send('{} gets a {} shoved up their ass'.format(member.mention, ctx.invoked_with))
            elif ctx.invoked_with in ['whale']:
                await ctx.send('{} gets smushed by a giant {}'.format(member.mention, ctx.invoked_with))
        logging.info('Done trouting')

    # Owner only commands

    @commands.command()
    @commands.is_owner()
    async def smite(self, ctx: commands.Context, member: discord.Member):
        logging.info('Smite {}'.format(member))
        await ctx.message.delete()
        await ctx.invoke(self.disobedience, member, 'it was the way of the Steins;Gate')

    @commands.command()
    @commands.is_owner()
    async def disobedience(self, ctx: commands.Context, member: discord.Member, reason: str):
        await ctx.send('{} smites {} for {}'.format(self._bot.user.mention, member.mention, reason))

    # Listeners

    @commands.Cog.listener()
    async def on_message(self, message: discord.Message):
        logging.info('Author: {}; Content: {}'.format(message.author, message.content))
        # Ignore anything from a bot
        if message.author.bot:
            return

        channel = message.channel
        # Get mad
        if message.mention_everyone:
            file_list = os.listdir(self._res_path)
            selected_reaction = random.choice(file_list)
            autism = message.guild.get_role(557816089296502784)
            await message.author.add_roles(autism)
            await channel.send(content=condemn, file=discord.File(self._res_path + selected_reaction))
            condemn = '{} joins the {} gang for tagging too many people'.format( \
                    message.author.mention, autism.mention)

    # Helper methods
    def _spongecaseify(self, message):
        response_words = []
        for word in message.split(' '):
            if not self._spongebob_regex.search(word):
                spongecased_word = self._spongecase_word(word)
                while len(word) > 1 and (spongecased_word.islower() or spongecased_word.isupper()):
                    spongecased_word = self._spongecase_word(word)
                response_words.append(spongecased_word)
            else:
                response_words.append(word)
        return ' '.join(response_words)

    def _spongecase_word(self, word):
        spongecased_word = ''
        wlen = len(word)
        count = wlen // 2
        for i in range(wlen):
            if random.random() < count / (wlen - i):
                spongecased_word += word[i].lower()
                count -= 1
            else:
                spongecased_word += word[i].upper()
        return spongecased_word

def setup(bot: commands.Bot):
    logging.info('Setting up Misc extension')
    bot.add_cog(Misc(bot))
    logging.info('Done setting up Misc extension')
<|endoftext|>


<commit_before># select = map, groupBy = itertools.groupby
from types import GeneratorType
from itertools import zip_longest
from math import inf

class DuplicitValueExc(Exception):
    """
    Exception which means that there are multiple items which this query
    selected but it should return only one
    """

class NoValueExc(Exception):
    """
    Exception which means that query did not selected any item
    """

def distinctBy(iterable, fn):
    """
    uniq operation with key selector
    """
    s = set()
    for i in iterable:
        r = fn(i)
        if r not in s:
            s.add(r)
            yield i

def single(iterable, fn):
    """
    Get value from iterable where fn(item) and check
    if there is not fn(other item)

    :raise DuplicitValueExc: when there are multiple items satisfying fn()
    :raise NoValueExc: when no value satisfying fn(item) found
    """
    found = False
    ret = None

    for i in iterable:
        if fn(i):
            if found:
                raise DuplicitValueExc(i)
            found = True
            ret = i

    if not found:
        raise NoValueExc()

    return ret

def arr_any(iterable, fn):
    """
    :return: True if fn(item) for any item else False
    """
    for item in iterable:
        if fn(item):
            return True
    return False

def arr_all(iterable, fn):
    """
    :return: True if fn(item) for all items in interable or iterable
        is empty else False
    """
    for item in iterable:
        if not fn(item):
            return False
    return True

def take(iterrable, howMay):
    """
    :return: generator of first n items from iterrable
    """
    assert howMay >= 0

    if not howMay:
        return

    last = howMay - 1
    for i, item in enumerate(iterrable):
        yield item
        if i == last:
            return

def where(iterable, fn):
    """
    :return: generator of items from iterable where fn(item)
    """
    for i in iterable:
        if fn(i):
            yield i

def iter_with_last(iterable):
    """
    :return: generator of tuples (isLastFlag, item)
    """
    # Ensure it's an iterator and get the first field
    iterable = iter(iterable)
    prev = next(iterable)
    for item in iterable:
        # Lag by one item so I know I'm not at the end
        yield False, prev
        prev = item
    # Last item
    yield True, prev

def groupedby(collection, fn):
    """
    same like itertools.groupby

    :note: This function does not needs initial sorting like itertools.groupby

    :attention: Order of pairs is not deterministic.
    """
    d = {}
    for item in collection:
        k = fn(item)
        try:
            arr = d[k]
        except KeyError:
            arr = []
            d[k] = arr
        arr.append(item)

    yield from d.items()

def flatten(iterables, level=inf):
    """
    Flatten nested lists, tuples, generators and maps

    :param level: maximum depth of flattening
    """
    if level >= 0 and isinstance(iterables, (list, tuple, GeneratorType,
                                             map, zip)):
        level -= 1
        for i in iterables:
            yield from flatten(i, level=level)
    else:
        yield iterables

def grouper(n, iterable, padvalue=None):
    """grouper(3, 'abcdefg', 'x') -->
       ('a','b','c'), ('d','e','f'), ('g','x','x')
    """
    return zip_longest(*[iter(iterable)] * n, fillvalue=padvalue)

def areSetsIntersets(setA, setB):
    """
    Check if intersection of sets is not empty
    """
    return any(x in setA for x in setB)
<commit_msg>new helper array function balanced_reduce<commit_after># select = map, groupBy = itertools.groupby
from types import GeneratorType
from itertools import zip_longest
from math import inf

class DuplicitValueExc(Exception):
    """
    Exception which means that there are multiple items which this query
    selected but it should return only one
    """

class NoValueExc(Exception):
    """
    Exception which means that query did not selected any item
    """

def distinctBy(iterable, fn):
    """
    uniq operation with key selector
    """
    s = set()
    for i in iterable:
        r = fn(i)
        if r not in s:
            s.add(r)
            yield i

def single(iterable, fn):
    """
    Get value from iterable where fn(item) and check
    if there is not fn(other item)

    :raise DuplicitValueExc: when there are multiple items satisfying fn()
    :raise NoValueExc: when no value satisfying fn(item) found
    """
    found = False
    ret = None

    for i in iterable:
        if fn(i):
            if found:
                raise DuplicitValueExc(i)
            found = True
            ret = i

    if not found:
        raise NoValueExc()

    return ret

def arr_any(iterable, fn):
    """
    :return: True if fn(item) for any item else False
    """
    for item in iterable:
        if fn(item):
            return True
    return False

def arr_all(iterable, fn):
    """
    :return: True if fn(item) for all items in interable or iterable
        is empty else False
    """
    for item in iterable:
        if not fn(item):
            return False
    return True

def take(iterrable, howMay):
    """
    :return: generator of first n items from iterrable
    """
    assert howMay >= 0

    if not howMay:
        return

    last = howMay - 1
    for i, item in enumerate(iterrable):
        yield item
        if i == last:
            return

def where(iterable, fn):
    """
    :return: generator of items from iterable where fn(item)
    """
    for i in iterable:
        if fn(i):
            yield i

def iter_with_last(iterable):
    """
    :return: generator of tuples (isLastFlag, item)
    """
    # Ensure it's an iterator and get the first field
    iterable = iter(iterable)
    prev = next(iterable)
    for item in iterable:
        # Lag by one item so I know I'm not at the end
        yield False, prev
        prev = item
    # Last item
    yield True, prev

def groupedby(collection, fn):
    """
    same like itertools.groupby

    :note: This function does not needs initial sorting like itertools.groupby

    :attention: Order of pairs is not deterministic.
    """
    d = {}
    for item in collection:
        k = fn(item)
        try:
            arr = d[k]
        except KeyError:
            arr = []
            d[k] = arr
        arr.append(item)

    yield from d.items()

def flatten(iterables, level=inf):
    """
    Flatten nested lists, tuples, generators and maps

    :param level: maximum depth of flattening
    """
    if level >= 0 and isinstance(iterables, (list, tuple, GeneratorType,
                                             map, zip)):
        level -= 1
        for i in iterables:
            yield from flatten(i, level=level)
    else:
        yield iterables

def grouper(n, iterable, padvalue=None):
    """grouper(3, 'abcdefg', 'x') -->
       ('a','b','c'), ('d','e','f'), ('g','x','x')
    """
    return zip_longest(*[iter(iterable)] * n, fillvalue=padvalue)

def areSetsIntersets(setA, setB):
    """
    Check if intersection of sets is not empty
    """
    return any(x in setA for x in setB)

def balanced_reduce(arr, opFn):
    while len(arr) > 1:
        nextArr = []
        for a, b in grouper(2, arr):
            nextArr.append(opFn(a, b))
        arr = nextArr

    return arr[0]
<|endoftext|>