def test_value_characters (self): feature = BaseFeature(self.bfm, 'voiced') self.assertEqual(feature.get_value_characters(HAS_FEATURE), set()) self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE), set()) character1 = BaseCharacter(self.bfm, 'a') character1.set_feature_value(feature, HAS_FEATURE) self.assertEqual(feature.get_value_characters(HAS_FEATURE), set([character1])) self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE), set()) character1.set_feature_value(feature, NOT_HAS_FEATURE) self.assertEqual(feature.get_value_characters(HAS_FEATURE), set()) self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE), set([character1])) character2 = DiacriticCharacter(self.bfm, 'b') character2.set_feature_value(feature, HAS_FEATURE) self.assertEqual(feature.get_value_characters(HAS_FEATURE), set([character2])) self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE), set([character1])) character2.set_feature_value(feature, INAPPLICABLE_FEATURE) self.assertEqual(feature.get_value_characters(HAS_FEATURE), set()) self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE), set([character1])) character3 = SpacingCharacter(self.bfm, 'c') character3.set_feature_value(feature, NOT_HAS_FEATURE) self.assertEqual(feature.get_value_characters(HAS_FEATURE), set()) self.assertEqual(feature.get_value_characters(NOT_HAS_FEATURE), set([character1, character3]))
def _populate_binary_features_model(self): self.bfm = BinaryFeaturesModel() self.anterior = BaseFeature(self.bfm, 'anterior') self.back = BaseFeature(self.bfm, 'back') self.coronal = BaseFeature(self.bfm, 'coronal') self.long = BaseFeature(self.bfm, 'long') self.voiced = BaseFeature(self.bfm, 'voiced') self.p = BaseCharacter(self.bfm, 'p') self.p.set_feature_value(self.anterior, HAS_FEATURE) self.p.set_feature_value(self.back, NOT_HAS_FEATURE) self.p.set_feature_value(self.coronal, NOT_HAS_FEATURE) self.p.set_feature_value(self.long, NOT_HAS_FEATURE) self.p.set_feature_value(self.voiced, NOT_HAS_FEATURE) self.b = BaseCharacter(self.bfm, 'b') self.b.set_feature_value(self.anterior, HAS_FEATURE) self.b.set_feature_value(self.back, NOT_HAS_FEATURE) self.b.set_feature_value(self.coronal, NOT_HAS_FEATURE) self.b.set_feature_value(self.long, NOT_HAS_FEATURE) self.b.set_feature_value(self.voiced, HAS_FEATURE) self.t = BaseCharacter(self.bfm, 't') self.t.set_feature_value(self.anterior, HAS_FEATURE) self.t.set_feature_value(self.back, NOT_HAS_FEATURE) self.t.set_feature_value(self.coronal, HAS_FEATURE) self.t.set_feature_value(self.long, NOT_HAS_FEATURE) self.t.set_feature_value(self.voiced, NOT_HAS_FEATURE) self.d = BaseCharacter(self.bfm, 'd') self.d.set_feature_value(self.anterior, HAS_FEATURE) self.d.set_feature_value(self.back, NOT_HAS_FEATURE) self.d.set_feature_value(self.coronal, HAS_FEATURE) self.d.set_feature_value(self.long, NOT_HAS_FEATURE) self.d.set_feature_value(self.voiced, HAS_FEATURE) self.q = BaseCharacter(self.bfm, 'q') self.q.set_feature_value(self.anterior, NOT_HAS_FEATURE) self.q.set_feature_value(self.back, HAS_FEATURE) self.q.set_feature_value(self.coronal, NOT_HAS_FEATURE) self.q.set_feature_value(self.long, NOT_HAS_FEATURE) self.q.set_feature_value(self.voiced, NOT_HAS_FEATURE) self.ring = DiacriticCharacter(self.bfm, '̥') self.ring.set_feature_value(self.anterior, INAPPLICABLE_FEATURE) self.ring.set_feature_value(self.back, INAPPLICABLE_FEATURE) self.ring.set_feature_value(self.coronal, INAPPLICABLE_FEATURE) self.ring.set_feature_value(self.long, INAPPLICABLE_FEATURE) self.ring.set_feature_value(self.voiced, NOT_HAS_FEATURE) self.caret = DiacriticCharacter(self.bfm, '̬') self.caret.set_feature_value(self.anterior, INAPPLICABLE_FEATURE) self.caret.set_feature_value(self.back, INAPPLICABLE_FEATURE) self.caret.set_feature_value(self.coronal, INAPPLICABLE_FEATURE) self.caret.set_feature_value(self.long, INAPPLICABLE_FEATURE) self.caret.set_feature_value(self.voiced, HAS_FEATURE) self.ː = SpacingCharacter(self.bfm, 'ː') self.ː.set_feature_value(self.anterior, INAPPLICABLE_FEATURE) self.ː.set_feature_value(self.back, INAPPLICABLE_FEATURE) self.ː.set_feature_value(self.coronal, INAPPLICABLE_FEATURE) self.ː.set_feature_value(self.long, HAS_FEATURE) self.ː.set_feature_value(self.voiced, INAPPLICABLE_FEATURE)
def test_base_cluster_creation_illegal(self): bfm1 = BinaryFeaturesModel() bfm2 = BinaryFeaturesModel() character1 = BaseCharacter(bfm1, 'a') character2 = DiacriticCharacter(bfm2, 'b') character3 = DiacriticCharacter(bfm1, 'd') character4 = SpacingCharacter(bfm1, 'e') nf1 = NormalisedForm('{}{}'.format(BNFM, HAS_FEATURE)) # A BaseCluster must be initialised with either a base # character or a normalised form. self.assertRaises(IllegalArgumentError, BaseCluster, bfm1) # A BaseCluster must not be initialised with both a normalised # form and any other argument. self.assertRaises(IllegalArgumentError, BaseCluster, bfm1, base_character=character1, normalised_form=nf1) self.assertRaises(IllegalArgumentError, BaseCluster, bfm1, diacritic_characters=[character3], normalised_form=nf1) self.assertRaises(IllegalArgumentError, BaseCluster, bfm1, spacing_characters=[character4], normalised_form=nf1) # All of the characters in a BaseCluster must be associated with # the same binary features model. self.assertRaises(MismatchedModelsError, BaseCluster, bfm1, base_character=character1, diacritic_characters=[character2]) # A BaseCluster expects specific types of characters in its # arguments. self.assertRaises(MismatchedTypesError, BaseCluster, bfm1, base_character=character3) self.assertRaises(MismatchedTypesError, BaseCluster, bfm1, base_character=character1, diacritic_characters=[character4]) self.assertRaises(MismatchedTypesError, BaseCluster, bfm1, base_character=character1, spacing_characters=[character3])
def test_object_caching (self): # Creating a Character with the same IPA form as an existing # Character must return the existing Character, if both are # associated with the same BinaryFeaturesModel. character1 = BaseCharacter(self.bfm, 'a') character2 = BaseCharacter(self.bfm, 'a') self.assertEqual(character1, character2) character3 = BaseCharacter(self.bfm, 'b') self.assertNotEqual(character1, character3) bfm2 = BinaryFeaturesModel() character4 = BaseCharacter(bfm2, 'a') self.assertNotEqual(character1, character4) # It is an error to create a Character with the same IPA form # but of a different type (subclass). self.assertRaises(InvalidCharacterError, DiacriticCharacter, self.bfm, 'a') # Initialising of the Character should happen only once. feature = BaseFeature(self.bfm, 'voiced') character1.set_feature_value(feature, HAS_FEATURE) self.assertEqual(character1.get_feature_value(feature), HAS_FEATURE) character5 = BaseCharacter(self.bfm, 'a') self.assertEqual(character1.get_feature_value(feature), HAS_FEATURE) character6 = DiacriticCharacter(self.bfm, 'c') character6.set_feature_value(feature, HAS_FEATURE) self.assertEqual(character6.get_feature_value(feature), HAS_FEATURE) character7 = DiacriticCharacter(self.bfm, 'c') self.assertEqual(character6.get_feature_value(feature), HAS_FEATURE) character8 = SpacingCharacter(self.bfm, 'd') character8.set_feature_value(feature, HAS_FEATURE) self.assertEqual(character8.get_feature_value(feature), HAS_FEATURE) character9 = SpacingCharacter(self.bfm, 'd') self.assertEqual(character8.get_feature_value(feature), HAS_FEATURE) character10 = SuprasegmentalCharacter(self.bfm, 'e') feature2 = SuprasegmentalFeature(self.bfm, 'syllabic') character10.set_feature_value(feature2, HAS_FEATURE) self.assertEqual(character10.get_feature_value(feature2), HAS_FEATURE) character11 = SuprasegmentalCharacter(self.bfm, 'e') self.assertEqual(character10.get_feature_value(feature2), HAS_FEATURE)
def test_delete (self): Feature._cache = {} self.assertEqual(len(Feature._cache), 0) feature = BaseFeature(self.bfm, 'voiced') character = BaseCharacter(self.bfm, 'a') character.set_feature_value(feature, HAS_FEATURE) self.assertEqual(len(Feature._cache), 1) self.assertEqual(character.get_feature_value(feature), HAS_FEATURE) feature.delete() self.assertEqual(len(Feature._cache), 0) self.assertRaises(MismatchedModelsError, character.get_feature_value, feature) feature = BaseFeature(self.bfm, 'voiced') character = SpacingCharacter(self.bfm, 'b') self.assertEqual(len(Feature._cache), 1) feature.delete() self.assertEqual(len(Feature._cache), 0)
def test_spacing_characters (self): self.assertEqual(len(self.bfm.spacing_characters), 0) character1 = SpacingCharacter(self.bfm, 'a') self.assertEqual(len(self.bfm.spacing_characters), 1) self.assertTrue(character1 in self.bfm.spacing_characters) character2 = SpacingCharacter(self.bfm, 'b') self.assertEqual(len(self.bfm.spacing_characters), 2) self.assertTrue(character1 in self.bfm.spacing_characters) self.assertTrue(character2 in self.bfm.spacing_characters) character2.delete() self.assertEqual(len(self.bfm.spacing_characters), 1) self.assertTrue(character1 in self.bfm.spacing_characters) character1.delete() self.assertEqual(len(self.bfm.spacing_characters), 0) character3 = SuprasegmentalCharacter(self.bfm, 'c') self.assertEqual(len(self.bfm.spacing_characters), 0)
def test_object_caching(self): # Creating a Character with the same IPA form as an existing # Character must return the existing Character, if both are # associated with the same BinaryFeaturesModel. character1 = BaseCharacter(self.bfm, 'a') character2 = BaseCharacter(self.bfm, 'a') self.assertEqual(character1, character2) character3 = BaseCharacter(self.bfm, 'b') self.assertNotEqual(character1, character3) bfm2 = BinaryFeaturesModel() character4 = BaseCharacter(bfm2, 'a') self.assertNotEqual(character1, character4) # It is an error to create a Character with the same IPA form # but of a different type (subclass). self.assertRaises(InvalidCharacterError, DiacriticCharacter, self.bfm, 'a') # Initialising of the Character should happen only once. feature = BaseFeature(self.bfm, 'voiced') character1.set_feature_value(feature, HAS_FEATURE) self.assertEqual(character1.get_feature_value(feature), HAS_FEATURE) character5 = BaseCharacter(self.bfm, 'a') self.assertEqual(character1.get_feature_value(feature), HAS_FEATURE) character6 = DiacriticCharacter(self.bfm, 'c') character6.set_feature_value(feature, HAS_FEATURE) self.assertEqual(character6.get_feature_value(feature), HAS_FEATURE) character7 = DiacriticCharacter(self.bfm, 'c') self.assertEqual(character6.get_feature_value(feature), HAS_FEATURE) character8 = SpacingCharacter(self.bfm, 'd') character8.set_feature_value(feature, HAS_FEATURE) self.assertEqual(character8.get_feature_value(feature), HAS_FEATURE) character9 = SpacingCharacter(self.bfm, 'd') self.assertEqual(character8.get_feature_value(feature), HAS_FEATURE) character10 = SuprasegmentalCharacter(self.bfm, 'e') feature2 = SuprasegmentalFeature(self.bfm, 'syllabic') character10.set_feature_value(feature2, HAS_FEATURE) self.assertEqual(character10.get_feature_value(feature2), HAS_FEATURE) character11 = SuprasegmentalCharacter(self.bfm, 'e') self.assertEqual(character10.get_feature_value(feature2), HAS_FEATURE)
def test_model(self): configuration = ''' [Base Features] anterior low syllabic voiced [Base Characters] a: b: anterior c: low, voiced [Diacritic Characters] ̥: +anterior [Spacing Characters] ʰ: -low, +voiced [Suprasegmental Features] phrase stressed [Suprasegmental Characters] |: +phrase ˈ: +stressed, +phrase ''' model = self.parser.parse(configuration) # Base features. self.assertEqual(len(model.base_features), 4) anterior = BaseFeature(model, 'anterior') low = BaseFeature(model, 'low') syllabic = BaseFeature(model, 'syllabic') voiced = BaseFeature(model, 'voiced') self.assertEqual(len(model.base_features), 4) self.assertTrue(anterior in model.base_features) self.assertTrue(low in model.base_features) self.assertTrue(syllabic in model.base_features) self.assertTrue(voiced in model.base_features) # Base characters. self.assertEqual(len(model.base_characters), 3) a = BaseCharacter(model, 'a') b = BaseCharacter(model, 'b') c = BaseCharacter(model, 'c') self.assertEqual(len(model.base_characters), 3) self.assertTrue(a in model.base_characters) self.assertTrue(b in model.base_characters) self.assertTrue(c in model.base_characters) # Diacritic characters. self.assertEqual(len(model.diacritic_characters), 1) ring = DiacriticCharacter(model, '̥') self.assertEqual(len(model.diacritic_characters), 1) self.assertTrue(ring in model.diacritic_characters) # Spacing characters. self.assertEqual(len(model.spacing_characters), 1) ʰ = SpacingCharacter(model, 'ʰ') self.assertEqual(len(model.spacing_characters), 1) self.assertTrue(ʰ in model.spacing_characters) # Suprasegmental features. self.assertEqual(len(model.suprasegmental_features), 2) phrase = SuprasegmentalFeature(model, 'phrase') stressed = SuprasegmentalFeature(model, 'stressed') self.assertEqual(len(model.suprasegmental_features), 2) self.assertTrue(phrase in model.suprasegmental_features) self.assertTrue(stressed in model.suprasegmental_features) # Suprasegmental characters. self.assertEqual(len(model.suprasegmental_characters), 2) bar = SuprasegmentalCharacter(model, '|') ˈ = SuprasegmentalCharacter(model, 'ˈ') self.assertEqual(len(model.suprasegmental_characters), 2) self.assertTrue(bar in model.suprasegmental_characters) self.assertTrue(ˈ in model.suprasegmental_characters) # Feature values. anterior_has_feature = anterior.get_value_characters(HAS_FEATURE) self.assertEqual(len(anterior_has_feature), 2) self.assertTrue(b in anterior_has_feature) self.assertTrue(ring in anterior_has_feature) anterior_not_has_feature = anterior.get_value_characters( NOT_HAS_FEATURE) self.assertEqual(len(anterior_not_has_feature), 2) self.assertTrue(a in anterior_not_has_feature) self.assertTrue(c in anterior_not_has_feature) anterior_inapplicable_feature = anterior.get_value_characters( INAPPLICABLE_FEATURE) self.assertEqual(len(anterior_inapplicable_feature), 1) self.assertTrue(ʰ in anterior_inapplicable_feature) phrase_has_feature = phrase.get_value_characters(HAS_FEATURE) self.assertEqual(len(phrase_has_feature), 2) self.assertTrue(bar in phrase_has_feature) self.assertTrue(ˈ in phrase_has_feature) phrase_not_has_feature = phrase.get_value_characters(NOT_HAS_FEATURE) self.assertEqual(len(phrase_not_has_feature), 0) phrase_inapplicable_feature = phrase.get_value_characters( INAPPLICABLE_FEATURE) self.assertEqual(len(phrase_inapplicable_feature), 0)