<commit_before>import unittest
import sys
from io import StringIO
import inspect

from classes import Paladin
from spells import PaladinSpell
from models.spells.loader import load_paladin_spells_for_level

class PaladinTests(unittest.TestCase):
    def setUp(self):
        self.name = "Netherblood"
        self.level = 3
        self.dummy = Paladin(name=self.name, level=self.level, health=100, mana=100, strength=10)

    def test_init(self):
        """ The __init__ should load/save all the spells for the Paladin"""
        spells = [spell for level in range(1,self.level+1) for spell in load_paladin_spells_for_level(level)]

        self.assertNotEqual(len(self.dummy.learned_spells), 0)
        for spell in spells:
            self.assertIn(spell.name, self.dummy.learned_spells)
            char_spell = self.dummy.learned_spells[spell.name]
            # find the largest rank in our spells list (the char has the highest rank only)
            max_rank = list(sorted(filter(lambda x: x.name == spell.name, spells), key=lambda x: x.rank))[-1].rank

            self.assertEqual(char_spell.rank, max_rank)

    def test_leave_combat(self):
        """
        Except the normal behaviour, leave_combat should remove the SOR buff from the pally
        and reset his spell cds
        """
        self.dummy._in_combat = True
        self.dummy.SOR_ACTIVE = True
        for spell in self.dummy.learned_spells.values():
            spell._cooldown_counter = 100

        self.assertTrue(self.dummy.is_in_combat())

        self.dummy.leave_combat()

        self.assertFalse(self.dummy.is_in_combat())
        self.assertFalse(self.dummy.SOR_ACTIVE)
        # All cooldowns should be reset
        self.assertTrue(all([spell._cooldown_counter == 0 for spell in self.dummy.learned_spells.values()]))

    def test_reset_spell_cooldowns(self):
        """ The reset_spell_cooldowns goes through every spell and resets its CD"""
        for spell in self.dummy.learned_spells.values():
            spell._cooldown_counter = 100
        self.assertTrue(all([spell._cooldown_counter != 0 for spell in self.dummy.learned_spells.values()]))

        self.dummy.reset_spell_cooldowns()

        self.assertTrue(all([spell._cooldown_counter == 0 for spell in self.dummy.learned_spells.values()]))

    def test_level_up(self):
        """ Except the normal behaviour, it should learn new spells for the character """
        # empty the learned spells, it's stored as a static variable, which is not good practice but doesn't hurt in the game
        Paladin.learned_spells = {}
        pl = Paladin(name="fuck a nine to five")

        spells_to_learn = [spell.name for spell in load_paladin_spells_for_level(pl.level + 1)]
        for spell in spells_to_learn:
            self.assertNotIn(spell, pl.learned_spells)
        pl._level_up()
        for spell in spells_to_learn:
            self.assertIn(spell, pl.learned_spells)

    def test_level_up_to_level(self):
        """ Except the normal behaviour, it should learn new spells for the character """
        # empty the learned spells, it's stored as a static variable, which is not good practice but doesn't hurt in the game
        Paladin.learned_spells = {}
        pl = Paladin(name="fuck a nine to five")
        to_level = 4

        spells_to_learn = [spell for level in range(2, to_level + 1) for spell in load_paladin_spells_for_level(level)]
        for spell in spells_to_learn:
            has_not_learned_spell = spell.name not in pl.learned_spells
            has_smaller_rank = spell.rank > pl.learned_spells[spell.name].rank if not has_not_learned_spell else False
            self.assertTrue(has_not_learned_spell or has_smaller_rank)
        pl._level_up(to_level=to_level)
        for spell in spells_to_learn:
            self.assertIn(spell.name, pl.learned_spells)

    def test_lookup_and_handle_new_spells(self):
        """ Should look up the available spells for our level and learn them or update our existing ones"""
        Paladin.learned_spells = {}
        pl = Paladin(name="fuck a nine to five")
        print(pl.learned_spells)
        pl.level = 3
        spells_to_learn = [spell for spell in load_paladin_spells_for_level(pl.level)]
        for spell in spells_to_learn:
            has_not_learned_spell = spell.name not in pl.learned_spells
            has_smaller_rank = spell.rank > pl.learned_spells[spell.name].rank if not has_not_learned_spell else False
            self.assertTrue(has_not_learned_spell or has_smaller_rank)

        pl._lookup_and_handle_new_spells()

        for spell in spells_to_learn:
            self.assertIn(spell.name, pl.learned_spells)

    def test_learn_new_spell(self):
        """ Given a PaladinSpell, add it to the learned_spells dictionary"""
        spell = PaladinSpell(name="Too_Alive", rank=5)
        expected_message = f'You have learned a new spell - {spell.name}'

        self.assertNotIn(spell.name, self.dummy.learned_spells)
        try:
            output = StringIO()
            sys.stdout = output

            self.dummy.learn_new_spell(spell)

            self.assertIn(expected_message, output.getvalue())
        finally:
            sys.stdout = sys.__stdout__
        self.assertIn(spell.name, self.dummy.learned_spells)

    def test_lookup_available_spells_to_learn(self):
        """ It's a generator function returning a spell that can be learnt for the level """
        lev = 3
        expected_spells = load_paladin_spells_for_level(lev)
        generator = self.dummy._lookup_available_spells_to_learn(lev)

        self.assertTrue(inspect.isgenerator(generator))
        for spell in expected_spells:
            self.assertEqual(vars(next(generator)), vars(spell))

    def test_update_spell(self):
        """ The update_spell() function updates a spell we already have learned"""
        f_spell = PaladinSpell('Spell', rank=1)
        s_spell = PaladinSpell('Spell', rank=2)
        expected_message = f'Spell {f_spell.name} has been updated to rank {s_spell.rank}!'
        self.dummy.learn_new_spell(f_spell)

        try:
            output = StringIO()
            sys.stdout = output

            self.dummy.update_spell(s_spell)

            self.assertIn(expected_message, output.getvalue())
        finally:
            sys.stdout = sys.__stdout__

        # assert that it updated the rank
        self.assertEqual(self.dummy.learned_spells[s_spell.name].rank, s_spell.rank)
        self.assertGreater(self.dummy.learned_spells[s_spell.name].rank, f_spell.rank)

    def test_spell_handler_sor(self):
        """
        The spell handler takes spell names and casts the appropriate function
        It might work in a bad way since it's not too testable
        """
        unsuccessful_message = 'Unsuccessful cast'
        sor_success_msg = 'SOR_CASTED'
        sor_command_name = 'sor'
        # Mock the function that should get called
        self.dummy.spell_seal_of_righteousness = lambda x: sor_success_msg

        try:
            output = StringIO()
            sys.stdout = output
            result = self.dummy.spell_handler(sor_command_name, None)

            self.assertNotIn(unsuccessful_message, output.getvalue())
        finally:
            sys.stdout = sys.__stdout__

        # Assert that it called the spell_seal_of_righteousness function
        self.assertEqual(result, sor_success_msg)

    def test_spell_handler_fol(self):
        unsuccessful_message = 'Unsuccessful cast'
        fol_success_msg = 'FOL_CASTED'
        fol_command_name = 'fol'
        # Mock the function that should get called
        self.dummy.spell_flash_of_light = lambda x: fol_success_msg

        try:
            output = StringIO()
            sys.stdout = output
            result = self.dummy.spell_handler(fol_command_name, None)

            self.assertNotIn(unsuccessful_message, output.getvalue())
        finally:
            sys.stdout = sys.__stdout__

        # Assert that it called the spell_seal_of_righteousness function
        self.assertEqual(result, fol_success_msg)

    def test_spell_handler_ms(self):
        unsuccessful_message = 'Unsuccessful cast'
        ms_success_msg = 'MS_CASTED'
        ms_command_name = 'ms'
        # Mock the function that should get called
        self.dummy.spell_melting_strike = lambda target=None, spell=None: ms_success_msg

        try:
            output = StringIO()
            sys.stdout = output
            result = self.dummy.spell_handler(ms_command_name, None)

            self.assertNotIn(unsuccessful_message, output.getvalue())
        finally:
            sys.stdout = sys.__stdout__

        # Assert that it called the spell_seal_of_righteousness function
        self.assertEqual(result, ms_success_msg)

    def test_spell_handler_invalid_spell(self):
        unsuccessful_message = 'Unsuccessful cast'
        invalid_command = 'WooHoo'

        try:
            output = StringIO()
            sys.stdout = output
            result = self.dummy.spell_handler(invalid_command, None)

            self.assertIn(unsuccessful_message, output.getvalue())
        finally:
            sys.stdout = sys.__stdout__

        self.assertFalse(result)

if __name__ == '__main__':
    unittest.main()
<commit_msg>Test for spell_seal_of_righteousness()<commit_after>import unittest
import sys
from io import StringIO
import inspect

from classes import Paladin
from spells import PaladinSpell
from models.spells.loader import load_paladin_spells_for_level

