Beispiel #1
0
 def test_match_string(self):
     form = GramForm("мр,ед,им")
     self.assertEqual(form.match_string("мр"), "мр")
     self.assertEqual(form.match_string("ед"), "ед")
     self.assertEqual(form.match_string("им"), "им")
     self.assertEqual(form.match_string("!имя"), "!имя")
     self.assertFalse(form.match_string("жр"))
Beispiel #2
0
 def test_multi_form_change(self):
     form = GramForm(u'мн,рд,мр')
     form.update(u'дт,ед')
     self.assertTrue(u'дт' in form.form)
     self.assertTrue(u'ед' in form.form)
     self.assertFalse(u'рд' in form.form)
     self.assertFalse(u'мн' in form.form)
Beispiel #3
0
 def test_multi_form_change(self):
     form = GramForm(u'мн,рд,мр')
     form.update(u'дт,ед')
     self.assertTrue(u'дт' in form.form)
     self.assertTrue(u'ед' in form.form)
     self.assertFalse(u'рд' in form.form)
     self.assertFalse(u'мн' in form.form)
Beispiel #4
0
 def test_match_string(self):
     form = GramForm(u'мр,ед,им')
     self.assertEqual(form.match_string(u'мр'), u'мр')
     self.assertEqual(form.match_string(u'ед'), u'ед')
     self.assertEqual(form.match_string(u'им'), u'им')
     self.assertEqual(form.match_string(u'!имя'), u'!имя')
     self.assertFalse(form.match_string(u'жр'))
Beispiel #5
0
 def test_multi_form_change(self):
     form = GramForm("мн,рд,мр")
     form.update("дт,ед")
     self.assertTrue("дт" in form.form)
     self.assertTrue("ед" in form.form)
     self.assertFalse("рд" in form.form)
     self.assertFalse("мн" in form.form)
Beispiel #6
0
 def test_form_str(self):
     form = GramForm(u'мр,мн,рд')
     self.assertTrue(form.get_form_string().count(u'мр') == 1)
     self.assertTrue(form.get_form_string().count(u'мн') == 1)
     self.assertTrue(form.get_form_string().count(u'рд') == 1)
     self.assertTrue(len(form.get_form_string()) == (2 * 3) + 2)
     form.update(u'дт')
     self.assertTrue(form.get_form_string().count(u'мр') == 1)
     self.assertTrue(form.get_form_string().count(u'мн') == 1)
     self.assertTrue(form.get_form_string().count(u'дт') == 1)
     self.assertTrue(len(form.get_form_string()) == (2 * 3) + 2)
Beispiel #7
0
 def is_correct(frm):
     correct = True
     if norm:
         correct = frm['norm'] == norm
     if method:
         correct = correct and (method in frm['method'])
     if cls:
         correct = correct and (frm['class'] == cls)
     if form:
         gram_filter = GramForm(form)
         gram_form = GramForm(frm['info'])
         correct = correct and gram_form.match(gram_filter)
     return correct
Beispiel #8
0
 def is_correct(frm):
     correct = True
     if norm:
         correct = frm['norm'] == norm
     if method:
         correct = correct and (method in frm['method'])
     if cls:
         correct = correct and (frm['class'] == cls)
     if form:
         gram_filter = GramForm(form)
         gram_form = GramForm(frm['info'])
         correct = correct and gram_form.match(gram_filter)
     return correct
Beispiel #9
0
 def test_form_str(self):
     form = GramForm("мр,мн,рд")
     self.assertTrue(form.get_form_string().count("мр") == 1)
     self.assertTrue(form.get_form_string().count("мн") == 1)
     self.assertTrue(form.get_form_string().count("рд") == 1)
     self.assertTrue(len(form.get_form_string()) == (2 * 3) + 2)
     form.update("дт")
     self.assertTrue(form.get_form_string().count("мр") == 1)
     self.assertTrue(form.get_form_string().count("мн") == 1)
     self.assertTrue(form.get_form_string().count("дт") == 1)
     self.assertTrue(len(form.get_form_string()) == (2 * 3) + 2)
Beispiel #10
0
 def test_form_str(self):
     form = GramForm(u'мр,мн,рд')
     self.assertTrue(form.get_form_string().count(u'мр') == 1)
     self.assertTrue(form.get_form_string().count(u'мн') == 1)
     self.assertTrue(form.get_form_string().count(u'рд') == 1)
     self.assertTrue(len(form.get_form_string()) == (2*3)+2)
     form.update(u'дт')
     self.assertTrue(form.get_form_string().count(u'мр') == 1)
     self.assertTrue(form.get_form_string().count(u'мн') == 1)
     self.assertTrue(form.get_form_string().count(u'дт') == 1)
     self.assertTrue(len(form.get_form_string()) == (2*3)+2)
