from tinydb import Query, TinyDB

from models.match import Match
from models.round import Round
from models.db_manager_players import Db_manager_player
from utils.transform_date import date_iso2fr

class Db_manager_tournament:
    """Manager for tournament table on database"""

    def __init__(self):
        db = TinyDB('chess_tournament')
        self.tournaments_table = db.table("tournaments")

    def get_all(self):
        """Get all tournament on db only base info

        Return:
            list[Tournament]: list of tournament obj

        """
        from models.tournament import Tournament
        tournaments_obj_list: list[Tournament] = []
        for document in self.tournaments_table:
            tournament_id = document.doc_id
            tournament_obj = self.get_one(tournament_id)
            if tournament_obj:
                tournaments_obj_list.append(tournament_obj)
        return tournaments_obj_list

    def get_one(self, tournament_id):
        """Get one tournament on db only base info

        Args:
            int: tournament id

        Return:
            Tournament: tournament obj

        """

        from models.tournament import Tournament
        document = self.tournaments_table.get(doc_id=tournament_id)
        if document:
            tournament_obj = Tournament(
                document["name"],
                document["place"],
                document["date"],
                document["time_ctrl"],
                document["description"],
                document["round"]
            )
            tournament_obj.set_id(document.doc_id)
            tournament_obj.set_status(document["status"])
            return tournament_obj
        return False

    def _get_players_by_tournament_id(self, tournament_id: int) -> dict:
        """Get players of one tournament

        Args:
            int: tournament id

        Return:
            dict: key = id of player, value = points of the player

        """
        tournament_document = self.tournaments_table.get(doc_id=tournament_id)
        player_dict = {}
        if tournament_document:
            player_dict = tournament_document.get('players')
            if player_dict:
                return player_dict
        return {}

    def get_players_all_tournaments(self) -> set[int]:
        """Get players of all tournaments

        Return:
            set[int]: id of players

        """

        tournaments_obj_list = self.get_all()
        players_set: set[int] = set()
        for tournament_obj in tournaments_obj_list:
            if tournament_obj.get_id:
                players_dict = self._get_players_by_tournament_id(
                    tournament_obj.get_id)
                player_id_list = [int(key) for key in players_dict]
                players_set.update(player_id_list)
        return players_set

    def get_one_from_db(self, tournament_id: int):
        """Get complete obj tournament from db

        Args:
            int: tournament id

        Return:
            Tournament: base info + players + rounds + matchs
        """
        tournament_document = self.tournaments_table.get(doc_id=tournament_id)
        if tournament_document:
            tournament_obj = self.get_one(tournament_id)
            if tournament_obj:
                # Create Players list
                self._create_players_obj_list(tournament_id)
                tournament_players_dict = tournament_document["players"]
                # Extract players_id from key
                players_id: list[int] = [key for key in tournament_players_dict]
                # Extract player_ point with key
                players_points: list[int] = [
                    tournament_players_dict[key] for key in tournament_players_dict
                ]
                for player_id, player_points in zip(players_id, players_points):
                    tournament_obj.add_player_from_db(player_id, player_points)
                # Create rounds and matchs
                round_obj_list = self.get_rounds_by_tournament_id(tournament_id)
                for round_obj in round_obj_list:
                    tournament_obj.add_round_from_db(round_obj)
                return tournament_obj
        return False

    def get_rounds_by_tournament_id(self, tournament_id: int) -> list[Round] | list:
        """Get rounds of a tournament

        Args:
            int: tournament id

        Return:
            list[Round]: list of round obj with matchs

        """
        tournament_document = self.tournaments_table.get(doc_id=tournament_id)
        if tournament_document:
            rounds_db_list = tournament_document["rounds"]
            players_obj_list = self._create_players_obj_list(tournament_id)
            round_obj_list: list[Round] = []
            for round_item in rounds_db_list:
                # Create one round
                # Round is close ?
                if round_item["date_end"] is not None:
                    round_obj = Round.add_round_from_db(
                        round_item["name"],
                        round_item["date_begin"],
                        round_item["date_end"]
                    )
                else:
                    # Round is not close
                    round_obj = Round.add_round_from_db(
                        round_item["name"],
                        round_item["date_begin"]
                    )
                # Create matchs
                for match_db in round_item["matchs"]:
                    birth_date_iso_player_1 = match_db["player_1"]["birth_date"]
                    birth_date_iso_player_2 = match_db["player_2"]["birth_date"]
                    birth_date_fr_player_1 = date_iso2fr(birth_date_iso_player_1)
                    birth_date_fr_player_2 = date_iso2fr(birth_date_iso_player_2)
                    match_db["player_1"]["birth_date"] = birth_date_fr_player_1
                    match_db["player_2"]["birth_date"] = birth_date_fr_player_2
                    # Find player1 in list
                    player_1 = [
                        player for player in players_obj_list
                        if ((
                            player.get_player["name"]
                        ) == (
                            match_db["player_1"]["name"]
                        )
                        ) and ((
                            player.get_player["surname"]
                        ) == (
                            match_db["player_1"]["surname"]
                        )
                        ) and ((
                            player.get_player["birth_date"]
                        ) == (
                            match_db["player_1"]["birth_date"]
                        ))]
                    score_player_1 = match_db["score_player_1"]
                    player_1 = player_1[0]
                    # Find player2 in list
                    player_2 = [
                        player for player in players_obj_list
                        if ((
                            player.get_player["name"]
                        ) == (
                            match_db["player_2"]["name"]
                        )
                        ) and ((
                            player.get_player["surname"]
                        ) == (
                            match_db["player_2"]["surname"]
                        )
                        ) and ((
                            player.get_player["birth_date"]
                        ) == (
                            match_db["player_2"]["birth_date"]
                        ))]
                    score_player_2 = match_db["score_player_2"]
                    player_2 = player_2[0]
                    # Create one match
                    match_obj = Match(player_1,
                                      player_2,
                                      score_player_1,
                                      score_player_2
                                      )
                    round_obj.add_match(match_obj)
                round_obj_list.append(round_obj)
            return round_obj_list
        return []

    def update_players_by_tournament_id(self, tournament):
        """Update players dict of one tournament on db

        Args:
            str: name of tournament
            str: date of tournament
            dict: key = id of player, value = points of the player

        """

        from models.tournament import Tournament
        tournament_obj: Tournament = tournament
        tournament_id = tournament_obj.get_id
        tournament_players = tournament_obj.get_players
        if tournament_id:
            self.tournaments_table.update(
                {"players": tournament_players}, doc_ids=[tournament_id])

    def update_round_quantity_by_tournament_id(self, tournament):
        """Update round quantity  by tournament id

        Args:
            tournament_obj(Tournament): Current tournament

        """
        from models.tournament import Tournament
        tournament_obj: Tournament = tournament
        tournament_id = tournament_obj.get_id
        tournament_round_quantity = tournament_obj.get_round
        if tournament_id:
            self.tournaments_table.update(
                {"round": tournament_round_quantity}, doc_ids=[tournament_id])

    def update_status_by_tournament_id(self, tournament):
        """Update tournament status  by tournament id

        Args:
            tournament_obj(Tournament): Current tournament

        """
        from models.tournament import Tournament
        tournament_obj: Tournament = tournament
        tournament_id = tournament_obj.get_id
        tournament_status = tournament_obj.get_status
        if tournament_id:
            self.tournaments_table.update(
                {"status": tournament_status}, doc_ids=[tournament_id])

    def add_one(self, tournament) -> bool | int:
        """Add a tournament base info on db

        Args:
            Tournament: tournament obj

        Return:
            bool | int: True if succes, tournament id if already exist

        """

        from models.tournament import Tournament
        tournament_obj: Tournament = tournament
        tournament_dict = tournament_obj.get_tournament
        tournament = Query()
        # tournament exist ?
        if not self.tournaments_table.search(
                (
                    tournament.name == tournament_dict["name"]
                ) & (
                    tournament.date == tournament_dict["date"]
                )):
            # Create tournament in db and get id
            tournament_id = self.tournaments_table.insert(tournament_dict)
            tournament_obj.set_id(tournament_id)
            return True
        else:
            # Tournament already exist, find is id and return it
            tournament_document = self.tournaments_table.get(
                (
                    tournament.name == tournament_dict["name"]
                ) & (
                    tournament.date == tournament_dict["date"]
                )
            )
            if tournament_document:
                tournament_id = tournament_document.doc_id
                return tournament_id
        # This never append
        return False

    def update_rounds_by_tournament_id(self, tournament):
        """Update rounds of one tournament on db

        Args:
            str: name of tournament
            str: date of tournament
            list[Round]: list of round obj to update

        """
        from models.tournament import Tournament
        tournament_obj: Tournament = tournament
        tournament_id = tournament_obj.get_id
        if tournament_id:
            tournament_rounds = tournament_obj.get_rounds
            # Build rounds infos
            rounds_list = []
            for round in tournament_rounds:
                round_to_add = {"name": round.get_name}
                round_to_add["date_begin"] = round.get_begin
                if round.get_end is not None:
                    round_to_add["date_end"] = round.get_end
                # Build matchs infos
                matchs = []
                for match in round.get_matchs:
                    match_to_add = {
                        "player_1": match.get_players[0].get_player,
                        "player_2": match.get_players[1].get_player,
                        "score_player_1": match.get_scores[0],
                        "score_player_2": match.get_scores[1]}
                    matchs.append(match_to_add)
                round_to_add.update({"matchs": matchs})
                rounds_list.append(round_to_add)
            # Update database
            self.tournaments_table.update(
                {"rounds": rounds_list}, doc_ids=[tournament_id])

    def _create_players_obj_list(self, tournament_id):
        """Create a list of player obj of a tournament

        Args:
            int: tournament id

        Return:
            list[Player]: list of player obj

        """
        from models.player import Player
        manager_player_obj = Db_manager_player()
        players_obj_list: list[Player] = []
        tournament_document = self.tournaments_table.get(doc_id=tournament_id)
        if tournament_document:
            tournament_players_dict = tournament_document["players"]
            # Extract players_id from key
            players_id: list[int] = [key for key in tournament_players_dict]
            for player_id in players_id:
                # Find data of one player
                player_obj = manager_player_obj.get_by_id(player_id)
                if player_obj:
                    player_dict = player_obj.get_player
                    # Create one player
                    player_obj_to_add: Player = Player.add_player_from_db(
                        player_dict["name"],
                        player_dict["surname"],
                        player_dict["birth_date"],
                        player_dict["gender"],
                        player_dict["classification"],
                        player_id)
                    # Add Player to Players for this tournament
                    players_obj_list.append(player_obj_to_add)
            return players_obj_list
        return[]


import tensorflow as tf

def Conv_layer(names, input, w_shape, b_shape, strid):
    with tf.variable_scope(names) as scope:
        weights = tf.Variable(tf.truncated_normal(shape = w_shape, stddev = 1.0, dtype = tf.float32),
                              name = 'weights_{}'.format(names), dtype = tf.float32)

        biases = tf.Variable(tf.constant(value = 0.1, dtype = tf.float32, shape = b_shape),
                             name='biases_{}'.format(names), dtype = tf.float32)

        conv = tf.nn.conv2d(input, weights, strides = [1, strid[0], strid[1], 1], padding = 'SAME')
        # print(strid)
        conv = tf.nn.bias_add(conv, biases)
        conv_out = tf.nn.relu(conv, name = 'relu_{}'.format(names))

        # print("---------names:{}".format(conv_out))
        return conv_out

