コード例 #1
0
 def test_object_caching(self):
     # Creating a Feature with the same name as an existing
     # Feature must return the existing Feature, if both are
     # associated with the same BinaryFeaturesModel.
     feature1 = BaseFeature(self.bfm, 'voiced')
     feature2 = BaseFeature(self.bfm, 'voiced')
     self.assertEqual(feature1, feature2)
     feature3 = BaseFeature(self.bfm, 'consonantal')
     self.assertNotEqual(feature1, feature3)
     bfm2 = BinaryFeaturesModel()
     feature4 = BaseFeature(bfm2, 'voiced')
     self.assertNotEqual(feature1, feature4)
     # It is an error to create a Feature with the same IPA form
     # but of a different type (subclass).
     self.assertRaises(InvalidFeatureError, SuprasegmentalFeature, self.bfm,
                       'voiced')
     # Initialisation of a Feature should happen only once.
     character1 = BaseCharacter(self.bfm, 'a')
     character1.set_feature_value(feature1, HAS_FEATURE)
     self.assertEqual(feature1.get_value_characters(HAS_FEATURE),
                      set([character1]))
     feature5 = BaseFeature(self.bfm, 'voiced')
     self.assertEqual(feature1.get_value_characters(HAS_FEATURE),
                      set([character1]))
     feature6 = SuprasegmentalFeature(self.bfm, 'syllabic')
     character2 = SuprasegmentalCharacter(self.bfm, 'b')
     character2.set_feature_value(feature6, HAS_FEATURE)
     self.assertEqual(feature6.get_value_characters(HAS_FEATURE),
                      set([character2]))
     feature7 = SuprasegmentalFeature(self.bfm, 'syllabic')
     self.assertEqual(feature6.get_value_characters(HAS_FEATURE),
                      set([character2]))
コード例 #2
0
 def setUp (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')
コード例 #3
0
 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)
コード例 #4
0
 def test_feature_value_illegal(self):
     # The Feature must belong to the same BinaryFeaturesModel as
     # the Character.
     character = SuprasegmentalCharacter(self.bfm, 'a')
     bfm2 = BinaryFeaturesModel()
     feature1 = SuprasegmentalFeature(bfm2, 'voiced')
     self.assertRaises(MismatchedModelsError, character.get_feature_value,
                       feature1)
     self.assertRaises(MismatchedModelsError, character.set_feature_value,
                       feature1, HAS_FEATURE)
     # The Feature's type (subclass) must be appropriate to the
     # type (subclass) of the Character.
     feature2 = BaseFeature(self.bfm, 'stressed')
     self.assertRaises(MismatchedTypesError, character.get_feature_value,
                       feature2)
     self.assertRaises(MismatchedTypesError, character.set_feature_value,
                       feature2, HAS_FEATURE)
     # A SuprasegmentalCharacter must have a feature value for all
     # SuprasegmentalFeatures.
     feature3 = SuprasegmentalFeature(self.bfm, 'syllabic')
     self.assertRaises(InvalidCharacterError, character.get_feature_value,
                       feature3)
     # Only certain values are permitted.
     self.assertRaises(IllegalArgumentError, character.set_feature_value,
                       feature3, True)
コード例 #5
0
 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]))
コード例 #6
0
 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)
コード例 #7
0
ファイル: character_tests.py プロジェクト: Anaphory/zounds
 def test_delete(self):
     self.assertEqual(len(Character._cache), 0)
     feature = BaseFeature(self.bfm, 'voiced')
     character = BaseCharacter(self.bfm, 'a')
     character.set_feature_value(feature, HAS_FEATURE)
     self.assertEqual(feature.get_value_characters(HAS_FEATURE),
                      set([character]))
     self.assertEqual(len(Character._cache), 1)
     character.delete()
     self.assertEqual(len(Character._cache), 0)
     self.assertEqual(feature.get_value_characters(HAS_FEATURE), set())
