Repository: MycroftAI/lingua-franca

Issue:
PR#2347 Fix extractnumber_es, add extract_numbers_es
https://github.com/MycroftAI/mycroft-core/pull/2347


- Fix bug causing extractnumber_es to return a sum instead of a list
- Add Spanish parser to extract_numbers and extract_number


Comments:

Patch:
diff --git a/lingua_franca/lang/parse_es.py b/lingua_franca/lang/parse_es.py
index bebda23..d2ebea9 100644
--- a/lingua_franca/lang/parse_es.py
+++ b/lingua_franca/lang/parse_es.py
@@ -20,7 +20,8 @@
 """
 from datetime import datetime
 from dateutil.relativedelta import relativedelta
-from lingua_franca.lang.parse_common import is_numeric, look_for_fractions
+from lingua_franca.lang.format_es import pronounce_number_es
+from lingua_franca.lang.parse_common import *
 from lingua_franca.lang.common_data_es import _ARTICLES_ES, _NUM_STRING_ES
 
 
@@ -57,7 +58,12 @@ def isFractional_es(input_str):
     return False
 
 
-def extractnumber_es(text):
+# TODO: short_scale and ordinals don't do anything here.
+# The parameters are present in the function signature for API compatibility
+# reasons.
+#
+# Returns incorrect output on certain fractional phrases like, "cuarto de dos"
+def extractnumber_es(text, short_scale=True, ordinals=False):
     """
     This function prepares the given text for parsing by making
     numbers consistent, getting rid of contractions, etc.
@@ -108,7 +114,7 @@ def extractnumber_es(text):
                 result = 0
             # handle fractions
             if next_word != "avos":
-                result += val
+                result = val
             else:
                 result = float(result) / float(val)
 
@@ -263,6 +269,24 @@ def es_number_parse(words, i):
 
     return es_number(i)
 
+def extract_numbers_es(text, short_scale=True, ordinals=False):
+    """
+        Takes in a string and extracts a list of numbers.
+
+    Args:
+        text (str): the string to extract a number from
+        short_scale (bool): Use "short scale" or "long scale" for large
+            numbers -- over a million.  The default is short scale, which
+            is now common in most English speaking countries.
+            See https://en.wikipedia.org/wiki/Names_of_large_numbers
+        ordinals (bool): consider ordinal numbers, e.g. third=3 instead of 1/3
+    Returns:
+        list: list of extracted numbers as floats
+    """
+    return extract_numbers_generic(text, pronounce_number_es, extractnumber_es,
+                                   short_scale=short_scale, ordinals=ordinals)
+
+
 
 def normalize_es(text, remove_articles):
     """ Spanish string normalization """
diff --git a/lingua_franca/parse.py b/lingua_franca/parse.py
index 69b803d..bcb521f 100644
--- a/lingua_franca/parse.py
+++ b/lingua_franca/parse.py
@@ -105,6 +105,8 @@ def extract_numbers(text, short_scale=True, ordinals=False, lang=None):
         return extract_numbers_it(text, short_scale, ordinals)
     elif lang_code == "da":
         return extract_numbers_da(text, short_scale, ordinals)
+    elif lang_code == "es":
+        return extract_numbers_es(text, short_scale, ordinals)
     # TODO: extractnumbers_xx for other languages
     _log_unsupported_language(lang_code,
                               ['en', 'it', 'fr', 'de', 'da'])
@@ -145,8 +147,9 @@ def extract_number(text, short_scale=True, ordinals=False, lang=None):
         return extractnumber_de(text)
     elif lang_code == "da":
         return extractnumber_da(text)
+    elif lang_code == "es":
+        return extract_numbers_es(text, short_scale, ordinals)
     elif lang_code == "nl":
-        print("EXTRACTING NL")
         return extractnumber_nl(text, short_scale=short_scale,
                                 ordinals=ordinals)
     # TODO: extractnumber_xx for other languages


Test patch:
diff --git a/test/test_parse_es.py b/test/test_parse_es.py
index cb92e31..34e7472 100644
--- a/test/test_parse_es.py
+++ b/test/test_parse_es.py
@@ -16,13 +16,14 @@
 #
 import unittest
 
-from lingua_franca.parse import normalize
+from lingua_franca.parse import normalize, extract_numbers, extract_number
 
 
 class TestNormalize(unittest.TestCase):
     """
         Test cases for Spanish parsing
     """
+
     def test_articles_es(self):
         self.assertEqual(normalize("esta es la prueba", lang="es",
                                    remove_articles=True),
@@ -76,6 +77,15 @@ class TestNormalize(unittest.TestCase):
             lang="es"),
             "999999")
 
+    def test_extract_number_es(self):
+        self.assertEqual(sorted(extract_numbers(
+            "1 7 cuatro catorce ocho 157", lang='es')), [1, 4, 7, 8, 14, 157])
+        self.assertEqual(sorted(extract_numbers(
+            "1 7 cuatro albuquerque naranja John Doe catorce ocho 157",
+            lang='es')), [1, 4, 7, 8, 14, 157])
+        self.assertEqual(extract_number("seis punto dos", lang='es'), 6.2)
+        self.assertEqual(extract_numbers("un medio", lang='es'), [0.5])
+
 
 if __name__ == "__main__":
     unittest.main()