text:
import os
import tempfile

import pymorphy

from unittest import TestCase

from textgen.words import Noun, Adjective, Verb, NounGroup, Fake, Participle, ShortParticiple, Pronoun
from textgen.templates import Args, Template, Dictionary, Vocabulary
from textgen.conf import APP_DIR, textgen_settings
from textgen.logic import import_texts
from textgen.exceptions import NormalFormNeeded

morph = pymorphy.get_morph(textgen_settings.PYMORPHY_DICTS_DIRECTORY)

class NounTest(TestCase):

    def test_create_from_baseword(self):
        noun = Noun.create_from_baseword(morph, u'обезьянка')
        self.assertEqual(noun.normalized, u'обезьянка')
        self.assertEqual(noun.properties, (u'жр',))
        self.assertEqual(noun.forms, (u'обезьянка',
                                      u'обезьянки',
                                      u'обезьянке',
                                      u'обезьянку',
                                      u'обезьянкой',
                                      u'обезьянке',
                                      u'обезьянки',
                                      u'обезьянок',
                                      u'обезьянкам',
                                      u'обезьянок',
                                      u'обезьянками',
                                      u'обезьянках'))

    def test_pluralize(self):
        noun = Noun.create_from_baseword(morph, u'монета')
        self.assertEqual(noun.normalized, u'монета')
        self.assertEqual(noun.pluralize(1, Args()), u'монета')
        self.assertEqual(noun.pluralize(2, Args()), u'монеты')
        self.assertEqual(noun.pluralize(3, Args()), u'монеты')
        self.assertEqual(noun.pluralize(5, Args()), u'монет')
        self.assertEqual(noun.pluralize(10, Args()), u'монет')
        self.assertEqual(noun.pluralize(11, Args()), u'монет')
        self.assertEqual(noun.pluralize(12, Args()), u'монет')
        self.assertEqual(noun.pluralize(21, Args()), u'монета')
        self.assertEqual(noun.pluralize(33, Args()), u'монеты')
        self.assertEqual(noun.pluralize(36, Args()), u'монет')
        self.assertEqual(noun.pluralize(113, Args()), u'монет')
        self.assertEqual(noun.pluralize(9003, Args()), u'монеты')

        self.assertEqual(noun.pluralize(1, Args(u'рд')), u'монеты')
        self.assertEqual(noun.pluralize(2, Args(u'рд')), u'монет')
        self.assertEqual(noun.pluralize(3, Args(u'рд')), u'монет')
        self.assertEqual(noun.pluralize(5, Args(u'рд')), u'монет')
        self.assertEqual(noun.pluralize(10, Args(u'рд')), u'монет')
        self.assertEqual(noun.pluralize(11, Args(u'рд')), u'монет')
        self.assertEqual(noun.pluralize(12, Args(u'рд')), u'монет')
        self.assertEqual(noun.pluralize(21, Args(u'рд')), u'монеты')
        self.assertEqual(noun.pluralize(33, Args(u'рд')), u'монет')
        self.assertEqual(noun.pluralize(36, Args(u'рд')), u'монет')
        self.assertEqual(noun.pluralize(113, Args(u'рд')), u'монет')
        self.assertEqual(noun.pluralize(9003, Args(u'рд')), u'монет')

        self.assertEqual(noun.pluralize(1, Args(u'вн')), u'монету')
        self.assertEqual(noun.pluralize(2, Args(u'вн')), u'монеты')
        self.assertEqual(noun.pluralize(3, Args(u'вн')), u'монеты')
        self.assertEqual(noun.pluralize(5, Args(u'вн')), u'монет')
        self.assertEqual(noun.pluralize(10, Args(u'вн')), u'монет')
        self.assertEqual(noun.pluralize(11, Args(u'вн')), u'монет')
        self.assertEqual(noun.pluralize(12, Args(u'вн')), u'монет')
        self.assertEqual(noun.pluralize(21, Args(u'вн')), u'монету')
        self.assertEqual(noun.pluralize(33, Args(u'вн')), u'монеты')
        self.assertEqual(noun.pluralize(36, Args(u'вн')), u'монет')
        self.assertEqual(noun.pluralize(113, Args(u'вн')), u'монет')
        self.assertEqual(noun.pluralize(9003, Args(u'вн')), u'монеты')

        self.assertEqual(noun.pluralize(1, Args(u'дт')), u'монете')
        self.assertEqual(noun.pluralize(2, Args(u'дт')), u'монетам')
        self.assertEqual(noun.pluralize(3, Args(u'дт')), u'монетам')
        self.assertEqual(noun.pluralize(5, Args(u'дт')), u'монетам')
        self.assertEqual(noun.pluralize(10, Args(u'дт')), u'монетам')
        self.assertEqual(noun.pluralize(11, Args(u'дт')), u'монетам')
        self.assertEqual(noun.pluralize(12, Args(u'дт')), u'монетам')
        self.assertEqual(noun.pluralize(21, Args(u'дт')), u'монете')
        self.assertEqual(noun.pluralize(33, Args(u'дт')), u'монетам')
        self.assertEqual(noun.pluralize(36, Args(u'дт')), u'монетам')
        self.assertEqual(noun.pluralize(113, Args(u'дт')), u'монетам')
        self.assertEqual(noun.pluralize(9003, Args(u'дт')), u'монетам')

        self.assertEqual(noun.pluralize(1, Args(u'тв')), u'монетой')
        self.assertEqual(noun.pluralize(2, Args(u'тв')), u'монетами')
        self.assertEqual(noun.pluralize(3, Args(u'тв')), u'монетами')
        self.assertEqual(noun.pluralize(5, Args(u'тв')), u'монетами')
        self.assertEqual(noun.pluralize(10, Args(u'тв')), u'монетами')
        self.assertEqual(noun.pluralize(11, Args(u'тв')), u'монетами')
        self.assertEqual(noun.pluralize(12, Args(u'тв')), u'монетами')
        self.assertEqual(noun.pluralize(21, Args(u'тв')), u'монетой')
        self.assertEqual(noun.pluralize(33, Args(u'тв')), u'монетами')
        self.assertEqual(noun.pluralize(36, Args(u'тв')), u'монетами')
        self.assertEqual(noun.pluralize(113, Args(u'тв')), u'монетами')
        self.assertEqual(noun.pluralize(9003, Args(u'тв')), u'монетами')

        self.assertEqual(noun.pluralize(1, Args(u'пр')), u'монете')
        self.assertEqual(noun.pluralize(2, Args(u'пр')), u'монетах')
        self.assertEqual(noun.pluralize(3, Args(u'пр')), u'монетах')
        self.assertEqual(noun.pluralize(5, Args(u'пр')), u'монетах')
        self.assertEqual(noun.pluralize(10, Args(u'пр')), u'монетах')
        self.assertEqual(noun.pluralize(11, Args(u'пр')), u'монетах')
        self.assertEqual(noun.pluralize(12, Args(u'пр')), u'монетах')
        self.assertEqual(noun.pluralize(21, Args(u'пр')), u'монете')
        self.assertEqual(noun.pluralize(33, Args(u'пр')), u'монетах')
        self.assertEqual(noun.pluralize(36, Args(u'пр')), u'монетах')
        self.assertEqual(noun.pluralize(113, Args(u'пр')), u'монетах')
        self.assertEqual(noun.pluralize(9003, Args(u'пр')), u'монетах')

    def test_get_form(self):
        noun = Noun.create_from_baseword(morph, u'обезьянка')
        self.assertEqual(noun.get_form(Args(u'рд', u'мн')), u'обезьянок')
        self.assertEqual(noun.get_form(Args(u'дт', u'ед')), u'обезьянке')

    def test_serialization(self):
        noun_1 = Noun.create_from_baseword(morph, u'обезьянка')
        data  = noun_1.serialize()

        noun_2 = Noun.deserialize(data)

        self.assertEqual(noun_1.normalized , noun_2.normalized)
        self.assertEqual(noun_1.forms, noun_2.forms)
        self.assertEqual(noun_1.properties, noun_2.properties)

    def test_normal_form(self):
        self.assertRaises(NormalFormNeeded, Noun.create_from_baseword, morph, u'обезьянки')
        Noun.create_from_baseword(morph, u'ножницы')