def Max_pool_lrn(names, input, ksize, is_lrn):
    with tf.variable_scope(names) as scope:
        Max_pool_out = tf.nn.max_pool(input, ksize = ksize, strides = [1, 2, 2, 1], padding = 'SAME', name = 'max_pool_{}'.format(names))
        if is_lrn:
            Max_pool_out = tf.nn.lrn(Max_pool_out, depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name = 'lrn_{}'.format(names))
            # print("use lrn operation")
    return Max_pool_out

def Dropout_layer(names, input, drop_rate):
    with tf.variable_scope(names) as scope:
        #drop_out =local3
        drop_out = tf.nn.dropout(input, drop_rate)
    return drop_out

def local_layer(names, input, w_shape, b_shape):
    with tf.variable_scope(names) as scope:
        weights = tf.Variable(tf.truncated_normal(shape = w_shape, stddev=0.005, dtype = tf.float32),
                              name = 'weights_{}'.format(names), dtype = tf.float32)

        biases = tf.Variable(tf.constant(value = 0.1, dtype = tf.float32, shape = b_shape),
                             name='biases_{}'.format(names), dtype=tf.float32)

        local = tf.nn.relu(tf.matmul(input, weights) + biases, name ='local_{}'.format(names))
    return local

def inference(images, batch_size, n_classes):#,drop_rate

    conv1 = Conv_layer(names = 'conv_block1', input = images , w_shape = [3, 3, 3, 64], b_shape = [64], strid = [1, 1])
    conv2 = Conv_layer(names = 'conv_block2', input = conv1 , w_shape = [3, 3, 64, 64], b_shape = [64], strid = [1, 1])
    pool_1 = Max_pool_lrn(names = 'pooling1', input = conv2 , ksize = [1, 2, 2, 1], is_lrn = True)
    print('pool_1',pool_1.shape) #(?, 112, 112, 64)
    conv3 = Conv_layer(names = 'conv_block3', input = pool_1 , w_shape = [3, 3, 64, 128], b_shape = [128], strid = [1, 1])
    conv4 = Conv_layer(names = 'conv_block4', input = conv3 , w_shape = [3, 3, 128, 128], b_shape = [128], strid = [1, 1])
    pool_2 = Max_pool_lrn(names = 'pooling2', input = conv4 , ksize = [1, 2, 2, 1], is_lrn = False)
    print('pool_2',pool_2.shape) #(?, 56, 56, 128)
    conv5 = Conv_layer(names = 'conv_block5', input = pool_2 , w_shape = [3, 3, 128, 256], b_shape = [256], strid = [1, 1])
    conv6 = Conv_layer(names = 'conv_block6', input = conv5 , w_shape = [3, 3, 256, 256], b_shape = [256], strid = [1, 1])
    conv7 = Conv_layer(names = 'conv_block7', input = conv6 , w_shape = [3, 3, 256, 256], b_shape = [256], strid = [1, 1])
    pool_3 = Max_pool_lrn(names = 'pooling3', input = conv7 , ksize = [1, 2, 2, 1], is_lrn = False)
    print('pool_3',pool_3.shape) #(?, 28, 28, 256)
    conv8 = Conv_layer(names = 'conv_block8', input = pool_3 , w_shape = [3, 3, 256, 512], b_shape = [512], strid = [1, 1])
    conv9 = Conv_layer(names = 'conv_block9', input = conv8 , w_shape = [3, 3, 512, 512], b_shape = [512], strid = [1, 1])
    conv10 = Conv_layer(names = 'conv_block10', input = conv9 , w_shape = [3, 3, 512, 512], b_shape = [512], strid = [1, 1])
    pool_4 = Max_pool_lrn(names = 'pooling4', input = conv10 , ksize = [1, 2, 2, 1], is_lrn = False)
    print('pool_4',pool_4.shape) #(?, 14, 14, 512)
    conv11 = Conv_layer(names = 'conv_block11', input = pool_4 , w_shape = [3, 3, 512, 512], b_shape = [512], strid = [1, 1])
    conv12 = Conv_layer(names = 'conv_block12', input = conv11 , w_shape = [3, 3, 512, 512], b_shape = [512], strid = [1, 1])
    conv13 = Conv_layer(names = 'conv_block13', input = conv12 , w_shape = [3, 3, 512, 64], b_shape = [64], strid = [1, 1])
    pool_5 = Max_pool_lrn(names = 'pooling5', input = conv13 , ksize = [1, 2, 2, 1], is_lrn = False)
    print('pool_5',pool_5.shape) #(?, 7, 7, 64)

    #reshape = tf.reshape(pool_5, shape=[batch_size, -1]) #(128, ?)
    shape = pool_5.get_shape().as_list()
    print('shape',shape)#
    dim = 1
    for i in range(1,len(shape)):
      dim*=shape[i]
    pool_5reshape = tf.reshape(pool_5, [-1, dim])
    dim = pool_5reshape.get_shape()[1].value
    print('dim',dim) #None
    local_1 = local_layer(names = 'local1_scope', input = pool_5reshape , w_shape = [dim, 1024], b_shape = [1024])
    print('local_1',local_1.shape)
    local_2 = local_layer(names = 'local2_scope', input = local_1 , w_shape = [1024, 1024], b_shape = [1024])
    print('local_2',local_2.shape)

    with tf.variable_scope('softmax_linear') as scope:
        weights = tf.Variable(tf.truncated_normal(shape=[1024, n_classes], stddev=0.005, dtype=tf.float32),
                              name='softmax_linear', dtype=tf.float32)

        biases = tf.Variable(tf.constant(value=0.1, dtype=tf.float32, shape=[n_classes]),
                             name='biases', dtype=tf.float32)

        softmax_linear = tf.add(tf.matmul(local_2, weights), biases, name='softmax_linear')
        # print("---------softmax_linear:{}".format(softmax_linear))

    return softmax_linear

def losses(logits, labels):
    with tf.variable_scope('loss') as scope:
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=labels,
                                                                       name='xentropy_per_example')
        # print("\ncross_entropy:{},cross_entropy.shape:{}".format(cross_entropy,cross_entropy.shape))
        # print("---------cross_entropy:{}".format(cross_entropy))
        loss = tf.reduce_mean(cross_entropy, name='loss')
        tf.summary.scalar(scope.name + '/loss', loss)
    return loss

def trainning(loss, learning_rate):
    with tf.name_scope('optimizer'):
        optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
        global_step = tf.Variable(0, name='global_step', trainable=False)
        train_op = optimizer.minimize(loss, global_step=global_step)
    return train_op

def evaluation(logits, labels):
    with tf.variable_scope('accuracy') as scope:
        correct = tf.nn.in_top_k(logits, labels, 1)
        correct = tf.cast(correct, tf.float16)
        accuracy = tf.reduce_mean(correct)
        tf.summary.scalar(scope.name + '/accuracy', accuracy)
    return accuracy


from python.lib.testcase import KphpServerAutoTestCase

class TestSimpleScenarioExample(KphpServerAutoTestCase):
    @classmethod
    def extra_class_setup(cls):
        cls.kphp_server.update_options({
            "--define": "hello=world"
        })

    def test_master_process_log(self):
        self.kphp_server.restart()
        self.kphp_server.assert_log(["master"], "Can't find master process starting message")

    def test_uptime_stat(self):
        self.kphp_server.assert_stats({"kphp_server.uptime": self.cmpGe(1)})

    def test_send_request_check_log_and_stat(self):
        initial_stats = self.kphp_server.get_stats()

        resp = self.kphp_server.http_get()
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.text, "Hello world!")

        self.kphp_server.assert_log(["worked"], "Can't find worker process request message")
        self.kphp_server.assert_stats({
            "kphp_server.workers_general_requests_total_incoming_queries": self.cmpGe(1)
        }, initial_stats=initial_stats)
        self.assertKphpNoTerminatedRequests()

    def test_define(self):
        resp = self.kphp_server.http_get("/ini_get?hello")
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.text, "world")


import asyncio
from functools import wraps

import pytest

from pnq._itertools import AsyncMap, DebugPath, Lazy, Map, Sleep
from pnq._itertools.core import IterType, Query, QueryNormal, QuerySyncToAsync