コード例 #8
0
ファイル: character_tests.py プロジェクト: Anaphory/zounds
 def test_normalised_form(self):
     feature1 = BaseFeature(self.bfm, 'anterior')
     character1 = DiacriticCharacter(self.bfm, 'a')
     character1.set_feature_value(feature1, HAS_FEATURE)
     self.assertEqual(character1.normalised_form,
                      NormalisedForm('{0}{1}'.format(BNFM, HAS_FEATURE)))
     # Adding a feature changes the normalised form.
     feature2 = BaseFeature(self.bfm, 'dental')
     character1.set_feature_value(feature2, INAPPLICABLE_FEATURE)
     self.assertEqual(
         character1.normalised_form,
         NormalisedForm('{0}{1}{2}'.format(BNFM, HAS_FEATURE,
                                           INAPPLICABLE_FEATURE)))
     # The order of the normalised form feature values is
     # alphabetical by feature name.
     feature3 = BaseFeature(self.bfm, 'consonantal')
     character1.set_feature_value(feature3, NOT_HAS_FEATURE)
     self.assertEqual(
         character1.normalised_form,
         NormalisedForm('{0}{1}{2}{3}'.format(BNFM, HAS_FEATURE,
                                              NOT_HAS_FEATURE,
                                              INAPPLICABLE_FEATURE)))
     # Renaming a feature may change the normalised form.
     feature1.name = 'vocalic'
     self.assertEqual(
         character1.normalised_form,
         NormalisedForm('{0}{1}{2}{3}'.format(BNFM, NOT_HAS_FEATURE,
                                              INAPPLICABLE_FEATURE,
                                              HAS_FEATURE)))
     # Changing a feature value changes the normalised form.
     character1.set_feature_value(feature1, NOT_HAS_FEATURE)
     self.assertEqual(
         character1.normalised_form,
         NormalisedForm('{0}{1}{2}{1}'.format(BNFM, NOT_HAS_FEATURE,
                                              INAPPLICABLE_FEATURE)))
     # Removing a feature value changes the normalised form.
     feature2.delete()
     self.assertEqual(
         character1.normalised_form,
         NormalisedForm('{0}{1}{1}'.format(BNFM, NOT_HAS_FEATURE)))
コード例 #9
0
 def test_normalised_form(self):
     feature1 = SuprasegmentalFeature(self.bfm, 'anterior')
     character = SuprasegmentalCharacter(self.bfm, 'n')
     character.set_feature_value(feature1, HAS_FEATURE)
     self.assertEqual(character.normalised_form,
                      NormalisedForm('{0}{1}'.format(SNFM, HAS_FEATURE)))
     # Adding a feature changes the normalised form.
     feature2 = SuprasegmentalFeature(self.bfm, 'dental')
     # All features must have a value.
     self.assertRaises(InvalidCharacterError, getattr, character,
                       'normalised_form')
     character.set_feature_value(feature2, NOT_HAS_FEATURE)
     self.assertEqual(
         character.normalised_form,
         NormalisedForm('{0}{1}{2}'.format(SNFM, HAS_FEATURE,
                                           NOT_HAS_FEATURE)))
     # The order of the normalised form feature values is
     # alphabetical by feature name.
     feature3 = SuprasegmentalFeature(self.bfm, 'consonantal')
     character.set_feature_value(feature3, HAS_FEATURE)
     self.assertEqual(
         character.normalised_form,
         NormalisedForm('{0}{1}{1}{2}'.format(SNFM, HAS_FEATURE,
                                              NOT_HAS_FEATURE)))
     # Renaming a feature may change the normalised form.
     feature3.name = 'vocalic'
     self.assertEqual(
         character.normalised_form,
         NormalisedForm('{0}{1}{2}{1}'.format(SNFM, HAS_FEATURE,
                                              NOT_HAS_FEATURE)))
     # Changing a feature value changes the normalised form.
     character.set_feature_value(feature1, INAPPLICABLE_FEATURE)
     self.assertEqual(
         character.normalised_form,
         NormalisedForm('{0}{3}{2}{1}'.format(SNFM, HAS_FEATURE,
                                              NOT_HAS_FEATURE,
                                              INAPPLICABLE_FEATURE)))
     # Removing a feature value changes the normalised form.
     feature3.delete()
     self.assertEqual(
         character.normalised_form,
         NormalisedForm('{0}{2}{1}'.format(SNFM, NOT_HAS_FEATURE,
                                           INAPPLICABLE_FEATURE)))
     # Adding a feature of a different type does not change the
     # normalised form.
     feature4 = BaseFeature(self.bfm, 'syllabic')
     self.assertEqual(
         character.normalised_form,
         NormalisedForm('{0}{2}{1}'.format(SNFM, NOT_HAS_FEATURE,
                                           INAPPLICABLE_FEATURE)))
