diff --git a/num2words/base.py b/num2words/base.py index 48837b1..61b81b0 100644 --- a/num2words/base.py +++ b/num2words/base.py @@ -29,7 +29,6 @@ class Num2Word_Base(object): CURRENCY_ADJECTIVES = {} def __init__(self): - self.cards = OrderedDict() self.is_title = False self.precision = 2 self.exclude_title = [] @@ -40,21 +39,22 @@ class Num2Word_Base(object): self.errmsg_negord = "Cannot treat negative num %s as ordinal." self.errmsg_toobig = "abs(%s) must be less than %s." - self.base_setup() self.setup() - self.set_numwords() - self.MAXVAL = 1000 * list(self.cards.keys())[0] + # uses cards + if any(hasattr(self, field) for field in + ['high_numwords', 'mid_numwords', 'low_numwords']): + self.cards = OrderedDict() + self.set_numwords() + self.MAXVAL = 1000 * list(self.cards.keys())[0] def set_numwords(self): self.set_high_numwords(self.high_numwords) self.set_mid_numwords(self.mid_numwords) self.set_low_numwords(self.low_numwords) - def gen_high_numwords(self, units, tens, lows): - out = [u + t for t in tens for u in units] - out.reverse() - return out + lows + def set_high_numwords(self, *args): + raise NotImplementedError def set_mid_numwords(self, mid): for key, val in mid: @@ -102,8 +102,6 @@ class Num2Word_Base(object): except (ValueError, TypeError, AssertionError): return self.to_cardinal_float(value) - self.verify_num(value) - out = "" if value < 0: value = abs(value) @@ -197,9 +195,6 @@ class Num2Word_Base(object): if not abs(value) == value: raise TypeError(self.errmsg_negord % value) - def verify_num(self, value): - return 1 - def set_wordnums(self): pass @@ -264,6 +259,9 @@ class Num2Word_Base(object): def _cents_verbose(self, number, currency): return self.to_cardinal(number) + def _cents_terse(self, number, currency): + return "%02d" % number + def to_currency(self, val, currency='EUR', cents=True, seperator=',', adjective=False): """ @@ -292,7 +290,7 @@ class Num2Word_Base(object): minus_str = "%s " % self.negword if is_negative else "" cents_str = self._cents_verbose(right, currency) \ - if cents else "%02d" % right + if cents else self._cents_terse(right, currency) return u'%s%s %s%s %s %s' % ( minus_str, @@ -303,27 +301,5 @@ class Num2Word_Base(object): self.pluralize(right, cr2) ) - def base_setup(self): - pass - def setup(self): pass - - def test(self, value): - try: - _card = self.to_cardinal(value) - except Exception: - _card = "invalid" - - try: - _ord = self.to_ordinal(value) - except Exception: - _ord = "invalid" - - try: - _ordnum = self.to_ordinal_num(value) - except Exception: - _ordnum = "invalid" - - print("For %s, card is %s;\n\tord is %s; and\n\tordnum is %s." - % (value, _card, _ord, _ordnum)) diff --git a/num2words/lang_CZ.py b/num2words/lang_CZ.py index c94e2c5..0a29049 100644 --- a/num2words/lang_CZ.py +++ b/num2words/lang_CZ.py @@ -97,10 +97,6 @@ class Num2Word_CZ(Num2Word_Base): self.negword = "mínus" self.pointword = "celá" - def set_numwords(self): - # @FIXME - self.cards[0] = [] - def to_cardinal(self, number): n = str(number).replace(',', '.') if '.' in n: diff --git a/num2words/lang_DE.py b/num2words/lang_DE.py index e019e25..da2c2f1 100644 --- a/num2words/lang_DE.py +++ b/num2words/lang_DE.py @@ -21,12 +21,8 @@ from .lang_EU import Num2Word_EU class Num2Word_DE(Num2Word_EU): - def set_high_numwords(self, high): - max = 3 + 6 * len(high) - - for word, n in zip(high, range(max, 3, -6)): - self.cards[10 ** n] = word + "illiarde" - self.cards[10 ** (n - 3)] = word + "illion" + GIGA_SUFFIX = "illiarde" + MEGA_SUFFIX = "illion" def setup(self): self.negword = "minus " @@ -131,31 +127,3 @@ class Num2Word_DE(Num2Word_EU): if not (val // 100) % 10: return self.to_cardinal(val) return self.to_splitnum(val, hightxt="hundert", longval=longval) - - -n2w = Num2Word_DE() -to_card = n2w.to_cardinal -to_ord = n2w.to_ordinal -to_ordnum = n2w.to_ordinal_num - - -def main(): - for val in [1, 7, 8, 12, 17, 81, 91, 99, 100, 101, 102, 155, - 180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000, - 8280, 8291, 150000, 500000, 3000000, 1000000, 2000001, - 1000000000, 2000000000, -21212121211221211111, -2.121212, - -1.0000100]: - n2w.test(val) - - n2w.test(13253254360678768017687001076010010122121321432104732075403270570) - n2w.test(3000000) - n2w.test(3000000000001) - n2w.test(3000000324566) - print(n2w.to_currency(112121)) - print(n2w.to_year(2000)) - print(n2w.to_year(1820)) - print(n2w.to_year(2001)) - - -if __name__ == "__main__": - main() diff --git a/num2words/lang_DK.py b/num2words/lang_DK.py index 06ba56c..c1a8bb3 100644 --- a/num2words/lang_DK.py +++ b/num2words/lang_DK.py @@ -20,16 +20,14 @@ from . import lang_EU class Num2Word_DK(lang_EU.Num2Word_EU): - def set_high_numwords(self, high): - max = 3 + 6 * len(high) - for word, n in zip(high, range(max, 3, -6)): - self.cards[10 ** n] = word + "illarder" - self.cards[10 ** (n - 3)] = word + "illioner" + GIGA_SUFFIX = "illarder" + MEGA_SUFFIX = "illioner" def setup(self): + super(Num2Word_DK, self).setup() + self.negword = "minus " self.pointword = "komma" - self.errmsg_nornum = "Kun tal kan blive konverteret til ord." self.exclude_title = ["og", "komma", "minus"] self.mid_numwords = [(1000, "tusind"), (100, "hundrede"), @@ -131,27 +129,3 @@ class Num2Word_DK(lang_EU.Num2Word_EU): if not (val // 100) % 10: return self.to_cardinal(val) return self.to_splitnum(val, hightxt="hundrede", longval=longval) - - -n2w = Num2Word_DK() -to_card = n2w.to_cardinal -to_ord = n2w.to_ordinal -to_ordnum = n2w.to_ordinal_num -to_year = n2w.to_year - - -def main(): - for val in [1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155, - 180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000, - 8280, 8291, 150000, 500000, 1000000, 2000000, 2000001, - -21212121211221211111, -2.121212, -1.0000100]: - n2w.test(val) - n2w.test(13253254360678768017687001076010010122121321432104732075403270573) - for val in [1, 120, 160, 1000, 1120, 1800, 1976, 2000, 2010, 2099, 2171]: - print(val, "er", n2w.to_currency(val)) - print(val, "er", n2w.to_year(val)) - n2w.test(65132) - - -if __name__ == "__main__": - main() diff --git a/num2words/lang_EN.py b/num2words/lang_EN.py index d589254..d766aae 100644 --- a/num2words/lang_EN.py +++ b/num2words/lang_EN.py @@ -30,7 +30,6 @@ class Num2Word_EN(lang_EU.Num2Word_EU): self.negword = "minus " self.pointword = "point" - self.errmsg_nornum = "Only numbers may be converted to words." self.exclude_title = ["and", "point", "minus"] self.mid_numwords = [(1000, "thousand"), (100, "hundred"), diff --git a/num2words/lang_EN_IN.py b/num2words/lang_EN_IN.py index 88d1057..5911805 100644 --- a/num2words/lang_EN_IN.py +++ b/num2words/lang_EN_IN.py @@ -23,24 +23,3 @@ class Num2Word_EN_IN(Num2Word_EN): def set_high_numwords(self, high): self.cards[10 ** 7] = "crore" self.cards[10 ** 5] = "lakh" - - -n2w = Num2Word_EN_IN() -to_card = n2w.to_cardinal -to_ord = n2w.to_ordinal -to_ordnum = n2w.to_ordinal_num - - -def main(): - for val in (15000, - 15 * 10 ** 5, - 15 * 10 ** 6, - 15 * 10 ** 7, - 15 * 10 ** 8, - 15 * 10 ** 9, - 15 * 10 ** 10): - n2w.test(val) - - -if __name__ == "__main__": - main() diff --git a/num2words/lang_ES.py b/num2words/lang_ES.py index a123776..99f1ec0 100644 --- a/num2words/lang_ES.py +++ b/num2words/lang_ES.py @@ -29,11 +29,8 @@ class Num2Word_ES(Num2Word_EU): } # //CHECK: Is this sufficient?? - def set_high_numwords(self, high): - max = 3 + 6 * len(high) - - for word, n in zip(high, range(max, 3, -6)): - self.cards[10 ** (n - 3)] = word + "illón" + GIGA_SUFFIX = None + MEGA_SUFFIX = "illón" def setup(self): lows = ["cuatr", "tr", "b", "m"] diff --git a/num2words/lang_EU.py b/num2words/lang_EU.py index ddfee92..b46818d 100644 --- a/num2words/lang_EU.py +++ b/num2words/lang_EU.py @@ -51,18 +51,29 @@ class Num2Word_EU(Num2Word_Base): 'NOK': 'Norwegian', } - def set_high_numwords(self, high): - max = 3 + 6 * len(high) + GIGA_SUFFIX = "illiard" + MEGA_SUFFIX = "illion" - for word, n in zip(high, range(max, 3, -6)): - self.cards[10 ** n] = word + "illiard" - self.cards[10 ** (n - 3)] = word + "illion" + def set_high_numwords(self, high): + cap = 3 + 6 * len(high) + + for word, n in zip(high, range(cap, 3, -6)): + if self.GIGA_SUFFIX: + self.cards[10 ** n] = word + self.GIGA_SUFFIX + + if self.MEGA_SUFFIX: + self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX + + def gen_high_numwords(self, units, tens, lows): + out = [u + t for t in tens for u in units] + out.reverse() + return out + lows def pluralize(self, n, forms): form = 0 if n == 1 else 1 return forms[form] - def base_setup(self): + def setup(self): lows = ["non", "oct", "sept", "sext", "quint", "quadr", "tr", "b", "m"] units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept", "octo", "novem"] diff --git a/num2words/lang_FI.py b/num2words/lang_FI.py index 25921c5..3b6bae6 100644 --- a/num2words/lang_FI.py +++ b/num2words/lang_FI.py @@ -523,9 +523,10 @@ class Num2Word_FI(lang_EU.Num2Word_EU): self.ords[key] = val def setup(self): + super(Num2Word_FI, self).setup() + self.negword = "miinus " self.pointword = "pilkku" - self.errmsg_nornum = "Vain numerot voidaan muuttaa sanoiksi." self.exclude_title = ["pilkku", "miinus"] self.mid_numwords = [ @@ -646,8 +647,6 @@ class Num2Word_FI(lang_EU.Num2Word_EU): "cardinal floating point numbers.") return self.to_cardinal_float(value) - self.verify_num(value) - out = "" if value < 0: value = abs(value) diff --git a/num2words/lang_JA.py b/num2words/lang_JA.py index 1af9568..928dddf 100644 --- a/num2words/lang_JA.py +++ b/num2words/lang_JA.py @@ -353,6 +353,23 @@ class Num2Word_JA(Num2Word_Base): self.pointword = ("点", "てん") self.exclude_title = ["点", "マイナス"] + self.high_numwords = [ + ("万", "まん"), # 10**4 man + ("億", "おく"), # 10**8 oku + ("兆", "ちょう"), # 10**12 chō + ("京", "けい"), # 10**16 kei + ("垓", "がい"), # 10**20 gai + ("秭", "し"), # 10**24 shi + ("穣", "じょう"), # 10**28 jō + ("溝", "こう"), # 10**32 kō + ("澗", "かん"), # 10**36 kan + ("正", "せい"), # 10**40 sei + ("載", "さい"), # 10**44 sai + ("極", "ごく"), # 10**48 goku + ] + + self.high_numwords.reverse() + self.mid_numwords = [ (1000, ("千", "せん")), (100, ("百", "ひゃく")), @@ -502,23 +519,6 @@ class Num2Word_JA(Num2Word_Base): (cr2[1] if reading else cr2[0]) if cr2 else '', ) - def base_setup(self): - self.high_numwords = [ - ("万", "まん"), # 10**4 man - ("億", "おく"), # 10**8 oku - ("兆", "ちょう"), # 10**12 chō - ("京", "けい"), # 10**16 kei - ("垓", "がい"), # 10**20 gai - ("秭", "し"), # 10**24 shi - ("穣", "じょう"), # 10**28 jō - ("溝", "こう"), # 10**32 kō - ("澗", "かん"), # 10**36 kan - ("正", "せい"), # 10**40 sei - ("載", "さい"), # 10**44 sai - ("極", "ごく"), # 10**48 goku - ] - self.high_numwords.reverse() - def splitnum(self, value, reading, prefer): for elem in self.cards: if elem > value: @@ -553,8 +553,6 @@ class Num2Word_JA(Num2Word_Base): return self.to_cardinal_float(value, reading=reading, prefer=prefer) - self.verify_num(value) - out = "" if value < 0: value = abs(value) diff --git a/num2words/lang_LT.py b/num2words/lang_LT.py index 4a1d8a9..ddd003e 100644 --- a/num2words/lang_LT.py +++ b/num2words/lang_LT.py @@ -110,10 +110,6 @@ class Num2Word_LT(Num2Word_Base): self.negword = "minus" self.pointword = "kablelis" - def set_numwords(self): - # @FIXME - self.cards[0] = [] - def pluralize(self, n, forms): n1, n2, n3 = get_digits(n) if n2 == 1 or n1 == 0 or n == 0: diff --git a/num2words/lang_LV.py b/num2words/lang_LV.py index 55304b6..d1bd934 100644 --- a/num2words/lang_LV.py +++ b/num2words/lang_LV.py @@ -127,10 +127,6 @@ class Num2Word_LV(Num2Word_Base): self.negword = "mīnus" self.pointword = "komats" - def set_numwords(self): - # @FIXME - self.cards[0] = [] - def to_cardinal(self, number): n = str(number).replace(',', '.') base_str, n = self.parse_minus(n) diff --git a/num2words/lang_NL.py b/num2words/lang_NL.py index ccee1b7..b89dc4d 100644 --- a/num2words/lang_NL.py +++ b/num2words/lang_NL.py @@ -21,14 +21,12 @@ from .lang_EU import Num2Word_EU class Num2Word_NL(Num2Word_EU): - def set_high_numwords(self, high): - max = 3 + 6 * len(high) - - for word, n in zip(high, range(max, 3, -6)): - self.cards[10 ** n] = word + "iljard" - self.cards[10 ** (n - 3)] = word + "iljoen" + GIGA_SUFFIX = "iljard" + MEGA_SUFFIX = "iljoen" def setup(self): + super(Num2Word_NL, self).setup() + self.negword = "min " self.pointword = "komma" # "Cannot treat float %s as ordinal." @@ -142,30 +140,3 @@ class Num2Word_NL(Num2Word_EU): if not (val // 100) % 10: return self.to_cardinal(val) return self.to_splitnum(val, hightxt="honderd", longval=longval) - - -n2w = Num2Word_NL() -to_card = n2w.to_cardinal -to_ord = n2w.to_ordinal -to_ordnum = n2w.to_ordinal_num - - -def main(): - for val in [1, 7, 8, 12, 17, 62, 81, 91, 99, 100, 101, 102, 155, - 180, 300, 308, 832, 1000, 1001, 1061, 1062, 1100, 1500, 1701, - 3000, 8280, 8291, 150000, 500000, 3000000, 1000000, 2000001, - 1000000000, 2000000000, -21212121211221211111, -2.121212, - -1.0000100]: - n2w.test(val) - - n2w.test(3000000) - n2w.test(3000000000001) - n2w.test(3000000324566) - print(n2w.to_currency(112121)) - print(n2w.to_year(2000)) - print(n2w.to_year(1820)) - print(n2w.to_year(2001)) - - -if __name__ == "__main__": - main() diff --git a/num2words/lang_NO.py b/num2words/lang_NO.py index 1d47e96..5f252f4 100644 --- a/num2words/lang_NO.py +++ b/num2words/lang_NO.py @@ -20,16 +20,24 @@ from . import lang_EU class Num2Word_NO(lang_EU.Num2Word_EU): + GIGA_SUFFIX = "illard" + MEGA_SUFFIX = "illion" + def set_high_numwords(self, high): - max = 3 + 6 * len(high) - for word, n in zip(high, range(max, 3, -6)): - self.cards[10 ** n] = word + "illard" - self.cards[10 ** (n - 3)] = word + "illion" + cap = 3 + 6 * len(high) + + for word, n in zip(high, range(cap, 3, -6)): + if self.GIGA_SUFFIX: + self.cards[10 ** n] = word + self.GIGA_SUFFIX + + if self.MEGA_SUFFIX: + self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX def setup(self): + super(Num2Word_NO, self).setup() + self.negword = "minus " self.pointword = "komma" - self.errmsg_nornum = "Bare tall kan bli konvertert til ord." self.exclude_title = ["og", "komma", "minus"] self.mid_numwords = [(1000, "tusen"), (100, "hundre"), @@ -97,26 +105,3 @@ class Num2Word_NO(lang_EU.Num2Word_EU): def to_currency(self, val, longval=True): return self.to_splitnum(val, hightxt="krone/r", lowtxt="\xf8re/r", jointxt="og", longval=longval, cents=True) - - -n2w = Num2Word_NO() -to_card = n2w.to_cardinal -to_ord = n2w.to_ordinal -to_ordnum = n2w.to_ordinal_num -to_year = n2w.to_year - - -def main(): - for val in [1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155, - 180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000, - 8280, 8291, 150000, 500000, 1000000, 2000000, 2000001, - -21212121211221211111, -2.121212, -1.0000100]: - n2w.test(val) - n2w.test(13253254360678768017687001076010010122121321432104732075403270573) - for val in [1, 120, 1000, 1120, 1800, 1976, 2000, 2010, 2099, 2171]: - print(val, "er", n2w.to_currency(val)) - print(val, "er", n2w.to_year(val)) - - -if __name__ == "__main__": - main() diff --git a/num2words/lang_PL.py b/num2words/lang_PL.py index 7520e7d..4289177 100644 --- a/num2words/lang_PL.py +++ b/num2words/lang_PL.py @@ -97,10 +97,6 @@ class Num2Word_PL(Num2Word_Base): self.negword = "minus" self.pointword = "przecinek" - def set_numwords(self): - # @FIXME - self.cards[0] = [] - def to_cardinal(self, number): n = str(number).replace(',', '.') if '.' in n: diff --git a/num2words/lang_PT_BR.py b/num2words/lang_PT_BR.py index 0bb8f1a..8899a65 100644 --- a/num2words/lang_PT_BR.py +++ b/num2words/lang_PT_BR.py @@ -30,10 +30,10 @@ class Num2Word_PT_BR(lang_EU.Num2Word_EU): self.cards[10**n] = word + "ilhão" def setup(self): + super(Num2Word_PT_BR, self).setup() + self.negword = "menos " self.pointword = "vírgula" - self.errmsg_nornum = "Somente números podem ser convertidos para " \ - "palavras" self.exclude_title = ["e", "vírgula", "menos"] self.mid_numwords = [ diff --git a/num2words/lang_RU.py b/num2words/lang_RU.py index d6f7ba4..6461b35 100644 --- a/num2words/lang_RU.py +++ b/num2words/lang_RU.py @@ -109,10 +109,6 @@ class Num2Word_RU(Num2Word_Base): self.negword = "минус" self.pointword = "запятая" - def set_numwords(self): - # @FIXME - self.cards[0] = [] - def to_cardinal(self, number): n = str(number).replace(',', '.') if '.' in n: diff --git a/num2words/lang_SL.py b/num2words/lang_SL.py index 56c1a23..7b73304 100644 --- a/num2words/lang_SL.py +++ b/num2words/lang_SL.py @@ -24,14 +24,12 @@ from .lang_EU import Num2Word_EU class Num2Word_SL(Num2Word_EU): - def set_high_numwords(self, high): - max = 3 + 6*len(high) - - for word, n in zip(high, range(max, 3, -6)): - self.cards[10**n] = word + "iljard" - self.cards[10**(n-3)] = word + "iljon" + GIGA_SUFFIX = "iljard" + MEGA_SUFFIX = "iljon" def setup(self): + super(Num2Word_SL, self).setup() + self.negword = "minus " self.pointword = "celih" self.errmsg_nonnum = "Only numbers may be converted to words." @@ -143,25 +141,3 @@ class Num2Word_SL(Num2Word_EU): if not (val//100) % 10: return self.to_cardinal(val) return self.to_splitnum(val, hightxt="hundert", longval=longval) - - -n2w = Num2Word_SL() -to_card = n2w.to_cardinal -to_ord = n2w.to_ordinal -to_ordnum = n2w.to_ordinal_num - - -def main(): - for val in [1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155, - 180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000, - 8280, 8291, 150000, 500000, 1000000, 2000000, 2000001, - -21212121211221211111, -2.121212, -1.0000100]: - n2w.test(val) - - n2w.test(13253254360678768017687001076010010122121321432104732075403270573) - print(n2w.to_currency(112121)) - print(n2w.to_year(2000)) - - -if __name__ == "__main__": - main() diff --git a/num2words/lang_UK.py b/num2words/lang_UK.py index a730774..b751bed 100644 --- a/num2words/lang_UK.py +++ b/num2words/lang_UK.py @@ -110,10 +110,6 @@ class Num2Word_UK(Num2Word_Base): self.negword = "мiнус" self.pointword = "кома" - def set_numwords(self): - # @FIXME - self.cards[0] = [] - def to_cardinal(self, number): n = str(number).replace(',', '.') if '.' in n: diff --git a/tests/test_en.py b/tests/test_en.py index 2aae58e..069bb42 100644 --- a/tests/test_en.py +++ b/tests/test_en.py @@ -30,6 +30,15 @@ class Num2WordsENTest(TestCase): self.assertEqual(num2words(12.53), "twelve point five three") self.assertEqual(num2words(12.59), "twelve point five nine") + def test_overflow(self): + with self.assertRaises(OverflowError): + num2words("1000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000") + def test_to_currency(self): self.assertEqual( num2words('38.4', lang='en', to='currency', seperator=' and',