def async_test(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        async def main():
            return await func(*args, **kwargs)

        return asyncio.run(main())

    return wrapper

async def aiter(iterable=[]):
    for i in iterable:
        yield i

async def create_aiter():
    yield 4
    yield 5
    yield 6

async def list_async(aiter):
    return [x async for x in aiter]

def test_iter_type():
    assert not IterType.IMPOSSIBLE
    assert IterType.NORMAL
    assert IterType.ASYNC
    assert IterType.BOTH

    assert (IterType.NORMAL & IterType.BOTH) == IterType.NORMAL
    assert (IterType.ASYNC & IterType.BOTH) == IterType.ASYNC
    assert (IterType.BOTH & IterType.BOTH) == IterType.BOTH

    assert (IterType.NORMAL & IterType.ASYNC) == IterType.IMPOSSIBLE
    assert (IterType.ASYNC & IterType.ASYNC) == IterType.ASYNC
    assert (IterType.BOTH & IterType.ASYNC) == IterType.ASYNC

    assert (IterType.NORMAL & IterType.NORMAL) == IterType.NORMAL
    assert (IterType.ASYNC & IterType.NORMAL) == IterType.IMPOSSIBLE
    assert (IterType.BOTH & IterType.NORMAL) == IterType.NORMAL

    assert (IterType.NORMAL & IterType.IMPOSSIBLE) == IterType.IMPOSSIBLE
    assert (IterType.ASYNC & IterType.IMPOSSIBLE) == IterType.IMPOSSIBLE
    assert (IterType.BOTH & IterType.IMPOSSIBLE) == IterType.IMPOSSIBLE

class Test010_Async:
    @async_test
    async def test_async(self):
        q1 = Query([1, 2, 3])
        assert list(q1) == [1, 2, 3]

        with pytest.raises(NotImplementedError):
            [x async for x in q1]

        q2 = Query(create_aiter())
        assert [x async for x in q2] == [4, 5, 6]

        with pytest.raises(NotImplementedError):
            list(q2)

    @async_test
    async def test_chain(self):
        q1 = QueryNormal([1, 2, 3])
        assert list(q1) == [1, 2, 3]
        assert [x async for x in q1] == [1, 2, 3]

        q2 = Query(q1)
        assert list(q2) == [1, 2, 3]
        assert [x async for x in q2] == [1, 2, 3]

        q3 = QuerySyncToAsync(q2)
        with pytest.raises(NotImplementedError):
            assert list(q3) == [1, 2, 3]

        assert [x async for x in q3] == [1, 2, 3]

        q4 = Map(q1, lambda x: x * 2)
        assert list(q4) == [2, 4, 6]
        assert [x async for x in q4] == [2, 4, 6]

        q5 = Map(q2, lambda x: x * 2)
        assert list(q5) == [2, 4, 6]
        assert [x async for x in q5] == [2, 4, 6]

        q6 = Map(q3, lambda x: x * 2)
        with pytest.raises(NotImplementedError):
            assert list(q6) == [2, 4, 6]
        assert [x async for x in q6] == [2, 4, 6]

        q7 = Map(q6, lambda x: x * 2)
        with pytest.raises(NotImplementedError):
            assert list(q7) == [4, 8, 12]
        assert [x async for x in q7] == [4, 8, 12]

        async def mul_2(x):
            return x * 2

        q8 = AsyncMap(q7, mul_2)
        with pytest.raises(NotImplementedError):
            assert list(q8) == [8, 16, 24]
        assert [x async for x in q8] == [8, 16, 24]

        q9 = Map(q8, lambda x: x * 2)
        with pytest.raises(NotImplementedError):
            assert list(q9) == [16, 32, 48]
        assert [x async for x in q9] == [16, 32, 48]

    @async_test
    async def test_lazy(self):
        assert Lazy(Query([1, 2, 3]), list)() == [1, 2, 3]
        assert await Lazy(Query(create_aiter()), list_async) == [4, 5, 6]

    @async_test
    async def test_map_debug(self):
        map_five = lambda x: 5  # noqa
        map_ten = lambda x: 10  # noqa
        assert Lazy(DebugPath(Query([1, 2, 3]), map_five, map_ten), list)() == [5, 5, 5]
        assert await Lazy(
            DebugPath(Query(create_aiter()), map_five, map_ten), list_async
        ) == [10, 10, 10]

    @async_test
    async def test_sleep(self):
        assert list(Sleep(Query([1, 2, 3]), 0)) == [1, 2, 3]
        assert [x async for x in Sleep(Query(aiter([1, 2, 3])), 0)] == [1, 2, 3]

    def test_builder(self):
        from pnq._itertools.builder import Builder

        assert list(Builder.query([1, 2, 3])) == [1, 2, 3]
        assert list(Builder.query({1: "a", 2: "b"})) == [(1, "a"), (2, "b")]

    @pytest.mark.xfail
    def test_builder_run(self):  # FIXME: テストが通らない
        import tempfile

        from pnq._itertools.builder import Builder
        from pnq.aio import CancelToken

        async def func_1():
            return 100

        assert Builder.run(func_1) == 100

        with tempfile.TemporaryFile() as f:
            # 引数なしで関数が実行できること
            async def write_1():
                f.write(b"test1")
                f.flush()

            Builder.run(write_1)
            f.seek(0)
            assert f.read() == b"test1"

        with tempfile.TemporaryFile() as f:
            # tokenを受け取ってファイルを書き込めること
            async def write_2(token):
                f.write(b"test2")
                f.flush()
                assert isinstance(token, CancelToken)
                assert token.is_running()

            Builder.run(write_2)
            f.seek(0)
            assert f.read() == b"test2"

    @pytest.mark.skipif(True, reason="CI/CDで失敗するためスキップ")
    @pytest.mark.slow
    def test_builder_run_signal(self):
        import signal
        import subprocess
        import time
        from functools import partial
        from pathlib import Path

        sigtest = Path(__file__).absolute().parent / "__signal_test"

        popen = partial(
            subprocess.Popen, stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )

        p = popen(["python", sigtest, "0"])
        outs, errs = p.communicate()
        assert b"" in outs
        assert b"" in outs
        assert p.returncode == 0

        p = popen(["python", sigtest, "1"])
        outs, errs = p.communicate()
        assert b"" in outs
        assert b"" in outs
        assert p.returncode == 0

        # SIGINTを送信した時、強制キャンセルされることを確認
        p = popen(["python", sigtest, "0"])
        time.sleep(0.1)
        p.send_signal(signal.SIGINT)
        outs, errs = p.communicate()
        assert b"SIGINT" in outs
        assert b"forcibly" in outs
        assert b"Task was destroyed" in errs
        assert p.returncode == 1

        # SIGINTを送信した時、強制キャンセルされないことを確認
        p = popen(["python", sigtest, "1"])
        time.sleep(0.1)
        p.send_signal(signal.SIGINT)
        outs, errs = p.communicate()
        assert b"SIGINT" in outs
        assert b"safely shut down" in outs
        assert b"" in errs
        assert p.returncode == 0


from django.conf.urls.defaults import *
from django.conf import settings
from tollgate.frontend.forms import *
from tollgate.frontend.views import *
from django.contrib.auth.decorators import permission_required

# TODO: shuffle these into views.py
from django.views.generic.base import TemplateView

from tollgate.frontend.models import IP4PortForward
from django.contrib.auth.views import password_change
from django.utils.decorators import decorator_from_middleware
from django.core.urlresolvers import get_callable
from tollgate.frontend.common import TollgateMiddleware

ip4portforward_qsd = dict(
	model=IP4PortForward
)

urlpatterns = (
	# login system
	url(
		r'^login/$',
		'login',
		name='login'
	),

	url(
		r'^logout/$',
		'logout',
		name='logout'
	),

	url(
		r'^account/password_change/$',
		password_change,
		dict(post_change_redirect='../..'),
		name='account_password_change'
	),

	# captive portal
	url(
		r'^internet/login/here/$',
		'internet_login_here',
		name='internet-login-here'
	),

	url(
		r'^internet/login/(?P<mac_address>[\dA-Fa-f]{12})/$',
		'internet_login',
		name='internet-login'
	),

	url(
		'^internet/disown/(?P<host_id>\d+)/$',
		'internet_disown',
		name='internet-disown'
	),

	url(
		r'^internet/$',
		'internet',
		name='internet'
	),

	url(
		r'^internet/offline/$',
		'internet_offline',
		name='internet-offline'
	),

	# my devices and quota
	url(
		r'^quota/on/$',
		'quota_on',
		name='quota-on'
	),

	url(
		r'^quota/off/$',
		'quota_off',
		name='quota-off'
	),

	url(
		r'^quota/user-reset/$',
		'quota_user_reset',
		name='quota-user-reset'
	),

	url(
		r'^quota/$',
		'quota',
		name='quota'
	),

	# quota management
	url(
		r'^usage/all/on/$',
		'usage_all_on',
		name='usage-all-on'
	),

	url(
		r'^usage/all/really-on/$',
		'usage_all_really_on',
		name='usage-all-really-on'
	),

	url(
		r'^usage/all/off/$',
		'usage_all_off',
		name='usage-all-off'
	),

	url(
		r'^usage/(?P<aid>\d+)/on/$',
		'usage_on',
		name='usage-on'
	),

	url(
		r'^usage/(?P<aid>\d+)/off/$',
		'usage_off',
		name='usage-off'
	),

	url(
		r'^usage/(?P<aid>\d+)/reset/$',
		'usage_reset',
		name='usage-reset'
	),

	url(
		r'^usage/(?P<aid>\d+)/disable/$',
		'usage_disable',
		name='usage-disable'
	),

	url(
		r'^usage/(?P<aid>\d+)/$',
		'usage_info',
		name='usage-info'
	),

	url(
		r'^usage/$',
		'usage',
		name='usage'
	),

	url(
		r'^usage/sort/heavy$',
		'usage_heavy',
		name='usage-heavy'
	),

	url(
		r'^usage/sort/speed$',
		'usage_speed',
		name='usage-speed'
	),

	url(
		r'^usage/sort/morereset$',
		'usage_morereset',
		name='usage-morereset'
	),

	# computer list
	url(
		r'^pclist/unowned/$',
		'pclist_unowned',
		name='pclist-unowned'
	),

	url(
		r'^pclist/$',
		'pclist',
		name='pclist'
	),

	# captive portal landing page
	url(
		r'^captive_landing/?$',
		'captive_landing',
		name='captive-landing'
	),

	# help pages
	url(
		r'^help/new/$',
		TemplateView.as_view(
			template_name='frontend/help/new.html',
		),
		name='help-new'
	),

	url(
		r'^help/api/$',
		TemplateView.as_view(
			template_name='frontend/help/api.html',
		),
		name='help-api'
	),

	url(
		r'^help/source/$',
		TemplateView.as_view(
			template_name='frontend/help/source.html',
		),
		name='source'
	),

	# signin system
	url(
		r'^signin/$',
		'signin1',
		name='signin'
	),

	url(
		r'^signin/create/$',
		'signin2',
		name='signin2'
	),

	url(
		r'^signin/(?P<uid>\d+)/$',
		'signin3',
		name='signin3'
	),

	# port forwarding system
	# TODO: shuffle to views.py
	url(
		r'^ip4portforwards/$',
		permission_required('frontend.can_ip4portforward')(
			IP4PortForwardListView.as_view()
		),
		name='ip4portforward_list'
	),

	url(
		r'^ip4portforwards/force-apply/$',
		permission_required('frontend.can_ip4portforward')(
			ip4portforward_forceapply
		),
		name='ip4portforward_forceapply'
	),

	url(
		r'^ip4portforwards/add/$',
		permission_required('frontend.can_ip4portforward')(
			ip4portforward_create
		),
		name='ip4portforward_add'
	),

	url(
		r'^ip4portforwards/(?P<pk>\d+)/$',
		permission_required('frontend.can_ip4portforward')(
			IP4PortForwardUpdateView.as_view()
		),
		name='ip4portforward_edit'
	),

	url(
		r'^ip4portforwards/(?P<object_id>\d+)/toggle/$',
		permission_required('frontend.can_ip4portforward')(
			ip4portforward_toggle
		),
		name='ip4portforward_toggle'
	),

	url(
		r'^ip4portforwards/(?P<pk>\d+)/delete/$',
		permission_required('frontend.can_ip4portforward')(
			IP4PortForwardDeleteView.as_view()
		),
		name='ip4portforward_delete'
	),

	# preferences
	url(
		r'^preferences/theme-change/$',
		'theme_change',
		name='theme-change'
	),

	url(
		r'^$',
		'index',
		name='index'),
)

# Append the TollgateMiddleware to all views
def append_middleware(urlhandler):
	"Append TollgateMiddleware to the views."
	urlhandler.add_prefix('tollgate.frontend.views')
	urlhandler._callback = decorator_from_middleware(
		TollgateMiddleware
	)(urlhandler.callback)

	return urlhandler

# wrap middleware on all of them.
urlpatterns = patterns('',
	*[append_middleware(x) for x in urlpatterns]
)


from functools import cmp_to_key
import subprocess
import sys
import logging
import re
import threading
import time
import os
from urllib.error import HTTPError
import requests
from requests.exceptions import ConnectionError
from urllib3.exceptions import NewConnectionError

from cryptoadvance.specter.specter_error import SpecterError

logger = logging.getLogger(__name__)

class VersionChecker:
    def __init__(self, name="cryptoadvance.specter", specter=None):
        self.name = name

        self.current = self._get_current_version()
        self.latest = "unknown"
        self.upgrade = False
        self.running = False
        self.specter = specter

    def start(self):
        if not self.running:
            self.running = True
            self.thread = threading.Thread(target=self.loop)
            self.thread.daemon = True
            self.thread.start()

    def stop(self):
        logger.info("version checker stopped.")
        self.running = False

    @property
    def info(self):
        info = {"current": self.current, "latest": self.latest, "upgrade": self.upgrade}
        return info

    @property
    def installation_type(self):
        """app or pip"""
        if getattr(sys, "frozen", False):
            return "app"
        else:
            return "pip"

    def loop(self, dt=3600):
        """Checks for updates once per hour"""
        while self.running:
            self.current, self.latest, self.upgrade = self.get_version_info()
            logger.info(
                f"version checked, install_type {self.installation_type} curr: {self.current} latest: {self.latest} ==> upgrade: {self.upgrade}"
            )
            time.sleep(dt)

    def _get_binary_version(self):
        """
        Get binary version: current, latest.
        Fails if version.txt is not present.
        Returns latest = "unknown" if fetch failed.
        """
        current = self._get_current_version()
        latest = "unknown"
        if self.name != "cryptoadvance.specter":
            logger.warning(
                "We're checking here for a different binary than specter-desktop. We're hopefully in a pytest"
            )
        latest = self._get_latest_version_from_github()
        return current, latest

    def _get_pip_version(self):
        """
        returns current, latest
        """
        current = self._get_current_version()
        latest = "unknown"
        try:
            if self.specter:
                requests_session = self.specter.requests_session(force_tor=False)
            else:
                requests_session = requests.Session()

            releases = (
                requests_session.get(f"https://pypi.org/pypi/{self.name}/json")
                .json()["releases"]
                .keys()
            )
            releases = list(releases)
            for i in range(-1, 0 - len(releases), -1):
                # for some stupid reason, rc-versions are BEFORE the real versions
                if not releases[i][:-1].endswith("rc"):
                    latest = releases[i]
                    break
        except (
            HTTPError,
            ConnectionError,
            ConnectionRefusedError,
            NewConnectionError,
        ) as e:
            logger.error(f"{e} while checking for new pypi version")
        except Exception as e:
            logger.exception(e)
            latest = "unknown"
        return current, latest

    def get_version_info(self):
        """
        Returns a triple of the current version
        of the pip-package cryptoadvance.specter and
        the latest version and whether you should upgrade.
        """
        # check if we have version.txt file
        # this is the case for binaries
        current = "unknown"
        latest = "unknown"
        # check binary version
        if self.installation_type == "app":
            current, latest = self._get_binary_version()
        else:
            current, latest = self._get_pip_version()

        # check that both current and latest versions match the pattern
        # vA.B.C or just A.B.C
        # For vA.B.C-preX or something like that we don't show notification
        if re.search(r"v?([\d+]).([\d+]).([\d+])$", current):
            if re.search(r"v?([\d+]).([\d+]).([\d+])$", latest):
                return (
                    current,
                    latest,
                    # check without leading v so v1.2.3 = 1.2.3
                    latest.replace("v", "") != current.replace("v", ""),
                )
        # if current version is not A.B.C - stop periodic checks
        else:
            self.stop()
        return current, latest, False

    def _get_latest_version_from_github(self):
        try:
            if self.specter:
                requests_session = self.specter.requests_session(force_tor=False)
            else:
                requests_session = requests.Session()
            releases = (
                requests_session.get(f"https://pypi.org/pypi/{self.name}/json")
                .json()["releases"]
                .keys()
            )
            latest = sorted(releases, key=cmp_to_key(compare))[0]
        except Exception as e:
            logger.exception(e)
            latest = "unknown"
        return latest

    @classmethod
    def _get_current_version(self):
        """Returns the version found in cryptoadvance.specter._version or "unknown"
        if that doesn't exist
        """
        try:
            from cryptoadvance.specter._version import version
        except ModuleNotFoundError:
            return "unknown"
        return "v" + version

def compare(version1: str, version2: str) -> int:
    """Compares two version strings like v1.5.1 and v1.6.0 and returns
    * 1 : version2 is bigger that version1
    * -1 : version1 is bigger than version2
    * 0 : both are the same
    This is not supporting semver and it doesn't take any postfix (-pre5)
    into account and is therefore a naive implementation
    """
    version1 = _parse_version(version1)
    version2 = _parse_version(version2)

    if version1["major"] > version2["major"]:
        return -1
    elif version1["major"] < version2["major"]:
        return 1
    if version1["minor"] > version2["minor"]:
        return -1
    elif version1["minor"] < version2["minor"]:
        return 1
    if version1["patch"] > version2["patch"]:
        return -1
    elif version1["patch"] < version2["patch"]:
        return 1
    if version1["postfix"] == "" and version2["postfix"] == "":
        return 0
    if version1["postfix"] == "" and version2["postfix"] != "":
        return -1
    if version1["postfix"] != "" and version2["postfix"] == "":
        return 1
    version1["postfix"] = (
        version1["postfix"].replace("-", "").replace("rc", "").replace("pre", "")
    )
    version2["postfix"] = (
        version2["postfix"].replace("-", "").replace("rc", "").replace("pre", "")
    )
    if version1["postfix"] < version2["postfix"]:
        return 1
    if version1["postfix"] > version2["postfix"]:
        return -1
    return 0

def _parse_version(version: str) -> dict:
    """Parses version-strings like v1.5.6-pre5 and returns a dict
    This also parses something like:
    2.0.0rc20.dev0+ga99ede2a.d20230215
    but ignores the stuff behind the postfix (which is good enough for our use cases)
    see also: https://github.com/pypa/setuptools_scm/#default-versioning-scheme
    """
    if version.startswith("0.1.dev") or version.startswith("v0.1.dev"):
        # setuptools_scm creates weird versions if you're somewhere where no tags are available
        # on the .git
        # This is the case in testing-scenarios. I couldn't figure out how to convince
        # setuptools_scm to at least return 0.0.1dev or something like that.
        # Anyway, let's return something, it's not relevant anyway.
        # And the alternative would be yet another dependency like e.g. packaging
        return {
            "major": 0,
            "minor": 1,
            "patch": 0,
            "postfix": "",
        }
    try:

        if version[0] == "v":
            version = version[1:]
        version = version.replace("rc", "-pre")
        version_ar = version.split(".")
        if len(version_ar) == 5 or len(version_ar) == 4:
            version_ar = version_ar[0:3]
        if len(version_ar) != 3:
            raise SpecterError(
                f"version {version} does not have 3 separated digits but {len(version_ar)}"
            )
        postfix = ""
        if "-" in version_ar[2]:
            postfix = version_ar[2].split("-")[1]
            version_ar[2] = version_ar[2].split("-")[0]
        return {
            "major": int(version_ar[0]),
            "minor": int(version_ar[1]),
            "patch": int(version_ar[2]),
            "postfix": postfix,
        }
    except Exception as e:
        logger.error(f"{str(e)} parsing version {version} ")
        raise e


# 1000-digit Fibonacci number
#
# The Fibonacci sequence is defined by the recurrence relation:
#
# F(n) = F(n−1) + F(n−2), where F(1) = 1 and F(2) = 1.
# Hence the first 12 terms will be:
#
# F(1) = 1
# F(2) = 1
# F(3) = 2
# F(4) = 3
# F(5) = 5
# F(6) = 8
# F(7) = 13
# F(8) = 21
# F(9) = 34
# F(10) = 55
# F(11) = 89
# F(12) = 144
# The 12th term, F(12), is the first term to contain three digits.
#
# What is the index of the first term in the Fibonacci sequence to contain 1000 digits?

import time

def fib(digits):
  (a, b) = 1, 1
  max_num = 10**(digits - 1)
  i = 2
  while b < max_num:
    (a, b) = (b, a + b)
    i += 1
  return i

t0 = time.time()
result = fib(1000)
t1 = time.time()

print(result)
print('time %f' % (t1 - t0))
# 4782
# time 0.000838


import csv

dict_team = dict()
team = None
non_experienced = []
experienced = []

def merge_dicts(*dict_args):

    # Takes to two dictionaries and combines them to one
    result = {}
    for dictionary in dict_args:
        result.update(dictionary)
    return result

def make_dict(ex_players, non_players):
    # Make a dictionary from 6 players; 3 experienced and 3 non experienced players
    first_dict = {ex_players[0]: ", ".join(ex_players) for ex_players in ex_players[:3]}
    second_dict = {non_players[0]: ", ".join(non_players) for non_players in non_players[:3]}

    # Deletes every player from list when added to dictionary
    del ex_players[:3]
    del non_players[:3]

    return first_dict, second_dict

def write_to_file(team, teams, team_name):

    # Takes the name of the right team and write it to the file
    print(list(teams.keys())[team_name], file = f)

    # Write  guardian(s) name(s), player's name, team name to file
    for player in team.values():
        print(player, file = f)

if __name__ == "__main__":

    #Open CSV file and read it
    with open("soccer_players.csv", 'r') as csv_file:
        csv_reader = csv.reader(csv_file)

        for players in csv_reader:

            #Seperate experienced from non_experienced players
            if players[2].lower() == "yes":
                experienced.append(players)
            else:
                non_experienced.append(players)

        #Takes out the list of name, height,... out of the list
        team_order = non_experienced.pop(0)

        sharks, sharks2 = make_dict(experienced,non_experienced)
        team_sharks = merge_dicts(sharks, sharks2)

        raptors, raptors2 = make_dict(experienced, non_experienced)
        team_raptors =  merge_dicts(raptors, raptors2)

        dragons, dragons2 = make_dict(experienced, non_experienced)
        team_dragons =  merge_dicts(dragons, dragons2)

        all_teams = {"Sharks": team_sharks,
        "Raptors": team_raptors,
        "Dragons": team_dragons}

        with open('teams.txt', 'w') as f:

            #Open text file and write to the text file the  team name and players
            for i,team in enumerate(all_teams.values()):
                f.write(str(write_to_file(team, all_teams, i)))
                f.write(str("\n"))


import random
import sys
database = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
         'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

def BatchStringGenerator():
    for i in range(n):
        if a < b:
            c = random.choice(range(a, b))
        else:
            sys.exit('Incorrect min and max string lengths. Try again.')
        r.append(RandomStringGenerator(database))
    return r

a = input('Enter minimum string length: ')
b = input('Enter maximum string length: ')
n = input('How many random strings to generate? ')

print(BatchStringGenerator(int(a), int(b)))


from .max_prob import MaxProb
from .max_uncertainty import Uncertainty
from .mix_checking import MixChecking

# from .auto_mixed_sd import AutoMixedSD
# from .max_prob_with_prioritize_fulltext import MaxProbPrioritizeFulltext
# from .mix_checking_inside import MixCheckingInside
# from .title import Title

def get_query_class(name):
    mapper = {
        "max_prob": MaxProb,
        "uncertainty": Uncertainty,
        "mix_checking": MixChecking,
    }
    return mapper.get(name)


import re
from datetime import datetime
import json
import glob
import os
import pendulum

class EmailFiles:
    @staticmethod
    def get_list_of_files(pattern):
        return glob.glob(pattern)

class ParseShadowBackupEmails:
    active_email_dictionary = {}
    web_page_file = 'sp.html'
    master_email_dictionary = {}
    change_count = 0
    backup_code_1120 = []
    backup_code_1121 = []
    backup_code_unknown = []
    default_threshold = 72
    row_id = 0
    date_format = '%m-%d-%Y %H:%M:%S'
    max_parse_time = 'none'
    min_parse_time = 'none'
    company_count = 0
    table_width = "100%"

    def __init__(self, directory):
        self.dictionary_file = os.getenv("HOME") + '/email_dictionary.json'
        list_of_email_files = self.check_for_shadow_email(EmailFiles.get_list_of_files(directory))
        subjects = self.get_subjects(list_of_email_files)
        split_subjects = self.split_subject(subjects)
        self.build_unique_active_dictionary(split_subjects)
        self.load_master_dictionary()
        self.compare_master_and_active_dictionaries()

    @staticmethod
    def check_for_shadow_email(list_of_files):
        list_of_shadow_emails = []
        for email in list_of_files:
            with open(email) as f:
                if 'ShadowProtectSvc' in f.read():
                    list_of_shadow_emails.append(email)
        return list_of_shadow_emails

    def get_subjects(self, list_of_email_files):
        subjects = []
        for email in list_of_email_files:
            with open(email) as f:
                file_data = f.readlines()
                subjects.append(self.get_match_and_next_line("^Subject:", file_data))
                os.remove(email)
        return subjects

    def rename_web_page(self):
        os.rename(self.web_page_file, "/var/www/html/reports/" + self.web_page_file)

    @staticmethod
    def get_match_and_next_line(pattern, file_data):
        from_date = ''
        for line_number, line in enumerate(file_data):
            if re.search("^From", line) and line_number == 1:
                from_date = "| " + line
            if re.search(pattern, line):
                subject = line.rstrip() + " " + file_data[line_number + 1].rstrip() + " " + from_date.rstrip()
                return subject

    def split_subject(self, subjects):
        split_subjects = []
        for subject in subjects:
            split_subject = subject.split('|')
            split_subjects.append(self.create_dictionary(split_subject))
        return split_subjects

    def create_dictionary(self, split_subject):
        if len(split_subject) == 7:
            subject_dictionary = {
                'server': str(split_subject[0].strip().replace('Subject: ', '')),
                'client': str(split_subject[1].strip()),
                'company': str(split_subject[2].strip()),
                'backup_code': str(self.get_backup_code(split_subject[5].strip())),
                'email_time': self.convert_utc_to_local(str(self.get_email_time(split_subject[-1].strip()))),
                'threshold': self.default_threshold
            }
            return subject_dictionary

    def convert_utc_to_local(self, email_time):
        dt = pendulum.from_format(email_time, 'MMM DD HH:mm:ss YYYY', tz='UTC')
        tz = pendulum.timezone('US/Eastern')
        in_est = tz.convert(dt)
        return in_est.strftime(self.date_format)

    def build_unique_active_dictionary(self, split_subjects):
        split_subjects = list(filter(None.__ne__, split_subjects))
        for subject in split_subjects:
            key = subject['company'] + subject['server'] + subject['client']
            if key not in self.active_email_dictionary:
                self.active_email_dictionary[key] = subject
            elif key in self.active_email_dictionary:
                datetime_object_in_dict = datetime.strptime(self.active_email_dictionary[key]['email_time'],
                                                            self.date_format)
                datetime_object = datetime.strptime(subject['email_time'], self.date_format)
                if datetime_object > datetime_object_in_dict:
                    self.active_email_dictionary[key] = subject
        self.initialize_dictionary()

    def compare_master_and_active_dictionaries(self):
        for key, email_data in self.active_email_dictionary.items():
            if key not in self.master_email_dictionary:
                self.master_email_dictionary[key] = email_data
                self.change_count += 1
            elif key in self.master_email_dictionary:
                datetime_object_in_master_dict = datetime.strptime(self.master_email_dictionary[key]['email_time'],
                                                                   self.date_format)
                datetime_object = datetime.strptime(email_data['email_time'], self.date_format)
                if datetime_object > datetime_object_in_master_dict:
                    if self.master_email_dictionary[key]['threshold'] != email_data['threshold']:
                        email_data['threshold'] = self.master_email_dictionary[key]['threshold']
                    self.master_email_dictionary[key] = email_data
                    self.change_count += 1
        if self.change_count > 0:
            print("Something Change Updating Dictionary on disk")
            self.save_json(self.master_email_dictionary, self.dictionary_file)

    def generate_html_table(self):
        self.sort_master_dictionary_for_web_page()
        table = ''
        table += self.build_html_table_header()
        table += self.build_html_table_data('unknown', self.backup_code_unknown)
        table += self.build_html_table_data('critical', self.backup_code_1121)
        table += self.build_html_table_data('ok', self.backup_code_1120)
        table += self.build_html_table_footer()
        with open(self.web_page_file, "w") as text_file:
            text_file.write(table)

    def build_dashboard(self):
        current_time = pendulum.now('US/Eastern')
        table = ''
        table += "
\n"
        table += "
\n"
        table += " OK 	\n"
        table += " UNKNOWN 	\n"
        table += " CRITICAL 	\n"
        table += " Clients 	\n"
        table += " Companies 	\n"
        table += " First Email 	\n"
        table += " Last Email 	\n"
        table += " Page Generated 	\n"
        table += "
\n"
        table += "
\n"
        table += " " + str(len(self.backup_code_1120)) + "	\n"
        table += " " + str(len(self.backup_code_unknown)) + "	\n"
        table += " " + str(len(self.backup_code_1121)) + "	\n"
        table += " " + str(
            len(self.backup_code_1121) + len(self.backup_code_1120) + len(self.backup_code_unknown)) + "	\n"
        table += " " + str(self.company_count) + "	\n"
        table += " " + self.min_parse_time.strftime(self.date_format) + "	\n"
        table += " " + self.max_parse_time.strftime(self.date_format) + "	\n"
        table += " " + current_time.strftime(self.date_format) + "	\n"
        table += "

\n"
        return table

    def build_html_table_data(self, status, list_of_code):
        table_data = ''
        for data in list_of_code:
            self.row_id += 1
            table_data += self.build_table_row_data(self.row_id, status, data)
        return table_data

    @staticmethod
    def get_row_color(status):
        colors = {'unknown': 'orange', 'ok': 'white', 'critical': 'E64A34'}
        return colors[status]

    def build_table_row_data(self, row_id, status, row):
        table_row = ''
        table_row += "
"
        table_row += "" + str(row_id) + "	"
        table_row += "" + status.upper() + "	"
        table_row += "" + row['company'] + "	"
        table_row += "" + row['server'] + "	"
        table_row += "" + row['client'] + "	"
        table_row += "" + row['email_time'] + "	"
        table_row += "" + row['backup_code'] + "	"
        table_row += "" + str(row['threshold']) + " Hours	"
        table_row += "
\n"
        return table_row

    def build_html_table_header(self):
        header = ['id', 'status', 'company', 'server', 'client', 'last email', 'backup_code', 'threshold']
        table_head = ''
        table_head += "\n"
        table_head += "\n"
        table_head += "<title> Shadow Protect Backup Status </title>\n"
        table_head += "\n"
        table_head += self.build_dashboard()
        table_head += "
\n"
        table_head += "
"
        for column in header:
            table_head += '' + column.upper() + '	'
        table_head += "
\n"
        return table_head

    @staticmethod
    def build_html_table_footer():
        footer = ''
        footer += "
"
        footer += ""
        return footer

    def sort_master_dictionary_for_web_page(self):
        company_list = []
        for key, data in sorted(self.master_email_dictionary.items()):
            company_list.append(data['company'])
            self.get_parse_time(data['email_time'])
            now = pendulum.now('US/Eastern')
            threshold_time = now.subtract(hours=data['threshold'])
            alert_time_formatted = threshold_time.strftime(self.date_format)
            alert_time = datetime.strptime(alert_time_formatted, self.date_format)
            email_time = datetime.strptime(data['email_time'], self.date_format)
            if email_time < alert_time:
                self.backup_code_unknown.append(data)
            elif data['backup_code'] == "1120":
                self.backup_code_1120.append(data)
            elif data['backup_code'] == "1121":
                self.backup_code_1121.append(data)
        self.company_count = len(set(company_list))

    def get_parse_time(self, parse_time):
        if self.max_parse_time == 'none':
            self.max_parse_time = datetime.strptime(parse_time, self.date_format)
        elif datetime.strptime(parse_time, self.date_format) > self.max_parse_time:
            self.max_parse_time = datetime.strptime(parse_time, self.date_format)
        if self.min_parse_time == 'none':
            self.min_parse_time = datetime.strptime(parse_time, self.date_format)
        elif datetime.strptime(parse_time, self.date_format) < self.min_parse_time:
            self.min_parse_time = datetime.strptime(parse_time, self.date_format)

    def load_master_dictionary(self):
        if os.path.isfile(self.dictionary_file):
            self.master_email_dictionary = self.load_json(self.dictionary_file)

    def initialize_dictionary(self):
        if not os.path.isfile(self.dictionary_file):
            print("Initialized Dictionary on Disk")
            try:
                self.save_json(self.active_email_dictionary, self.dictionary_file)
            except (FileNotFoundError, FileExistsError, IOError) as err:
                print(err)

    @staticmethod
    def save_json(data, file_name):
        try:
            with open(file_name, 'w') as fp:
                json.dump(data, fp)
        except (FileNotFoundError, FileExistsError, IOError) as err:
            print(err)

    @staticmethod
    def load_json(file_name):
        try:
            with open(file_name, 'r') as fp:
                return json.load(fp)
        except (FileExistsError, IOError) as err:
            print(err)

    @staticmethod
    def get_backup_code(raw_code):
        backup_code = raw_code.split()
        return backup_code[1].strip("'")

    @staticmethod
    def get_email_time(raw_email_time):
        email_time_list = raw_email_time.split()
        email_time = email_time_list[-4] + ' ' + email_time_list[-3] + ' ' + email_time_list[-2] + ' ' + \
                     email_time_list[-1]
        return email_time


import pygit2

import os
import re
import sys

from argparse import ArgumentParser

cli = ArgumentParser()
subparsers = cli.add_subparsers(dest="subcommand")

def argument(*name_or_flags, **kwargs):
    """Convenience function to properly format arguments to pass to the
    subcommand decorator.
    """
    return (list(name_or_flags), kwargs)

def subcommand(args=[], parent=subparsers):
    """Decorator to define a new subcommand in a sanity-preserving way.
    The function will be stored in the ``func`` variable when the parser
    parses arguments so that it can be called directly like so::
        args = cli.parse_args()
        args.func(args)
    Usage example::
        @subcommand([argument("-d", help="Enable debug mode", action="store_true")])
        def subcommand(args):
            print(args)
    Then on the command line::
        $ python cli.py subcommand -d
    """
    def decorator(func):
        parser = parent.add_parser(func.__name__, description=func.__doc__)
        for arg in args:
            parser.add_argument(*arg[0], **arg[1])
        parser.set_defaults(func=func)
    return decorator

BITCOIN_CHAIN = ["testnet","mainnet", "regtest"]

def get_branches():
    return pygit2.Repository(path=os.getenv('GITDIR')).branches.local

@subcommand([argument("branches", help="Name",action="store_true")])
def branches(args):
    print(list(get_branches()))

@subcommand([argument("context", help="Context")])
def context(args):
    if "::" in args.context:
        cmd = []
        context = args.context.split("::")
        if context[0] in BITCOIN_CHAIN:
            cmd.append(f"export BITCOIN_CHAIN={context[0]};")
        else:
            print(f"echo {context[0]} is an 'Invalid chain'")

        filtered_branches = [branch for branch in get_branches() if context[1] in branch]
        if len(filtered_branches) > 1:
            print(f"echo Found more than one branch matching {context[1]}")

        else:
            cmd.append(f"export BITCOIN_GIT_BRANCH={filtered_branches[0]};")

        print("".join(cmd))

if __name__ == "__main__":
    args = cli.parse_args()
    if args.subcommand is None:
        cli.print_help()
    else:
        args.func(args)


import datetime
import filecmp
import os
import random
import tempfile
import time

import glanceclient.exc
from oslo.config import cfg

from nova import context
from nova import exception
from nova.image import glance
from nova import test
from nova.tests.api.openstack import fakes
from nova.tests.glance import stubs as glance_stubs
from nova.tests import matchers

CONF = cfg.CONF

class NullWriter(object):
    """Used to test ImageService.get which takes a writer object."""

    def write(self, *arg, **kwargs):
        pass

class TestGlanceSerializer(test.TestCase):
    def test_serialize(self):
        metadata = {'name': 'image1',
                    'is_public': True,
                    'foo': 'bar',
                    'properties': {
                        'prop1': 'propvalue1',
                        'mappings': [
                            {'virtual': 'aaa',
                             'device': 'bbb'},
                            {'virtual': 'xxx',
                             'device': 'yyy'}],
                        'block_device_mapping': [
                            {'virtual_device': 'fake',
                             'device_name': '/dev/fake'},
                            {'virtual_device': 'ephemeral0',
                             'device_name': '/dev/fake0'}]}}

        converted_expected = {
            'name': 'image1',
            'is_public': True,
            'foo': 'bar',
            'properties': {
                'prop1': 'propvalue1',
                'mappings':
                '[{"device": "bbb", "virtual": "aaa"}, '
                '{"device": "yyy", "virtual": "xxx"}]',
                'block_device_mapping':
                '[{"virtual_device": "fake", "device_name": "/dev/fake"}, '
                '{"virtual_device": "ephemeral0", '
                '"device_name": "/dev/fake0"}]'}}
        converted = glance._convert_to_string(metadata)
        self.assertEqual(converted, converted_expected)
        self.assertEqual(glance._convert_from_string(converted), metadata)

class TestGlanceImageService(test.TestCase):
    """
    Tests the Glance image service.

    At a high level, the translations involved are:

        1. Glance -> ImageService - This is needed so we can support
           multple ImageServices (Glance, Local, etc)

        2. ImageService -> API - This is needed so we can support multple
           APIs (OpenStack, EC2)

    """
    NOW_GLANCE_OLD_FORMAT = "2010-10-11T10:30:22"
    NOW_GLANCE_FORMAT = "2010-10-11T10:30:22.000000"

    class tzinfo(datetime.tzinfo):
        @staticmethod
        def utcoffset(*args, **kwargs):
            return datetime.timedelta()

    NOW_DATETIME = datetime.datetime(2010, 10, 11, 10, 30, 22, tzinfo=tzinfo())

    def setUp(self):
        super(TestGlanceImageService, self).setUp()
        fakes.stub_out_compute_api_snapshot(self.stubs)

        client = glance_stubs.StubGlanceClient()
        self.service = self._create_image_service(client)
        self.context = context.RequestContext('fake', 'fake', auth_token=True)

    def _create_image_service(self, client):
        def _fake_create_glance_client(context, host, port, use_ssl, version):
            return client

        self.stubs.Set(glance, '_create_glance_client',
                _fake_create_glance_client)

        client_wrapper = glance.GlanceClientWrapper(
                'fake', 'fake_host', 9292)
        return glance.GlanceImageService(client=client_wrapper)

    @staticmethod
    def _make_fixture(**kwargs):
        fixture = {'name': None,
                   'properties': {},
                   'status': None,
                   'is_public': None}
        fixture.update(kwargs)
        return fixture

    def _make_datetime_fixture(self):
        return self._make_fixture(created_at=self.NOW_GLANCE_FORMAT,
                                  updated_at=self.NOW_GLANCE_FORMAT,
                                  deleted_at=self.NOW_GLANCE_FORMAT)

    def test_create_with_instance_id(self):
        # Ensure instance_id is persisted as an image-property.
        fixture = {'name': 'test image',
                   'is_public': False,
                   'properties': {'instance_id': '42', 'user_id': 'fake'}}

        image_id = self.service.create(self.context, fixture)['id']
        image_meta = self.service.show(self.context, image_id)
        expected = {
            'id': image_id,
            'name': 'test image',
            'is_public': False,
            'size': None,
            'min_disk': None,
            'min_ram': None,
            'disk_format': None,
            'container_format': None,
            'checksum': None,
            'created_at': self.NOW_DATETIME,
            'updated_at': self.NOW_DATETIME,
            'deleted_at': None,
            'deleted': None,
            'status': None,
            'properties': {'instance_id': '42', 'user_id': 'fake'},
            'owner': None,
        }
        self.assertThat(image_meta, matchers.DictMatches(expected))

        image_metas = self.service.detail(self.context)
        self.assertThat(image_metas[0], matchers.DictMatches(expected))

    def test_create_without_instance_id(self):
        """
        Ensure we can create an image without having to specify an
        instance_id. Public images are an example of an image not tied to an
        instance.
        """
        fixture = {'name': 'test image', 'is_public': False}
        image_id = self.service.create(self.context, fixture)['id']

        expected = {
            'id': image_id,
            'name': 'test image',
            'is_public': False,
            'size': None,
            'min_disk': None,
            'min_ram': None,
            'disk_format': None,
            'container_format': None,
            'checksum': None,
            'created_at': self.NOW_DATETIME,
            'updated_at': self.NOW_DATETIME,
            'deleted_at': None,
            'deleted': None,
            'status': None,
            'properties': {},
            'owner': None,
        }
        actual = self.service.show(self.context, image_id)
        self.assertThat(actual, matchers.DictMatches(expected))

    def test_create(self):
        fixture = self._make_fixture(name='test image')
        num_images = len(self.service.detail(self.context))
        image_id = self.service.create(self.context, fixture)['id']

        self.assertNotEquals(None, image_id)
        self.assertEquals(num_images + 1,
                          len(self.service.detail(self.context)))

    def test_create_and_show_non_existing_image(self):
        fixture = self._make_fixture(name='test image')
        image_id = self.service.create(self.context, fixture)['id']

        self.assertNotEquals(None, image_id)
        self.assertRaises(exception.ImageNotFound,
                          self.service.show,
                          self.context,
                          'bad image id')

    def test_detail_private_image(self):
        fixture = self._make_fixture(name='test image')
        fixture['is_public'] = False
        properties = {'owner_id': 'proj1'}
        fixture['properties'] = properties

        self.service.create(self.context, fixture)['id']

        proj = self.context.project_id
        self.context.project_id = 'proj1'

        image_metas = self.service.detail(self.context)

        self.context.project_id = proj

        self.assertEqual(1, len(image_metas))
        self.assertEqual(image_metas[0]['name'], 'test image')
        self.assertEqual(image_metas[0]['is_public'], False)

    def test_detail_marker(self):
        fixtures = []
        ids = []
        for i in range(10):
            fixture = self._make_fixture(name='TestImage %d' % (i))
            fixtures.append(fixture)
            ids.append(self.service.create(self.context, fixture)['id'])

        image_metas = self.service.detail(self.context, marker=ids[1])
        self.assertEquals(len(image_metas), 8)
        i = 2
        for meta in image_metas:
            expected = {
                'id': ids[i],
                'status': None,
                'is_public': None,
                'name': 'TestImage %d' % (i),
                'properties': {},
                'size': None,
                'min_disk': None,
                'min_ram': None,
                'disk_format': None,
                'container_format': None,
                'checksum': None,
                'created_at': self.NOW_DATETIME,
                'updated_at': self.NOW_DATETIME,
                'deleted_at': None,
                'deleted': None,
                'owner': None,
            }

            self.assertThat(meta, matchers.DictMatches(expected))
            i = i + 1

    def test_detail_limit(self):
        fixtures = []
        ids = []
        for i in range(10):
            fixture = self._make_fixture(name='TestImage %d' % (i))
            fixtures.append(fixture)
            ids.append(self.service.create(self.context, fixture)['id'])

        image_metas = self.service.detail(self.context, limit=5)
        self.assertEquals(len(image_metas), 5)

    def test_detail_default_limit(self):
        fixtures = []
        ids = []
        for i in range(10):
            fixture = self._make_fixture(name='TestImage %d' % (i))
            fixtures.append(fixture)
            ids.append(self.service.create(self.context, fixture)['id'])

        image_metas = self.service.detail(self.context)
        for i, meta in enumerate(image_metas):
            self.assertEqual(meta['name'], 'TestImage %d' % (i))

    def test_detail_marker_and_limit(self):
        fixtures = []
        ids = []
        for i in range(10):
            fixture = self._make_fixture(name='TestImage %d' % (i))
            fixtures.append(fixture)
            ids.append(self.service.create(self.context, fixture)['id'])

        image_metas = self.service.detail(self.context, marker=ids[3], limit=5)
        self.assertEquals(len(image_metas), 5)
        i = 4
        for meta in image_metas:
            expected = {
                'id': ids[i],
                'status': None,
                'is_public': None,
                'name': 'TestImage %d' % (i),
                'properties': {},
                'size': None,
                'min_disk': None,
                'min_ram': None,
                'disk_format': None,
                'container_format': None,
                'checksum': None,
                'created_at': self.NOW_DATETIME,
                'updated_at': self.NOW_DATETIME,
                'deleted_at': None,
                'deleted': None,
                'owner': None,
            }
            self.assertThat(meta, matchers.DictMatches(expected))
            i = i + 1

    def test_detail_invalid_marker(self):
        fixtures = []
        ids = []
        for i in range(10):
            fixture = self._make_fixture(name='TestImage %d' % (i))
            fixtures.append(fixture)
            ids.append(self.service.create(self.context, fixture)['id'])

        self.assertRaises(exception.Invalid, self.service.detail,
                          self.context, marker='invalidmarker')

    def test_update(self):
        fixture = self._make_fixture(name='test image')
        image = self.service.create(self.context, fixture)
        image_id = image['id']
        fixture['name'] = 'new image name'
        self.service.update(self.context, image_id, fixture)

        new_image_data = self.service.show(self.context, image_id)
        self.assertEquals('new image name', new_image_data['name'])

    def test_delete(self):
        fixture1 = self._make_fixture(name='test image 1')
        fixture2 = self._make_fixture(name='test image 2')
        fixtures = [fixture1, fixture2]

        num_images = len(self.service.detail(self.context))
        self.assertEquals(0, num_images)

        ids = []
        for fixture in fixtures:
            new_id = self.service.create(self.context, fixture)['id']
            ids.append(new_id)

        num_images = len(self.service.detail(self.context))
        self.assertEquals(2, num_images)

        self.service.delete(self.context, ids[0])
        # When you delete an image from glance, it sets the status to DELETED
        # and doesn't actually remove the image.

        # Check the image is still there.
        num_images = len(self.service.detail(self.context))
        self.assertEquals(2, num_images)

        # Check the image is marked as deleted.
        num_images = reduce(lambda x, y: x + (0 if y['deleted'] else 1),
                            self.service.detail(self.context), 0)
        self.assertEquals(1, num_images)

    def test_show_passes_through_to_client(self):
        fixture = self._make_fixture(name='image1', is_public=True)
        image_id = self.service.create(self.context, fixture)['id']

        image_meta = self.service.show(self.context, image_id)
        expected = {
            'id': image_id,
            'name': 'image1',
            'is_public': True,
            'size': None,
            'min_disk': None,
            'min_ram': None,
            'disk_format': None,
            'container_format': None,
            'checksum': None,
            'created_at': self.NOW_DATETIME,
            'updated_at': self.NOW_DATETIME,
            'deleted_at': None,
            'deleted': None,
            'status': None,
            'properties': {},
            'owner': None,
        }
        self.assertEqual(image_meta, expected)

    def test_show_raises_when_no_authtoken_in_the_context(self):
        fixture = self._make_fixture(name='image1',
                                     is_public=False,
                                     properties={'one': 'two'})
        image_id = self.service.create(self.context, fixture)['id']
        self.context.auth_token = False
        self.assertRaises(exception.ImageNotFound,
                          self.service.show,
                          self.context,
                          image_id)

    def test_detail_passes_through_to_client(self):
        fixture = self._make_fixture(name='image10', is_public=True)
        image_id = self.service.create(self.context, fixture)['id']
        image_metas = self.service.detail(self.context)
        expected = [
            {
                'id': image_id,
                'name': 'image10',
                'is_public': True,
                'size': None,
                'min_disk': None,
                'min_ram': None,
                'disk_format': None,
                'container_format': None,
                'checksum': None,
                'created_at': self.NOW_DATETIME,
                'updated_at': self.NOW_DATETIME,
                'deleted_at': None,
                'deleted': None,
                'status': None,
                'properties': {},
                'owner': None,
            },
        ]
        self.assertEqual(image_metas, expected)

    def test_show_makes_datetimes(self):
        fixture = self._make_datetime_fixture()
        image_id = self.service.create(self.context, fixture)['id']
        image_meta = self.service.show(self.context, image_id)
        self.assertEqual(image_meta['created_at'], self.NOW_DATETIME)
        self.assertEqual(image_meta['updated_at'], self.NOW_DATETIME)

    def test_detail_makes_datetimes(self):
        fixture = self._make_datetime_fixture()
        self.service.create(self.context, fixture)
        image_meta = self.service.detail(self.context)[0]
        self.assertEqual(image_meta['created_at'], self.NOW_DATETIME)
        self.assertEqual(image_meta['updated_at'], self.NOW_DATETIME)

    def test_download_with_retries(self):
        tries = [0]

        class MyGlanceStubClient(glance_stubs.StubGlanceClient):
            """A client that fails the first time, then succeeds."""
            def get(self, image_id):
                if tries[0] == 0:
                    tries[0] = 1
                    raise glanceclient.exc.ServiceUnavailable('')
                else:
                    return {}

        client = MyGlanceStubClient()
        service = self._create_image_service(client)
        image_id = 1  # doesn't matter
        writer = NullWriter()

        # When retries are disabled, we should get an exception
        self.flags(glance_num_retries=0)
        self.assertRaises(exception.GlanceConnectionFailed,
                service.download, self.context, image_id, writer)

        # Now lets enable retries. No exception should happen now.
        tries = [0]
        self.flags(glance_num_retries=1)
        service.download(self.context, image_id, writer)

    def test_download_file_url(self):
        class MyGlanceStubClient(glance_stubs.StubGlanceClient):
            """A client that returns a file url."""

            (outfd, s_tmpfname) = tempfile.mkstemp(prefix='directURLsrc')
            outf = os.fdopen(outfd, 'w')
            inf = open('/dev/urandom', 'r')
            for i in range(10):
                _data = inf.read(1024)
                outf.write(_data)
            outf.close()

            def get(self, image_id):
                return type('GlanceTestDirectUrlMeta', (object,),
                            {'direct_url': 'file://%s' + self.s_tmpfname})

        client = MyGlanceStubClient()
        (outfd, tmpfname) = tempfile.mkstemp(prefix='directURLdst')
        writer = os.fdopen(outfd, 'w')

        service = self._create_image_service(client)
        image_id = 1  # doesn't matter

        self.flags(allowed_direct_url_schemes=['file'])
        service.download(self.context, image_id, writer)
        writer.close()

        # compare the two files
        rc = filecmp.cmp(tmpfname, client.s_tmpfname)
        self.assertTrue(rc, "The file %s and %s should be the same" %
                        (tmpfname, client.s_tmpfname))
        os.remove(client.s_tmpfname)
        os.remove(tmpfname)

    def test_client_forbidden_converts_to_imagenotauthed(self):
        class MyGlanceStubClient(glance_stubs.StubGlanceClient):
            """A client that raises a Forbidden exception."""
            def get(self, image_id):
                raise glanceclient.exc.Forbidden(image_id)

        client = MyGlanceStubClient()
        service = self._create_image_service(client)
        image_id = 1  # doesn't matter
        writer = NullWriter()
        self.assertRaises(exception.ImageNotAuthorized, service.download,
                          self.context, image_id, writer)

    def test_client_httpforbidden_converts_to_imagenotauthed(self):
        class MyGlanceStubClient(glance_stubs.StubGlanceClient):
            """A client that raises a HTTPForbidden exception."""
            def get(self, image_id):
                raise glanceclient.exc.HTTPForbidden(image_id)

        client = MyGlanceStubClient()
        service = self._create_image_service(client)
        image_id = 1  # doesn't matter
        writer = NullWriter()
        self.assertRaises(exception.ImageNotAuthorized, service.download,
                          self.context, image_id, writer)

    def test_client_notfound_converts_to_imagenotfound(self):
        class MyGlanceStubClient(glance_stubs.StubGlanceClient):
            """A client that raises a NotFound exception."""
            def get(self, image_id):
                raise glanceclient.exc.NotFound(image_id)

        client = MyGlanceStubClient()
        service = self._create_image_service(client)
        image_id = 1  # doesn't matter
        writer = NullWriter()
        self.assertRaises(exception.ImageNotFound, service.download,
                          self.context, image_id, writer)

    def test_client_httpnotfound_converts_to_imagenotfound(self):
        class MyGlanceStubClient(glance_stubs.StubGlanceClient):
            """A client that raises a HTTPNotFound exception."""
            def get(self, image_id):
                raise glanceclient.exc.HTTPNotFound(image_id)

        client = MyGlanceStubClient()
        service = self._create_image_service(client)
        image_id = 1  # doesn't matter
        writer = NullWriter()
        self.assertRaises(exception.ImageNotFound, service.download,
                          self.context, image_id, writer)

    def test_glance_client_image_id(self):
        fixture = self._make_fixture(name='test image')
        image_id = self.service.create(self.context, fixture)['id']
        (service, same_id) = glance.get_remote_image_service(
                self.context, image_id)
        self.assertEquals(same_id, image_id)

    def test_glance_client_image_ref(self):
        fixture = self._make_fixture(name='test image')
        image_id = self.service.create(self.context, fixture)['id']
        image_url = 'http://something-less-likely/%s' % image_id
        (service, same_id) = glance.get_remote_image_service(
                self.context, image_url)
        self.assertEquals(same_id, image_id)
        self.assertEquals(service._client.host,
                'something-less-likely')

def _create_failing_glance_client(info):
    class MyGlanceStubClient(glance_stubs.StubGlanceClient):
        """A client that fails the first time, then succeeds."""
        def get(self, image_id):
            info['num_calls'] += 1
            if info['num_calls'] == 1:
                raise glanceclient.exc.ServiceUnavailable('')
            return {}

    return MyGlanceStubClient()

class TestGlanceClientWrapper(test.TestCase):

    def setUp(self):
        super(TestGlanceClientWrapper, self).setUp()
        # host1 has no scheme, which is http by default
        self.flags(glance_api_servers=['host1:9292', 'https://host2:9293',
            'http://host3:9294'])

        # Make the test run fast
        def _fake_sleep(secs):
            pass
        self.stubs.Set(time, 'sleep', _fake_sleep)

    def test_static_client_without_retries(self):
        self.flags(glance_num_retries=0)

        ctxt = context.RequestContext('fake', 'fake')
        fake_host = 'host4'
        fake_port = 9295
        fake_use_ssl = False

        info = {'num_calls': 0}

        def _fake_create_glance_client(context, host, port, use_ssl, version):
            self.assertEqual(host, fake_host)
            self.assertEqual(port, fake_port)
            self.assertEqual(use_ssl, fake_use_ssl)
            return _create_failing_glance_client(info)

        self.stubs.Set(glance, '_create_glance_client',
                _fake_create_glance_client)

        client = glance.GlanceClientWrapper(context=ctxt,
                host=fake_host, port=fake_port, use_ssl=fake_use_ssl)
        self.assertRaises(exception.GlanceConnectionFailed,
                client.call, ctxt, 1, 'get', 'meow')
        self.assertEqual(info['num_calls'], 1)

    def test_default_client_without_retries(self):
        self.flags(glance_num_retries=0)

        ctxt = context.RequestContext('fake', 'fake')

        info = {'num_calls': 0,
                'host': 'host1',
                'port': 9292,
                'use_ssl': False}

        # Leave the list in a known-order
        def _fake_shuffle(servers):
            pass

        def _fake_create_glance_client(context, host, port, use_ssl, version):
            self.assertEqual(host, info['host'])
            self.assertEqual(port, info['port'])
            self.assertEqual(use_ssl, info['use_ssl'])
            return _create_failing_glance_client(info)

        self.stubs.Set(random, 'shuffle', _fake_shuffle)
        self.stubs.Set(glance, '_create_glance_client',
                _fake_create_glance_client)

        client = glance.GlanceClientWrapper()
        client2 = glance.GlanceClientWrapper()
        self.assertRaises(exception.GlanceConnectionFailed,
                client.call, ctxt, 1, 'get', 'meow')
        self.assertEqual(info['num_calls'], 1)

        info = {'num_calls': 0,
                'host': 'host2',
                'port': 9293,
                'use_ssl': True}

        def _fake_shuffle2(servers):
            # fake shuffle in a known manner
            servers.append(servers.pop(0))

        self.stubs.Set(random, 'shuffle', _fake_shuffle2)

        self.assertRaises(exception.GlanceConnectionFailed,
                client2.call, ctxt, 1, 'get', 'meow')
        self.assertEqual(info['num_calls'], 1)

    def test_static_client_with_retries(self):
        self.flags(glance_num_retries=1)

        ctxt = context.RequestContext('fake', 'fake')
        fake_host = 'host4'
        fake_port = 9295
        fake_use_ssl = False

        info = {'num_calls': 0}

        def _fake_create_glance_client(context, host, port, use_ssl, version):
            self.assertEqual(host, fake_host)
            self.assertEqual(port, fake_port)
            self.assertEqual(use_ssl, fake_use_ssl)
            return _create_failing_glance_client(info)

        self.stubs.Set(glance, '_create_glance_client',
                _fake_create_glance_client)

        client = glance.GlanceClientWrapper(context=ctxt,
                host=fake_host, port=fake_port, use_ssl=fake_use_ssl)
        client.call(ctxt, 1, 'get', 'meow')
        self.assertEqual(info['num_calls'], 2)

    def test_default_client_with_retries(self):
        self.flags(glance_num_retries=1)

        ctxt = context.RequestContext('fake', 'fake')

        info = {'num_calls': 0,
                'host0': 'host1',
                'port0': 9292,
                'use_ssl0': False,
                'host1': 'host2',
                'port1': 9293,
                'use_ssl1': True}

        # Leave the list in a known-order
        def _fake_shuffle(servers):
            pass

        def _fake_create_glance_client(context, host, port, use_ssl, version):
            attempt = info['num_calls']
            self.assertEqual(host, info['host%s' % attempt])
            self.assertEqual(port, info['port%s' % attempt])
            self.assertEqual(use_ssl, info['use_ssl%s' % attempt])
            return _create_failing_glance_client(info)

        self.stubs.Set(random, 'shuffle', _fake_shuffle)
        self.stubs.Set(glance, '_create_glance_client',
                _fake_create_glance_client)

        client = glance.GlanceClientWrapper()
        client2 = glance.GlanceClientWrapper()
        client.call(ctxt, 1, 'get', 'meow')
        self.assertEqual(info['num_calls'], 2)

        def _fake_shuffle2(servers):
            # fake shuffle in a known manner
            servers.append(servers.pop(0))

        self.stubs.Set(random, 'shuffle', _fake_shuffle2)

        info = {'num_calls': 0,
                'host0': 'host2',
                'port0': 9293,
                'use_ssl0': True,
                'host1': 'host3',
                'port1': 9294,
                'use_ssl1': False}

        client2.call(ctxt, 1, 'get', 'meow')
        self.assertEqual(info['num_calls'], 2)

class TestGlanceUrl(test.TestCase):

    def test_generate_glance_http_url(self):
        generated_url = glance.generate_glance_url()
        http_url = "http://%s:%d" % (CONF.glance_host, CONF.glance_port)
        self.assertEqual(generated_url, http_url)

    def test_generate_glance_https_url(self):
        self.flags(glance_protocol="https")
        generated_url = glance.generate_glance_url()
        https_url = "https://%s:%d" % (CONF.glance_host, CONF.glance_port)
        self.assertEqual(generated_url, https_url)


class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        l1 = len(text1) + 1
        l2 = len(text2) + 1
        dp = [[0] * l2 for i in range(l1)]
        for i in range(1, l1):
            for j in range(1, l2):
                if text1[i-1] == text2[j-1]:
                    dp[i][j] = dp[i-1][j-1] + 1
                else:
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1])

        return dp[-1][-1]