Beispiel #11
0
def normalize(morph, lastname, hints=u''):
    '''
    Возвращает нормальную форму (именительный падеж) фамилии для заданного рода

    Параметры:

    * hints - подсказки об исходной форме фамилии (u'мр' или u'жр',
      по-умолчанию принимается u'мр')
    '''

    hints_form = GramForm(hints)
    gender_tag = (hints_form.match_string(u'жр') or u'мр')

    # FIXME: эта функция возвращает саму форму, а Morph.normalize возвращает
    # множество (set) возможных форм, одно из двух лучше поправить.
    return inflect(morph, lastname, u'им,ед,%s' % gender_tag)
Beispiel #12
0
 def test_lemma_graminfo(self):
     info = morph_ru.get_graminfo(u'СУСЛИКАМИ')
     self.assertEqual(len(info), 1)
     info = info[0]
     gram_form = GramForm(info['info'])
     self.assertEqual(gram_form.form, set([u'мр', u'тв', u'мн']))
     self.assertEqual(info['norm'], u'СУСЛИК')
Beispiel #13
0
def pluralize_inflected(morph, lastname, num, hints=u''):
    '''
    Вернуть фамилию в форме, которая будет сочетаться с переданным числом.
    Например: 1 Попугаев, 2 Попугаевых, 5 Попугаевых.

    Параметры:

    * morph - объект Morph
    * lastname - фамилия которую хотим склонять
    * num - число
    * hints - подсказки об исходной форме фамилии (u'мр' или u'жр')
    '''

    if num == 1:
        return normalize(morph, lastname, hints)

    hints_form = GramForm(hints)

    gender_tag = (hints_form.match_string(u'жр') or u'мр')
    return pluralize(morph, lastname, u'мн,рд,%s' % gender_tag)
Beispiel #14
0
def inflect(morph, lastname, gram_form):
    '''
    Вернуть вариант фамилии который соотвествует данной грамматической
    форме

    Параметры:

    * morph - объект Morph
    * lastname - фамилия которую хотим склонять
    * gram_form - желаемые характеристики грам. формы (если u'жр' отсутствует
      в этом параметре, то по-умолчанию принимается u'мр', или u'мр-жр', если
      указано u'мн')
    '''

    expected_form = GramForm(gram_form)

    gender_tag = (u'мр-жр' if expected_form.match_string(u'мн') else None)
    if not gender_tag:
        gender_tag = (expected_form.match_string(u'жр') or u'мр')

    # За один проход проверяется, что исходное слово может быть склонено как
    # фамилия и выбирается форма подходящая под gram_form

    present_in_decline = False
    accepted = {}
    for item in decline(lastname):
        form = GramForm(item.get('info', u''))

        # Если в результате склонения не получилось исходной формы - ложное срабатывание

        # Обязательно проверяется род: при склонении в противоположном роде
        # может получиться исходная форма но нас интересует совпадение только в
        # заданном роде

        if item.get('word', '') == lastname:
            # В случае склонения во множественную форму, род игнорируется.
            # Род всех фамилий во множественном числе - мр-жр.
            if expected_form.match_string(u'мн') or form.match_string(gender_tag):
                present_in_decline = True

        expected = form.match(expected_form)

        if expected and not accepted:
            accepted = item
            # Здесь break не нужен т.к. present_in_decline всё ещё может быть
            # не установлена в корректное значение

    # Если в результате склонения исходной формы не получилось,
    # возвращается результат склонения как для обычного слова

    if present_in_decline and accepted:
        return accepted.get('word', u'')
    else:
        return morph.inflect_ru(lastname, gram_form, smart_guess=False)
Beispiel #15
0
def pluralize(morph, lastname, gram_form=u''):
    '''
    Вернуть фамилию  во множественном числе.

    Параметры:

    * morph - объект Morph
    * lastname - фамилия которую хотим склонять
    * gram_form - желаемые характеристики грам. формы
    '''

    expected_form = GramForm(gram_form)

    # Удалить из желаемой формы признаки рода и числа
    refined_form = GramForm(gram_form).clear_gender().clear_number()

    # Если дан gram_form - склонить в указанную форму
    if refined_form.get_form_string():
        return inflect(
            morph,
            lastname,
            u','.join((refined_form.get_form_string(), u'мн',)))

    # Иначе - найти форму исходной фамилии и склонить в неё же, но во мн. числе
    # Если в желаемой форме был указан род - использовать как подсказку
    gender_tag = (expected_form.match_string(u'жр') or u'мр')

    for item in decline(lastname):
        form = GramForm(item.get('info', u''))

        # Проверить наличие исходной формы в заданном роде (аналогично inflect())
        if item.get('word', u'') == lastname and form.match_string(gender_tag):
            for case in (u'им', u'рд', u'дт', u'вн', u'тв', u'пр'):
                if form.match_string(case):
                    return inflect(morph, lastname, u'мн,%s' % case)

    # В случае неудачи - просклонять как обычное слово
    return morph.pluralize_ru(lastname, gram_form)
Beispiel #16
0
 def test_match(self):
     form = GramForm(u"мр,ед,имя")
     self.assertTrue(form.match(GramForm(u"мр")))
     self.assertTrue(form.match(GramForm(u"ед,мр")))
Beispiel #17
0
 def test_match_inverted(self):
     form = GramForm("мр,ед,имя")
     self.assertFalse(form.match(GramForm("мр,!имя")))
     self.assertTrue(form.match(GramForm("ед,!тв")))