class NounGroupTest(TestCase):

    def test_create_from_baseword(self):
        group = NounGroup.create_from_baseword(morph, u'жирная крыса')
        self.assertEqual(group.normalized, u'жирная крыса')
        self.assertEqual(group.properties, (u'жр',))
        self.assertEqual(group.forms, (u'жирная крыса',
                                       u'жирной крысы',
                                       u'жирной крысе',
                                       u'жирную крысу',
                                       u'жирной крысой',
                                       u'жирной крысе',
                                       u'жирные крысы',
                                       u'жирных крыс',
                                       u'жирным крысам',
                                       u'жирная крыс', #???????? possible bug in pymorphy
                                       u'жирными крысами',
                                       u'жирных крысах'))

    def test_pluralize(self):
        group = NounGroup.create_from_baseword(morph, u'жирная крыса')
        self.assertEqual(group.pluralize(1, Args()), u'жирная крыса')
        self.assertEqual(group.pluralize(2, Args()), u'жирные крысы')
        self.assertEqual(group.pluralize(3, Args()), u'жирные крысы')
        self.assertEqual(group.pluralize(5, Args()), u'жирных крыс')
        self.assertEqual(group.pluralize(10, Args()), u'жирных крыс')
        self.assertEqual(group.pluralize(11, Args()), u'жирных крыс')
        self.assertEqual(group.pluralize(12, Args()), u'жирных крыс')
        self.assertEqual(group.pluralize(21, Args()), u'жирная крыса')
        self.assertEqual(group.pluralize(33, Args()), u'жирные крысы')
        self.assertEqual(group.pluralize(36, Args()), u'жирных крыс')

        self.assertEqual(group.pluralize(1, Args(u'дт')), u'жирной крысе')
        self.assertEqual(group.pluralize(2, Args(u'дт')), u'жирным крысам')
        self.assertEqual(group.pluralize(3, Args(u'дт')), u'жирным крысам')
        self.assertEqual(group.pluralize(5, Args(u'дт')), u'жирным крысам')
        self.assertEqual(group.pluralize(10, Args(u'дт')), u'жирным крысам')
        self.assertEqual(group.pluralize(11, Args(u'дт')), u'жирным крысам')
        self.assertEqual(group.pluralize(12, Args(u'дт')), u'жирным крысам')
        self.assertEqual(group.pluralize(21, Args(u'дт')), u'жирной крысе')
        self.assertEqual(group.pluralize(33, Args(u'дт')), u'жирным крысам')
        self.assertEqual(group.pluralize(36, Args(u'дт')), u'жирным крысам')

    def test_get_form(self):
        group = NounGroup.create_from_baseword(morph, u'жирная крыса')
        self.assertEqual(group.get_form(Args(u'рд', u'мн')), u'жирных крыс')
        self.assertEqual(group.get_form(Args(u'дт')), u'жирной крысе')

    def test_serialization(self):
        group_1 = NounGroup.create_from_baseword(morph, u'жирная крыса')
        data = group_1.serialize()

        group_2 = NounGroup.deserialize(data)

        self.assertEqual(group_1.normalized , group_2.normalized)
        self.assertEqual(group_1.forms, group_2.forms)
        self.assertEqual(group_1.properties, group_2.properties)

    def test_2_adjective(self):
        group = NounGroup.create_from_baseword(morph, u'белая жирная крыса')
        self.assertEqual(group.normalized, u'белая жирная крыса')
        self.assertEqual(group.properties, (u'жр',))
        self.assertEqual(group.forms, (u'белая жирная крыса',
                                       u'белой жирной крысы',
                                       u'белой жирной крысе',
                                       u'белую жирную крысу',
                                       u'белой жирной крысой',
                                       u'белой жирной крысе',
                                       u'белые жирные крысы',
                                       u'белых жирных крыс',
                                       u'белым жирным крысам',
                                       u'белая жирная крыс', #???????? possible bug in pymorphy
                                       u'белыми жирными крысами',
                                       u'белых жирных крысах'))

    def test_2_nouns(self):
        group = NounGroup.create_from_baseword(morph, u'тень автора')
        self.assertEqual(group.normalized, u'тень автора')
        self.assertEqual(group.properties, (u'жр',))
        self.assertEqual(group.forms, (u'тень автора',
                                       u'тени автора',
                                       u'тени автора',
                                       u'тень автора',
                                       u'тенью автора',
                                       u'тени автора',
                                       u'тени автора',
                                       u'теней автора',
                                       u'теням автора',
                                       u'теней автора', #???????? possible bug in pymorphy
                                       u'тенями автора',
                                       u'тенях автора'))

    def test_normal_form(self):
        self.assertRaises(NormalFormNeeded, NounGroup.create_from_baseword, morph, u'добрые обезьянки')
        NounGroup.create_from_baseword(morph, u'большие ножницы')