import pandas as pd
from cert import certi
# df = pd.read_excel(r'C:\Users\KIIT\Desktop\certificates\final.xlsx', sheet_name=3)
# names = df['name']

df = pd.read_excel(r'C:\Users\KIIT\Desktop\certificates\final.xlsx', sheet_name=5)
names = []

# print(names)

for i in df['nameleader']:
    names.append(i)
for i in df['member2name']:
    names.append(i)
for i in df['member3name']:
    names.append(i)
for i in df['member4name']:
    names.append(i)
for i in df['member5name']:
    names.append(i)

while ' ' in names:
    names.remove(' ')

for i in range(len(names)):
    names[i] = names[i].title()

# print(len(names))
print(*names,sep='\n')
for i in names:
    certi(i)


import pandas as pd
import cv2
import torch
from torchvision import transforms
from models.resnet import Resnet
from models.efficientnet import EfficientNetModel

def preprocess_csv(df):
    df = df.drop(['width', 'height', 'xmin', 'ymin', 'xmax', 'ymax'], axis=1)
    df['class'] = df['class'].replace(['military tank', 'civilian car', 'military helicopter', 'military aircraft',
                                       'military truck', 'civilian aircraft'], ['0', '1', '2', '3', '4', '5'])
    return df

def get_model(model_name, num_classes):
    model = None
    if 'resnet' in model_name:
        model = Resnet(model_name, num_classes)
    elif 'efficientnet' in model_name:
        model = EfficientNetModel(model_name, num_classes)
    else:
        raise ValueError(f'Undefined model name: {model_name}')
    return model

