From ec62cadf4c1417261e3c7bc9e4c07a01ca2d324b Mon Sep 17 00:00:00 2001 From: Jani Monoses Date: Thu, 24 May 2018 12:40:00 +0300 Subject: [PATCH] Updates to Romanian support (#2354) * Add back Romanian in conftest * Romanian lex_attr * More tokenizer exceptions for Romanian * Add tests for some Romanian tokenizer exceptions --- spacy/lang/ro/lex_attrs.py | 42 +++++++++++++++++++++++++++ spacy/lang/ro/tokenizer_exceptions.py | 5 ++-- spacy/tests/conftest.py | 2 +- spacy/tests/lang/ro/test_tokenizer.py | 25 ++++++++++++++++ 4 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 spacy/lang/ro/lex_attrs.py create mode 100644 spacy/tests/lang/ro/test_tokenizer.py diff --git a/spacy/lang/ro/lex_attrs.py b/spacy/lang/ro/lex_attrs.py new file mode 100644 index 000000000..48027186b --- /dev/null +++ b/spacy/lang/ro/lex_attrs.py @@ -0,0 +1,42 @@ +# coding: utf8 +from __future__ import unicode_literals + +from ...attrs import LIKE_NUM + + +_num_words = set(""" +zero unu doi două trei patru cinci șase șapte opt nouă zece +unsprezece doisprezece douăsprezece treisprezece patrusprezece cincisprezece șaisprezece șaptesprezece optsprezece nouăsprezece +douăzeci treizeci patruzeci cincizeci șaizeci șaptezeci optzeci nouăzeci +sută mie milion miliard bilion trilion cvadrilion catralion cvintilion sextilion septilion enșpemii +""".split()) + +_ordinal_words = set(""" +primul doilea treilea patrulea cincilea șaselea șaptelea optulea nouălea zecelea +prima doua treia patra cincia șasea șaptea opta noua zecea +unsprezecelea doisprezecelea treisprezecelea patrusprezecelea cincisprezecelea șaisprezecelea șaptesprezecelea optsprezecelea nouăsprezecelea +unsprezecea douăsprezecea treisprezecea patrusprezecea cincisprezecea șaisprezecea șaptesprezecea optsprezecea nouăsprezecea +douăzecilea treizecilea patruzecilea cincizecilea șaizecilea șaptezecilea optzecilea nouăzecilea sutălea +douăzecea treizecea patruzecea cincizecea șaizecea șaptezecea optzecea nouăzecea suta +miilea mielea mia milionulea milioana miliardulea miliardelea miliarda enșpemia +""".split()) + + +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.lower() in _num_words: + return True + if text.lower() in _ordinal_words: + return True + return False + + +LEX_ATTRS = { + LIKE_NUM: like_num +} diff --git a/spacy/lang/ro/tokenizer_exceptions.py b/spacy/lang/ro/tokenizer_exceptions.py index 42ccd6a93..bc501c32a 100644 --- a/spacy/lang/ro/tokenizer_exceptions.py +++ b/spacy/lang/ro/tokenizer_exceptions.py @@ -9,8 +9,9 @@ _exc = {} # Source: https://en.wiktionary.org/wiki/Category:Romanian_abbreviations for orth in [ - "1-a", "1-ul", "10-a", "10-lea", "2-a", "3-a", "3-lea", "6-lea", - "d-voastră", "dvs.", "Rom.", "str."]: + "1-a", "2-a", "3-a", "4-a", "5-a", "6-a", "7-a", "8-a", "9-a", "10-a", "11-a", "12-a", + "1-ul", "2-lea", "3-lea", "4-lea", "5-lea", "6-lea", "7-lea", "8-lea", "9-lea", "10-lea", "11-lea", "12-lea", + "d-voastră", "dvs.", "ing.", "dr.", "Rom.", "str.", "nr.", "etc.", "d.p.d.v.", "dpdv", "șamd.", "ș.a.m.d."]: _exc[orth] = [{ORTH: orth}] diff --git a/spacy/tests/conftest.py b/spacy/tests/conftest.py index 67f7479d1..afb3ad5cd 100644 --- a/spacy/tests/conftest.py +++ b/spacy/tests/conftest.py @@ -15,7 +15,7 @@ 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', 'ru', 'sv', 'tr', 'ar', 'xx'] + 'it', 'nb', 'nl', 'pl', 'pt', 'ro', 'ru', 'sv', 'tr', 'ar', 'xx'] _models = {'en': ['en_core_web_sm'], 'de': ['de_core_news_md'], diff --git a/spacy/tests/lang/ro/test_tokenizer.py b/spacy/tests/lang/ro/test_tokenizer.py new file mode 100644 index 000000000..e754eaeae --- /dev/null +++ b/spacy/tests/lang/ro/test_tokenizer.py @@ -0,0 +1,25 @@ +# coding: utf8 +from __future__ import unicode_literals + +import pytest + +DEFAULT_TESTS = [ + ('Adresa este str. Principală nr. 5.', ['Adresa', 'este', 'str.', 'Principală', 'nr.', '5', '.']), + ('Teste, etc.', ['Teste', ',', 'etc.']), + ('Lista, ș.a.m.d.', ['Lista', ',', 'ș.a.m.d.']), + ('Și d.p.d.v. al...', ['Și', 'd.p.d.v.', 'al', '...']) +] + +NUMBER_TESTS = [ + ('Clasa a 4-a.', ['Clasa', 'a', '4-a', '.']), + ('Al 12-lea ceas.', ['Al', '12-lea', 'ceas', '.']) +] + +TESTCASES = DEFAULT_TESTS + NUMBER_TESTS + + +@pytest.mark.parametrize('text,expected_tokens', TESTCASES) +def test_tokenizer_handles_testcases(ro_tokenizer, text, expected_tokens): + tokens = ro_tokenizer(text) + token_list = [token.text for token in tokens if not token.is_space] + assert expected_tokens == token_list