class AdjectiveTest(TestCase):

    def test_create_from_baseword(self):
        adj = Adjective.create_from_baseword(morph, u'глупый')
        self.assertEqual(adj.normalized, u'глупый')
        self.assertEqual(adj.forms, (u'глупый',
                                     u'глупого',
                                     u'глупому',
                                     u'глупый',
                                     u'глупым',
                                     u'глупом',
                                     u'глупая',
                                     u'глупой',
                                     u'глупой',
                                     u'глупую',
                                     u'глупой',
                                     u'глупой',
                                     u'глупое',
                                     u'глупого',
                                     u'глупому',
                                     u'глупое',
                                     u'глупым',
                                     u'глупом',
                                     u'глупые',
                                     u'глупых',
                                     u'глупым',
                                     u'глупый', #???????? possible bug in pymorphy
                                     u'глупыми',
                                     u'глупых'))

    def test_pluralize(self):
        adj = Adjective.create_from_baseword(morph, u'красивый')

        self.assertEqual(adj.normalized, u'красивый')

        self.assertEqual(adj.pluralize(1, Args()), u'красивый')
        self.assertEqual(adj.pluralize(2, Args()), u'красивые')
        self.assertEqual(adj.pluralize(3, Args()), u'красивые')
        self.assertEqual(adj.pluralize(5, Args()), u'красивых')
        self.assertEqual(adj.pluralize(10, Args()), u'красивых')
        self.assertEqual(adj.pluralize(11, Args()), u'красивых')
        self.assertEqual(adj.pluralize(12, Args()), u'красивых')
        self.assertEqual(adj.pluralize(21, Args()), u'красивый')
        self.assertEqual(adj.pluralize(33, Args()), u'красивые')
        self.assertEqual(adj.pluralize(36, Args()), u'красивых')

        self.assertEqual(adj.pluralize(1, Args(u'дт', u'жр')), u'красивой')
        self.assertEqual(adj.pluralize(2, Args(u'дт', u'жр')), u'красивым')
        self.assertEqual(adj.pluralize(3, Args(u'дт', u'жр')), u'красивым')
        self.assertEqual(adj.pluralize(5, Args(u'дт', u'жр')), u'красивым')
        self.assertEqual(adj.pluralize(10, Args(u'дт', u'жр')), u'красивым')
        self.assertEqual(adj.pluralize(11, Args(u'дт', u'жр')), u'красивым')
        self.assertEqual(adj.pluralize(12, Args(u'дт', u'жр')), u'красивым')
        self.assertEqual(adj.pluralize(21, Args(u'дт', u'жр')), u'красивой')
        self.assertEqual(adj.pluralize(33, Args(u'дт', u'жр')), u'красивым')
        self.assertEqual(adj.pluralize(36, Args(u'дт', u'жр')), u'красивым')

        self.assertEqual(adj.pluralize(1, Args(u'тв')), u'красивым')
        self.assertEqual(adj.pluralize(2, Args(u'тв')), u'красивыми')
        self.assertEqual(adj.pluralize(3, Args(u'тв')), u'красивыми')
        self.assertEqual(adj.pluralize(5, Args(u'тв')), u'красивыми')
        self.assertEqual(adj.pluralize(10, Args(u'тв')), u'красивыми')
        self.assertEqual(adj.pluralize(11, Args(u'тв')), u'красивыми')
        self.assertEqual(adj.pluralize(12, Args(u'тв')), u'красивыми')
        self.assertEqual(adj.pluralize(21, Args(u'тв')), u'красивым')
        self.assertEqual(adj.pluralize(33, Args(u'тв')), u'красивыми')
        self.assertEqual(adj.pluralize(36, Args(u'тв')), u'красивыми')

    def test_serialization(self):
        adj_1 = Adjective.create_from_baseword(morph, u'обезьянка')
        data = adj_1.serialize()

        adj_2 = Adjective.deserialize(data)

        self.assertEqual(adj_1.normalized , adj_2.normalized)
        self.assertEqual(adj_1.forms, adj_2.forms)
        self.assertEqual(adj_1.properties, adj_2.properties)

    def test_normal_form(self):
        self.assertRaises(NormalFormNeeded, Adjective.create_from_baseword, morph, u'добрые')

class PronounTest(TestCase):

    def test_create_from_baseword(self):
        pronoun = Pronoun.create_from_baseword(morph, u'он')
        self.assertEqual(pronoun.normalized, u'он')
        self.assertEqual(pronoun.forms, (u'он',
                                     u'его',
                                     u'ему',
                                     u'его',
                                     u'им',
                                     u'нем',
                                     u'она',
                                     u'ее',
                                     u'ей',
                                     u'ее',
                                     u'ей',
                                     u'ней',
                                     u'оно',
                                     u'его',
                                     u'ему',
                                     u'его',
                                     u'им',
                                     u'нём',
                                     u'они',
                                     u'их',
                                     u'им',
                                     u'их',
                                     u'ими',
                                     u'них'))

    def test_pluralize(self):
        # now I can't write correct test for pluralization of pronouns, let wait for some bugs in text generation
        pass

    def test_serialization(self):
        pronoun_1 = Pronoun.create_from_baseword(morph, u'он')
        data = pronoun_1.serialize()

        pronoun_2 = Pronoun.deserialize(data)

        self.assertEqual(pronoun_1.normalized , pronoun_2.normalized)
        self.assertEqual(pronoun_1.forms, pronoun_2.forms)
        self.assertEqual(pronoun_1.properties, pronoun_2.properties)

    def test_normal_form(self):
        self.assertRaises(NormalFormNeeded, Pronoun.create_from_baseword, morph, u'они')

class VerbTest(TestCase):

    def test_create_from_baseword(self):
        verb = Verb.create_from_baseword(morph, u'говорил')
        self.assertEqual(verb.normalized, u'говорил')
        self.assertEqual(verb.forms, (u'говорил',
                                      u'говорила',
                                      u'говорило',
                                      u'говорили',
                                      u'говорю',
                                      u'говорим',
                                      u'говоришь',
                                      u'говорите',
                                      u'говорит',
                                      u'говорят',
                                      u'говорил',
                                      u'говорил',
                                      u'говорил',
                                      u'говорил',
                                      u'говорил',
                                      u'говорил',))

        verb = Verb.create_from_baseword(morph, u'поговорил')
        self.assertEqual(verb.normalized, u'поговорил')
        self.assertEqual(verb.forms, (u'поговорил',
                                      u'поговорила',
                                      u'поговорило',
                                      u'поговорили',
                                      u'поговорил',
                                      u'поговорил',
                                      u'поговорил',
                                      u'поговорил',
                                      u'поговорил',
                                      u'поговорил',
                                      u'поговорю',
                                      u'поговорим',
                                      u'поговоришь',
                                      u'поговорите',
                                      u'поговорит',
                                      u'поговорят',))

    def test_word_recover(self):
        verb = Verb.create_from_baseword(morph, u'восстановил')
        self.assertEqual(verb.normalized, u'восстановил')
        self.assertEqual(verb.forms, (u'восстановил',
                                      u'восстановила',
                                      u'восстановило',
                                      u'восстановили',
                                      u'восстановил',
                                      u'восстановил',
                                      u'восстановил',
                                      u'восстановил',
                                      u'восстановил',
                                      u'восстановил',
                                      u'восстановлю',
                                      u'восстановим',
                                      u'восстановишь',
                                      u'восстановите',
                                      u'восстановит',
                                      u'восстановят',))

    def test_pluralize(self):
        verb = Verb.create_from_baseword(morph, u'взметнулся')
        self.assertEqual(verb.pluralize(1, Args(u'прш', u'жр')), u'взметнулась')
        self.assertEqual(verb.pluralize(2, Args(u'прш', u'жр')), u'взметнулись')
        self.assertEqual(verb.pluralize(3, Args(u'прш', u'жр')), u'взметнулись')
        self.assertEqual(verb.pluralize(5, Args(u'прш', u'жр')), u'взметнулись')
        self.assertEqual(verb.pluralize(10, Args(u'прш', u'жр')), u'взметнулись')
        self.assertEqual(verb.pluralize(11, Args(u'прш', u'жр')), u'взметнулись')
        self.assertEqual(verb.pluralize(12, Args(u'прш', u'жр')), u'взметнулись')
        self.assertEqual(verb.pluralize(21, Args(u'прш', u'жр')), u'взметнулась')
        self.assertEqual(verb.pluralize(33, Args(u'прш', u'жр')), u'взметнулись')
        self.assertEqual(verb.pluralize(36, Args(u'прш', u'жр')), u'взметнулись')

    def test_serialization(self):
        verb_1 = Verb.create_from_baseword(morph, u'бежал')
        data = verb_1.serialize()

        verb_2 = Verb.deserialize(data)

        self.assertEqual(verb_1.normalized , verb_2.normalized)
        self.assertEqual(verb_1.forms, verb_2.forms)
        self.assertEqual(verb_1.properties, verb_2.properties)

    def test_normal_form(self):
        self.assertRaises(NormalFormNeeded, Verb.create_from_baseword, morph, u'бежит')
        self.assertRaises(NormalFormNeeded, Verb.create_from_baseword, morph, u'бежали')
        self.assertRaises(NormalFormNeeded, Verb.create_from_baseword, morph, u'бежала')
        Verb.create_from_baseword(morph, u'бежал')
        self.assertRaises(NormalFormNeeded, Verb.create_from_baseword, morph, u'побежит')
        self.assertRaises(NormalFormNeeded, Verb.create_from_baseword, morph, u'побежали')
        self.assertRaises(NormalFormNeeded, Verb.create_from_baseword, morph, u'побежала')
        Verb.create_from_baseword(morph, u'побежал')