def get_mean_and_std(dataloader):
    channels_sum, channels_squared_sum, num_batches = 0, 0, 0
    for data, _ in dataloader:
        convert_tensor = transforms.ToTensor()
        data = convert_tensor(data)
        data = data.unsqueeze(0)
        channels_sum += torch.mean(data, dim=[0, 2, 3])
        channels_squared_sum += torch.mean(data ** 2, dim=[0, 2, 3])
        num_batches += 1

    mean = channels_sum / num_batches
    std = (channels_squared_sum / num_batches - mean ** 2) ** 0.5

    return mean, std

def balance_dataframe(data):
    data = data.groupby('class')
    data = pd.DataFrame(data.apply(lambda x: x.sample(data.size().min()).reset_index(drop=True)))

    return data

def get_dataset_counts_info(X_train, X_test):
    print(f'Length of X_train: {len(X_train)}')
    print(X_train['class'].value_counts())
    print('--------------------')
    print(f'Length of X_test: {len(X_test)}')
    print(X_test['class'].value_counts())

def image_resize(image, width=None, height=None, inter=cv2.INTER_AREA):
    dim = None
    (h, w) = image.shape[:2]
    if width is None and height is None:
        return image
    if width is None:
        r = height / float(h)
        dim = (int(w * r), height)
    else:
        r = width / float(w)
        dim = (width, int(h * r))

    resized = cv2.resize(image, dim, interpolation=inter)
    return resized