class PaladinTests(unittest.TestCase):
    def setUp(self):
        self.name = "Netherblood"
        self.level = 3
        self.dummy = Paladin(name=self.name, level=self.level, health=100, mana=100, strength=10)

    def test_init(self):
        """ The __init__ should load/save all the spells for the Paladin"""
        spells = [spell for level in range(1,self.level+1) for spell in load_paladin_spells_for_level(level)]

        self.assertNotEqual(len(self.dummy.learned_spells), 0)
        for spell in spells:
            self.assertIn(spell.name, self.dummy.learned_spells)
            char_spell = self.dummy.learned_spells[spell.name]
            # find the largest rank in our spells list (the char has the highest rank only)
            max_rank = list(sorted(filter(lambda x: x.name == spell.name, spells), key=lambda x: x.rank))[-1].rank

            self.assertEqual(char_spell.rank, max_rank)

    def test_leave_combat(self):
        """
        Except the normal behaviour, leave_combat should remove the SOR buff from the pally
        and reset his spell cds
        """
        self.dummy._in_combat = True
        self.dummy.SOR_ACTIVE = True
        for spell in self.dummy.learned_spells.values():
            spell._cooldown_counter = 100

        self.assertTrue(self.dummy.is_in_combat())

        self.dummy.leave_combat()

        self.assertFalse(self.dummy.is_in_combat())
        self.assertFalse(self.dummy.SOR_ACTIVE)
        # All cooldowns should be reset
        self.assertTrue(all([spell._cooldown_counter == 0 for spell in self.dummy.learned_spells.values()]))

    def test_reset_spell_cooldowns(self):
        """ The reset_spell_cooldowns goes through every spell and resets its CD"""
        for spell in self.dummy.learned_spells.values():
            spell._cooldown_counter = 100
        self.assertTrue(all([spell._cooldown_counter != 0 for spell in self.dummy.learned_spells.values()]))

        self.dummy.reset_spell_cooldowns()

        self.assertTrue(all([spell._cooldown_counter == 0 for spell in self.dummy.learned_spells.values()]))

    def test_level_up(self):
        """ Except the normal behaviour, it should learn new spells for the character """
        # empty the learned spells, it's stored as a static variable, which is not good practice but doesn't hurt in the game
        Paladin.learned_spells = {}
        pl = Paladin(name="fuck a nine to five")

        spells_to_learn = [spell.name for spell in load_paladin_spells_for_level(pl.level + 1)]
        for spell in spells_to_learn:
            self.assertNotIn(spell, pl.learned_spells)
        pl._level_up()
        for spell in spells_to_learn:
            self.assertIn(spell, pl.learned_spells)

    def test_level_up_to_level(self):
        """ Except the normal behaviour, it should learn new spells for the character """
        # empty the learned spells, it's stored as a static variable, which is not good practice but doesn't hurt in the game
        Paladin.learned_spells = {}
        pl = Paladin(name="fuck a nine to five")
        to_level = 4

        spells_to_learn = [spell for level in range(2, to_level + 1) for spell in load_paladin_spells_for_level(level)]
        for spell in spells_to_learn:
            has_not_learned_spell = spell.name not in pl.learned_spells
            has_smaller_rank = spell.rank > pl.learned_spells[spell.name].rank if not has_not_learned_spell else False
            self.assertTrue(has_not_learned_spell or has_smaller_rank)
        pl._level_up(to_level=to_level)
        for spell in spells_to_learn:
            self.assertIn(spell.name, pl.learned_spells)

    def test_lookup_and_handle_new_spells(self):
        """ Should look up the available spells for our level and learn them or update our existing ones"""
        Paladin.learned_spells = {}
        pl = Paladin(name="fuck a nine to five")
        print(pl.learned_spells)
        pl.level = 3
        spells_to_learn = [spell for spell in load_paladin_spells_for_level(pl.level)]
        for spell in spells_to_learn:
            has_not_learned_spell = spell.name not in pl.learned_spells
            has_smaller_rank = spell.rank > pl.learned_spells[spell.name].rank if not has_not_learned_spell else False
            self.assertTrue(has_not_learned_spell or has_smaller_rank)

        pl._lookup_and_handle_new_spells()

        for spell in spells_to_learn:
            self.assertIn(spell.name, pl.learned_spells)

    def test_learn_new_spell(self):
        """ Given a PaladinSpell, add it to the learned_spells dictionary"""
        spell = PaladinSpell(name="Too_Alive", rank=5)
        expected_message = f'You have learned a new spell - {spell.name}'

        self.assertNotIn(spell.name, self.dummy.learned_spells)
        try:
            output = StringIO()
            sys.stdout = output

            self.dummy.learn_new_spell(spell)

            self.assertIn(expected_message, output.getvalue())
        finally:
            sys.stdout = sys.__stdout__
        self.assertIn(spell.name, self.dummy.learned_spells)

    def test_lookup_available_spells_to_learn(self):
        """ It's a generator function returning a spell that can be learnt for the level """
        lev = 3
        expected_spells = load_paladin_spells_for_level(lev)
        generator = self.dummy._lookup_available_spells_to_learn(lev)

        self.assertTrue(inspect.isgenerator(generator))
        for spell in expected_spells:
            self.assertEqual(vars(next(generator)), vars(spell))

    def test_update_spell(self):
        """ The update_spell() function updates a spell we already have learned"""
        f_spell = PaladinSpell('Spell', rank=1)
        s_spell = PaladinSpell('Spell', rank=2)
        expected_message = f'Spell {f_spell.name} has been updated to rank {s_spell.rank}!'
        self.dummy.learn_new_spell(f_spell)

        try:
            output = StringIO()
            sys.stdout = output

            self.dummy.update_spell(s_spell)

            self.assertIn(expected_message, output.getvalue())
        finally:
            sys.stdout = sys.__stdout__

        # assert that it updated the rank
        self.assertEqual(self.dummy.learned_spells[s_spell.name].rank, s_spell.rank)
        self.assertGreater(self.dummy.learned_spells[s_spell.name].rank, f_spell.rank)

    def test_spell_handler_sor(self):
        """
        The spell handler takes spell names and casts the appropriate function
        It might work in a bad way since it's not too testable
        """
        unsuccessful_message = 'Unsuccessful cast'
        sor_success_msg = 'SOR_CASTED'
        sor_command_name = 'sor'
        # Mock the function that should get called
        self.dummy.spell_seal_of_righteousness = lambda x: sor_success_msg

        try:
            output = StringIO()
            sys.stdout = output
            result = self.dummy.spell_handler(sor_command_name, None)

            self.assertNotIn(unsuccessful_message, output.getvalue())
        finally:
            sys.stdout = sys.__stdout__

        # Assert that it called the spell_seal_of_righteousness function
        self.assertEqual(result, sor_success_msg)

    def test_spell_handler_fol(self):
        unsuccessful_message = 'Unsuccessful cast'
        fol_success_msg = 'FOL_CASTED'
        fol_command_name = 'fol'
        # Mock the function that should get called
        self.dummy.spell_flash_of_light = lambda x: fol_success_msg

        try:
            output = StringIO()
            sys.stdout = output
            result = self.dummy.spell_handler(fol_command_name, None)

            self.assertNotIn(unsuccessful_message, output.getvalue())
        finally:
            sys.stdout = sys.__stdout__

        # Assert that it called the spell_seal_of_righteousness function
        self.assertEqual(result, fol_success_msg)

    def test_spell_handler_ms(self):
        unsuccessful_message = 'Unsuccessful cast'
        ms_success_msg = 'MS_CASTED'
        ms_command_name = 'ms'
        # Mock the function that should get called
        self.dummy.spell_melting_strike = lambda target=None, spell=None: ms_success_msg

        try:
            output = StringIO()
            sys.stdout = output
            result = self.dummy.spell_handler(ms_command_name, None)

            self.assertNotIn(unsuccessful_message, output.getvalue())
        finally:
            sys.stdout = sys.__stdout__

        # Assert that it called the spell_seal_of_righteousness function
        self.assertEqual(result, ms_success_msg)

    def test_spell_handler_invalid_spell(self):
        unsuccessful_message = 'Unsuccessful cast'
        invalid_command = 'WooHoo'

        try:
            output = StringIO()
            sys.stdout = output
            result = self.dummy.spell_handler(invalid_command, None)

            self.assertIn(unsuccessful_message, output.getvalue())
        finally:
            sys.stdout = sys.__stdout__

        self.assertFalse(result)

    def test_spell_seal_of_righteousness(self):
        sor: PaladinSpell = self.dummy.learned_spells[Paladin.KEY_SEAL_OF_RIGHTEOUSNESS]
        expected_message = f'{self.dummy.name} activates {Paladin.KEY_SEAL_OF_RIGHTEOUSNESS}!'
        expected_mana = self.dummy.mana - sor.mana_cost
        self.assertFalse(self.dummy.SOR_ACTIVE)
        self.assertEqual(self.dummy.SOR_TURNS, 0)

        try:
            output = StringIO()
            sys.stdout = output

            self.dummy.spell_seal_of_righteousness(sor)

            self.assertIn(expected_message, output.getvalue())
        finally:
            sys.stdout = sys.__stdout__

        self.assertTrue(self.dummy.SOR_ACTIVE)
        self.assertEqual(self.dummy.SOR_TURNS, 3)
        self.assertEqual(self.dummy.mana, expected_mana)

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


<commit_before>from __future__ import print_function
import networkx as nx
import dag_util as du
from nodes.attributes import NodeAttr
from networkx.algorithms.dag import ancestors, topological_sort
from nodes.pprinter import pprint_one_constraint

# TODO: - Put solution to tracepoint in AMPL automatically, maybe .sol file to
#             converter?
#       - Clean up test, improve coverage
#       - import sparsity pattern from AMPL
#       - dbg_info, show nvars, ncons, cons type, num of ref sols, model name
#       - Where are the var bounds? -> For named ones, at the definition,
#                                      CSEs *must* not have any, assert inserted
#       - color given nodes on the plot yellow
#       - try to get defined variable names
#
#       - defined var topological orders should be stored as well
#         not clear how to avoid recomputations, maybe removing
#         aliases wasn't the best idea? -> Cut corners, ignore inefficiencies
#                                          for now; def vars won't be that
#                                          common anyway with connected units