class ParticipleTest(TestCase):

    def test_create_from_baseword(self):
        part = Participle.create_from_baseword(morph, u'летевший')
        self.assertEqual(part.normalized, u'летевший')

        self.assertEqual(part.forms, (u'летевший',
                                      u'летевшего',
                                      u'летевшему',
                                      u'летевший',
                                      u'летевшим',
                                      u'летевшем',
                                      u'летевшая',
                                      u'летевшей',
                                      u'летевшей',
                                      u'летевшую',
                                      u'летевшей',
                                      u'летевшей',
                                      u'летевшее',
                                      u'летевшего',
                                      u'летевшему',
                                      u'летевшее',
                                      u'летевшим',
                                      u'летевшем',
                                      u'летевшие',
                                      u'летевших',
                                      u'летевшим',
                                      u'летевший',
                                      u'летевшими',
                                      u'летевших',
                                      u'летящий',
                                      u'летящего',
                                      u'летящему',
                                      u'летевший',
                                      u'летящим',
                                      u'летящем',
                                      u'летящая',
                                      u'летящей',
                                      u'летящей',
                                      u'летящую',
                                      u'летящей',
                                      u'летящей',
                                      u'летящее',
                                      u'летящего',
                                      u'летящему',
                                      u'летящее',
                                      u'летящим',
                                      u'летящем',
                                      u'летящие',
                                      u'летящих',
                                      u'летящим',
                                      u'летевший',
                                      u'летящими',
                                      u'летящих',))

    def test_pluralize(self):
        part = Participle.create_from_baseword(morph, u'летевший')
        self.assertEqual(part.pluralize(1, Args(u'прш', u'жр')), u'летевшая')
        self.assertEqual(part.pluralize(2, Args(u'прш', u'жр')), u'летевшие')
        self.assertEqual(part.pluralize(3, Args(u'прш', u'жр')), u'летевшие')
        self.assertEqual(part.pluralize(5, Args(u'прш', u'жр')), u'летевших')
        self.assertEqual(part.pluralize(10, Args(u'прш', u'жр')), u'летевших')
        self.assertEqual(part.pluralize(11, Args(u'прш', u'жр')), u'летевших')
        self.assertEqual(part.pluralize(12, Args(u'прш', u'жр')), u'летевших')
        self.assertEqual(part.pluralize(21, Args(u'прш', u'жр')), u'летевшая')
        self.assertEqual(part.pluralize(33, Args(u'прш', u'жр')), u'летевшие')
        self.assertEqual(part.pluralize(36, Args(u'прш', u'жр')), u'летевших')

    def test_serialization(self):
        part_1 = Participle.create_from_baseword(morph, u'бежал')
        data = part_1.serialize()

        part_2 = Participle.deserialize(data)

        self.assertEqual(part_1.normalized , part_2.normalized)
        self.assertEqual(part_1.forms, part_2.forms)
        self.assertEqual(part_1.properties, part_2.properties)

    def test_normal_form(self):
        self.assertRaises(NormalFormNeeded, Participle.create_from_baseword, morph, u'летящий')
        self.assertRaises(NormalFormNeeded, Participle.create_from_baseword, morph, u'летевшая')
        self.assertRaises(NormalFormNeeded, Participle.create_from_baseword, morph, u'летевшого')
        self.assertRaises(NormalFormNeeded, Participle.create_from_baseword, morph, u'летевшие')
        Participle.create_from_baseword(morph, u'летевший')

class ShortParticipleTest(TestCase):

    def test_create_from_baseword(self):
        part = ShortParticiple.create_from_baseword(morph, u'исцелён')
        self.assertEqual(part.normalized, u'исцелён')

        self.assertEqual(part.forms, (u'исцелен',
                                      u'исцелена',
                                      u'исцелено',
                                      u'исцелены',
                                      u'исцелен',
                                      u'исцелен',
                                      u'исцелен',
                                      u'исцелен'))

    def test_pluralize(self):
        part = ShortParticiple.create_from_baseword(morph, u'исцелён')
        self.assertEqual(part.pluralize(1, Args(u'прш', u'жр')), u'исцелена')
        self.assertEqual(part.pluralize(2, Args(u'прш', u'жр')), u'исцелены')
        self.assertEqual(part.pluralize(3, Args(u'прш', u'жр')), u'исцелены')
        self.assertEqual(part.pluralize(5, Args(u'прш', u'жр')), u'исцелены')
        self.assertEqual(part.pluralize(10, Args(u'прш', u'жр')), u'исцелены')
        self.assertEqual(part.pluralize(11, Args(u'прш', u'жр')), u'исцелены')
        self.assertEqual(part.pluralize(12, Args(u'прш', u'жр')), u'исцелены')
        self.assertEqual(part.pluralize(21, Args(u'прш', u'жр')), u'исцелена')
        self.assertEqual(part.pluralize(33, Args(u'прш', u'жр')), u'исцелены')
        self.assertEqual(part.pluralize(36, Args(u'прш', u'жр')), u'исцелены')

    def test_serialization(self):
        part_1 = ShortParticiple.create_from_baseword(morph, u'исцелён')
        data = part_1.serialize()

        part_2 = Participle.deserialize(data)

        self.assertEqual(part_1.normalized , part_2.normalized)
        self.assertEqual(part_1.forms, part_2.forms)
        self.assertEqual(part_1.properties, part_2.properties)

    def test_normal_form(self):
        self.assertRaises(NormalFormNeeded, ShortParticiple.create_from_baseword, morph, u'исцелена')
        self.assertRaises(NormalFormNeeded, ShortParticiple.create_from_baseword, morph, u'исцелены')
        ShortParticiple.create_from_baseword(morph, u'исцелён')