import glob
import os
import pickle
from collections import defaultdict
from multiprocessing import Pool

import torch as torch
from tqdm import tqdm
from rouge_utils import _get_word_ngrams, cal_rouge
import dill

def _cal_rouge(sents, abstract):

    evaluated_1grams = [_get_word_ngrams(1, [sent.split()]) for sent in sents]
    reference_1grams = _get_word_ngrams(1, [abstract[0].split()])
    evaluated_2grams = [_get_word_ngrams(2, [sent.split()]) for sent in sents]
    reference_2grams = _get_word_ngrams(2,  [abstract[0].split()])

    candidates_1 = [evaluated_1grams[idx] for idx in range(len(evaluated_1grams))]
    candidates_1 = set.union(*map(set, candidates_1))
    candidates_2 = [evaluated_2grams[idx] for idx in range(len(evaluated_2grams))]
    candidates_2 = set.union(*map(set, candidates_2))

    rouge_1 = cal_rouge(candidates_1, reference_1grams)['f']
    rouge_2 = cal_rouge(candidates_2, reference_2grams)['f']

    return (rouge_1 + rouge_2) / 2

def _mp_rouge(params):
    i, j ,p_id, src_sent_1, src_sent_2, tgt = params
    rg_sent_1 = _cal_rouge([src_sent_1], [tgt])
    rg_sent_2 = _cal_rouge([src_sent_1] + [src_sent_2], [tgt])
    return {
        'index': (i, j),
        'rg_diff': rg_sent_2 - rg_sent_1,
        'paper_id': p_id
    }

