Commits

sirex  committed 527d3fb Draft

Initial code.

  • Participants
  • Parent commits dd15efb

Comments (0)

Files changed (3)

File src/lema/__init__.py

+# coding: utf-8
+
+#   lema - a tool to work with database of lithuanian words.
+#   Copyright (C) 2012 Mantas Zimnickas <sirexas@gmail.com>
+#
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import codecs
+import os.path
+import re
+import sys
+
+from collections import defaultdict
+from operator import itemgetter
+
+import unidecode
+
+from lema.afiksai import PRIESDELIAI, PRIESAGOS, GALUNES
+
+words_re = re.compile(r'\w+', re.UNICODE)
+clean_re = re.compile(r'[0-9_]+')
+
+META_SIZE = 6
+
+
+# Kalbos dalys
+DAIKTAVARDIS  = 'd'
+BUDVARDIS     = 'b'
+SKAITVARDIS   = 's'
+IVARDIS       = 'i'
+VEIKSMAZODIS  = 'v'
+PRIEVEIKSMIS  = 'p'
+PRIELINKSNIS  = 'l'
+JUNGTUKAS     = 'j'
+DALELYTE      = 'y'
+JAUSTUKAS     = 'u'
+ISTIKTUKAS    = 't'
+AKRONIMAS     = 'k'
+SUTRUMPINIMAS = 'm'
+KALBOS_DALYS = (DAIKTAVARDIS, BUDVARDIS, SKAITVARDIS, IVARDIS, VEIKSMAZODIS,
+                PRIEVEIKSMIS, PRIELINKSNIS, JUNGTUKAS, DALELYTE, JAUSTUKAS,
+                ISTIKTUKAS, AKRONIMAS, SUTRUMPINIMAS)
+
+# Veiksmažodžių formos
+BENDRATIS    = 'B'
+DALYVIS      = 'D'
+PADALYVIS    = 'A'
+PUSDALYVIS   = 'U'
+BUDINYS      = 'B'
+VEIKSM_FORMOS = (BENDRATIS, DALYVIS, PADALYVIS, PUSDALYVIS, BUDINYS)
+KALBOS_DALYS += VEIKSM_FORMOS  # veiksmažodžių formos naudojamos kaip kalbos
+                               # dalys
+
+# Nuosaka
+TIESIOGINE   = 't'
+LIEPIAMOJI   = 'l'
+TARIAMOJI    = 'r'
+NUOSAKA = (TIESIOGINE, TARIAMOJI, LIEPIAMOJI)
+
+# Dalyvių rūšys
+VEIKIAMOJI   = 'v'
+NEVEIKIAMOJI = '-'
+REIKIAMYBE   = 'r'  # skaitytinas, skaitytina; rašytinas, rašytina
+DALYVIO_RUSIS = (VEIKIAMOJI, NEVEIKIAMOJI, REIKIAMYBE)
+
+# Teigiamas, neigiamas
+TEIGIAMAS = 't'
+NEIGIAMAS = 'n'
+TEIGIAMUMAS = (TEIGIAMAS, NEIGIAMAS)
+
+# Giminė
+VYRISKA       = 'v'
+TIK_VYRISKA   = 'V'  # Žodis turi tik vyrišką giminę
+MOTERISKA     = 'm'
+TIK_MOTERISKA = 'M'  # Žodis turi tik moterišką giminę
+BEVARDE       = 'e'
+BENDROJI      = 'b'
+
+GIMINE = (VYRISKA, TIK_VYRISKA, MOTERISKA, TIK_MOTERISKA, BEVARDE, BENDROJI)
+
+# Skaičius
+VIENASKAITA     = 'v'  # žodis
+TIK_VIENASKAITA = 'V'  # ?
+DAUGISKAITA     = 'd'  # žodžiai
+TIK_DAUGISKAITA = 'D'  # finansai
+SKAICIUS = (VIENASKAITA, TIK_VIENASKAITA, DAUGISKAITA, TIK_DAUGISKAITA)
+
+# Linksnis
+VARDININKAS   = 'v'  # kas
+KILMININKAS   = 'k'  # ko
+NAUDININKAS   = 'n'  # kam
+GALININKAS    = 'g'  # ką
+INAGININKAS   = 'i'  # kuo
+VIETININKAS   = 't'  # kur
+SAUKSMININKAS = 's'  # !
+LINKSNIUOTE = (VARDININKAS, KILMININKAS, GALININKAS, INAGININKAS, VIETININKAS,
+               SAUKSMININKAS)
+
+# Laipsniai
+NELAIPSNIUOJAMAS  = '-'
+NELYGINAMASIS     = 'n'
+AUKSTELESNYSIS    = 'l'
+AUKSTESNYSIS      = 't'
+AUKSCIAUSIAS      = 'c'
+VISU_AUKSCIAUSIAS = 'v'
+LAIPSNIUOTE = (NELYGINAMASIS, AUKSTELESNYSIS, AUKSTESNYSIS, AUKSCIAUSIAS,
+               VISU_AUKSCIAUSIAS)
+
+# Laikai
+ESAMASIS         = 'e'
+BUTASIS_KARTINIS = 'k'
+BUTASIS_DAZNINIS = 'd'
+BUSIMASIS        = 'b'
+LAIKAS = (ESAMASIS, BUTASIS_KARTINIS, BUTASIS_DAZNINIS, BUSIMASIS)
+
+# Asmenuotė
+ASMUO1 = '1'  # skaitau
+ASMUO2 = '2'  # skaitai
+ASMUO3 = '3'  # skaito
+ASMENUOTE = (ASMUO1, ASMUO2, ASMUO3)
+
+# Apibrėžtumas
+IVARDZIUOTINIS   = 'i'  # naujasis, tyrasis
+
+# Sangrąžiškumas
+NESANGRAZINIS = 'n'
+SANGRAZINIS   = 's'
+
+# Daiktavardžių skyriai
+TIKRINIS     = 't'  # priskiriami pavadinimai, vardai (Antanas, Vilnius), jie rašomi didžiąja raide
+KONKRETUSIS  = 'k'  # reiškiamus daiktus matome, galime paliesti (daiktai, augalai, gyvūnai, žmonės, vietovės)
+ABSTRAKTUSIS = 'a'  # gamtos, visuomenės reiškinių, ypatybių, veiksmų pavadinimas
+KUOPINIS     = 'u'  # nusako daiktų grupę (beržynas, jaunimas, krūmynas)
+BENDRINIS    = 'b'  # visi kiti bendriniai pavadinimai (stalas, kėdė)
+DAIKT_SKYRIUS = (ABSTRAKTUSIS, KONKRETUSIS, TIKRINIS, BENDRINIS, KUOPINIS)
+
+# Skaitvardžių skyriai
+PAGRINDIS    = 'p'  # vienas, šimtas...
+DAUGINIS     = 'd'  # treji, penkerios...
+KUOPINIS     = 'u'  # penketas, šešetas...
+TRUPMENINIS  = 't'  # pusantro, pustrečio...
+KELINTINIS   = 'l'  # penktas, dešimtas...
+KIEKINIAI = (PAGRINDIS, DAUGINIS, KUOPINIS, TRUPMENINIS)
+SKAITV_SKYRIUS = KIEKINIAI + (KELINTINIS,)
+
+# Įvardžių skyriai
+ASMENINIS    = 'a'
+SAVYBINIS    = 's'
+SANGRAZINIS  = 'g'
+PARODOMASIS  = 'p'
+PAZIMIMASIS  = 'z'
+KLAUSIAMASIS = 'k'
+SANTIKINIS   = 't'
+NEZIMIMASIS  = 'n'
+IVARD_SKYRIUS = (ASMENINIS, SAVYBINIS, SANGRAZINIS, PARODOMASIS, PAZIMIMASIS,
+                 KLAUSIAMASIS, SANTIKINIS, NEZIMIMASIS)
+
+# Prieveiksmių skyriai
+BUDO        = 'b'
+KIEKYBES    = 'k'
+VIETOS      = 'v'
+LAIKO       = 'l'
+PRIEZASTIES = 'p'
+PRIEV_SKYRIUS = (BUDO, KIEKYBES, VIETOS, LAIKO, PRIEZASTIES)
+
+# Jungtukų skyriai
+SUJUNGIAMIEJI  = 's'
+PRIJUNGIAMIEJI = 'p'
+JUNGTUKU_SKYRIUS = (SUJUNGIAMIEJI, PRIJUNGIAMIEJI)
+
+# Ištiktukų skyriai
+IMITUOJANTYS_GARSUS = 'g'
+VEIKSMAZODINIAI     = 'v'
+ISTIKTUKU_SKYRIUS = (IMITUOJANTYS_GARSUS, VEIKSMAZODINIAI)
+
+# Morfologija
+MORFOLOGIJA = {
+    DAIKTAVARDIS: (GIMINE, SKAICIUS, LINKSNIUOTE, DAIKT_SKYRIUS),
+    BUDVARDIS:    (GIMINE, SKAICIUS, LINKSNIUOTE, LAIPSNIUOTE, IVARDZIUOTINIS),
+    SKAITVARDIS:  (GIMINE, SKAICIUS, LINKSNIUOTE, SKAITV_SKYRIUS),
+    IVARDIS:      (GIMINE, SKAICIUS, LINKSNIUOTE, IVARD_SKYRIUS),
+
+    VEIKSMAZODIS: (ASMENUOTE, SKAICIUS, LAIKAS, NUOSAKA, SANGRAZINIS,
+                   TEIGIAMUMAS),
+    BENDRATIS:    (SANGRAZINIS, TEIGIAMUMAS),
+    DALYVIS:      (GIMINE, SKAICIUS, LINKSNIUOTE, LAIKAS, DALYVIO_RUSIS,
+                   SANGRAZINIS, IVARDZIUOTINIS, TEIGIAMUMAS),
+    PUSDALYVIS:   (GIMINE, SKAICIUS, SANGRAZINIS, TEIGIAMUMAS),
+    PADALYVIS:    (LAIKAS, SANGRAZINIS, TEIGIAMUMAS),
+    BUDINYS:      (LAIPSNIUOTE, PRIEV_SKYRIUS, TEIGIAMUMAS),
+
+    PRIEVEIKSMIS: (LAIPSNIUOTE, PRIEV_SKYRIUS, TEIGIAMUMAS),
+
+    JUNGTUKAS:    (JUNGTUKU_SKYRIUS,),
+    ISTIKTUKAS:   (ISTIKTUKU_SKYRIUS,),
+
+    PRIELINKSNIS: (),
+    DALELYTE:     (),
+    JAUSTUKAS:    (),
+}
+
+# Leksika
+SINONIMAS = 's'
+ANTONIMAS = 'a'
+TIPAS     = 't'  # Žodžio tipas, pvz.: vilnius t=miestas
+
+# Visos leksikos žymės rašomos tik prie lemos tipo žodžio, prie kitų žodžio
+# formų leksikos žymės nerašomos.
+LEKSIKA = (SINONIMAS, ANTONIMAS, TIPAS)
+
+# Lema
+LEMA      = 'l'  # Pagrindinė žodžio forma
+
+# Pagrindinės žodžio formos
+# Pagal šias taisykles nustatoma ar žodis yra lema.
+# None - bet kokia reikšmė
+PAGRINDINE_FORMA = {
+    DAIKTAVARDIS: (None, VIENASKAITA, VARDININKAS),
+    BUDVARDIS: (None, VIENASKAITA, VARDININKAS),
+    SKAITVARDIS: (None, VIENASKAITA, VARDININKAS),
+    IVARDIS: (None, VIENASKAITA, VARDININKAS),
+    BENDRATIS: (None, '-',),
+    DALYVIS: (None, VIENASKAITA, VARDININKAS, ESAMASIS, None, None, None, '-'),
+    PUSDALYVIS: (None, VIENASKAITA, None, '-'),
+    JUNGTUKAS: (),
+    ISTIKTUKAS: (),
+    PRIELINKSNIS: (),
+    DALELYTE: (),
+    JAUSTUKAS: (),
+}
+
+# Visos leksikos žymės
+LEKSIKOS_ZYMES = (LEMA,) + LEKSIKA
+
+
+def get_prefix(word):
+    u"""
+
+    >>> get_prefix(u'')
+    '__'
+
+    >>> get_prefix(u'ą')
+    'a_'
+
+    >>> get_prefix(u'ąb')
+    'ab'
+
+    >>> get_prefix(u'ąbc')
+    'ab'
+
+    """
+    slug = unidecode.unidecode(word).lower()
+    slug = slug.ljust(2, '_')
+    return slug[:2]
+
+
+def normalize(word):
+    return clean_re.sub('', word).lower()
+
+
+def get_galunes():
+    galunes = defaultdict(list)
+    for galune, forma in GALUNES:
+        galunes[galune].append(forma)
+    return list(sorted(galunes.items(), key=lambda a: len(a[0]), reverse=True))
+
+
+def detect_galune(word):
+    for galune, choices in get_galunes():
+        if word.endswith(galune):
+            ret = []
+            for data, lema, extra in choices:
+                lema = word[:-len(galune)] + lema
+                extra['l'] = lema
+                ret.append((data, extra))
+            return ret
+    return []
+
+
+def get_priesdeliai():
+    priesdeliai = defaultdict(list)
+    for priesdelis, forma in PRIESDELIAI:
+        priesdeliai[priesdelis].append(forma)
+    return list(sorted(priesdeliai.items(), key=lambda a: len(a[0]), reverse=True))
+
+
+def detect_priesdelis(word):
+    pass
+
+
+def words_from_stream(f, chunk_size=1024):
+    """Read words from stream.
+
+    >>> import StringIO
+    >>> stream = StringIO.StringIO('abc abc abc')
+    >>> list(words_from_stream(stream, 5))
+    ['abc', 'abc', 'abc']
+
+    >>> stream = StringIO.StringIO('abc abc ab')
+    >>> list(words_from_stream(stream, 5))
+    ['abc', 'abc', 'ab']
+
+    >>> stream = StringIO.StringIO('abc abc a')
+    >>> list(words_from_stream(stream, 5))
+    ['abc', 'abc', 'a']
+
+    >>> stream = StringIO.StringIO('a b')
+    >>> list(words_from_stream(stream, 5))
+    ['a', 'b']
+
+    """
+    chunk = f.read(chunk_size)
+    while chunk:
+        words = words_re.findall(chunk)
+        if len(chunk) >= chunk_size:
+            chunk = words.pop()
+        else:
+            chunk = ''
+        for word in words:
+            word = normalize(word)
+            if word:
+                yield word
+        chunk += f.read(chunk_size)
+
+
+class Lema(object):
+    def __init__(self, dbpath='.'):
+        self.dbpath = dbpath
+        self.words = {}
+
+    def read(self, prefix):
+        path = os.path.join(self.dbpath, prefix)
+        if os.path.exists(path):
+            db = codecs.open(path, 'rb', 'utf-8')
+            self.words[prefix] = self.read_file(db)
+            db.close()
+        else:
+            self.words[prefix] = {}
+        return self.words[prefix]
+
+    def read_file(self, f):
+        u"""
+
+        >>> import pprint
+        >>> import StringIO
+        >>> db = Lema()
+        >>> f = StringIO.StringIO(u'bdv--- žodžiai l=žodis')
+        >>> r = db.read_file(f)
+        >>> print(unicode(pprint.pformat(r), 'unicode_escape'))
+        {u'žodžiai': (u'bdv---', {u'l': u'žodis'})}
+
+        """
+        d = {}
+        for line in f:
+            meta = line[:META_SIZE]
+            word = line[META_SIZE+1:].strip()
+            extra = {}
+            if ' ' in word:
+                word, extra_line = word.split(' ', 1)
+                for item in extra_line.split(' '):
+                    k, v = item.split('=', 1)
+                    extra[k] = v
+            if word:
+                d[word] = (meta, extra)
+        return d
+
+    def write(self):
+        for prefix, words in self.words.items():
+            path = os.path.join(self.dbpath, prefix)
+            db = codecs.open(path, 'wb', 'utf-8')
+            self.write_file(db, words)
+            db.close()
+
+    def write_file(solf, f, words):
+        u"""
+
+        >>> import StringIO
+        >>> db = Lema()
+        >>> f = StringIO.StringIO()
+        >>> words = {u'žodžiai': (u'bdv---', {'l': u'žodis'})}
+        >>> db.write_file(f, words)
+        >>> print(f.getvalue())
+        bdv--- žodžiai l=žodis
+        <BLANKLINE>
+
+        """
+        for word, data in sorted(words.items(), key=itemgetter(0)):
+            data, extra = data
+            if extra:
+                extra_line = ' '.join(['%s=%s' % (k, v)
+                                       for k, v in extra.items()])
+                f.write(u'%s %s %s\n' % (data, word, extra_line))
+            else:
+                f.write(u'%s %s\n' % (data, word))
+
+    def get_words_by_prefix(self, prefix):
+        try:
+            return self.words[prefix]
+        except KeyError:
+            return self.read(prefix)
+
+    def update(self, word):
+        wdata = self.get(word)
+        if not wdata:
+            wdata = self.add(word)
+        return wdata
+
+    def import_stream(self, f):
+        for word in words_from_stream(f):
+            yield (word,) + self.update(word)
+
+    def import_text(self, text):
+        for word in words_re.finditer(text):
+            word = normalize(word.group())
+            if word:
+                yield (word,) + self.update(word)
+
+    def add(self, word, data='------', extra=None):
+        u"""
+
+        >>> import pprint
+        >>> db = Lema()
+        >>> db.add(u'žodžiai')
+        ('------', {})
+        >>> r = db.words
+        >>> print(unicode(pprint.pformat(r), 'unicode_escape'))
+        {'zo': {u'žodžiai': ('------', {})}}
+
+        """
+        prefix = get_prefix(word)
+        word = word.lower()
+        words = self.get_words_by_prefix(prefix)
+        wdata = (data, extra or {})
+        words[word] = wdata
+        return wdata
+
+    def get(self, word):
+        u"""Read word from database.
+
+        >>> import pprint
+        >>> db = Lema()
+        >>> db.words['zo'] = {u'žodžiai': (u'bdv---', {'l': u'žodis'})}
+        >>> r = db.get(u'žodžiai')
+        >>> print(unicode(pprint.pformat(r), 'unicode_escape'))
+        (u'bdv---', {'l': u'žodis'})
+
+        """
+        prefix = get_prefix(word)
+        word = word.lower()
+        words = self.get_words_by_prefix(prefix)
+        return words.get(word)
+
+    def lema(self, word):
+        u"""
+
+        >>> import pprint
+        >>> db = Lema()
+        >>> db.words['zo'] = {u'žodžiai': (u'bdv---', {'l': u'žodis'})}
+        >>> r = db.lema(u'žodžiai')
+        >>> print(r)
+        žodis
+
+        """
+        meta, extra = self.get(word)
+        if 'l' in extra:
+            return extra['l']
+        else:
+            return word
+
+
+def read_html(html):
+    from BeautifulSoup import BeautifulSoup
+    soup = BeautifulSoup(html)
+    return ' '.join([e for e in soup.recursiveChildGenerator()
+                      if isinstance(e,unicode)])
+
+def get_ignore_words():
+    ignorewords = set()
+    if not os.path.exists('ignorewords'):
+        return ignorewords
+    f = codecs.open('ignorewords', 'rb', 'utf-8')
+    for line in f:
+        ignorewords.add(line.strip())
+    f.close()
+    return ignorewords
+
+
+def save_ignore_words(ignorewords):
+    f = codecs.open('ignorewords', 'wb', 'utf-8')
+    for word in sorted(ignorewords):
+        f.write(word + '\n')
+    f.close()
+
+
+def print_stats(words):
+    ignorewords = get_ignore_words()
+    lemas = defaultdict(int)
+    for word, meta, extra in words:
+        if word in ignorewords:
+            print("Ignoring '%s' from ignorewords file." % word)
+            continue
+        elif 's' in extra:
+            lema = extra['s']
+        elif 'l' in extra:
+            lema = extra['l']
+        else:
+            lema = word
+
+            if lema not in lemas:
+                guesses = detect_galune(lema)
+                if guesses:
+                    print('Unknown word: %s' % lema)
+                    for data, extra in guesses:
+                        print('     . %s %s' % (data, extra.get('l')))
+                    user_input = raw_input('Enter correct value: ')
+                    if 'q' == user_input:
+                        save_ignore_words(ignorewords)
+                        return
+                    elif 'i' == user_input:
+                        ignorewords.add(word)
+                        print("Added '%s' word to ignorewords file." % word)
+                else:
+                    print("Ignoring '%s' autodetected." % lema)
+
+
+        lemas[lema] += 1
+    for lema, times in sorted(lemas.items(), key=itemgetter(1)):
+        print('%6d %s' % (times, lema))
+    save_ignore_words(ignorewords)
+
+
+def main():
+    import argparse
+
+    parser = argparse.ArgumentParser(description='Process some integers.')
+    parser.add_argument('--lema', dest='lema', action='store',
+                        help='get lema')
+    parser.add_argument('--html', dest='html', action='store_true',
+                        help='input file is html file')
+
+    parser.add_argument('-i', dest='input_file', action='store',
+                        help='read words from input file')
+
+    args = parser.parse_args()
+
+    if args.input_file:
+        stdin = codecs.open(args.input_file, 'rb', 'utf-8')
+    else:
+        stdin = sys.stdin
+
+    db = Lema('db')
+
+    if args.lema:
+        print(db.lema(args.lema))
+
+    elif args.html:
+        html = read_html(stdin.read())
+        print_stats(db.import_text(html))
+        db.write()
+
+    else:
+        stream = codecs.getreader("utf-8")(stdin)
+        print_stats(db.import_stream(stream))
+        db.write()
+
+    if args.input_file:
+        stdin.close()
+
+
+if __name__ == '__main__':
+    main()