class DictionaryTest(TestCase):

    def setUp(self):
        self.monkey = Noun.create_from_baseword(morph, u'обезьянка')
        self.silly = Adjective.create_from_baseword(morph, u'глупый')
        self.hit = Verb.create_from_baseword(morph, u'ударил')

    def test_create(self):
        dictionary = Dictionary()

        dictionary.add_word(self.monkey)
        dictionary.add_word(self.silly)
        dictionary.add_word(self.hit)

        self.assertEqual(dictionary.get_word(u'обезьянка'), self.monkey)
        self.assertEqual(dictionary.get_word(u'глупый'), self.silly)
        self.assertEqual(dictionary.get_word(u'ударил'), self.hit)

    def test_serialization(self):

        with tempfile.NamedTemporaryFile(delete=False) as f:
            dictionary = Dictionary()

            dictionary.add_word(self.monkey)
            dictionary.add_word(self.silly)
            dictionary.add_word(self.hit)

            dictionary.save(storage=f.name)

            dictionary = Dictionary()
            dictionary.load(storage=f.name)

            self.assertEqual(dictionary.get_word(u'обезьянка').normalized, u'обезьянка')
            self.assertEqual(dictionary.get_word(u'глупый').normalized, u'глупый')
            self.assertEqual(dictionary.get_word(u'ударил').normalized, u'ударил')

class VocabularyTest(TestCase):

    def setUp(self):
        self.t1 = Template.create(morph, u'ударить [[hero|вн]]')
        self.t2 = Template.create(morph, u'ударить [[hero|вн,мн]]')
        self.t3 = Template.create(morph, u'[{тенью|hero|тв}] [[hero|рд]]')

    def __assertChoices(self, voc):
        choosed_2 = False
        choosed_3 = False

        for i in xrange(100):
            self.assertEqual(voc.get_random_phrase('type_1').template, self.t1.template)

            choice = voc.get_random_phrase('type_2')
            if choice.template == self.t2.template:
                choosed_2 = True
            if choice.template == self.t3.template:
                choosed_3 = True
            self.assertTrue(choice.template in [self.t2.template, self.t3.template])

        self.assertTrue(choosed_2 and choosed_3)

    def test_create(self):

        voc = Vocabulary()

        voc.add_phrase('type_1', self.t1)
        voc.add_phrase('type_2', self.t2)
        voc.add_phrase('type_2', self.t3)

        self.__assertChoices(voc)

    def test_save_load(self):
        with tempfile.NamedTemporaryFile(delete=False) as f:
            voc = Vocabulary()

            voc.add_phrase('type_1', self.t1)
            voc.add_phrase('type_2', self.t2)
            voc.add_phrase('type_2', self.t3)

            voc.save(storage=f.name)

            voc = Vocabulary()

            voc.load(storage=f.name)

            self.__assertChoices(voc)

class TemplateTest(TestCase):

    def setUp(self):
        self.dictionary = Dictionary()
        self.dictionary.add_word(Noun.create_from_baseword(morph, u'обезьянка'))
        self.dictionary.add_word(Noun.create_from_baseword(morph, u'тень'))
        self.dictionary.add_word(Adjective.create_from_baseword(morph, u'глупый'))
        self.dictionary.add_word(Verb.create_from_baseword(morph, u'ударил'))
        self.dictionary.add_word(Verb.create_from_baseword(morph, u'подставил'))
        self.dictionary.add_word(Adjective.create_from_baseword(morph, u'целый'))

    def test_externals(self):
        template = Template.create(morph, u'ударить [[hero|вн]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка'}), u'ударить обезьянку')

        template = Template.create(morph, u'ударить [[hero|вн,мн]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка' } ), u'ударить обезьянок')

    def test_partial_dependence(self):
        template = Template.create(morph, u'ударить [[hero|вн]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': (u'обезьянка', u'мн') } ), u'ударить обезьянок')

    def test_internals(self):
        template = Template.create(morph, u'[{тень|hero|тв}] [[hero|рд]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': (u'обезьянка', u'мн')} ), u'тенями обезьянок')

    def test_noun_dependences(self):
        template = Template.create(morph, u'[[shadow|hero|тв]] [[hero|рд]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': (u'обезьянка', u'мн'),
                                                               'shadow': u'тень'} ), u'тенями обезьянок')

    def test_numeral_1_dependences(self):
        template = Template.create(morph, u'[[number||]] [[hero|number|им]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка',
                                                               'number': 1} ), u'1 обезьянка')

        template = Template.create(morph, u'[[number||]] [[hero|number|рд]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка',
                                                               'number': 1} ), u'1 обезьянки')

        template = Template.create(morph, u'[[number||]] [[hero|number|дт]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка',
                                                               'number': 1} ), u'1 обезьянке')

    def test_numeral_2_dependences(self):
        template = Template.create(morph, u'[[number||]] [[hero|number|им]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка',
                                                               'number': 2} ), u'2 обезьянки')

        template = Template.create(morph, u'[[number||]] [[hero|number|рд]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка',
                                                               'number': 2} ), u'2 обезьянок')

        template = Template.create(morph, u'[[number||]] [[hero|number|дт]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка',
                                                               'number': 2} ), u'2 обезьянкам')

    def test_numeral_13_adj_dependences(self):
        template = Template.create(morph, u'[[number||]] [{целый|number|}]')
        self.assertEqual(template.substitute(self.dictionary, {'number': 13} ), u'13 целых')

    def test_numeral_5_dependences(self):
        template = Template.create(morph, u'[[number||]] [[hero|number|им]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка',
                                                               'number': 5} ), u'5 обезьянок')

        template = Template.create(morph, u'[[number||]] [[hero|number|рд]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка',
                                                               'number': 5} ), u'5 обезьянок')

        template = Template.create(morph, u'[[number||]] [[hero|number|дт]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка',
                                                               'number': 5} ), u'5 обезьянкам')

    def test_dependences(self):
        template = Template.create(morph, u'[{глупый|hero|рд}] [[hero|рд]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка'} ), u'глупой обезьянки')

        template = Template.create(morph, u'враг [{ударил|hero|буд,3л}] [[hero|вн]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка'} ), u'враг ударит обезьянку')

        template = Template.create(morph, u'крыса [{ударил|прш,жр}] [[hero|вн]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': u'обезьянка'} ), u'крыса ударила обезьянку')

    def test_fake_substitutions(self):
        template = Template.create(morph, u'[{глупый|hero|рд}] [[hero|рд]]')
        self.assertEqual(template.substitute(self.dictionary, {'hero': Fake(u'19x5')} ), u'глупого 19x5')

    def test_upper_case(self):
        template = Template.create(morph, u'Первое предложение. [{подставил|hero|прш,загл}] слово в начало, а затем вставим имя от [[hero|рд]]. [[shadow|загл]] пришла.')
        result = template.substitute(self.dictionary, {'hero': (u'обезьянка', u'загл'), 'shadow': u'тень'} )
        self.assertEqual(result, u'Первое предложение. Подставила слово в начало, а затем вставим имя от Обезьянки. Тень пришла.')