class Problem:

    def __init__(self):
        self.dag = nx.DiGraph()
        self.con_ends_num = { } # con sink node -> con num (in AMPL)
        self.con_num_name = { } # con num -> con name (in AMPL)
        self.var_num_name = { } # var num (in AMPL) -> var name (in AMPL)
        self.var_node_ids = set()
        self.defined_vars = set() # node ids after elimination
        self.model_name   = '(none)'
        self.nvars        = int(-1) # number of variables
        self.con_top_ord  = { } # con sink node -> con topological order
        self.refsols      = [ ]

    def setup(self):
        dag = self.dag
        du.dbg_info(dag)
        dag.graph['name'] = self.model_name
        self.setup_constraint_names()
        self.setup_nodes()
        # The followings are simplifications
        #-------------------------------------------
        # remove bogus named var aliasing
        du.assert_var_num_equals_node_id_for_named_vars(dag, self.var_num_name)
        # remove named vars from var_node_ids, we asserted just above that
        # they are nodes 0:nvars
        self.var_node_ids.difference_update( xrange(self.nvars) )
        # the rest assumes that named var nodes are no longer in var_node_ids!
        self.remove_var_aliases()
        #-------------------------------------------
        # nl2dag erroneously turns defined vars into constraints
        self.reconstruct_CSEs()
        self.remove_unused_def_vars()
        self.remove_identity_sum_nodes()
        self.remove_def_var_aliasing_another_node()
        #-------------------------------------------
        self.collect_constraint_topological_orders()
        #-------------------------------------------
        self.pprint_constraints()
        #-------------------------------------------
        du.dbg_info(dag)

    def setup_constraint_names(self):
        for node_id, con_num in self.con_ends_num.iteritems():
            d = self.dag.node[node_id]
            d[NodeAttr.name] = self.con_num_name.get(con_num, '_c%d' % con_num)
            d[NodeAttr.con_num] = con_num

    def setup_nodes(self):
        for node_id, d in self.dag.nodes_iter(data=True):
            d[NodeAttr.type].setup(node_id, d, self)

    def remove_var_aliases(self):
        var_aliases = self.get_var_aliases()
        for node_id, var_num in var_aliases.iteritems():
            du.reparent(self.dag, var_num, node_id)
        self.var_node_ids -= var_aliases.viewkeys()

    def get_var_aliases(self):
        var_aliases = { } # alias node id -> named var aliased
        # this new dict is needed as we remove nodes from the dag as we reparent
        nvars = self.nvars
        for node_id, var_num in du.itr_var_num(self.dag, self.var_node_ids):
            if var_num < nvars: # true if referencing a named var; false for CSE
                var_aliases[node_id] = var_num
        return var_aliases

    def reconstruct_CSEs(self):
        con_ends = self.get_unnamed_constraints()
        dag = self.dag
        du.assert_CSE_defining_constraints(dag, con_ends, self.var_num_name)
        self.eliminate_def_vars(con_ends)
        self.remove_CSE_aliases(con_ends)

    def get_unnamed_constraints(self):
        return [ n for n in self.con_ends_num   \
                         if self.con_ends_num[n] not in self.con_num_name ]

    def eliminate_def_vars(self, con_ends):
        #  defined variable := its defining constraint
        print('cons: ', sorted(self.con_ends_num.viewkeys()))
        dag = self.dag
        for sum_node_id in con_ends:
            var_node_id = sum_node_id + 1 # already asserted that it is true
            du.reverse_edge_to_get_def_var(dag, sum_node_id, var_node_id)
            self.con_ends_num.pop(sum_node_id) # safe: iterating on a copy
            self.defined_vars.add(var_node_id)
        print('cons: ', sorted(self.con_ends_num.viewkeys()))

    def remove_CSE_aliases(self, con_ends):
        dag = self.dag
        # var_num -> defining node
        var_num_def_node = { dag.node[n+1][NodeAttr.var_num] : n+1 \
                                 for n in con_ends }
        print('defined vars, var num -> defining node:\n  %s\n'%var_num_def_node)
        var_node_ids = self.var_node_ids
        du.assert_vars_are_CSEs(dag, var_node_ids, var_num_def_node)
        var_aliases = var_node_ids - self.defined_vars
        for var_node in var_aliases:
            var_num = dag.node[var_node][NodeAttr.var_num]
            def_node = var_num_def_node[var_num]
            assert def_node!=var_node, '%d, %d' % (def_node, var_node)
            du.reparent(dag, def_node, var_node, new_parent_is_source=False)
        self.var_node_ids.clear() # after eliminating the CSEs, we don't need it

    def remove_unused_def_vars(self):
        dag = self.dag
        removed = [ ]
        for n in du.itr_sinks(dag, self.defined_vars):
            deps = ancestors(dag, n)
            deps.add(n)
            con_dag = dag.subgraph(deps)
            reverse_order = topological_sort(con_dag, reverse=True)
            removed = self.delete_sinks_recursively(reverse_order)
        print('Unused nodes:', removed)
        self.defined_vars.difference_update(removed)

    def delete_sinks_recursively(self, reverse_order):
        dag = self.dag
        removed = [ ]
        for n in reverse_order:
            if du.is_sink(dag, n):
                removed.append(n)
                du.remove_node(dag, n)
        return removed

    def remove_identity_sum_nodes(self):
        dag = self.dag
        to_delete = self.get_identity_sum_nodes()
        for n, (pred, succ) in to_delete.iteritems():
            du.remove_node(dag, n)
            d = dag.node[succ] # may need it to transfer var_num to new parent
            du.reparent(dag, pred, succ, new_parent_is_source=False)
            self.update_defined_var_bookkeeping(pred, succ, d)

    def get_identity_sum_nodes(self):
        # SISO sum nodes with in and out edge weight == 1 and d_term == 0
        dag = self.dag
        to_delete = { }
        for n in du.itr_siso_sum_nodes(dag):
            pred = dag.pred[n].keys()[0]
            succ = dag.succ[n].keys()[0]
            in_mul  = dag.edge[pred][n]['weight']
            out_mul = dag.edge[n][succ]['weight']
            d = dag.node[n]
            d_term  = d.get(NodeAttr.d_term, 0.0)
            assert NodeAttr.bounds not in d, d
            if in_mul==1.0 and out_mul==1.0 and d_term==0.0:
                to_delete[n] = (pred, succ)
        print('identity sum nodes:', to_delete)
        return to_delete

    def update_defined_var_bookkeeping(self, new_def_var, old_def_var, d):
        if old_def_var in self.defined_vars:
            # move defined var from old_def_var to new_def_var
            self.defined_vars.remove(old_def_var)
            self.defined_vars.add(new_def_var)
            # transfer var_num; if new_def_var is already a defined var
            # then keep the smaller var_num
            var_num = d[NodeAttr.var_num]
            d_pred  = self.dag.node[new_def_var]
            old_var_num = d_pred.get(NodeAttr.var_num, var_num)
            d_pred[NodeAttr.var_num] = min(var_num, old_var_num)

    def remove_def_var_aliasing_another_node(self):
        dag = self.dag
        to_delete = self.get_def_var_aliasing_another_node()
        for n, pred in to_delete.iteritems():
            d = dag.node[n]  # need it to transfer var_num to new parent
            dag.remove_edge(pred, n)
            du.reparent(dag, pred, n, new_parent_is_source=False)
            self.update_defined_var_bookkeeping(pred, n, d)

    def get_def_var_aliasing_another_node(self):
        # def var_node with a single input, edge weight one and no d_term
        dag = self.dag
        to_delete = { }
        for n in du.itr_single_input_nodes(dag, self.defined_vars):
            pred = dag.pred[n].keys()[0]
            in_mul  = dag.edge[pred][n]['weight']
            d = dag.node[n]
            assert NodeAttr.bounds not in d, d
            d_term  = d.get(NodeAttr.d_term, 0.0)
            if in_mul==1.0 and d_term==0.0:
                to_delete[n] = pred
        print('var nodes just aliasing:', to_delete)
        return to_delete

    def collect_constraint_topological_orders(self):
        dag = self.dag
        for sink_node in self.con_ends_num:
            dependecies = ancestors(dag, sink_node)
            dependecies.add(sink_node)
            con_dag = dag.subgraph(dependecies)
            eval_order = du.deterministic_topological_sort(con_dag)
            self.con_top_ord[sink_node] = eval_order

    def pprint_constraints(self):
        for sink_node in self.con_ends_num:
            eval_order = self.con_top_ord[sink_node]
            con_num = self.con_ends_num[sink_node]
            con_dag = self.dag.subgraph(eval_order)
            nvars   = self.nvars
            pprint_one_constraint(sink_node, con_num, con_dag, eval_order, nvars)

    def dbg_show_node_types(self):
        dag = self.dag
        for n in dag:
            print('%d  %s' % (n, du.get_pretty_type_str(dag, n)))
        print()

<commit_msg>Updated TODOs<commit_after>from __future__ import print_function
import networkx as nx
import dag_util as du
from nodes.attributes import NodeAttr
from networkx.algorithms.dag import ancestors, topological_sort
from nodes.pprinter import pprint_one_constraint

# TODO: - Put solution to tracepoint in AMPL automatically, maybe .sol file to
#             converter?
#       - Clean up test, improve coverage
#       - import sparsity pattern from AMPL
#       - dbg_info, show nvars, ncons, cons type, num of ref sols, model name
#       - report / fix plotting bugs
#       - code generation for AD and constraint propagation
#       - Where are the var bounds? -> For named ones, at the definition,
#                                      CSEs *must* not have any, assert inserted
#       - color given nodes on the plot yellow (selected ones for debugging,
#             sinks, def var nodes, etc.)
#       - try to get defined variable names
#
#       - defined var topological orders should be stored as well
#         not clear how to avoid recomputations, maybe removing
#         aliases wasn't the best idea? -> Cut corners, ignore inefficiencies
#                                          for now; def vars won't be that
#                                          common anyway with connected units

class Problem:

    def __init__(self):
        self.dag = nx.DiGraph()
        self.con_ends_num = { } # con sink node -> con num (in AMPL)
        self.con_num_name = { } # con num -> con name (in AMPL)
        self.var_num_name = { } # var num (in AMPL) -> var name (in AMPL)
        self.var_node_ids = set()
        self.defined_vars = set() # node ids after elimination
        self.model_name   = '(none)'
        self.nvars        = int(-1) # number of variables
        self.con_top_ord  = { } # con sink node -> con topological order
        self.refsols      = [ ]

    def setup(self):
        dag = self.dag
        du.dbg_info(dag)
        dag.graph['name'] = self.model_name
        self.setup_constraint_names()
        self.setup_nodes()
        # The followings are simplifications
        #-------------------------------------------
        # remove bogus named var aliasing
        du.assert_var_num_equals_node_id_for_named_vars(dag, self.var_num_name)
        # remove named vars from var_node_ids, we asserted just above that
        # they are nodes 0:nvars
        self.var_node_ids.difference_update( xrange(self.nvars) )
        # the rest assumes that named var nodes are no longer in var_node_ids!
        self.remove_var_aliases()
        #-------------------------------------------
        # nl2dag erroneously turns defined vars into constraints
        self.reconstruct_CSEs()
        self.remove_unused_def_vars()
        self.remove_identity_sum_nodes()
        self.remove_def_var_aliasing_another_node()
        #-------------------------------------------
        self.collect_constraint_topological_orders()
        #-------------------------------------------
        self.pprint_constraints()
        #-------------------------------------------
        du.dbg_info(dag)

    def setup_constraint_names(self):
        for node_id, con_num in self.con_ends_num.iteritems():
            d = self.dag.node[node_id]
            d[NodeAttr.name] = self.con_num_name.get(con_num, '_c%d' % con_num)
            d[NodeAttr.con_num] = con_num

    def setup_nodes(self):
        for node_id, d in self.dag.nodes_iter(data=True):
            d[NodeAttr.type].setup(node_id, d, self)

    def remove_var_aliases(self):
        var_aliases = self.get_var_aliases()
        for node_id, var_num in var_aliases.iteritems():
            du.reparent(self.dag, var_num, node_id)
        self.var_node_ids -= var_aliases.viewkeys()

    def get_var_aliases(self):
        var_aliases = { } # alias node id -> named var aliased
        # this new dict is needed as we remove nodes from the dag as we reparent
        nvars = self.nvars
        for node_id, var_num in du.itr_var_num(self.dag, self.var_node_ids):
            if var_num < nvars: # true if referencing a named var; false for CSE
                var_aliases[node_id] = var_num
        return var_aliases

    def reconstruct_CSEs(self):
        con_ends = self.get_unnamed_constraints()
        dag = self.dag
        du.assert_CSE_defining_constraints(dag, con_ends, self.var_num_name)
        self.eliminate_def_vars(con_ends)
        self.remove_CSE_aliases(con_ends)

    def get_unnamed_constraints(self):
        return [ n for n in self.con_ends_num   \
                         if self.con_ends_num[n] not in self.con_num_name ]

    def eliminate_def_vars(self, con_ends):
        #  defined variable := its defining constraint
        print('cons: ', sorted(self.con_ends_num.viewkeys()))
        dag = self.dag
        for sum_node_id in con_ends:
            var_node_id = sum_node_id + 1 # already asserted that it is true
            du.reverse_edge_to_get_def_var(dag, sum_node_id, var_node_id)
            self.con_ends_num.pop(sum_node_id) # safe: iterating on a copy
            self.defined_vars.add(var_node_id)
        print('cons: ', sorted(self.con_ends_num.viewkeys()))

    def remove_CSE_aliases(self, con_ends):
        dag = self.dag
        # var_num -> defining node
        var_num_def_node = { dag.node[n+1][NodeAttr.var_num] : n+1 \
                                 for n in con_ends }
        print('defined vars, var num -> defining node:\n  %s\n'%var_num_def_node)
        var_node_ids = self.var_node_ids
        du.assert_vars_are_CSEs(dag, var_node_ids, var_num_def_node)
        var_aliases = var_node_ids - self.defined_vars
        for var_node in var_aliases:
            var_num = dag.node[var_node][NodeAttr.var_num]
            def_node = var_num_def_node[var_num]
            assert def_node!=var_node, '%d, %d' % (def_node, var_node)
            du.reparent(dag, def_node, var_node, new_parent_is_source=False)
        self.var_node_ids.clear() # after eliminating the CSEs, we don't need it

    def remove_unused_def_vars(self):
        dag = self.dag
        removed = [ ]
        for n in du.itr_sinks(dag, self.defined_vars):
            deps = ancestors(dag, n)
            deps.add(n)
            con_dag = dag.subgraph(deps)
            reverse_order = topological_sort(con_dag, reverse=True)
            removed = self.delete_sinks_recursively(reverse_order)
        print('Unused nodes:', removed)
        self.defined_vars.difference_update(removed)

    def delete_sinks_recursively(self, reverse_order):
        dag = self.dag
        removed = [ ]
        for n in reverse_order:
            if du.is_sink(dag, n):
                removed.append(n)
                du.remove_node(dag, n)
        return removed

    def remove_identity_sum_nodes(self):
        dag = self.dag
        to_delete = self.get_identity_sum_nodes()
        for n, (pred, succ) in to_delete.iteritems():
            du.remove_node(dag, n)
            d = dag.node[succ] # may need it to transfer var_num to new parent
            du.reparent(dag, pred, succ, new_parent_is_source=False)
            self.update_defined_var_bookkeeping(pred, succ, d)

    def get_identity_sum_nodes(self):
        # SISO sum nodes with in and out edge weight == 1 and d_term == 0
        dag = self.dag
        to_delete = { }
        for n in du.itr_siso_sum_nodes(dag):
            pred = dag.pred[n].keys()[0]
            succ = dag.succ[n].keys()[0]
            in_mul  = dag.edge[pred][n]['weight']
            out_mul = dag.edge[n][succ]['weight']
            d = dag.node[n]
            d_term  = d.get(NodeAttr.d_term, 0.0)
            assert NodeAttr.bounds not in d, d
            if in_mul==1.0 and out_mul==1.0 and d_term==0.0:
                to_delete[n] = (pred, succ)
        print('identity sum nodes:', to_delete)
        return to_delete

    def update_defined_var_bookkeeping(self, new_def_var, old_def_var, d):
        if old_def_var in self.defined_vars:
            # move defined var from old_def_var to new_def_var
            self.defined_vars.remove(old_def_var)
            self.defined_vars.add(new_def_var)
            # transfer var_num; if new_def_var is already a defined var
            # then keep the smaller var_num
            var_num = d[NodeAttr.var_num]
            d_pred  = self.dag.node[new_def_var]
            old_var_num = d_pred.get(NodeAttr.var_num, var_num)
            d_pred[NodeAttr.var_num] = min(var_num, old_var_num)

    def remove_def_var_aliasing_another_node(self):
        dag = self.dag
        to_delete = self.get_def_var_aliasing_another_node()
        for n, pred in to_delete.iteritems():
            d = dag.node[n]  # need it to transfer var_num to new parent
            dag.remove_edge(pred, n)
            du.reparent(dag, pred, n, new_parent_is_source=False)
            self.update_defined_var_bookkeeping(pred, n, d)

    def get_def_var_aliasing_another_node(self):
        # def var_node with a single input, edge weight one and no d_term
        dag = self.dag
        to_delete = { }
        for n in du.itr_single_input_nodes(dag, self.defined_vars):
            pred = dag.pred[n].keys()[0]
            in_mul  = dag.edge[pred][n]['weight']
            d = dag.node[n]
            assert NodeAttr.bounds not in d, d
            d_term  = d.get(NodeAttr.d_term, 0.0)
            if in_mul==1.0 and d_term==0.0:
                to_delete[n] = pred
        print('var nodes just aliasing:', to_delete)
        return to_delete

    def collect_constraint_topological_orders(self):
        dag = self.dag
        for sink_node in self.con_ends_num:
            dependecies = ancestors(dag, sink_node)
            dependecies.add(sink_node)
            con_dag = dag.subgraph(dependecies)
            eval_order = du.deterministic_topological_sort(con_dag)
            self.con_top_ord[sink_node] = eval_order

    def pprint_constraints(self):
        for sink_node in self.con_ends_num:
            eval_order = self.con_top_ord[sink_node]
            con_num = self.con_ends_num[sink_node]
            con_dag = self.dag.subgraph(eval_order)
            nvars   = self.nvars
            pprint_one_constraint(sink_node, con_num, con_dag, eval_order, nvars)

    def dbg_show_node_types(self):
        dag = self.dag
        for n in dag:
            print('%d  %s' % (n, du.get_pretty_type_str(dag, n)))
        print()