コード例 #10
0
 def test_name(self):
     feature = BaseFeature(self.bfm, 'voiced')
     self.assertEqual(feature.name, 'voiced')
     # Feature names can be set.
     feature.name = 'vocalic'
     self.assertEqual(feature.name, 'vocalic')
     # Feature names must be unique across all features in a binary
     # features model.
     feature2 = SuprasegmentalFeature(self.bfm, 'consonantal')
     self.assertRaises(InvalidFeatureError, setattr, feature2, 'name',
                       'vocalic')
     # Setting the name to the existing name should not raise an error.
     feature2.name = 'consonantal'
     self.assertEqual(feature2.name, 'consonantal')
コード例 #11
0
 def test_optional_sections(self):
     # Optional sections should be optional.
     configuration = '''
       [Base Features] anterior low syllabic voiced
       [Base Characters] a: b: anterior c: low, voiced'''
     model = self.parser.parse(configuration)
     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)
     # Feature values.
     anterior_has_feature = anterior.get_value_characters(HAS_FEATURE)
     self.assertEqual(len(anterior_has_feature), 1)
     self.assertTrue(b 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), 0)
コード例 #12
0
 def test_normalised_form_cluster_creation(self):
     # Test that the correct subclass of Cluster is created from a
     # normalised form.
     bfm = BinaryFeaturesModel()
     feature1 = BaseFeature(bfm, 'anterior')
     feature2 = SuprasegmentalFeature(bfm, 'long')
     character1 = BaseCharacter(bfm, 'a')
     character1.set_feature_value(feature1, HAS_FEATURE)
     character2 = SuprasegmentalCharacter(bfm, 'b')
     character2.set_feature_value(feature2, HAS_FEATURE)
     nf1 = NormalisedForm('{}{}'.format(BNFM, HAS_FEATURE))
     nf2 = NormalisedForm('{}{}'.format(SNFM, HAS_FEATURE))
     cluster1 = Cluster(bfm, normalised_form=nf1)
     cluster2 = Cluster(bfm, normalised_form=nf2)
     self.assertTrue(isinstance(cluster1, BaseCluster))
     self.assertTrue(isinstance(cluster2, SuprasegmentalCluster))
     self.assertRaises(IllegalArgumentError, Cluster, '')
コード例 #13
0
ファイル: optional_tests.py プロジェクト: Anaphory/zounds
 def test_applier_form (self):
     a = BaseCharacter(self.bfm, 'a')
     cluster1 = BaseCluster(self.bfm, base_character=a)
     cluster1_form = '{0}{1}{2}{3}{3}'.format(AFM, BNFM, HAS_FEATURE,
                                              NOT_HAS_FEATURE)
     self.optional.append(cluster1)
     expected = '({})?'.format(cluster1_form)
     self.assertEqual(self.optional.applier_form, expected)
     self.optional.match_multiple = True
     expected = '({})*'.format(cluster1_form)
     self.assertEqual(self.optional.applier_form, expected)
     voiced = BaseFeature(self.bfm, 'voiced')
     feature_set = BaseFeatureSet(self.bfm)
     feature_set.set(voiced, HAS_FEATURE)
     feature_set_form = '{0}{1}{2}{2}{3}'.format(
         AFM, BNFM, INAPPLICABLE_FEATURE, HAS_FEATURE)
     self.optional.append(feature_set)
     expected = '({}{})*'.format(cluster1_form, feature_set_form)
     self.assertEqual(self.optional.applier_form, expected)
コード例 #14
0
ファイル: character_tests.py プロジェクト: Anaphory/zounds
 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)
コード例 #15
0
 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)