class LoadDataTest(TestCase):

    def setUp(self):
        pass

    def test_load(self):
        with tempfile.NamedTemporaryFile(delete=False) as voc_f:
            with tempfile.NamedTemporaryFile(delete=False) as dict_f:
                import_texts(morph,
                             source_dir=os.path.join(APP_DIR, 'fixtures', 'texts_src'),
                             tech_vocabulary_path=os.path.join(APP_DIR, 'fixtures', 'vocabulary.json'),
                             voc_storage=voc_f.name,
                             dict_storage=dict_f.name)


text:
local require                   = require

local log                       = require "hs.logger".new "tangentPref"
local inspect                   = require "hs.inspect"

local application               = require "hs.application"
local dialog                    = require "hs.dialog"
local image                     = require "hs.image"
local timer                     = require "hs.timer"

local config                    = require "cp.config"
local cpDialog                  = require "cp.dialog"
local html                      = require "cp.web.html"
local i18n                      = require "cp.i18n"
local tools                     = require "cp.tools"

local chooseFileOrFolder        = dialog.chooseFileOrFolder
local displayChooseFromList     = cpDialog.displayChooseFromList
local doAfter                   = timer.doAfter
local escapeTilda               = tools.escapeTilda
local imageFromAppBundle        = image.imageFromAppBundle
local imageFromPath             = image.imageFromPath
local infoForBundlePath         = application.infoForBundlePath
local mergeTable                = tools.mergeTable
local spairs                    = tools.spairs
local split                     = tools.split
local tableContains             = tools.tableContains
local tableCount                = tools.tableCount
local webviewAlert              = dialog.webviewAlert

local mod = {}

-- TANGENT_WEBSITE -> string
-- Constant
-- Tangent Website URL.
local TANGENT_WEBSITE = "http://www.tangentwave.co.uk/"

-- DOWNLOAD_TANGENT_HUB -> string
-- Constant
-- URL to download Tangent Hub Application.
local DOWNLOAD_TANGENT_HUB = "http://www.tangentwave.co.uk/download/tangent-hub-installer-mac/"

-- DEFAULT_LAST_APPLICATION -> string
-- Constant
-- The default last application.
local DEFAULT_LAST_APPLICATION = "Final Cut Pro"

-- renderPanel(context) -> none
-- Function
-- Generates the Preference Panel HTML Content.
--
-- Parameters:
--  * context - Table of data that you want to share with the renderer
--
-- Returns:
--  * HTML content as string
local function renderPanel(context)
    if not mod._renderPanel then
        local errorMessage
        mod._renderPanel, errorMessage = mod._env:compileTemplate("html/panel.html")
        if errorMessage then
            log.ef(errorMessage)
            return nil
        end
    end
    return mod._renderPanel(context)
end

-- generateContent() -> string
-- Function
-- Generates the Preference Panel HTML Content.
--
-- Parameters:
--  * None
--
-- Returns:
--  * HTML content as string
local function generateContent()
    local applicationNames = mod._tangentManager.applicationNames()
    table.sort(applicationNames)

    local context = {
        applicationNames        = applicationNames,
        webviewLabel            = mod._prefsManager.getLabel(),
        maxItems                = mod._tangentManager.NUMBER_OF_FAVOURITES,
        spairs                  = spairs,
        none                    = i18n("none"),
        i18n                    = i18n,
    }
    return renderPanel(context)
end

-- updateUI() -> none
-- Function
-- Updates the preferences panel user interface.
--
-- Parameters:
--  * None
--
-- Returns:
--  * None
local function updateUI()
    local script = ""

    --------------------------------------------------------------------------------
    -- This will only happen if a Custom Application is deleted:
    --------------------------------------------------------------------------------
    local lastApplication = mod.lastApplication()
    local connection = mod._tangentManager.getConnection(lastApplication)
    if not connection then
        lastApplication = DEFAULT_LAST_APPLICATION
        connection = mod._tangentManager.getConnection(lastApplication)
    end

    --------------------------------------------------------------------------------
    -- Enable or Disable the "Add Application" drop down option:
    --------------------------------------------------------------------------------
    local maxConnections = mod._tangentManager.MAXIMUM_CONNECTIONS
    local applicationNames = mod._tangentManager.applicationNames()
    local connectionCount = #applicationNames
    local allowAddApplication = true
    if connectionCount >= maxConnections then
        allowAddApplication = false
    end
    script = script .. [[document.getElementById("addApplication").disabled = ]] .. tostring(not allowAddApplication) .. [[;]]

    --------------------------------------------------------------------------------
    -- Enable or Disable the "Remove Application" drop down option:
    --------------------------------------------------------------------------------
    local customApplications = mod._tangentManager.customApplications()
    local customApplicationsCount = tableCount(customApplications)
    local allowRemoveApplication = true
    if customApplicationsCount == 0 then
        allowRemoveApplication = false
    end
    script = script .. [[document.getElementById("removeApplication").disabled = ]] .. tostring(not allowRemoveApplication) .. [[;]]

    --------------------------------------------------------------------------------
    -- Update the application drop down list:
    --------------------------------------------------------------------------------
    script = script .. [[changeValueByID('application', `]] .. escapeTilda(lastApplication) .. [[`);]]

    --------------------------------------------------------------------------------
    -- Update the enabled button checkbox:
    --------------------------------------------------------------------------------
    local enabled = connection and connection.enabled() or false
    script = script .. [[changeCheckedByID('enabled', ]] .. tostring(enabled) .. [[);]]

    --------------------------------------------------------------------------------
    -- Update the Favourites titles:
    --------------------------------------------------------------------------------
    local faves = connection and connection.favourites() or {}
    local max = mod._tangentManager.NUMBER_OF_FAVOURITES
    for i = 1, max do
        local fave = faves[tostring(i)]
        if fave then
            local actionTitle = fave.actionTitle
            script = script .. [[changeValueByID('label_]] .. i .. [[', `]] .. escapeTilda(actionTitle) .. [[`);]]
        else
            script = script .. [[changeValueByID('label_]] .. i .. [[', `]] .. i18n("none") .. [[`);]]
        end
    end

    --------------------------------------------------------------------------------
    -- Inject the JavaScript:
    --------------------------------------------------------------------------------
    local injectScript = mod._prefsManager.injectScript
    injectScript(script)
end