File src/lema/afiksai.py

+# coding: utf-8
+
+
+PRIESDELIAI = (
+    # Būdvardis
+    (u'ne',       ('b?n',                  {}) ),
+    # Veiksmažodis
+    (u'ne',       ('v?????n',              {}) ),
+    # Dalyvis
+    (u'ne',       ('D???????n',            {}) ),
+    # Pusdalyvis
+    (u'ne',       ('U???n',                {}) ),
+    # Padalyvis
+    (u'ne',       ('A??n',                 {}) ),
+    # Būdinys
+    (u'ne',       ('B??n',                 {}) ),
+    # Prieveiksmis
+    (u'ne',       ('p??n',                 {}) ),
+
+    (u'pri',      ('?',                    {}) ),
+)
+
+
+PRIESAGOS = (
+    (u'tin',      ('D???-r---',            {}) ),
+    (u'ien',      ('dm????',               {'t': 'pavardė'}) ),
+    (u'ait',      ('dm????',               {'t': 'pavardė'}) ),
+)
+
+
+GALUNES = (
+
+    # Daiktavardžiai
+    # (vyr. g., vns.)
+    (u'as',       ('dvvv?',     u'as',     {}) ),
+    (u'o',        ('dvvk?',     u'as',     {}) ),
+    (u'ui',       ('dvvn?',     u'as',     {}) ),
+    (u'ą',        ('dvvg?',     u'as',     {}) ),
+    (u'u',        ('dvvi?',     u'as',     {}) ),
+    (u'e',        ('dvvt?',     u'as',     {}) ),
+    (u'ai',       ('dvvs?',     u'as',     {}) ),
+    # (vyr. g., dgs.)
+    (u'ai',       ('dvdv?',     u'as',     {}) ),
+    (u'ų',        ('dvdk?',     u'as',     {}) ),
+    (u'ams',      ('dvdn?',     u'as',     {}) ),
+    (u'us',       ('dvdg?',     u'as',     {}) ),
+    (u'ais',      ('dvdi?',     u'as',     {}) ),
+    (u'uose',     ('dvdt?',     u'as',     {}) ),
+    (u'ai',       ('dvds?',     u'as',     {}) ),
+    # (mot. g., vns.)
+    (u'a',        ('dmvv?',     u'a',      {}) ),
+    (u'os',       ('dmvk?',     u'a',      {}) ),
+    (u'ai',       ('dmvn?',     u'a',      {}) ),
+    (u'ą',        ('dmvg?',     u'a',      {}) ),
+    (u'a',        ('dmvi?',     u'a',      {}) ),
+    (u'oje',      ('dmvt?',     u'a',      {}) ),
+    (u'a',        ('dmvs?',     u'a',      {}) ),
+    # (mot. g., dgs.)
+    (u'os',       ('dmdv?',     u'a',      {}) ),
+    (u'ų',        ('dmdk?',     u'a',      {}) ),
+    (u'oms',      ('dmdn?',     u'a',      {}) ),
+    (u'as',       ('dmdg?',     u'a',      {}) ),
+    (u'omis',     ('dmdi?',     u'a',      {}) ),
+    (u'ose',      ('dmdt?',     u'a',      {}) ),
+    (u'os',       ('dmds?',     u'a',      {}) ),
+
+    # (vyr. g., vns.)
+    (u'is',       ('dvvv?',     u'is',     {}) ),
+    (u'io',       ('dvvk?',     u'is',     {}) ),
+    (u'iui',      ('dvvn?',     u'is',     {}) ),
+    (u'į',        ('dvvg?',     u'is',     {}) ),
+    (u'iu',       ('dvvi?',     u'is',     {}) ),
+    (u'iyje',     ('dvvt?',     u'is',     {}) ),
+    (u'i',        ('dvvs?',     u'is',     {}) ),
+    # (vyr. g., dgs.)
+    (u'iai',      ('dvdv?',     u'is',     {}) ),
+    (u'ių',       ('dvdk?',     u'is',     {}) ),
+    (u'iams',     ('dvdn?',     u'is',     {}) ),
+    (u'ius',      ('dvdg?',     u'is',     {}) ),
+    (u'iais',     ('dvdi?',     u'is',     {}) ),
+    (u'iuose',    ('dvdt?',     u'is',     {}) ),
+    (u'iai',      ('dvds?',     u'is',     {}) ),
+    # (mot. g., vns.)
+    (u'ė',        ('dmvv?',     u'ė',      {}) ),
+    (u'ės',       ('dmvk?',     u'ė',      {}) ),
+    (u'ei',       ('dmvn?',     u'ė',      {}) ),
+    (u'ę',        ('dmvg?',     u'ė',      {}) ),
+    (u'e',        ('dmvi?',     u'ė',      {}) ),
+    (u'ėje',      ('dmvt?',     u'ė',      {}) ),
+    (u'e',        ('dmvs?',     u'ė',      {}) ),
+    # (mot. g., dgs.)
+    (u'ės',       ('dmdv?',     u'ė',      {}) ),
+    (u'ių',       ('dmdk?',     u'ė',      {}) ),
+    (u'ėms',      ('dmdn?',     u'ė',      {}) ),
+    (u'es',       ('dmdg?',     u'ė',      {}) ),
+    (u'ėmis',     ('dmdi?',     u'ė',      {}) ),
+    (u'ėse',      ('dmdt?',     u'ė',      {}) ),
+    (u'ės',       ('dmds?',     u'ė',      {}) ),
+
+
+    # Būdvardžiai
+    # (vyr. g., vns.)
+    (u'asis',     ('bvvv?',     u'asis',   {}) ),
+    (u'ojo',      ('bvvk?',     u'asis',   {}) ),
+    (u'ajam',     ('bvvn?',     u'asis',   {}) ),
+    (u'ajį',      ('bvvg?',     u'asis',   {}) ),
+    (u'uoju',     ('bvvi?',     u'asis',   {}) ),
+    (u'ajame',    ('bvvt?',     u'asis',   {}) ),
+    (u'asis',     ('bvvs?',     u'asis',   {}) ),
+    # (vyr. g., dgs.)
+    (u'ieji',     ('bvdv?',     u'asis',   {}) ),
+    (u'ųjų',      ('bvdk?',     u'asis',   {}) ),
+    (u'iesiems',  ('bvdn?',     u'asis',   {}) ),
+    (u'uosius',   ('bvdg?',     u'asis',   {}) ),
+    (u'aisiais',  ('bvdi?',     u'asis',   {}) ),
+    (u'uosiuose', ('bvdt?',     u'asis',   {}) ),
+    (u'ieji',     ('bvds?',     u'asis',   {}) ),
+    # (mot. g., vns.)
+    (u'oji',      ('bmvv?',     u'oji',    {}) ),
+    (u'osios',    ('bmvk?',     u'oji',    {}) ),
+    (u'ajai',     ('bmvn?',     u'oji',    {}) ),
+    (u'ają',      ('bmvg?',     u'oji',    {}) ),
+    (u'ąja',      ('bmvi?',     u'oji',    {}) ),
+    (u'ojoje',    ('bmvt?',     u'oji',    {}) ),
+    (u'oji',      ('bmvs?',     u'oji',    {}) ),
+    # (mot. g., dgs.)
+    (u'osios',    ('bmdv?',     u'oji',    {}) ),
+    (u'ųjų',      ('bmdk?',     u'oji',    {}) ),
+    (u'osioms',   ('bmdn?',     u'oji',    {}) ),
+    (u'ąsias',    ('bmdg?',     u'oji',    {}) ),
+    (u'osiomis',  ('bmdi?',     u'oji',    {}) ),
+    (u'osiose',   ('bmdt?',     u'oji',    {}) ),
+    (u'osios',    ('bmds?',     u'oji',    {}) ),
+
+
+    # Veiksmažodžio bendratis
+    (u'ti',       ('B--',       u'ti',     {}) ),
+
+
+    # Veiksmažodžiai
+    (u'iesti',    ('B--',       u'iesti',  {}) ),
+    # (vns., es. l.)
+    (u'iečiu',    ('v1vet--',   u'iesti',  {}) ),
+    (u'ieti',     ('v2vet--',   u'iesti',  {}) ),
+    (u'iečia',    ('v3vet--',   u'iesti',  {}) ),
+    # (dgs., es. l.)
+    (u'iečiame',  ('v1det--',   u'iesti',  {}) ),
+    (u'iečiate',  ('v2det--',   u'iesti',  {}) ),
+    (u'iečia',    ('v3det--',   u'iesti',  {}) ),
+    # (vns., būt. k. l.)
+    (u'iečiau',   ('v1vkt--',   u'iesti',  {}) ),
+    (u'ietei',    ('v2vkt--',   u'iesti',  {}) ),
+    (u'ietė',     ('v3vkt--',   u'iesti',  {}) ),
+    # (dgs., būt. k. l.)
+    (u'ietėme',   ('v1dkt--',   u'iesti',  {}) ),
+    (u'ietė',     ('v2dkt--',   u'iesti',  {}) ),
+    (u'ietė',     ('v3dkt--',   u'iesti',  {}) ),
+    # (vns., būt. d. l.)
+    (u'davau',    ('v1vdt--',   u'iesti',  {}) ),
+    (u'davai',    ('v2vdt--',   u'iesti',  {}) ),
+    (u'davo',     ('v3vdt--',   u'iesti',  {}) ),
+    # (dgs., būt. d. l.)
+    (u'davome',   ('v1ddt--',   u'iesti',  {}) ),
+    (u'davote',   ('v2ddt--',   u'iesti',  {}) ),
+    (u'davo',     ('v3ddt--',   u'iesti',  {}) ),
+    # (vns., būs. l.)
+    (u'iesiu',    ('v1vbt--',   u'iesti',  {}) ),
+    (u'iesi',     ('v2vbt--',   u'iesti',  {}) ),
+    (u'ies',      ('v3vbt--',   u'iesti',  {}) ),
+    # (dgs., būs. l.)
+    (u'iesime',   ('v1dbt--',   u'iesti',  {}) ),
+    (u'iesite',   ('v2dbt--',   u'iesti',  {}) ),
+    (u'ies',      ('v3dbt--',   u'iesti',  {}) ),
+
+
+    # Reikiamybės dalyviai
+    # (vyr. g., vns.)
+    (u'tinas',    ('Dvvv-r---', u'tinas',  {}) ),
+    (u'tino',     ('Dvvk-r---', u'tinas',  {}) ),
+    (u'tinam',    ('Dvvn-r---', u'tinas',  {}) ),
+    (u'tiną',     ('Dvvg-r---', u'tinas',  {}) ),
+    (u'tinu',     ('Dvvi-r---', u'tinas',  {}) ),
+    (u'tiname',   ('Dvvt-r---', u'tinas',  {}) ),
+    # (vyr. g., dgs.)
+    (u'tini',     ('Dvdv-r---', u'tinas',  {}) ),
+    (u'tinų',     ('Dvdk-r---', u'tinas',  {}) ),
+    (u'tiniems',  ('Dvdn-r---', u'tinas',  {}) ),
+    (u'tinus',    ('Dvdg-r---', u'tinas',  {}) ),
+    (u'tinais',   ('Dvdi-r---', u'tinas',  {}) ),
+    (u'tinuose',  ('Dvdt-r---', u'tinas',  {}) ),
+    # (mot. g., vns.)
+    (u'tina',     ('Dmvv-r---', u'tina',   {}) ),
+    (u'tinos',    ('Dmvk-r---', u'tina',   {}) ),
+    (u'tinai',    ('Dmvn-r---', u'tina',   {}) ),
+    (u'tiną',     ('Dmvg-r---', u'tina',   {}) ),
+    (u'tina',     ('Dmvi-r---', u'tina',   {}) ),
+    (u'tinoje',   ('Dmvt-r---', u'tina',   {}) ),
+    # (mot. g., dgs.)
+    (u'tinos',    ('Dmdv-r---', u'tina',   {}) ),
+    (u'tinų',     ('Dmdk-r---', u'tina',   {}) ),
+    (u'tinoms',   ('Dmdn-r---', u'tina',   {}) ),
+    (u'tinas',    ('Dmdg-r---', u'tina',   {}) ),
+    (u'tinomis',  ('Dmdi-r---', u'tina',   {}) ),
+    (u'tinose',   ('Dmdt-r---', u'tina',   {}) ),
+
+    # Prieveiksmiai
+    # PRIEVEIKSMIS: (LAIPSNIUOTE, PRIEV_SKYRIUS, NEIGIAMAS),
+    (u'iai',      ('pn??',      u'us',     {})),
+    (u'ai',       ('pn??',      u'as',     {})),
+    (u'iese',     ('p-??',      u'i',      {})),
+    (u'iau',      ('pt??',      u'as',     {})),
+    (u'iau',      ('pt??',      u'us',     {})),
+    (u'iausiai',  ('pc??',      u'as',     {})),
+    (u'iausiai',  ('pc??',      u'us',     {})),
+
+    # Pavardės
+    # (vyr. g., vns.)
+    (u'kas',      ('dvvv**',    u'kas',    {'t': 'pavardė'}) ),
+    (u'ko',       ('dvvk**',    u'kas',    {'t': 'pavardė'}) ),
+    (u'kui',      ('dvvn**',    u'kas',    {'t': 'pavardė'}) ),
+    (u'ką',       ('dvvg**',    u'kas',    {'t': 'pavardė'}) ),
+    (u'ku',       ('dvvi**',    u'kas',    {'t': 'pavardė'}) ),
+    (u'ke',       ('dvvt**',    u'kas',    {'t': 'pavardė'}) ),
+    (u'kai',      ('dvvs**',    u'kas',    {'t': 'pavardė'}) ),
+    # (vyr. g., dgs.)
+    (u'kai',      ('dvdv**',    u'kas',    {'t': 'pavardė'}) ),
+    (u'kų',       ('dvdk**',    u'kas',    {'t': 'pavardė'}) ),
+    (u'kams',     ('dvdn**',    u'kas',    {'t': 'pavardė'}) ),
+    (u'kus',      ('dvdg**',    u'kas',    {'t': 'pavardė'}) ),
+    (u'kais',     ('dvdi**',    u'kas',    {'t': 'pavardė'}) ),
+    (u'kuose',    ('dvdt**',    u'kas',    {'t': 'pavardė'}) ),
+    (u'kai',      ('dvds**',    u'kas',    {'t': 'pavardė'}) ),
+    # (mot. g., vns.)
+    (u'ienė',     ('dmvv**',    u'ienė',   {'t': 'pavardė'}) ),
+    (u'ienės',    ('dmvk**',    u'ienė',   {'t': 'pavardė'}) ),
+    (u'ienei',    ('dmvn**',    u'ienė',   {'t': 'pavardė'}) ),
+    (u'ienę',     ('dmvg**',    u'ienė',   {'t': 'pavardė'}) ),
+    (u'iene',     ('dmvi**',    u'ienė',   {'t': 'pavardė'}) ),
+    (u'ienėje',   ('dmvt**',    u'ienė',   {'t': 'pavardė'}) ),
+    (u'ienę',     ('dmvs**',    u'ienė',   {'t': 'pavardė'}) ),
+    # (mot. g., dgs.)
+    (u'ienės',    ('dmdv**',    u'ienė',   {'t': 'pavardė'}) ),
+    (u'ienių',    ('dmdk**',    u'ienė',   {'t': 'pavardė'}) ),
+    (u'ienėms',   ('dmdn**',    u'ienė',   {'t': 'pavardė'}) ),
+    (u'ienes',    ('dmdg**',    u'ienė',   {'t': 'pavardė'}) ),
+    (u'ienėmis',  ('dmdi**',    u'ienė',   {'t': 'pavardė'}) ),
+    (u'ienėse',   ('dmdt**',    u'ienė',   {'t': 'pavardė'}) ),
+    (u'ienės',    ('dmds**',    u'ienė',   {'t': 'pavardė'}) ),
+    # (mot. g., vns.)
+    (u'aitė',     ('dmvv**',    u'aitė',   {'t': 'pavardė'}) ),
+    (u'aitės',    ('dmvk**',    u'aitė',   {'t': 'pavardė'}) ),
+    (u'aitei',    ('dmvn**',    u'aitė',   {'t': 'pavardė'}) ),
+    (u'aitę',     ('dmvg**',    u'aitė',   {'t': 'pavardė'}) ),
+    (u'aite',     ('dmvi**',    u'aitė',   {'t': 'pavardė'}) ),
+    (u'aitėje',   ('dmvt**',    u'aitė',   {'t': 'pavardė'}) ),
+    (u'aitę',     ('dmvs**',    u'aitė',   {'t': 'pavardė'}) ),
+    # (mot. g., dgs.)
+    (u'aitės',    ('dmdv**',    u'aitė',   {'t': 'pavardė'}) ),
+    (u'aičių',    ('dmdk**',    u'aitė',   {'t': 'pavardė'}) ),
+    (u'aitėms',   ('dmdn**',    u'aitė',   {'t': 'pavardė'}) ),
+    (u'aites',    ('dmdg**',    u'aitė',   {'t': 'pavardė'}) ),
+    (u'aitėmis',  ('dmdi**',    u'aitė',   {'t': 'pavardė'}) ),
+    (u'aitėse',   ('dmdt**',    u'aitė',   {'t': 'pavardė'}) ),
+    (u'aitės',    ('dmds**',    u'aitė',   {'t': 'pavardė'}) ),
+
+)
+

File src/lema/tests.py

+# coding: utf-8
+
+import doctest
+import unittest
+
+from lema import Lema
+
+
+class TestAutodetect(unittest.TestCase):
+    def test_nepripazinti(self):
+        lema = Lema()
+        forms = lema.detect(u'nepripažinti')
+        print(forms)
+
+
+def suite():
+    loader = unittest.TestLoader()
+    tests = unittest.TestSuite()
+    tests.addTests(doctest.DocTestSuite(lema))
+    tests.addTests(loader.loadTestsFromName(__name__))
+    return tests
+
+
+def main():
+    unittest.TextTestRunner().run(suite())
+
+
+if __name__ == '__main__':
+    main()