if __name__ == '__main__':
    BASE_DIR = os.getenv('BERT_DIR')

    if not os.path.exists(BASE_DIR[:-1] + '-graph'):
        os.makedirs(BASE_DIR[:-1] + '-graph')

    BASE_DIR_WR = BASE_DIR[:-1] + '-graph'

    for se in ['train', 'val', 'test']:
    # for se in ['train']:
        prepare_array = []
        print('populating the ROUGE list...')

        for f in tqdm(glob.glob(BASE_DIR + '/' + se + '*.pt'), total=len(glob.glob(BASE_DIR + '/' + se + '*.pt'))):
            datasets = torch.load(f)

            for d in datasets:
                src_sents = d['src_tokens']
                if len(src_sents) == len(d['src_sent_labels']):
                    src_sents = [' '.join(s) for s in src_sents]
                    tgt = d['tgt_txt']
                    p_id = d['paper_id']

                    for i, src_sent_1 in enumerate(src_sents):
                        for j, src_sent_2 in enumerate(src_sents):
                            if j > i:
                                prepare_array.append((i, j, p_id, src_sent_1, src_sent_2, tgt))
                            # _mp_rouge(prepare_array[-1])
                else:
                    import pdb;pdb.set_trace()

        paper_id_edges =  defaultdict(lambda: defaultdict(dict))
        pool = Pool(15)

        # compute pair-wise ROUGE

        for out in tqdm(pool.imap_unordered(_mp_rouge, prepare_array), total=len(prepare_array)):
            paper_id_edges[out['paper_id']][out['index'][0]][out['index'][1]] = out['rg_diff']

        pool.close()
        pool.join()

        print(f'Now saving {se} graph...')

        torch.save(
            obj=paper_id_edges,
            f=f'/disk1/sajad/datasets/sci/arxivL/rouge_edge/{se}.pkl',
            pickle_module=dill
        )

        print(f'Now re-saving {se} torch files...')

        for f in tqdm(glob.glob(BASE_DIR + '/' + se + '*.pt'), total=len(glob.glob(BASE_DIR + '/' + se + '*.pt'))):
            datasets = torch.load(f)
            new_datasets = []

            for d in datasets:
                edge_weights = []
                src_sents = d['src_tokens']
                p_id = d['paper_id']

                for i, src_sent_1 in enumerate(src_sents):
                    for j, src_sent_2 in enumerate(src_sents):
                        if i == j:
                            edge_weights.append(0.0)

                        elif i > j:
                            edge_weight = paper_id_edges[p_id][j][i]
                            edge_weights.append(edge_weight)

                        elif i < j:
                            edge_weight = paper_id_edges[p_id][i][j]
                            edge_weights.append(edge_weight)

                d['edge_weights'] = edge_weights
                new_datasets.append(d)

            torch.save(new_datasets, f.replace('new', 'new-graph'))


"""
This solution uses a recursive function to go through each node using postorder
traversal. It checks if each node's value is in the bound. If not it returns
the correct node the parent should attach to.
"""

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def trim_bst(self, root: TreeNode, low: int, high: int) -> TreeNode:
        # if the node does not exist, return null
        if not root:
            return None

        # proceed to the left and right child
        root.left = self.trim_bst(root.left, low, high)
        root.right = self.trim_bst(root.right, low, high)

        # if the node's value is in the bound, return itself
        # if the node's value is not in the bound, return the left or right
        # child if there is one.
        # the children of the node is in the bound because the child is
        # evaluate and changed first
        if low <= root.val <= high:
            return root
        else:
            if root.left:
                return root.left
            if root.right:
                return root.right

            return None