-- tangentPanelCallback() -> none
-- Function
-- JavaScript Callback for the Preferences Panel
--
-- Parameters:
--  * id - ID as string
--  * params - Table of paramaters
--
-- Returns:
--  * None
local function tangentPanelCallback(id, params)
    if params and params["type"] then
        if params["type"] == "updateUI" then
            --------------------------------------------------------------------------------
            -- Update the User Interface:
            --------------------------------------------------------------------------------
            updateUI()
        elseif params["type"] == "changeEnabled" then
            --------------------------------------------------------------------------------
            -- Change the Enabled Checkbox:
            --------------------------------------------------------------------------------
            local enabled = params.enabled
            local lastApplication = mod.lastApplication()
            local connection = mod._tangentManager.getConnection(lastApplication)
            connection.enabled(enabled)
        elseif params["type"] == "changeApplication" then
            local app = params.application
            if app == "Remove Application" then
                --------------------------------------------------------------------------------
                -- Remove Application:
                --------------------------------------------------------------------------------
                local applicationNames = mod._tangentManager.applicationNames()
                table.sort(applicationNames)

                local result = displayChooseFromList("Please select the application you want to remove:", applicationNames)
                local applicationToRemove = result and result[1]
                if applicationToRemove then
                    mod._tangentManager.removeCustomApplication(applicationToRemove)

                    --------------------------------------------------------------------------------
                    -- Refresh the UI:
                    --------------------------------------------------------------------------------
                    mod._prefsManager.refresh()
                else
                    updateUI()
                end
            elseif app == "Add Application" then
                --------------------------------------------------------------------------------
                -- Add Application:
                --------------------------------------------------------------------------------
                local files = chooseFileOrFolder(i18n("pleaseSelectAnApplication") .. ":", "/Applications", true, false, false, {"app"}, false)
                if files then
                    local path = files["1"]
                    local info = path and infoForBundlePath(path)
                    local applicationName = info and info.CFBundleDisplayName or info.CFBundleName or info.CFBundleExecutable
                    local bundleExecutable = info and info.CFBundleExecutable
                    if applicationName and bundleExecutable then
                        local applicationNames = mod._tangentManager.applicationNames()
                        if not tableContains(applicationNames, applicationName) then
                            mod._tangentManager.registerCustomApplication(applicationName, bundleExecutable)

                            --------------------------------------------------------------------------------
                            -- Refresh the UI:
                            --------------------------------------------------------------------------------
                            mod._prefsManager.refresh()
                        else
                            webviewAlert(mod._prefsManager.getWebview(), function() end, i18n("failedToAddCustomApplication"), i18n("duplicateCustomApplication"), i18n("ok"))
                        end
                    else
                        webviewAlert(mod._prefsManager.getWebview(), function() end, i18n("failedToAddCustomApplication"), i18n("failedToAddCustomApplicationDescription"), i18n("ok"))
                        log.ef("Something went wrong trying to add a custom application.\n\nPath: '%s'\nbundleExecutable: '%s'\napplicationName: '%s'",path, bundleExecutable, applicationName)
                    end
                    updateUI()
                end
            else
                mod.lastApplication(app)
                updateUI()
            end
        elseif params["type"] == "updateAction" then
            --------------------------------------------------------------------------------
            -- Setup Activators:
            --------------------------------------------------------------------------------
            local appParameter = params["application"]

            --------------------------------------------------------------------------------
            -- Convert the display name to the legacy group ID or use the bundle ID:
            --------------------------------------------------------------------------------
            local applicationNameToGroupID = mod._tangentManager.applicationNameToGroupID
            local activatorID = applicationNameToGroupID[appParameter] or appParameter

            if not mod.activator then
                mod.activator = {}
            end

            if not mod.activator[activatorID] then
                --------------------------------------------------------------------------------
                -- Create a new Action Activator:
                --------------------------------------------------------------------------------
                local handlerIds = mod._actionManager.handlerIds()

                --------------------------------------------------------------------------------
                -- Determine if there's a legacy group ID and display name:
                --------------------------------------------------------------------------------
                local displayName
                local legacyGroupID
                local thebundleID
                local registeredApps = mod._appmanager.getApplications()
                for bundleID, v in pairs(registeredApps) do
                    if activatorID == bundleID or activatorID == v.legacyGroupID then
                        legacyGroupID = v.legacyGroupID or bundleID
                        displayName = v.displayName
                        thebundleID = bundleID
                        break
                    end
                end

                --------------------------------------------------------------------------------
                -- Create new Activator:
                --------------------------------------------------------------------------------
                mod.activator[activatorID] = mod._actionManager.getActivator("tangentPreferences" .. activatorID)

                --------------------------------------------------------------------------------
                -- Don't include Touch Bar widgets, MIDI Controls or Global Menu Actions:
                --------------------------------------------------------------------------------
                local allowedHandlers = {}
                for _,v in pairs(handlerIds) do
                    local handlerTable = split(v, "_")
                    local partB = handlerTable[2]
                    if partB ~= "widgets" and partB ~= "midicontrols" and v ~= "global_menuactions" then
                        table.insert(allowedHandlers, v)
                    end
                end
                local unpack = table.unpack
                mod.activator[activatorID]:allowHandlers(unpack(allowedHandlers))

                --------------------------------------------------------------------------------
                -- Gather Toolbar Icons for Search Console:
                --------------------------------------------------------------------------------
                local defaultSearchConsoleToolbar = mod._appmanager.defaultSearchConsoleToolbar()
                local appSearchConsoleToolbar = mod._appmanager.getSearchConsoleToolbar(activatorID) or {}
                local searchConsoleToolbar = mergeTable(defaultSearchConsoleToolbar, appSearchConsoleToolbar)
                mod.activator[activatorID]:toolbarIcons(searchConsoleToolbar)

                --------------------------------------------------------------------------------
                -- Only customise known applications:
                --------------------------------------------------------------------------------
                if thebundleID then
                    --------------------------------------------------------------------------------
                    -- Only enable handlers for the current app:
                    --------------------------------------------------------------------------------
                    local enabledHandlerID = legacyGroupID or activatorID
                    if enabledHandlerID and enabledHandlerID == "All Applications" then
                        enabledHandlerID = "global"
                    end
                    mod.activator[activatorID]:enableHandlers(enabledHandlerID)

                    --------------------------------------------------------------------------------
                    -- Add a specific toolbar icon for the current application:
                    --------------------------------------------------------------------------------
                    if enabledHandlerID and enabledHandlerID ~= "global" then
                        local icon = imageFromAppBundle(thebundleID)
                        mod.activator[activatorID]:setBundleID(enabledHandlerID, icon, displayName)
                    end
                end
            end

            --------------------------------------------------------------------------------
            -- Setup Activator Callback:
            --------------------------------------------------------------------------------
            mod.activator[activatorID]:onActivate(function(handler, action, text)
                    --------------------------------------------------------------------------------
                    -- Process Stylised Text:
                    --------------------------------------------------------------------------------
                    if text and type(text) == "userdata" then
                        text = text:convert("text")
                    end

                    local actionTitle = text

                    local handlerID = handler:id()
                    local buttonID = params.buttonID

                    local lastApplication = mod.lastApplication()
                    local connection = mod._tangentManager.getConnection(lastApplication)
                    local faves = connection.favourites()

                    faves[tostring(buttonID)] = {
                        actionTitle = actionTitle,
                        handlerID = handlerID,
                        action = action,
                    }

                    connection.favourites(faves)

                    --------------------------------------------------------------------------------
                    -- Add a slight delay to give the UI time to update before we rebuild the
                    -- Tangent XML files:
                    --------------------------------------------------------------------------------
                    doAfter(0.5, function() connection:updateControls() end)

                    updateUI()
                end)

            --------------------------------------------------------------------------------
            -- Show Activator:
            --------------------------------------------------------------------------------
            mod.activator[activatorID]:show()
        elseif params["type"] == "clearAction" then
            local buttonID = params.buttonID
            local lastApplication = mod.lastApplication()
            local connection = mod._tangentManager.getConnection(lastApplication)
            local faves = connection.favourites()
            faves[tostring(buttonID)] = nil
            connection.favourites(faves)

            --------------------------------------------------------------------------------
            -- Add a slight delay to give the UI time to update before we rebuild the
            -- Tangent XML files:
            --------------------------------------------------------------------------------
            doAfter(0.5, function() connection:updateControls() end)

            updateUI()
        else
            --------------------------------------------------------------------------------
            -- Unknown Callback:
            --------------------------------------------------------------------------------
            log.df("Unknown Callback in Tangent Preferences Panel:")
            log.df("id: %s", inspect(id))
            log.df("params: %s", inspect(params))
        end
    end
