Commits

Mikhail Korobov committed 3c903e5

smarter class for parse result

Comments (0)

Files changed (2)

pymorphy2/analyzer.py

 import collections
 from pymorphy2 import opencorpora_dict
 
-Parse = collections.namedtuple('Parse', 'word, tag, normal_form, para_id, idx, estimate')
+_Parse = collections.namedtuple('Parse', 'word, tag, normal_form, para_id, idx, estimate')
+
+class Parse(_Parse):
+    """
+    Parse result wrapper.
+    """
+    _morph = None
+
+    def inflect(self, required_grammemes):
+        res = self._morph._inflect(self, required_grammemes)
+        return None if not res else res[0]
+
+    @property
+    def lexeme(self):
+        """ A lexeme this form belongs to. """
+        return self._morph._decline([self])
+
+    @property
+    def is_known(self):
+        """ True if this form is a known dictionary form. """
+        # return self.estimate == 1?
+        return self._morph.word_is_known(self.word, strict_ee=True)
+
+    @property
+    def normalized(self):
+        """ A :class:`Parse` instance for :attr:`self.normal_form`. """
+        if self.idx == 0:
+            return self
+
+        tag = self._morph._build_tag_info(self.para_id, 0)
+        return self.__class__(self.normal_form, tag, self.normal_form,
+                              self.para_id, 0, self.estimate)
+
 
 class MorphAnalyzer(object):
     """
         path = self.choose_dictionary_path(path)
         self._dictionary = opencorpora_dict.load(path)
         self._ee = self._dictionary.words.compile_replaces({'е': 'ё'})
-        self._result_type = result_type
 
+        if result_type is not None:
+            # create a subclass with the same name,
+            # but with _morph attribute bound to self
+            res_type = type(
+                result_type.__name__,
+                (result_type,),
+                {'_morph': self}
+            )
+            self._result_type = res_type
+        else:
+            self._result_type = None
 
     @classmethod
     def choose_dictionary_path(cls, path=None):

tests/test_result_wrapper.py

+# -*- coding: utf-8 -*-
+from __future__ import absolute_import, unicode_literals
+
+from .utils import morph
+
+def test_indexing():
+    assert len(morph.parse('стреляли')) == 1
+    p = morph.parse('стреляли')[0]
+
+    assert p[0] == 'стреляли' # word
+    assert p[1].POS == 'VERB' # tag
+    assert p[2] == 'стрелять'
+
+    assert p[0] == p.word
+    assert p[1] == p.tag
+    assert p[2] == p.normal_form
+
+def test_inflect_valid():
+    p = morph.parse('стреляли')[0]
+    assert p.inflect(set(['femn'])).word == 'стреляла'
+
+def test_inflect_invalid():
+    p = morph.parse('стреляли')[0]
+    assert p.inflect(set(['NOUN'])) == None
+
+
+def test_is_known():
+    assert morph.parse('стреляли')[0].is_known
+    assert not morph.parse('сптриояли')[0].is_known
+
+def test_normalized():
+    assert morph.parse('стреляли')[0].normalized.word == 'стрелять'
+
+def test_lexeme():
+    parses = morph.parse('кот')
+    assert len(parses) == 1
+
+    forms = [p.word for p in parses[0].lexeme]
+    assert forms == ['кот', 'кота', 'коту', 'кота', 'котом', 'коте',
+                     'коты', 'котов', 'котам', 'котов', 'котами', 'котах']
+
+
+