diff --git a/.github/contributors/aliiae.md b/.github/contributors/aliiae.md new file mode 100644 index 000000000..7e9cd4850 --- /dev/null +++ b/.github/contributors/aliiae.md @@ -0,0 +1,106 @@ +# spaCy contributor agreement + +This spaCy Contributor Agreement (**"SCA"**) is based on the +[Oracle Contributor Agreement](http://www.oracle.com/technetwork/oca-405177.pdf). +The SCA applies to any contribution that you make to any product or project +managed by us (the **"project"**), and sets out the intellectual property rights +you grant to us in the contributed materials. The term **"us"** shall mean +[ExplosionAI UG (haftungsbeschränkt)](https://explosion.ai/legal). The term +**"you"** shall mean the person or entity identified below. + +If you agree to be bound by these terms, fill in the information requested +below and include the filled-in version with your first pull request, under the +folder [`.github/contributors/`](/.github/contributors/). The name of the file +should be your GitHub username, with the extension `.md`. For example, the user +example_user would create the file `.github/contributors/example_user.md`. + +Read this agreement carefully before signing. These terms and conditions +constitute a binding legal agreement. + +## Contributor Agreement + +1. The term "contribution" or "contributed materials" means any source code, +object code, patch, tool, sample, graphic, specification, manual, +documentation, or any other material posted or submitted by you to the project. + +2. With respect to any worldwide copyrights, or copyright applications and +registrations, in your contribution: + + * you hereby assign to us joint ownership, and to the extent that such + assignment is or becomes invalid, ineffective or unenforceable, you hereby + grant to us a perpetual, irrevocable, non-exclusive, worldwide, no-charge, + royalty-free, unrestricted license to exercise all rights under those + copyrights. This includes, at our option, the right to sublicense these same + rights to third parties through multiple levels of sublicensees or other + licensing arrangements; + + * you agree that each of us can do all things in relation to your + contribution as if each of us were the sole owners, and if one of us makes + a derivative work of your contribution, the one who makes the derivative + work (or has it made will be the sole owner of that derivative work; + + * you agree that you will not assert any moral rights in your contribution + against us, our licensees or transferees; + + * you agree that we may register a copyright in your contribution and + exercise all ownership rights associated with it; and + + * you agree that neither of us has any duty to consult with, obtain the + consent of, pay or render an accounting to the other for any use or + distribution of your contribution. + +3. With respect to any patents you own, or that you can license without payment +to any third party, you hereby grant to us a perpetual, irrevocable, +non-exclusive, worldwide, no-charge, royalty-free license to: + + * make, have made, use, sell, offer to sell, import, and otherwise transfer + your contribution in whole or in part, alone or in combination with or + included in any product, work or materials arising out of the project to + which your contribution was submitted, and + + * at our option, to sublicense these same rights to third parties through + multiple levels of sublicensees or other licensing arrangements. + +4. Except as set out above, you keep all right, title, and interest in your +contribution. The rights that you grant to us under these terms are effective +on the date you first submitted a contribution to us, even if your submission +took place before the date you sign these terms. + +5. You covenant, represent, warrant and agree that: + + * Each contribution that you submit is and shall be an original work of + authorship and you can legally grant the rights set out in this SCA; + + * to the best of your knowledge, each contribution will not violate any + third party's copyrights, trademarks, patents, or other intellectual + property rights; and + + * each contribution shall be in compliance with U.S. export control laws and + other applicable export and import laws. You agree to notify us if you + become aware of any circumstance which would make any of the foregoing + representations inaccurate in any respect. We may publicly disclose your + participation in the project, including the fact that you have signed the SCA. + +6. This SCA is governed by the laws of the State of California and applicable +U.S. Federal law. Any choice of law rules will not apply. + +7. Please place an “x” on one of the applicable statement below. Please do NOT +mark both statements: + + * [x] I am signing on behalf of myself as an individual and no other person + or entity, including my employer, has or will have rights with respect to my + contributions. + + * [ ] I am signing on behalf of my employer or a legal entity and I have the + actual authority to contractually bind that entity. + +## Contributor Details + +| Field | Entry | +|------------------------------- | -------------------- | +| Name | Aliia Erofeeva | +| Company name (if applicable) | | +| Title or role (if applicable) | | +| Date | 13 June 2018 | +| GitHub username | aliiae | +| Website (optional) | | diff --git a/spacy/lang/char_classes.py b/spacy/lang/char_classes.py index c0ecf5b3f..77a4c69df 100644 --- a/spacy/lang/char_classes.py +++ b/spacy/lang/char_classes.py @@ -16,9 +16,11 @@ _latin = r'[[\p{Ll}||\p{Lu}]&&\p{Latin}]' _persian = r'[\p{L}&&\p{Arabic}]' _russian_lower = r'[ёа-я]' _russian_upper = r'[ЁА-Я]' +_tatar_lower = r'[әөүҗңһ]' +_tatar_upper = r'[ӘӨҮҖҢҺ]' -_upper = [_latin_upper, _russian_upper] -_lower = [_latin_lower, _russian_lower] +_upper = [_latin_upper, _russian_upper, _tatar_upper] +_lower = [_latin_lower, _russian_lower, _tatar_lower] _uncased = [_bengali, _hebrew, _persian] ALPHA = merge_char_classes(_upper + _lower + _uncased) diff --git a/spacy/lang/tt/__init__.py b/spacy/lang/tt/__init__.py new file mode 100644 index 000000000..b4117403f --- /dev/null +++ b/spacy/lang/tt/__init__.py @@ -0,0 +1,31 @@ +# coding: utf8 +from __future__ import unicode_literals + +from .lex_attrs import LEX_ATTRS +from .punctuation import TOKENIZER_INFIXES +from .stop_words import STOP_WORDS +from .tokenizer_exceptions import TOKENIZER_EXCEPTIONS +from ..tokenizer_exceptions import BASE_EXCEPTIONS +from ...attrs import LANG +from ...language import Language +from ...util import update_exc + + +class TatarDefaults(Language.Defaults): + lex_attr_getters = dict(Language.Defaults.lex_attr_getters) + lex_attr_getters[LANG] = lambda text: 'tt' + + lex_attr_getters.update(LEX_ATTRS) + + tokenizer_exceptions = update_exc(BASE_EXCEPTIONS, TOKENIZER_EXCEPTIONS) + infixes = tuple(TOKENIZER_INFIXES) + + stop_words = STOP_WORDS + + +class Tatar(Language): + lang = 'tt' + Defaults = TatarDefaults + + +__all__ = ['Tatar'] diff --git a/spacy/lang/tt/examples.py b/spacy/lang/tt/examples.py new file mode 100644 index 000000000..efa8b547c --- /dev/null +++ b/spacy/lang/tt/examples.py @@ -0,0 +1,19 @@ +# coding: utf8 +from __future__ import unicode_literals + +""" +Example sentences to test spaCy and its language models. +>>> from spacy.lang.tt.examples import sentences +>>> docs = nlp.pipe(sentences) +""" + +sentences = [ + "Apple Бөекбритания стартабын $1 миллиард өчен сатып алыун исәпли.", + "Автоном автомобильләр иминият җаваплылыкны җитештерүчеләргә күчерә.", + "Сан-Франциско тротуар буенча йөри торган робот-курьерларны тыю мөмкинлеген карый.", + "Лондон - Бөекбританиядә урнашкан зур шәһәр.", + "Син кайда?", + "Францияда кем президент?", + "Америка Кушма Штатларының башкаласы нинди шәһәр?", + "Барак Обама кайчан туган?" +] diff --git a/spacy/lang/tt/lex_attrs.py b/spacy/lang/tt/lex_attrs.py new file mode 100644 index 000000000..8f332ecb9 --- /dev/null +++ b/spacy/lang/tt/lex_attrs.py @@ -0,0 +1,29 @@ +# coding: utf8 +from __future__ import unicode_literals + +from ...attrs import LIKE_NUM + +_num_words = ['нуль', 'ноль', 'бер', 'ике', 'өч', 'дүрт', 'биш', 'алты', 'җиде', + 'сигез', 'тугыз', 'ун', 'унбер', 'унике', 'унөч', 'ундүрт', + 'унбиш', 'уналты', 'унҗиде', 'унсигез', 'унтугыз', 'егерме', + 'утыз', 'кырык', 'илле', 'алтмыш', 'җитмеш', 'сиксән', 'туксан', + 'йөз', 'мең', 'төмән', 'миллион', 'миллиард', 'триллион', + 'триллиард'] + + +def like_num(text): + text = text.replace(',', '').replace('.', '') + if text.isdigit(): + return True + if text.count('/') == 1: + num, denom = text.split('/') + if num.isdigit() and denom.isdigit(): + return True + if text in _num_words: + return True + return False + + +LEX_ATTRS = { + LIKE_NUM: like_num +} diff --git a/spacy/lang/tt/punctuation.py b/spacy/lang/tt/punctuation.py new file mode 100644 index 000000000..e45983926 --- /dev/null +++ b/spacy/lang/tt/punctuation.py @@ -0,0 +1,19 @@ +# coding: utf8 +from __future__ import unicode_literals + +from ..char_classes import ALPHA, ALPHA_LOWER, ALPHA_UPPER, QUOTES, HYPHENS +from ..char_classes import LIST_ELLIPSES, LIST_ICONS + +_hyphens_no_dash = HYPHENS.replace('-', '').strip('|').replace('||', '') +_infixes = (LIST_ELLIPSES + LIST_ICONS + + [r'(?<=[{}])\.(?=[{}])'.format(ALPHA_LOWER, ALPHA_UPPER), + r'(?<=[{a}])[,!?/\(\)]+(?=[{a}])'.format(a=ALPHA), + r'(?<=[{a}{q}])[:<>=](?=[{a}])'.format(a=ALPHA, q=QUOTES), + r'(?<=[{a}])--(?=[{a}])'.format(a=ALPHA), + r'(?<=[{a}]),(?=[{a}])'.format(a=ALPHA), + r'(?<=[{a}])([{q}\)\]\(\[])(?=[\-{a}])'.format(a=ALPHA, q=QUOTES), + r'(?<=[{a}])[?";:=,.]*(?:{h})(?=[{a}])'.format(a=ALPHA, + h=_hyphens_no_dash), + r'(?<=[0-9])-(?=[0-9])']) + +TOKENIZER_INFIXES = _infixes diff --git a/spacy/lang/tt/stop_words.py b/spacy/lang/tt/stop_words.py new file mode 100644 index 000000000..d800ada46 --- /dev/null +++ b/spacy/lang/tt/stop_words.py @@ -0,0 +1,174 @@ +# encoding: utf8 +from __future__ import unicode_literals + +# Tatar stopwords are from https://github.com/aliiae/stopwords-tt + +STOP_WORDS = set("""алай алайса алар аларга аларда алардан аларны аларның аларча +алары аларын аларынга аларында аларыннан аларының алтмыш алтмышынчы алтмышынчыга +алтмышынчыда алтмышынчыдан алтмышынчылар алтмышынчыларга алтмышынчыларда +алтмышынчылардан алтмышынчыларны алтмышынчыларның алтмышынчыны алтмышынчының +алты алтылап алтынчы алтынчыга алтынчыда алтынчыдан алтынчылар алтынчыларга +алтынчыларда алтынчылардан алтынчыларны алтынчыларның алтынчыны алтынчының +алтышар анда андагы андай андый андыйга андыйда андыйдан андыйны андыйның аннан +ансы анча аны аныкы аныкын аныкынга аныкында аныкыннан аныкының анысы анысын +анысынга анысында анысыннан анысының аның аныңча аркылы ары аша аңа аңар аңарга +аңарда аңардагы аңардан + +бар бара барлык барча барчасы барчасын барчасына барчасында барчасыннан +барчасының бары башка башкача бе­лән без безгә бездә бездән безне безнең безнеңчә +белдерүенчә белән бер бергә беренче беренчегә беренчедә беренчедән беренчеләр +беренчеләргә беренчеләрдә беренчеләрдән беренчеләрне беренчеләрнең беренчене +беренченең беркайда беркайсы беркая беркаян беркем беркемгә беркемдә беркемне +беркемнең беркемнән берлән берни бернигә бернидә бернидән бернинди бернине +бернинең берничек берничә бернәрсә бернәрсәгә бернәрсәдә бернәрсәдән бернәрсәне +бернәрсәнең беррәттән берсе берсен берсенгә берсендә берсенең берсеннән берәр +берәрсе берәрсен берәрсендә берәрсенең берәрсеннән берәрсенә берәү бигрәк бик +бирле бит биш бишенче бишенчегә бишенчедә бишенчедән бишенчеләр бишенчеләргә +бишенчеләрдә бишенчеләрдән бишенчеләрне бишенчеләрнең бишенчене бишенченең +бишләп болай болар боларга боларда болардан боларны боларның болары боларын +боларынга боларында боларыннан боларының бу буе буена буенда буенча буйлап +буларак булачак булды булмый булса булып булыр булырга бусы бүтән бәлки бән +бәрабәренә бөтен бөтенесе бөтенесен бөтенесендә бөтенесенең бөтенесеннән +бөтенесенә + +вә + +гел генә гына гүя гүяки гәрчә + +да ди дигән диде дип дистәләгән дистәләрчә дүрт дүртенче дүртенчегә дүртенчедә +дүртенчедән дүртенчеләр дүртенчеләргә дүртенчеләрдә дүртенчеләрдән дүртенчеләрне +дүртенчеләрнең дүртенчене дүртенченең дүртләп дә + +егерме егерменче егерменчегә егерменчедә егерменчедән егерменчеләр +егерменчеләргә егерменчеләрдә егерменчеләрдән егерменчеләрне егерменчеләрнең +егерменчене егерменченең ел елда + +иде идек идем ике икенче икенчегә икенчедә икенчедән икенчеләр икенчеләргә +икенчеләрдә икенчеләрдән икенчеләрне икенчеләрнең икенчене икенченең икешәр икән +илле илленче илленчегә илленчедә илленчедән илленчеләр илленчеләргә +илленчеләрдә илленчеләрдән илленчеләрне илленчеләрнең илленчене илленченең илә +илән инде исә итеп иткән итте итү итә итәргә иң + +йөз йөзенче йөзенчегә йөзенчедә йөзенчедән йөзенчеләр йөзенчеләргә йөзенчеләрдә +йөзенчеләрдән йөзенчеләрне йөзенчеләрнең йөзенчене йөзенченең йөзләгән йөзләрчә +йөзәрләгән + +кадәр кай кайбер кайберләре кайберсе кайберәү кайберәүгә кайберәүдә кайберәүдән +кайберәүне кайберәүнең кайдагы кайсы кайсыбер кайсын кайсына кайсында кайсыннан +кайсының кайчангы кайчандагы кайчаннан караганда карамастан карамый карата каршы +каршына каршында каршындагы кебек кем кемгә кемдә кемне кемнең кемнән кенә ки +килеп килә кирәк кына кырыгынчы кырыгынчыга кырыгынчыда кырыгынчыдан +кырыгынчылар кырыгынчыларга кырыгынчыларда кырыгынчылардан кырыгынчыларны +кырыгынчыларның кырыгынчыны кырыгынчының кырык күк күпләгән күпме күпмеләп +күпмешәр күпмешәрләп күптән күрә + +ләкин + +максатында менә мең меңенче меңенчегә меңенчедә меңенчедән меңенчеләр +меңенчеләргә меңенчеләрдә меңенчеләрдән меңенчеләрне меңенчеләрнең меңенчене +меңенченең меңләгән меңләп меңнәрчә меңәрләгән меңәрләп миллиард миллиардлаган +миллиардларча миллион миллионлаган миллионнарча миллионынчы миллионынчыга +миллионынчыда миллионынчыдан миллионынчылар миллионынчыларга миллионынчыларда +миллионынчылардан миллионынчыларны миллионынчыларның миллионынчыны +миллионынчының мин миндә мине минем минемчә миннән миңа монда мондагы мондые +мондыен мондыенгә мондыендә мондыеннән мондыеның мондый мондыйга мондыйда +мондыйдан мондыйлар мондыйларга мондыйларда мондыйлардан мондыйларны +мондыйларның мондыйлары мондыйларын мондыйларынга мондыйларында мондыйларыннан +мондыйларының мондыйны мондыйның моннан монсыз монча моны моныкы моныкын +моныкынга моныкында моныкыннан моныкының монысы монысын монысынга монысында +монысыннан монысының моның моңа моңар моңарга мәгълүматынча мәгәр мән мөмкин + +ни нибарысы никадәре нинди ниндие ниндиен ниндиенгә ниндиендә ниндиенең +ниндиеннән ниндиләр ниндиләргә ниндиләрдә ниндиләрдән ниндиләрен ниндиләренн +ниндиләреннгә ниндиләренндә ниндиләреннең ниндиләренннән ниндиләрне ниндиләрнең +ниндирәк нихәтле ничаклы ничек ничәшәр ничәшәрләп нуль нче нчы нәрсә нәрсәгә +нәрсәдә нәрсәдән нәрсәне нәрсәнең + +саен сез сезгә сездә сездән сезне сезнең сезнеңчә сигез сигезенче сигезенчегә +сигезенчедә сигезенчедән сигезенчеләр сигезенчеләргә сигезенчеләрдә +сигезенчеләрдән сигезенчеләрне сигезенчеләрнең сигезенчене сигезенченең +сиксән син синдә сине синең синеңчә синнән сиңа соң сыман сүзенчә сүзләренчә + +та таба теге тегеләй тегеләр тегеләргә тегеләрдә тегеләрдән тегеләре тегеләрен +тегеләренгә тегеләрендә тегеләренең тегеләреннән тегеләрне тегеләрнең тегенди +тегендигә тегендидә тегендидән тегендине тегендинең тегендә тегендәге тегене +тегенеке тегенекен тегенекенгә тегенекендә тегенекенең тегенекеннән тегенең +тегеннән тегесе тегесен тегесенгә тегесендә тегесенең тегесеннән тегеңә тиеш тик +тикле тора триллиард триллион тугыз тугызлап тугызлашып тугызынчы тугызынчыга +тугызынчыда тугызынчыдан тугызынчылар тугызынчыларга тугызынчыларда +тугызынчылардан тугызынчыларны тугызынчыларның тугызынчыны тугызынчының туксан +туксанынчы туксанынчыга туксанынчыда туксанынчыдан туксанынчылар туксанынчыларга +туксанынчыларда туксанынчылардан туксанынчыларны туксанынчыларның туксанынчыны +туксанынчының турында тыш түгел тә тәгаенләнгән төмән + +уенча уйлавынча ук ул ун уналты уналтынчы уналтынчыга уналтынчыда уналтынчыдан +уналтынчылар уналтынчыларга уналтынчыларда уналтынчылардан уналтынчыларны +уналтынчыларның уналтынчыны уналтынчының унарлаган унарлап унаула унаулап унбер +унберенче унберенчегә унберенчедә унберенчедән унберенчеләр унберенчеләргә +унберенчеләрдә унберенчеләрдән унберенчеләрне унберенчеләрнең унберенчене +унберенченең унбиш унбишенче унбишенчегә унбишенчедә унбишенчедән унбишенчеләр +унбишенчеләргә унбишенчеләрдә унбишенчеләрдән унбишенчеләрне унбишенчеләрнең +унбишенчене унбишенченең ундүрт ундүртенче ундүртенчегә ундүртенчедә +ундүртенчедән ундүртенчеләр ундүртенчеләргә ундүртенчеләрдә ундүртенчеләрдән +ундүртенчеләрне ундүртенчеләрнең ундүртенчене ундүртенченең унике уникенче +уникенчегә уникенчедә уникенчедән уникенчеләр уникенчеләргә уникенчеләрдә +уникенчеләрдән уникенчеләрне уникенчеләрнең уникенчене уникенченең унлаган +унлап уннарча унсигез унсигезенче унсигезенчегә унсигезенчедә унсигезенчедән +унсигезенчеләр унсигезенчеләргә унсигезенчеләрдә унсигезенчеләрдән +унсигезенчеләрне унсигезенчеләрнең унсигезенчене унсигезенченең унтугыз +унтугызынчы унтугызынчыга унтугызынчыда унтугызынчыдан унтугызынчылар +унтугызынчыларга унтугызынчыларда унтугызынчылардан унтугызынчыларны +унтугызынчыларның унтугызынчыны унтугызынчының унынчы унынчыга унынчыда +унынчыдан унынчылар унынчыларга унынчыларда унынчылардан унынчыларны +унынчыларның унынчыны унынчының унҗиде унҗиденче унҗиденчегә унҗиденчедә +унҗиденчедән унҗиденчеләр унҗиденчеләргә унҗиденчеләрдә унҗиденчеләрдән +унҗиденчеләрне унҗиденчеләрнең унҗиденчене унҗиденченең унөч унөченче унөченчегә +унөченчедә унөченчедән унөченчеләр унөченчеләргә унөченчеләрдә унөченчеләрдән +унөченчеләрне унөченчеләрнең унөченчене унөченченең утыз утызынчы утызынчыга +утызынчыда утызынчыдан утызынчылар утызынчыларга утызынчыларда утызынчылардан +утызынчыларны утызынчыларның утызынчыны утызынчының + +фикеренчә фәкать + +хакында хәбәр хәлбуки хәтле хәтта + +чаклы чакта чөнки + +шикелле шул шулай шулар шуларга шуларда шулардан шуларны шуларның шулары шуларын +шуларынга шуларында шуларыннан шуларының шулкадәр шултикле шултиклем шулхәтле +шулчаклы шунда шундагы шундый шундыйга шундыйда шундыйдан шундыйны шундыйның +шунлыктан шуннан шунсы шунча шуны шуныкы шуныкын шуныкынга шуныкында шуныкыннан +шуныкының шунысы шунысын шунысынга шунысында шунысыннан шунысының шуның шушы +шушында шушыннан шушыны шушының шушыңа шуңа шуңар шуңарга + +элек + +югыйсә юк юкса + +я ягъни язуынча яисә яки яктан якын ярашлы яхут яшь яшьлек + +җиде җиделәп җиденче җиденчегә җиденчедә җиденчедән җиденчеләр җиденчеләргә +җиденчеләрдә җиденчеләрдән җиденчеләрне җиденчеләрнең җиденчене җиденченең +җидешәр җитмеш җитмешенче җитмешенчегә җитмешенчедә җитмешенчедән җитмешенчеләр +җитмешенчеләргә җитмешенчеләрдә җитмешенчеләрдән җитмешенчеләрне +җитмешенчеләрнең җитмешенчене җитмешенченең җыенысы + +үз үзе үзем үземдә үземне үземнең үземнән үземә үзен үзендә үзенең үзеннән үзенә +үк + +һичбер һичбере һичберен һичберендә һичберенең һичбереннән һичберенә һичберсе +һичберсен һичберсендә һичберсенең һичберсеннән һичберсенә һичберәү һичберәүгә +һичберәүдә һичберәүдән һичберәүне һичберәүнең һичкайсы һичкайсыга һичкайсыда +һичкайсыдан һичкайсыны һичкайсының һичкем һичкемгә һичкемдә һичкемне һичкемнең +һичкемнән һични һичнигә һичнидә һичнидән һичнинди һичнине һичнинең һичнәрсә +һичнәрсәгә һичнәрсәдә һичнәрсәдән һичнәрсәне һичнәрсәнең һәм һәммә һәммәсе +һәммәсен һәммәсендә һәммәсенең һәммәсеннән һәммәсенә һәр һәрбер һәрбере һәрберсе +һәркайсы һәркайсыга һәркайсыда һәркайсыдан һәркайсыны һәркайсының һәркем +һәркемгә һәркемдә һәркемне һәркемнең һәркемнән һәрни һәрнәрсә һәрнәрсәгә +һәрнәрсәдә һәрнәрсәдән һәрнәрсәне һәрнәрсәнең һәртөрле + +ә әгәр әйтүенчә әйтүләренчә әлбәттә әле әлеге әллә әмма әнә + +өстәп өч өчен өченче өченчегә өченчедә өченчедән өченчеләр өченчеләргә +өченчеләрдә өченчеләрдән өченчеләрне өченчеләрнең өченчене өченченең өчләп +өчәрләп""".split()) diff --git a/spacy/lang/tt/tokenizer_exceptions.py b/spacy/lang/tt/tokenizer_exceptions.py new file mode 100644 index 000000000..d2d234c36 --- /dev/null +++ b/spacy/lang/tt/tokenizer_exceptions.py @@ -0,0 +1,52 @@ +# coding: utf8 +from __future__ import unicode_literals + +from ...symbols import ORTH, LEMMA, NORM + +_exc = {} + +_abbrev_exc = [ + # Weekdays abbreviations + {ORTH: "дш", LEMMA: "дүшәмбе"}, + {ORTH: "сш", LEMMA: "сишәмбе"}, + {ORTH: "чш", LEMMA: "чәршәмбе"}, + {ORTH: "пш", LEMMA: "пәнҗешәмбе"}, + {ORTH: "җм", LEMMA: "җомга"}, + {ORTH: "шб", LEMMA: "шимбә"}, + {ORTH: "яш", LEMMA: "якшәмбе"}, + + # Months abbreviations + {ORTH: "гый", LEMMA: "гыйнвар"}, + {ORTH: "фев", LEMMA: "февраль"}, + {ORTH: "мар", LEMMA: "март"}, + {ORTH: "мар", LEMMA: "март"}, + {ORTH: "апр", LEMMA: "апрель"}, + {ORTH: "июн", LEMMA: "июнь"}, + {ORTH: "июл", LEMMA: "июль"}, + {ORTH: "авг", LEMMA: "август"}, + {ORTH: "сен", LEMMA: "сентябрь"}, + {ORTH: "окт", LEMMA: "октябрь"}, + {ORTH: "ноя", LEMMA: "ноябрь"}, + {ORTH: "дек", LEMMA: "декабрь"}, + + # Number abbreviations + {ORTH: "млрд", LEMMA: "миллиард"}, + {ORTH: "млн", LEMMA: "миллион"}, +] + +for abbr in _abbrev_exc: + for orth in (abbr[ORTH], abbr[ORTH].capitalize(), abbr[ORTH].upper()): + _exc[orth] = [{ORTH: orth, LEMMA: abbr[LEMMA], NORM: abbr[LEMMA]}] + _exc[orth + "."] = [ + {ORTH: orth + ".", LEMMA: abbr[LEMMA], NORM: abbr[LEMMA]} + ] + +for exc_data in [ # "etc." abbreviations + {ORTH: "һ.б.ш.", NORM: "һәм башка шундыйлар"}, + {ORTH: "һ.б.", NORM: "һәм башка"}, + {ORTH: "б.э.к.", NORM: "безнең эрага кадәр"}, + {ORTH: "б.э.", NORM: "безнең эра"}]: + exc_data[LEMMA] = exc_data[NORM] + _exc[exc_data[ORTH]] = [exc_data] + +TOKENIZER_EXCEPTIONS = _exc diff --git a/spacy/tests/conftest.py b/spacy/tests/conftest.py index f703489e3..d378db588 100644 --- a/spacy/tests/conftest.py +++ b/spacy/tests/conftest.py @@ -15,7 +15,8 @@ from .. import util # here if it's using spaCy's tokenizer (not a different library) # TODO: re-implement generic tokenizer tests _languages = ['bn', 'da', 'de', 'en', 'es', 'fi', 'fr', 'ga', 'he', 'hu', 'id', - 'it', 'nb', 'nl', 'pl', 'pt', 'ro', 'ru', 'sv', 'tr', 'ar', 'xx'] + 'it', 'nb', 'nl', 'pl', 'pt', 'ro', 'ru', 'sv', 'tr', 'ar', 'tt', + 'xx'] _models = {'en': ['en_core_web_sm'], 'de': ['de_core_news_sm'], @@ -153,6 +154,10 @@ def th_tokenizer(): def tr_tokenizer(): return util.get_lang_class('tr').Defaults.create_tokenizer() +@pytest.fixture +def tt_tokenizer(): + return util.get_lang_class('tt').Defaults.create_tokenizer() + @pytest.fixture def ar_tokenizer(): return util.get_lang_class('ar').Defaults.create_tokenizer() diff --git a/spacy/tests/lang/tt/__init__.py b/spacy/tests/lang/tt/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/spacy/tests/lang/tt/test_tokenizer.py b/spacy/tests/lang/tt/test_tokenizer.py new file mode 100644 index 000000000..c052c1846 --- /dev/null +++ b/spacy/tests/lang/tt/test_tokenizer.py @@ -0,0 +1,75 @@ +# coding: utf8 +from __future__ import unicode_literals + +import pytest + +INFIX_HYPHEN_TESTS = [ + ("Явым-төшем күләме.", "Явым-төшем күләме .".split()), + ("Хатын-кыз киеме.", "Хатын-кыз киеме .".split()) +] + +PUNC_INSIDE_WORDS_TESTS = [ + ("Пассаҗир саны - 2,13 млн — кеше/көндә (2010), 783,9 млн. кеше/елда.", + "Пассаҗир саны - 2,13 млн — кеше / көндә ( 2010 ) ," + " 783,9 млн. кеше / елда .".split()), + ("Ту\"кай", "Ту \" кай".split()) +] + +MIXED_ORDINAL_NUMS_TESTS = [ + ("Иртәгә 22нче гыйнвар...", "Иртәгә 22нче гыйнвар ...".split()) +] + +ABBREV_TESTS = [ + ("«3 елда (б.э.к.) туган", "« 3 елда ( б.э.к. ) туган".split()), + ("тукымадан һ.б.ш. тегелгән.", "тукымадан һ.б.ш. тегелгән .".split()) +] + +NAME_ABBREV_TESTS = [ + ("Ә.Тукай", "Ә.Тукай".split()), + ("Ә.тукай", "Ә.тукай".split()), + ("ә.Тукай", "ә . Тукай".split()), + ("Миләүшә.", "Миләүшә .".split()) +] + +TYPOS_IN_PUNC_TESTS = [ + ("«3 елда , туган", "« 3 елда , туган".split()), + ("«3 елда,туган", "« 3 елда , туган".split()), + ("«3 елда,туган.", "« 3 елда , туган .".split()), + ("Ул эшли(кайчан?)", "Ул эшли ( кайчан ? )".split()), + ("Ул (кайчан?)эшли", "Ул ( кайчан ?) эшли".split()) # "?)" => "?)" or "? )" +] + +LONG_TEXTS_TESTS = [ + ("Иң борынгы кешеләр суыклар һәм салкын кышлар булмый торган җылы" + "якларда яшәгәннәр, шуңа күрә аларга кием кирәк булмаган.Йөз" + "меңнәрчә еллар үткән, борынгы кешеләр акрынлап Европа һәм Азиянең" + "салкын илләрендә дә яши башлаганнар. Алар кырыс һәм салкын" + "кышлардан саклану өчен кием-салым уйлап тапканнар - итәк.", + "Иң борынгы кешеләр суыклар һәм салкын кышлар булмый торган җылы" + "якларда яшәгәннәр , шуңа күрә аларга кием кирәк булмаган . Йөз" + "меңнәрчә еллар үткән , борынгы кешеләр акрынлап Европа һәм Азиянең" + "салкын илләрендә дә яши башлаганнар . Алар кырыс һәм салкын" + "кышлардан саклану өчен кием-салым уйлап тапканнар - итәк .".split() + ) +] + +TESTCASES = (INFIX_HYPHEN_TESTS + PUNC_INSIDE_WORDS_TESTS + + MIXED_ORDINAL_NUMS_TESTS + ABBREV_TESTS + NAME_ABBREV_TESTS + + LONG_TEXTS_TESTS + TYPOS_IN_PUNC_TESTS) + +NORM_TESTCASES = [ + ("тукымадан һ.б.ш. тегелгән.", + ["тукымадан", "һәм башка шундыйлар", "тегелгән", "."]) +] + + +@pytest.mark.parametrize("text,expected_tokens", TESTCASES) +def test_tokenizer_handles_testcases(tt_tokenizer, text, expected_tokens): + tokens = [token.text for token in tt_tokenizer(text) if not token.is_space] + assert expected_tokens == tokens + + +@pytest.mark.parametrize('text,norms', NORM_TESTCASES) +def test_tokenizer_handles_norm_exceptions(tt_tokenizer, text, norms): + tokens = tt_tokenizer(text) + assert [token.norm_ for token in tokens] == norms