From 7c92b5d19346cde17a9f3a7cb5017ad6f41f4351 Mon Sep 17 00:00:00 2001 From: Tiendil Date: Sun, 26 Jan 2014 15:30:04 +0300 Subject: [PATCH] generators tests --- pynames/__init__.py | 2 ++ pynames/from_list_generator.py | 22 +++++++++----- pynames/from_tables_generator.py | 29 ++++++++++--------- pynames/generators.py | 21 +++----------- .../korean/fixtures/korean_names_list.json | 1 + .../fixtures/mongolian_names_list.json | 1 + pynames/orc/fixtures/orc_names_list.json | 5 ++-- pynames/relations.py | 16 ++++++++++ .../russian/fixtures/pagan_names_list.json | 1 + .../fixtures/scandinavian_names_list.json | 17 +++++------ .../fixtures/test_from_list_generator.json | 3 +- pynames/tests/test_generators.py | 2 ++ 12 files changed, 69 insertions(+), 51 deletions(-) create mode 100644 pynames/relations.py diff --git a/pynames/__init__.py b/pynames/__init__.py index 3f6572d..7406fb8 100644 --- a/pynames/__init__.py +++ b/pynames/__init__.py @@ -5,3 +5,5 @@ import pynames.mongolian import pynames.scandinavian import pynames.korean import pynames.russian + +from pynames.generators import GENDER, LANGUAGE diff --git a/pynames/from_list_generator.py b/pynames/from_list_generator.py index 3418218..55517bb 100644 --- a/pynames/from_list_generator.py +++ b/pynames/from_list_generator.py @@ -17,10 +17,13 @@ class FromListGenerator(BaseGenerator): error_msg = 'FromListGenerator: you must make subclass of FromListGenerator and define attribute SOURCE in it.' raise NotImplementedError(error_msg) + with open(self.SOURCE) as f: - names_data = json.load(f) + names_data = json.load(f, encoding='utf-8') + self.native_language = names_data['native_language'] + self.languages = set(names_data['languages']) for name_data in names_data['names']: - self.names_list.append(Name(names_data['native_language'], name_data)) + self.names_list.append(Name(self.native_language, name_data)) if not self.names_list: raise PynamesException('FromListGenerator: no names loaded from "%s"' % self.SOURCE) @@ -33,18 +36,23 @@ class FromListGenerator(BaseGenerator): key = self._get_cache_key(genders) genders = frozenset(genders) if key not in self.choices: - self.choices[key] = [name_record - for name_record in self.names_list + self.choices[key] = [name_record + for name_record in self.names_list if name_record.exists_for(genders)] return self.choices[key] - def get_names_number(self, genders=GENDER.ALL): + def get_names_number(self, genders=GENDER.ALL): return len(self._get_slice(genders)) - def get_name(self, genders=GENDER.ALL): + def get_name(self, genders=GENDER.ALL): return random.choice(self._get_slice(genders)) - def get_name_simple(self, gender=GENDER.MALE, language=LANGUAGE.NATIVE): + def get_name_simple(self, gender=GENDER.MALE, language=LANGUAGE.NATIVE): name = self.get_name(genders=[gender]) return name.get_for(gender, language) + def test_names_consistency(self, test): + for name in self.names_list: + for gender in GENDER.ALL: + if gender in name.translations: + test.assertEqual(set(name.translations[gender].keys()) & self.languages, self.languages) diff --git a/pynames/from_tables_generator.py b/pynames/from_tables_generator.py index 19f8fe7..9e9f791 100644 --- a/pynames/from_tables_generator.py +++ b/pynames/from_tables_generator.py @@ -27,12 +27,12 @@ class Template(object): return number def get_name(self, tables): - languages = dict( (lang, u'') for lang in self.languages) + languages = dict( (lang, u'') for lang in self.languages) for slug in self.template: record = random.choice(tables[slug]) for lang in languages: languages[lang] += record['languages'][lang] - genders = dict( (gender, languages) for gender in self.genders) + genders = dict( (gender, languages) for gender in self.genders) return Name(self.native_language, {'genders': genders}) @@ -52,9 +52,9 @@ class FromTablesGenerator(BaseGenerator): with open(self.SOURCE) as f: data = json.load(f) - native_language = data['native_language'] - languages = data['languages'] - self.templates = [ Template(template_name, native_language, languages, template_data) + self.native_language = data['native_language'] + self.languages = set(data['languages']) + self.templates = [ Template(template_name, self.native_language, self.languages, template_data) for template_name, template_data in data['templates'].items() ] self.tables = data['tables'] @@ -66,7 +66,7 @@ class FromTablesGenerator(BaseGenerator): key = self._get_templates_cache_key(genders) genders = frozenset(genders) if key not in self.templates_choices: - self.templates_choices[key] = [template + self.templates_choices[key] = [template for template in self.templates if template.exists_for(genders)] return self.templates_choices[key] @@ -75,27 +75,30 @@ class FromTablesGenerator(BaseGenerator): pass - def get_names_number(self, genders=GENDER.ALL): + def get_names_number(self, genders=GENDER.ALL): templates = self._get_templates_slice(genders) number = sum([template.get_names_number(self.tables) for template in templates]) return number - def get_name(self, genders=GENDER.ALL): + def get_name(self, genders=GENDER.ALL): templates = self._get_templates_slice(genders) definition_number = sum([template.probability for template in templates]) choice = random.randint(1, definition_number) - + for template in templates: if choice > template.probability: choice -= template.probability continue return template.get_name(self.tables) - - raise PynamesException('FromTablesGenerator: wrong template structure - cannot choose template for genders %r with template source: "%s"' % (genders, self.SOURCE) ) - def get_name_simple(self, gender=GENDER.MALE, language=LANGUAGE.NATIVE): + raise PynamesException('FromTablesGenerator: wrong template structure - cannot choose template for genders %r with template source: "%s"' % (genders, self.SOURCE) ) + + def get_name_simple(self, gender=GENDER.MALE, language=LANGUAGE.NATIVE): name = self.get_name(genders=[gender]) return name.get_for(gender, language) - + def test_names_consistency(self, test): + for table_name, table in self.tables.iteritems(): + for record in table: + test.assertEqual(set(record['languages'].keys()) & self.languages, self.languages) diff --git a/pynames/generators.py b/pynames/generators.py index 521cb24..1216e76 100644 --- a/pynames/generators.py +++ b/pynames/generators.py @@ -1,25 +1,12 @@ # coding: utf-8 +from pynames.relations import GENDER, LANGUAGE + + class PynamesException(Exception): pass -class GENDER: - MALE = 'm' - FEMALE = 'f' - MF = ['m', 'f'] - - ALL = ['m', 'f'] - - -class LANGUAGE: - RU = 'ru' - EN = 'en' - NATIVE = 'native' - - ALL = ['ru', 'en', 'native'] - - class BaseGenerator(object): pass @@ -45,7 +32,7 @@ class Name(object): for gender in GENDER.ALL: if gender in self.genders: return self.translations[gender][self.native_language] - error_msg = 'Name: can not get default value for name with data: %r' % self.genders + error_msg = u'Name: can not get default value for name with data: %r' % self.genders raise PynamesException(error_msg) def __str__(self): return self.__unicode__() diff --git a/pynames/korean/fixtures/korean_names_list.json b/pynames/korean/fixtures/korean_names_list.json index 23c07de..5a12fea 100644 --- a/pynames/korean/fixtures/korean_names_list.json +++ b/pynames/korean/fixtures/korean_names_list.json @@ -2,6 +2,7 @@ "source": "http://www.gaminggeeks.org/Resources/KateMonk/", "translation": "Wizard-worker and Swingaroo", "native_language": "en", + "languages": ["en", "ru"], "names": [ {"genders": {"m": {"en": "An-Kor", "ru":"Ан-Кор"}}}, {"genders": {"m": {"en": "Bong-Chol", "ru":"Бонг-Чол"}}}, {"genders": {"m": {"en": "Bum-Kun", "ru":"Бум-Кун"}}}, diff --git a/pynames/mongolian/fixtures/mongolian_names_list.json b/pynames/mongolian/fixtures/mongolian_names_list.json index 606258c..d7522de 100644 --- a/pynames/mongolian/fixtures/mongolian_names_list.json +++ b/pynames/mongolian/fixtures/mongolian_names_list.json @@ -2,6 +2,7 @@ "source": "http://www.gaminggeeks.org/Resources/KateMonk/", "translation": "Wizard-worker and Swingaroo", "native_language": "en", + "languages": ["en", "ru"], "names": [{"genders": {"m": {"en": "Al", "ru": "Ал"}, "f": {"en": "Al", "ru": "Ал"}}}, {"genders": {"m": {"en": "Alagh", "ru": "Алагх"}, "f": {"en": "Alagh", "ru": "Алагх"}}}, {"genders": {"m": {"en": "Altan", "ru": "Алтан"}, "f": {"en": "Altan", "ru": "Алтан"}}}, diff --git a/pynames/orc/fixtures/orc_names_list.json b/pynames/orc/fixtures/orc_names_list.json index cc53c78..03a11f5 100644 --- a/pynames/orc/fixtures/orc_names_list.json +++ b/pynames/orc/fixtures/orc_names_list.json @@ -1,6 +1,7 @@ { "source": "Wizard-worker", "native_language": "ru", + "languages": ["ru"], "names": [ {"genders": {"m": {"ru": "Ахн"}}}, {"genders": {"m": {"ru": "Ахер"}}}, {"genders": {"m": {"ru": "Авех"}}}, @@ -218,7 +219,7 @@ {"genders": {"m": {"ru": "Хрох"}}}, {"genders": {"m": {"ru": "Хген"}}}, {"genders": {"m": {"ru": "Хсухон"}}}, - + {"genders": {"f": {"ru": "Атта"}}}, {"genders": {"f": {"ru": "Асса"}}}, @@ -465,5 +466,3 @@ {"genders": {"f": {"ru": "Шушша"}}} ] } - - diff --git a/pynames/relations.py b/pynames/relations.py new file mode 100644 index 0000000..9b1ab12 --- /dev/null +++ b/pynames/relations.py @@ -0,0 +1,16 @@ +# coding: utf-8 + +class GENDER: + MALE = 'm' + FEMALE = 'f' + MF = ['m', 'f'] + + ALL = ['m', 'f'] + + +class LANGUAGE: + RU = 'ru' + EN = 'en' + NATIVE = 'native' + + ALL = ['ru', 'en', 'native'] diff --git a/pynames/russian/fixtures/pagan_names_list.json b/pynames/russian/fixtures/pagan_names_list.json index 9f0bcca..7196773 100644 --- a/pynames/russian/fixtures/pagan_names_list.json +++ b/pynames/russian/fixtures/pagan_names_list.json @@ -1,6 +1,7 @@ { "source": "http://paganism.msk.ru/name/name.htm", "native_language": "ru", + "languages": ["ru"], "names": [ {"genders": {"m": {"ru": "Бажен"}, "f": {"ru": "Бажена"}}}, {"genders": {"m": {"ru": "Белослав"}, "f": {"ru": "Белослава"}}}, {"genders": {"m": {"ru": "Беримир"}}}, diff --git a/pynames/scandinavian/fixtures/scandinavian_names_list.json b/pynames/scandinavian/fixtures/scandinavian_names_list.json index 4134b8a..8ce5f13 100644 --- a/pynames/scandinavian/fixtures/scandinavian_names_list.json +++ b/pynames/scandinavian/fixtures/scandinavian_names_list.json @@ -1,8 +1,9 @@ { "source": "http://www.gaminggeeks.org/Resources/KateMonk/", "translation": "Wizard-worker and Swingaroo", - "native_language": "ru", - "names": [ + "native_language": "en", + "languages": ["en", "ru"], + "names": [ {"genders": {"m": {"en": "Adalbrikt", "ru": "Адалбрикт", "ru_ext": "Адалбрикт"}}}, {"genders": {"m": {"en": "Adalradr", "ru": "Адалрадр", "ru_ext": "Адалрадр"}}}, {"genders": {"m": {"en": "Adalstein", "ru": "Адалстейн", "ru_ext": "Адалстėн"}}}, @@ -12,10 +13,10 @@ {"genders": {"m": {"en": "Aflaeg", "ru": "Афлаег", "ru_ext": "Афлäг"}}}, {"genders": {"m": {"en": "Agder", "ru": "Агдер", "ru_ext": "Агдер"}}}, {"genders": {"m": {"en": "Agdir", "ru": "Агдир", "ru_ext": "Агдир"}}}, - {"genders": {"m": {"en": "Agger", "ru": "Аггер", "ru_ext": "Аггер"}}}, + {"genders": {"m": {"en": "Agger", "ru": "Аггер", "ru_ext": "Аггер"}}}, {"genders": {"m": {"en": "Agmund", "ru": "Агмунд", "ru_ext": "Агмунд"}}}, {"genders": {"m": {"en": "Agmundr", "ru": "Агмундр", "ru_ext": "Агмундр"}}}, - {"genders": {"m": {"en": "Anulo", "ru": "Ануло", "ru_ext": "Ануло"}}}, + {"genders": {"m": {"en": "Anulo", "ru": "Ануло", "ru_ext": "Ануло"}}}, {"genders": {"m": {"en": "Agnarr", "ru": "Агнарр", "ru_ext": "Агнарр"}}}, {"genders": {"m": {"en": "Alaf", "ru": "Алаф", "ru_ext": "Алаф"}}}, {"genders": {"m": {"en": "Aleifr", "ru": "Алейфр", "ru_ext": "Алėфр"}}}, @@ -73,7 +74,7 @@ {"genders": {"m": {"en": "AbjГёrn", "ru": "Абгёрн", "ru_ext": "Абгёрн"}}}, {"genders": {"m": {"en": "Asbrand", "ru": "Асбранд", "ru_ext": "Асбранд"}}}, {"genders": {"m": {"en": "Asfrith", "ru": "Асфрит", "ru_ext": "Асфриѳ"}}}, - {"genders": {"m": {"en": "Asgaut"}, "ru": "Асгаут", "ru_ext": "Асгáт"}}, + {"genders": {"m": {"en": "Asgaut", "ru": "Асгаут", "ru_ext": "Асгáт"}}}, {"genders": {"m": {"en": "Asgautr", "ru": "Асгаутр", "ru_ext": "Асгáтр"}}}, {"genders": {"m": {"en": "Asgeir", "ru": "Асгейр", "ru_ext": "Асгėр"}}}, {"genders": {"m": {"en": "Asgeirr", "ru": "Асгейрр", "ru_ext": "Асгėрр"}}}, @@ -960,7 +961,7 @@ {"genders": {"f": {"en": "Alkai", "ru": "Алкаи", "ru_ext": "Алкаї"}}}, {"genders": {"f": {"en": "Alphege", "ru": "Алфеге", "ru-ext": "Алфеге"}}}, {"genders": {"f": {"en": "Amunde", "ru": "Амунде", "ru-ext": "Амунде"}}}, - {"genders": {"f": {"en": "Amundi", "ru": "Амунди", "ru-ext": "Амунди"}}}, + {"genders": {"f": {"en": "Amundi", "ru": "Амунди", "ru-ext": "Амунди"}}}, {"genders": {"f": {"en": "Api", "ru": "Апи", "ru-ext": "Апи"}}}, {"genders": {"f": {"en": "Arne", "ru": "Арне", "ru-ext": "Арне"}}}, {"genders": {"f": {"en": "Arni", "ru": "Арни", "ru-ext": "Арни"}}}, @@ -1230,8 +1231,4 @@ {"genders": {"f": {"en": "Vidfari", "ru": "Видфари", "ru-ext": "Видфари"}}}, {"genders": {"f": {"en": "Viglei", "ru": "Виглей", "ru-ext": "Виглė"}}}, {"genders": {"f": {"en": "Vili", "ru": "Вили", "ru-ext": "Вили"}}}] - - } - - diff --git a/pynames/tests/fixtures/test_from_list_generator.json b/pynames/tests/fixtures/test_from_list_generator.json index 5688e5f..94a4c69 100644 --- a/pynames/tests/fixtures/test_from_list_generator.json +++ b/pynames/tests/fixtures/test_from_list_generator.json @@ -1,5 +1,6 @@ { "native_language": "ru", + "languages": ["ru"], "names": [ {"genders": {"m": {"ru": "ru_m_name_1", "en": "en_m_name_1"}}}, @@ -24,4 +25,4 @@ "f": {"ru": "ru_f_name_5", "en": "en_f_name_5"}}} ] -} \ No newline at end of file +} diff --git a/pynames/tests/test_generators.py b/pynames/tests/test_generators.py index 308cf60..f75082d 100644 --- a/pynames/tests/test_generators.py +++ b/pynames/tests/test_generators.py @@ -59,6 +59,8 @@ def create_test_method(generator_class): self.assertTrue(generator.get_name_simple()) self.assertTrue(generator.get_name()) + generator.test_names_consistency(self) + test_method.__name__ = 'test_%s' % generator.__name__ return test_method