<|endoftext|>


<commit_before>import unittest
import subprocess
import re
import errno
import os
import shutil
from plexcleaner.database import Database
from plexcleaner.media import Movie
from testfixtures import log_capture

from plexcleaner import cleaner
from plexcleaner.exception import PlexCleanerException

__author__ = 'Jean-Bernard Ratte - jean.bernard.ratte@unary.ca'
# flake8: noqa

class TestCleaner(unittest.TestCase):
    _BLK_SIZE = 1024
    _KB_TO_B = 1024

    def test_get_free_fs_space(self):
        reg = re.compile("[ ]+")
        output = subprocess.check_output(['df', '-k', '-P', './']).lower()
        actual = dict(zip(reg.split(output.split('\n')[0]), reg.split(output.split('\n')[1])))
        available = self._BLK_SIZE * self._KB_TO_B * int(actual['available'])
        self.assertEqual(available, cleaner.get_free_fs_space('./'))

    @log_capture()
    def test_log_error_EACCES(self, l):
        cleaner.log_error(errno.EACCES, '/')
        self.assertIn('Not enough permission', str(l))

    @log_capture()
    def test_log_error_ENOSPC(self, l):
        cleaner.log_error(errno.ENOSPC, '/')
        self.assertIn('Not enough space', str(l))

    @log_capture()
    def test_log_error_ELSE(self, l):
        cleaner.log_error(errno.ENODATA, '/')
        self.assertIn('Unknown error', str(l))

    @log_capture()
    def test_log_error_ENOENT(self, l):
        cleaner.log_error(errno.ENOENT, '/')
        self.assertIn('Unable to locate', str(l))

    def test_is_plex_running_no_pid_file(self):
        self.assertFalse(cleaner.is_plex_running(pid_file='/PlexMediaServer.pid'))

    def test_is_plex_running_pid_file_with_ok_pid(self):
        self.assertTrue(cleaner.is_plex_running(pid_file='./tests/dummy/ok.pid'))

    def test_is_plex_running_pid_file_with_ok_no_perm_pid(self):
        self.assertTrue(cleaner.is_plex_running(pid_file='./tests/dummy/ok_no_perm.pid'))

    def test_is_plex_running_pid_file_with_empty_pid(self):
        with self.assertRaises(PlexCleanerException) as e:
            cleaner.is_plex_running(pid_file='./tests/dummy/empty.pid')
        self.assertIn('Unable to validate if Plex is running', e.exception.message)

    def test_is_plex_running_pid_file_with_bad_pid(self):
        with self.assertRaises(PlexCleanerException) as e:
            cleaner.is_plex_running(pid_file='./tests/dummy/bad.pid')
        self.assertIn('Unable to validate if Plex is running', e.exception.message)

    def test_is_plex_running_pid_file_with_max_pid(self):
        self.assertFalse(cleaner.is_plex_running(pid_file='./tests/dummy/max.pid'))

    def test_move_media(self):
        shutil.copy('./tests/library/2 Guns.avi', './tests/library/abc.avi')
        cleaner.create_dir('./tests/library/2 Guns (2009)')
        self.assertTrue(os.path.isdir('./tests/library/2 Guns (2009)'))
        moved = cleaner.move_media('./tests/library/abc.avi', './tests/library/2 Guns (2009)/2 Guns.avi')
        self.assertTrue(os.path.exists('./tests/library/2 Guns (2009)/2 Guns.avi'))
        self.assertTrue(moved)

    @log_capture()
    def test_move_media_exist(self, l):
        shutil.copy('./tests/library/2 Guns.avi', './tests/library/abc.avi')
        cleaner.create_dir('./tests/library/2 Guns (2009)')
        self.assertTrue(os.path.isdir('./tests/library/2 Guns (2009)'))
        moved = cleaner.move_media('./tests/library/abc.avi', './tests/library/2 Guns (2009)/2 Guns.avi')
        self.assertTrue(moved)
        self.assertIn('already exist', str(l))

    def test_move_media_src_default(self):
        with self.assertRaises(PlexCleanerException) as e:
            moved = cleaner.move_media('./tests/library/does_not_exist.avi', './tests/library/2 Guns (2009)/2 Guns.avi')
            self.assertFalse(moved)
        self.assertTrue('error occurred' in e.exception.message)

    def test_copy_jacket(self):
        cleaner.create_dir('./tests/library/2 Guns (2009)')
        self.assertTrue(os.path.isdir('./tests/library/2 Guns (2009)'))
        cleaner.copy_jacket('./tests/posters/com.plexapp.agents.themoviedb_1a3b1b98c2799d759e110285001f536982cdb869',
                            './tests/library/2 Guns (2009)/poster.jpg', False)
        self.assertTrue(os.path.exists('./tests/library/2 Guns (2009)/poster.jpg'))

    def test_copy_jacket_skip(self):
        cleaner.create_dir('./tests/library/13 (2009)')
        self.assertTrue(os.path.isdir('./tests/library/13 (2009)'))
        copied = cleaner.copy_jacket('./tests/posters/com.plexapp.agents.themoviedb_1a3b1b98c2799d759e110285001f536982cdb869',
                                     './tests/library/13 (2009)/poster.jpg', False)
        self.assertTrue(copied)
        self.assertTrue(os.path.exists('./tests/library/13 (2009)/poster.jpg'))
        copied = cleaner.copy_jacket('./tests/posters/com.plexapp.agents.themoviedb_1a3b1b98c2799d759e110285001f536982cdb869',
                                     './tests/library/13 (2009)/poster.jpg', True)
        self.assertFalse(copied)

    @log_capture()
    def test_copy_jacket_file_missing(self, l):
        cleaner.copy_jacket('./tests/posters/missing', './tests/library/2 Guns (2009)/poster.jpg', False)
        self.assertTrue(os.path.exists('./tests/library/2 Guns (2009)/poster.jpg'))
        self.assertIn('Unable to locate', str(l))

    def test_create_dir(self):
        cleaner.create_dir('./tests/library/test_directory')
        self.assertTrue(os.path.isdir('./tests/library/test_directory'))

    @log_capture()
    def test_create_dir_exist(self, l):
        cleaner.create_dir('./tests/library/test_directory_exist')
        self.assertTrue(os.path.isdir('./tests/library/test_directory_exist'))
        cleaner.create_dir('./tests/library/test_directory_exist')
        self.assertIn('already exist', str(l))

    def test_create_bad_perm(self):
        cleaner.create_dir('./tests/library/test_directory_perm')
        self.assertTrue(os.path.isdir('./tests/library/test_directory_perm'))
        os.chmod('./tests/library/test_directory_perm', 400)

        with self.assertRaises(PlexCleanerException) as e:
            cleaner.create_dir('./tests/library/test_directory_perm/bad')
        self.assertTrue('Unable to create' in e.exception.message)

    def test_update_database(self):
        with Database(database_override='./tests/database/com.plexapp.plugins.library.db') as db:
            m = Movie(1, u"a", '/tests/b.avi', 2010, 2, 2.2, 'c',
                      './tests/posters/com.plexapp.agents.themoviedb_1a3b1b98c2799d759e110285001f536982cdb869')
            before = db._cursor.execute('SELECT file FROM media_parts WHERE id = ?', (m.mid, )).fetchone()
            cleaner.update_database(db, m)
            after = db._cursor.execute('SELECT file FROM media_parts WHERE id = ?', (m.mid, )).fetchone()
            self.assertNotEqual(before[0], after[0])
            db.rollback()

    def test_update_database_no_update(self):
        with Database(database_override='./tests/database/com.plexapp.plugins.library.db') as db:
            m = Movie(1, u"a", '/tests/b.avi', 2010, 2, 2.2, 'c',
                      './tests/posters/com.plexapp.agents.themoviedb_1a3b1b98c2799d759e110285001f536982cdb869')
            before = db._cursor.execute('SELECT file FROM media_parts WHERE id = ?', (m.mid, )).fetchone()
            cleaner.update_database(db, m)
            after = db._cursor.execute('SELECT file FROM media_parts WHERE id = ?', (m.mid, )).fetchone()
            self.assertEqual(before[0], after[0])
<commit_msg>added new test for perms<commit_after>import unittest
import subprocess
import re
import errno
import os
import shutil
from plexcleaner.database import Database
from plexcleaner.media import Movie
from testfixtures import log_capture

from plexcleaner import cleaner
from plexcleaner.exception import PlexCleanerException

__author__ = 'Jean-Bernard Ratte - jean.bernard.ratte@unary.ca'
# flake8: noqa