end

--- plugins.core.tangent.prefs.init() -> none
--- Function
--- Initialise Module.
---
--- Parameters:
---  * None
---
--- Returns:
---  * None
function mod.init(deps, env)
    --------------------------------------------------------------------------------
    -- Inter-plugin Connectivity:
    --------------------------------------------------------------------------------
    mod._actionManager  = deps.actionManager
    mod._appmanager     = deps.appManager
    mod._prefsManager   = deps.prefsManager
    mod._tangentManager = deps.tangentManager
    mod._env            = env

    --- plugins.core.tangent.prefs.lastApplication <cp.prop: string>
    --- Field
    --- Last Application used in the Preferences Panel.
    mod.lastApplication = config.prop("tangent.preferences.lastApplication", DEFAULT_LAST_APPLICATION)

    --------------------------------------------------------------------------------
    -- Setup Tangent Preferences Panel:
    --------------------------------------------------------------------------------
    mod._panel = mod._prefsManager.addPanel({
        priority    = 2032.1,
        id          = "tangent",
        label       = i18n("tangentPanelLabel"),
        image       = imageFromPath(env:pathToAbsolute("/images/tangent.icns")),
        tooltip     = i18n("tangentPanelTooltip"),
        height      = 830,
    })
        :addContent(1, html.style ([[
            .tangentButtonOne {
                float:left;
                width: 192px;
            }
            .tangentButtonTwo {
                float:left;
                margin-left: 5px;
                width: 192px;
            }
            .tangentButtonThree {
                clear:both;
                float:left;
                margin-top: 5px;
                width: 192px;
            }
            .tangentButtonFour {
                float:left;
                margin-top: 5px;
                margin-left: 5px;
                width: 192px;
            }
        ]], true))
        :addHeading(2, i18n("tangentPanelSupport"))
        :addParagraph(3, i18n("tangentPreferencesInfo"), false)
        :addParagraph(3.1, html.br())
        :addParagraph(3.2, html.span {class="tip"} (html(i18n("tangentTip"), false) ) .. "\n\n")
        :addParagraph(3.3, html.br())
        --------------------------------------------------------------------------------
        -- Enable Tangent Support:
        --------------------------------------------------------------------------------
        :addCheckbox(4,
            {
                label = i18n("enableTangentPanelSupport"),
                onchange = function(_, params)
                    if params.checked and not mod._tangentManager.tangentHubInstalled() then
                        webviewAlert(mod._prefsManager.getWebview(), function()
                            mod._tangentManager.enabled(false)
                            mod._prefsManager.injectScript([[
                                document.getElementById("enableTangentSupport").checked = false;
                            ]])
                        end, i18n("tangentPanelSupport"), i18n("mustInstallTangentMapper"), i18n("ok"))
                    else
                        mod._tangentManager.enabled(params.checked)
                    end
                end,
                checked = mod._tangentManager.enabled,
                id = "enableTangentSupport",
            }
        )
        :addParagraph(5, html.br())
        --------------------------------------------------------------------------------
        -- Open Tangent Mapper:
        --------------------------------------------------------------------------------
        :addButton(6,
            {
                label = i18n("openTangentMapper"),
                onclick = function()
                    if mod._tangentManager.tangentMapperInstalled() then
                        mod._tangentManager.launchTangentMapper()
                    else
                        webviewAlert(mod._prefsManager.getWebview(), function() end, i18n("tangentMapperNotFound"), i18n("tangentMapperNotFoundMessage"), i18n("ok"))
                    end
                end,
                class = "tangentButtonOne",
            }
        )
        --------------------------------------------------------------------------------
        -- Download Tangent Hub:
        --------------------------------------------------------------------------------
        :addButton(8,
            {
                label = i18n("downloadTangentHub"),
                onclick = function()
                    os.execute('open "' .. DOWNLOAD_TANGENT_HUB .. '"')
                end,
                class = "tangentButtonTwo",
            }
        )
        --------------------------------------------------------------------------------
        -- Visit Tangent Website:
        --------------------------------------------------------------------------------
        :addButton(9,
            {
                label = i18n("visitTangentWebsite"),
                onclick = function()
                    os.execute('open "' .. TANGENT_WEBSITE .. '"')
                end,
                class = "tangentButtonTwo",
            }
        )
        :addParagraph(10, html.br())
        :addParagraph(11, html.br())
        :addHeading(12, i18n("tangent") .. " " .. i18n("favourites"))
        :addParagraph(13, i18n("tangentFavouriteDescription"), false)
        :addContent(14, generateContent, false)

        --------------------------------------------------------------------------------
        -- Setup Callback Manager:
        --------------------------------------------------------------------------------
        :addHandler("onchange", "tangentPanelCallback", tangentPanelCallback)

    return mod
end

local plugin = {
    id              = "core.tangent.prefs",
    group           = "core",
    dependencies    = {
        ["core.controlsurfaces.manager"]        = "prefsManager",
        ["core.tangent.manager"]                = "tangentManager",
        ["core.action.manager"]                 = "actionManager",
        ["core.application.manager"]            = "appManager",
    }
}

function plugin.init(deps, env)
    return mod.init(deps, env)
end

return plugin

redpajama_set_name: RedPajamaGithub


text:
package org.wso2.carbon.identity.common.util;

import org.wso2.carbon.identity.common.base.exception.IdentityException;
import org.wso2.carbon.identity.common.util.config.IdentityConfigUtils;
import org.wso2.carbon.identity.common.util.jdbc.JDBCUtils;
import org.wso2.carbon.identity.common.util.keystore.KeyStoreUtils;
import org.wso2.carbon.identity.common.util.log.LogUtils;
import org.wso2.carbon.identity.common.util.passwordsafe.PasswordSafeUtils;
import org.wso2.carbon.identity.common.util.stream.StreamUtils;
import org.wso2.carbon.identity.common.util.url.URLUtils;
import org.wso2.carbon.identity.common.util.validation.ValidationUtils;
import org.wso2.carbon.identity.common.util.xml.XMLUtils;

/**
 * Identity util service.
 */
public interface IdentityUtilService {

    JDBCUtils getJDBCUtils() throws IdentityException;

    KeyStoreUtils getKeyStoreUtils() throws IdentityException;

    LogUtils getLogUtils() throws IdentityException;

    PasswordSafeUtils getPasswordSafeUtils() throws IdentityException;

    StreamUtils getStreamUtils() throws IdentityException;

    URLUtils getURLUtils() throws IdentityException;

    ValidationUtils getValidationUtils() throws IdentityException;

    XMLUtils getXMLUtils() throws IdentityException;

    IdentityUtils getIdentityUtils() throws IdentityException;

    IdentityConfigUtils getIdentityConfigUtils() throws IdentityException;

}