Beispiel #18
0
 def test_match(self):
     form = GramForm("мр,ед,имя")
     self.assertTrue(form.match(GramForm("мр")))
     self.assertTrue(form.match(GramForm("ед,мр")))
Beispiel #19
0
 def test_from_str(self):
     form = GramForm(u'мн,рд')
     self.assertTrue(u'рд' in form.form)
     self.assertTrue(u'мн' in form.form)
Beispiel #20
0
def decline(lastname, gram_form=u''):
    ''' Склоняет фамилию и возвращает все возможные формы '''

    # Из фамилии выделяется предполагаемая лемма (Табуретов -> Табуретов,
    # Табуретовым -> Табуретов), лемма склоняется по правилам склонения фамилий

    def guess_lemma(name):
        '''
        Попытаться угадать сложносклоняемую фамилию (Цапок, Бегунец, Берия)

        Возвращает пару (name=lemma+suffix, lemma) либо (None, None)
        '''

        name_len = len(name)

        # Попытка угадать склонённую фамилию из 13.1.12 ("Берией")
        if name_len > 2 and name[-2:] in (u'ИИ', u'ИЮ',):
            return (lastname[:-2] + u'ИЯ', lastname[:-2])
        elif name_len > 3 and name[-3:] in (u'ИЕЙ',):
            return (lastname[:-3] + u'ИЯ', lastname[:-3])

        # Попытка угадать склонённую фамилию, закачивающуюся на -ок ("Цапка")
        # Работает, только если буква перед окончанием согласная.
        # Проверка согласной делается для исключения склонённых фамилий на -ак
        # ("Собчака")
        if name_len > 3 and name[-2:] in (u'КА', u'КУ', u'КЕ',) and name[-3] in CONSONANTS:
            return (lastname[:-2] + u'ОК', lastname[:-2])
        elif name_len > 4 and name[-3:] in (u'КОМ',) and name[-4] in CONSONANTS:
            return (lastname[:-3] + u'ОК', lastname[:-3])

        # Попытка угадать склонённую фамилию, закачивающуюся на -ец ("Бегунец")
        # FIXME: необходима проверка на коллизии с другими фамилиями (как в
        # случае с "Цапок")
        if name_len > 3 and name[-2:] in (u'ЦА', u'ЦУ', u'ЦЕ',):
            return (lastname[:-2] + u'ЕЦ', lastname[:-2])

        return (None, None)


    match = LASTNAME_PATTERN.search(lastname)
    lemma = name = match.group(1) if match else lastname # name is lemma + suffix
    name_len = len(name)

    guessed_name, guessed_lemma = guess_lemma(name)
    if guessed_name and guessed_lemma:
        name, lemma = guessed_name, guessed_lemma

    cases, plural_cases = {}, ()
    if name_len > 2:
        cases, plural_cases = CASEMAP.get(name[-2:], ({}, ()))
        if cases:
            lemma = name[:-2]

    if not cases and name_len > 3:
        cases, plural_cases = CASEMAP.get(name[-3:], ({}, ()))
        if cases:
            lemma = name[:-3]

    # В случае 13.1.12 лемма состоит из фамилии, за исключением
    # двух последних букв
    if cases is CASES_IA or cases is CASES_OK:
        lemma = name = name[:-2]

    if not cases:
        return []

    expected_form = GramForm(gram_form)

    forms = []
    for i, case in zip(xrange(6), (u'им', u'рд', u'дт', u'вн', u'тв', u'пр',)):
        for gender_tag in (u'мр', u'жр',):
            form = GramForm(u'%s,%s,фам,ед' % (case, gender_tag,))

            if gram_form and not form.match(expected_form):
                continue

            forms.append({
                'word': u'%s%s' % (name, cases[gender_tag][i]),
                'class': u'С',
                'info': form.get_form_string(),
                'lemma': name,
                'method': u'decline_lastname (%s)' % lastname,
                'norm': u'%s%s' % (name, cases[gender_tag][0]),
            })

        plural_form = GramForm(u'%s,мр-жр,фам,мн' % (case,))

        if gram_form and not plural_form.match(expected_form):
            continue

        forms.append({
            'word': u'%s%s' % (name, plural_cases[i]),
            'class': u'С',
            'info': plural_form.get_form_string(),
            'lemma': name,
            'method': u'decline_lastname (%s)' % lastname,
            'norm': u'%s%s' % (name, plural_cases[0]),
        })

    # Просклонять рекурсивно для случая с множественным числом фамилии.
    # Козловых -> фам,им; Козловых (мн) -> Козлов -> фам,им
    if lemma != name and LASTNAME_PATTERN.match(lemma):
        refinement = decline(lemma)
        if refinement:
            return forms + refinement

    return forms
Beispiel #21
0
 def test_match_inverted(self):
     form = GramForm(u"мр,ед,имя")
     self.assertFalse(form.match(GramForm(u"мр,!имя")))
     self.assertTrue(form.match(GramForm(u"ед,!тв")))