class TestCleaner(unittest.TestCase):
    _BLK_SIZE = 1024
    _KB_TO_B = 1024

    def test_get_free_fs_space(self):
        reg = re.compile("[ ]+")
        output = subprocess.check_output(['df', '-k', '-P', './']).lower()
        actual = dict(zip(reg.split(output.split('\n')[0]), reg.split(output.split('\n')[1])))
        available = self._BLK_SIZE * self._KB_TO_B * int(actual['available'])
        self.assertEqual(available, cleaner.get_free_fs_space('./'))

    @log_capture()
    def test_log_error_EACCES(self, l):
        cleaner.log_error(errno.EACCES, '/')
        self.assertIn('Not enough permission', str(l))

    @log_capture()
    def test_log_error_ENOSPC(self, l):
        cleaner.log_error(errno.ENOSPC, '/')
        self.assertIn('Not enough space', str(l))

    @log_capture()
    def test_log_error_ELSE(self, l):
        cleaner.log_error(errno.ENODATA, '/')
        self.assertIn('Unknown error', str(l))

    @log_capture()
    def test_log_error_ENOENT(self, l):
        cleaner.log_error(errno.ENOENT, '/')
        self.assertIn('Unable to locate', str(l))

    def test_is_plex_running_no_pid_file(self):
        self.assertFalse(cleaner.is_plex_running(pid_file='/PlexMediaServer.pid'))

    def test_is_plex_running_pid_file_with_ok_pid(self):
        self.assertTrue(cleaner.is_plex_running(pid_file='./tests/dummy/ok.pid'))

    def test_is_plex_running_pid_file_with_ok_no_perm_pid(self):
        self.assertTrue(cleaner.is_plex_running(pid_file='./tests/dummy/ok_no_perm.pid'))

    def test_is_plex_running_pid_file_with_empty_pid(self):
        with self.assertRaises(PlexCleanerException) as e:
            cleaner.is_plex_running(pid_file='./tests/dummy/empty.pid')
        self.assertIn('Unable to validate if Plex is running', e.exception.message)

    def test_is_plex_running_pid_file_with_bad_pid(self):
        with self.assertRaises(PlexCleanerException) as e:
            cleaner.is_plex_running(pid_file='./tests/dummy/bad.pid')
        self.assertIn('Unable to validate if Plex is running', e.exception.message)

    def test_is_plex_running_pid_file_with_max_pid(self):
        self.assertFalse(cleaner.is_plex_running(pid_file='./tests/dummy/max.pid'))

    def test_move_media(self):
        shutil.copy('./tests/library/2 Guns.avi', './tests/library/abc.avi')
        cleaner.create_dir('./tests/library/2 Guns (2009)')
        self.assertTrue(os.path.isdir('./tests/library/2 Guns (2009)'))
        moved = cleaner.move_media('./tests/library/abc.avi', './tests/library/2 Guns (2009)/2 Guns.avi')
        self.assertTrue(os.path.exists('./tests/library/2 Guns (2009)/2 Guns.avi'))
        self.assertTrue(moved)

    @log_capture()
    def test_move_media_exist(self, l):
        shutil.copy('./tests/library/2 Guns.avi', './tests/library/abc.avi')
        cleaner.create_dir('./tests/library/2 Guns (2009)')
        self.assertTrue(os.path.isdir('./tests/library/2 Guns (2009)'))
        moved = cleaner.move_media('./tests/library/abc.avi', './tests/library/2 Guns (2009)/2 Guns.avi')
        self.assertTrue(moved)
        self.assertIn('already exist', str(l))

    def test_move_media_src_default(self):
        with self.assertRaises(PlexCleanerException) as e:
            moved = cleaner.move_media('./tests/library/does_not_exist.avi', './tests/library/2 Guns (2009)/2 Guns.avi')
            self.assertFalse(moved)
        self.assertTrue('error occurred' in e.exception.message)

    def test_copy_jacket(self):
        cleaner.create_dir('./tests/library/2 Guns (2009)')
        self.assertTrue(os.path.isdir('./tests/library/2 Guns (2009)'))
        cleaner.copy_jacket('./tests/posters/com.plexapp.agents.themoviedb_1a3b1b98c2799d759e110285001f536982cdb869',
                            './tests/library/2 Guns (2009)/poster.jpg', False)
        self.assertTrue(os.path.exists('./tests/library/2 Guns (2009)/poster.jpg'))

    def test_copy_jacket_skip(self):
        cleaner.create_dir('./tests/library/13 (2009)')
        self.assertTrue(os.path.isdir('./tests/library/13 (2009)'))
        copied = cleaner.copy_jacket('./tests/posters/com.plexapp.agents.themoviedb_1a3b1b98c2799d759e110285001f536982cdb869',
                                     './tests/library/13 (2009)/poster.jpg', False)
        self.assertTrue(copied)
        self.assertTrue(os.path.exists('./tests/library/13 (2009)/poster.jpg'))
        copied = cleaner.copy_jacket('./tests/posters/com.plexapp.agents.themoviedb_1a3b1b98c2799d759e110285001f536982cdb869',
                                     './tests/library/13 (2009)/poster.jpg', True)
        self.assertFalse(copied)

    @log_capture()
    def test_copy_jacket_file_missing(self, l):
        cleaner.copy_jacket('./tests/posters/missing', './tests/library/2 Guns (2009)/poster.jpg', False)
        self.assertTrue(os.path.exists('./tests/library/2 Guns (2009)/poster.jpg'))
        self.assertIn('Unable to locate', str(l))

    def test_create_dir(self):
        cleaner.create_dir('./tests/library/test_directory')
        self.assertTrue(os.path.isdir('./tests/library/test_directory'))

    @log_capture()
    def test_create_dir_exist(self, l):
        cleaner.create_dir('./tests/library/test_directory_exist')
        self.assertTrue(os.path.isdir('./tests/library/test_directory_exist'))
        cleaner.create_dir('./tests/library/test_directory_exist')
        self.assertIn('already exist', str(l))

    def test_create_bad_perm(self):
        cleaner.create_dir('./tests/library/test_directory_perm')
        self.assertTrue(os.path.isdir('./tests/library/test_directory_perm'))
        os.chmod('./tests/library/test_directory_perm', 400)

        with self.assertRaises(PlexCleanerException) as e:
            cleaner.create_dir('./tests/library/test_directory_perm/bad')
        self.assertTrue('Unable to create' in e.exception.message)

    def test_update_database(self):
        with Database(database_override='./tests/database/com.plexapp.plugins.library.db') as db:
            m = Movie(1, u"a", '/tests/b.avi', 2010, 2, 2.2, 'c',
                      './tests/posters/com.plexapp.agents.themoviedb_1a3b1b98c2799d759e110285001f536982cdb869')
            before = db._cursor.execute('SELECT file FROM media_parts WHERE id = ?', (m.mid, )).fetchone()
            cleaner.update_database(db, m)
            after = db._cursor.execute('SELECT file FROM media_parts WHERE id = ?', (m.mid, )).fetchone()
            self.assertNotEqual(before[0], after[0])
            db.rollback()

    def test_check_permission(self):
        self.assertFalse(cleaner.check_permission('/'))
<|endoftext|>


<commit_before>import unittest

import pandas.util.testing as pdt
import recordlinkage

from numpy import nan, arange
import pandas

STRING_SIM_ALGORITHMS = [
    'jaro', 'jaro_winkler', 'dameraulevenshtein',
    'levenshtein', 'q_gram', 'cosine'
]

# nosetests tests/test_compare.py:TestCompare

class TestCompare(unittest.TestCase):

    @classmethod
    def setUpClass(self):

        self.A = pandas.DataFrame([
            [u'Donell', u'Gerlach', 20, u'New York'],
            [nan, u'Smit', 17, u'Boston'],
            [u'Kalie', u'Flatley', 33, u'Boston'],
            [u'Kittie', u'Schuster', 27, nan],
            [nan, nan, nan, u'South Devyn']
        ],
            columns=['given_name', 'lastname', 'age', 'place'])

        self.A.index.name = 'index_df1'

        self.B = pandas.DataFrame([
            [u'Donel', u'Gerleach', 20, u'New York'],
            [nan, u'Smith', 17, u'Boston'],
            [u'Kaly', u'Flatley', 33, u'Boston'],
            [u'Kittie', nan, 20, nan],
            [u'Bob', u'Armstrong', 70, u'Lake Gavinmouth']
        ],
            columns=['given_name', 'lastname', 'age', 'place'])

        self.B.index.name = 'index_df2'

        self.index_AB = pandas.MultiIndex.from_arrays(
            [arange(len(self.A)), arange(len(self.B))],
            names=[self.A.index.name, self.B.index.name])

# nosetests tests/test_compare.py:TestCompareAPI

class TestCompareAPI(TestCompare):

    def test_instance_linking(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        result = comp.exact('given_name', 'given_name')
        self.assertIsInstance(result, pandas.Series)
        self.assertEqual(result.name, None)

        result = comp.numeric('age', 'age', 2)
        self.assertIsInstance(result, pandas.Series)
        self.assertEqual(result.name, None)

        for alg in STRING_SIM_ALGORITHMS:

            # Missing values
            result = comp.fuzzy('given_name', 'given_name', method=alg)

            self.assertIsInstance(result, pandas.Series)
            self.assertEqual(result.name, None)

    def test_name_series_linking(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        result = comp.exact('given_name', 'given_name', name="given_name_comp")
        self.assertIsInstance(result, pandas.Series)
        self.assertEqual(result.name, "given_name_comp")

        result = comp.numeric('age', 'age', 2, name="given_name_comp")
        self.assertIsInstance(result, pandas.Series)
        self.assertEqual(result.name, "given_name_comp")

        for alg in STRING_SIM_ALGORITHMS:

            # Missing values
            result = comp.fuzzy('given_name', 'given_name',
                                method=alg, name="given_name_comp")

            self.assertIsInstance(result, pandas.Series)
            self.assertEqual(result.name, "given_name_comp")

# nosetests tests/test_compare.py:TestCompareAlgorithms

class TestCompareAlgorithms(TestCompare):

    def test_exact(self):

        self.A['test'] = ['Bob', 'Myrthe', 'Ally', 'John', 'Rose']
        self.B['test'] = ['Bob', 'Myrte', 'Ally', 'John', 'Roze']

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        result = comp.exact('test', 'test')
        expected = pandas.Series([1, 0, 1, 1, 0], index=self.index_AB)

        pdt.assert_series_equal(result, expected)

    def test_link_exact_missing(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        # Missing values as 0
        result = comp.exact('given_name', 'given_name', missing_value=0)
        expected = pandas.Series([0, 0, 0, 1, 0], index=self.index_AB)

        pdt.assert_series_equal(result, expected)

        # Missing values as nan
        result = comp.exact('given_name', 'given_name', missing_value=nan)
        expected = pandas.Series([0, nan, 0, 1, nan], index=self.index_AB)

        pdt.assert_series_equal(result, expected)

        # Missing values as nan
        result = comp.exact('given_name', 'given_name', missing_value=9)
        expected = pandas.Series([0, 9, 0, 1, 9], index=self.index_AB)

        pdt.assert_series_equal(result, expected)

    def test_link_exact_disagree(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        # Missing values 0 and disagreement as 2
        result = comp.exact('given_name', 'given_name',
                            disagree_value=2, missing_value=0, name='y_name')
        expected = pandas.Series(
            [2, 0, 2, 1, 0], index=self.index_AB, name='y_name')

        pdt.assert_series_equal(result, expected)

    def test_dedup_exact_basic(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.A)

        # Missing values
        result = comp.exact('given_name', 'given_name')  # , name='y_name')
        # , name='y_name')
        expected = pandas.Series([1, 0, 1, 1, 0], index=self.index_AB)

        pdt.assert_series_equal(result, expected)

    def test_numeric(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        # Missing values
        result = comp.numeric('age', 'age', 2)
        expected = pandas.Series(
            [1, 1, 1, 0, 0], index=self.index_AB)  # , name='age')

        pdt.assert_series_equal(result, expected)

    def test_geo(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        # Missing values
        result = comp.geo('age', 'age', 'age', 'age', 2)

        self.assertTrue(result.notnull().any())
        self.assertTrue((result[result.notnull()] >= 0).all())
        self.assertTrue((result[result.notnull()] <= 1).all())

    def test_numeric_batch(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        for alg in ['step', 'linear', 'squared']:

            print (alg)

            # Missing values
            result = comp.numeric('age', 'age', 2, method=alg)

            print (result)

            self.assertTrue(result.notnull().any())
            self.assertTrue((result[result.notnull()] >= 0).all())
            self.assertTrue((result[result.notnull()] <= 1).all())

    def test_fuzzy_does_not_exist(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.A)

        self.assertRaises(
            ValueError, comp.fuzzy, 'given_name',
            'given_name', name='y_name', method='unknown_algorithm')

    def test_fuzzy_same_labels(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        for alg in STRING_SIM_ALGORITHMS:

            print (alg)

            # Missing values
            result = comp.fuzzy('given_name', 'given_name',
                                method=alg, missing_value=0)
            result = comp.fuzzy('given_name', 'given_name',
                                alg, missing_value=0)

            print (result)

            self.assertTrue(result.notnull().any())
            self.assertTrue((result[result.notnull()] >= 0).all())
            self.assertTrue((result[result.notnull()] <= 1).all())

    def test_fuzzy_different_labels(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        for alg in STRING_SIM_ALGORITHMS:

            print (alg)

            # Missing values
            # Change in future (should work without method)
            result = comp.fuzzy('given_name', 'given_name',
                                method=alg, missing_value=0)

            print (result)

            self.assertTrue(result.notnull().any())
            self.assertTrue((result[result.notnull()] >= 0).all())
            self.assertTrue((result[result.notnull()] <= 1).all())

            # Debug trick
            # if alg == 'q_gram':
            #     rr

    # def test_batch_compare(self):

    #     comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

    #     # Missing values as 0
    #     result = comp.exact('given_name', 'given_name',
    #                         missing_value=0, name='y_name')

        # pdt.assert_series_equal(result, expected)
<commit_msg>Update deprecated tests fuzzy-->string<commit_after>import unittest

import pandas.util.testing as pdt
import recordlinkage

from numpy import nan, arange
import pandas

STRING_SIM_ALGORITHMS = [
    'jaro', 'jaro_winkler', 'dameraulevenshtein',
    'levenshtein', 'q_gram', 'cosine'
]

# nosetests tests/test_compare.py:TestCompare

class TestCompare(unittest.TestCase):

    @classmethod
    def setUpClass(self):

        self.A = pandas.DataFrame([
            [u'Donell', u'Gerlach', 20, u'New York'],
            [nan, u'Smit', 17, u'Boston'],
            [u'Kalie', u'Flatley', 33, u'Boston'],
            [u'Kittie', u'Schuster', 27, nan],
            [nan, nan, nan, u'South Devyn']
        ],
            columns=['given_name', 'lastname', 'age', 'place'])

        self.A.index.name = 'index_df1'

        self.B = pandas.DataFrame([
            [u'Donel', u'Gerleach', 20, u'New York'],
            [nan, u'Smith', 17, u'Boston'],
            [u'Kaly', u'Flatley', 33, u'Boston'],
            [u'Kittie', nan, 20, nan],
            [u'Bob', u'Armstrong', 70, u'Lake Gavinmouth']
        ],
            columns=['given_name', 'lastname', 'age', 'place'])

        self.B.index.name = 'index_df2'

        self.index_AB = pandas.MultiIndex.from_arrays(
            [arange(len(self.A)), arange(len(self.B))],
            names=[self.A.index.name, self.B.index.name])

# nosetests tests/test_compare.py:TestCompareAPI

class TestCompareAPI(TestCompare):

    def test_instance_linking(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        result = comp.exact('given_name', 'given_name')
        self.assertIsInstance(result, pandas.Series)
        self.assertEqual(result.name, None)

        result = comp.numeric('age', 'age', 2)
        self.assertIsInstance(result, pandas.Series)
        self.assertEqual(result.name, None)

        for alg in STRING_SIM_ALGORITHMS:

            # Missing values
            result = comp.string('given_name', 'given_name', method=alg)

            self.assertIsInstance(result, pandas.Series)
            self.assertEqual(result.name, None)

    def test_name_series_linking(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        result = comp.exact('given_name', 'given_name', name="given_name_comp")
        self.assertIsInstance(result, pandas.Series)
        self.assertEqual(result.name, "given_name_comp")

        result = comp.numeric('age', 'age', 2, name="given_name_comp")
        self.assertIsInstance(result, pandas.Series)
        self.assertEqual(result.name, "given_name_comp")

        for alg in STRING_SIM_ALGORITHMS:

            # Missing values
            result = comp.string('given_name', 'given_name',
                                 method=alg, name="given_name_comp")

            self.assertIsInstance(result, pandas.Series)
            self.assertEqual(result.name, "given_name_comp")

# nosetests tests/test_compare.py:TestCompareAlgorithms

class TestCompareAlgorithms(TestCompare):

    def test_exact(self):

        self.A['test'] = ['Bob', 'Myrthe', 'Ally', 'John', 'Rose']
        self.B['test'] = ['Bob', 'Myrte', 'Ally', 'John', 'Roze']

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        result = comp.exact('test', 'test')
        expected = pandas.Series([1, 0, 1, 1, 0], index=self.index_AB)

        pdt.assert_series_equal(result, expected)

    def test_link_exact_missing(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        # Missing values as 0
        result = comp.exact('given_name', 'given_name', missing_value=0)
        expected = pandas.Series([0, 0, 0, 1, 0], index=self.index_AB)

        pdt.assert_series_equal(result, expected)

        # Missing values as nan
        result = comp.exact('given_name', 'given_name', missing_value=nan)
        expected = pandas.Series([0, nan, 0, 1, nan], index=self.index_AB)

        pdt.assert_series_equal(result, expected)

        # Missing values as nan
        result = comp.exact('given_name', 'given_name', missing_value=9)
        expected = pandas.Series([0, 9, 0, 1, 9], index=self.index_AB)

        pdt.assert_series_equal(result, expected)

    def test_link_exact_disagree(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        # Missing values 0 and disagreement as 2
        result = comp.exact('given_name', 'given_name',
                            disagree_value=2, missing_value=0, name='y_name')
        expected = pandas.Series(
            [2, 0, 2, 1, 0], index=self.index_AB, name='y_name')

        pdt.assert_series_equal(result, expected)

    def test_dedup_exact_basic(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.A)

        # Missing values
        result = comp.exact('given_name', 'given_name')  # , name='y_name')
        # , name='y_name')
        expected = pandas.Series([1, 0, 1, 1, 0], index=self.index_AB)

        pdt.assert_series_equal(result, expected)

    def test_numeric(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        # Missing values
        result = comp.numeric('age', 'age', 2)
        expected = pandas.Series(
            [1, 1, 1, 0, 0], index=self.index_AB)  # , name='age')

        pdt.assert_series_equal(result, expected)

    def test_geo(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        # Missing values
        result = comp.geo('age', 'age', 'age', 'age', 2)

        self.assertTrue(result.notnull().any())
        self.assertTrue((result[result.notnull()] >= 0).all())
        self.assertTrue((result[result.notnull()] <= 1).all())

    def test_numeric_batch(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        for alg in ['step', 'linear', 'squared']:

            print (alg)

            # Missing values
            result = comp.numeric('age', 'age', 2, method=alg)

            print (result)

            self.assertTrue(result.notnull().any())
            self.assertTrue((result[result.notnull()] >= 0).all())
            self.assertTrue((result[result.notnull()] <= 1).all())

    def test_fuzzy_does_not_exist(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.A)

        self.assertRaises(
            ValueError, comp.string, 'given_name',
            'given_name', name='y_name', method='unknown_algorithm')

    def test_fuzzy_same_labels(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        for alg in STRING_SIM_ALGORITHMS:

            print (alg)

            # Missing values
            result = comp.string('given_name', 'given_name',
                                method=alg, missing_value=0)
            result = comp.string('given_name', 'given_name',
                                alg, missing_value=0)

            print (result)

            self.assertTrue(result.notnull().any())
            self.assertTrue((result[result.notnull()] >= 0).all())
            self.assertTrue((result[result.notnull()] <= 1).all())

    def test_fuzzy_different_labels(self):

        comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

        for alg in STRING_SIM_ALGORITHMS:

            print (alg)

            # Missing values
            # Change in future (should work without method)
            result = comp.string('given_name', 'given_name',
                                method=alg, missing_value=0)

            print (result)

            self.assertTrue(result.notnull().any())
            self.assertTrue((result[result.notnull()] >= 0).all())
            self.assertTrue((result[result.notnull()] <= 1).all())

            # Debug trick
            # if alg == 'q_gram':
            #     rr

    # def test_batch_compare(self):

    #     comp = recordlinkage.Compare(self.index_AB, self.A, self.B)

    #     # Missing values as 0
    #     result = comp.exact('given_name', 'given_name',
    #                         missing_value=0, name='y_name')

        # pdt.assert_series_equal(result, expected)
<|endoftext|>


<commit_before>from datetime import datetime, timedelta
from http.cookies import SimpleCookie
from sanic import Sanic
from sanic.response import json, text
from sanic.utils import sanic_endpoint_test

# ------------------------------------------------------------ #
#  GET
# ------------------------------------------------------------ #

def test_cookies():
    app = Sanic('test_text')

    @app.route('/')
    def handler(request):
        response = text('Cookies are: {}'.format(request.cookies['test']))
        response.cookies['right_back'] = 'at you'
        return response

    request, response = sanic_endpoint_test(app, cookies={"test": "working!"})
    response_cookies = SimpleCookie()
    response_cookies.load(response.headers.get('Set-Cookie', {}))

    assert response.text == 'Cookies are: working!'
    assert response_cookies['right_back'].value == 'at you'

def test_cookie_options():
    app = Sanic('test_text')

    @app.route('/')
    def handler(request):
        response = text("OK")
        response.cookies['test'] = 'at you'
        response.cookies['test']['httponly'] = True
        response.cookies['test']['expires'] = datetime.now() + timedelta(seconds=10)
        return response

    request, response = sanic_endpoint_test(app)
    response_cookies = SimpleCookie()
    response_cookies.load(response.headers.get('Set-Cookie', {}))

    assert response_cookies['test'].value == 'at you'
    assert response_cookies['test']['httponly'] == True<commit_msg>test for http2 lowercase header cookies<commit_after>from datetime import datetime, timedelta
from http.cookies import SimpleCookie
from sanic import Sanic
from sanic.response import json, text
from sanic.utils import sanic_endpoint_test

# ------------------------------------------------------------ #
#  GET
# ------------------------------------------------------------ #

def test_cookies():
    app = Sanic('test_text')

    @app.route('/')
    def handler(request):
        response = text('Cookies are: {}'.format(request.cookies['test']))
        response.cookies['right_back'] = 'at you'
        return response

    request, response = sanic_endpoint_test(app, cookies={"test": "working!"})
    response_cookies = SimpleCookie()
    response_cookies.load(response.headers.get('Set-Cookie', {}))

    assert response.text == 'Cookies are: working!'
    assert response_cookies['right_back'].value == 'at you'

def test_http2_cookies():
    app = Sanic('test_http2_cookies')

    @app.route('/')
    async def handler(request):
        response = text('Cookies are: {}'.format(request.cookies['test']))
        return response

    headers = {'cookie': 'test=working!'}
    request, response = sanic_endpoint_test(app, headers=headers)

    assert response.text == 'Cookies are: working!'

def test_cookie_options():
    app = Sanic('test_text')

    @app.route('/')
    def handler(request):
        response = text("OK")
        response.cookies['test'] = 'at you'
        response.cookies['test']['httponly'] = True
        response.cookies['test']['expires'] = datetime.now() + timedelta(seconds=10)
        return response

    request, response = sanic_endpoint_test(app)
    response_cookies = SimpleCookie()
    response_cookies.load(response.headers.get('Set-Cookie', {}))

    assert response_cookies['test'].value == 'at you'
    assert response_cookies['test']['httponly'] == True<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from .base import CounterTestCase
from random import randint

class CounterTests(CounterTestCase):
    def test_mixin(self):
        for name in ('Builtin', 'Counter', 'Test'):
            u = self.User(username=name)
            u.save()
            u.age = randint(0, 99)
            u.save()
        # counter should only increases after the first save
        self.assertEqual(self.User.count(), 3)

    def test_initial(self):
        self.assertEqual(0, self.Counter.count('something-new'))

    def test_increase(self):
        k = 'another'
        self.Counter.increase(k)  # increase by 1
        self.assertEqual(1, self.Counter.count(k))

    def test_decrease(self):
        k = 'decrease'
        self.Counter.increase(k)  # increase by 1
        self.Counter.decrease(k)  # decrease by 1
        self.assertEqual(0, self.Counter.count(k))

    def test_change_by(self):
        k = 'more'
        self.Counter.change_by(k, 3)   # increase by 3
        self.assertEqual(3, self.Counter.count(k))

        count = self.Counter.count(k)
        self.Counter.change_by(k, -1)  # decrease by 1
        self.assertEqual(count - 1, self.Counter.count(k))
<commit_msg>simpler CounterTests<commit_after># -*- coding: utf-8 -*-
from .base import CounterTestCase
from random import randint

class CounterTests(CounterTestCase):
    def test_mixin(self):
        for name in ('Builtin', 'Counter', 'Test'):
            u = self.User(username=name)
            u.save()
            u.age = randint(0, 99)
            u.save()
        # counter should only increases after the first save
        self.assertEqual(self.User.count(), 3)

    def test_initial(self):
        self.assertEqual(0, self.Counter.count('something-new'))

    def test_increase(self):
        k = 'another'
        self.assertEqual(1, self.Counter.increase(k))  # increase by 1

    def test_decrease(self):
        k = 'decrease'
        self.Counter.increase(k)  # increase by 1
        self.Counter.decrease(k)  # decrease by 1
        self.assertEqual(0, self.Counter.count(k))

    def test_change_by(self):
        k = 'more'
        self.assertEqual(3, self.Counter.change_by(k, 3))       # increase 0 by 3
        self.assertEqual(3 - 1, self.Counter.change_by(k, -1))  # decrease 3 by 1
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import unicode_literals

import pytest

from durga import element

def test_get_default_url_attribute(resource):
    class DefaultURLElement(element.Element):
        url = 'https://api.example.com/movies/23'

    assert DefaultURLElement(resource).get_url() == DefaultURLElement.url

def test_get_custom_url_attribute(resource):
    resource.url_attribute = 'resource_uri'

    class CustomURLElement(element.Element):
        _resource = resource
        resource_uri = 'https://api.example.com/movies/23'

    assert CustomURLElement(resource).get_url() == CustomURLElement.resource_uri

def test_get_dynamic_url(resource):
    class DynamicURLElement(element.Element):
        _resource = resource
        id = '23'

    with pytest.raises(AssertionError) as excinfo:
        DynamicURLElement(None).get_url()
    assert excinfo.value.msg == 'You must define an id_attribute attribute at NoneType.'
    resource.id_attribute = 'id'
    element_obj = DynamicURLElement(resource)
    assert element_obj.get_url() == '/'.join([resource.get_url(), element_obj.id])
<commit_msg>Element._resource should only be set using the constructor<commit_after># -*- coding: utf-8 -*-
from __future__ import unicode_literals

import pytest

from durga import element

def test_get_default_url_attribute(resource):
    class DefaultURLElement(element.Element):
        url = 'https://api.example.com/movies/23'

    assert DefaultURLElement(resource).get_url() == DefaultURLElement.url

def test_get_custom_url_attribute(resource):
    resource.url_attribute = 'resource_uri'

    class CustomURLElement(element.Element):
        resource_uri = 'https://api.example.com/movies/23'

    assert CustomURLElement(resource).get_url() == CustomURLElement.resource_uri

def test_get_dynamic_url(resource):
    class DynamicURLElement(element.Element):
        id = '23'

    with pytest.raises(AssertionError) as excinfo:
        DynamicURLElement(None).get_url()
    assert excinfo.value.msg == 'You must define an id_attribute attribute at NoneType.'
    resource.id_attribute = 'id'
    element_obj = DynamicURLElement(resource)
    assert element_obj.get_url() == '/'.join([resource.get_url(), element_obj.id])
<|endoftext|>


<commit_before># An example file full of tests for py.test
# Documentation: http://pytest.org/

def test_example():
    # If the function runs to completion, all is well.
    pass
<commit_msg>remove example test<commit_after><|endoftext|>


<commit_before># $Id$

## PycURL module
import pycurl

## Callback function invoked when progress information is updated
def progress(download_t, download_d, upload_t, upload_d):
    print 'Total to download %d bytes, have %d bytes so far' % \
          (download_t, download_d)

url = 'http://www.cnn.com'

print 'Starting downloading', url
print
f = open('body', 'w')
h = open('header', 'w')
c = pycurl.init()
c.setopt(pycurl.URL, url)
c.setopt(pycurl.FILE, f)
c.setopt(pycurl.NOPROGRESS, 0)
c.setopt(pycurl.PROGRESSFUNCTION, progress)
c.setopt(pycurl.FOLLOWLOCATION, 1)
c.setopt(pycurl.MAXREDIRS, 5)
c.setopt(pycurl.WRITEHEADER, h)
c.setopt(pycurl.OPT_FILETIME, 1)
c.perform()

print
print 'Download speed: %f bytes/second' % c.getinfo(pycurl.SPEED_DOWNLOAD)
print 'Document size: %d bytes' % c.getinfo(pycurl.SIZE_DOWNLOAD)
print 'Effective URL:', c.getinfo(pycurl.EFFECTIVE_URL)
print 'Content-type:', c.getinfo(pycurl.CONTENT_TYPE)
print 'Redirect-time:', c.getinfo(pycurl.REDIRECT_TIME)
print 'Redirect-count:', c.getinfo(pycurl.REDIRECT_COUNT)
print 'Filetime:', c.getinfo(pycurl.INFO_FILETIME)
print
print "Header is in file 'header', body is in file 'body'"

c.cleanup()
f.close()
h.close()
<commit_msg>filetime test now included here<commit_after># $Id$

import time

## PycURL module
import pycurl

## Callback function invoked when progress information is updated
def progress(download_t, download_d, upload_t, upload_d):
    print 'Total to download %d bytes, have %d bytes so far' % \
          (download_t, download_d)

url = 'http://www.cnn.com'

print 'Starting downloading', url
print
f = open('body', 'w')
h = open('header', 'w')
c = pycurl.init()
c.setopt(pycurl.URL, url)
c.setopt(pycurl.FILE, f)
c.setopt(pycurl.NOPROGRESS, 0)
c.setopt(pycurl.PROGRESSFUNCTION, progress)
c.setopt(pycurl.FOLLOWLOCATION, 1)
c.setopt(pycurl.MAXREDIRS, 5)
c.setopt(pycurl.WRITEHEADER, h)
c.setopt(pycurl.OPT_FILETIME, 1)
c.perform()

print
print 'Download speed: %f bytes/second' % c.getinfo(pycurl.SPEED_DOWNLOAD)
print 'Document size: %d bytes' % c.getinfo(pycurl.SIZE_DOWNLOAD)
print 'Effective URL:', c.getinfo(pycurl.EFFECTIVE_URL)
print 'Content-type:', c.getinfo(pycurl.CONTENT_TYPE)
print 'Redirect-time:', c.getinfo(pycurl.REDIRECT_TIME)
print 'Redirect-count:', c.getinfo(pycurl.REDIRECT_COUNT)
epoch = c.getinfo(pycurl.INFO_FILETIME)
print 'Filetime: %d (%s)' % (epoch, time.ctime(epoch))
print
print "Header is in file 'header', body is in file 'body'"

c.cleanup()
f.close()
h.close()
<|endoftext|>


<commit_before>"""
Tests for gravity-style spatial interaction models
"""

__author__ = 'toshan'

import unittest
import numpy as np
import pandas as pd
import gravity2 as grav

class TestUnconstrained(unittest.TestCase):
    """Unconstrained class for unit tests"""
    def setUp(self):
        self.f = np.array([56, 100.8, 173.6, 235.2, 87.36,
                           28., 100.8, 69.44, 235.2, 145.6,
                           22., 26.4, 136.4, 123.2, 343.2,
                           14., 75.6, 130.2, 70.56, 163.8,
                           22, 59.4,  204.6,  110.88,  171.6])
        self.V = np.repeat(np.array([56, 56, 44, 42, 66]), 5)
        self.o = np.repeat(np.array(range(1, 6)), 5)
        self.W = np.tile(np.array([10, 18, 62, 84, 78]), 5)
        self.d = np.tile(np.array(range(1, 6)), 5)
        self.dij = np.array([10, 10, 20, 20, 50,
                             20, 10, 50, 20, 30,
                             20, 30, 20, 30, 10,
                             30, 10, 20, 50, 20,
                             30, 20, 20, 50, 30])
        self.dt = pd.DataFrame({'origins': self.o,
                                'destinations': self.d,
                                'V': self.V,
                                'W': self.W,
                                'Dij': self.dij,
                                'flows': self.f})

    def test_Uconstrained(self):
        model = grav.Unconstrained(self.dt, 'origins', 'destinations', 'flows',
            ['V'], ['W'], 'Dij', 'pow')
        V = 1.0
        W = 1.0
        beta = -1.0
        self.assertAlmostEqual(model.p['V'], V, delta=.0001)
        self.assertAlmostEqual(model.p['W'], W, delta=.0001)
        self.assertAlmostEqual(model.p['beta'], beta, delta=.0001)

class TestProductionConstrained(unittest.TestCase):
    """Production constrained class for unit tests"""
    def setUp(self):
        self.f = np.array([0, 6469, 7629, 20036, 4690,
                           6194, 11688, 2243, 8857, 7248,
                           3559, 9221, 10099, 22866, 3388,
                           9986, 46618, 11639, 1380, 5261,
                           5985, 6731, 2704, 12250, 16132])
        self.o = np.repeat(1, 25)
        self.d = np.array(range(1, 26))
        self.dij = np.array([0, 576, 946, 597, 373,
                             559, 707, 1208, 602, 692,
                             681, 1934, 332, 595, 906,
                             425, 755, 672, 1587, 526,
                             484, 2141, 2182, 410, 540])
        self.pop = np.array([1596000, 2071000, 3376000, 6978000, 1345000,
                             2064000, 2378000, 1239000, 4435000, 1999000,
                             1274000, 7042000, 834000, 1268000, 1965000,
                             1046000, 12131000, 4824000, 969000, 2401000,
                             2410000, 2847000, 1425000, 1089000, 2909000])
        self.dt = pd.DataFrame({'origins': self.o,
                                'destinations': self.d,
                                'pop': self.pop,
                                'Dij': self.dij,
                                'flows': self.f})

    def test_Production_Constrained(self):
        model = grav.ProductionConstrained(self.dt, 'origins', 'destinations', 'flows',
            ['pop'], 'Dij', 'pow')
        pop = 0.7818262
        beta = -0.7365098
        self.assertAlmostEqual(model.p['pop'], pop, delta=.0001)
        self.assertAlmostEqual(model.p['beta'], beta, delta=.0001)

class TestAttractionConstrained(unittest.TestCase):
    """Attraction constrained class for unit tests"""
    def setUp(self):
        self.f = np.array([56, 100.8, 173.6, 235.2, 87.36,
                           28., 100.8, 69.44, 235.2, 145.6,
                           22., 26.4, 136.4, 123.2, 343.2,
                           14., 75.6, 130.2, 70.56, 163.8,
                           22, 59.4,  204.6,  110.88,  171.6])
        self.V = np.repeat(np.array([56, 56, 44, 42, 66]), 5)
        self.o = np.repeat(np.array(range(1, 6)), 5)
        self.W = np.tile(np.array([10, 18, 62, 84, 78]), 5)
        self.d = np.tile(np.array(range(1, 6)), 5)
        self.dij = np.array([10, 10, 20, 20, 50,
                             20, 10, 50, 20, 30,
                             20, 30, 20, 30, 10,
                             30, 10, 20, 50, 20,
                             30, 20, 20, 50, 30])
        self.dt = pd.DataFrame({'origins': self.o,
                                'destinations': self.d,
                                'V': self.V,
                                'Dij': self.dij,
                                'flows': self.f})

    def test_Attraction_Constrained(self):
        model = grav.AttractionConstrained(self.dt, 'origins', 'destinations', 'flows',
            ['V'], 'Dij', 'pow')
        V = 1.0
        beta = -1.0
        self.assertAlmostEqual(model.p['V'], V, delta=.0001)
        self.assertAlmostEqual(model.p['beta'], beta, delta=.0001)

class TestDoublyConstrained(unittest.TestCase):
    """Doubly constrained class for unit tests"""
    def setUp(self):
        self.f = np.array([0, 180048, 79223, 26887, 198144, 17995, 35563, 30528, 110792,
                        283049, 0, 300345, 67280, 718673, 55094, 93434, 87987, 268458,
                        87267, 237229, 0, 281791, 551483, 230788, 178517, 172711, 394481,
                        29877, 60681, 286580, 0, 143860, 49892, 185618, 181868, 274629,
                        130830, 382565, 346407, 92308, 0, 252189, 192223, 89389, 279739,
                        21434, 53772, 287340, 49828, 316650, 0, 141679, 27409, 87938,
                        30287, 64645, 161645, 144980, 199466, 121366, 0, 134229, 289880,
                        21450, 43749, 97808, 113683, 89806, 25574, 158006, 0, 437255,
                        72114, 133122, 229764, 165405, 266305, 66324, 252039, 342948, 0])
        self.o = np.repeat(np.array(range(1, 10)), 9)
        self.d = np.tile(np.array(range(1, 10)), 9)
        self.dij = np.array([0, 219, 1009, 1514, 974, 1268, 1795, 2420, 3174,
                            219, 0, 831, 1336, 755, 1049, 1576, 2242, 2996,
                            1009, 831, 0, 505, 1019, 662, 933, 1451, 2205,
                            1514, 1336, 505, 0, 1370, 888, 654, 946, 1700,
                            974, 755, 1019, 1370, 0, 482, 1144, 2278, 2862,
                            1268, 1049, 662, 888, 482, 0, 662, 1795, 2380,
                            1795, 1576, 933, 654, 1144, 662, 0, 1287, 1779,
                            2420, 2242, 1451, 946, 2278, 1795, 1287, 0, 754,
                            3147, 2996, 2205, 1700, 2862, 2380, 1779, 754, 0])
        self.dt = pd.DataFrame({'Origin': self.o,
                                'Destination': self.d,
                                'flows': self.f,
                                'Dij': self.dij})

    def test_Doubly_Constrained(self):
        model = grav.DoublyConstrained(self.dt, 'Origin', 'Destination', 'flows', 'Dij', 'exp')
        beta = -0.0007369
        self.assertAlmostEqual(model.p['beta'], beta, delta=.0000001)
        print model.system_stats
        print model.parameter_stats
        print model.model_fit_stats
        print model.entropy_stats

if __name__ == '__main__':
    unittest.main()<commit_msg>deleted print statements<commit_after>"""
Tests for gravity-style spatial interaction models
"""

__author__ = 'toshan'

import unittest
import numpy as np
import pandas as pd
import gravity2 as grav

class TestUnconstrained(unittest.TestCase):
    """Unconstrained class for unit tests"""
    def setUp(self):
        self.f = np.array([56, 100.8, 173.6, 235.2, 87.36,
                           28., 100.8, 69.44, 235.2, 145.6,
                           22., 26.4, 136.4, 123.2, 343.2,
                           14., 75.6, 130.2, 70.56, 163.8,
                           22, 59.4,  204.6,  110.88,  171.6])
        self.V = np.repeat(np.array([56, 56, 44, 42, 66]), 5)
        self.o = np.repeat(np.array(range(1, 6)), 5)
        self.W = np.tile(np.array([10, 18, 62, 84, 78]), 5)
        self.d = np.tile(np.array(range(1, 6)), 5)
        self.dij = np.array([10, 10, 20, 20, 50,
                             20, 10, 50, 20, 30,
                             20, 30, 20, 30, 10,
                             30, 10, 20, 50, 20,
                             30, 20, 20, 50, 30])
        self.dt = pd.DataFrame({'origins': self.o,
                                'destinations': self.d,
                                'V': self.V,
                                'W': self.W,
                                'Dij': self.dij,
                                'flows': self.f})

    def test_Uconstrained(self):
        model = grav.Unconstrained(self.dt, 'origins', 'destinations', 'flows',
            ['V'], ['W'], 'Dij', 'pow')
        V = 1.0
        W = 1.0
        beta = -1.0
        self.assertAlmostEqual(model.p['V'], V, delta=.0001)
        self.assertAlmostEqual(model.p['W'], W, delta=.0001)
        self.assertAlmostEqual(model.p['beta'], beta, delta=.0001)

class TestProductionConstrained(unittest.TestCase):
    """Production constrained class for unit tests"""
    def setUp(self):
        self.f = np.array([0, 6469, 7629, 20036, 4690,
                           6194, 11688, 2243, 8857, 7248,
                           3559, 9221, 10099, 22866, 3388,
                           9986, 46618, 11639, 1380, 5261,
                           5985, 6731, 2704, 12250, 16132])
        self.o = np.repeat(1, 25)
        self.d = np.array(range(1, 26))
        self.dij = np.array([0, 576, 946, 597, 373,
                             559, 707, 1208, 602, 692,
                             681, 1934, 332, 595, 906,
                             425, 755, 672, 1587, 526,
                             484, 2141, 2182, 410, 540])
        self.pop = np.array([1596000, 2071000, 3376000, 6978000, 1345000,
                             2064000, 2378000, 1239000, 4435000, 1999000,
                             1274000, 7042000, 834000, 1268000, 1965000,
                             1046000, 12131000, 4824000, 969000, 2401000,
                             2410000, 2847000, 1425000, 1089000, 2909000])
        self.dt = pd.DataFrame({'origins': self.o,
                                'destinations': self.d,
                                'pop': self.pop,
                                'Dij': self.dij,
                                'flows': self.f})

    def test_Production_Constrained(self):
        model = grav.ProductionConstrained(self.dt, 'origins', 'destinations', 'flows',
            ['pop'], 'Dij', 'pow')
        pop = 0.7818262
        beta = -0.7365098
        self.assertAlmostEqual(model.p['pop'], pop, delta=.0001)
        self.assertAlmostEqual(model.p['beta'], beta, delta=.0001)

class TestAttractionConstrained(unittest.TestCase):
    """Attraction constrained class for unit tests"""
    def setUp(self):
        self.f = np.array([56, 100.8, 173.6, 235.2, 87.36,
                           28., 100.8, 69.44, 235.2, 145.6,
                           22., 26.4, 136.4, 123.2, 343.2,
                           14., 75.6, 130.2, 70.56, 163.8,
                           22, 59.4,  204.6,  110.88,  171.6])
        self.V = np.repeat(np.array([56, 56, 44, 42, 66]), 5)
        self.o = np.repeat(np.array(range(1, 6)), 5)
        self.W = np.tile(np.array([10, 18, 62, 84, 78]), 5)
        self.d = np.tile(np.array(range(1, 6)), 5)
        self.dij = np.array([10, 10, 20, 20, 50,
                             20, 10, 50, 20, 30,
                             20, 30, 20, 30, 10,
                             30, 10, 20, 50, 20,
                             30, 20, 20, 50, 30])
        self.dt = pd.DataFrame({'origins': self.o,
                                'destinations': self.d,
                                'V': self.V,
                                'Dij': self.dij,
                                'flows': self.f})

    def test_Attraction_Constrained(self):
        model = grav.AttractionConstrained(self.dt, 'origins', 'destinations', 'flows',
            ['V'], 'Dij', 'pow')
        V = 1.0
        beta = -1.0
        self.assertAlmostEqual(model.p['V'], V, delta=.0001)
        self.assertAlmostEqual(model.p['beta'], beta, delta=.0001)

class TestDoublyConstrained(unittest.TestCase):
    """Doubly constrained class for unit tests"""
    def setUp(self):
        self.f = np.array([0, 180048, 79223, 26887, 198144, 17995, 35563, 30528, 110792,
                        283049, 0, 300345, 67280, 718673, 55094, 93434, 87987, 268458,
                        87267, 237229, 0, 281791, 551483, 230788, 178517, 172711, 394481,
                        29877, 60681, 286580, 0, 143860, 49892, 185618, 181868, 274629,
                        130830, 382565, 346407, 92308, 0, 252189, 192223, 89389, 279739,
                        21434, 53772, 287340, 49828, 316650, 0, 141679, 27409, 87938,
                        30287, 64645, 161645, 144980, 199466, 121366, 0, 134229, 289880,
                        21450, 43749, 97808, 113683, 89806, 25574, 158006, 0, 437255,
                        72114, 133122, 229764, 165405, 266305, 66324, 252039, 342948, 0])
        self.o = np.repeat(np.array(range(1, 10)), 9)
        self.d = np.tile(np.array(range(1, 10)), 9)
        self.dij = np.array([0, 219, 1009, 1514, 974, 1268, 1795, 2420, 3174,
                            219, 0, 831, 1336, 755, 1049, 1576, 2242, 2996,
                            1009, 831, 0, 505, 1019, 662, 933, 1451, 2205,
                            1514, 1336, 505, 0, 1370, 888, 654, 946, 1700,
                            974, 755, 1019, 1370, 0, 482, 1144, 2278, 2862,
                            1268, 1049, 662, 888, 482, 0, 662, 1795, 2380,
                            1795, 1576, 933, 654, 1144, 662, 0, 1287, 1779,
                            2420, 2242, 1451, 946, 2278, 1795, 1287, 0, 754,
                            3147, 2996, 2205, 1700, 2862, 2380, 1779, 754, 0])
        self.dt = pd.DataFrame({'Origin': self.o,
                                'Destination': self.d,
                                'flows': self.f,
                                'Dij': self.dij})

    def test_Doubly_Constrained(self):
        model = grav.DoublyConstrained(self.dt, 'Origin', 'Destination', 'flows', 'Dij', 'exp')
        beta = -0.0007369
        self.assertAlmostEqual(model.p['beta'], beta, delta=.0000001)

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