diff -Nru python-num2words-0.5.6/bin/num2words python-num2words-0.5.9/bin/num2words --- python-num2words-0.5.6/bin/num2words 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/bin/num2words 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +"""num2words: convert numbers into words. + +Usage: + num2words [options] + num2words --list-languages + num2words --list-converters + num2words --help + +Arguments: + Number you want to convert into words + +Options: + -L --list-languages Show all languages. + -C --list-converters Show all converters. + -l --lang= Output language [default: en]. + -t --to= Output converter [default: cardinal]. + -h --help Show this message. + -v --version Show version. + +Examples: + $ num2words 10001 + ten thousand and one + + $ num2words 24,120.10 + twenty-four thousand, one hundred and twenty point one + + $ num2words 24,120.10 -l es + veinticuatro mil ciento veinte punto uno + + $num2words 2.14 -l es --to currency + dos euros con catorce centimos +""" + +from __future__ import print_function, unicode_literals +import os +import sys +from docopt import docopt +import num2words + +__version__ = "0.5.9" +__license__ = "LGPL" + + +def get_languages(): + return sorted(list(num2words.CONVERTER_CLASSES.keys())) + + +def get_converters(): + return sorted(list(num2words.CONVERTES_TYPES)) + + +def main(): + version = "{}=={}".format(os.path.basename(__file__), __version__) + args = docopt(__doc__, argv=None, help=True, version=version, options_first=False) + if args["--list-languages"]: + for lang in get_languages(): + sys.stdout.write(lang) + sys.stdout.write(os.linesep) + sys.exit(0) + if args["--list-converters"]: + for lang in get_converters(): + sys.stdout.write(lang) + sys.stdout.write(os.linesep) + sys.exit(0) + try: + words = num2words.num2words(args[''], lang=args['--lang'], to=args['--to']) + sys.stdout.write(words+os.linesep) + sys.exit(0) + except Exception as err: + sys.stderr.write(str(args[''])) + sys.stderr.write(str(err) + os.linesep) + sys.stderr.write(__doc__) + sys.exit(1) + + +if __name__ == '__main__': + main() diff -Nru python-num2words-0.5.6/CHANGES.rst python-num2words-0.5.9/CHANGES.rst --- python-num2words-0.5.6/CHANGES.rst 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/CHANGES.rst 2019-01-11 01:09:08.000000000 +0000 @@ -1,6 +1,45 @@ Changelog ========= +Version 0.5.9 -- 2019/01/10 +--------------------------- + +* Fix encoding issue on release 0.5.8 (#229) +* Improve Polish localization (#228) + + +Version 0.5.8 -- 2018/11/17 +--------------------------- + +* Add Portuguese (Portugal) localization (#198) +* Add a command line tool to use num2words +* Use language iso code for Vietnamese +* Improve Korean localization (#219) +* Improve Serbian (Latin) localization (#207) +* Improve testing setup (#220) +* Improve German localization (#214) (#222) +* Improve Romanian localization (#215) +* Improve Spanish localization (#187) (#200) +* Improve Russian localization (#211) (#212) +* Improve French localization (23902ab) +* Improve Arabic localization (#176) +* Improve Lithuanian and Latvian localization (#185) +* Improve Ukrainian localization (#183) + + +Version 0.5.7 -- 2018/06/27 +--------------------------- + +* Add Finnish localization. (#170) +* Add Japanese localization. (#171) +* Add belgian-french localization. (#151) +* Add Czech localization. (#154) +* Add Thai localization. (#139) +* Improve English localization. (#144) +* Improve Spanish localization. (#167) +* Improve Italian localization. (#143) +* Improve documentation. (#155, #145, #174) + Version 0.5.6 -- 2017/11/22 --------------------------- diff -Nru python-num2words-0.5.6/CONTRIBUTING.md python-num2words-0.5.9/CONTRIBUTING.md --- python-num2words-0.5.6/CONTRIBUTING.md 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/CONTRIBUTING.md 2019-01-11 01:09:08.000000000 +0000 @@ -34,7 +34,7 @@ * Is the code PEP8 compliant? * Is the code covered by tests? -[TravisCI](https://travis-ci.org/) is configured to run those checks on every Pull-Request. It is recommanded you configure your fork to do the same. +[TravisCI](https://travis-ci.org/) is configured to run those checks on every Pull-Request. It is recommended you configure your fork to do the same. ### Reporting bugs diff -Nru python-num2words-0.5.6/.coveragerc python-num2words-0.5.9/.coveragerc --- python-num2words-0.5.6/.coveragerc 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/.coveragerc 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,5 @@ +[run] +branch = true +source = + num2words + tests diff -Nru python-num2words-0.5.6/debian/changelog python-num2words-0.5.9/debian/changelog --- python-num2words-0.5.6/debian/changelog 2021-01-04 16:38:55.000000000 +0000 +++ python-num2words-0.5.9/debian/changelog 2021-01-19 15:16:13.000000000 +0000 @@ -1,9 +1,28 @@ -python-num2words (0.5.6-1.1) unstable; urgency=medium +python-num2words (0.5.9-1) unstable; urgency=medium - * Non maintainer upload by the Reproducible Builds team. - * No source change upload to rebuild on buildd with .buildinfo files. + * Team upload. - -- Holger Levsen Mon, 04 Jan 2021 17:38:55 +0100 + [ Ondřej Nový ] + * d/control: Remove ancient X-Python3-Version field + * Use debhelper-compat instead of debian/compat. + * d/control: Update Maintainer field with new Debian Python Team + contact address. + * d/control: Update Vcs-* fields with new Debian Python Team Salsa + layout. + + [ Debian Janitor ] + * debian/copyright: use spaces rather than tabs to start continuation + lines. + * Bump debhelper from old 11 to 12. + * Set upstream metadata fields: Bug-Database, Bug-Submit, Repository, + Repository-Browse. + + [ Raphaël Hertzog ] + * New upstream version 0.5.9 + * Add python3-docopt to Build-Depends + * Disable CLI tests as we don't have python3-delegator in Debian + + -- Raphaël Hertzog Tue, 19 Jan 2021 16:16:13 +0100 python-num2words (0.5.6-1) unstable; urgency=medium diff -Nru python-num2words-0.5.6/debian/compat python-num2words-0.5.9/debian/compat --- python-num2words-0.5.6/debian/compat 2018-04-10 16:05:40.000000000 +0000 +++ python-num2words-0.5.9/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -11 diff -Nru python-num2words-0.5.6/debian/control python-num2words-0.5.9/debian/control --- python-num2words-0.5.6/debian/control 2018-04-10 16:05:40.000000000 +0000 +++ python-num2words-0.5.9/debian/control 2021-01-19 15:16:13.000000000 +0000 @@ -1,14 +1,13 @@ Source: python-num2words Section: python Priority: optional -Maintainer: Debian Python Modules Team +Maintainer: Debian Python Team Uploaders: Sophie Brun -Build-Depends: debhelper (>= 11), dh-python, python3-all, python3-setuptools +Build-Depends: debhelper-compat (= 12), dh-python, python3-all, python3-setuptools, python3-docopt Standards-Version: 4.1.4 Homepage: https://github.com/savoirfairelinux/num2words -X-Python3-Version: >= 3.2 -Vcs-Git: https://salsa.debian.org/python-team/modules/python-num2words.git -Vcs-Browser: https://salsa.debian.org/python-team/modules/python-num2words +Vcs-Git: https://salsa.debian.org/python-team/packages/python-num2words.git +Vcs-Browser: https://salsa.debian.org/python-team/packages/python-num2words Testsuite: autopkgtest-pkg-python Package: python3-num2words diff -Nru python-num2words-0.5.6/debian/copyright python-num2words-0.5.9/debian/copyright --- python-num2words-0.5.6/debian/copyright 2018-04-10 16:05:40.000000000 +0000 +++ python-num2words-0.5.9/debian/copyright 2021-01-19 15:16:13.000000000 +0000 @@ -4,7 +4,7 @@ Files: * Copyright: 2013-2015 Savoir-faire Linux inc. - 2017 Tufan Kaynak, Framras + 2017 Tufan Kaynak, Framras 2015 Blaz Bregar 2003 Taro Ogawa License: LGPL-2.1+ diff -Nru python-num2words-0.5.6/debian/patches/Disable-CLI-tests-as-we-don-t-have-python3-delegator-in-D.patch python-num2words-0.5.9/debian/patches/Disable-CLI-tests-as-we-don-t-have-python3-delegator-in-D.patch --- python-num2words-0.5.6/debian/patches/Disable-CLI-tests-as-we-don-t-have-python3-delegator-in-D.patch 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/debian/patches/Disable-CLI-tests-as-we-don-t-have-python3-delegator-in-D.patch 2021-01-19 15:16:13.000000000 +0000 @@ -0,0 +1,137 @@ +From: =?utf-8?q?Rapha=C3=ABl_Hertzog?= +Date: Tue, 19 Jan 2021 16:26:29 +0100 +Subject: Disable CLI tests as we don't have python3-delegator in Debian + +--- + setup.py | 1 - + tests/test_cli.py | 111 ------------------------------------------------------ + 2 files changed, 112 deletions(-) + delete mode 100644 tests/test_cli.py + +diff --git a/setup.py b/setup.py +index fbc34f7..a830169 100644 +--- a/setup.py ++++ b/setup.py +@@ -75,5 +75,4 @@ setup( + classifiers=CLASSIFIERS, + scripts=['bin/num2words'], + install_requires=["docopt>=0.6.2"], +- tests_require=['delegator.py'], + ) +diff --git a/tests/test_cli.py b/tests/test_cli.py +deleted file mode 100644 +index 484a8dc..0000000 +--- a/tests/test_cli.py ++++ /dev/null +@@ -1,111 +0,0 @@ +-#!/usr/bin/env python +-# -*- coding: utf-8 -*- +-# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +-# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. +- +-# This library is free software; you can redistribute it and/or +-# modify it under the terms of the GNU Lesser General Public +-# License as published by the Free Software Foundation; either +-# version 2.1 of the License, or (at your option) any later version. +-# This library 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 +-# Lesser General Public License for more details. +-# You should have received a copy of the GNU Lesser General Public +-# License along with this library; if not, write to the Free Software +-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +-# MA 02110-1301 USA +- +-from __future__ import unicode_literals +- +-import os +-import unittest +- +-import delegator +-import num2words +- +- +-class CliCaller(object): +- +- def __init__(self): +- self.cmd = os.path.realpath(os.path.join(os.path.dirname(__file__), +- "..", "bin", "num2words")) +- self.cmd_list = ["python", self.cmd] +- +- def run_cmd(self, *args): +- cmd_list = self.cmd_list + [str(arg) for arg in args] +- cmd = " ".join(cmd_list) +- return delegator.run(cmd) +- +- +-class CliTestCase(unittest.TestCase): +- """Test the command line app""" +- +- def setUp(self): +- self.cli = CliCaller() +- +- def test_cli_help(self): +- """num2words without arguments should exit with status 1 +- and show docopt's default short usage message +- """ +- output = self.cli.run_cmd() +- self.assertEqual(output.return_code, 1) +- self.assertTrue(output.err.startswith('Usage:')) +- +- def test_cli_list_langs(self): +- """You should be able to list all availabe languages +- """ +- output = self.cli.run_cmd('--list-languages') +- self.assertEqual( +- sorted(list(num2words.CONVERTER_CLASSES.keys())), +- output.out.strip().split(os.linesep) +- ) +- output = self.cli.run_cmd('-L') +- self.assertEqual( +- sorted(list(num2words.CONVERTER_CLASSES.keys())), +- output.out.strip().split(os.linesep) +- ) +- +- def test_cli_list_converters(self): +- """You should be able to list all available converters +- """ +- output = self.cli.run_cmd('--list-converters') +- self.assertEqual( +- sorted(list(num2words.CONVERTES_TYPES)), +- output.out.strip().split(os.linesep) +- ) +- output = self.cli.run_cmd('-C') +- self.assertEqual( +- sorted(list(num2words.CONVERTES_TYPES)), +- output.out.strip().split(os.linesep) +- ) +- +- def test_cli_default_lang(self): +- """Default to english +- """ +- output = self.cli.run_cmd(150) +- self.assertEqual(output.return_code, 0) +- self.assertEqual( +- output.out.strip(), +- "one hundred and fifty point zero" +- ) +- +- def test_cli_with_lang(self): +- """You should be able to specify a language +- """ +- output = self.cli.run_cmd(150, '--lang', 'es') +- self.assertEqual(output.return_code, 0) +- self.assertEqual( +- output.out.strip(), +- "ciento cincuenta punto cero" +- ) +- +- def test_cli_with_lang_to(self): +- """You should be able to specify a language +- """ +- output = self.cli.run_cmd(150.55, '--lang', 'es', '--to', 'currency') +- self.assertEqual(output.return_code, 0) +- self.assertEqual( +- output.out.strip(), +- "ciento cincuenta euros con cincuenta y cinco centimos" +- ) diff -Nru python-num2words-0.5.6/debian/patches/series python-num2words-0.5.9/debian/patches/series --- python-num2words-0.5.6/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/debian/patches/series 2021-01-19 15:16:13.000000000 +0000 @@ -0,0 +1 @@ +Disable-CLI-tests-as-we-don-t-have-python3-delegator-in-D.patch diff -Nru python-num2words-0.5.6/debian/upstream/metadata python-num2words-0.5.9/debian/upstream/metadata --- python-num2words-0.5.6/debian/upstream/metadata 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/debian/upstream/metadata 2021-01-19 15:16:13.000000000 +0000 @@ -0,0 +1,4 @@ +Bug-Database: https://github.com/savoirfairelinux/num2words/issues +Bug-Submit: https://github.com/savoirfairelinux/num2words/issues/new +Repository: https://github.com/savoirfairelinux/num2words.git +Repository-Browse: https://github.com/savoirfairelinux/num2words diff -Nru python-num2words-0.5.6/docker-compose.yml python-num2words-0.5.9/docker-compose.yml --- python-num2words-0.5.6/docker-compose.yml 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/docker-compose.yml 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,7 @@ +version: '3.0' +services: + web: + image: python:3-alpine + command: python3 -m http.server 8080 + volumes: + - .:/num2words diff -Nru python-num2words-0.5.6/.gitignore python-num2words-0.5.9/.gitignore --- python-num2words-0.5.6/.gitignore 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/.gitignore 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,6 @@ *.pyc build dist +.idea/ *.egg-info /.tox diff -Nru python-num2words-0.5.6/MANIFEST.in python-num2words-0.5.9/MANIFEST.in --- python-num2words-0.5.6/MANIFEST.in 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/MANIFEST.in 2019-01-11 01:09:08.000000000 +0000 @@ -1,3 +1,4 @@ include CHANGES.rst include COPYING include tests/* +include bin/num2words diff -Nru python-num2words-0.5.6/num2words/base.py python-num2words-0.5.9/num2words/base.py --- python-num2words-0.5.6/num2words/base.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/base.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -29,7 +30,6 @@ CURRENCY_ADJECTIVES = {} def __init__(self): - self.cards = OrderedDict() self.is_title = False self.precision = 2 self.exclude_title = [] @@ -40,21 +40,22 @@ 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: @@ -89,14 +90,19 @@ return out + def parse_minus(self, num_str): + """Detach minus and return it as symbol with new num_str.""" + if num_str.startswith('-'): + # Extra spacing to compensate if there is no minus. + return '%s ' % self.negword, num_str[1:] + return '', num_str + def to_cardinal(self, value): try: assert int(value) == value except (ValueError, TypeError, AssertionError): return self.to_cardinal_float(value) - self.verify_num(value) - out = "" if value < 0: value = abs(value) @@ -190,12 +196,6 @@ if not abs(value) == value: raise TypeError(self.errmsg_negord % value) - def verify_num(self, value): - return 1 - - def set_wordnums(self): - pass - def to_ordinal(self, value): return self.to_cardinal(value) @@ -257,6 +257,9 @@ 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): """ @@ -285,7 +288,7 @@ 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, @@ -296,27 +299,5 @@ 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 -Nru python-num2words-0.5.6/num2words/compat.py python-num2words-0.5.9/num2words/compat.py --- python-num2words-0.5.6/num2words/compat.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/compat.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,6 @@ +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. -# Copyright (c) 2016, Savoir-faire Linux inc. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -15,6 +16,12 @@ # MA 02110-1301 USA +try: + strtype = basestring +except NameError: + strtype = str + + def to_s(val): try: return unicode(val) diff -Nru python-num2words-0.5.6/num2words/currency.py python-num2words-0.5.9/num2words/currency.py --- python-num2words-0.5.6/num2words/currency.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/currency.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,39 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + from __future__ import division -from decimal import Decimal +from decimal import ROUND_HALF_UP, Decimal -def parse_currency_parts(value): +def parse_currency_parts(value, is_int_with_cents=True): if isinstance(value, int): - # assume cents if value is integer - negative = value < 0 - value = abs(value) - integer, cents = divmod(value, 100) + if is_int_with_cents: + # assume cents if value is integer + negative = value < 0 + value = abs(value) + integer, cents = divmod(value, 100) + else: + negative = value < 0 + integer, cents = abs(value), 0 - elif isinstance(value, Decimal): + else: + value = Decimal(value) + value = value.quantize( + Decimal('.01'), + rounding=ROUND_HALF_UP + ) negative = value < 0 value = abs(value) integer, fraction = divmod(value, 1) integer = int(integer) cents = int(fraction * 100) - else: - # @TODO consider using something (babel) that does locale aware parsing - value = str(value).replace(',', '.') - negative = value.startswith('-') - - if negative: - value = value.lstrip('-') - - if '.' in value: - integer, fraction = value.rsplit('.', 1) - fraction = fraction.ljust(2, "0") - else: - integer, fraction = value, 0 - - integer = int(integer) - cents = int(fraction) - return integer, cents, negative diff -Nru python-num2words-0.5.6/num2words/__init__.py python-num2words-0.5.9/num2words/__init__.py --- python-num2words-0.5.6/num2words/__init__.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/__init__.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -17,54 +18,72 @@ from __future__ import unicode_literals from . import lang_AR +from . import lang_CZ from . import lang_EN from . import lang_EN_IN from . import lang_FR from . import lang_FR_CH +from . import lang_FR_BE from . import lang_FR_DZ from . import lang_DE from . import lang_ES +from . import lang_FI from . import lang_LT from . import lang_LV from . import lang_PL +from . import lang_RO from . import lang_RU from . import lang_ID +from . import lang_JA from . import lang_NO from . import lang_DK +from . import lang_PT from . import lang_PT_BR from . import lang_HE from . import lang_IT from . import lang_ES_VE from . import lang_ES_CO -from . import lang_VN +from . import lang_VI from . import lang_TR from . import lang_NL from . import lang_UK from . import lang_SL +from . import lang_SR +from . import lang_TH +from . import lang_KO CONVERTER_CLASSES = { 'ar': lang_AR.Num2Word_AR(), + 'cz': lang_CZ.Num2Word_CZ(), 'en': lang_EN.Num2Word_EN(), 'en_IN': lang_EN_IN.Num2Word_EN_IN(), 'fr': lang_FR.Num2Word_FR(), 'fr_CH': lang_FR_CH.Num2Word_FR_CH(), + 'fr_BE': lang_FR_BE.Num2Word_FR_BE(), 'fr_DZ': lang_FR_DZ.Num2Word_FR_DZ(), 'de': lang_DE.Num2Word_DE(), + 'fi': lang_FI.Num2Word_FI(), 'es': lang_ES.Num2Word_ES(), 'es_CO': lang_ES_CO.Num2Word_ES_CO(), 'es_VE': lang_ES_VE.Num2Word_ES_VE(), 'id': lang_ID.Num2Word_ID(), + 'ja': lang_JA.Num2Word_JA(), + 'ko': lang_KO.Num2Word_KO(), 'lt': lang_LT.Num2Word_LT(), 'lv': lang_LV.Num2Word_LV(), 'pl': lang_PL.Num2Word_PL(), + 'ro': lang_RO.Num2Word_RO(), 'ru': lang_RU.Num2Word_RU(), 'sl': lang_SL.Num2Word_SL(), + 'sr': lang_SR.Num2Word_SR(), 'no': lang_NO.Num2Word_NO(), 'dk': lang_DK.Num2Word_DK(), + 'pt': lang_PT.Num2Word_PT(), 'pt_BR': lang_PT_BR.Num2Word_PT_BR(), 'he': lang_HE.Num2Word_HE(), 'it': lang_IT.Num2Word_IT(), - 'vi_VN': lang_VN.Num2Word_VN(), + 'vi': lang_VI.Num2Word_VI(), + 'th': lang_TH.Num2Word_TH(), 'tr': lang_TR.Num2Word_TR(), 'nl': lang_NL.Num2Word_NL(), 'uk': lang_UK.Num2Word_UK() diff -Nru python-num2words-0.5.6/num2words/lang_AR.py python-num2words-0.5.9/num2words/lang_AR.py --- python-num2words-0.5.6/num2words/lang_AR.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_AR.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. +# Copyright (c) 2018, Abdullah Alhazmy, Alhazmy13. All Rights Reserved. + # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -15,106 +17,336 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA -from __future__ import division, print_function, unicode_literals - -from . import lang_EU - - -class Num2Word_AR(lang_EU.Num2Word_EU): - def set_high_numwords(self, high): - max = 3 + 3 * len(high) - for word, n in zip(high, range(max, 3, -3)): - self.cards[10 ** n] = word + "illion" - - def setup(self): - self.negword = "سالب " - self.pointword = "فاصلة" - self.errmsg_nornum = "Only numbers may be converted to words." - self.exclude_title = ["و", "فاصلة", "سالب"] - - self.mid_numwords = [(1000000, "مليون"), (1000, "ألف"), (100, "مئة"), - (90, "تسعين"), (80, "ثمانين"), (70, "سبعين"), - (60, "ستين"), (50, "خمسين"), (40, "أربعين"), - (30, "ثلاثين")] - self.low_numwords = ["عشرين", "تسعة عشر", "ثمانية عشر", "سبعة عشر", - "ستة عشر", "خمسة عشر", "أربعة عشر", "ثلاثة عشر", - "اثناعشر", "أحد عشر", "عشرة", "تسعة", "ثمانية", - "سبعة", "ستة", "خمسة", "أربعة", "ثلاثة", "اثنين", - "واحد", "صفر"] - self.ords = {"واحد": "أول", - "اثنين": "ثاني", - "ثلاثة": "ثالث", - "أربعة": "رابع", - "خمسة": "خامس", - "ثمانية": "ثامن", - "تسعة": "تاسع", - "اثناعشر": "ثاني عشر"} - - def merge(self, lpair, rpair): - ltext, lnum = lpair - rtext, rnum = rpair - if lnum == 1 and rnum < 100: - return (rtext, rnum) - elif 100 > lnum > rnum: - return ("%s و%s" % (rtext, ltext), rnum + lnum) - elif lnum >= 100 > rnum: - return ("%s و %s" % (ltext, rtext), lnum + rnum) - elif rnum > lnum: - if lnum == 1 and rnum in [100, 1000, 1000000]: - return ("%s" % (rtext), rnum * lnum) - if lnum == 2 and rnum == 100: - return ("مئتين", rnum * lnum) - if lnum == 2 and rnum in [100, 1000]: - return ("%sين" % (rtext), rnum * lnum) - return ("%s %s" % (ltext, rtext), lnum * rnum) - return ("%s، %s" % (ltext, rtext), lnum + rnum) - - def to_ordinal(self, value): - self.verify_ordinal(value) - outwords = self.to_cardinal(value).split(" ") - lastwords = outwords[-1].split("-") - lastword = lastwords[-1].lower() - try: - lastword = self.ords[lastword] - except KeyError: - lastword += "" - lastwords[-1] = self.title(lastword) - outwords[-1] = "،".join(lastwords) - return " ".join(outwords) +import re +from decimal import Decimal +from math import floor + +CURRENCY_SR = [("ريال", "ريالان", "ريالات", "ريالاً"), + ("هللة", "هللتان", "هللات", "هللة")] +CURRENCY_EGP = [("جنيه", "جنيهان", "جنيهات", "جنيهاً"), + ("قرش", "قرشان", "قروش", "قرش")] +CURRENCY_KWD = [("دينار", "ديناران", "دينارات", "ديناراً"), + ("فلس", "فلسان", "فلس", "فلس")] + +ARABIC_ONES = [ + "", "واحد", "اثنان", "ثلاثة", "أربعة", "خمسة", "ستة", "سبعة", "ثمانية", + "تسعة", + "عشرة", "أحد عشر", "اثنا عشر", "ثلاثة عشر", "أربعة عشر", "خمسة عشر", + "ستة عشر", "سبعة عشر", "ثمانية عشر", + "تسعة عشر" +] + + +class Num2Word_AR(object): + errmsg_too_big = "Too large" + max_num = 10 ** 36 + + def __init__(self): + self.number = 0 + self.arabicPrefixText = "" + self.arabicSuffixText = "" + self.integer_value = 0 + self._decimalValue = "" + self.partPrecision = 2 + self.currency_unit = CURRENCY_SR[0] + self.currency_subunit = CURRENCY_SR[1] + self.isCurrencyPartNameFeminine = True + self.isCurrencyNameFeminine = False + self.separator = 'و' + + self.arabicOnes = ARABIC_ONES + self.arabicFeminineOnes = [ + "", "إحدى", "اثنتان", "ثلاث", "أربع", "خمس", "ست", "سبع", "ثمان", + "تسع", + "عشر", "إحدى عشرة", "اثنتا عشرة", "ثلاث عشرة", "أربع عشرة", + "خمس عشرة", "ست عشرة", "سبع عشرة", "ثماني عشرة", + "تسع عشرة" + ] + self.arabicOrdinal = [ + "", "اول", "ثاني", "ثالث", "رابع", "خامس", "سادس", "سابع", "ثامن", + "تاسع", "عاشر", "حادي عشر", "ثاني عشر", "ثالث عشر", "رابع عشر", + "خامس عشر", "سادس عشر", "سابع عشر", "ثامن عشر", "تاسع عشر" + ] + self.arabicTens = [ + "عشرون", "ثلاثون", "أربعون", "خمسون", "ستون", "سبعون", "ثمانون", + "تسعون" + ] + self.arabicHundreds = [ + "", "مائة", "مئتان", "ثلاثمائة", "أربعمائة", "خمسمائة", "ستمائة", + "سبعمائة", "ثمانمائة", "تسعمائة" + ] + self.arabicAppendedTwos = [ + "مئتا", "ألفا", "مليونا", "مليارا", "تريليونا", "كوادريليونا", + "كوينتليونا", "سكستيليونا" + ] + self.arabicTwos = [ + "مئتان", "ألفان", "مليونان", "ملياران", "تريليونان", + "كوادريليونان", "كوينتليونان", "سكستيليونان" + ] + self.arabicGroup = [ + "مائة", "ألف", "مليون", "مليار", "تريليون", "كوادريليون", + "كوينتليون", "سكستيليون" + ] + self.arabicAppendedGroup = [ + "", "ألفاً", "مليوناً", "ملياراً", "تريليوناً", "كوادريليوناً", + "كوينتليوناً", "سكستيليوناً" + ] + self.arabicPluralGroups = [ + "", "آلاف", "ملايين", "مليارات", "تريليونات", "كوادريليونات", + "كوينتليونات", "سكستيليونات" + ] + + def number_to_arabic(self, arabic_prefix_text, arabic_suffix_text): + self.arabicPrefixText = arabic_prefix_text + self.arabicSuffixText = arabic_suffix_text + self.extract_integer_and_decimal_parts() + + def extract_integer_and_decimal_parts(self): + re.split('\\.', str(self.number)) + splits = re.split('\\.', str(self.number)) + + self.integer_value = int(splits[0]) + if len(splits) > 1: + self._decimalValue = int(self.decimal_value(splits[1])) + else: + self._decimalValue = 0 + + def decimal_value(self, decimal_part): + + if self.partPrecision is not len(decimal_part): + decimal_part_length = len(decimal_part) + + decimal_part_builder = decimal_part + for i in range(0, self.partPrecision - decimal_part_length): + decimal_part_builder += '0' + decimal_part = decimal_part_builder + + if len(decimal_part) <= self.partPrecision: + dec = len(decimal_part) + else: + dec = self.partPrecision + result = decimal_part[0: dec] + else: + result = decimal_part + + for i in range(len(result), self.partPrecision): + result += '0' + return result + + def digit_feminine_status(self, digit, group_level): + if group_level == -1: + if self.isCurrencyPartNameFeminine: + return self.arabicFeminineOnes[int(digit)] + else: + return self.arabicOnes[int(digit)] + elif group_level == 0: + if self.isCurrencyNameFeminine: + return self.arabicFeminineOnes[int(digit)] + else: + return self.arabicOnes[int(digit)] + + else: + return self.arabicOnes[int(digit)] + + def process_arabic_group(self, group_number, group_level, + remaining_number): + tens = Decimal(group_number) % Decimal(100) + hundreds = Decimal(group_number) / Decimal(100) + ret_val = "" + + if int(hundreds) > 0: + if tens == 0 and int(hundreds) == 2: + ret_val = "{}".format(self.arabicAppendedTwos[0]) + else: + ret_val = "{}".format(self.arabicHundreds[int(hundreds)]) + + if tens > 0: + if tens < 20: + if tens == 2 and int(hundreds) == 0 and group_level > 0: + if self.integer_value in [2000, 2000000, 2000000000, + 2000000000000, 2000000000000000, + 2000000000000000000]: + ret_val = "{}".format( + self.arabicAppendedTwos[int(group_level)]) + else: + ret_val = "{}".format( + self.arabicTwos[int(group_level)]) + else: + if ret_val != "": + ret_val += " و " + + if tens == 1 and group_level > 0 and hundreds == 0: + ret_val += "" + elif (tens == 1 or tens == 2) and ( + group_level == 0 or group_level == -1) and \ + hundreds == 0 and remaining_number == 0: + ret_val += "" + else: + ret_val += self.digit_feminine_status(int(tens), + group_level) + else: + ones = tens % 10 + tens = (tens / 10) - 2 + if ones > 0: + if ret_val is not "" and tens < 4: + ret_val += " و " + + ret_val += self.digit_feminine_status(ones, group_level) + if ret_val is not "" and ones != 0: + ret_val += " و " + + ret_val += self.arabicTens[int(tens)] + + return ret_val + + def convert(self, value): + self.number = "{:.9f}".format(value) + self.number_to_arabic(self.arabicPrefixText, self.arabicSuffixText) + return self.convert_to_arabic() + + def convert_to_arabic(self): + temp_number = Decimal(self.number) + + if temp_number == Decimal(0): + return "صفر" + + decimal_string = self.process_arabic_group(self._decimalValue, + -1, + Decimal(0)) + ret_val = "" + group = 0 + + while temp_number > Decimal(0): + + number_to_process = int( + Decimal(str(temp_number)) % Decimal(str(1000))) + temp_number = int(Decimal(temp_number) / Decimal(1000)) + + group_description = \ + self.process_arabic_group(number_to_process, + group, + Decimal(floor(temp_number))) + if group_description is not '': + if group > 0: + if ret_val is not "": + ret_val = "{} و {}".format("", ret_val) + if number_to_process != 2: + if number_to_process % 100 != 1: + if 3 <= number_to_process <= 10: + ret_val = "{} {}".format( + self.arabicPluralGroups[group], ret_val) + else: + if ret_val is not "": + ret_val = "{} {}".format( + self.arabicAppendedGroup[group], + ret_val) + else: + ret_val = "{} {}".format( + self.arabicGroup[group], ret_val) + + else: + ret_val = "{} {}".format(self.arabicGroup[group], + ret_val) + ret_val = "{} {}".format(group_description, ret_val) + group += 1 + formatted_number = "" + if self.arabicPrefixText is not "": + formatted_number += "{} ".format(self.arabicPrefixText) + formatted_number += ret_val + if self.integer_value != 0: + remaining100 = int(self.integer_value % 100) + + if remaining100 == 0: + formatted_number += self.currency_unit[0] + elif remaining100 == 1: + formatted_number += self.currency_unit[0] + elif remaining100 == 2: + if self.integer_value == 2: + formatted_number += self.currency_unit[1] + else: + formatted_number += self.currency_unit[0] + elif 3 <= remaining100 <= 10: + formatted_number += self.currency_unit[2] + elif 11 <= remaining100 <= 99: + formatted_number += self.currency_unit[3] + if self._decimalValue != 0: + formatted_number += " {} ".format(self.separator) + formatted_number += decimal_string + + if self._decimalValue != 0: + formatted_number += " " + remaining100 = int(self._decimalValue % 100) + + if remaining100 == 0: + formatted_number += self.currency_subunit[0] + elif remaining100 == 1: + formatted_number += self.currency_subunit[0] + elif remaining100 == 2: + formatted_number += self.currency_subunit[1] + elif 3 <= remaining100 <= 10: + formatted_number += self.currency_subunit[2] + elif 11 <= remaining100 <= 99: + formatted_number += self.currency_subunit[3] + + if self.arabicSuffixText is not "": + formatted_number += " {}".format(self.arabicSuffixText) + + return formatted_number + + def validate_number(self, number): + if number >= self.max_num: + raise OverflowError(self.errmsg_too_big) + return number + + def set_currency_prefer(self, currency): + if currency is 'EGP': + self.currency_unit = CURRENCY_EGP[0] + self.currency_subunit = CURRENCY_EGP[1] + elif currency is 'KWD': + self.currency_unit = CURRENCY_KWD[0] + self.currency_subunit = CURRENCY_KWD[1] + else: + self.currency_unit = CURRENCY_SR[0] + self.currency_subunit = CURRENCY_SR[1] + + def to_currency(self, value, currency='SR', prefix='', suffix=''): + self.set_currency_prefer(currency) + self.isCurrencyNameFeminine = False + self.separator = "و" + self.arabicOnes = ARABIC_ONES + self.arabicPrefixText = prefix + self.arabicSuffixText = suffix + return self.convert(value=value) + + def to_ordinal(self, number, prefix=''): + if number <= 19: + return "{}".format(self.arabicOrdinal[number]) + if number < 100: + self.isCurrencyNameFeminine = True + else: + self.isCurrencyNameFeminine = False + self.currency_subunit = ('', '', '', '') + self.currency_unit = ('', '', '', '') + self.arabicPrefixText = prefix + self.arabicSuffixText = "" + return "{}".format(self.convert(abs(number)).strip()) + + def to_year(self, value): + value = self.validate_number(value) + return self.to_cardinal(value) def to_ordinal_num(self, value): - self.verify_ordinal(value) - return "%s%s" % (value, self.to_ordinal(value)[-2:]) - - def to_year(self, val, longval=True): - if not (val // 100) % 10: - return self.to_cardinal(val) - return self.to_splitnum(val, hightxt="مئة", jointxt="و", - longval=longval) - - def to_currency(self, val, longval=True): - return self.to_splitnum(val, hightxt="ريال", lowtxt="هللة", - jointxt="و", longval=longval, cents=True) - - -n2w = Num2Word_AR() -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, "is", n2w.to_currency(val)) - print(val, "is", n2w.to_year(val)) - + return self.to_ordinal(value).strip() -if __name__ == "__main__": - main() + def to_cardinal(self, number): + number = self.validate_number(number) + minus = '' + if number < 0: + minus = 'سالب ' + self.separator = ',' + self.currency_subunit = ('', '', '', '') + self.currency_unit = ('', '', '', '') + self.arabicPrefixText = "" + self.arabicSuffixText = "" + self.arabicOnes = ARABIC_ONES + return minus + self.convert(value=abs(number)).strip() diff -Nru python-num2words-0.5.6/num2words/lang_CZ.py python-num2words-0.5.9/num2words/lang_CZ.py --- python-num2words-0.5.6/num2words/lang_CZ.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_CZ.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +from .base import Num2Word_Base +from .utils import get_digits, splitbyx + +ZERO = ('nula',) + +ONES = { + 1: ('jedna',), + 2: ('dva',), + 3: ('tři',), + 4: ('čtyři',), + 5: ('pět',), + 6: ('šest',), + 7: ('sedm',), + 8: ('osm',), + 9: ('devět',), +} + +TENS = { + 0: ('deset',), + 1: ('jedenáct',), + 2: ('dvanáct',), + 3: ('třináct',), + 4: ('čtrnáct',), + 5: ('patnáct',), + 6: ('šestnáct',), + 7: ('sedmnáct',), + 8: ('osmnáct',), + 9: ('devatenáct',), +} + +TWENTIES = { + 2: ('dvacet',), + 3: ('třicet',), + 4: ('čtyřicet',), + 5: ('padesát',), + 6: ('šedesát',), + 7: ('sedmdesát',), + 8: ('osmdesát',), + 9: ('devadesát',), +} + +HUNDREDS = { + 1: ('sto',), + 2: ('dvěstě',), + 3: ('třista',), + 4: ('čtyřista',), + 5: ('pětset',), + 6: ('šestset',), + 7: ('sedmset',), + 8: ('osmset',), + 9: ('devětset',), +} + +THOUSANDS = { + 1: ('tisíc', 'tisíce', 'tisíc'), # 10^3 + 2: ('milion', 'miliony', 'milionů'), # 10^6 + 3: ('miliarda', 'miliardy', 'miliard'), # 10^9 + 4: ('bilion', 'biliony', 'bilionů'), # 10^12 + 5: ('biliarda', 'biliardy', 'biliard'), # 10^15 + 6: ('trilion', 'triliony', 'trilionů'), # 10^18 + 7: ('triliarda', 'triliardy', 'triliard'), # 10^21 + 8: ('kvadrilion', 'kvadriliony', 'kvadrilionů'), # 10^24 + 9: ('kvadriliarda', 'kvadriliardy', 'kvadriliard'), # 10^27 + 10: ('quintillion', 'quintilliony', 'quintillionů'), # 10^30 +} + + +class Num2Word_CZ(Num2Word_Base): + CURRENCY_FORMS = { + 'CZK': ( + ('koruna', 'koruny', 'korun'), ('halíř', 'halíře', 'haléřů') + ), + 'EUR': ( + ('euro', 'euro', 'euro'), ('cent', 'centy', 'centů') + ), + } + + def setup(self): + self.negword = "mínus" + self.pointword = "celá" + + def to_cardinal(self, number): + n = str(number).replace(',', '.') + if '.' in n: + left, right = n.split('.') + return u'%s %s %s' % ( + self._int2word(int(left)), + self.pointword, + self._int2word(int(right)) + ) + else: + return self._int2word(int(n)) + + def pluralize(self, n, forms): + if n == 1: + form = 0 + elif 5 > n % 10 > 1 and (n % 100 < 10 or n % 100 > 20): + form = 1 + else: + form = 2 + return forms[form] + + def to_ordinal(self, number): + raise NotImplementedError() + + def _int2word(self, n): + if n == 0: + return ZERO[0] + + words = [] + chunks = list(splitbyx(str(n), 3)) + i = len(chunks) + for x in chunks: + i -= 1 + + if x == 0: + continue + + n1, n2, n3 = get_digits(x) + + if n3 > 0: + words.append(HUNDREDS[n3][0]) + + if n2 > 1: + words.append(TWENTIES[n2][0]) + + if n2 == 1: + words.append(TENS[n1][0]) + elif n1 > 0 and not (i > 0 and x == 1): + words.append(ONES[n1][0]) + + if i > 0: + words.append(self.pluralize(x, THOUSANDS[i])) + + return ' '.join(words) diff -Nru python-num2words-0.5.6/num2words/lang_DE.py python-num2words-0.5.9/num2words/lang_DE.py --- python-num2words-0.5.6/num2words/lang_DE.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_DE.py 2019-01-11 01:09:08.000000000 +0000 @@ -21,12 +21,8 @@ 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 " @@ -74,15 +70,17 @@ "ert": "erts", "end": "ends", "ion": "ions", - "nen": "nens", - "rde": "rdes", - "rden": "rdens"} + "nen": "ns", + "rde": "rds", + "rden": "rds"} def merge(self, curr, next): ctext, cnum, ntext, nnum = curr + next if cnum == 1: - if nnum < 10 ** 6: + if nnum == 100 or nnum == 1000: + return ("ein" + ntext, nnum) + elif nnum < 10 ** 6: return next ctext = "eine" @@ -114,48 +112,38 @@ if outword.endswith(key): outword = outword[:len(outword) - len(key)] + self.ords[key] break - return outword + "te" + + res = outword + "te" + + # Exception: "hundertste" is usually preferred over "einhundertste" + if res == "eintausendste" or res == "einhundertste": + res = res.replace("ein", "", 1) + + return res def to_ordinal_num(self, value): self.verify_ordinal(value) return str(value) + "." def to_currency(self, val, longval=True, old=False): + hightxt = "Euro" + lowtxt = "Cent" if old: - return self.to_splitnum(val, hightxt="mark/s", lowtxt="pfennig/e", - jointxt="und", longval=longval) - return super(Num2Word_DE, self).to_currency(val, jointxt="und", - longval=longval) + hightxt = "Mark" + lowtxt = "Pfennig/e" + + cents = int(round(val*100)) + res = self.to_splitnum(cents, hightxt=hightxt, lowtxt=lowtxt, + jointxt="und", longval=longval) + + # Handle exception, in german is "ein Euro" and not "eins Euro" + if res.startswith("eins "): + res = res.replace("eins ", "ein ", 1) + + return res def to_year(self, val, longval=True): 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() + return self.to_splitnum(val, hightxt="hundert", longval=longval)\ + .replace(' ', '') diff -Nru python-num2words-0.5.6/num2words/lang_DK.py python-num2words-0.5.9/num2words/lang_DK.py --- python-num2words-0.5.6/num2words/lang_DK.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_DK.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -20,16 +21,14 @@ 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 +130,3 @@ 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 -Nru python-num2words-0.5.6/num2words/lang_EN_IN.py python-num2words-0.5.9/num2words/lang_EN_IN.py --- python-num2words-0.5.6/num2words/lang_EN_IN.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_EN_IN.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -23,24 +24,3 @@ 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 -Nru python-num2words-0.5.6/num2words/lang_EN.py python-num2words-0.5.9/num2words/lang_EN.py --- python-num2words-0.5.6/num2words/lang_EN.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_EN.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -30,7 +31,6 @@ 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"), @@ -45,9 +45,14 @@ self.ords = {"one": "first", "two": "second", "three": "third", + "four": "fourth", "five": "fifth", + "six": "sixth", + "seven": "seventh", "eight": "eighth", "nine": "ninth", + "ten": "tenth", + "eleven": "eleventh", "twelve": "twelfth"} def merge(self, lpair, rpair): @@ -82,8 +87,24 @@ self.verify_ordinal(value) return "%s%s" % (value, self.to_ordinal(value)[-2:]) - def to_year(self, val, longval=True): - if not (val // 100) % 10: - return self.to_cardinal(val) - return self.to_splitnum(val, hightxt="hundred", jointxt="and", - longval=longval) + def to_year(self, val, suffix=None, longval=True): + if val < 0: + val = abs(val) + suffix = 'BC' if not suffix else suffix + high, low = (val // 100, val % 100) + # If year is 00XX, X00X, or beyond 9999, go cardinal. + if (high == 0 + or (high % 10 == 0 and low < 10) + or high >= 100): + valtext = self.to_cardinal(val) + else: + hightext = self.to_cardinal(high) + if low == 0: + lowtext = "hundred" + elif low < 10: + lowtext = "oh-%s" % self.to_cardinal(low) + else: + lowtext = self.to_cardinal(low) + valtext = "%s %s" % (hightext, lowtext) + return (valtext if not suffix + else "%s %s" % (valtext, suffix)) diff -Nru python-num2words-0.5.6/num2words/lang_ES_CO.py python-num2words-0.5.9/num2words/lang_ES_CO.py --- python-num2words-0.5.6/num2words/lang_ES_CO.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_ES_CO.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,4 @@ -# encoding: UTF-8 - +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. diff -Nru python-num2words-0.5.6/num2words/lang_ES.py python-num2words-0.5.9/num2words/lang_ES.py --- python-num2words-0.5.6/num2words/lang_ES.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_ES.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,4 @@ -# encoding: UTF-8 - +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -22,12 +21,16 @@ class Num2Word_ES(Num2Word_EU): - # //CHECK: Is this sufficient?? - def set_high_numwords(self, high): - max = 3 + 6 * len(high) + CURRENCY_FORMS = { + 'EUR': (('euro', 'euros'), ('centimo', 'centimos')), + 'ESP': (('peseta', 'pesetas'), ('centimo', 'centimos')), + 'USD': (('dolar', 'dolares'), ('centavo', 'centavos')), + 'PEN': (('sol', 'soles'), ('centimo', 'centimos')), + } - for word, n in zip(high, range(max, 3, -6)): - self.cards[10 ** (n - 3)] = word + "illón" + # //CHECK: Is this sufficient?? + GIGA_SUFFIX = None + MEGA_SUFFIX = "illón" def setup(self): lows = ["cuatr", "tr", "b", "m"] @@ -165,11 +168,10 @@ self.verify_ordinal(value) return "%s%s" % (value, "º" if self.gender_stem == 'o' else "ª") - def to_currency(self, val, longval=True, old=False): - hightxt, lowtxt = "euro/s", "centavo/s" - if old: - hightxt, lowtxt = "peso/s", "peseta/s" - result = self.to_splitnum(val, hightxt=hightxt, lowtxt=lowtxt, - divisor=1, jointxt="y", longval=longval) + def to_currency(self, val, currency='EUR', cents=True, seperator=' con', + adjective=False): + result = super(Num2Word_ES, self).to_currency( + val, currency=currency, cents=cents, seperator=seperator, + adjective=adjective) # Handle exception, in spanish is "un euro" and not "uno euro" return result.replace("uno", "un") diff -Nru python-num2words-0.5.6/num2words/lang_ES_VE.py python-num2words-0.5.9/num2words/lang_ES_VE.py --- python-num2words-0.5.6/num2words/lang_ES_VE.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_ES_VE.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,4 @@ -# encoding: UTF-8 - +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. diff -Nru python-num2words-0.5.6/num2words/lang_EU.py python-num2words-0.5.9/num2words/lang_EU.py --- python-num2words-0.5.6/num2words/lang_EU.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_EU.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -40,6 +40,8 @@ 'SEK': (('krona', 'kronor'), ('öre', 'öre')), 'NOK': (('krone', 'kroner'), ('øre', 'øre')), 'PLN': (('zloty', 'zlotys', 'zlotu'), ('grosz', 'groszy')), + 'MXN': (('peso', 'pesos'), GENERIC_CENTS), + 'RON': (('leu', 'lei'), ('ban', 'bani')), } CURRENCY_ADJECTIVES = { @@ -49,20 +51,33 @@ 'USD': 'US', 'RUB': 'Russian', 'NOK': 'Norwegian', + 'MXN': 'Mexican', + 'RON': 'Romanian', } + GIGA_SUFFIX = "illiard" + MEGA_SUFFIX = "illion" + def set_high_numwords(self, high): - max = 3 + 6 * len(high) + cap = 3 + 6 * len(high) - for word, n in zip(high, range(max, 3, -6)): - self.cards[10 ** n] = word + "illiard" - self.cards[10 ** (n - 3)] = word + "illion" + 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 -Nru python-num2words-0.5.6/num2words/lang_FI.py python-num2words-0.5.9/num2words/lang_FI.py --- python-num2words-0.5.6/num2words/lang_FI.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_FI.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,736 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import division, print_function, unicode_literals + +from collections import OrderedDict + +from . import lang_EU + +GENERIC_CENTS = ('sentti', 'senttiä') +GENERIC_CENTAVOS = ('centavo', 'centavoa') + +# grammatical cases +NOM = 10 # nominative: the dictionary form +GEN = 11 # genitive: ~of/'s +ACC = 12 # accusative: not used; either nominative or genitive +PTV = 13 # partitive: as an object +# locative cases (internal) +INE = 14 # inessive: in +ELA = 15 # elative: from/out of +ILL = 16 # illative: into +# locative cases (external) +ADE = 17 # adessive: at/on +ABL = 18 # ablative: from (after being at/on, not in) +ALL = 19 # allative: to +# essive +ESS = 20 # essive: as (in the role of) +TRANSL = 21 # translative: to (the role of; being sth) +# rare +INSTRUC = 22 # instructive: with (plural is the same as singular) +ABE = 23 # abessive: without +COM = 24 # comitative: together with (plural = singular) + +NAME_TO_CASE = { + 'nominative': NOM, + 'genitive': GEN, + 'accusative': ACC, + 'partitive': PTV, + 'inessive': INE, + 'elative': ELA, + 'illative': ILL, + 'adessive': ADE, + 'ablative': ABL, + 'allative': ALL, + 'essive': ESS, + 'translative': TRANSL, + 'instructive': INSTRUC, + 'abessive': ABE, + 'comitative': COM, +} + +# https://en.wikibooks.org/wiki/Finnish/Grammar-Vowel_harmony +BACK_TO_FRONT = { + 'a': 'ä', + 'o': 'ö', + 'u': 'y', +} + +# https://en.wiktionary.org/wiki/Appendix:Finnish_nominal_inflection +# CASE: (SINGULAR_SUFFIX+, PLURAL_SUFFIX+) +KOTUS_TYPE = { + + # Kotus type 5/risti, no gradation + 5: { + # grammatical + NOM: ('i', 'it'), + GEN: ('in', 'ien'), + PTV: ('ia', 'eja'), + # locative, internal + INE: ('issa', 'eissa'), + ELA: ('ista', 'eista'), + ILL: ('iin', 'eihin'), + # locative, external + ADE: ('illa', 'eilla'), + ABL: ('ilta', 'eilta'), + ALL: ('ille', 'eille'), + # essive + ESS: ('ina', 'eina'), + TRANSL: ('iksi', 'eiksi'), + # rare + INSTRUC: ('ein', 'ein'), + ABE: ('itta', 'eitta'), + COM: ('eine', 'eine'), # works better + }, + + # Kotus type 7/ovi, no gradation + 7: { + # grammatical + NOM: ('i', 'et'), + GEN: ('en', 'ien'), + PTV: ('ea', 'ia'), + # locative, internal + INE: ('essa', 'issa'), + ELA: ('esta', 'ista'), + ILL: ('een', 'iin'), + # locative, external + ADE: ('ella', 'illa'), + ABL: ('elta', 'ilta'), + ALL: ('elle', 'ille'), + # essive + ESS: ('ena', 'ina'), + TRANSL: ('eksi', 'iksi'), + # rare + INSTRUC: ('in', 'in'), + ABE: ('etta', 'itta'), + COM: ('ine', 'ine'), # works better + }, + + # Kotus type 8/nalle, no gradation + 8: { + # grammatical + NOM: ('e', 'et'), + GEN: ('en', ('ejen', 'ein')), + PTV: ('ea', 'eja'), + # locative, internal + INE: ('essa', 'eissa'), + ELA: ('esta', 'eista'), + ILL: ('een', 'eihin'), + # locative, external + ADE: ('ella', 'eilla'), + ABL: ('elta', 'eilta'), + ALL: ('elle', 'eille'), + # essive + ESS: ('ena', 'eina'), + TRANSL: ('eksi', 'eiksi'), + # rare + INSTRUC: ('ein', 'ein'), + ABE: ('etta', 'eitta'), + COM: ('eine', 'eine'), # works better + }, + + # Kotus type 9/kala, t-d gradation (sata) + 109: { + # grammatical + NOM: ('ta', 'dat'), + GEN: ('dan', ('tojen', 'tain')), + PTV: ('taa', 'toja'), + # locative, internal + INE: ('dassa', 'doissa'), + ELA: ('dasta', 'doista'), + ILL: ('taan', 'toihin'), + # locative, external + ADE: ('dalla', 'doilla'), + ABL: ('dalta', 'doilta'), + ALL: ('dalle', 'doille'), + # essive + ESS: ('tana', 'toina'), + TRANSL: ('daksi', 'doiksi'), + # rare + INSTRUC: ('doin', 'doin'), + ABE: ('datta', 'doitta'), + COM: ('toine', 'toine'), # works better + }, + + # Kotus type 10/koira, no gradation + 10: { + # grammatical + NOM: ('a', 'at'), + GEN: ('an', ('ien', 'ain')), + PTV: ('aa', 'ia'), + # locative, internal + INE: ('assa', 'issa'), + ELA: ('asta', 'ista'), + ILL: ('aan', 'iin'), + # locative, external + ADE: ('alla', 'illa'), + ABL: ('alta', 'ilta'), + ALL: ('alle', 'ille'), + # essive + ESS: ('ana', 'ina'), + TRANSL: ('aksi', 'iksi'), + # rare + INSTRUC: ('in', 'in'), + ABE: ('atta', 'itta'), + COM: ('ine', 'ine'), # works better + }, + + # Kotus type 27/käsi, t-d gradation + 27: { + # grammatical + NOM: ('si', 'det'), + GEN: ('den', ('sien', 'tten')), + PTV: ('tta', 'sia'), + # locative, internal + INE: ('dessa', 'sissa'), + ELA: ('desta', 'sista'), + ILL: ('teen', 'siin'), + # locative, external + ADE: ('della', 'silla'), + ABL: ('delta', 'silta'), + ALL: ('delle', 'sille'), + # essive + ESS: ('tena', 'sina'), + TRANSL: ('deksi', 'siksi'), + # rare + INSTRUC: ('sin', 'sin'), + ABE: ('detta', 'sitta'), + COM: ('sine', 'sine'), # works better + }, + + # Kotus type 31/kaksi, t-d gradation + 31: { + # grammatical + NOM: ('ksi', 'hdet'), + GEN: ('hden', 'ksien'), + PTV: ('hta', 'ksia'), + # locative, internal + INE: ('hdessa', 'ksissa'), + ELA: ('hdesta', 'ksista'), + ILL: ('hteen', 'ksiin'), + # locative, external + ADE: ('hdella', 'ksilla'), + ABL: ('hdelta', 'ksilta'), + ALL: ('hdelle', 'ksille'), + # essive + ESS: ('htena', 'ksina'), + TRANSL: ('hdeksi', 'ksiksi'), + # rare + INSTRUC: ('ksin', 'ksin'), + ABE: ('hdetta', 'ksitta'), + COM: ('ksine', 'ksine'), # works better + }, + + # Kotus type 32/sisar, no gradation + 32: { + # grammatical + NOM: ('', 'et'), + GEN: ('en', ('ien', 'ten')), + PTV: ('ta', 'ia'), + # locative, internal + INE: ('essa', 'issa'), + ELA: ('esta', 'ista'), + ILL: ('een', 'iin'), + # locative, external + ADE: ('ella', 'illa'), + ABL: ('elta', 'ilta'), + ALL: ('elle', 'ille'), + # essive + ESS: ('ena', 'ina'), + TRANSL: ('eksi', 'iksi'), + # rare + INSTRUC: ('in', 'in'), + ABE: ('etta', 'itta'), + COM: ('ine', 'ine'), # works better + }, + + # Kotus type 38/nainen, no gradation + 38: { + # grammatical + NOM: ('nen', 'set'), + GEN: ('sen', ('sten', 'sien')), + PTV: ('sta', 'sia'), + # locative, internal + INE: ('sessa', 'sissa'), + ELA: ('sesta', 'sista'), + ILL: ('seen', 'siin'), + # locative, external + ADE: ('sella', 'silla'), + ABL: ('selta', 'silta'), + ALL: ('selle', 'sille'), + # essive + ESS: ('sena', 'sina'), + TRANSL: ('seksi', 'siksi'), + # rare + INSTRUC: ('sin', 'sin'), + ABE: ('setta', 'sitta'), + COM: ('sine', 'sine'), # works better + }, + + # Kotus type 45/kahdeksas, nt-nn gradation + 45: { + # grammatical + NOM: ('s', 'nnet'), + GEN: ('nnen', 'nsien'), + PTV: ('tta', 'nsia'), + # locative, internal + INE: ('nnessa', 'nsissa'), + ELA: ('nnesta', 'nsista'), + ILL: ('nteen', 'nsiin'), + # locative, external + ADE: ('nnella', 'nsilla'), + ABL: ('nnelta', 'nsilta'), + ALL: ('nnelle', 'nsille'), + # essive + ESS: ('ntena', 'nsina'), + TRANSL: ('nneksi', 'nsiksi'), + # rare + INSTRUC: ('nsin', 'nsin'), + ABE: ('nnetta', 'nsitta'), + COM: ('nsine', 'nsine'), # works better + }, + + # Kotus type 46/tuhat, nt-nn gradation + 46: { + # grammatical + NOM: ('t', 'nnet'), + GEN: ('nnen', ('nsien', 'nten')), + PTV: ('tta', 'nsia'), + # locative, internal + INE: ('nnessa', 'nsissa'), + ELA: ('nnesta', 'nsista'), + ILL: ('nteen', 'nsiin'), + # locative, external + ADE: ('nnella', 'nsilla'), + ABL: ('nnelta', 'nsilta'), + ALL: ('nnelle', 'nsille'), + # essive + ESS: ('ntena', 'nsina'), + TRANSL: ('nneksi', 'nsiksi'), + # rare + INSTRUC: ('nsin', 'nsin'), + ABE: ('nnetta', 'nsitta'), + COM: ('nsine', 'nsine'), # works better + }, +} + +# kolme +KOTUS_TYPE[108] = { + c: (KOTUS_TYPE[8][c][0], KOTUS_TYPE[7][c][1]) + for c in KOTUS_TYPE[8] +} +KOTUS_TYPE[108][INSTRUC] = ('en', 'in') +KOTUS_TYPE[108][ABE] = ('etta', 'itta') +KOTUS_TYPE[108][COM] = ('ine', 'ine') + +# seitsemän, kahdeksan, yhdeksän +KOTUS_TYPE[110] = KOTUS_TYPE[10].copy() +KOTUS_TYPE[110][NOM] = ('an', 'at') + +# kymmenen +KOTUS_TYPE[132] = KOTUS_TYPE[32].copy() +KOTUS_TYPE[132][NOM] = ('en', 'et') + + +def inflect(parts, options): + if not isinstance(parts, list): + parts = [parts] + + out = '' + for part in parts: + # part is plain text, concat and continue + if not isinstance(part, tuple): + out += part + continue + # predefined case (kaksikymmentä, ...) + tmp_case = options.case + if len(part) == 3: + # override singular nominative only + if options.case == NOM and not options.plural: + tmp_case = part[2] + part = part[:2] + # stem and suffix + stem, kotus_type = part + suffix = KOTUS_TYPE[kotus_type][tmp_case][options.plural] + # many choices, choose preferred or first + if isinstance(suffix, tuple): + common = set(suffix) & set(options.prefer or set()) + if len(common) == 1: + suffix = common.pop() + else: + suffix = suffix[0] + # apply vowel harmony + if not set(BACK_TO_FRONT) & set(stem): + for back, front in BACK_TO_FRONT.items(): + suffix = suffix.replace(back, front) + # concat + out += stem + suffix + + return out + + +class Options(object): + def __init__(self, ordinal, case, plural, prefer): + self.ordinal = ordinal + self.case = case + self.plural = plural + self.prefer = prefer + + def variation(self, ordinal=None, case=None, plural=None, prefer=None): + return Options( + ordinal if ordinal is not None else self.ordinal, + case if case is not None else self.case, + plural if plural is not None else self.plural, + prefer if prefer is not None else self.prefer, + ) + + +class Num2Word_FI(lang_EU.Num2Word_EU): + CURRENCY_FORMS = { + 'BRL': (('real', 'realia'), GENERIC_CENTAVOS), + 'CHF': (('frangi', 'frangia'), ('rappen', 'rappenia')), + 'CNY': (('juan', 'juania'), ('fen', 'feniä')), + 'EUR': (('euro', 'euroa'), GENERIC_CENTS), + 'FIM': (('markka', 'markkaa'), ('penni', 'penniä')), # historical + 'INR': (('rupia', 'rupiaa'), ('paisa', 'paisaa')), + 'JPY': (('jeni', 'jeniä'), ('sen', 'seniä')), # rare subunit + 'KRW': (('won', 'wonia'), ('jeon', 'jeonia')), # rare subunit + 'KPW': (('won', 'wonia'), ('chon', 'chonia')), # rare subunit + 'MXN': (('peso', 'pesoa'), GENERIC_CENTAVOS), + 'RUB': (('rupla', 'ruplaa'), ('kopeekka', 'kopeekkaa')), + 'TRY': (('liira', 'liiraa'), ('kuruş', 'kuruşia')), + 'ZAR': (('randi', 'randia'), GENERIC_CENTS), + } + + # crowns + for curr_code in 'DKK', 'ISK', 'NOK', 'SEK': + CURRENCY_FORMS[curr_code] = (('kruunu', 'kruunua'), ('äyri', 'äyriä')) + + # dollars + for curr_code in 'AUD', 'CAD', 'HKD', 'NZD', 'SGD', 'USD': + CURRENCY_FORMS[curr_code] = ( + ('dollari', 'dollaria'), GENERIC_CENTS) + + # pounds + for curr_code in ('GBP',): + CURRENCY_FORMS[curr_code] = (('punta', 'puntaa'), ('penny', 'pennyä')) + + CURRENCY_ADJECTIVES = { + 'AUD': 'Australian', + 'BRL': 'Brasilian', + 'CAD': 'Kanadan', + 'CHF': 'Sveitsin', + 'DKK': 'Tanskan', + 'FIM': 'Suomen', # historical + 'GBP': 'Englannin', + 'HKD': 'Hongkongin', + 'INR': 'Intian', + 'ISK': 'Islannin', + 'KRW': 'Etelä-Korean', + 'KPW': 'Pohjois-Korean', + 'MXN': 'Meksikon', + 'NOK': 'Norjan', + 'NZD': 'Uuden-Seelannin', + 'RUB': 'Venäjän', + 'SEK': 'Ruotsin', + 'SGD': 'Singaporen', + 'TRY': 'Turkin', + 'USD': 'Yhdysvaltain', + 'ZAR': 'Etelä-Afrikan', + } + + def __init__(self): + self.ords = OrderedDict() + super(Num2Word_FI, self).__init__() + + def set_numwords(self): + self.set_high_numwords(self.high_numwords) + self.set_mid_numwords(self.mid_numwords, self.mid_ords) + self.set_low_numwords(self.low_numwords, self.low_ords) + + def set_high_numwords(self, high): + # references: + # https://fi.wikipedia.org/wiki/Suurten_lukujen_nimet + # https://en.wikipedia.org/wiki/Names_of_large_numbers#Standard_dictionary_numbers + + # translate to Finnish + replacements = [ + ("qu", "kv"), + ("x", "ks"), + ("c", "k"), + ("kent", "sent"), # applied after c -> k to cent + ] + translated = [] + for i, numword in enumerate(high): + # notes: + # - 1e6**9 can be either noviljoona or noniljoona + # - 1e6**38 and above are untested + + # 1e6**6 is sekstiljoona but 1e6**16 is sedekiljoona + if numword.startswith("sex") and numword != "sext": + numword = numword.replace("sex", "se") + # 1e6**7 is septiljoona but 1e6**17 is septendekiljoona + elif numword.startswith("sept") and numword != "sept": + numword = "septen" + numword[len("sept"):] + # 1e6**8 is oktiljoona but 1e6**18 is duodevigintiljoona + # (2 from 20) + elif numword.startswith("octo"): + numword = high[i + -10] + numword = "duode" + numword[len("octo"):] + # 1e6**9 is noniljoona but 1e6**19 is undevigintiljoona (1 from 20) + elif numword.startswith("nove"): + numword = high[i + -10] + numword = "unde" + numword[len("nove") + 1:] + + # apply general replacements to all numwords + for repl in replacements: + numword = numword.replace(repl[0], repl[1]) + translated.append(numword) + + max = 6 * len(translated) + for word, n in zip(translated, range(max, 0, -6)): + if n == 6: + # irregularity considering short scale and long scale + self.cards[10 ** 9] = ("miljard", 5) + self.ords[10 ** 9] = ("miljardi", 45) + self.cards[10 ** n] = (word + "iljoon", 10) + self.ords[10 ** n] = (word + "iljoona", 45) + + def set_mid_numwords(self, cards, ords): + for key, val in cards: + self.cards[key] = val + for key, val in ords: + self.ords[key] = val + + def set_low_numwords(self, cards, ords): + for key, val in cards: + self.cards[key] = val + for key, val in ords: + self.ords[key] = val + + def setup(self): + super(Num2Word_FI, self).setup() + + self.negword = "miinus " + self.pointword = "pilkku" + self.exclude_title = ["pilkku", "miinus"] + + self.mid_numwords = [ + (1000, ("tuha", 46)), + (100, ("sa", 109)), + (90, [("yhdeks", 110), ("kymmen", 132, PTV)]), + (80, [("kahdeks", 110), ("kymmen", 132, PTV)]), + (70, [("seitsem", 110), ("kymmen", 132, PTV)]), + (60, [("kuu", 27), ("kymmen", 132, PTV)]), + (50, [("vii", 27), ("kymmen", 132, PTV)]), + (40, [("nelj", 10), ("kymmen", 132, PTV)]), + (30, [("kolm", 108), ("kymmen", 132, PTV)]), + ] + + self.mid_ords = [ + (1000, ("tuhanne", 45)), + (100, ("sada", 45)), + (90, [("yhdeksä", 45), ("kymmene", 45)]), + (80, [("kahdeksa", 45), ("kymmene", 45)]), + (70, [("seitsemä", 45), ("kymmene", 45)]), + (60, [("kuude", 45), ("kymmene", 45)]), + (50, [("viide", 45), ("kymmene", 45)]), + (40, [("neljä", 45), ("kymmene", 45)]), + (30, [("kolma", 45), ("kymmene", 45)]), + ] + + self.low_numwords = [ + (20, [("ka", 31), ("kymmen", 132, PTV)]), + (19, [("yhdeks", 110), "toista"]), + (18, [("kahdeks", 110), "toista"]), + (17, [("seitsem", 110), "toista"]), + (16, [("kuu", 27), "toista"]), + (15, [("vii", 27), "toista"]), + (14, [("nelj", 10), "toista"]), + (13, [("kolm", 108), "toista"]), + (12, [("ka", 31), "toista"]), + (11, [("y", 31), "toista"]), + (10, ("kymmen", 132)), + (9, ("yhdeks", 110)), + (8, ("kahdeks", 110)), + (7, ("seitsem", 110)), + (6, ("kuu", 27)), + (5, ("vii", 27)), + (4, ("nelj", 10)), + (3, ("kolm", 108)), + (2, ("ka", 31)), + (1, ("y", 31)), + (0, ("noll", 10)), + ] + + self.low_ords = [ + (20, [("kahde", 45), ("kymmene", 45)]), + (19, [("yhdeksä", 45), "toista"]), + (18, [("kahdeksa", 45), "toista"]), + (17, [("seitsemä", 45), "toista"]), + (16, [("kuude", 45), "toista"]), + (15, [("viide", 45), "toista"]), + (14, [("neljä", 45), "toista"]), + (13, [("kolma", 45), "toista"]), + (12, [("kahde", 45), "toista"]), + (11, [("yhde", 45), "toista"]), + (10, ("kymmene", 45)), + (9, ("yhdeksä", 45)), + (8, ("kahdeksa", 45)), + (7, ("seitsemä", 45)), + (6, ("kuude", 45)), + (5, ("viide", 45)), + (4, ("neljä", 45)), + (3, ("kolma", 45)), + (2, ("toi", 38)), + (1, ("ensimmäi", 38)), + (0, ("nolla", 45)), + ] + + def merge(self, lpair, rpair, options): + ltext, lnum = lpair + rtext, rnum = rpair + + # http://www.kielitoimistonohjepankki.fi/ohje/49 + fmt = "%s%s" + # ignore lpair if lnum is 1 + if lnum == 1: + rtext = inflect(rtext, options) + return (rtext, rnum) + # rnum is added to lnum + elif lnum > rnum: + ltext = inflect(ltext, options) + rtext = inflect(rtext, options) + # separate groups with space + if lnum >= 1000: + fmt = "%s %s" + return (fmt % (ltext, rtext), lnum + rnum) + # rnum is multiplied by lnum + elif lnum < rnum: + if options.ordinal: + # kahdessadas, not toinensadas + if lnum == 2: + ltext = ("kahde", 45) + rtext = inflect(rtext, options) + else: + # kaksituhatta but kahdettuhannet + rcase = options.case + if options.case == NOM and not options.plural: + rcase = PTV + rtext = inflect(rtext, options.variation(case=rcase)) + ltext = inflect(ltext, options) + return (fmt % (ltext, rtext), lnum * rnum) + + def to_cardinal(self, value, case='nominative', plural=False, prefer=None): + case = NAME_TO_CASE[case] + options = Options(False, case, plural, prefer) + try: + assert int(value) == value + except (ValueError, TypeError, AssertionError): + if case != NOM: + raise NotImplementedError( + "Cases other than nominative are not implemented for " + "cardinal floating point numbers.") + return self.to_cardinal_float(value) + + out = "" + if value < 0: + value = abs(value) + out = self.negword + + if value >= self.MAXVAL: + raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL)) + + val = self.splitnum(value, options) + words, num = self.clean(val, options) + return self.title(out + words) + + def to_ordinal(self, value, case='nominative', plural=False, prefer=None): + case = NAME_TO_CASE[case] + options = Options(True, case, plural, prefer) + + self.verify_ordinal(value) + if value >= self.MAXVAL: + raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL)) + + val = self.splitnum(value, options) + words, num = self.clean(val, options) + return self.title(words) + + def to_ordinal_num(self, value, case='nominative', plural=False): + case = NAME_TO_CASE[case] + raise NotImplementedError + + def to_year(self, val, suffix=None, longval=True): + suffix = suffix or "" + if val < 0: + val = abs(val) + suffix = suffix or " ennen ajanlaskun alkua" + return self.to_cardinal(val).replace(" ", "") + suffix + + def to_currency(self, val, currency="EUR", cents=True, seperator=" ja", + adjective=False): + return super(Num2Word_FI, self).to_currency( + val, currency=currency, cents=cents, seperator=seperator, + adjective=adjective) + + def splitnum(self, value, options): + elems = self.ords if options.ordinal else self.cards + for elem in elems: + if elem > value: + continue + + out = [] + if value == 0: + div, mod = 1, 0 + else: + div, mod = divmod(value, elem) + + if div == 1: + out.append((elems[1], 1)) + else: + if div == value: # The system tallies, eg Roman Numerals + return [(div * elems[elem], div*elem)] + out.append(self.splitnum(div, options)) + + out.append((elems[elem], elem)) + + if mod: + out.append(self.splitnum(mod, options)) + + return out + + def clean(self, val, options): + out = val + while len(val) != 1: + out = [] + left, right = val[:2] + if isinstance(left, tuple) and isinstance(right, tuple): + out.append(self.merge(left, right, options)) + if val[2:]: + out.append(val[2:]) + else: + for elem in val: + if isinstance(elem, list): + if len(elem) == 1: + out.append(elem[0]) + else: + out.append(self.clean(elem, options)) + else: + out.append(elem) + val = out + return out[0] diff -Nru python-num2words-0.5.6/num2words/lang_FR_BE.py python-num2words-0.5.9/num2words/lang_FR_BE.py --- python-num2words-0.5.6/num2words/lang_FR_BE.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_FR_BE.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import print_function, unicode_literals + +from .lang_FR import Num2Word_FR + + +class Num2Word_FR_BE(Num2Word_FR): + def setup(self): + Num2Word_FR.setup(self) + + self.mid_numwords = [(1000, "mille"), (100, "cent"), (90, "nonante"), + (80, "quatre-vingt"), (70, "septante"), + (60, "soixante"), (50, "cinquante"), + (40, "quarante"), (30, "trente")] + + def merge(self, curr, next): + ctext, cnum, ntext, nnum = curr + next + + if cnum == 1: + if nnum < 1000000: + return next + + if cnum < 1000 and nnum != 1000 and\ + ntext[-1] != "s" and not nnum % 100: + ntext += "s" + + if nnum < cnum < 100: + if nnum % 10 == 1: + return ("%s et %s" % (ctext, ntext), cnum + nnum) + return ("%s-%s" % (ctext, ntext), cnum + nnum) + if nnum > cnum: + return ("%s %s" % (ctext, ntext), cnum * nnum) + return ("%s %s" % (ctext, ntext), cnum + nnum) diff -Nru python-num2words-0.5.6/num2words/lang_FR_CH.py python-num2words-0.5.9/num2words/lang_FR_CH.py --- python-num2words-0.5.6/num2words/lang_FR_CH.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_FR_CH.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -14,7 +14,6 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA - from __future__ import print_function, unicode_literals from .lang_FR import Num2Word_FR diff -Nru python-num2words-0.5.6/num2words/lang_FR_DZ.py python-num2words-0.5.9/num2words/lang_FR_DZ.py --- python-num2words-0.5.6/num2words/lang_FR_DZ.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_FR_DZ.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. diff -Nru python-num2words-0.5.6/num2words/lang_FR.py python-num2words-0.5.9/num2words/lang_FR.py --- python-num2words-0.5.6/num2words/lang_FR.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_FR.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -51,7 +51,10 @@ if nnum < 1000000: return next else: - if (not (cnum - 80) % 100 or not cnum % 100) and ctext[-1] == "s": + if (not (cnum - 80) % 100 + or (not cnum % 100 and cnum < 1000))\ + and nnum < 1000000 \ + and ctext[-1] == "s": ctext = ctext[:-1] if cnum < 1000 and nnum != 1000 and \ ntext[-1] != "s" and not nnum % 100: @@ -93,5 +96,6 @@ hightxt = "euro/s" if old: hightxt = "franc/s" - return self.to_splitnum(val, hightxt=hightxt, lowtxt="centime/s", - divisor=1, jointxt="et", longval=longval) + cents = int(round(val*100)) + return self.to_splitnum(cents, hightxt=hightxt, lowtxt="centime/s", + divisor=100, jointxt="et", longval=longval) diff -Nru python-num2words-0.5.6/num2words/lang_HE.py python-num2words-0.5.9/num2words/lang_HE.py --- python-num2words-0.5.6/num2words/lang_HE.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_HE.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,5 @@ -# -*- encoding: utf-8 -*- -# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or @@ -18,7 +18,7 @@ from __future__ import print_function, unicode_literals -from .utils import get_digits, splitby3 +from .utils import get_digits, splitbyx ZERO = (u'אפס',) @@ -90,13 +90,15 @@ words = [] - chunks = list(splitby3(str(n))) + chunks = list(splitbyx(str(n), 3)) i = len(chunks) for x in chunks: i -= 1 - n1, n2, n3 = get_digits(x) - # print str(n3) + str(n2) + str(n1) + if x == 0: + continue + + n1, n2, n3 = get_digits(x) if n3 > 0: if n3 <= 2: diff -Nru python-num2words-0.5.6/num2words/lang_ID.py python-num2words-0.5.9/num2words/lang_ID.py --- python-num2words-0.5.6/num2words/lang_ID.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_ID.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. diff -Nru python-num2words-0.5.6/num2words/lang_IT.py python-num2words-0.5.9/num2words/lang_IT.py --- python-num2words-0.5.6/num2words/lang_IT.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_IT.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,7 @@ -# -*- encoding: utf-8 -*- -# +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either @@ -169,7 +171,7 @@ def to_cardinal(self, number): if number < 0: string = Num2Word_IT.MINUS_PREFIX_WORD + self.to_cardinal(-number) - elif number % 1 != 0: + elif isinstance(number, float): string = self.float_to_words(number) elif number < 20: string = CARDINAL_WORDS[number] diff -Nru python-num2words-0.5.6/num2words/lang_JA.py python-num2words-0.5.9/num2words/lang_JA.py --- python-num2words-0.5.6/num2words/lang_JA.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_JA.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,589 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import division, print_function, unicode_literals + +from .base import Num2Word_Base +from .compat import strtype, to_s +from .currency import parse_currency_parts, prefix_currency + + +def select_text(text, reading=False, prefer=None): + """Select the correct text from the Japanese number, reading and + alternatives""" + # select kanji number or kana reading + if reading: + text = text[1] + else: + text = text[0] + + # select the preferred one or the first one from multiple alternatives + if not isinstance(text, strtype): + common = set(text) & set(prefer or set()) + if len(common) == 1: + text = common.pop() + else: + text = text[0] + + return text + + +def rendaku_merge_pairs(lpair, rpair): + """Merge lpair < rpair while applying semi-irregular rendaku rules""" + ltext, lnum = lpair + rtext, rnum = rpair + if lnum > rnum: + raise ValueError + + if rpair == ("ひゃく", 100): + if lpair == ("さん", 3): + rtext = "びゃく" + elif lpair == ("ろく", 6): + ltext = "ろっ" + rtext = "ぴゃく" + elif lpair == ("はち", 8): + ltext = "はっ" + rtext = "ぴゃく" + elif rpair == ("せん", 1000): + if lpair == ("さん", 3): + rtext = "ぜん" + elif lpair == ("はち", 8): + ltext = "はっ" + elif rpair == ("ちょう", 10**12): + if lpair == ("いち", 1): + ltext = "いっ" + elif lpair == ("はち", 8): + ltext = "はっ" + elif lpair == ("じゅう", 10): + ltext = "じゅっ" + elif rpair == ("けい", 10**16): + if lpair == ("いち", 1): + ltext = "いっ" + elif lpair == ("ろく", 6): + ltext = "ろっ" + elif lpair == ("はち", 8): + ltext = "はっ" + elif lpair == ("じゅう", 10): + ltext = "じゅっ" + elif lpair == ("ひゃく", 100): + ltext = "ひゃっ" + + return ("%s%s" % (ltext, rtext), lnum * rnum) + + +# Source: https://www.sljfaq.org/afaq/era-list.html +# if there are multiple eras for the same year, use the last one +ERA_START = [ + (645, ("大化", "たいか")), + (650, ("白雉", "はくち")), + (686, ("朱鳥", "しゅちょう")), + (701, ("大宝", "たいほう")), + (704, ("慶雲", "けいうん")), + (708, ("和銅", "わどう")), + (715, ("霊亀", "れいき")), + (717, ("養老", "ようろう")), + (724, ("神亀", "じんき")), + (729, ("天平", "てんぴょう")), + (749, ("天平感宝", "てんぴょうかんぽう")), + (749, ("天平勝宝", "てんぴょうしょうほう")), + (757, ("天平宝字", "てんぴょうじょうじ")), + (765, ("天平神護", "てんぴょうじんご")), + (767, ("神護景雲", "じんごけいうん")), + (770, ("宝亀", "ほうき")), + (781, ("天応", "てんおう")), + (782, ("延暦", "えんりゃく")), + (806, ("大同", "だいどう")), + (810, ("弘仁", "こうにん")), + (823, ("天長", "てんちょう")), + (834, ("承和", "じょうわ")), + (848, ("嘉祥", "かしょう")), + (851, ("仁寿", "にんじゅ")), + (855, ("斉衡", "さいこう")), + (857, ("天安", "てんあん")), + (859, ("貞観", "じょうがん")), + (877, ("元慶", "がんぎょう")), + (885, ("仁和", "にんな")), + (889, ("寛平", "かんぴょう")), + (898, ("昌泰", "しょうたい")), + (901, ("延喜", "えんぎ")), + (923, ("延長", "えんちょう")), + (931, ("承平", "じょうへい")), + (938, ("天慶", "てんぎょう")), + (947, ("天暦", "てんりゃく")), + (957, ("天徳", "てんとく")), + (961, ("応和", "おうわ")), + (964, ("康保", "こうほう")), + (968, ("安和", "あんな")), + (970, ("天禄", "てんろく")), + (974, ("天延", "てんえん")), + (976, ("貞元", "じょうげん")), + (979, ("天元", "てんげん")), + (983, ("永観", "えいかん")), + (985, ("寛和", "かんな")), + (987, ("永延", "えいえん")), + (989, ("永祚", "えいそ")), + (990, ("正暦", "しょうりゃく")), + (995, ("長徳", "ちょうとく")), + (999, ("長保", "ちょうほう")), + (1004, ("寛弘", "かんこう")), + (1013, ("長和", "ちょうわ")), + (1017, ("寛仁", "かんにん")), + (1021, ("治安", "じあん")), + (1024, ("万寿", "まんじゅ")), + (1028, ("長元", "ちょうげん")), + (1037, ("長暦", "ちょうりゃく")), + (1040, ("長久", "ちょうきゅう")), + (1045, ("寛徳", "かんとく")), + (1046, ("永承", "えいしょう")), + (1053, ("天喜", "てんぎ")), + (1058, ("康平", "こうへい")), + (1065, ("治暦", "じりゃく")), + (1069, ("延久", "えんきゅう")), + (1074, ("承保", "じょうほう")), + (1078, ("承暦", "じょうりゃく")), + (1081, ("永保", "えいほう")), + (1084, ("応徳", "おうとく")), + (1087, ("寛治", "かんじ")), + (1095, ("嘉保", "かほう")), + (1097, ("永長", "えいちょう")), + (1098, ("承徳", "じょうとく")), + (1099, ("康和", "こうわ")), + (1104, ("長治", "ちょうじ")), + (1106, ("嘉承", "かじょう")), + (1108, ("天仁", "てんにん")), + (1110, ("天永", "てんねい")), + (1113, ("永久", "えいきゅう")), + (1118, ("元永", "げんえい")), + (1120, ("保安", "ほうあん")), + (1124, ("天治", "てんじ")), + (1126, ("大治", "だいじ")), + (1131, ("天承", "てんしょう")), + (1132, ("長承", "ちょうしょう")), + (1135, ("保延", "ほうえん")), + (1141, ("永治", "えいじ")), + (1142, ("康治", "こうじ")), + (1144, ("天養", "てんよう")), + (1145, ("久安", "きゅうあん")), + (1151, ("仁平", "にんぺい")), + (1154, ("久寿", "きゅうじゅ")), + (1156, ("保元", "ほうげん")), + (1159, ("平治", "へいじ")), + (1160, ("永暦", "えいりゃく")), + (1161, ("応保", "おうほう")), + (1163, ("長寛", "ちょうかん")), + (1165, ("永万", "えいまん")), + (1166, ("仁安", "にんあん")), + (1169, ("嘉応", "かおう")), + (1171, ("承安", "しょうあん")), + (1175, ("安元", "あんげん")), + (1177, ("治承", "じしょう")), + (1181, ("養和", "ようわ")), + (1182, ("寿永", "じゅえい")), + (1184, ("元暦", "げんりゃく")), + (1185, ("文治", "ぶんじ")), + (1190, ("建久", "けんきゅう")), + (1199, ("正治", "しょうじ")), + (1201, ("建仁", "けんにん")), + (1204, ("元久", "げんきゅう")), + (1206, ("建永", "けんえい")), + (1207, ("承元", "じょうげん")), + (1211, ("建暦", "けんりゃく")), + (1214, ("建保", "けんぽう")), + (1219, ("承久", "じょうきゅう")), + (1222, ("貞応", "じょうおう")), + (1225, ("元仁", "げんにん")), + (1225, ("嘉禄", "かろく")), + (1228, ("安貞", "あんてい")), + (1229, ("寛喜", "かんき")), + (1232, ("貞永", "じょうえい")), + (1233, ("天福", "てんぷく")), + (1235, ("文暦", "ぶんりゃく")), + (1235, ("嘉禎", "かてい")), + (1239, ("暦仁", "りゃくにん")), + (1239, ("延応", "えんおう")), + (1240, ("仁治", "にんじ")), + (1243, ("寛元", "かんげん")), + (1247, ("宝治", "ほうじ")), + (1249, ("建長", "けんちょう")), + (1256, ("康元", "こうげん")), + (1257, ("正嘉", "しょうか")), + (1259, ("正元", "しょうげん")), + (1260, ("文応", "ぶんおう")), + (1261, ("弘長", "こうちょう")), + (1264, ("文永", "ぶんえい")), + (1275, ("健治", "けんじ")), + (1278, ("弘安", "こうあん")), + (1288, ("正応", "しょうおう")), + (1293, ("永仁", "えいにん")), + (1299, ("正安", "しょうあん")), + (1303, ("乾元", "けんげん")), + (1303, ("嘉元", "かげん")), + (1307, ("徳治", "とくじ")), + (1308, ("延慶", "えんきょう")), + (1311, ("応長", "おうちょう")), + (1312, ("正和", "しょうわ")), + (1317, ("文保", "ぶんぽう")), + (1319, ("元応", "げんおう")), + (1321, ("元亨", "げんこう")), + (1325, ("正中", "しょうちゅ")), + (1326, ("嘉暦", "かりゃく")), + (1329, ("元徳", "げんとく")), + (1331, ("元弘", "げんこう")), + (1332, ("正慶", "しょうけい")), + (1334, ("建武", "けんむ")), + (1336, ("延元", "えいげん")), + (1338, ("暦応", "りゃくおう")), + (1340, ("興国", "こうこく")), + (1342, ("康永", "こうえい")), + (1345, ("貞和", "じょうわ")), + (1347, ("正平", "しょうへい")), + (1350, ("観応", "かんおう")), + (1352, ("文和", "ぶんな")), + (1356, ("延文", "えんぶん")), + (1361, ("康安", "こうあん")), + (1362, ("貞治", "じょうじ")), + (1368, ("応安", "おうあん")), + (1370, ("建徳", "けんとく")), + (1372, ("文中", "ぶんちゅう")), + (1375, ("永和", "えいわ")), + (1375, ("天授", "てんじゅ")), + (1379, ("康暦", "こうりゃく")), + (1381, ("永徳", "えいとく")), + (1381, ("弘和", "こうわ")), + (1384, ("至徳", "しとく")), + (1384, ("元中", "げんちゅう")), + (1387, ("嘉慶", "かけい")), + (1389, ("康応", "こうおう")), + (1390, ("明徳", "めいとく")), + (1394, ("応永", "おうえい")), + (1428, ("正長", "しょうちょう")), + (1429, ("永享", "えいきょう")), + (1441, ("嘉吉", "かきつ")), + (1444, ("文安", "ぶんあん")), + (1449, ("宝徳", "ほうとく")), + (1452, ("享徳", "きょうとく")), + (1455, ("康正", "こうしょう")), + (1457, ("長禄", "ちょうろく")), + (1461, ("寛正", "かんしょう")), + (1466, ("文正", "ぶんしょう")), + (1467, ("応仁", "おうにん")), + (1469, ("文明", "ぶんめい")), + (1487, ("長享", "ちょうきょう")), + (1489, ("延徳", "えんとく")), + (1492, ("明応", "めいおう")), + (1501, ("文亀", "ぶんき")), + (1504, ("永正", "えいしょう")), + (1521, ("大永", "だいえい")), + (1528, ("享禄", "きょうろく")), + (1532, ("天文", "てんぶん")), + (1555, ("弘治", "こうじ")), + (1558, ("永禄", "えいろく")), + (1570, ("元亀", "げんき")), + (1573, ("天正", "てんしょう")), + (1593, ("文禄", "ぶんろく")), + (1596, ("慶長", "けいちょう")), + (1615, ("元和", "げんな")), + (1624, ("寛永", "かんえい")), + (1645, ("正保", "しょうほう")), + (1648, ("慶安", "けいあん")), + (1652, ("承応", "じょうおう")), + (1655, ("明暦", "めいれき")), + (1658, ("万治", "まんじ")), + (1661, ("寛文", "かんぶん")), + (1673, ("延宝", "えんぽう")), + (1681, ("天和", "てんな")), + (1684, ("貞享", "じょうきょう")), + (1688, ("元禄", "げんろく")), + (1704, ("宝永", "ほうえい")), + (1711, ("正徳", "しょうとく")), + (1716, ("享保", "きょうほう")), + (1736, ("元文", "げんぶん")), + (1741, ("寛保", "かんぽう")), + (1744, ("延享", "えんきょう")), + (1748, ("寛延", "かんえん")), + (1751, ("宝暦", "ほうれき")), + (1764, ("明和", "めいわ")), + (1773, ("安永", "あんえい")), + (1781, ("天明", "てんめい")), + (1801, ("寛政", "かんせい")), + (1802, ("享和", "きょうわ")), + (1804, ("文化", "ぶんか")), + (1818, ("文政", "ぶんせい")), + (1831, ("天保", "てんぽう")), + (1845, ("弘化", "こうか")), + (1848, ("嘉永", "かえい")), + (1855, ("安政", "あんせい")), + (1860, ("万延", "まんえい")), + (1861, ("文久", "ぶんきゅう")), + (1864, ("元治", "げんじ")), + (1865, ("慶応", "けいおう")), + (1868, ("明治", "めいじ")), + (1912, ("大正", "たいしょう")), + (1926, ("昭和", "しょうわ")), + (1989, ("平成", "へいせい")), +] + + +class Num2Word_JA(Num2Word_Base): + CURRENCY_FORMS = { + 'JPY': (('円', 'えん'), ()), + } + + def set_high_numwords(self, high): + max = 4 * len(high) + for word, n in zip(high, range(max, 0, -4)): + self.cards[10 ** n] = word + + def setup(self): + self.negword = "マイナス" + 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, ("百", "ひゃく")), + ] + + self.low_numwords = [ + ("十", "じゅう"), # 10 jū + ("九", "きゅう"), # 9 kyū + ("八", "はち"), # 8 hachi + ("七", ("なな", "しち")), # 7 nana, shichi + ("六", "ろく"), # 6 roku + ("五", "ご"), # 5 go + ("四", ("よん", "し")), # 4 yon, shi + ("三", "さん"), # 3 san + ("二", "に"), # 2 ni + ("一", "いち"), # 1 ichi + # both are alternatives, 零 doesn't map to ゼロ or 〇 to れい + (("零", "〇"), ("ゼロ", "れい")), # 0 ZERO, rei + ] + + def merge(self, lpair, rpair): + ltext, lnum = lpair + rtext, rnum = rpair + + fmt = "%s%s" + # ignore lpair if lnum is 1 and rnum is less than 10000 + if lnum == 1 and rnum < 10000: + return rpair + # rnum is added to lnum + elif lnum > rnum: + return (fmt % (ltext, rtext), lnum + rnum) + # rnum is multiplied by lnum + elif lnum < rnum: + return rendaku_merge_pairs(lpair, rpair) + + def _ordinal_suffix(self, reading, counter): + if reading: + if counter == "番": + return "ばんめ" + else: + raise NotImplementedError( + "Reading not implemented for %s" % counter) + else: + return counter + "目" + + def to_ordinal(self, value, reading=False, prefer=None, counter="番"): + self.verify_ordinal(value) + base = self.to_cardinal(value, reading=reading, prefer=prefer) + return "%s%s" % (base, self._ordinal_suffix(reading, counter)) + + def to_ordinal_num(self, value, reading=False, counter="番"): + return "%s%s" % (value, self._ordinal_suffix(reading, counter)) + + def to_year(self, val, suffix=None, longval=True, reading=False, + prefer=None, era=True): + year = val + # Gregorian calendar + if not era: + prefix = "" + if year < 0: + year = abs(year) + prefix = "きげんぜん" if reading else "紀元前" + + year_words = self.to_cardinal(year, reading=reading, prefer=prefer) + if reading and year % 10 == 9: + year_words = year_words[:-3] + "く" + + return "%s%s%s" % (prefix, year_words, "ねん" if reading else "年") + + # Era calendar (default) + min_year = ERA_START[0][0] + last_era_idx = len(ERA_START) - 1 + if year < min_year: + raise ValueError( + "Can't convert years less than %s to era" % min_year) + + first = 0 + last = last_era_idx + era_idx = None + while era_idx is None: + mid = (first + last) // 2 + if mid == last_era_idx or (ERA_START[mid][0] <= year and + ERA_START[mid + 1][0] > year): + era_idx = mid + # if an era lasting less than a year is preferred, choose it + if prefer: + i = mid - 1 + while i >= 0 and ERA_START[i][0] == year: + # match kanji or hiragana + if set(ERA_START[i][1]) & set(prefer): + era_idx = i + break + i -= 1 + + # ends up at the last index where year >= ERA_START[mid][0] + if year < ERA_START[mid][0]: + last = mid - 1 + else: + first = mid + 1 + + era = ERA_START[era_idx] + era_name = era[1][0] + era_year = year - era[0] + 1 + fmt = "%s%s年" + if reading == "arabic": + era_year_words = str(era_year) + elif reading: + era_name = era[1][1] + era_year_words = (self.to_cardinal(era_year, reading=True, + prefer=prefer) + if era_year != 1 else "がん") + if era_year % 10 == 9: + era_year_words = era_year_words[:-3] + "く" + fmt = "%s%sねん" + else: + era_year_words = (self.to_cardinal(era_year, reading=False, + prefer=prefer) + if era_year != 1 else "元") + + return fmt % (era_name, era_year_words) + + def to_currency(self, val, currency="JPY", cents=False, seperator="", + adjective=False, reading=False, prefer=None): + left, right, is_negative = parse_currency_parts( + val, is_int_with_cents=cents) + + try: + cr1, cr2 = self.CURRENCY_FORMS[currency] + if (cents or abs(val) != left) and not cr2: + raise ValueError('Decimals not supported for "%s"' % currency) + except KeyError: + raise NotImplementedError( + 'Currency code "%s" not implemented for "%s"' % + (currency, self.__class__.__name__)) + + if adjective and currency in self.CURRENCY_ADJECTIVES: + cr1 = prefix_currency(self.CURRENCY_ADJECTIVES[currency], cr1) + + minus_str = self.negword if is_negative else "" + + return '%s%s%s%s%s' % ( + minus_str, + self.to_cardinal(left, reading=reading, prefer=prefer), + cr1[1] if reading else cr1[0], + self.to_cardinal(right, reading=reading, prefer=prefer) + if cr2 else '', + (cr2[1] if reading else cr2[0]) if cr2 else '', + ) + + def splitnum(self, value, reading, prefer): + for elem in self.cards: + if elem > value: + continue + + out = [] + if value == 0: + div, mod = 1, 0 + else: + div, mod = divmod(value, elem) + + if div == 1: + out.append((select_text(self.cards[1], reading, prefer), 1)) + else: + if div == value: # The system tallies, eg Roman Numerals + return [( + div * select_text(self.cards[elem], reading, prefer), + div * elem)] + out.append(self.splitnum(div, reading, prefer)) + + out.append((select_text(self.cards[elem], reading, prefer), elem)) + + if mod: + out.append(self.splitnum(mod, reading, prefer)) + + return out + + def to_cardinal(self, value, reading=False, prefer=None): + try: + assert int(value) == value + except (ValueError, TypeError, AssertionError): + return self.to_cardinal_float(value, reading=reading, + prefer=prefer) + + out = "" + if value < 0: + value = abs(value) + out = self.negword + + if value >= self.MAXVAL: + raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL)) + + val = self.splitnum(value, reading, prefer) + words, _ = self.clean(val) + return self.title(out + words) + + def to_cardinal_float(self, value, reading=False, prefer=None): + prefer = prefer or ["れい"] + try: + float(value) == value + except (ValueError, TypeError, AssertionError): + raise TypeError(self.errmsg_nonnum % value) + + pre, post = self.float2tuple(float(value)) + + post = str(post) + post = '0' * (self.precision - len(post)) + post + + out = [self.to_cardinal(pre, reading=reading, prefer=prefer)] + if self.precision: + out.append(self.title(self.pointword[1 if reading else 0])) + + for i in range(self.precision): + curr = int(post[i]) + out.append(to_s( + self.to_cardinal(curr, reading=reading, prefer=prefer))) + + return "".join(out) diff -Nru python-num2words-0.5.6/num2words/lang_KO.py python-num2words-0.5.9/num2words/lang_KO.py --- python-num2words-0.5.6/num2words/lang_KO.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_KO.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import division, print_function, unicode_literals + +from .base import Num2Word_Base +from .currency import parse_currency_parts + + +class Num2Word_KO(Num2Word_Base): + CURRENCY_FORMS = { + 'KRW': ('원', None), + 'USD': ('달러', '센트'), + 'JPY': ('엔', None) + } + + def set_high_numwords(self, high): + max = 4 * len(high) + for word, n in zip(high, range(max, 0, -4)): + self.cards[10 ** n] = word + + def setup(self): + super(Num2Word_KO, self).setup() + + self.negword = "마이너스 " + self.pointword = "점" + + self.high_numwords = [ + '무량대수', + '불가사의', + '나유타', + '아승기', + '항하사', + '극', + '재', + '정', + '간', + '구', + '양', + '자', + '해', + '경', + '조', + '억', + '만'] + self.mid_numwords = [(1000, "천"), (100, "백")] + self.low_numwords = ["십", "구", "팔", "칠", "육", "오", "사", "삼", "이", + "일", "영"] + self.ords = {"일": "한", + "이": "두", + "삼": "세", + "사": "네", + "오": "다섯", + "육": "여섯", + "칠": "일곱", + "팔": "여덟", + "구": "아홉", + "십": "열", + "이십": "스물", + "삼십": "서른", + "사십": "마흔", + "오십": "쉰", + "육십": "예순", + "칠십": "일흔", + "팔십": "여든", + "구십": "아흔"} + + def merge(self, lpair, rpair): + ltext, lnum = lpair + rtext, rnum = rpair + if lnum == 1 and rnum <= 10000: + return rpair + elif 10000 > lnum > rnum: + return ("%s%s" % (ltext, rtext), lnum + rnum) + elif lnum >= 10000 and lnum > rnum: + return ("%s %s" % (ltext, rtext), lnum + rnum) + else: + return ("%s%s" % (ltext, rtext), lnum * rnum) + + def to_ordinal(self, value): + self.verify_ordinal(value) + if(value == 1): + return "첫 번째" + outwords = self.to_cardinal(value).split(" ") + lastwords = outwords[-1].split("백") + if "십" in lastwords[-1]: + ten_one = lastwords[-1].split("십") + ten_one[0] = self.ords[ten_one[0] + "십"] + try: + ten_one[1] = self.ords[ten_one[1]] + ten_one[0] = ten_one[0].replace("스무", "스물") + except KeyError: + pass + lastwords[-1] = ''.join(ten_one) + else: + lastwords[-1] = self.ords[lastwords[-1]] + outwords[-1] = "백 ".join(lastwords) + return " ".join(outwords) + " 번째" + + def to_ordinal_num(self, value): + self.verify_ordinal(value) + return "%s 번째" % (value) + + def to_year(self, val, suffix=None, longval=True): + if val < 0: + val = abs(val) + suffix = '기원전' if not suffix else suffix + valtext = self.to_cardinal(val) + return ("%s년" % valtext if not suffix + else "%s %s년" % (suffix, valtext)) + + def to_currency(self, val, currency="KRW", cents=False, seperator="", + adjective=False): + left, right, is_negative = parse_currency_parts( + val, is_int_with_cents=cents) + + try: + cr1, cr2 = self.CURRENCY_FORMS[currency] + if (cents or right) and not cr2: + raise ValueError('Decimals not supported for "%s"' % currency) + except KeyError: + raise NotImplementedError( + 'Currency code "%s" not implemented for "%s"' % + (currency, self.__class__.__name__)) + + minus_str = self.negword if is_negative else "" + return '%s%s%s%s%s' % ( + minus_str, + ''.join(self.to_cardinal(left).split()), + cr1, + ' ' + self.to_cardinal(right) + if cr2 else '', + cr2 if cr2 else '', + ) diff -Nru python-num2words-0.5.6/num2words/lang_LT.py python-num2words-0.5.9/num2words/lang_LT.py --- python-num2words-0.5.6/num2words/lang_LT.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_LT.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -14,13 +14,26 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA + from __future__ import unicode_literals from .base import Num2Word_Base -from .utils import get_digits, splitby3 +from .utils import get_digits, splitbyx ZERO = ('nulis',) +ONES_FEMININE = { + 1: ('viena',), + 2: ('dvi',), + 3: ('trys',), + 4: ('keturios',), + 5: ('penkios',), + 6: ('šešios',), + 7: ('septynios',), + 8: ('aštuonios',), + 9: ('devynios',), +} + ONES = { 1: ('vienas',), 2: ('du',), @@ -72,21 +85,31 @@ 10: ('naintilijonas', 'naintilijonai', 'naintilijonų'), } +GENERIC_CENTS = ('centas', 'centai', 'centų') + class Num2Word_LT(Num2Word_Base): CURRENCY_FORMS = { - 'LTL': (('litas', 'litai', 'litų'), ('centas', 'centai', 'centų')), - 'EUR': (('euras', 'eurai', 'eurų'), ('centas', 'centai', 'centų')), + 'LTL': (('litas', 'litai', 'litų'), GENERIC_CENTS), + 'EUR': (('euras', 'eurai', 'eurų'), GENERIC_CENTS), + 'USD': (('doleris', 'doleriai', 'dolerių'), GENERIC_CENTS), + 'GBP': ( + ('svaras sterlingų', 'svarai sterlingų', 'svarų sterlingų'), + ('pensas', 'pensai', 'pensų') + ), + 'PLN': ( + ('zlotas', 'zlotai', 'zlotų'), + ('grašis', 'grašiai', 'grašių')), + 'RUB': ( + ('rublis', 'rubliai', 'rublių'), + ('kapeika', 'kapeikos', 'kapeikų') + ), } def setup(self): 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: @@ -98,29 +121,38 @@ def to_cardinal(self, number): n = str(number).replace(',', '.') + base_str, n = self.parse_minus(n) if '.' in n: left, right = n.split('.') - return '%s %s %s' % ( + return '%s%s %s %s' % ( + base_str, self._int2word(int(left)), self.pointword, self._int2word(int(right)) ) else: - return self._int2word(int(n)) + return "%s%s" % (base_str, self._int2word(int(n))) def to_ordinal(self, number): raise NotImplementedError() - def _int2word(self, n): + def _cents_verbose(self, number, currency): + return self._int2word(number, currency == 'RUB') + + def _int2word(self, n, feminine=False): if n == 0: return ZERO[0] words = [] - chunks = list(splitby3(str(n))) + chunks = list(splitbyx(str(n), 3)) i = len(chunks) for x in chunks: i -= 1 + + if x == 0: + continue + n1, n2, n3 = get_digits(x) if n3 > 0: @@ -136,7 +168,10 @@ if n2 == 1: words.append(TENS[n1][0]) elif n1 > 0: - words.append(ONES[n1][0]) + if (i == 1 or feminine and i == 0) and n < 1000: + words.append(ONES_FEMININE[n1][0]) + else: + words.append(ONES[n1][0]) if i > 0: words.append(self.pluralize(x, THOUSANDS[i])) diff -Nru python-num2words-0.5.6/num2words/lang_LV.py python-num2words-0.5.9/num2words/lang_LV.py --- python-num2words-0.5.6/num2words/lang_LV.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_LV.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -14,10 +14,11 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA + from __future__ import unicode_literals from .base import Num2Word_Base -from .utils import get_digits, splitby3 +from .utils import get_digits, splitbyx ZERO = ('nulle',) @@ -126,21 +127,19 @@ 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) if '.' in n: left, right = n.split('.') - return u'%s %s %s' % ( + return '%s%s %s %s' % ( + base_str, self._int2word(int(left)), self.pointword, self._int2word(int(right)) ) else: - return self._int2word(int(n)) + return "%s%s" % (base_str, self._int2word(int(n))) def pluralize(self, n, forms): form = 0 if (n % 10 == 1 and n % 100 != 11) else 1 if n != 0 else 2 @@ -154,10 +153,14 @@ return ZERO[0] words = [] - chunks = list(splitby3(str(n))) + chunks = list(splitbyx(str(n), 3)) i = len(chunks) for x in chunks: i -= 1 + + if x == 0: + continue + n1, n2, n3 = get_digits(x) if n3 > 0: @@ -177,7 +180,7 @@ elif n1 > 0 and not (i > 0 and x == 1): words.append(ONES[n1][0]) - if i > 0 and x != 0: + if i > 0: words.append(self.pluralize(x, THOUSANDS[i])) return ' '.join(words) diff -Nru python-num2words-0.5.6/num2words/lang_NL.py python-num2words-0.5.9/num2words/lang_NL.py --- python-num2words-0.5.6/num2words/lang_NL.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_NL.py 2019-01-11 01:09:08.000000000 +0000 @@ -21,31 +21,33 @@ class Num2Word_NL(Num2Word_EU): - def set_high_numwords(self, high): - max = 3 + 6 * len(high) + CURRENCY_FORMS = { + 'EUR': (('euro', 'euros'), ('cent', 'cents')), + } - 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." self.errmsg_floatord = ( "Het zwevende puntnummer %s kan niet omgezet worden " + "naar een ordernummer." - ) + ) # "type(((type(%s)) ) not in [long, int, float]" self.errmsg_nonnum = ( "Alleen nummers (type (%s)) kunnen naar " + "woorden omgezet worden." - ) + ) # "Cannot treat negative num %s as ordinal." self.errmsg_negord = ( "Het negatieve getal %s kan niet omgezet " + "worden naar een ordernummer." - ) + ) # "abs(%s) must be less than %s." self.errmsg_toobig = "Het getal %s moet minder zijn dan %s." self.exclude_title = [] @@ -57,13 +59,14 @@ "sexagint", "septuagint", "oktogint", "nonagint"] self.high_numwords = ( - ["zend"] + self.gen_high_numwords(units, tens, lows) - ) + ["zend"] + self.gen_high_numwords(units, tens, lows)) + self.mid_numwords = [(1000, "duizend"), (100, "honderd"), (90, "negentig"), (80, "tachtig"), (70, "zeventig"), (60, "zestig"), (50, "vijftig"), (40, "veertig"), (30, "dertig")] + self.low_numwords = ["twintig", "negentien", "achttien", "zeventien", "zestien", "vijftien", "veertien", "dertien", "twaalf", "elf", "tien", "negen", "acht", "zeven", @@ -116,7 +119,7 @@ val = cnum + nnum word = ctext + ntext - return (word, val) + return word, val def to_ordinal(self, value): self.verify_ordinal(value) @@ -131,41 +134,19 @@ self.verify_ordinal(value) return str(value) + "." - def to_currency(self, val, longval=True, old=False): - if old: - return self.to_splitnum(val, hightxt="euro/s", lowtxt="cent/s", - jointxt="en", longval=longval) - return super(Num2Word_NL, self).to_currency(val, jointxt="en", - longval=longval) + def pluralize(self, n, forms): + """ + :param n: + :param forms: + :return: + + gettext form is nplurals=2; plural=(n != 1); + but this claims https://onzetaal.nl/taaladvies/euro-euros/ + not sure if it's applied only to euro + """ + return forms[0] def to_year(self, val, longval=True): 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 -Nru python-num2words-0.5.6/num2words/lang_NO.py python-num2words-0.5.9/num2words/lang_NO.py --- python-num2words-0.5.6/num2words/lang_NO.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_NO.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -20,16 +21,24 @@ 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 +106,3 @@ 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 -Nru python-num2words-0.5.6/num2words/lang_PL.py python-num2words-0.5.9/num2words/lang_PL.py --- python-num2words-0.5.6/num2words/lang_PL.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_PL.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -14,10 +14,11 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA + from __future__ import unicode_literals from .base import Num2Word_Base -from .utils import get_digits, splitby3 +from .utils import get_digits, splitbyx ZERO = ('zero',) @@ -66,20 +67,31 @@ 6: ('sześćset',), 7: ('siedemset',), 8: ('osiemset',), - 9: ('dziewęćset',), + 9: ('dziewięćset',), } THOUSANDS = { - 1: ('tysiąc', 'tysiące', 'tysięcy'), # 10^3 - 2: ('milion', 'miliony', 'milionów'), # 10^6 - 3: ('miliard', 'miliardy', 'miliardów'), # 10^9 - 4: ('bilion', 'biliony', 'bilionów'), # 10^12 - 5: ('biliard', 'biliardy', 'biliardów'), # 10^15 - 6: ('trylion', 'tryliony', 'trylionów'), # 10^18 - 7: ('tryliard', 'tryliardy', 'tryliardów'), # 10^21 - 8: ('kwadrylion', 'kwadryliony', 'kwadrylionów'), # 10^24 - 9: ('kwaryliard', 'kwadryliardy', 'kwadryliardów'), # 10^27 - 10: ('kwintylion', 'kwintyliony', 'kwintylionów'), # 10^30 + 1: ('tysiąc', 'tysiące', 'tysięcy'), # 10^3 + 2: ('milion', 'miliony', 'milionów'), # 10^6 + 3: ('miliard', 'miliardy', 'miliardów'), # 10^9 + 4: ('bilion', 'biliony', 'bilionów'), # 10^12 + 5: ('biliard', 'biliardy', 'biliardów'), # 10^15 + 6: ('trylion', 'tryliony', 'trylionów'), # 10^18 + 7: ('tryliard', 'tryliardy', 'tryliardów'), # 10^21 + 8: ('kwadrylion', 'kwadryliony', 'kwadrylionów'), # 10^24 + 9: ('kwadryliard', 'kwadryliardy', 'kwadryliardów'), # 10^27 + 10: ('kwintylion', 'kwintyliony', 'kwintylionów'), # 10^30 + 11: ('kwintyliard', 'kwintyliardy', 'kwintyliardów'), # 10^33 + 12: ('sekstylion', 'sekstyliony', 'sekstylionów'), # 10^36 + 13: ('sekstyliard', 'sekstyliardy', 'sekstyliardów'), # 10^39 + 14: ('septylion', 'septyliony', 'septylionów'), # 10^42 + 15: ('septyliard', 'septyliardy', 'septyliardów'), # 10^45 + 16: ('oktylion', 'oktyliony', 'oktylionów'), # 10^48 + 17: ('oktyliard', 'oktyliardy', 'oktyliardów'), # 10^51 + 18: ('nonylion', 'nonyliony', 'nonylionów'), # 10^54 + 19: ('nonyliard', 'nonyliardy', 'nonyliardów'), # 10^57 + 20: ('decylion', 'decyliony', 'decylionów'), # 10^60 + 21: ('decyliard', 'decyliardy', 'decyliardów'), # 10^63 } @@ -97,10 +109,6 @@ 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: @@ -130,10 +138,14 @@ return ZERO[0] words = [] - chunks = list(splitby3(str(n))) + chunks = list(splitbyx(str(n), 3)) i = len(chunks) for x in chunks: i -= 1 + + if x == 0: + continue + n1, n2, n3 = get_digits(x) if n3 > 0: diff -Nru python-num2words-0.5.6/num2words/lang_PT_BR.py python-num2words-0.5.9/num2words/lang_PT_BR.py --- python-num2words-0.5.6/num2words/lang_PT_BR.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_PT_BR.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -15,76 +14,26 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA - from __future__ import division, unicode_literals import re -from . import lang_EU +from . import lang_PT -class Num2Word_PT_BR(lang_EU.Num2Word_EU): +class Num2Word_PT_BR(lang_PT.Num2Word_PT): def set_high_numwords(self, high): max = 3 + 3*len(high) for word, n in zip(high, range(max, 3, -3)): self.cards[10**n] = word + "ilhão" def setup(self): - 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 = [ - (1000, "mil"), (100, "cem"), (90, "noventa"), - (80, "oitenta"), (70, "setenta"), (60, "sessenta"), - (50, "cinquenta"), (40, "quarenta"), (30, "trinta") - ] - self.low_numwords = [ - "vinte", "dezenove", "dezoito", "dezessete", "dezesseis", - "quinze", "catorze", "treze", "doze", "onze", "dez", - "nove", "oito", "sete", "seis", "cinco", "quatro", "três", "dois", - "um", "zero" - ] - self.ords = [ - { - 0: "", - 1: "primeiro", - 2: "segundo", - 3: "terceiro", - 4: "quarto", - 5: "quinto", - 6: "sexto", - 7: "sétimo", - 8: "oitavo", - 9: "nono", - }, - { - 0: "", - 1: "décimo", - 2: "vigésimo", - 3: "trigésimo", - 4: "quadragésimo", - 5: "quinquagésimo", - 6: "sexagésimo", - 7: "septuagésimo", - 8: "octogésimo", - 9: "nonagésimo", - }, - { - 0: "", - 1: "centésimo", - 2: "ducentésimo", - 3: "tricentésimo", - 4: "quadrigentésimo", - 5: "quingentésimo", - 6: "seiscentésimo", - 7: "septigentésimo", - 8: "octigentésimo", - 9: "nongentésimo", - }, - ] + super(Num2Word_PT_BR, self).setup() + + self.low_numwords[1] = 'dezenove' + self.low_numwords[3] = 'dezessete' + self.low_numwords[4] = 'dezesseis' + self.thousand_separators = { 3: "milésimo", 6: "milionésimo", @@ -92,17 +41,6 @@ 12: "trilionésimo", 15: "quadrilionésimo" } - self.hundreds = { - 1: "cento", - 2: "duzentos", - 3: "trezentos", - 4: "quatrocentos", - 5: "quinhentos", - 6: "seiscentos", - 7: "setecentos", - 8: "oitocentos", - 9: "novecentos", - } def merge(self, curr, next): ctext, cnum, ntext, nnum = curr + next @@ -132,58 +70,20 @@ return (ctext + ntext, cnum * nnum) def to_cardinal(self, value): - result = super(Num2Word_PT_BR, self).to_cardinal(value) + result = lang_PT.Num2Word_EU.to_cardinal(self, value) # Transforms "mil E cento e catorze reais" into "mil, cento e catorze # reais" for ext in ( 'mil', 'milhão', 'milhões', 'bilhão', 'bilhões', 'trilhão', 'trilhões', 'quatrilhão', 'quatrilhões'): - if re.match('.*{} e \w*ento'.format(ext), result): + if re.match('.*{} e \\w*ento'.format(ext), result): result = result.replace( '{} e'.format(ext), '{},'.format(ext), 1 ) return result - def to_ordinal(self, value): - self.verify_ordinal(value) - - result = [] - value = str(value) - thousand_separator = '' - - for idx, char in enumerate(value[::-1]): - if idx and idx % 3 == 0: - thousand_separator = self.thousand_separators[idx] - - if char != '0' and thousand_separator: - # avoiding "segundo milionésimo milésimo" for 6000000, - # for instance - result.append(thousand_separator) - thousand_separator = '' - - result.append(self.ords[idx % 3][int(char)]) - - result = ' '.join(result[::-1]) - result = result.strip() - result = re.sub('\s+', ' ', result) - - if result.startswith('primeiro') and value != '1': - # avoiding "primeiro milésimo", "primeiro milionésimo" and so on - result = result[9:] - - return result - - def to_ordinal_num(self, value): - self.verify_ordinal(value) - return "%sº" % (value) - - def to_year(self, val, longval=True): - if val < 0: - return self.to_cardinal(abs(val)) + ' antes de Cristo' - return self.to_cardinal(val) - def to_currency(self, val, longval=True): integer_part, decimal_part = ('%.2f' % val).split('.') diff -Nru python-num2words-0.5.6/num2words/lang_PT.py python-num2words-0.5.9/num2words/lang_PT.py --- python-num2words-0.5.6/num2words/lang_PT.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_PT.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,246 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import division, unicode_literals + +import re + +from .lang_EU import Num2Word_EU + +DOLLAR = ('dólar', 'dólares') +CENTS = ('cêntimo', 'cêntimos') + + +class Num2Word_PT(Num2Word_EU): + + CURRENCY_FORMS = { + 'AUD': (DOLLAR, CENTS), + 'CAD': (DOLLAR, CENTS), + 'EUR': (('euro', 'euros'), CENTS), + 'GBP': (('libra', 'libras'), ('péni', 'pence')), + 'USD': (DOLLAR, CENTS), + } + + GIGA_SUFFIX = None + MEGA_SUFFIX = "ilião" + + def setup(self): + super(Num2Word_PT, self).setup() + lows = ["quatr", "tr", "b", "m"] + self.high_numwords = self.gen_high_numwords([], [], lows) + self.negword = "menos " + self.pointword = "vírgula" + self.exclude_title = ["e", "vírgula", "menos"] + + self.mid_numwords = [ + (1000, "mil"), (100, "cem"), (90, "noventa"), + (80, "oitenta"), (70, "setenta"), (60, "sessenta"), + (50, "cinquenta"), (40, "quarenta"), (30, "trinta") + ] + self.low_numwords = [ + "vinte", "dezanove", "dezoito", "dezassete", "dezasseis", + "quinze", "catorze", "treze", "doze", "onze", "dez", + "nove", "oito", "sete", "seis", "cinco", "quatro", "três", "dois", + "um", "zero" + ] + self.ords = [ + { + 0: "", + 1: "primeiro", + 2: "segundo", + 3: "terceiro", + 4: "quarto", + 5: "quinto", + 6: "sexto", + 7: "sétimo", + 8: "oitavo", + 9: "nono", + }, + { + 0: "", + 1: "décimo", + 2: "vigésimo", + 3: "trigésimo", + 4: "quadragésimo", + 5: "quinquagésimo", + 6: "sexagésimo", + 7: "septuagésimo", + 8: "octogésimo", + 9: "nonagésimo", + }, + { + 0: "", + 1: "centésimo", + 2: "ducentésimo", + 3: "tricentésimo", + 4: "quadrigentésimo", + 5: "quingentésimo", + 6: "seiscentésimo", + 7: "septigentésimo", + 8: "octigentésimo", + 9: "nongentésimo", + }, + ] + self.thousand_separators = { + 3: "milésimo", + 6: "milionésimo", + 9: "milésimo milionésimo", + 12: "bilionésimo", + 15: "milésimo bilionésimo" + } + self.hundreds = { + 1: "cento", + 2: "duzentos", + 3: "trezentos", + 4: "quatrocentos", + 5: "quinhentos", + 6: "seiscentos", + 7: "setecentos", + 8: "oitocentos", + 9: "novecentos", + } + + def merge(self, curr, next): + ctext, cnum, ntext, nnum = curr + next + + if cnum == 1: + if nnum < 1000000: + return next + ctext = "um" + elif cnum == 100 and not nnum % 1000 == 0: + ctext = "cento" + + if nnum < cnum: + if cnum < 100: + return ("%s e %s" % (ctext, ntext), cnum + nnum) + return ("%s e %s" % (ctext, ntext), cnum + nnum) + + elif (not nnum % 1000000000) and cnum > 1: + ntext = ntext[:-4] + "liões" + elif (not nnum % 1000000) and cnum > 1: + ntext = ntext[:-4] + "lhões" + # correct "milião" to "milhão" + if ntext == 'milião': + ntext = 'milhão' + if nnum == 100: + ctext = self.hundreds[cnum] + ntext = "" + + else: + ntext = " " + ntext + + return (ctext + ntext, cnum * nnum) + + def to_cardinal(self, value): + result = super(Num2Word_PT, self).to_cardinal(value) + + # Transforms "mil e cento e catorze" into "mil cento e catorze" + # Transforms "cem milhões e duzentos mil e duzentos e dez" em "cem + # milhões duzentos mil duzentos e dez" but "cem milhões e duzentos + # mil e duzentos" in "cem milhões duzentos mil e duzentos" and not in + # "cem milhões duzentos mil duzentos" + for ext in ( + 'mil', 'milhão', 'milhões', 'mil milhões', + 'bilião', 'biliões', 'mil biliões'): + if re.match('.*{} e \\w*entos? (?=.*e)'.format(ext), result): + result = result.replace( + '{} e'.format(ext), '{}'.format(ext) + ) + + return result + + # for the ordinal conversion the code is similar to pt_BR code, + # although there are other rules that are probably more correct in + # Portugal. Concerning numbers from 2000th on, saying "dois + # milésimos" instead of "segundo milésimo" (the first number + # would be used in the cardinal form instead of the ordinal) is better. + # This was not implemented. + # source: + # https://ciberduvidas.iscte-iul.pt/consultorio/perguntas/a-forma-por-extenso-de-2000-e-de-outros-ordinais/16428 + def to_ordinal(self, value): + # Before changing this function remember this is used by pt-BR + # so act accordingly + self.verify_ordinal(value) + + result = [] + value = str(value) + thousand_separator = '' + + for idx, char in enumerate(value[::-1]): + if idx and idx % 3 == 0: + thousand_separator = self.thousand_separators[idx] + + if char != '0' and thousand_separator: + # avoiding "segundo milionésimo milésimo" for 6000000, + # for instance + result.append(thousand_separator) + thousand_separator = '' + + result.append(self.ords[idx % 3][int(char)]) + + result = ' '.join(result[::-1]) + result = result.strip() + result = re.sub('\\s+', ' ', result) + + if result.startswith('primeiro') and value != '1': + # avoiding "primeiro milésimo", "primeiro milionésimo" and so on + result = result[9:] + + return result + + def to_ordinal_num(self, value): + # Before changing this function remember this is used by pt-BR + # so act accordingly + self.verify_ordinal(value) + return "%sº" % (value) + + def to_year(self, val, longval=True): + # Before changing this function remember this is used by pt-BR + # so act accordingly + if val < 0: + return self.to_cardinal(abs(val)) + ' antes de Cristo' + return self.to_cardinal(val) + + def to_currency(self, val, currency='EUR', cents=True, seperator=' e', + adjective=False): + # change negword because base.to_currency() does not need space after + backup_negword = self.negword + self.negword = self.negword[:-1] + result = super(Num2Word_PT, self).to_currency( + val, currency=currency, cents=cents, seperator=seperator, + adjective=adjective) + # undo the change on negword + self.negword = backup_negword + + # transforms "milhões euros" em "milhões de euros" + try: + cr1, _ = self.CURRENCY_FORMS[currency] + except KeyError: + raise NotImplementedError( + 'Currency code "%s" not implemented for "%s"' % + (currency, self.__class__.__name__)) + + for ext in ( + 'milhão', 'milhões', 'bilião', + 'biliões', 'trilião', 'triliões'): + if re.match('.*{} (?={})'.format(ext, cr1[1]), result): + result = result.replace( + '{}'.format(ext), '{} de'.format(ext), 1 + ) + # do not print "e zero cêntimos" + result = result.replace(' e zero cêntimos', '') + return result diff -Nru python-num2words-0.5.6/num2words/lang_RO.py python-num2words-0.5.9/num2words/lang_RO.py --- python-num2words-0.5.6/num2words/lang_RO.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_RO.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import division, print_function, unicode_literals + +from . import lang_EU + + +class Num2Word_RO(lang_EU.Num2Word_EU): + GIGA_SUFFIX = "iliard/e" + MEGA_SUFFIX = "ilion" + # inflection for million follows different rule + MEGA_SUFFIX_I = "ilioane" + + def setup(self): + super(Num2Word_RO, self).setup() + + self.negword = "minus " + self.pointword = "virgulă" + self.exclude_title = ["și", "virgulă", "minus"] + self.errmsg_toobig = ( + "Numărul e prea mare pentru a fi convertit în cuvinte." + ) + self.mid_numwords = [(1000, "mie/i"), (100, "sută/e"), + (90, "nouăzeci"), (80, "optzeci"), + (70, "șaptezeci"), (60, "șaizeci"), + (50, "cincizeci"), (40, "patruzeci"), + (30, "treizeci")] + self.low_numwords = ["douăzeci", "nouăsprezece", "optsprezece", + "șaptesprezece", "șaisprezece", "cincisprezece", + "paisprezece", "treisprezece", "doisprezece", + "unsprezece", "zece", "nouă", "opt", "șapte", + "șase", "cinci", "patru", "trei", "doi", + "unu", "zero"] + self.gen_numwords = ["", "o", "două", "trei", "patru", "cinci", + "șase", "șapte", "opt", "nouă"] + self.gen_numwords_m = ["", "un", "două", "trei", "patru", "cinci", + "șase", "șapte", "opt", "nouă"] + self.numwords_inflections = { + 100: self.gen_numwords, + 1000: self.gen_numwords, + 1000000: self.gen_numwords_m, + 1000000000: self.gen_numwords_m + } + self.ords = {"unu": "primul", + "doi": "al doilea", + "three": "al treilea", + "cinci": "al cincilea", + "opt": "al optulea", + "nouă": "al nouălea", + "doisprezece": "al doisprezecelea"} + + def merge(self, lpair, rpair): + ltext, lnum = lpair + rtext, rnum = rpair + rtext_i = self.inflect(rnum, rtext) + if lnum > 1 and rtext_i.endswith(self.MEGA_SUFFIX): + rtext_i = rtext_i.replace(self.MEGA_SUFFIX, self.MEGA_SUFFIX_I) + if 1 <= lnum < 10: + if rnum not in self.numwords_inflections: + return (rtext, rnum) + else: + rtext_i = self.inflect(lnum * rnum, rtext) + lresult = (self.numwords_inflections[rnum][lnum], rtext_i) + return ("%s %s" % lresult, rnum) + elif 10 < lnum < 100: + if lnum % 10 == 0: + return ("%s și %s" % (ltext, rtext), lnum + rnum) + else: + return ("%s %s" % (ltext, rtext_i), lnum * rnum) + else: + if rnum in self.numwords_inflections: + rtext_i = self.inflect(lnum * rnum, rtext) + return ("%s %s" % (ltext, rtext_i), lnum * rnum) + + def to_ordinal(self, value): + self.verify_ordinal(value) + if value == 1: + return "primul" + else: + value = self.to_cardinal(value) + return "al %slea" % (value) + + def to_ordinal_num(self, value): + self.verify_ordinal(value) + if value == 1: + return "1-ul" + return "al %s-lea" % (value) + + def inflect(self, value, text): + text = text.split("/") + if value in (1, 100, 1000, 100000, 1000000000): + return text[0] + if len(text) > 1 and text[0][-1] in "aăeiou": + text[0] = text[0][:-1] + return "".join(text) + + def to_currency(self, val, longval=True, old=False): + cents = int(round(val*100)) + result = self.to_splitnum(cents, hightxt="leu/i", lowtxt="ban/i", + divisor=100, jointxt="și", longval=longval) + return result.replace( + "unu leu", "un leu" + ).replace("unu ban", "un ban") + + def to_year(self, val, suffix=None, longval=True): + result = super(Num2Word_RO, self).to_year( + val, + longval=longval + ) + # for years we want the era negation e.g. B.C., in our case + # it's î.Hr. or î.e.n + if result.startswith(self.negword): + result = result.replace(self.negword, "") + suffix = "î.Hr." if not suffix else suffix + if suffix: + result = "".join([ + result, + " ", + suffix + ]) + return result diff -Nru python-num2words-0.5.6/num2words/lang_RU.py python-num2words-0.5.9/num2words/lang_RU.py --- python-num2words-0.5.6/num2words/lang_RU.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_RU.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -14,10 +14,11 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA + from __future__ import unicode_literals from .base import Num2Word_Base -from .utils import get_digits, splitby3 +from .utils import get_digits, splitbyx ZERO = ('ноль',) @@ -103,15 +104,35 @@ 'EUR': ( ('евро', 'евро', 'евро'), ('цент', 'цента', 'центов') ), + 'USD': ( + ('доллар', 'доллара', 'долларов'), ('цент', 'цента', 'центов') + ), } def setup(self): self.negword = "минус" self.pointword = "запятая" - - def set_numwords(self): - # @FIXME - self.cards[0] = [] + self.ords = {"ноль": "нулевой", + "один": "первый", + "два": "второй", + "три": "третий", + "четыре": "четвертый", + "пять": "пятый", + "шесть": "шестой", + "семь": "седьмой", + "восемь": "восьмой", + "девять": "девятый", + "сто": "сотый"} + self.ords_feminine = {"один": "", + "одна": "", + "две": "двух", + "три": "трёх", + "четыре": "четырёх", + "пять": "пяти", + "шесть": "шести", + "семь": "семи", + "восемь": "восьми", + "девять": "девяти"} def to_cardinal(self, number): n = str(number).replace(',', '.') @@ -138,7 +159,41 @@ return forms[form] def to_ordinal(self, number): - raise NotImplementedError() + self.verify_ordinal(number) + outwords = self.to_cardinal(number).split(" ") + lastword = outwords[-1].lower() + try: + if len(outwords) > 1: + if outwords[-2] in self.ords_feminine: + outwords[-2] = self.ords_feminine.get( + outwords[-2], outwords[-2]) + elif outwords[-2] == 'десять': + outwords[-2] = outwords[-2][:-1] + 'и' + if len(outwords) == 3: + if outwords[-3] in ['один', 'одна']: + outwords[-3] = '' + lastword = self.ords[lastword] + except KeyError: + if lastword[:-3] in self.ords_feminine: + lastword = self.ords_feminine.get( + lastword[:-3], lastword) + "сотый" + elif lastword[-1] == "ь" or lastword[-2] == "т": + lastword = lastword[:-1] + "ый" + elif lastword[-1] == "к": + lastword = lastword + "овой" + elif lastword[-5:] == "десят": + lastword = lastword.replace('ь', 'и') + 'ый' + elif lastword[-2] == "ч" or lastword[-1] == "ч": + if lastword[-2] == "ч": + lastword = lastword[:-1] + "ный" + if lastword[-1] == "ч": + lastword = lastword + "ный" + elif lastword[-1] == "н" or lastword[-2] == "н": + lastword = lastword[:lastword.rfind('н') + 1] + "ный" + elif lastword[-1] == "д" or lastword[-2] == "д": + lastword = lastword[:lastword.rfind('д') + 1] + "ный" + outwords[-1] = self.title(lastword) + return " ".join(outwords).strip() def _cents_verbose(self, number, currency): return self._int2word(number, currency == 'RUB') @@ -151,10 +206,14 @@ return ZERO[0] words = [] - chunks = list(splitby3(str(n))) + chunks = list(splitbyx(str(n), 3)) i = len(chunks) for x in chunks: i -= 1 + + if x == 0: + continue + n1, n2, n3 = get_digits(x) if n3 > 0: @@ -169,7 +228,7 @@ ones = ONES_FEMININE if i == 1 or feminine and i == 0 else ONES words.append(ones[n1][0]) - if i > 0 and x != 0: + if i > 0: words.append(self.pluralize(x, THOUSANDS[i])) return ' '.join(words) diff -Nru python-num2words-0.5.6/num2words/lang_SL.py python-num2words-0.5.9/num2words/lang_SL.py --- python-num2words-0.5.6/num2words/lang_SL.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_SL.py 2019-01-11 01:09:08.000000000 +0000 @@ -16,22 +16,18 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA -# -*- coding: utf-8 -*- - from __future__ import unicode_literals 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 +139,3 @@ 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 -Nru python-num2words-0.5.6/num2words/lang_SR.py python-num2words-0.5.9/num2words/lang_SR.py --- python-num2words-0.5.6/num2words/lang_SR.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_SR.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +from .base import Num2Word_Base +from .currency import parse_currency_parts, prefix_currency +from .utils import get_digits, splitbyx + +ZERO = ('nula',) + +ONES = { + 1: ('jedan', 'jedna'), + 2: ('dva', 'dve'), + 3: ('tri', 'tri'), + 4: ('četiri', 'četiri'), + 5: ('pet', 'pet'), + 6: ('šest', 'šest'), + 7: ('sedam', 'sedam'), + 8: ('osam', 'osam'), + 9: ('devet', 'devet'), +} + +TENS = { + 0: ('deset',), + 1: ('jedanaest',), + 2: ('dvanaest',), + 3: ('trinaest',), + 4: ('četrnaest',), + 5: ('petnaest',), + 6: ('šesnaest',), + 7: ('sedamnaest',), + 8: ('osamnaest',), + 9: ('devetnaest',), +} + +TWENTIES = { + 2: ('dvadeset',), + 3: ('trideset',), + 4: ('četrdeset',), + 5: ('pedeset',), + 6: ('šezdeset',), + 7: ('sedamdeset',), + 8: ('osamdeset',), + 9: ('devedeset',), +} + +HUNDREDS = { + 1: ('sto',), + 2: ('dvesta',), + 3: ('trista',), + 4: ('četristo',), + 5: ('petsto',), + 6: ('šesto',), + 7: ('sedamsto',), + 8: ('osamsto',), + 9: ('devetsto',), +} + +SCALE = { + 0: ('', '', '', False), + 1: ('hiljada', 'hiljade', 'hiljada', True), # 10^3 + 2: ('milion', 'miliona', 'miliona', False), # 10^6 + 3: ('bilion', 'biliona', 'biliona', False), # 10^9 + 4: ('trilion', 'triliona', 'triliona', False), # 10^12 + 5: ('kvadrilion', 'kvadriliona', 'kvadriliona', False), # 10^15 + 6: ('kvintilion', 'kvintiliona', 'kvintiliona', False), # 10^18 + 7: ('sekstilion', 'sekstiliona', 'sekstiliona', False), # 10^21 + 8: ('septilion', 'septiliona', 'septiliona', False), # 10^24 + 9: ('oktilion', 'oktiliona', 'oktiliona', False), # 10^27 + 10: ('nonilion', 'noniliona', 'noniliona', False), # 10^30 +} + + +class Num2Word_SR(Num2Word_Base): + CURRENCY_FORMS = { + 'RUB': ( + ('rublja', 'rublje', 'rublji', True), + ('kopejka', 'kopejke', 'kopejki', True) + ), + 'EUR': ( + ('evro', 'evra', 'evra', False), + ('cent', 'centa', 'centi', False) + ), + 'RSD': ( + ('dinar', 'dinara', 'dinara', False), + ('para', 'pare', 'para', True) + ), + } + + def setup(self): + self.negword = "minus" + self.pointword = "zapeta" + + def to_cardinal(self, number, feminine=False): + n = str(number).replace(',', '.') + if '.' in n: + left, right = n.split('.') + return u'%s %s %s' % ( + self._int2word(int(left), feminine), + self.pointword, + self._int2word(int(right), feminine) + ) + else: + return self._int2word(int(n), feminine) + + def pluralize(self, number, forms): + if number % 100 < 10 or number % 100 > 20: + if number % 10 == 1: + form = 0 + elif 1 < number % 10 < 5: + form = 1 + else: + form = 2 + else: + form = 2 + return forms[form] + + def to_ordinal(self, number): + raise NotImplementedError() + + def _cents_verbose(self, number, currency): + return self._int2word( + number, + self.CURRENCY_FORMS[currency][1][-1] + ) + + def _int2word(self, number, feminine=False): + if number < 0: + return ' '.join([self.negword, self._int2word(abs(number))]) + + if number == 0: + return ZERO[0] + + words = [] + chunks = list(splitbyx(str(number), 3)) + chunk_len = len(chunks) + for chunk in chunks: + chunk_len -= 1 + digit_right, digit_mid, digit_left = get_digits(chunk) + + if digit_left > 0: + words.append(HUNDREDS[digit_left][0]) + + if digit_mid > 1: + words.append(TWENTIES[digit_mid][0]) + + if digit_mid == 1: + words.append(TENS[digit_right][0]) + elif digit_right > 0: + is_feminine = feminine or SCALE[chunk_len][-1] + gender_idx = int(is_feminine) + words.append( + ONES[digit_right][gender_idx] + ) + + if chunk_len > 0 and chunk != 0: + words.append(self.pluralize(chunk, SCALE[chunk_len])) + + return ' '.join(words) + + def to_currency(self, val, currency='EUR', cents=True, seperator=',', + adjective=False): + """ + Args: + val: Numeric value + currency (str): Currency code + cents (bool): Verbose cents + seperator (str): Cent seperator + adjective (bool): Prefix currency name with adjective + Returns: + str: Formatted string + + """ + left, right, is_negative = parse_currency_parts(val) + + try: + cr1, cr2 = self.CURRENCY_FORMS[currency] + + except KeyError: + raise NotImplementedError( + 'Currency code "%s" not implemented for "%s"' % + (currency, self.__class__.__name__)) + + if adjective and currency in self.CURRENCY_ADJECTIVES: + cr1 = prefix_currency( + self.CURRENCY_ADJECTIVES[currency], + cr1 + ) + + minus_str = "%s " % self.negword if is_negative else "" + cents_str = self._cents_verbose(right, currency) \ + if cents else self._cents_terse(right, currency) + + return u'%s%s %s%s %s %s' % ( + minus_str, + self.to_cardinal(left, feminine=cr1[-1]), + self.pluralize(left, cr1), + seperator, + cents_str, + self.pluralize(right, cr2) + ) diff -Nru python-num2words-0.5.6/num2words/lang_TH.py python-num2words-0.5.9/num2words/lang_TH.py --- python-num2words-0.5.6/num2words/lang_TH.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_TH.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +from num2words.base import Num2Word_Base +from num2words.currency import parse_currency_parts +from num2words.utils import splitbyx + + +class Num2Word_TH(Num2Word_Base): + + def setup(self): + self.negword = 'ติดลบ' + self.pointword = 'จุด' + + self.CURRENCY_FORMS = { + 'THB': (('บาท', 'บาท'), ('สตางค์', 'สตางค์')), + 'USD': (('ดอลลาร์', 'ดอลลาร์'), ('เซนต์', 'เซนต์')), + 'EUR': (('ยูโร', 'ยูโร'), ('เซนต์', 'เซนต์')), + } + + self.high_numwords = [] + + self.mid_numwords = ['', 'สิบ', 'ร้อย', 'พัน', 'หมื่น', 'แสน', 'ล้าน'] + + self.low_numwords = [ + 'ศูนย์', 'หนึ่ง', 'สอง', 'สาม', 'สี่', + 'ห้า', 'หก', 'เจ็ด', 'แปด', 'เก้า' + ] + + def set_high_numwords(self, high_numwords): + pass + + def set_mid_numwords(self, mid_numwords): + pass + + def splitnum(self, six_num): + length = len(six_num) > 1 + word_num = '' + + for index, num in enumerate(map(int, six_num)): + if num: + if index: + word_num = self.mid_numwords[index] + word_num + + if length and num == 1 and index == 0: + word_num += 'เอ็ด' + elif index == 1 and num == 2: + word_num = 'ยี่' + word_num + elif index != 1 or num != 1: + word_num = self.low_numwords[num] + word_num + + elif num == 0 and index == 0 and length == 0: + word_num = self.low_numwords[0] + + return word_num + + def split_six(self, num_txt): + result = splitbyx(num_txt, 6, format_int=False) + result = list(result)[::-1] + number_list = [] + for i in result: + number_list.append(i[::-1]) + return number_list + + def add_text_million(self, word_num): + result = '' + + for index, t in enumerate(reversed(word_num)): + if index == 0: + result = t + else: + result = result + 'ล้าน' + t + + return result + + def round_2_decimal(self, number): + integer, cents, negative = parse_currency_parts( + number, is_int_with_cents=False + ) + integer = '{}'.format(integer) + cents = '{}'.format(cents) + + if len(cents) < 2: + add_zero = 2 - len(cents) + cents = ('0' * add_zero) + cents + + text_num = integer + '.' + cents + + return text_num, negative + + def left_num_to_text(self, number): + + left_num_list = self.split_six(number) + + left_text_list = [] + for i in left_num_list: + left_text_list.append(self.splitnum(i)) + + left_text = self.add_text_million(left_text_list) + return left_text + + def to_cardinal(self, number): + negative = number < 0 + + pre, post = self.float2tuple(number) + precision = self.precision + pre = '{}'.format(pre) + post = '{}'.format(post) + + if negative: + pre = pre.lstrip('-') + + if len(post) < precision: + add_zero = precision - len(post) + post = ('0' * add_zero) + post + + result = self.left_num_to_text(pre) + + right_text = '' + if not post == '0': + for i in map(int, post): + right_text = right_text + self.low_numwords[i] + result = result + 'จุด' + right_text + + if negative: + result = 'ติดลบ' + result + + return result + + def to_ordinal(self, number): + return self.to_cardinal(number) + + def to_currency(self, number, currency='THB'): + + number, negative = self.round_2_decimal(number) + + split_num = number.split('.') + + left_num = split_num[0] + left_text = self.left_num_to_text(left_num) + + right_num = split_num[1] + right_text = self.splitnum(right_num[::-1].rstrip('0')) + + try: + cr1, cr2 = self.CURRENCY_FORMS[currency] + + except KeyError: + raise NotImplementedError( + 'Currency code "%s" not implemented for "%s"' % + (currency, self.__class__.__name__)) + + if right_num == '00': + if currency == 'THB': + result = left_text + cr1[0] + 'ถ้วน' + else: + result = left_text + cr1[0] + else: + if left_num == '0': + result = right_text + cr2[0] + else: + result = left_text + cr1[0] + right_text + cr2[0] + + if negative: + result = self.negword + result + + return result diff -Nru python-num2words-0.5.6/num2words/lang_TR.py python-num2words-0.5.9/num2words/lang_TR.py --- python-num2words-0.5.6/num2words/lang_TR.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_TR.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # Copyright (c) 2017, Tufan Kaynak, Framras. All Rights Reserved. diff -Nru python-num2words-0.5.6/num2words/lang_UK.py python-num2words-0.5.9/num2words/lang_UK.py --- python-num2words-0.5.6/num2words/lang_UK.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_UK.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- # Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. @@ -14,10 +14,11 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA + from __future__ import unicode_literals from .base import Num2Word_Base -from .utils import get_digits, splitby3 +from .utils import get_digits, splitbyx ZERO = ('нуль',) @@ -102,7 +103,7 @@ ('копiйка', 'копiйки', 'копiйок') ), 'EUR': ( - ('евро', 'евро', 'евро'), ('цент', 'центи', 'центiв') + ('євро', 'євро', 'євро'), ('цент', 'центи', 'центiв') ), } @@ -110,10 +111,6 @@ 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: @@ -147,10 +144,14 @@ return ZERO[0] words = [] - chunks = list(splitby3(str(n))) + chunks = list(splitbyx(str(n), 3)) i = len(chunks) for x in chunks: i -= 1 + + if x == 0: + continue + n1, n2, n3 = get_digits(x) if n3 > 0: @@ -166,7 +167,7 @@ ones = ONES_FEMININE if i == 1 or feminine and i == 0 else ONES words.append(ones[n1][0]) - if i > 0 and ((n1 + n2 + n3) > 0): + if i > 0: words.append(self.pluralize(x, THOUSANDS[i])) return ' '.join(words) diff -Nru python-num2words-0.5.6/num2words/lang_VI.py python-num2words-0.5.9/num2words/lang_VI.py --- python-num2words-0.5.6/num2words/lang_VI.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_VI.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +to_19 = (u'không', u'một', u'hai', u'ba', u'bốn', u'năm', u'sáu', + u'bảy', u'tám', u'chín', u'mười', u'mười một', u'mười hai', + u'mười ba', u'mười bốn', u'mười lăm', u'mười sáu', u'mười bảy', + u'mười tám', u'mười chín') +tens = (u'hai mươi', u'ba mươi', u'bốn mươi', u'năm mươi', + u'sáu mươi', u'bảy mươi', u'tám mươi', u'chín mươi') +denom = ('', + u'nghìn', u'triệu', u'tỷ', u'nghìn tỷ', u'trăm nghìn tỷ', + 'Quintillion', 'Sextillion', 'Septillion', 'Octillion', 'Nonillion', + 'Decillion', 'Undecillion', 'Duodecillion', 'Tredecillion', + 'Quattuordecillion', 'Sexdecillion', 'Septendecillion', + 'Octodecillion', 'Novemdecillion', 'Vigintillion') + + +class Num2Word_VI(object): + + def _convert_nn(self, val): + if val < 20: + return to_19[val] + for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens)): + if dval + 10 > val: + if val % 10: + a = u'lăm' + if to_19[val % 10] == u'một': + a = u'mốt' + else: + a = to_19[val % 10] + if to_19[val % 10] == u'năm': + a = u'lăm' + return dcap + ' ' + a + return dcap + + def _convert_nnn(self, val): + word = '' + (mod, rem) = (val % 100, val // 100) + if rem > 0: + word = to_19[rem] + u' trăm' + if mod > 0: + word = word + ' ' + if mod > 0 and mod < 10: + if mod == 5: + word = word != '' and word + u'lẻ năm' or word + u'năm' + else: + word = word != '' and word + u'lẻ ' \ + + self._convert_nn(mod) or word + self._convert_nn(mod) + if mod >= 10: + word = word + self._convert_nn(mod) + return word + + def vietnam_number(self, val): + if val < 100: + return self._convert_nn(val) + if val < 1000: + return self._convert_nnn(val) + for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom))): + if dval > val: + mod = 1000 ** didx + lval = val // mod + r = val - (lval * mod) + + ret = self._convert_nnn(lval) + u' ' + denom[didx] + if 99 >= r > 0: + ret = self._convert_nnn(lval) + u' ' + denom[didx] + u' lẻ' + if r > 0: + ret = ret + ' ' + self.vietnam_number(r) + return ret + + def number_to_text(self, number): + number = '%.2f' % number + the_list = str(number).split('.') + start_word = self.vietnam_number(int(the_list[0])) + final_result = start_word + if len(the_list) > 1 and int(the_list[1]) > 0: + end_word = self.vietnam_number(int(the_list[1])) + final_result = final_result + ' phẩy ' + end_word + return final_result + + def to_cardinal(self, number): + return self.number_to_text(number) + + def to_ordinal(self, number): + return self.to_cardinal(number) diff -Nru python-num2words-0.5.6/num2words/lang_VN.py python-num2words-0.5.9/num2words/lang_VN.py --- python-num2words-0.5.6/num2words/lang_VN.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/lang_VN.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. -# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. - -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# This library 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 -# Lesser General Public License for more details. -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301 USA - -from __future__ import unicode_literals - -to_19 = (u'không', u'một', u'hai', u'ba', u'bốn', u'năm', u'sáu', - u'bảy', u'tám', u'chín', u'mười', u'mười một', u'mười hai', - u'mười ba', u'mười bốn', u'mười lăm', u'mười sáu', u'mười bảy', - u'mười tám', u'mười chín') -tens = (u'hai mươi', u'ba mươi', u'bốn mươi', u'năm mươi', - u'sáu mươi', u'bảy mươi', u'tám mươi', u'chín mươi') -denom = ('', - u'nghìn', u'triệu', u'tỷ', u'nghìn tỷ', u'trăm nghìn tỷ', - 'Quintillion', 'Sextillion', 'Septillion', 'Octillion', 'Nonillion', - 'Decillion', 'Undecillion', 'Duodecillion', 'Tredecillion', - 'Quattuordecillion', 'Sexdecillion', 'Septendecillion', - 'Octodecillion', 'Novemdecillion', 'Vigintillion') - - -class Num2Word_VN(object): - - def _convert_nn(self, val): - if val < 20: - return to_19[val] - for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens)): - if dval + 10 > val: - if val % 10: - a = u'lăm' - if to_19[val % 10] == u'một': - a = u'mốt' - else: - a = to_19[val % 10] - if to_19[val % 10] == u'năm': - a = u'lăm' - return dcap + ' ' + a - return dcap - - def _convert_nnn(self, val): - word = '' - (mod, rem) = (val % 100, val // 100) - if rem > 0: - word = to_19[rem] + u' trăm' - if mod > 0: - word = word + ' ' - if mod > 0 and mod < 10: - if mod == 5: - word = word != '' and word + u'lẻ năm' or word + u'năm' - else: - word = word != '' and word + u'lẻ ' \ - + self._convert_nn(mod) or word + self._convert_nn(mod) - if mod >= 10: - word = word + self._convert_nn(mod) - return word - - def vietnam_number(self, val): - if val < 100: - return self._convert_nn(val) - if val < 1000: - return self._convert_nnn(val) - for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom))): - if dval > val: - mod = 1000 ** didx - lval = val // mod - r = val - (lval * mod) - - ret = self._convert_nnn(lval) + u' ' + denom[didx] - if 99 >= r > 0: - ret = self._convert_nnn(lval) + u' ' + denom[didx] + u' lẻ' - if r > 0: - ret = ret + ' ' + self.vietnam_number(r) - return ret - - def number_to_text(self, number): - number = '%.2f' % number - the_list = str(number).split('.') - start_word = self.vietnam_number(int(the_list[0])) - final_result = start_word - if len(the_list) > 1 and int(the_list[1]) > 0: - end_word = self.vietnam_number(int(the_list[1])) - final_result = final_result + ' phẩy ' + end_word - return final_result - - def to_cardinal(self, number): - return self.number_to_text(number) - - def to_ordinal(self, number): - return self.to_cardinal(number) diff -Nru python-num2words-0.5.6/num2words/utils.py python-num2words-0.5.9/num2words/utils.py --- python-num2words-0.5.6/num2words/utils.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/num2words/utils.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,14 +1,35 @@ -def splitby3(n): +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + + +def splitbyx(n, x, format_int=True): length = len(n) - if length > 3: - start = length % 3 + if length > x: + start = length % x if start > 0: - yield int(n[:start]) - for i in range(start, length, 3): - yield int(n[i:i+3]) + result = n[:start] + yield int(result) if format_int else result + for i in range(start, length, x): + result = n[i:i+x] + yield int(result) if format_int else result else: - yield int(n) + yield int(n) if format_int else n def get_digits(n): - return [int(x) for x in reversed(list(('%03d' % n)[-3:]))] + a = [int(x) for x in reversed(list(('%03d' % n)[-3:]))] + return a diff -Nru python-num2words-0.5.6/README.rst python-num2words-0.5.9/README.rst --- python-num2words-0.5.6/README.rst 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/README.rst 2019-01-11 01:09:08.000000000 +0000 @@ -1,6 +1,9 @@ num2words - Convert numbers to words in multiple languages ========================================================== +.. image:: https://img.shields.io/pypi/v/num2words.svg + :target: https://pypi.python.org/pypi/num2words + .. image:: https://travis-ci.org/savoirfairelinux/num2words.svg?branch=master :target: https://travis-ci.org/savoirfairelinux/num2words @@ -13,7 +16,9 @@ of languages) and can even generate ordinal numbers like ``forty-second`` (although this last feature is a bit buggy for some languages at the moment). -The project is hosted on https://github.com/savoirfairelinux/num2words +The project is hosted on GitHub_. Contributions are welcome. + +.. _GitHub: https://github.com/savoirfairelinux/num2words Installation ------------ @@ -26,26 +31,41 @@ python setup.py install -The test suite in this library new, so it's rather thin, but it can be ran with:: +The test suite in this library is new, so it's rather thin, but it can be run with:: python setup.py test +To run the full CI test suite which includes linting and multiple python environments:: + + pip install tox + tox + Usage ----- +Command line:: + + $ num2words 10001 + ten thousand and one + $ num2words 24,120.10 + twenty-four thousand, one hundred and twenty point one + $ num2words 24,120.10 -l es + veinticuatro mil ciento veinte punto uno + $num2words 2.14 -l es --to currency + dos euros con catorce centimos -There's only one function to use:: +In code there's only one function to use:: >>> from num2words import num2words >>> num2words(42) forty-two - >>> num2words(42, to='cardinal') + >>> num2words(42, to='ordinal') forty-second >>> num2words(42, lang='fr') quarante-deux -Besides the numerical argument, there's two optional arguments. +Besides the numerical argument, there are two main optional arguments. -**to:** The converter to use. Supperted values are: +**to:** The converter to use. Supported values are: * ``cardinal`` (default) * ``ordinal`` @@ -57,6 +77,7 @@ * ``en`` (English, default) * ``ar`` (Arabic) +* ``cz`` (Czech) * ``de`` (German) * ``dk`` (Danish) * ``en_GB`` (English - Great Britain) @@ -65,25 +86,35 @@ * ``es_CO`` (Spanish - Colombia) * ``es_VE`` (Spanish - Venezuela) * ``eu`` (EURO) +* ``fi`` (Finnish) * ``fr`` (French) * ``fr_CH`` (French - Switzerland) +* ``fr_BE`` (French - Belgium) * ``fr_DZ`` (French - Algeria) * ``he`` (Hebrew) * ``id`` (Indonesian) * ``it`` (Italian) +* ``ja`` (Japanese) +* ``ko`` (Korean) * ``lt`` (Lithuanian) * ``lv`` (Latvian) * ``no`` (Norwegian) * ``pl`` (Polish) -* ``pt_BR`` (Brazilian Portuguese) +* ``pt`` (Portuguese) +* ``pt_BR`` (Portuguese - Brazilian) * ``sl`` (Slovene) +* ``sr`` (Serbian) +* ``ro`` (Romanian) * ``ru`` (Russian) +* ``sl`` (Slovene) * ``tr`` (Turkish) -* ``vn`` (Vietnamese) +* ``th`` (Thai) +* ``vi`` (Vietnamese) * ``nl`` (Dutch) * ``uk`` (Ukrainian) -You can supply values like ``fr_FR``, the code will be correctly interpreted. If +You can supply values like ``fr_FR``; if the country doesn't exist but the +language does, the code will fall back to the base language (i.e. ``fr``). If you supply an unsupported language, ``NotImplementedError`` is raised. Therefore, if you want to call ``num2words`` with a fallback, you can do:: @@ -92,10 +123,20 @@ except NotImplementedError: return num2words(42, lang='en') +Additionally, some converters and languages support other optional arguments +that are needed to make the converter useful in practice. + +Wiki +---- +For additional information on some localization please check the Wiki_. +And feel free to propose wiki enhancement. + +.. _Wiki: https://github.com/savoirfairelinux/num2words/wiki + History ------- -``num2words`` is based on an old library, ``pynum2word`` created by Taro Ogawa +``num2words`` is based on an old library, ``pynum2word``, created by Taro Ogawa in 2003. Unfortunately, the library stopped being maintained and the author can't be reached. There was another developer, Marius Grigaitis, who in 2011 added Lithuanian support, but didn't take over maintenance of the project. diff -Nru python-num2words-0.5.6/requirements-test.txt python-num2words-0.5.9/requirements-test.txt --- python-num2words-0.5.6/requirements-test.txt 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/requirements-test.txt 2019-01-11 01:09:08.000000000 +0000 @@ -3,5 +3,4 @@ isort pep8<1.6 coverage -coveralls - +delegator.py diff -Nru python-num2words-0.5.6/setup.py python-num2words-0.5.9/setup.py --- python-num2words-0.5.6/setup.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/setup.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,27 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +import re +from io import open + from setuptools import find_packages, setup +PACKAGE_NAME = "num2words" + CLASSIFIERS = [ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', @@ -13,19 +35,37 @@ 'Topic :: Text Processing :: Linguistic', ] -LONG_DESC = open('README.rst', 'rt').read() + '\n\n' + \ - open('CHANGES.rst', 'rt').read() +LONG_DESC = open('README.rst', 'rt', encoding="utf-8").read() + '\n\n' + \ + open('CHANGES.rst', 'rt', encoding="utf-8").read() + + +def find_version(fname): + """Parse file & return version number matching 0.0.1 regex + Returns str or raises RuntimeError + """ + version = '' + with open(fname, 'r', encoding="utf-8") as fp: + reg = re.compile(r'__version__ = [\'"]([^\'"]*)[\'"]') + for line in fp: + m = reg.match(line) + if m: + version = m.group(1) + break + if not version: + raise RuntimeError('Cannot find version information') + return version + setup( - name='num2words', - version='0.5.6', + name=PACKAGE_NAME, + version=find_version("bin/num2words"), description='Modules to convert numbers to words. Easily extensible.', long_description=LONG_DESC, license='LGPL', author='Taro Ogawa ', author_email='tos@users.sourceforge.net', maintainer='Savoir-faire Linux inc.', - maintainer_email='ernesto.rodriguezortiz@savoirfairelinux.com', + maintainer_email='istvan.szalai@savoirfairelinux.com', keywords=' number word numbers words convert conversion i18n ' 'localisation localization internationalisation ' 'internationalization', @@ -33,4 +73,7 @@ packages=find_packages(exclude=['tests']), test_suite='tests', classifiers=CLASSIFIERS, + scripts=['bin/num2words'], + install_requires=["docopt>=0.6.2"], + tests_require=['delegator.py'], ) diff -Nru python-num2words-0.5.6/tests/test_ar.py python-num2words-0.5.9/tests/test_ar.py --- python-num2words-0.5.6/tests/test_ar.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_ar.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,5 @@ -# encoding: UTF-8 +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or @@ -13,51 +14,100 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA -from __future__ import unicode_literals from unittest import TestCase from num2words import num2words -TEST_CASES_CARDINAL = ( - (1, 'واحد'), - (2, 'اثنين'), - (11, 'أحد عشر'), - (12, 'اثناعشر'), - (20, 'عشرين'), - (21, 'واحد وعشرين'), - (26, 'ستة وعشرين'), - (30, 'ثلاثين'), - (67, 'سبعة وستين'), - (70, 'سبعين'), - (100, 'مئة'), - (101, 'مئة و واحد'), - (199, 'مئة و تسعة وتسعين'), - (203, 'مئتين و ثلاثة'), - (1000, 'ألف'), - (1001, 'ألف و واحد'), - (1097, 'ألف و سبعة وتسعين'), - (1000000, 'مليون'), - (1000001, 'مليون و واحد'), -) - -TEST_CASES_ORDINAL = ( - (1, 'أول'), - (8, 'ثامن'), - (12, 'ثاني عشر'), - (100, 'مئة'), -) - class Num2WordsARTest(TestCase): - def test_number(self): - for test in TEST_CASES_CARDINAL: - self.assertEqual(num2words(test[0], lang='ar'), test[1]) + def test_default_currency(self): + self.assertEqual(num2words(1, to='currency', lang='ar'), 'واحد ريال') + self.assertEqual(num2words(2, to='currency', lang='ar'), + 'اثنان ريالان') + self.assertEqual(num2words(10, to='currency', lang='ar'), + 'عشرة ريالات') + self.assertEqual(num2words(100, to='currency', lang='ar'), 'مائة ريال') + self.assertEqual(num2words(652.12, to='currency', lang='ar'), + 'ستمائة و اثنان و خمسون ريالاً و اثنتا عشرة هللة') + self.assertEqual(num2words(324, to='currency', lang='ar'), + 'ثلاثمائة و أربعة و عشرون ريالاً') + self.assertEqual(num2words(2000, to='currency', lang='ar'), + 'ألفا ريال') + self.assertEqual(num2words(541, to='currency', lang='ar'), + 'خمسمائة و واحد و أربعون ريالاً') + self.assertEqual(num2words(10000, to='currency', lang='ar'), + 'عشرة آلاف ريال') + self.assertEqual(num2words(20000.12, to='currency', lang='ar'), + 'عشرون ألف ريال و اثنتا عشرة هللة') + self.assertEqual(num2words(1000000, to='currency', lang='ar'), + 'واحد مليون ريال') + val = 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر ريالاً' + self.assertEqual(num2words(923411, to='currency', lang='ar'), val) + self.assertEqual(num2words(63411, to='currency', lang='ar'), + 'ثلاثة و ستون ألفاً و أربعمائة و أحد عشر ريالاً') + self.assertEqual(num2words(1000000.99, to='currency', lang='ar'), + 'واحد مليون ريال و تسع و تسعون هللة') + + def test_currency_parm(self): + self.assertEqual( + num2words(1, to='currency', lang='ar', currency="KWD"), + 'واحد دينار') + self.assertEqual( + num2words(10, to='currency', lang='ar', currency="EGP"), + 'عشرة جنيهات') + self.assertEqual( + num2words(20000.12, to='currency', lang='ar', currency="EGP"), + 'عشرون ألف جنيه و اثنتا عشرة قرش') + self.assertEqual( + num2words(923411, to='currency', lang='ar', currency="SR"), + 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر ريالاً') + self.assertEqual( + num2words(1000000.99, to='currency', lang='ar', currency="KWD"), + 'واحد مليون دينار و تسع و تسعون فلس') def test_ordinal(self): - for test in TEST_CASES_ORDINAL: - self.assertEqual( - num2words(test[0], lang='ar', ordinal=True), - test[1] - ) + self.assertEqual(num2words(1, to='ordinal', lang='ar'), 'اول') + self.assertEqual(num2words(2, to='ordinal', lang='ar'), 'ثاني') + self.assertEqual(num2words(3, to='ordinal', lang='ar'), 'ثالث') + self.assertEqual(num2words(4, to='ordinal', lang='ar'), 'رابع') + self.assertEqual(num2words(5, to='ordinal', lang='ar'), 'خامس') + self.assertEqual(num2words(6, to='ordinal', lang='ar'), 'سادس') + self.assertEqual(num2words(9, to='ordinal', lang='ar'), 'تاسع') + self.assertEqual(num2words(20, to='ordinal', lang='ar'), 'عشرون') + self.assertEqual(num2words(94, to='ordinal', lang='ar'), + 'أربع و تسعون') + self.assertEqual(num2words(102, to='ordinal', lang='ar'), + 'مائة و اثنان') + self.assertEqual( + num2words(923411, to='ordinal_num', lang='ar'), + 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر') + + def test_cardinal(self): + self.assertEqual(num2words(12, to='cardinal', lang='ar'), 'اثنا عشر') + self.assertEqual(num2words(-8324, to='cardinal', lang='ar'), + 'سالب ثمانية آلاف و ثلاثمائة و أربعة و عشرون') + self.assertEqual( + num2words(3431.12, to='cardinal', lang='ar'), + 'ثلاثة آلاف و أربعمائة و واحد و ثلاثون , اثنتا عشرة') + self.assertEqual(num2words(431, to='cardinal', lang='ar'), + 'أربعمائة و واحد و ثلاثون') + self.assertEqual(num2words(94231, to='cardinal', lang='ar'), + 'أربعة و تسعون ألفاً و مئتان و واحد و ثلاثون') + self.assertEqual(num2words(1431, to='cardinal', lang='ar'), + 'واحد ألف و أربعمائة و واحد و ثلاثون') + + def test_prefix_and_suffix(self): + self.assertEqual(num2words(645, to='currency', + lang='ar', prefix="فقط", suffix="لاغير"), + 'فقط ستمائة و خمسة و أربعون ريالاً لاغير') + + def test_year(self): + self.assertEqual(num2words(2000, to='year', lang='ar'), 'ألفا') + + def test_max_numbers(self): + with self.assertRaises(Exception) as context: + num2words(10 ** 36, to='year', lang='ar') + + self.assertTrue('Too large' in str(context.exception)) diff -Nru python-num2words-0.5.6/tests/test_base.py python-num2words-0.5.9/tests/test_base.py --- python-num2words-0.5.6/tests/test_base.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_base.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +from decimal import Decimal +from unittest import TestCase + +from num2words.base import Num2Word_Base + + +class Num2WordBaseTest(TestCase): + @classmethod + def setUpClass(cls): + super(Num2WordBaseTest, cls).setUpClass() + cls.base = Num2Word_Base() + + def test_to_currency_not_implemented(self): + with self.assertRaises(NotImplementedError): + self.base.to_currency(Decimal('1.00'), currency='EUR') diff -Nru python-num2words-0.5.6/tests/test_cli.py python-num2words-0.5.9/tests/test_cli.py --- python-num2words-0.5.6/tests/test_cli.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_cli.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +import os +import unittest + +import delegator +import num2words + + +class CliCaller(object): + + def __init__(self): + self.cmd = os.path.realpath(os.path.join(os.path.dirname(__file__), + "..", "bin", "num2words")) + self.cmd_list = ["python", self.cmd] + + def run_cmd(self, *args): + cmd_list = self.cmd_list + [str(arg) for arg in args] + cmd = " ".join(cmd_list) + return delegator.run(cmd) + + +class CliTestCase(unittest.TestCase): + """Test the command line app""" + + def setUp(self): + self.cli = CliCaller() + + def test_cli_help(self): + """num2words without arguments should exit with status 1 + and show docopt's default short usage message + """ + output = self.cli.run_cmd() + self.assertEqual(output.return_code, 1) + self.assertTrue(output.err.startswith('Usage:')) + + def test_cli_list_langs(self): + """You should be able to list all availabe languages + """ + output = self.cli.run_cmd('--list-languages') + self.assertEqual( + sorted(list(num2words.CONVERTER_CLASSES.keys())), + output.out.strip().split(os.linesep) + ) + output = self.cli.run_cmd('-L') + self.assertEqual( + sorted(list(num2words.CONVERTER_CLASSES.keys())), + output.out.strip().split(os.linesep) + ) + + def test_cli_list_converters(self): + """You should be able to list all available converters + """ + output = self.cli.run_cmd('--list-converters') + self.assertEqual( + sorted(list(num2words.CONVERTES_TYPES)), + output.out.strip().split(os.linesep) + ) + output = self.cli.run_cmd('-C') + self.assertEqual( + sorted(list(num2words.CONVERTES_TYPES)), + output.out.strip().split(os.linesep) + ) + + def test_cli_default_lang(self): + """Default to english + """ + output = self.cli.run_cmd(150) + self.assertEqual(output.return_code, 0) + self.assertEqual( + output.out.strip(), + "one hundred and fifty point zero" + ) + + def test_cli_with_lang(self): + """You should be able to specify a language + """ + output = self.cli.run_cmd(150, '--lang', 'es') + self.assertEqual(output.return_code, 0) + self.assertEqual( + output.out.strip(), + "ciento cincuenta punto cero" + ) + + def test_cli_with_lang_to(self): + """You should be able to specify a language + """ + output = self.cli.run_cmd(150.55, '--lang', 'es', '--to', 'currency') + self.assertEqual(output.return_code, 0) + self.assertEqual( + output.out.strip(), + "ciento cincuenta euros con cincuenta y cinco centimos" + ) diff -Nru python-num2words-0.5.6/tests/test_currency.py python-num2words-0.5.9/tests/test_currency.py --- python-num2words-0.5.6/tests/test_currency.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_currency.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,3 +1,20 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + from decimal import Decimal from unittest import TestCase @@ -6,23 +23,41 @@ class CurrencyTestCase(TestCase): def test_parse_currency_parts(self): - # integer cents + # integer with cents self.assertEqual(parse_currency_parts(101), (1, 1, False)) self.assertEqual(parse_currency_parts(-123), (1, 23, True)) + # integer without cents + self.assertEqual(parse_currency_parts(101, is_int_with_cents=False), + (101, 0, False)) + self.assertEqual(parse_currency_parts(-123, is_int_with_cents=False), + (123, 0, True)) + + # float + self.assertEqual(parse_currency_parts(1.01), (1, 1, False)) + self.assertEqual(parse_currency_parts(-1.23), (1, 23, True)) + self.assertEqual(parse_currency_parts(-1.2), (1, 20, True)) + self.assertEqual(parse_currency_parts(0.004), (0, 0, False)) + self.assertEqual(parse_currency_parts(0.005), (0, 1, False)) + self.assertEqual(parse_currency_parts(0.006), (0, 1, False)) + self.assertEqual(parse_currency_parts(0.0005), (0, 0, False)) + self.assertEqual(parse_currency_parts(0.984), (0, 98, False)) + self.assertEqual(parse_currency_parts(0.989), (0, 99, False)) + self.assertEqual(parse_currency_parts(0.994), (0, 99, False)) + self.assertEqual(parse_currency_parts(0.999), (1, 0, False)) + # self.assertEqual(parse_currency_parts(0.985), (0, 99, False)) + # self.assertEqual(parse_currency_parts(0.995), (1, 0, False)) + # decimal self.assertEqual(parse_currency_parts(Decimal("1.01")), (1, 1, False)) self.assertEqual(parse_currency_parts(Decimal("-1.23")), (1, 23, True)) self.assertEqual(parse_currency_parts(Decimal("-1.233")), (1, 23, True)) + self.assertEqual(parse_currency_parts(Decimal("-1.989")), + (1, 99, True)) # string self.assertEqual(parse_currency_parts("1.01"), (1, 1, False)) self.assertEqual(parse_currency_parts("-1.23"), (1, 23, True)) self.assertEqual(parse_currency_parts("-1.2"), (1, 20, True)) self.assertEqual(parse_currency_parts("1"), (1, 0, False)) - - # float - self.assertEqual(parse_currency_parts(1.01), (1, 1, False)) - self.assertEqual(parse_currency_parts(-1.23), (1, 23, True)) - self.assertEqual(parse_currency_parts(-1.2), (1, 20, True)) diff -Nru python-num2words-0.5.6/tests/test_cz.py python-num2words-0.5.9/tests/test_cz.py --- python-num2words-0.5.6/tests/test_cz.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_cz.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +from unittest import TestCase + +from num2words import num2words + + +class Num2WordsCZTest(TestCase): + def test_cardinal(self): + self.assertEqual(num2words(100, lang='cz'), "sto") + self.assertEqual(num2words(101, lang='cz'), "sto jedna") + self.assertEqual(num2words(110, lang='cz'), "sto deset") + self.assertEqual(num2words(115, lang='cz'), "sto patnáct") + self.assertEqual(num2words(123, lang='cz'), "sto dvacet tři") + self.assertEqual(num2words(1000, lang='cz'), "tisíc") + self.assertEqual(num2words(1001, lang='cz'), "tisíc jedna") + self.assertEqual(num2words(2012, lang='cz'), "dva tisíce dvanáct") + self.assertEqual( + num2words(12519.85, lang='cz'), + "dvanáct tisíc pětset devatenáct celá osmdesát pět" + ) + self.assertEqual( + num2words(123.50, lang='cz'), + "sto dvacet tři celá pět" + ) + self.assertEqual( + num2words(1234567890, lang='cz'), + "miliarda dvěstě třicet čtyři miliony pětset šedesát " + "sedm tisíc osmset devadesát" + ) + self.assertEqual( + num2words(215461407892039002157189883901676, lang='cz'), + "dvěstě patnáct quintillionů čtyřista šedesát jedna kvadriliard " + "čtyřista sedm kvadrilionů osmset devadesát dva triliardy třicet " + "devět trilionů dva biliardy sto padesát sedm bilionů sto " + "osmdesát devět miliard osmset osmdesát tři miliony " + "devětset jedna tisíc šestset sedmdesát šest" + ) + self.assertEqual( + num2words(719094234693663034822824384220291, lang='cz'), + "sedmset devatenáct quintillionů devadesát " + "čtyři kvadriliardy dvěstě třicet čtyři " + "kvadriliony šestset devadesát tři triliardy " + "šestset šedesát tři triliony třicet čtyři biliardy osmset " + "dvacet dva biliony osmset dvacet čtyři " + "miliardy třista osmdesát čtyři miliony dvěstě dvacet " + "tisíc dvěstě devadesát jedna" + ) + + def test_to_ordinal(self): + # @TODO: implement to_ordinal + with self.assertRaises(NotImplementedError): + num2words(1, lang='cz', to='ordinal') + + def test_currency(self): + self.assertEqual( + num2words(10.0, lang='cz', to='currency', currency='EUR'), + "deset euro, nula centů") + self.assertEqual( + num2words(1.0, lang='cz', to='currency', currency='CZK'), + "jedna koruna, nula haléřů") + self.assertEqual( + num2words(1234.56, lang='cz', to='currency', currency='EUR'), + "tisíc dvěstě třicet čtyři euro, padesát šest centů") + self.assertEqual( + num2words(1234.56, lang='cz', to='currency', currency='CZK'), + "tisíc dvěstě třicet čtyři koruny, padesát šest haléřů") + self.assertEqual( + num2words(101.11, lang='cz', to='currency', currency='EUR', + seperator=' a'), + "sto jedna euro a jedenáct centů") + self.assertEqual( + num2words(101.21, lang='cz', to='currency', currency='CZK', + seperator=' a'), + "sto jedna korun a dvacet jedna haléřů" + ) + self.assertEqual( + num2words(-12519.85, lang='cz', to='currency', cents=False), + "mínus dvanáct tisíc pětset devatenáct euro, 85 centů" + ) + self.assertEqual( + num2words(123.50, lang='cz', to='currency', currency='CZK', + seperator=' a'), + "sto dvacet tři koruny a padesát haléřů" + ) + self.assertEqual( + num2words(19.50, lang='cz', to='currency', cents=False), + "devatenáct euro, 50 centů" + ) diff -Nru python-num2words-0.5.6/tests/test_de.py python-num2words-0.5.9/tests/test_de.py --- python-num2words-0.5.6/tests/test_de.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_de.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,6 @@ -# -*- encoding: utf-8 -*- -# Copyright (c) 2015, Savoir-faire Linux inc. All Rights Reserved. +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -44,24 +45,69 @@ num2words(4000, ordinal=True, lang='de'), "viertausendste" ) self.assertEqual( - num2words(2000000, ordinal=True, lang='de'), "zwei millionenste" + num2words(2000000, ordinal=True, lang='de'), "zwei millionste" ) self.assertEqual( num2words(5000000000, ordinal=True, lang='de'), - "fünf milliardenste" + "fünf milliardste" ) def test_cardinal_at_some_numbers(self): + self.assertEqual(num2words(100, lang='de'), "einhundert") self.assertEqual(num2words(2000000, lang='de'), "zwei millionen") self.assertEqual(num2words(4000000000, lang='de'), "vier milliarden") + self.assertEqual(num2words(1000000000, lang='de'), "eine milliarde") def test_cardinal_for_decimal_number(self): self.assertEqual( num2words(3.486, lang='de'), "drei Komma vier acht sechs" ) + def test_giant_cardinal_for_merge(self): + self.assertEqual( + num2words(4500072900000111, lang='de'), + "vier billiarden fünfhundert billionen " + + "zweiundsiebzig milliarden neunhundert millionen einhundertelf" + ) + + def test_ordinal_num(self): + self.assertEqual(num2words(7, to="ordinal_num", lang='de'), "7.") + self.assertEqual(num2words(81, to="ordinal_num", lang='de'), "81.") + def test_ordinal_for_negative_numbers(self): self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='de') def test_ordinal_for_floating_numbers(self): self.assertRaises(TypeError, num2words, 2.453, ordinal=True, lang='de') + + def test_currency(self): + self.assertEqual(num2words(1, lang='de', to='currency'), + 'ein Euro') + self.assertEqual(num2words(12, lang='de', to='currency'), + 'zwölf Euro') + self.assertEqual(num2words(12.00, lang='de', to='currency'), + 'zwölf Euro') + self.assertEqual(num2words(100.0, lang='de', to='currency'), + "einhundert Euro") + self.assertEqual(num2words(190, lang='de', to='currency'), + "einhundertneunzig Euro") + self.assertEqual(num2words(1.90, lang='de', to='currency'), + "ein Euro und neunzig Cent") + self.assertEqual(num2words(3.4, lang='de', to='currency'), + "drei Euro und vierzig Cent") + self.assertEqual(num2words(20.18, lang='de', to='currency'), + "zwanzig Euro und achtzehn Cent") + self.assertEqual(num2words(3.04, lang='de', to='currency'), + "drei Euro und vier Cent") + + def test_old_currency(self): + self.assertEqual(num2words(12.00, to='currency', lang='de', old=True), + 'zwölf Mark') + + def test_year(self): + self.assertEqual(num2words(2002, to='year', lang='de'), + 'zweitausendzwei') + + def test_year_before_2000(self): + self.assertEqual(num2words(1780, to='year', lang='de'), + 'siebzehnhundertachtzig') diff -Nru python-num2words-0.5.6/tests/test_en_in.py python-num2words-0.5.9/tests/test_en_in.py --- python-num2words-0.5.6/tests/test_en_in.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_en_in.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from unittest import TestCase + +from num2words import num2words + + +class Num2WordsENINTest(TestCase): + def test_cardinal(self): + self.assertEqual(num2words(1e5, lang="en_IN"), "one lakh") + self.assertEqual(num2words(1e6, lang="en_IN"), "ten lakh") + self.assertEqual(num2words(1e7, lang="en_IN"), "one crore") diff -Nru python-num2words-0.5.6/tests/test_en.py python-num2words-0.5.9/tests/test_en.py --- python-num2words-0.5.6/tests/test_en.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_en.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or @@ -23,6 +25,34 @@ # ref https://github.com/savoirfairelinux/num2words/issues/8 self.assertEqual(num2words(199), "one hundred and ninety-nine") + def test_ordinal(self): + self.assertEqual( + num2words(1, lang='en', to='ordinal'), + 'first' + ) + self.assertEqual( + num2words(22, lang='en', to='ordinal'), + 'twenty-second' + ) + self.assertEqual( + num2words(12, lang='en', to='ordinal'), + 'twelfth' + ) + self.assertEqual( + num2words(130, lang='en', to='ordinal'), + 'one hundred and thirtieth' + ) + self.assertEqual( + num2words(1003, lang='en', to='ordinal'), + 'one thousand and third' + ) + + def test_ordinal_num(self): + self.assertEqual(num2words(10, lang='en', to='ordinal_num'), '10th') + self.assertEqual(num2words(21, lang='en', to='ordinal_num'), '21st') + self.assertEqual(num2words(102, lang='en', to='ordinal_num'), '102nd') + self.assertEqual(num2words(73, lang='en', to='ordinal_num'), '73rd') + def test_cardinal_for_float_number(self): # issue 24 self.assertEqual(num2words(12.5), "twelve point five") @@ -30,6 +60,15 @@ 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', @@ -59,3 +98,75 @@ cents=True, currency='USD'), 'four thousand, seven hundred and seventy-eight dollars and' ' zero cents') + + self.assertEqual( + num2words('1.1', lang='en', to='currency', seperator=' and', + cents=True, currency='MXN'), + "one peso and ten cents" + ) + + self.assertEqual( + num2words('158.3', lang='en', to='currency', seperator=' and', + cents=True, currency='MXN'), + "one hundred and fifty-eight pesos and thirty cents" + ) + + self.assertEqual( + num2words('2000.00', lang='en', to='currency', seperator=' and', + cents=True, currency='MXN'), + "two thousand pesos and zero cents" + ) + + self.assertEqual( + num2words('4.01', lang='en', to='currency', seperator=' and', + cents=True, currency='MXN'), + "four pesos and one cent" + ) + + def test_to_year(self): + # issue 141 + # "e2 e2" + self.assertEqual(num2words(1990, lang='en', to='year'), + 'nineteen ninety') + self.assertEqual(num2words(5555, lang='en', to='year'), + 'fifty-five fifty-five') + self.assertEqual(num2words(2017, lang='en', to='year'), + 'twenty seventeen') + self.assertEqual(num2words(1066, lang='en', to='year'), + 'ten sixty-six') + self.assertEqual(num2words(1865, lang='en', to='year'), + 'eighteen sixty-five') + # "e3 and e1"; "e2 oh-e1"; "e3" + self.assertEqual(num2words(3000, lang='en', to='year'), + 'three thousand') + self.assertEqual(num2words(2001, lang='en', to='year'), + 'two thousand and one') + self.assertEqual(num2words(1901, lang='en', to='year'), + 'nineteen oh-one') + self.assertEqual(num2words(2000, lang='en', to='year'), + 'two thousand') + self.assertEqual(num2words(905, lang='en', to='year'), + 'nine oh-five') + # "e2 hundred"; "e3" + self.assertEqual(num2words(6600, lang='en', to='year'), + 'sixty-six hundred') + self.assertEqual(num2words(1900, lang='en', to='year'), + 'nineteen hundred') + self.assertEqual(num2words(600, lang='en', to='year'), + 'six hundred') + self.assertEqual(num2words(50, lang='en', to='year'), + 'fifty') + self.assertEqual(num2words(0, lang='en', to='year'), + 'zero') + # suffixes + self.assertEqual(num2words(-44, lang='en', to='year'), + 'forty-four BC') + self.assertEqual(num2words(-44, lang='en', to='year', suffix='BCE'), + 'forty-four BCE') + self.assertEqual(num2words(1, lang='en', to='year', suffix='AD'), + 'one AD') + self.assertEqual(num2words(66, lang='en', to='year', + suffix='m.y.a.'), + 'sixty-six m.y.a.') + self.assertEqual(num2words(-66000000, lang='en', to='year'), + 'sixty-six million BC') diff -Nru python-num2words-0.5.6/tests/test_es_co.py python-num2words-0.5.9/tests/test_es_co.py --- python-num2words-0.5.6/tests/test_es_co.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_es_co.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,5 @@ -# encoding: UTF-8 +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or diff -Nru python-num2words-0.5.6/tests/test_es.py python-num2words-0.5.9/tests/test_es.py --- python-num2words-0.5.6/tests/test_es.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_es.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,5 @@ -# encoding: UTF-8 +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or @@ -13,6 +14,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA + from __future__ import unicode_literals from unittest import TestCase @@ -110,23 +112,47 @@ ) TEST_CASES_TO_CURRENCY = ( - (1, 'un euro'), - (2, 'dos euros'), - (8, 'ocho euros'), - (12, 'doce euros'), - (21, 'veintiun euros'), - (81.25, 'ochenta y un euros y veinticinco centavos'), - (100, 'cien euros'), -) - -TEST_CASES_TO_CURRENCY_OLD = ( - (1, 'un peso'), - (2, 'dos pesos'), - (8, 'ocho pesos'), - (12, 'doce pesos'), - (21, 'veintiun pesos'), - (81.25, 'ochenta y un pesos y veinticinco pesetas'), - (100, 'cien pesos'), + (1.00, 'un euro con cero centimos'), + (2.00, 'dos euros con cero centimos'), + (8.00, 'ocho euros con cero centimos'), + (12.00, 'doce euros con cero centimos'), + (21.00, 'veintiun euros con cero centimos'), + (81.25, 'ochenta y un euros con veinticinco centimos'), + (350.90, 'trescientos cincuenta euros con noventa centimos'), + (100.00, 'cien euros con cero centimos'), +) + +TEST_CASES_TO_CURRENCY_ESP = ( + (1.00, 'un peseta con cero centimos'), + (2.00, 'dos pesetas con cero centimos'), + (8.00, 'ocho pesetas con cero centimos'), + (12.00, 'doce pesetas con cero centimos'), + (21.00, 'veintiun pesetas con cero centimos'), + (81.25, 'ochenta y un pesetas con veinticinco centimos'), + (350.90, 'trescientos cincuenta pesetas con noventa centimos'), + (100.00, 'cien pesetas con cero centimos'), +) + +TEST_CASES_TO_CURRENCY_USD = ( + (1.00, 'un dolar con cero centavos'), + (2.00, 'dos dolares con cero centavos'), + (8.00, 'ocho dolares con cero centavos'), + (12.00, 'doce dolares con cero centavos'), + (21.00, 'veintiun dolares con cero centavos'), + (81.25, 'ochenta y un dolares con veinticinco centavos'), + (350.90, 'trescientos cincuenta dolares con noventa centavos'), + (100.00, 'cien dolares con cero centavos'), +) + +TEST_CASES_TO_CURRENCY_PEN = ( + (1.00, 'un sol con cero centimos'), + (2.00, 'dos soles con cero centimos'), + (8.00, 'ocho soles con cero centimos'), + (12.00, 'doce soles con cero centimos'), + (21.00, 'veintiun soles con cero centimos'), + (81.25, 'ochenta y un soles con veinticinco centimos'), + (350.90, 'trescientos cincuenta soles con noventa centimos'), + (100.00, 'cien soles con cero centimos'), ) @@ -157,9 +183,23 @@ test[1] ) - def test_currency_old(self): - for test in TEST_CASES_TO_CURRENCY_OLD: + def test_currency_esp(self): + for test in TEST_CASES_TO_CURRENCY_ESP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ESP'), + test[1] + ) + + def test_currency_usd(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='USD'), + test[1] + ) + + def test_currency_pen(self): + for test in TEST_CASES_TO_CURRENCY_PEN: self.assertEqual( - num2words(test[0], lang='es', to='currency', old=True), + num2words(test[0], lang='es', to='currency', currency='PEN'), test[1] ) diff -Nru python-num2words-0.5.6/tests/test_es_ve.py python-num2words-0.5.9/tests/test_es_ve.py --- python-num2words-0.5.6/tests/test_es_ve.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_es_ve.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,5 @@ -# encoding: UTF-8 +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or @@ -13,7 +14,6 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA - from __future__ import unicode_literals from num2words import num2words diff -Nru python-num2words-0.5.6/tests/test_fi.py python-num2words-0.5.9/tests/test_fi.py --- python-num2words-0.5.6/tests/test_fi.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_fi.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,2762 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import division, print_function, unicode_literals + +from unittest import TestCase + +from num2words import num2words + +CASES = ["nominative", "genitive", "partitive", # grammatical + "inessive", "elative", "illative", # internal locative + "adessive", "ablative", "allative", # external locative + "essive", "translative", # essive + "instructive", "abessive", "comitative"] # rare + + +def n2f(*args, **kwargs): + return num2words(lang='fi', *args, **kwargs) + + +class Num2WordsFITest(TestCase): + + def test_low(self): + + # zero + self.assertEqual( + tuple(n2f(0, to="cardinal", case=c) for c in CASES), + ("nolla", "nollan", "nollaa", + "nollassa", "nollasta", "nollaan", + "nollalla", "nollalta", "nollalle", + "nollana", "nollaksi", + "nollin", "nollatta", "nolline") + ) + self.assertEqual( + tuple(n2f(0, to="cardinal", case=c, plural=True) for c in CASES), + ("nollat", "nollien", "nollia", + "nollissa", "nollista", "nolliin", + "nollilla", "nollilta", "nollille", + "nollina", "nolliksi", + "nollin", "nollitta", "nolline") + ) + + # one + self.assertEqual( + tuple(n2f(1, to="cardinal", case=c) for c in CASES), + ("yksi", "yhden", "yhtä", + "yhdessä", "yhdestä", "yhteen", + "yhdellä", "yhdeltä", "yhdelle", + "yhtenä", "yhdeksi", + "yksin", "yhdettä", "yksine") + ) + self.assertEqual( + tuple(n2f(1, to="cardinal", case=c, plural=True) for c in CASES), + ("yhdet", "yksien", "yksiä", + "yksissä", "yksistä", "yksiin", + "yksillä", "yksiltä", "yksille", + "yksinä", "yksiksi", + "yksin", "yksittä", "yksine") + ) + + # two + self.assertEqual( + tuple(n2f(2, to="cardinal", case=c) for c in CASES), + ("kaksi", "kahden", "kahta", + "kahdessa", "kahdesta", "kahteen", + "kahdella", "kahdelta", "kahdelle", + "kahtena", "kahdeksi", + "kaksin", "kahdetta", "kaksine") + ) + self.assertEqual( + tuple(n2f(2, to="cardinal", case=c, plural=True) for c in CASES), + ("kahdet", "kaksien", "kaksia", + "kaksissa", "kaksista", "kaksiin", + "kaksilla", "kaksilta", "kaksille", + "kaksina", "kaksiksi", + "kaksin", "kaksitta", "kaksine") + ) + + # three + self.assertEqual( + tuple(n2f(3, to="cardinal", case=c) for c in CASES), + ("kolme", "kolmen", "kolmea", + "kolmessa", "kolmesta", "kolmeen", + "kolmella", "kolmelta", "kolmelle", + "kolmena", "kolmeksi", + "kolmen", "kolmetta", "kolmine") + ) + self.assertEqual( + tuple(n2f(3, to="cardinal", case=c, plural=True) for c in CASES), + ("kolmet", "kolmien", "kolmia", + "kolmissa", "kolmista", "kolmiin", + "kolmilla", "kolmilta", "kolmille", + "kolmina", "kolmiksi", + "kolmin", "kolmitta", "kolmine") + ) + + # four + self.assertEqual( + tuple(n2f(4, to="cardinal", case=c) for c in CASES), + ("neljä", "neljän", "neljää", + "neljässä", "neljästä", "neljään", + "neljällä", "neljältä", "neljälle", + "neljänä", "neljäksi", + "neljin", "neljättä", "neljine") + ) + self.assertEqual( + tuple(n2f(4, to="cardinal", case=c, plural=True) for c in CASES), + ("neljät", "neljien", "neljiä", + "neljissä", "neljistä", "neljiin", + "neljillä", "neljiltä", "neljille", + "neljinä", "neljiksi", + "neljin", "neljittä", "neljine") + ) + + # five + self.assertEqual( + tuple(n2f(5, to="cardinal", case=c) for c in CASES), + ("viisi", "viiden", "viittä", + "viidessä", "viidestä", "viiteen", + "viidellä", "viideltä", "viidelle", + "viitenä", "viideksi", + "viisin", "viidettä", "viisine") + ) + self.assertEqual( + tuple(n2f(5, to="cardinal", case=c, plural=True) for c in CASES), + ("viidet", "viisien", "viisiä", + "viisissä", "viisistä", "viisiin", + "viisillä", "viisiltä", "viisille", + "viisinä", "viisiksi", + "viisin", "viisittä", "viisine") + ) + + # six + self.assertEqual( + tuple(n2f(6, to="cardinal", case=c) for c in CASES), + ("kuusi", "kuuden", "kuutta", + "kuudessa", "kuudesta", "kuuteen", + "kuudella", "kuudelta", "kuudelle", + "kuutena", "kuudeksi", + "kuusin", "kuudetta", "kuusine") + ) + self.assertEqual( + tuple(n2f(6, to="cardinal", case=c, plural=True) for c in CASES), + ("kuudet", "kuusien", "kuusia", + "kuusissa", "kuusista", "kuusiin", + "kuusilla", "kuusilta", "kuusille", + "kuusina", "kuusiksi", + "kuusin", "kuusitta", "kuusine") + ) + + # seven + self.assertEqual( + tuple(n2f(7, to="cardinal", case=c) for c in CASES), + ("seitsemän", "seitsemän", "seitsemää", + "seitsemässä", "seitsemästä", "seitsemään", + "seitsemällä", "seitsemältä", "seitsemälle", + "seitsemänä", "seitsemäksi", + "seitsemin", "seitsemättä", "seitsemine") + ) + self.assertEqual( + tuple(n2f(7, to="cardinal", case=c, plural=True) for c in CASES), + ("seitsemät", "seitsemien", "seitsemiä", + "seitsemissä", "seitsemistä", "seitsemiin", + "seitsemillä", "seitsemiltä", "seitsemille", + "seitseminä", "seitsemiksi", + "seitsemin", "seitsemittä", "seitsemine") + ) + + # eight + self.assertEqual( + tuple(n2f(8, to="cardinal", case=c) for c in CASES), + ("kahdeksan", "kahdeksan", "kahdeksaa", + "kahdeksassa", "kahdeksasta", "kahdeksaan", + "kahdeksalla", "kahdeksalta", "kahdeksalle", + "kahdeksana", "kahdeksaksi", + "kahdeksin", "kahdeksatta", "kahdeksine") + ) + self.assertEqual( + tuple(n2f(8, to="cardinal", case=c, plural=True) for c in CASES), + ("kahdeksat", "kahdeksien", "kahdeksia", + "kahdeksissa", "kahdeksista", "kahdeksiin", + "kahdeksilla", "kahdeksilta", "kahdeksille", + "kahdeksina", "kahdeksiksi", + "kahdeksin", "kahdeksitta", "kahdeksine") + ) + self.assertEqual( + n2f(8, to="cardinal", case="genitive", plural=True, + prefer=["ain"]), + "kahdeksain" + ) + + # nine + self.assertEqual( + tuple(n2f(9, to="cardinal", case=c) for c in CASES), + ("yhdeksän", "yhdeksän", "yhdeksää", + "yhdeksässä", "yhdeksästä", "yhdeksään", + "yhdeksällä", "yhdeksältä", "yhdeksälle", + "yhdeksänä", "yhdeksäksi", + "yhdeksin", "yhdeksättä", "yhdeksine") + ) + self.assertEqual( + tuple(n2f(9, to="cardinal", case=c, plural=True) for c in CASES), + ("yhdeksät", "yhdeksien", "yhdeksiä", + "yhdeksissä", "yhdeksistä", "yhdeksiin", + "yhdeksillä", "yhdeksiltä", "yhdeksille", + "yhdeksinä", "yhdeksiksi", + "yhdeksin", "yhdeksittä", "yhdeksine") + ) + + # ten + self.assertEqual( + tuple(n2f(10, to="cardinal", case=c) for c in CASES), + ("kymmenen", "kymmenen", "kymmentä", + "kymmenessä", "kymmenestä", "kymmeneen", + "kymmenellä", "kymmeneltä", "kymmenelle", + "kymmenenä", "kymmeneksi", + "kymmenin", "kymmenettä", "kymmenine") + ) + self.assertEqual( + tuple(n2f(10, to="cardinal", case=c, plural=True) for c in CASES), + ("kymmenet", "kymmenien", "kymmeniä", + "kymmenissä", "kymmenistä", "kymmeniin", + "kymmenillä", "kymmeniltä", "kymmenille", + "kymmeninä", "kymmeniksi", + "kymmenin", "kymmenittä", "kymmenine") + ) + + # eleven + self.assertEqual( + tuple(n2f(11, to="cardinal", case=c) for c in CASES), + ("yksitoista", "yhdentoista", "yhtätoista", + "yhdessätoista", "yhdestätoista", "yhteentoista", + "yhdellätoista", "yhdeltätoista", "yhdelletoista", + "yhtenätoista", "yhdeksitoista", + "yksintoista", "yhdettätoista", "yksinetoista") + ) + self.assertEqual( + tuple(n2f(11, to="cardinal", case=c, plural=True) for c in CASES), + ("yhdettoista", "yksientoista", "yksiätoista", + "yksissätoista", "yksistätoista", "yksiintoista", + "yksillätoista", "yksiltätoista", "yksilletoista", + "yksinätoista", "yksiksitoista", + "yksintoista", "yksittätoista", "yksinetoista") + ) + + # twelve + self.assertEqual( + tuple(n2f(12, to="cardinal", case=c) for c in CASES), + ("kaksitoista", "kahdentoista", "kahtatoista", + "kahdessatoista", "kahdestatoista", "kahteentoista", + "kahdellatoista", "kahdeltatoista", "kahdelletoista", + "kahtenatoista", "kahdeksitoista", + "kaksintoista", "kahdettatoista", "kaksinetoista") + ) + self.assertEqual( + tuple(n2f(12, to="cardinal", case=c, plural=True) for c in CASES), + ("kahdettoista", "kaksientoista", "kaksiatoista", + "kaksissatoista", "kaksistatoista", "kaksiintoista", + "kaksillatoista", "kaksiltatoista", "kaksilletoista", + "kaksinatoista", "kaksiksitoista", + "kaksintoista", "kaksittatoista", "kaksinetoista") + ) + + # thirteen + self.assertEqual( + tuple(n2f(13, to="cardinal", case=c) for c in CASES), + ("kolmetoista", "kolmentoista", "kolmeatoista", + "kolmessatoista", "kolmestatoista", "kolmeentoista", + "kolmellatoista", "kolmeltatoista", "kolmelletoista", + "kolmenatoista", "kolmeksitoista", + "kolmentoista", "kolmettatoista", "kolminetoista") + ) + self.assertEqual( + tuple(n2f(13, to="cardinal", case=c, plural=True) for c in CASES), + ("kolmettoista", "kolmientoista", "kolmiatoista", + "kolmissatoista", "kolmistatoista", "kolmiintoista", + "kolmillatoista", "kolmiltatoista", "kolmilletoista", + "kolminatoista", "kolmiksitoista", + "kolmintoista", "kolmittatoista", "kolminetoista") + ) + + # fourteen + self.assertEqual( + tuple(n2f(14, to="cardinal", case=c) for c in CASES), + ("neljätoista", "neljäntoista", "neljäätoista", + "neljässätoista", "neljästätoista", "neljääntoista", + "neljällätoista", "neljältätoista", "neljälletoista", + "neljänätoista", "neljäksitoista", + "neljintoista", "neljättätoista", "neljinetoista") + ) + self.assertEqual( + tuple(n2f(14, to="cardinal", case=c, plural=True) for c in CASES), + ("neljättoista", "neljientoista", "neljiätoista", + "neljissätoista", "neljistätoista", "neljiintoista", + "neljillätoista", "neljiltätoista", "neljilletoista", + "neljinätoista", "neljiksitoista", + "neljintoista", "neljittätoista", "neljinetoista") + ) + + # fifteen + self.assertEqual( + tuple(n2f(15, to="cardinal", case=c) for c in CASES), + ("viisitoista", "viidentoista", "viittätoista", + "viidessätoista", "viidestätoista", "viiteentoista", + "viidellätoista", "viideltätoista", "viidelletoista", + "viitenätoista", "viideksitoista", + "viisintoista", "viidettätoista", "viisinetoista") + ) + self.assertEqual( + tuple(n2f(15, to="cardinal", case=c, plural=True) for c in CASES), + ("viidettoista", "viisientoista", "viisiätoista", + "viisissätoista", "viisistätoista", "viisiintoista", + "viisillätoista", "viisiltätoista", "viisilletoista", + "viisinätoista", "viisiksitoista", + "viisintoista", "viisittätoista", "viisinetoista") + ) + + # sixteen + self.assertEqual( + tuple(n2f(16, to="cardinal", case=c) for c in CASES), + ("kuusitoista", "kuudentoista", "kuuttatoista", + "kuudessatoista", "kuudestatoista", "kuuteentoista", + "kuudellatoista", "kuudeltatoista", "kuudelletoista", + "kuutenatoista", "kuudeksitoista", + "kuusintoista", "kuudettatoista", "kuusinetoista") + ) + self.assertEqual( + tuple(n2f(16, to="cardinal", case=c, plural=True) for c in CASES), + ("kuudettoista", "kuusientoista", "kuusiatoista", + "kuusissatoista", "kuusistatoista", "kuusiintoista", + "kuusillatoista", "kuusiltatoista", "kuusilletoista", + "kuusinatoista", "kuusiksitoista", + "kuusintoista", "kuusittatoista", "kuusinetoista") + ) + + # seventeen + self.assertEqual( + tuple(n2f(17, to="cardinal", case=c) for c in CASES), + ("seitsemäntoista", "seitsemäntoista", "seitsemäätoista", + "seitsemässätoista", "seitsemästätoista", "seitsemääntoista", + "seitsemällätoista", "seitsemältätoista", "seitsemälletoista", + "seitsemänätoista", "seitsemäksitoista", + "seitsemintoista", "seitsemättätoista", "seitseminetoista") + ) + self.assertEqual( + tuple(n2f(17, to="cardinal", case=c, plural=True) for c in CASES), + ("seitsemättoista", "seitsemientoista", "seitsemiätoista", + "seitsemissätoista", "seitsemistätoista", "seitsemiintoista", + "seitsemillätoista", "seitsemiltätoista", "seitsemilletoista", + "seitseminätoista", "seitsemiksitoista", + "seitsemintoista", "seitsemittätoista", "seitseminetoista") + ) + + # eighteen + self.assertEqual( + tuple(n2f(18, to="cardinal", case=c) for c in CASES), + ("kahdeksantoista", "kahdeksantoista", "kahdeksaatoista", + "kahdeksassatoista", "kahdeksastatoista", "kahdeksaantoista", + "kahdeksallatoista", "kahdeksaltatoista", "kahdeksalletoista", + "kahdeksanatoista", "kahdeksaksitoista", + "kahdeksintoista", "kahdeksattatoista", "kahdeksinetoista") + ) + self.assertEqual( + tuple(n2f(18, to="cardinal", case=c, plural=True) for c in CASES), + ("kahdeksattoista", "kahdeksientoista", "kahdeksiatoista", + "kahdeksissatoista", "kahdeksistatoista", "kahdeksiintoista", + "kahdeksillatoista", "kahdeksiltatoista", "kahdeksilletoista", + "kahdeksinatoista", "kahdeksiksitoista", + "kahdeksintoista", "kahdeksittatoista", "kahdeksinetoista") + ) + + # nineteen + self.assertEqual( + tuple(n2f(19, to="cardinal", case=c) for c in CASES), + ("yhdeksäntoista", "yhdeksäntoista", "yhdeksäätoista", + "yhdeksässätoista", "yhdeksästätoista", "yhdeksääntoista", + "yhdeksällätoista", "yhdeksältätoista", "yhdeksälletoista", + "yhdeksänätoista", "yhdeksäksitoista", + "yhdeksintoista", "yhdeksättätoista", "yhdeksinetoista") + ) + self.assertEqual( + tuple(n2f(19, to="cardinal", case=c, plural=True) for c in CASES), + ("yhdeksättoista", "yhdeksientoista", "yhdeksiätoista", + "yhdeksissätoista", "yhdeksistätoista", "yhdeksiintoista", + "yhdeksillätoista", "yhdeksiltätoista", "yhdeksilletoista", + "yhdeksinätoista", "yhdeksiksitoista", + "yhdeksintoista", "yhdeksittätoista", "yhdeksinetoista") + ) + + # twenty + self.assertEqual( + tuple(n2f(20, to="cardinal", case=c) for c in CASES), + ("kaksikymmentä", "kahdenkymmenen", "kahtakymmentä", + "kahdessakymmenessä", "kahdestakymmenestä", "kahteenkymmeneen", + "kahdellakymmenellä", "kahdeltakymmeneltä", "kahdellekymmenelle", + "kahtenakymmenenä", "kahdeksikymmeneksi", + "kaksinkymmenin", "kahdettakymmenettä", "kaksinekymmenine") + ) + self.assertEqual( + tuple(n2f(20, to="cardinal", case=c, plural=True) for c in CASES), + ("kahdetkymmenet", "kaksienkymmenien", "kaksiakymmeniä", + "kaksissakymmenissä", "kaksistakymmenistä", "kaksiinkymmeniin", + "kaksillakymmenillä", "kaksiltakymmeniltä", "kaksillekymmenille", + "kaksinakymmeninä", "kaksiksikymmeniksi", + "kaksinkymmenin", "kaksittakymmenittä", "kaksinekymmenine") + ) + + def test_low_ord(self): + + # minus one + with self.assertRaises(TypeError): + n2f(-1, to="ordinal") + + # zero + self.assertEqual( + tuple(n2f(0, to="ordinal", case=c) for c in CASES), + ("nollas", "nollannen", "nollatta", + "nollannessa", "nollannesta", "nollanteen", + "nollannella", "nollannelta", "nollannelle", + "nollantena", "nollanneksi", + "nollansin", "nollannetta", "nollansine") + ) + self.assertEqual( + tuple(n2f(0, to="ordinal", case=c, plural=True) for c in CASES), + ("nollannet", "nollansien", "nollansia", + "nollansissa", "nollansista", "nollansiin", + "nollansilla", "nollansilta", "nollansille", + "nollansina", "nollansiksi", + "nollansin", "nollansitta", "nollansine") + ) + + # one + self.assertEqual( + tuple(n2f(1, to="ordinal", case=c) for c in CASES), + ("ensimmäinen", "ensimmäisen", "ensimmäistä", + "ensimmäisessä", "ensimmäisestä", "ensimmäiseen", + "ensimmäisellä", "ensimmäiseltä", "ensimmäiselle", + "ensimmäisenä", "ensimmäiseksi", + "ensimmäisin", "ensimmäisettä", "ensimmäisine") + ) + self.assertEqual( + tuple(n2f(1, to="ordinal", case=c, plural=True) for c in CASES), + ("ensimmäiset", "ensimmäisten", "ensimmäisiä", + "ensimmäisissä", "ensimmäisistä", "ensimmäisiin", + "ensimmäisillä", "ensimmäisiltä", "ensimmäisille", + "ensimmäisinä", "ensimmäisiksi", + "ensimmäisin", "ensimmäisittä", "ensimmäisine") + ) + + # two + self.assertEqual( + tuple(n2f(2, to="ordinal", case=c) for c in CASES), + ("toinen", "toisen", "toista", + "toisessa", "toisesta", "toiseen", + "toisella", "toiselta", "toiselle", + "toisena", "toiseksi", + "toisin", "toisetta", "toisine") + ) + self.assertEqual( + tuple(n2f(2, to="ordinal", case=c, plural=True) for c in CASES), + ("toiset", "toisten", "toisia", + "toisissa", "toisista", "toisiin", + "toisilla", "toisilta", "toisille", + "toisina", "toisiksi", + "toisin", "toisitta", "toisine") + ) + + # three + self.assertEqual( + tuple(n2f(3, to="ordinal", case=c) for c in CASES), + ("kolmas", "kolmannen", "kolmatta", + "kolmannessa", "kolmannesta", "kolmanteen", + "kolmannella", "kolmannelta", "kolmannelle", + "kolmantena", "kolmanneksi", + "kolmansin", "kolmannetta", "kolmansine") + ) + self.assertEqual( + tuple(n2f(3, to="ordinal", case=c, plural=True) for c in CASES), + ("kolmannet", "kolmansien", "kolmansia", + "kolmansissa", "kolmansista", "kolmansiin", + "kolmansilla", "kolmansilta", "kolmansille", + "kolmansina", "kolmansiksi", + "kolmansin", "kolmansitta", "kolmansine") + ) + + # four + self.assertEqual( + tuple(n2f(4, to="ordinal", case=c) for c in CASES), + ("neljäs", "neljännen", "neljättä", + "neljännessä", "neljännestä", "neljänteen", + "neljännellä", "neljänneltä", "neljännelle", + "neljäntenä", "neljänneksi", + "neljänsin", "neljännettä", "neljänsine") + ) + self.assertEqual( + tuple(n2f(4, to="ordinal", case=c, plural=True) for c in CASES), + ("neljännet", "neljänsien", "neljänsiä", + "neljänsissä", "neljänsistä", "neljänsiin", + "neljänsillä", "neljänsiltä", "neljänsille", + "neljänsinä", "neljänsiksi", + "neljänsin", "neljänsittä", "neljänsine") + ) + + # five + self.assertEqual( + tuple(n2f(5, to="ordinal", case=c) for c in CASES), + ("viides", "viidennen", "viidettä", + "viidennessä", "viidennestä", "viidenteen", + "viidennellä", "viidenneltä", "viidennelle", + "viidentenä", "viidenneksi", + "viidensin", "viidennettä", "viidensine") + ) + self.assertEqual( + tuple(n2f(5, to="ordinal", case=c, plural=True) for c in CASES), + ("viidennet", "viidensien", "viidensiä", + "viidensissä", "viidensistä", "viidensiin", + "viidensillä", "viidensiltä", "viidensille", + "viidensinä", "viidensiksi", + "viidensin", "viidensittä", "viidensine") + ) + + # six + self.assertEqual( + tuple(n2f(6, to="ordinal", case=c) for c in CASES), + ("kuudes", "kuudennen", "kuudetta", + "kuudennessa", "kuudennesta", "kuudenteen", + "kuudennella", "kuudennelta", "kuudennelle", + "kuudentena", "kuudenneksi", + "kuudensin", "kuudennetta", "kuudensine") + ) + self.assertEqual( + tuple(n2f(6, to="ordinal", case=c, plural=True) for c in CASES), + ("kuudennet", "kuudensien", "kuudensia", + "kuudensissa", "kuudensista", "kuudensiin", + "kuudensilla", "kuudensilta", "kuudensille", + "kuudensina", "kuudensiksi", + "kuudensin", "kuudensitta", "kuudensine") + ) + + # seven + self.assertEqual( + tuple(n2f(7, to="ordinal", case=c) for c in CASES), + ("seitsemäs", "seitsemännen", "seitsemättä", + "seitsemännessä", "seitsemännestä", "seitsemänteen", + "seitsemännellä", "seitsemänneltä", "seitsemännelle", + "seitsemäntenä", "seitsemänneksi", + "seitsemänsin", "seitsemännettä", "seitsemänsine") + ) + self.assertEqual( + tuple(n2f(7, to="ordinal", case=c, plural=True) for c in CASES), + ("seitsemännet", "seitsemänsien", "seitsemänsiä", + "seitsemänsissä", "seitsemänsistä", "seitsemänsiin", + "seitsemänsillä", "seitsemänsiltä", "seitsemänsille", + "seitsemänsinä", "seitsemänsiksi", + "seitsemänsin", "seitsemänsittä", "seitsemänsine") + ) + + # eight + self.assertEqual( + tuple(n2f(8, to="ordinal", case=c) for c in CASES), + ("kahdeksas", "kahdeksannen", "kahdeksatta", + "kahdeksannessa", "kahdeksannesta", "kahdeksanteen", + "kahdeksannella", "kahdeksannelta", "kahdeksannelle", + "kahdeksantena", "kahdeksanneksi", + "kahdeksansin", "kahdeksannetta", "kahdeksansine") + ) + self.assertEqual( + tuple(n2f(8, to="ordinal", case=c, plural=True) for c in CASES), + ("kahdeksannet", "kahdeksansien", "kahdeksansia", + "kahdeksansissa", "kahdeksansista", "kahdeksansiin", + "kahdeksansilla", "kahdeksansilta", "kahdeksansille", + "kahdeksansina", "kahdeksansiksi", + "kahdeksansin", "kahdeksansitta", "kahdeksansine") + ) + + # nine + self.assertEqual( + tuple(n2f(9, to="ordinal", case=c) for c in CASES), + ("yhdeksäs", "yhdeksännen", "yhdeksättä", + "yhdeksännessä", "yhdeksännestä", "yhdeksänteen", + "yhdeksännellä", "yhdeksänneltä", "yhdeksännelle", + "yhdeksäntenä", "yhdeksänneksi", + "yhdeksänsin", "yhdeksännettä", "yhdeksänsine") + ) + self.assertEqual( + tuple(n2f(9, to="ordinal", case=c, plural=True) for c in CASES), + ("yhdeksännet", "yhdeksänsien", "yhdeksänsiä", + "yhdeksänsissä", "yhdeksänsistä", "yhdeksänsiin", + "yhdeksänsillä", "yhdeksänsiltä", "yhdeksänsille", + "yhdeksänsinä", "yhdeksänsiksi", + "yhdeksänsin", "yhdeksänsittä", "yhdeksänsine") + ) + + # ten + self.assertEqual( + tuple(n2f(10, to="ordinal", case=c) for c in CASES), + ("kymmenes", "kymmenennen", "kymmenettä", + "kymmenennessä", "kymmenennestä", "kymmenenteen", + "kymmenennellä", "kymmenenneltä", "kymmenennelle", + "kymmenentenä", "kymmenenneksi", + "kymmenensin", "kymmenennettä", "kymmenensine") + ) + self.assertEqual( + tuple(n2f(10, to="ordinal", case=c, plural=True) for c in CASES), + ("kymmenennet", "kymmenensien", "kymmenensiä", + "kymmenensissä", "kymmenensistä", "kymmenensiin", + "kymmenensillä", "kymmenensiltä", "kymmenensille", + "kymmenensinä", "kymmenensiksi", + "kymmenensin", "kymmenensittä", "kymmenensine") + ) + + # eleven + self.assertEqual( + tuple(n2f(11, to="ordinal", case=c) for c in CASES), + ("yhdestoista", "yhdennentoista", "yhdettätoista", + "yhdennessätoista", "yhdennestätoista", "yhdenteentoista", + "yhdennellätoista", "yhdenneltätoista", "yhdennelletoista", + "yhdentenätoista", "yhdenneksitoista", + "yhdensintoista", "yhdennettätoista", "yhdensinetoista") + ) + self.assertEqual( + tuple(n2f(11, to="ordinal", case=c, plural=True) for c in CASES), + ("yhdennettoista", "yhdensientoista", "yhdensiätoista", + "yhdensissätoista", "yhdensistätoista", "yhdensiintoista", + "yhdensillätoista", "yhdensiltätoista", "yhdensilletoista", + "yhdensinätoista", "yhdensiksitoista", + "yhdensintoista", "yhdensittätoista", "yhdensinetoista") + ) + + # twelve + self.assertEqual( + tuple(n2f(12, to="ordinal", case=c) for c in CASES), + ("kahdestoista", "kahdennentoista", "kahdettatoista", + "kahdennessatoista", "kahdennestatoista", "kahdenteentoista", + "kahdennellatoista", "kahdenneltatoista", "kahdennelletoista", + "kahdentenatoista", "kahdenneksitoista", + "kahdensintoista", "kahdennettatoista", "kahdensinetoista") + ) + self.assertEqual( + tuple(n2f(12, to="ordinal", case=c, plural=True) for c in CASES), + ("kahdennettoista", "kahdensientoista", "kahdensiatoista", + "kahdensissatoista", "kahdensistatoista", "kahdensiintoista", + "kahdensillatoista", "kahdensiltatoista", "kahdensilletoista", + "kahdensinatoista", "kahdensiksitoista", + "kahdensintoista", "kahdensittatoista", "kahdensinetoista") + ) + + # thirteen + self.assertEqual( + tuple(n2f(13, to="ordinal", case=c) for c in CASES), + ("kolmastoista", "kolmannentoista", "kolmattatoista", + "kolmannessatoista", "kolmannestatoista", "kolmanteentoista", + "kolmannellatoista", "kolmanneltatoista", "kolmannelletoista", + "kolmantenatoista", "kolmanneksitoista", + "kolmansintoista", "kolmannettatoista", "kolmansinetoista") + ) + self.assertEqual( + tuple(n2f(13, to="ordinal", case=c, plural=True) for c in CASES), + ("kolmannettoista", "kolmansientoista", "kolmansiatoista", + "kolmansissatoista", "kolmansistatoista", "kolmansiintoista", + "kolmansillatoista", "kolmansiltatoista", "kolmansilletoista", + "kolmansinatoista", "kolmansiksitoista", + "kolmansintoista", "kolmansittatoista", "kolmansinetoista") + ) + + # fourteen + self.assertEqual( + tuple(n2f(14, to="ordinal", case=c) for c in CASES), + ("neljästoista", "neljännentoista", "neljättätoista", + "neljännessätoista", "neljännestätoista", "neljänteentoista", + "neljännellätoista", "neljänneltätoista", "neljännelletoista", + "neljäntenätoista", "neljänneksitoista", + "neljänsintoista", "neljännettätoista", "neljänsinetoista") + ) + self.assertEqual( + tuple(n2f(14, to="ordinal", case=c, plural=True) for c in CASES), + ("neljännettoista", "neljänsientoista", "neljänsiätoista", + "neljänsissätoista", "neljänsistätoista", "neljänsiintoista", + "neljänsillätoista", "neljänsiltätoista", "neljänsilletoista", + "neljänsinätoista", "neljänsiksitoista", + "neljänsintoista", "neljänsittätoista", "neljänsinetoista") + ) + + # fifteen + self.assertEqual( + tuple(n2f(15, to="ordinal", case=c) for c in CASES), + ("viidestoista", "viidennentoista", "viidettätoista", + "viidennessätoista", "viidennestätoista", "viidenteentoista", + "viidennellätoista", "viidenneltätoista", "viidennelletoista", + "viidentenätoista", "viidenneksitoista", + "viidensintoista", "viidennettätoista", "viidensinetoista") + ) + self.assertEqual( + tuple(n2f(15, to="ordinal", case=c, plural=True) for c in CASES), + ("viidennettoista", "viidensientoista", "viidensiätoista", + "viidensissätoista", "viidensistätoista", "viidensiintoista", + "viidensillätoista", "viidensiltätoista", "viidensilletoista", + "viidensinätoista", "viidensiksitoista", + "viidensintoista", "viidensittätoista", "viidensinetoista") + ) + + # sixteen + self.assertEqual( + tuple(n2f(16, to="ordinal", case=c) for c in CASES), + ("kuudestoista", "kuudennentoista", "kuudettatoista", + "kuudennessatoista", "kuudennestatoista", "kuudenteentoista", + "kuudennellatoista", "kuudenneltatoista", "kuudennelletoista", + "kuudentenatoista", "kuudenneksitoista", + "kuudensintoista", "kuudennettatoista", "kuudensinetoista") + ) + self.assertEqual( + tuple(n2f(16, to="ordinal", case=c, plural=True) for c in CASES), + ("kuudennettoista", "kuudensientoista", "kuudensiatoista", + "kuudensissatoista", "kuudensistatoista", "kuudensiintoista", + "kuudensillatoista", "kuudensiltatoista", "kuudensilletoista", + "kuudensinatoista", "kuudensiksitoista", + "kuudensintoista", "kuudensittatoista", "kuudensinetoista") + ) + + # seventeen + self.assertEqual( + tuple(n2f(17, to="ordinal", case=c) for c in CASES), + ( + "seitsemästoista", + "seitsemännentoista", + "seitsemättätoista", + "seitsemännessätoista", + "seitsemännestätoista", + "seitsemänteentoista", + "seitsemännellätoista", + "seitsemänneltätoista", + "seitsemännelletoista", + "seitsemäntenätoista", + "seitsemänneksitoista", + "seitsemänsintoista", + "seitsemännettätoista", + "seitsemänsinetoista" + ) + ) + self.assertEqual( + tuple(n2f(17, to="ordinal", case=c, plural=True) for c in CASES), + ( + "seitsemännettoista", + "seitsemänsientoista", + "seitsemänsiätoista", + "seitsemänsissätoista", + "seitsemänsistätoista", + "seitsemänsiintoista", + "seitsemänsillätoista", + "seitsemänsiltätoista", + "seitsemänsilletoista", + "seitsemänsinätoista", + "seitsemänsiksitoista", + "seitsemänsintoista", + "seitsemänsittätoista", + "seitsemänsinetoista" + ) + ) + + # eighteen + self.assertEqual( + tuple(n2f(18, to="ordinal", case=c) for c in CASES), + ( + "kahdeksastoista", + "kahdeksannentoista", + "kahdeksattatoista", + "kahdeksannessatoista", + "kahdeksannestatoista", + "kahdeksanteentoista", + "kahdeksannellatoista", + "kahdeksanneltatoista", + "kahdeksannelletoista", + "kahdeksantenatoista", + "kahdeksanneksitoista", + "kahdeksansintoista", + "kahdeksannettatoista", + "kahdeksansinetoista" + ) + ) + self.assertEqual( + tuple(n2f(18, to="ordinal", case=c, plural=True) for c in CASES), + ( + "kahdeksannettoista", + "kahdeksansientoista", + "kahdeksansiatoista", + "kahdeksansissatoista", + "kahdeksansistatoista", + "kahdeksansiintoista", + "kahdeksansillatoista", + "kahdeksansiltatoista", + "kahdeksansilletoista", + "kahdeksansinatoista", + "kahdeksansiksitoista", + "kahdeksansintoista", + "kahdeksansittatoista", + "kahdeksansinetoista" + ) + ) + + # nineteen + self.assertEqual( + tuple(n2f(19, to="ordinal", case=c) for c in CASES), + ( + "yhdeksästoista", + "yhdeksännentoista", + "yhdeksättätoista", + "yhdeksännessätoista", + "yhdeksännestätoista", + "yhdeksänteentoista", + "yhdeksännellätoista", + "yhdeksänneltätoista", + "yhdeksännelletoista", + "yhdeksäntenätoista", + "yhdeksänneksitoista", + "yhdeksänsintoista", + "yhdeksännettätoista", + "yhdeksänsinetoista" + ) + ) + self.assertEqual( + tuple(n2f(19, to="ordinal", case=c, plural=True) for c in CASES), + ( + "yhdeksännettoista", + "yhdeksänsientoista", + "yhdeksänsiätoista", + "yhdeksänsissätoista", + "yhdeksänsistätoista", + "yhdeksänsiintoista", + "yhdeksänsillätoista", + "yhdeksänsiltätoista", + "yhdeksänsilletoista", + "yhdeksänsinätoista", + "yhdeksänsiksitoista", + "yhdeksänsintoista", + "yhdeksänsittätoista", + "yhdeksänsinetoista" + ) + ) + + # twenty + self.assertEqual( + tuple(n2f(20, to="ordinal", case=c) for c in CASES), + ( + "kahdeskymmenes", + "kahdennenkymmenennen", + "kahdettakymmenettä", + "kahdennessakymmenennessä", + "kahdennestakymmenennestä", + "kahdenteenkymmenenteen", + "kahdennellakymmenennellä", + "kahdenneltakymmenenneltä", + "kahdennellekymmenennelle", + "kahdentenakymmenentenä", + "kahdenneksikymmenenneksi", + "kahdensinkymmenensin", + "kahdennettakymmenennettä", + "kahdensinekymmenensine" + ) + ) + self.assertEqual( + tuple(n2f(20, to="ordinal", case=c, plural=True) for c in CASES), + ( + "kahdennetkymmenennet", + "kahdensienkymmenensien", + "kahdensiakymmenensiä", + "kahdensissakymmenensissä", + "kahdensistakymmenensistä", + "kahdensiinkymmenensiin", + "kahdensillakymmenensillä", + "kahdensiltakymmenensiltä", + "kahdensillekymmenensille", + "kahdensinakymmenensinä", + "kahdensiksikymmenensiksi", + "kahdensinkymmenensin", + "kahdensittakymmenensittä", + "kahdensinekymmenensine" + ) + ) + + def test_mid(self): + + # thirty + self.assertEqual( + tuple(n2f(30, to="cardinal", case=c) for c in CASES), + ("kolmekymmentä", "kolmenkymmenen", "kolmeakymmentä", + "kolmessakymmenessä", "kolmestakymmenestä", "kolmeenkymmeneen", + "kolmellakymmenellä", "kolmeltakymmeneltä", "kolmellekymmenelle", + "kolmenakymmenenä", "kolmeksikymmeneksi", + "kolmenkymmenin", "kolmettakymmenettä", "kolminekymmenine") + ) + self.assertEqual( + tuple(n2f(30, to="cardinal", case=c, plural=True) for c in CASES), + ("kolmetkymmenet", "kolmienkymmenien", "kolmiakymmeniä", + "kolmissakymmenissä", "kolmistakymmenistä", "kolmiinkymmeniin", + "kolmillakymmenillä", "kolmiltakymmeniltä", "kolmillekymmenille", + "kolminakymmeninä", "kolmiksikymmeniksi", + "kolminkymmenin", "kolmittakymmenittä", "kolminekymmenine") + ) + + # forty + self.assertEqual( + tuple(n2f(40, to="cardinal", case=c) for c in CASES), + ("neljäkymmentä", "neljänkymmenen", "neljääkymmentä", + "neljässäkymmenessä", "neljästäkymmenestä", "neljäänkymmeneen", + "neljälläkymmenellä", "neljältäkymmeneltä", "neljällekymmenelle", + "neljänäkymmenenä", "neljäksikymmeneksi", + "neljinkymmenin", "neljättäkymmenettä", "neljinekymmenine") + ) + self.assertEqual( + tuple(n2f(40, to="cardinal", case=c, plural=True) for c in CASES), + ("neljätkymmenet", "neljienkymmenien", "neljiäkymmeniä", + "neljissäkymmenissä", "neljistäkymmenistä", "neljiinkymmeniin", + "neljilläkymmenillä", "neljiltäkymmeniltä", "neljillekymmenille", + "neljinäkymmeninä", "neljiksikymmeniksi", + "neljinkymmenin", "neljittäkymmenittä", "neljinekymmenine") + ) + + # fifty + self.assertEqual( + tuple(n2f(50, to="cardinal", case=c) for c in CASES), + ("viisikymmentä", "viidenkymmenen", "viittäkymmentä", + "viidessäkymmenessä", "viidestäkymmenestä", "viiteenkymmeneen", + "viidelläkymmenellä", "viideltäkymmeneltä", "viidellekymmenelle", + "viitenäkymmenenä", "viideksikymmeneksi", + "viisinkymmenin", "viidettäkymmenettä", "viisinekymmenine") + ) + self.assertEqual( + tuple(n2f(50, to="cardinal", case=c, plural=True) for c in CASES), + ("viidetkymmenet", "viisienkymmenien", "viisiäkymmeniä", + "viisissäkymmenissä", "viisistäkymmenistä", "viisiinkymmeniin", + "viisilläkymmenillä", "viisiltäkymmeniltä", "viisillekymmenille", + "viisinäkymmeninä", "viisiksikymmeniksi", + "viisinkymmenin", "viisittäkymmenittä", "viisinekymmenine") + ) + + # sixty + self.assertEqual( + tuple(n2f(60, to="cardinal", case=c) for c in CASES), + ("kuusikymmentä", "kuudenkymmenen", "kuuttakymmentä", + "kuudessakymmenessä", "kuudestakymmenestä", "kuuteenkymmeneen", + "kuudellakymmenellä", "kuudeltakymmeneltä", "kuudellekymmenelle", + "kuutenakymmenenä", "kuudeksikymmeneksi", + "kuusinkymmenin", "kuudettakymmenettä", "kuusinekymmenine") + ) + self.assertEqual( + tuple(n2f(60, to="cardinal", case=c, plural=True) for c in CASES), + ("kuudetkymmenet", "kuusienkymmenien", "kuusiakymmeniä", + "kuusissakymmenissä", "kuusistakymmenistä", "kuusiinkymmeniin", + "kuusillakymmenillä", "kuusiltakymmeniltä", "kuusillekymmenille", + "kuusinakymmeninä", "kuusiksikymmeniksi", + "kuusinkymmenin", "kuusittakymmenittä", "kuusinekymmenine") + ) + + # seventy + self.assertEqual( + tuple(n2f(70, to="cardinal", case=c) for c in CASES), + ( + "seitsemänkymmentä", + "seitsemänkymmenen", + "seitsemääkymmentä", + "seitsemässäkymmenessä", + "seitsemästäkymmenestä", + "seitsemäänkymmeneen", + "seitsemälläkymmenellä", + "seitsemältäkymmeneltä", + "seitsemällekymmenelle", + "seitsemänäkymmenenä", + "seitsemäksikymmeneksi", + "seitseminkymmenin", + "seitsemättäkymmenettä", + "seitseminekymmenine" + ) + ) + self.assertEqual( + tuple(n2f(70, to="cardinal", case=c, plural=True) for c in CASES), + ( + "seitsemätkymmenet", + "seitsemienkymmenien", + "seitsemiäkymmeniä", + "seitsemissäkymmenissä", + "seitsemistäkymmenistä", + "seitsemiinkymmeniin", + "seitsemilläkymmenillä", + "seitsemiltäkymmeniltä", + "seitsemillekymmenille", + "seitseminäkymmeninä", + "seitsemiksikymmeniksi", + "seitseminkymmenin", + "seitsemittäkymmenittä", + "seitseminekymmenine" + ) + ) + + # eighty + self.assertEqual( + tuple(n2f(80, to="cardinal", case=c) for c in CASES), + ( + "kahdeksankymmentä", + "kahdeksankymmenen", + "kahdeksaakymmentä", + "kahdeksassakymmenessä", + "kahdeksastakymmenestä", + "kahdeksaankymmeneen", + "kahdeksallakymmenellä", + "kahdeksaltakymmeneltä", + "kahdeksallekymmenelle", + "kahdeksanakymmenenä", + "kahdeksaksikymmeneksi", + "kahdeksinkymmenin", + "kahdeksattakymmenettä", + "kahdeksinekymmenine" + ) + ) + self.assertEqual( + tuple(n2f(80, to="cardinal", case=c, plural=True) for c in CASES), + ( + "kahdeksatkymmenet", + "kahdeksienkymmenien", + "kahdeksiakymmeniä", + "kahdeksissakymmenissä", + "kahdeksistakymmenistä", + "kahdeksiinkymmeniin", + "kahdeksillakymmenillä", + "kahdeksiltakymmeniltä", + "kahdeksillekymmenille", + "kahdeksinakymmeninä", + "kahdeksiksikymmeniksi", + "kahdeksinkymmenin", + "kahdeksittakymmenittä", + "kahdeksinekymmenine" + ) + ) + + # ninety + self.assertEqual( + tuple(n2f(90, to="cardinal", case=c) for c in CASES), + ( + "yhdeksänkymmentä", + "yhdeksänkymmenen", + "yhdeksääkymmentä", + "yhdeksässäkymmenessä", + "yhdeksästäkymmenestä", + "yhdeksäänkymmeneen", + "yhdeksälläkymmenellä", + "yhdeksältäkymmeneltä", + "yhdeksällekymmenelle", + "yhdeksänäkymmenenä", + "yhdeksäksikymmeneksi", + "yhdeksinkymmenin", + "yhdeksättäkymmenettä", + "yhdeksinekymmenine" + ) + ) + self.assertEqual( + tuple(n2f(90, to="cardinal", case=c, plural=True) for c in CASES), + ( + "yhdeksätkymmenet", + "yhdeksienkymmenien", + "yhdeksiäkymmeniä", + "yhdeksissäkymmenissä", + "yhdeksistäkymmenistä", + "yhdeksiinkymmeniin", + "yhdeksilläkymmenillä", + "yhdeksiltäkymmeniltä", + "yhdeksillekymmenille", + "yhdeksinäkymmeninä", + "yhdeksiksikymmeniksi", + "yhdeksinkymmenin", + "yhdeksittäkymmenittä", + "yhdeksinekymmenine" + ) + ) + + # one hundred + self.assertEqual( + tuple(n2f(100, to="cardinal", case=c) for c in CASES), + ("sata", "sadan", "sataa", + "sadassa", "sadasta", "sataan", + "sadalla", "sadalta", "sadalle", + "satana", "sadaksi", + "sadoin", "sadatta", "satoine") + ) + self.assertEqual( + tuple(n2f(100, to="cardinal", case=c, plural=True) for c in CASES), + ("sadat", "satojen", "satoja", + "sadoissa", "sadoista", "satoihin", + "sadoilla", "sadoilta", "sadoille", + "satoina", "sadoiksi", + "sadoin", "sadoitta", "satoine") + ) + + # one hundred and twenty-three + self.assertEqual( + tuple(n2f(123, to="cardinal", case=c) for c in CASES), + ( + "satakaksikymmentäkolme", + "sadankahdenkymmenenkolmen", + "sataakahtakymmentäkolmea", + "sadassakahdessakymmenessäkolmessa", + "sadastakahdestakymmenestäkolmesta", + "sataankahteenkymmeneenkolmeen", + "sadallakahdellakymmenelläkolmella", + "sadaltakahdeltakymmeneltäkolmelta", + "sadallekahdellekymmenellekolmelle", + "satanakahtenakymmenenäkolmena", + "sadaksikahdeksikymmeneksikolmeksi", + "sadoinkaksinkymmeninkolmen", + "sadattakahdettakymmenettäkolmetta", + "satoinekaksinekymmeninekolmine" + ) + ) + self.assertEqual( + tuple(n2f(123, to="cardinal", case=c, plural=True) for c in CASES), + ( + "sadatkahdetkymmenetkolmet", + "satojenkaksienkymmenienkolmien", + "satojakaksiakymmeniäkolmia", + "sadoissakaksissakymmenissäkolmissa", + "sadoistakaksistakymmenistäkolmista", + "satoihinkaksiinkymmeniinkolmiin", + "sadoillakaksillakymmenilläkolmilla", + "sadoiltakaksiltakymmeniltäkolmilta", + "sadoillekaksillekymmenillekolmille", + "satoinakaksinakymmeninäkolmina", + "sadoiksikaksiksikymmeniksikolmiksi", + "sadoinkaksinkymmeninkolmin", + "sadoittakaksittakymmenittäkolmitta", + "satoinekaksinekymmeninekolmine" + ) + ) + + # one thousand + self.assertEqual( + tuple(n2f(1000, to="cardinal", case=c) for c in CASES), + ("tuhat", "tuhannen", "tuhatta", + "tuhannessa", "tuhannesta", "tuhanteen", + "tuhannella", "tuhannelta", "tuhannelle", + "tuhantena", "tuhanneksi", + "tuhansin", "tuhannetta", "tuhansine") + ) + self.assertEqual( + tuple(n2f(1000, to="cardinal", case=c, plural=True) + for c in CASES), + ("tuhannet", "tuhansien", "tuhansia", + "tuhansissa", "tuhansista", "tuhansiin", + "tuhansilla", "tuhansilta", "tuhansille", + "tuhansina", "tuhansiksi", + "tuhansin", "tuhansitta", "tuhansine") + ) + + # one thousand, two hundred and thirty-four + self.assertEqual( + tuple(n2f(1234, to="cardinal", case=c) for c in CASES), + ( + "tuhat kaksisataakolmekymmentäneljä", + "tuhannen kahdensadankolmenkymmenenneljän", + "tuhatta kahtasataakolmeakymmentäneljää", + "tuhannessa kahdessasadassakolmessakymmenessäneljässä", + "tuhannesta kahdestasadastakolmestakymmenestäneljästä", + "tuhanteen kahteensataankolmeenkymmeneenneljään", + "tuhannella kahdellasadallakolmellakymmenelläneljällä", + "tuhannelta kahdeltasadaltakolmeltakymmeneltäneljältä", + "tuhannelle kahdellesadallekolmellekymmenelleneljälle", + "tuhantena kahtenasatanakolmenakymmenenäneljänä", + "tuhanneksi kahdeksisadaksikolmeksikymmeneksineljäksi", + "tuhansin kaksinsadoinkolmenkymmeninneljin", + "tuhannetta kahdettasadattakolmettakymmenettäneljättä", + "tuhansine kaksinesatoinekolminekymmenineneljine" + ) + ) + self.assertEqual( + tuple(n2f(1234, to="cardinal", case=c, plural=True) + for c in CASES), + ( + "tuhannet kahdetsadatkolmetkymmenetneljät", + "tuhansien kaksiensatojenkolmienkymmenienneljien", + "tuhansia kaksiasatojakolmiakymmeniäneljiä", + "tuhansissa kaksissasadoissakolmissakymmenissäneljissä", + "tuhansista kaksistasadoistakolmistakymmenistäneljistä", + "tuhansiin kaksiinsatoihinkolmiinkymmeniinneljiin", + "tuhansilla kaksillasadoillakolmillakymmenilläneljillä", + "tuhansilta kaksiltasadoiltakolmiltakymmeniltäneljiltä", + "tuhansille kaksillesadoillekolmillekymmenilleneljille", + "tuhansina kaksinasatoinakolminakymmeninäneljinä", + "tuhansiksi kaksiksisadoiksikolmiksikymmeniksineljiksi", + "tuhansin kaksinsadoinkolminkymmeninneljin", + "tuhansitta kaksittasadoittakolmittakymmenittäneljittä", + "tuhansine kaksinesatoinekolminekymmenineneljine" + ) + ) + + def test_mid_ord(self): + + # thirty + self.assertEqual( + tuple(n2f(30, to="ordinal", case=c) for c in CASES), + ( + "kolmaskymmenes", + "kolmannenkymmenennen", + "kolmattakymmenettä", + "kolmannessakymmenennessä", + "kolmannestakymmenennestä", + "kolmanteenkymmenenteen", + "kolmannellakymmenennellä", + "kolmanneltakymmenenneltä", + "kolmannellekymmenennelle", + "kolmantenakymmenentenä", + "kolmanneksikymmenenneksi", + "kolmansinkymmenensin", + "kolmannettakymmenennettä", + "kolmansinekymmenensine" + ) + ) + self.assertEqual( + tuple(n2f(30, to="ordinal", case=c, plural=True) for c in CASES), + ( + "kolmannetkymmenennet", + "kolmansienkymmenensien", + "kolmansiakymmenensiä", + "kolmansissakymmenensissä", + "kolmansistakymmenensistä", + "kolmansiinkymmenensiin", + "kolmansillakymmenensillä", + "kolmansiltakymmenensiltä", + "kolmansillekymmenensille", + "kolmansinakymmenensinä", + "kolmansiksikymmenensiksi", + "kolmansinkymmenensin", + "kolmansittakymmenensittä", + "kolmansinekymmenensine" + ) + ) + + # forty + self.assertEqual( + tuple(n2f(40, to="ordinal", case=c) for c in CASES), + ( + "neljäskymmenes", + "neljännenkymmenennen", + "neljättäkymmenettä", + "neljännessäkymmenennessä", + "neljännestäkymmenennestä", + "neljänteenkymmenenteen", + "neljännelläkymmenennellä", + "neljänneltäkymmenenneltä", + "neljännellekymmenennelle", + "neljäntenäkymmenentenä", + "neljänneksikymmenenneksi", + "neljänsinkymmenensin", + "neljännettäkymmenennettä", + "neljänsinekymmenensine" + ) + ) + self.assertEqual( + tuple(n2f(40, to="ordinal", case=c, plural=True) for c in CASES), + ( + "neljännetkymmenennet", + "neljänsienkymmenensien", + "neljänsiäkymmenensiä", + "neljänsissäkymmenensissä", + "neljänsistäkymmenensistä", + "neljänsiinkymmenensiin", + "neljänsilläkymmenensillä", + "neljänsiltäkymmenensiltä", + "neljänsillekymmenensille", + "neljänsinäkymmenensinä", + "neljänsiksikymmenensiksi", + "neljänsinkymmenensin", + "neljänsittäkymmenensittä", + "neljänsinekymmenensine" + ) + ) + + # fifty + self.assertEqual( + tuple(n2f(50, to="ordinal", case=c) for c in CASES), + ( + "viideskymmenes", + "viidennenkymmenennen", + "viidettäkymmenettä", + "viidennessäkymmenennessä", + "viidennestäkymmenennestä", + "viidenteenkymmenenteen", + "viidennelläkymmenennellä", + "viidenneltäkymmenenneltä", + "viidennellekymmenennelle", + "viidentenäkymmenentenä", + "viidenneksikymmenenneksi", + "viidensinkymmenensin", + "viidennettäkymmenennettä", + "viidensinekymmenensine" + ) + ) + self.assertEqual( + tuple(n2f(50, to="ordinal", case=c, plural=True) for c in CASES), + ( + "viidennetkymmenennet", + "viidensienkymmenensien", + "viidensiäkymmenensiä", + "viidensissäkymmenensissä", + "viidensistäkymmenensistä", + "viidensiinkymmenensiin", + "viidensilläkymmenensillä", + "viidensiltäkymmenensiltä", + "viidensillekymmenensille", + "viidensinäkymmenensinä", + "viidensiksikymmenensiksi", + "viidensinkymmenensin", + "viidensittäkymmenensittä", + "viidensinekymmenensine" + ) + ) + + # sixty + self.assertEqual( + tuple(n2f(60, to="ordinal", case=c) for c in CASES), + ( + "kuudeskymmenes", + "kuudennenkymmenennen", + "kuudettakymmenettä", + "kuudennessakymmenennessä", + "kuudennestakymmenennestä", + "kuudenteenkymmenenteen", + "kuudennellakymmenennellä", + "kuudenneltakymmenenneltä", + "kuudennellekymmenennelle", + "kuudentenakymmenentenä", + "kuudenneksikymmenenneksi", + "kuudensinkymmenensin", + "kuudennettakymmenennettä", + "kuudensinekymmenensine" + ) + ) + self.assertEqual( + tuple(n2f(60, to="ordinal", case=c, plural=True) for c in CASES), + ( + "kuudennetkymmenennet", + "kuudensienkymmenensien", + "kuudensiakymmenensiä", + "kuudensissakymmenensissä", + "kuudensistakymmenensistä", + "kuudensiinkymmenensiin", + "kuudensillakymmenensillä", + "kuudensiltakymmenensiltä", + "kuudensillekymmenensille", + "kuudensinakymmenensinä", + "kuudensiksikymmenensiksi", + "kuudensinkymmenensin", + "kuudensittakymmenensittä", + "kuudensinekymmenensine" + ) + ) + + # seventy + self.assertEqual( + tuple(n2f(70, to="ordinal", case=c) for c in CASES), + ( + "seitsemäskymmenes", + "seitsemännenkymmenennen", + "seitsemättäkymmenettä", + "seitsemännessäkymmenennessä", + "seitsemännestäkymmenennestä", + "seitsemänteenkymmenenteen", + "seitsemännelläkymmenennellä", + "seitsemänneltäkymmenenneltä", + "seitsemännellekymmenennelle", + "seitsemäntenäkymmenentenä", + "seitsemänneksikymmenenneksi", + "seitsemänsinkymmenensin", + "seitsemännettäkymmenennettä", + "seitsemänsinekymmenensine" + ) + ) + self.assertEqual( + tuple(n2f(70, to="ordinal", case=c, plural=True) for c in CASES), + ( + "seitsemännetkymmenennet", + "seitsemänsienkymmenensien", + "seitsemänsiäkymmenensiä", + "seitsemänsissäkymmenensissä", + "seitsemänsistäkymmenensistä", + "seitsemänsiinkymmenensiin", + "seitsemänsilläkymmenensillä", + "seitsemänsiltäkymmenensiltä", + "seitsemänsillekymmenensille", + "seitsemänsinäkymmenensinä", + "seitsemänsiksikymmenensiksi", + "seitsemänsinkymmenensin", + "seitsemänsittäkymmenensittä", + "seitsemänsinekymmenensine" + ) + ) + + # eighty + self.assertEqual( + tuple(n2f(80, to="ordinal", case=c) for c in CASES), + ( + "kahdeksaskymmenes", + "kahdeksannenkymmenennen", + "kahdeksattakymmenettä", + "kahdeksannessakymmenennessä", + "kahdeksannestakymmenennestä", + "kahdeksanteenkymmenenteen", + "kahdeksannellakymmenennellä", + "kahdeksanneltakymmenenneltä", + "kahdeksannellekymmenennelle", + "kahdeksantenakymmenentenä", + "kahdeksanneksikymmenenneksi", + "kahdeksansinkymmenensin", + "kahdeksannettakymmenennettä", + "kahdeksansinekymmenensine" + ) + ) + self.assertEqual( + tuple(n2f(80, to="ordinal", case=c, plural=True) for c in CASES), + ( + "kahdeksannetkymmenennet", + "kahdeksansienkymmenensien", + "kahdeksansiakymmenensiä", + "kahdeksansissakymmenensissä", + "kahdeksansistakymmenensistä", + "kahdeksansiinkymmenensiin", + "kahdeksansillakymmenensillä", + "kahdeksansiltakymmenensiltä", + "kahdeksansillekymmenensille", + "kahdeksansinakymmenensinä", + "kahdeksansiksikymmenensiksi", + "kahdeksansinkymmenensin", + "kahdeksansittakymmenensittä", + "kahdeksansinekymmenensine" + ) + ) + + # ninety + self.assertEqual( + tuple(n2f(90, to="ordinal", case=c) for c in CASES), + ( + "yhdeksäskymmenes", + "yhdeksännenkymmenennen", + "yhdeksättäkymmenettä", + "yhdeksännessäkymmenennessä", + "yhdeksännestäkymmenennestä", + "yhdeksänteenkymmenenteen", + "yhdeksännelläkymmenennellä", + "yhdeksänneltäkymmenenneltä", + "yhdeksännellekymmenennelle", + "yhdeksäntenäkymmenentenä", + "yhdeksänneksikymmenenneksi", + "yhdeksänsinkymmenensin", + "yhdeksännettäkymmenennettä", + "yhdeksänsinekymmenensine" + ) + ) + self.assertEqual( + tuple(n2f(90, to="ordinal", case=c, plural=True) for c in CASES), + ( + "yhdeksännetkymmenennet", + "yhdeksänsienkymmenensien", + "yhdeksänsiäkymmenensiä", + "yhdeksänsissäkymmenensissä", + "yhdeksänsistäkymmenensistä", + "yhdeksänsiinkymmenensiin", + "yhdeksänsilläkymmenensillä", + "yhdeksänsiltäkymmenensiltä", + "yhdeksänsillekymmenensille", + "yhdeksänsinäkymmenensinä", + "yhdeksänsiksikymmenensiksi", + "yhdeksänsinkymmenensin", + "yhdeksänsittäkymmenensittä", + "yhdeksänsinekymmenensine" + ) + ) + + # one hundred + self.assertEqual( + tuple(n2f(100, to="ordinal", case=c) for c in CASES), + ("sadas", "sadannen", "sadatta", + "sadannessa", "sadannesta", "sadanteen", + "sadannella", "sadannelta", "sadannelle", + "sadantena", "sadanneksi", + "sadansin", "sadannetta", "sadansine") + ) + self.assertEqual( + tuple(n2f(100, to="ordinal", case=c, plural=True) for c in CASES), + ("sadannet", "sadansien", "sadansia", + "sadansissa", "sadansista", "sadansiin", + "sadansilla", "sadansilta", "sadansille", + "sadansina", "sadansiksi", + "sadansin", "sadansitta", "sadansine") + ) + + # one hundred and twenty-three + self.assertEqual( + tuple(n2f(123, to="ordinal", case=c) for c in CASES), + ( + "sadaskahdeskymmeneskolmas", + "sadannenkahdennenkymmenennenkolmannen", + "sadattakahdettakymmenettäkolmatta", + "sadannessakahdennessakymmenennessäkolmannessa", + "sadannestakahdennestakymmenennestäkolmannesta", + "sadanteenkahdenteenkymmenenteenkolmanteen", + "sadannellakahdennellakymmenennelläkolmannella", + "sadanneltakahdenneltakymmenenneltäkolmannelta", + "sadannellekahdennellekymmenennellekolmannelle", + "sadantenakahdentenakymmenentenäkolmantena", + "sadanneksikahdenneksikymmenenneksikolmanneksi", + "sadansinkahdensinkymmenensinkolmansin", + "sadannettakahdennettakymmenennettäkolmannetta", + "sadansinekahdensinekymmenensinekolmansine" + ) + ) + self.assertEqual( + tuple(n2f(123, to="ordinal", case=c, plural=True) for c in CASES), + ( + "sadannetkahdennetkymmenennetkolmannet", + "sadansienkahdensienkymmenensienkolmansien", + "sadansiakahdensiakymmenensiäkolmansia", + "sadansissakahdensissakymmenensissäkolmansissa", + "sadansistakahdensistakymmenensistäkolmansista", + "sadansiinkahdensiinkymmenensiinkolmansiin", + "sadansillakahdensillakymmenensilläkolmansilla", + "sadansiltakahdensiltakymmenensiltäkolmansilta", + "sadansillekahdensillekymmenensillekolmansille", + "sadansinakahdensinakymmenensinäkolmansina", + "sadansiksikahdensiksikymmenensiksikolmansiksi", + "sadansinkahdensinkymmenensinkolmansin", + "sadansittakahdensittakymmenensittäkolmansitta", + "sadansinekahdensinekymmenensinekolmansine" + ) + ) + + # one thousand + self.assertEqual( + tuple(n2f(1000, to="ordinal", case=c) for c in CASES), + ("tuhannes", "tuhannennen", "tuhannetta", + "tuhannennessa", "tuhannennesta", "tuhannenteen", + "tuhannennella", "tuhannennelta", "tuhannennelle", + "tuhannentena", "tuhannenneksi", + "tuhannensin", "tuhannennetta", "tuhannensine") + ) + self.assertEqual( + tuple(n2f(1000, to="ordinal", case=c, plural=True) for c in CASES), + ("tuhannennet", "tuhannensien", "tuhannensia", + "tuhannensissa", "tuhannensista", "tuhannensiin", + "tuhannensilla", "tuhannensilta", "tuhannensille", + "tuhannensina", "tuhannensiksi", + "tuhannensin", "tuhannensitta", "tuhannensine") + ) + + # one thousand, two hundred and thirty-four + self.assertEqual( + tuple(n2f(1234, to="ordinal", case=c) for c in CASES), + ( + "tuhannes kahdessadaskolmaskymmenesneljäs", + "tuhannennen kahdennensadannenkolmannenkymmenennenneljännen", + "tuhannetta kahdettasadattakolmattakymmenettäneljättä", + "tuhannennessa kahdennessasadannessa" + "kolmannessakymmenennessäneljännessä", + "tuhannennesta kahdennestasadannesta" + "kolmannestakymmenennestäneljännestä", + "tuhannenteen kahdenteensadanteen" + "kolmanteenkymmenenteenneljänteen", + "tuhannennella kahdennellasadannella" + "kolmannellakymmenennelläneljännellä", + "tuhannennelta kahdenneltasadannelta" + "kolmanneltakymmenenneltäneljänneltä", + "tuhannennelle kahdennellesadannelle" + "kolmannellekymmenennelleneljännelle", + "tuhannentena kahdentenasadantena" + "kolmantenakymmenentenäneljäntenä", + "tuhannenneksi kahdenneksisadanneksi" + "kolmanneksikymmenenneksineljänneksi", + "tuhannensin kahdensinsadansin" + "kolmansinkymmenensinneljänsin", + "tuhannennetta kahdennettasadannetta" + "kolmannettakymmenennettäneljännettä", + "tuhannensine kahdensinesadansine" + "kolmansinekymmenensineneljänsine" + ) + ) + self.assertEqual( + tuple(n2f(1234, to="ordinal", case=c, plural=True) for c in CASES), + ( + "tuhannennet kahdennetsadannet" + "kolmannetkymmenennetneljännet", + "tuhannensien kahdensiensadansien" + "kolmansienkymmenensienneljänsien", + "tuhannensia kahdensiasadansia" + "kolmansiakymmenensiäneljänsiä", + "tuhannensissa kahdensissasadansissa" + "kolmansissakymmenensissäneljänsissä", + "tuhannensista kahdensistasadansista" + "kolmansistakymmenensistäneljänsistä", + "tuhannensiin kahdensiinsadansiin" + "kolmansiinkymmenensiinneljänsiin", + "tuhannensilla kahdensillasadansilla" + "kolmansillakymmenensilläneljänsillä", + "tuhannensilta kahdensiltasadansilta" + "kolmansiltakymmenensiltäneljänsiltä", + "tuhannensille kahdensillesadansille" + "kolmansillekymmenensilleneljänsille", + "tuhannensina kahdensinasadansina" + "kolmansinakymmenensinäneljänsinä", + "tuhannensiksi kahdensiksisadansiksi" + "kolmansiksikymmenensiksineljänsiksi", + "tuhannensin kahdensinsadansin" + "kolmansinkymmenensinneljänsin", + "tuhannensitta kahdensittasadansitta" + "kolmansittakymmenensittäneljänsittä", + "tuhannensine kahdensinesadansine" + "kolmansinekymmenensineneljänsine" + ) + ) + + def test_high(self): + + # ten thousand + self.assertEqual( + tuple(n2f(10000, to="cardinal", case=c) for c in CASES), + ( + "kymmenentuhatta", + "kymmenentuhannen", + "kymmentätuhatta", + "kymmenessätuhannessa", + "kymmenestätuhannesta", + "kymmeneentuhanteen", + "kymmenellätuhannella", + "kymmeneltätuhannelta", + "kymmenelletuhannelle", + "kymmenenätuhantena", + "kymmeneksituhanneksi", + "kymmenintuhansin", + "kymmenettätuhannetta", + "kymmeninetuhansine" + ) + ) + self.assertEqual( + tuple(n2f(10000, to="cardinal", case=c, plural=True) + for c in CASES), + ( + "kymmenettuhannet", + "kymmenientuhansien", + "kymmeniätuhansia", + "kymmenissätuhansissa", + "kymmenistätuhansista", + "kymmeniintuhansiin", + "kymmenillätuhansilla", + "kymmeniltätuhansilta", + "kymmenilletuhansille", + "kymmeninätuhansina", + "kymmeniksituhansiksi", + "kymmenintuhansin", + "kymmenittätuhansitta", + "kymmeninetuhansine" + ) + ) + + # twelve thousand, three hundred and forty-five + self.assertEqual( + tuple(n2f(12345, to="cardinal", case=c) for c in CASES), + ( + "kaksitoistatuhatta " + "kolmesataaneljäkymmentäviisi", + "kahdentoistatuhannen " + "kolmensadanneljänkymmenenviiden", + "kahtatoistatuhatta " + "kolmeasataaneljääkymmentäviittä", + "kahdessatoistatuhannessa " + "kolmessasadassaneljässäkymmenessäviidessä", + "kahdestatoistatuhannesta " + "kolmestasadastaneljästäkymmenestäviidestä", + "kahteentoistatuhanteen " + "kolmeensataanneljäänkymmeneenviiteen", + "kahdellatoistatuhannella " + "kolmellasadallaneljälläkymmenelläviidellä", + "kahdeltatoistatuhannelta " + "kolmeltasadaltaneljältäkymmeneltäviideltä", + "kahdelletoistatuhannelle " + "kolmellesadalleneljällekymmenelleviidelle", + "kahtenatoistatuhantena " + "kolmenasatananeljänäkymmenenäviitenä", + "kahdeksitoistatuhanneksi " + "kolmeksisadaksineljäksikymmeneksiviideksi", + "kaksintoistatuhansin " + "kolmensadoinneljinkymmeninviisin", + "kahdettatoistatuhannetta " + "kolmettasadattaneljättäkymmenettäviidettä", + "kaksinetoistatuhansine " + "kolminesatoineneljinekymmenineviisine" + ) + ) + self.assertEqual( + tuple(n2f( + 12345, to="cardinal", case=c, plural=True) for c in CASES), + ( + "kahdettoistatuhannet " + "kolmetsadatneljätkymmenetviidet", + "kaksientoistatuhansien " + "kolmiensatojenneljienkymmenienviisien", + "kaksiatoistatuhansia " + "kolmiasatojaneljiäkymmeniäviisiä", + "kaksissatoistatuhansissa " + "kolmissasadoissaneljissäkymmenissäviisissä", + "kaksistatoistatuhansista " + "kolmistasadoistaneljistäkymmenistäviisistä", + "kaksiintoistatuhansiin " + "kolmiinsatoihinneljiinkymmeniinviisiin", + "kaksillatoistatuhansilla " + "kolmillasadoillaneljilläkymmenilläviisillä", + "kaksiltatoistatuhansilta " + "kolmiltasadoiltaneljiltäkymmeniltäviisiltä", + "kaksilletoistatuhansille " + "kolmillesadoilleneljillekymmenilleviisille", + "kaksinatoistatuhansina " + "kolminasatoinaneljinäkymmeninäviisinä", + "kaksiksitoistatuhansiksi " + "kolmiksisadoiksineljiksikymmeniksiviisiksi", + "kaksintoistatuhansin " + "kolminsadoinneljinkymmeninviisin", + "kaksittatoistatuhansitta " + "kolmittasadoittaneljittäkymmenittäviisittä", + "kaksinetoistatuhansine " + "kolminesatoineneljinekymmenineviisine" + ) + ) + + # one hundred thousand + self.assertEqual( + tuple(n2f(100000, to="cardinal", case=c) for c in CASES), + ("satatuhatta", "sadantuhannen", "sataatuhatta", + "sadassatuhannessa", "sadastatuhannesta", "sataantuhanteen", + "sadallatuhannella", "sadaltatuhannelta", "sadalletuhannelle", + "satanatuhantena", "sadaksituhanneksi", + "sadointuhansin", "sadattatuhannetta", "satoinetuhansine") + ) + self.assertEqual( + tuple(n2f(100000, to="cardinal", case=c, plural=True) + for c in CASES), + ("sadattuhannet", "satojentuhansien", "satojatuhansia", + "sadoissatuhansissa", "sadoistatuhansista", "satoihintuhansiin", + "sadoillatuhansilla", "sadoiltatuhansilta", "sadoilletuhansille", + "satoinatuhansina", "sadoiksituhansiksi", + "sadointuhansin", "sadoittatuhansitta", "satoinetuhansine") + ) + + # one hundred and twenty-three thousand, four hundred and fifty-six + self.assertEqual( + tuple(n2f(123456, to="cardinal", case=c) for c in CASES), + ( + "satakaksikymmentäkolmetuhatta " + "neljäsataaviisikymmentäkuusi", + "sadankahdenkymmenenkolmentuhannen " + "neljänsadanviidenkymmenenkuuden", + "sataakahtakymmentäkolmeatuhatta " + "neljääsataaviittäkymmentäkuutta", + "sadassakahdessakymmenessäkolmessatuhannessa " + "neljässäsadassaviidessäkymmenessäkuudessa", + "sadastakahdestakymmenestäkolmestatuhannesta " + "neljästäsadastaviidestäkymmenestäkuudesta", + "sataankahteenkymmeneenkolmeentuhanteen " + "neljäänsataanviiteenkymmeneenkuuteen", + "sadallakahdellakymmenelläkolmellatuhannella " + "neljälläsadallaviidelläkymmenelläkuudella", + "sadaltakahdeltakymmeneltäkolmeltatuhannelta " + "neljältäsadaltaviideltäkymmeneltäkuudelta", + "sadallekahdellekymmenellekolmelletuhannelle " + "neljällesadalleviidellekymmenellekuudelle", + "satanakahtenakymmenenäkolmenatuhantena " + "neljänäsatanaviitenäkymmenenäkuutena", + "sadaksikahdeksikymmeneksikolmeksituhanneksi " + "neljäksisadaksiviideksikymmeneksikuudeksi", + "sadoinkaksinkymmeninkolmentuhansin " + "neljinsadoinviisinkymmeninkuusin", + "sadattakahdettakymmenettäkolmettatuhannetta " + "neljättäsadattaviidettäkymmenettäkuudetta", + "satoinekaksinekymmeninekolminetuhansine " + "neljinesatoineviisinekymmeninekuusine" + ) + ) + self.assertEqual( + tuple(n2f(123456, to="cardinal", case=c, plural=True) + for c in CASES), + ( + "sadatkahdetkymmenetkolmettuhannet " + "neljätsadatviidetkymmenetkuudet", + "satojenkaksienkymmenienkolmientuhansien " + "neljiensatojenviisienkymmenienkuusien", + "satojakaksiakymmeniäkolmiatuhansia " + "neljiäsatojaviisiäkymmeniäkuusia", + "sadoissakaksissakymmenissäkolmissatuhansissa " + "neljissäsadoissaviisissäkymmenissäkuusissa", + "sadoistakaksistakymmenistäkolmistatuhansista " + "neljistäsadoistaviisistäkymmenistäkuusista", + "satoihinkaksiinkymmeniinkolmiintuhansiin " + "neljiinsatoihinviisiinkymmeniinkuusiin", + "sadoillakaksillakymmenilläkolmillatuhansilla " + "neljilläsadoillaviisilläkymmenilläkuusilla", + "sadoiltakaksiltakymmeniltäkolmiltatuhansilta " + "neljiltäsadoiltaviisiltäkymmeniltäkuusilta", + "sadoillekaksillekymmenillekolmilletuhansille " + "neljillesadoilleviisillekymmenillekuusille", + "satoinakaksinakymmeninäkolminatuhansina " + "neljinäsatoinaviisinäkymmeninäkuusina", + "sadoiksikaksiksikymmeniksikolmiksituhansiksi " + "neljiksisadoiksiviisiksikymmeniksikuusiksi", + "sadoinkaksinkymmeninkolmintuhansin " + "neljinsadoinviisinkymmeninkuusin", + "sadoittakaksittakymmenittäkolmittatuhansitta " + "neljittäsadoittaviisittäkymmenittäkuusitta", + "satoinekaksinekymmeninekolminetuhansine " + "neljinesatoineviisinekymmeninekuusine" + ) + ) + + # one million + self.assertEqual( + tuple(n2f(10**6, to="cardinal", case=c) for c in CASES), + ("miljoona", "miljoonan", "miljoonaa", + "miljoonassa", "miljoonasta", "miljoonaan", + "miljoonalla", "miljoonalta", "miljoonalle", + "miljoonana", "miljoonaksi", + "miljoonin", "miljoonatta", "miljoonine") + ) + self.assertEqual( + tuple(n2f(10**6, to="cardinal", case=c, plural=True) + for c in CASES), + ("miljoonat", "miljoonien", "miljoonia", + "miljoonissa", "miljoonista", "miljooniin", + "miljoonilla", "miljoonilta", "miljoonille", + "miljoonina", "miljooniksi", + "miljoonin", "miljoonitta", "miljoonine") + ) + + # one million, two hundred and thirty-four thousand, + # five hundred and sixty-seven + self.assertEqual( + tuple(n2f(1234567, to="cardinal", case=c) for c in CASES), + ( + "miljoona " + "kaksisataakolmekymmentäneljätuhatta " + "viisisataakuusikymmentäseitsemän", + "miljoonan " + "kahdensadankolmenkymmenenneljäntuhannen " + "viidensadankuudenkymmenenseitsemän", + "miljoonaa " + "kahtasataakolmeakymmentäneljäätuhatta " + "viittäsataakuuttakymmentäseitsemää", + "miljoonassa " + "kahdessasadassakolmessakymmenessäneljässätuhannessa " + "viidessäsadassakuudessakymmenessäseitsemässä", + "miljoonasta " + "kahdestasadastakolmestakymmenestäneljästätuhannesta " + "viidestäsadastakuudestakymmenestäseitsemästä", + "miljoonaan " + "kahteensataankolmeenkymmeneenneljääntuhanteen " + "viiteensataankuuteenkymmeneenseitsemään", + "miljoonalla " + "kahdellasadallakolmellakymmenelläneljällätuhannella " + "viidelläsadallakuudellakymmenelläseitsemällä", + "miljoonalta " + "kahdeltasadaltakolmeltakymmeneltäneljältätuhannelta " + "viideltäsadaltakuudeltakymmeneltäseitsemältä", + "miljoonalle " + "kahdellesadallekolmellekymmenelleneljälletuhannelle " + "viidellesadallekuudellekymmenelleseitsemälle", + "miljoonana " + "kahtenasatanakolmenakymmenenäneljänätuhantena " + "viitenäsatanakuutenakymmenenäseitsemänä", + "miljoonaksi " + "kahdeksisadaksikolmeksikymmeneksineljäksituhanneksi " + "viideksisadaksikuudeksikymmeneksiseitsemäksi", + "miljoonin " + "kaksinsadoinkolmenkymmeninneljintuhansin " + "viisinsadoinkuusinkymmeninseitsemin", + "miljoonatta " + "kahdettasadattakolmettakymmenettäneljättätuhannetta " + "viidettäsadattakuudettakymmenettäseitsemättä", + "miljoonine " + "kaksinesatoinekolminekymmenineneljinetuhansine " + "viisinesatoinekuusinekymmenineseitsemine" + ) + ) + self.assertEqual( + tuple(n2f(1234567, to="cardinal", case=c, plural=True) + for c in CASES), + ( + "miljoonat " + "kahdetsadatkolmetkymmenetneljättuhannet " + "viidetsadatkuudetkymmenetseitsemät", + "miljoonien " + "kaksiensatojenkolmienkymmenienneljientuhansien " + "viisiensatojenkuusienkymmenienseitsemien", + "miljoonia " + "kaksiasatojakolmiakymmeniäneljiätuhansia " + "viisiäsatojakuusiakymmeniäseitsemiä", + "miljoonissa " + "kaksissasadoissakolmissakymmenissäneljissätuhansissa " + "viisissäsadoissakuusissakymmenissäseitsemissä", + "miljoonista " + "kaksistasadoistakolmistakymmenistäneljistätuhansista " + "viisistäsadoistakuusistakymmenistäseitsemistä", + "miljooniin " + "kaksiinsatoihinkolmiinkymmeniinneljiintuhansiin " + "viisiinsatoihinkuusiinkymmeniinseitsemiin", + "miljoonilla " + "kaksillasadoillakolmillakymmenilläneljillätuhansilla " + "viisilläsadoillakuusillakymmenilläseitsemillä", + "miljoonilta " + "kaksiltasadoiltakolmiltakymmeniltäneljiltätuhansilta " + "viisiltäsadoiltakuusiltakymmeniltäseitsemiltä", + "miljoonille " + "kaksillesadoillekolmillekymmenilleneljilletuhansille " + "viisillesadoillekuusillekymmenilleseitsemille", + "miljoonina " + "kaksinasatoinakolminakymmeninäneljinätuhansina " + "viisinäsatoinakuusinakymmeninäseitseminä", + "miljooniksi " + "kaksiksisadoiksikolmiksikymmeniksineljiksituhansiksi " + "viisiksisadoiksikuusiksikymmeniksiseitsemiksi", + "miljoonin " + "kaksinsadoinkolminkymmeninneljintuhansin " + "viisinsadoinkuusinkymmeninseitsemin", + "miljoonitta " + "kaksittasadoittakolmittakymmenittäneljittätuhansitta " + "viisittäsadoittakuusittakymmenittäseitsemittä", + "miljoonine " + "kaksinesatoinekolminekymmenineneljinetuhansine " + "viisinesatoinekuusinekymmenineseitsemine" + ) + ) + + # one billion (short scale) + self.assertEqual( + tuple(n2f(10**9, to="cardinal", case=c) for c in CASES), + ("miljardi", "miljardin", "miljardia", + "miljardissa", "miljardista", "miljardiin", + "miljardilla", "miljardilta", "miljardille", + "miljardina", "miljardiksi", + "miljardein", "miljarditta", "miljardeine") + ) + self.assertEqual( + tuple(n2f(10**9, to="cardinal", case=c, plural=True) + for c in CASES), + ("miljardit", "miljardien", "miljardeja", + "miljardeissa", "miljardeista", "miljardeihin", + "miljardeilla", "miljardeilta", "miljardeille", + "miljardeina", "miljardeiksi", + "miljardein", "miljardeitta", "miljardeine") + ) + + # one billion, two hundred and thirty-four million, + # five hundred and sixty-seven thousand, eight hundred and ninety + # (short scale) + self.assertEqual( + tuple(n2f(1234567890, to="cardinal", case=c) for c in CASES), + ( + "miljardi " + "kaksisataakolmekymmentäneljämiljoonaa " + "viisisataakuusikymmentäseitsemäntuhatta " + "kahdeksansataayhdeksänkymmentä", + "miljardin " + "kahdensadankolmenkymmenenneljänmiljoonan " + "viidensadankuudenkymmenenseitsemäntuhannen " + "kahdeksansadanyhdeksänkymmenen", + "miljardia " + "kahtasataakolmeakymmentäneljäämiljoonaa " + "viittäsataakuuttakymmentäseitsemäätuhatta " + "kahdeksaasataayhdeksääkymmentä", + "miljardissa " + "kahdessasadassakolmessakymmenessäneljässämiljoonassa " + "viidessäsadassakuudessakymmenessäseitsemässätuhannessa " + "kahdeksassasadassayhdeksässäkymmenessä", + "miljardista " + "kahdestasadastakolmestakymmenestäneljästämiljoonasta " + "viidestäsadastakuudestakymmenestäseitsemästätuhannesta " + "kahdeksastasadastayhdeksästäkymmenestä", + "miljardiin " + "kahteensataankolmeenkymmeneenneljäänmiljoonaan " + "viiteensataankuuteenkymmeneenseitsemääntuhanteen " + "kahdeksaansataanyhdeksäänkymmeneen", + "miljardilla " + "kahdellasadallakolmellakymmenelläneljällämiljoonalla " + "viidelläsadallakuudellakymmenelläseitsemällätuhannella " + "kahdeksallasadallayhdeksälläkymmenellä", + "miljardilta " + "kahdeltasadaltakolmeltakymmeneltäneljältämiljoonalta " + "viideltäsadaltakuudeltakymmeneltäseitsemältätuhannelta " + "kahdeksaltasadaltayhdeksältäkymmeneltä", + "miljardille " + "kahdellesadallekolmellekymmenelleneljällemiljoonalle " + "viidellesadallekuudellekymmenelleseitsemälletuhannelle " + "kahdeksallesadalleyhdeksällekymmenelle", + "miljardina " + "kahtenasatanakolmenakymmenenäneljänämiljoonana " + "viitenäsatanakuutenakymmenenäseitsemänätuhantena " + "kahdeksanasatanayhdeksänäkymmenenä", + "miljardiksi " + "kahdeksisadaksikolmeksikymmeneksineljäksimiljoonaksi " + "viideksisadaksikuudeksikymmeneksiseitsemäksituhanneksi " + "kahdeksaksisadaksiyhdeksäksikymmeneksi", + "miljardein " + "kaksinsadoinkolmenkymmeninneljinmiljoonin " + "viisinsadoinkuusinkymmeninseitsemintuhansin " + "kahdeksinsadoinyhdeksinkymmenin", + "miljarditta " + "kahdettasadattakolmettakymmenettäneljättämiljoonatta " + "viidettäsadattakuudettakymmenettäseitsemättätuhannetta " + "kahdeksattasadattayhdeksättäkymmenettä", + "miljardeine " + "kaksinesatoinekolminekymmenineneljinemiljoonine " + "viisinesatoinekuusinekymmenineseitseminetuhansine " + "kahdeksinesatoineyhdeksinekymmenine" + ) + ) + self.assertEqual( + tuple(n2f(1234567890, to="cardinal", case=c, plural=True) + for c in CASES), + ( + "miljardit " + "kahdetsadatkolmetkymmenetneljätmiljoonat " + "viidetsadatkuudetkymmenetseitsemättuhannet " + "kahdeksatsadatyhdeksätkymmenet", + "miljardien " + "kaksiensatojenkolmienkymmenienneljienmiljoonien " + "viisiensatojenkuusienkymmenienseitsemientuhansien " + "kahdeksiensatojenyhdeksienkymmenien", + "miljardeja " + "kaksiasatojakolmiakymmeniäneljiämiljoonia " + "viisiäsatojakuusiakymmeniäseitsemiätuhansia " + "kahdeksiasatojayhdeksiäkymmeniä", + "miljardeissa " + "kaksissasadoissakolmissakymmenissäneljissämiljoonissa " + "viisissäsadoissakuusissakymmenissäseitsemissätuhansissa " + "kahdeksissasadoissayhdeksissäkymmenissä", + "miljardeista " + "kaksistasadoistakolmistakymmenistäneljistämiljoonista " + "viisistäsadoistakuusistakymmenistäseitsemistätuhansista " + "kahdeksistasadoistayhdeksistäkymmenistä", + "miljardeihin " + "kaksiinsatoihinkolmiinkymmeniinneljiinmiljooniin " + "viisiinsatoihinkuusiinkymmeniinseitsemiintuhansiin " + "kahdeksiinsatoihinyhdeksiinkymmeniin", + "miljardeilla " + "kaksillasadoillakolmillakymmenilläneljillämiljoonilla " + "viisilläsadoillakuusillakymmenilläseitsemillätuhansilla " + "kahdeksillasadoillayhdeksilläkymmenillä", + "miljardeilta " + "kaksiltasadoiltakolmiltakymmeniltäneljiltämiljoonilta " + "viisiltäsadoiltakuusiltakymmeniltäseitsemiltätuhansilta " + "kahdeksiltasadoiltayhdeksiltäkymmeniltä", + "miljardeille " + "kaksillesadoillekolmillekymmenilleneljillemiljoonille " + "viisillesadoillekuusillekymmenilleseitsemilletuhansille " + "kahdeksillesadoilleyhdeksillekymmenille", + "miljardeina " + "kaksinasatoinakolminakymmeninäneljinämiljoonina " + "viisinäsatoinakuusinakymmeninäseitseminätuhansina " + "kahdeksinasatoinayhdeksinäkymmeninä", + "miljardeiksi " + "kaksiksisadoiksikolmiksikymmeniksineljiksimiljooniksi " + "viisiksisadoiksikuusiksikymmeniksiseitsemiksituhansiksi " + "kahdeksiksisadoiksiyhdeksiksikymmeniksi", + "miljardein " + "kaksinsadoinkolminkymmeninneljinmiljoonin " + "viisinsadoinkuusinkymmeninseitsemintuhansin " + "kahdeksinsadoinyhdeksinkymmenin", + "miljardeitta " + "kaksittasadoittakolmittakymmenittäneljittämiljoonitta " + "viisittäsadoittakuusittakymmenittäseitsemittätuhansitta " + "kahdeksittasadoittayhdeksittäkymmenittä", + "miljardeine " + "kaksinesatoinekolminekymmenineneljinemiljoonine " + "viisinesatoinekuusinekymmenineseitseminetuhansine " + "kahdeksinesatoineyhdeksinekymmenine" + ) + ) + + # one trillion (short scale) + self.assertEqual( + tuple(n2f((10**6)**2, to="cardinal", case=c) for c in CASES), + ("biljoona", "biljoonan", "biljoonaa", + "biljoonassa", "biljoonasta", "biljoonaan", + "biljoonalla", "biljoonalta", "biljoonalle", + "biljoonana", "biljoonaksi", + "biljoonin", "biljoonatta", "biljoonine") + ) + self.assertEqual( + tuple(n2f((10**6)**2, to="cardinal", case=c, plural=True) + for c in CASES), + ("biljoonat", "biljoonien", "biljoonia", + "biljoonissa", "biljoonista", "biljooniin", + "biljoonilla", "biljoonilta", "biljoonille", + "biljoonina", "biljooniksi", + "biljoonin", "biljoonitta", "biljoonine") + ) + + # one quintillion (short scale) + self.assertEqual( + tuple(n2f((10**6)**3, to="cardinal", case=c) for c in CASES), + ("triljoona", "triljoonan", "triljoonaa", + "triljoonassa", "triljoonasta", "triljoonaan", + "triljoonalla", "triljoonalta", "triljoonalle", + "triljoonana", "triljoonaksi", + "triljoonin", "triljoonatta", "triljoonine") + ) + self.assertEqual( + tuple(n2f((10**6)**3, to="cardinal", case=c, plural=True) + for c in CASES), + ("triljoonat", "triljoonien", "triljoonia", + "triljoonissa", "triljoonista", "triljooniin", + "triljoonilla", "triljoonilta", "triljoonille", + "triljoonina", "triljooniksi", + "triljoonin", "triljoonitta", "triljoonine") + ) + + def test_high_ord(self): + + # ten thousand + self.assertEqual( + tuple(n2f(10000, to="ordinal", case=c) for c in CASES), + ( + "kymmenestuhannes", + "kymmenennentuhannennen", + "kymmenettätuhannetta", + "kymmenennessätuhannennessa", + "kymmenennestätuhannennesta", + "kymmenenteentuhannenteen", + "kymmenennellätuhannennella", + "kymmenenneltätuhannennelta", + "kymmenennelletuhannennelle", + "kymmenentenätuhannentena", + "kymmenenneksituhannenneksi", + "kymmenensintuhannensin", + "kymmenennettätuhannennetta", + "kymmenensinetuhannensine" + ) + ) + self.assertEqual( + tuple(n2f(10000, to="ordinal", case=c, plural=True) + for c in CASES), + ( + "kymmenennettuhannennet", + "kymmenensientuhannensien", + "kymmenensiätuhannensia", + "kymmenensissätuhannensissa", + "kymmenensistätuhannensista", + "kymmenensiintuhannensiin", + "kymmenensillätuhannensilla", + "kymmenensiltätuhannensilta", + "kymmenensilletuhannensille", + "kymmenensinätuhannensina", + "kymmenensiksituhannensiksi", + "kymmenensintuhannensin", + "kymmenensittätuhannensitta", + "kymmenensinetuhannensine" + ) + ) + + # twelve thousand, three hundred and forty-five + self.assertEqual( + tuple(n2f(12345, to="ordinal", case=c) for c in CASES), + ( + "kahdestoistatuhannes " + "kolmassadasneljäskymmenesviides", + "kahdennentoistatuhannennen " + "kolmannensadannenneljännenkymmenennenviidennen", + "kahdettatoistatuhannetta " + "kolmattasadattaneljättäkymmenettäviidettä", + "kahdennessatoistatuhannennessa " + "kolmannessasadannessaneljännessäkymmenennessäviidennessä", + "kahdennestatoistatuhannennesta " + "kolmannestasadannestaneljännestäkymmenennestäviidennestä", + "kahdenteentoistatuhannenteen " + "kolmanteensadanteenneljänteenkymmenenteenviidenteen", + "kahdennellatoistatuhannennella " + "kolmannellasadannellaneljännelläkymmenennelläviidennellä", + "kahdenneltatoistatuhannennelta " + "kolmanneltasadanneltaneljänneltäkymmenenneltäviidenneltä", + "kahdennelletoistatuhannennelle " + "kolmannellesadannelleneljännellekymmenennelleviidennelle", + "kahdentenatoistatuhannentena " + "kolmantenasadantenaneljäntenäkymmenentenäviidentenä", + "kahdenneksitoistatuhannenneksi " + "kolmanneksisadanneksineljänneksikymmenenneksiviidenneksi", + "kahdensintoistatuhannensin " + "kolmansinsadansinneljänsinkymmenensinviidensin", + "kahdennettatoistatuhannennetta " + "kolmannettasadannettaneljännettäkymmenennettäviidennettä", + "kahdensinetoistatuhannensine " + "kolmansinesadansineneljänsinekymmenensineviidensine" + ) + ) + self.assertEqual( + tuple(n2f(12345, to="ordinal", case=c, plural=True) + for c in CASES), + ( + "kahdennettoistatuhannennet " + "kolmannetsadannetneljännetkymmenennetviidennet", + "kahdensientoistatuhannensien " + "kolmansiensadansienneljänsienkymmenensienviidensien", + "kahdensiatoistatuhannensia " + "kolmansiasadansianeljänsiäkymmenensiäviidensiä", + "kahdensissatoistatuhannensissa " + "kolmansissasadansissaneljänsissäkymmenensissäviidensissä", + "kahdensistatoistatuhannensista " + "kolmansistasadansistaneljänsistäkymmenensistäviidensistä", + "kahdensiintoistatuhannensiin " + "kolmansiinsadansiinneljänsiinkymmenensiinviidensiin", + "kahdensillatoistatuhannensilla " + "kolmansillasadansillaneljänsilläkymmenensilläviidensillä", + "kahdensiltatoistatuhannensilta " + "kolmansiltasadansiltaneljänsiltäkymmenensiltäviidensiltä", + "kahdensilletoistatuhannensille " + "kolmansillesadansilleneljänsillekymmenensilleviidensille", + "kahdensinatoistatuhannensina " + "kolmansinasadansinaneljänsinäkymmenensinäviidensinä", + "kahdensiksitoistatuhannensiksi " + "kolmansiksisadansiksineljänsiksikymmenensiksiviidensiksi", + "kahdensintoistatuhannensin " + "kolmansinsadansinneljänsinkymmenensinviidensin", + "kahdensittatoistatuhannensitta " + "kolmansittasadansittaneljänsittäkymmenensittäviidensittä", + "kahdensinetoistatuhannensine " + "kolmansinesadansineneljänsinekymmenensineviidensine" + ) + ) + + # one hundred thousand + self.assertEqual( + tuple(n2f(100000, to="ordinal", case=c) for c in CASES), + ( + "sadastuhannes", + "sadannentuhannennen", + "sadattatuhannetta", + "sadannessatuhannennessa", + "sadannestatuhannennesta", + "sadanteentuhannenteen", + "sadannellatuhannennella", + "sadanneltatuhannennelta", + "sadannelletuhannennelle", + "sadantenatuhannentena", + "sadanneksituhannenneksi", + "sadansintuhannensin", + "sadannettatuhannennetta", + "sadansinetuhannensine" + ) + ) + self.assertEqual( + tuple(n2f(100000, to="ordinal", case=c, plural=True) + for c in CASES), + ( + "sadannettuhannennet", + "sadansientuhannensien", + "sadansiatuhannensia", + "sadansissatuhannensissa", + "sadansistatuhannensista", + "sadansiintuhannensiin", + "sadansillatuhannensilla", + "sadansiltatuhannensilta", + "sadansilletuhannensille", + "sadansinatuhannensina", + "sadansiksituhannensiksi", + "sadansintuhannensin", + "sadansittatuhannensitta", + "sadansinetuhannensine" + ) + ) + + # one hundred and twenty-three thousand, four hundred and fifty-six + self.assertEqual( + tuple(n2f(123456, to="ordinal", case=c) for c in CASES), + ( + "sadaskahdeskymmeneskolmastuhannes " + "neljässadasviideskymmeneskuudes", + "sadannenkahdennenkymmenennenkolmannentuhannennen " + "neljännensadannenviidennenkymmenennenkuudennen", + "sadattakahdettakymmenettäkolmattatuhannetta " + "neljättäsadattaviidettäkymmenettäkuudetta", + "sadannessakahdennessakymmenennessäkolmannessatuhannennessa " + "neljännessäsadannessaviidennessäkymmenennessäkuudennessa", + "sadannestakahdennestakymmenennestäkolmannestatuhannennesta " + "neljännestäsadannestaviidennestäkymmenennestäkuudennesta", + "sadanteenkahdenteenkymmenenteenkolmanteentuhannenteen " + "neljänteensadanteenviidenteenkymmenenteenkuudenteen", + "sadannellakahdennellakymmenennelläkolmannellatuhannennella " + "neljännelläsadannellaviidennelläkymmenennelläkuudennella", + "sadanneltakahdenneltakymmenenneltäkolmanneltatuhannennelta " + "neljänneltäsadanneltaviidenneltäkymmenenneltäkuudennelta", + "sadannellekahdennellekymmenennellekolmannelletuhannennelle " + "neljännellesadannelleviidennellekymmenennellekuudennelle", + "sadantenakahdentenakymmenentenäkolmantenatuhannentena " + "neljäntenäsadantenaviidentenäkymmenentenäkuudentena", + "sadanneksikahdenneksikymmenenneksikolmanneksituhannenneksi " + "neljänneksisadanneksiviidenneksikymmenenneksikuudenneksi", + "sadansinkahdensinkymmenensinkolmansintuhannensin " + "neljänsinsadansinviidensinkymmenensinkuudensin", + "sadannettakahdennettakymmenennettäkolmannettatuhannennetta " + "neljännettäsadannettaviidennettäkymmenennettäkuudennetta", + "sadansinekahdensinekymmenensinekolmansinetuhannensine " + "neljänsinesadansineviidensinekymmenensinekuudensine" + ) + ) + self.assertEqual( + tuple(n2f(123456, to="ordinal", case=c, plural=True) + for c in CASES), + ( + "sadannetkahdennetkymmenennetkolmannettuhannennet " + "neljännetsadannetviidennetkymmenennetkuudennet", + "sadansienkahdensienkymmenensienkolmansientuhannensien " + "neljänsiensadansienviidensienkymmenensienkuudensien", + "sadansiakahdensiakymmenensiäkolmansiatuhannensia " + "neljänsiäsadansiaviidensiäkymmenensiäkuudensia", + "sadansissakahdensissakymmenensissäkolmansissatuhannensissa " + "neljänsissäsadansissaviidensissäkymmenensissäkuudensissa", + "sadansistakahdensistakymmenensistäkolmansistatuhannensista " + "neljänsistäsadansistaviidensistäkymmenensistäkuudensista", + "sadansiinkahdensiinkymmenensiinkolmansiintuhannensiin " + "neljänsiinsadansiinviidensiinkymmenensiinkuudensiin", + "sadansillakahdensillakymmenensilläkolmansillatuhannensilla " + "neljänsilläsadansillaviidensilläkymmenensilläkuudensilla", + "sadansiltakahdensiltakymmenensiltäkolmansiltatuhannensilta " + "neljänsiltäsadansiltaviidensiltäkymmenensiltäkuudensilta", + "sadansillekahdensillekymmenensillekolmansilletuhannensille " + "neljänsillesadansilleviidensillekymmenensillekuudensille", + "sadansinakahdensinakymmenensinäkolmansinatuhannensina " + "neljänsinäsadansinaviidensinäkymmenensinäkuudensina", + "sadansiksikahdensiksikymmenensiksikolmansiksituhannensiksi " + "neljänsiksisadansiksiviidensiksikymmenensiksikuudensiksi", + "sadansinkahdensinkymmenensinkolmansintuhannensin " + "neljänsinsadansinviidensinkymmenensinkuudensin", + "sadansittakahdensittakymmenensittäkolmansittatuhannensitta " + "neljänsittäsadansittaviidensittäkymmenensittäkuudensitta", + "sadansinekahdensinekymmenensinekolmansinetuhannensine " + "neljänsinesadansineviidensinekymmenensinekuudensine" + ) + ) + + # one million + self.assertEqual( + tuple(n2f(10**6, to="ordinal", case=c) for c in CASES), + ("miljoonas", "miljoonannen", "miljoonatta", + "miljoonannessa", "miljoonannesta", "miljoonanteen", + "miljoonannella", "miljoonannelta", "miljoonannelle", + "miljoonantena", "miljoonanneksi", + "miljoonansin", "miljoonannetta", "miljoonansine") + ) + self.assertEqual( + tuple(n2f(10**6, to="ordinal", case=c, plural=True) + for c in CASES), + ("miljoonannet", "miljoonansien", "miljoonansia", + "miljoonansissa", "miljoonansista", "miljoonansiin", + "miljoonansilla", "miljoonansilta", "miljoonansille", + "miljoonansina", "miljoonansiksi", + "miljoonansin", "miljoonansitta", "miljoonansine") + ) + + # one million, two hundred and thirty-four thousand, + # five hundred and sixty-seven + self.assertEqual( + tuple(n2f(1234567, to="ordinal", case=c) for c in CASES), + ( + "miljoonas " + "kahdessadaskolmaskymmenesneljäs" + "tuhannes " + "viidessadaskuudeskymmenesseitsemäs", + "miljoonannen " + "kahdennensadannenkolmannenkymmenennenneljännen" + "tuhannennen " + "viidennensadannenkuudennenkymmenennenseitsemännen", + "miljoonatta " + "kahdettasadattakolmattakymmenettäneljättä" + "tuhannetta " + "viidettäsadattakuudettakymmenettäseitsemättä", + "miljoonannessa " + "kahdennessasadannessakolmannessakymmenennessäneljännessä" + "tuhannennessa " + "viidennessäsadannessakuudennessakymmenennessäseitsemännessä", + "miljoonannesta " + "kahdennestasadannestakolmannestakymmenennestäneljännestä" + "tuhannennesta " + "viidennestäsadannestakuudennestakymmenennestäseitsemännestä", + "miljoonanteen " + "kahdenteensadanteenkolmanteenkymmenenteenneljänteen" + "tuhannenteen " + "viidenteensadanteenkuudenteenkymmenenteenseitsemänteen", + "miljoonannella " + "kahdennellasadannellakolmannellakymmenennelläneljännellä" + "tuhannennella " + "viidennelläsadannellakuudennellakymmenennelläseitsemännellä", + "miljoonannelta " + "kahdenneltasadanneltakolmanneltakymmenenneltäneljänneltä" + "tuhannennelta " + "viidenneltäsadanneltakuudenneltakymmenenneltäseitsemänneltä", + "miljoonannelle " + "kahdennellesadannellekolmannellekymmenennelleneljännelle" + "tuhannennelle " + "viidennellesadannellekuudennellekymmenennelleseitsemännelle", + "miljoonantena " + "kahdentenasadantenakolmantenakymmenentenäneljäntenä" + "tuhannentena " + "viidentenäsadantenakuudentenakymmenentenäseitsemäntenä", + "miljoonanneksi " + "kahdenneksisadanneksikolmanneksikymmenenneksineljänneksi" + "tuhannenneksi " + "viidenneksisadanneksikuudenneksikymmenenneksiseitsemänneksi", + "miljoonansin " + "kahdensinsadansinkolmansinkymmenensinneljänsin" + "tuhannensin " + "viidensinsadansinkuudensinkymmenensinseitsemänsin", + "miljoonannetta " + "kahdennettasadannettakolmannettakymmenennettäneljännettä" + "tuhannennetta " + "viidennettäsadannettakuudennettakymmenennettäseitsemännettä", + "miljoonansine " + "kahdensinesadansinekolmansinekymmenensineneljänsine" + "tuhannensine " + "viidensinesadansinekuudensinekymmenensineseitsemänsine" + ) + ) + self.assertEqual( + tuple(n2f(1234567, to="ordinal", case=c, plural=True) + for c in CASES), + ( + "miljoonannet " + "kahdennetsadannetkolmannetkymmenennetneljännet" + "tuhannennet " + "viidennetsadannetkuudennetkymmenennetseitsemännet", + "miljoonansien " + "kahdensiensadansienkolmansienkymmenensienneljänsien" + "tuhannensien " + "viidensiensadansienkuudensienkymmenensienseitsemänsien", + "miljoonansia " + "kahdensiasadansiakolmansiakymmenensiäneljänsiä" + "tuhannensia " + "viidensiäsadansiakuudensiakymmenensiäseitsemänsiä", + "miljoonansissa " + "kahdensissasadansissakolmansissakymmenensissäneljänsissä" + "tuhannensissa " + "viidensissäsadansissakuudensissakymmenensissäseitsemänsissä", + "miljoonansista " + "kahdensistasadansistakolmansistakymmenensistäneljänsistä" + "tuhannensista " + "viidensistäsadansistakuudensistakymmenensistäseitsemänsistä", + "miljoonansiin " + "kahdensiinsadansiinkolmansiinkymmenensiinneljänsiin" + "tuhannensiin " + "viidensiinsadansiinkuudensiinkymmenensiinseitsemänsiin", + "miljoonansilla " + "kahdensillasadansillakolmansillakymmenensilläneljänsillä" + "tuhannensilla " + "viidensilläsadansillakuudensillakymmenensilläseitsemänsillä", + "miljoonansilta " + "kahdensiltasadansiltakolmansiltakymmenensiltäneljänsiltä" + "tuhannensilta " + "viidensiltäsadansiltakuudensiltakymmenensiltäseitsemänsiltä", + "miljoonansille " + "kahdensillesadansillekolmansillekymmenensilleneljänsille" + "tuhannensille " + "viidensillesadansillekuudensillekymmenensilleseitsemänsille", + "miljoonansina " + "kahdensinasadansinakolmansinakymmenensinäneljänsinä" + "tuhannensina " + "viidensinäsadansinakuudensinakymmenensinäseitsemänsinä", + "miljoonansiksi " + "kahdensiksisadansiksikolmansiksikymmenensiksineljänsiksi" + "tuhannensiksi " + "viidensiksisadansiksikuudensiksikymmenensiksiseitsemänsiksi", + "miljoonansin " + "kahdensinsadansinkolmansinkymmenensinneljänsin" + "tuhannensin " + "viidensinsadansinkuudensinkymmenensinseitsemänsin", + "miljoonansitta " + "kahdensittasadansittakolmansittakymmenensittäneljänsittä" + "tuhannensitta " + "viidensittäsadansittakuudensittakymmenensittäseitsemänsittä", + "miljoonansine " + "kahdensinesadansinekolmansinekymmenensineneljänsine" + "tuhannensine " + "viidensinesadansinekuudensinekymmenensineseitsemänsine" + ) + ) + + # one billion (short scale) + self.assertEqual( + tuple(n2f(10**9, to="ordinal", case=c) for c in CASES), + ("miljardis", "miljardinnen", "miljarditta", + "miljardinnessa", "miljardinnesta", "miljardinteen", + "miljardinnella", "miljardinnelta", "miljardinnelle", + "miljardintena", "miljardinneksi", + "miljardinsin", "miljardinnetta", "miljardinsine") + ) + self.assertEqual( + tuple(n2f(10**9, to="ordinal", case=c, plural=True) + for c in CASES), + ("miljardinnet", "miljardinsien", "miljardinsia", + "miljardinsissa", "miljardinsista", "miljardinsiin", + "miljardinsilla", "miljardinsilta", "miljardinsille", + "miljardinsina", "miljardinsiksi", + "miljardinsin", "miljardinsitta", "miljardinsine") + ) + + # one billion, two hundred and thirty-four million, + # five hundred and sixty-seven thousand, eight hundred and ninety + # (short scale) + self.assertEqual( + tuple(n2f(1234567890, to="ordinal", case=c) for c in CASES), + ( + "miljardis " + "kahdessadaskolmaskymmenesneljäs" + "miljoonas " + "viidessadaskuudeskymmenesseitsemäs" + "tuhannes " + "kahdeksassadasyhdeksäskymmenes", + "miljardinnen " + "kahdennensadannenkolmannenkymmenennenneljännen" + "miljoonannen " + "viidennensadannenkuudennenkymmenennenseitsemännen" + "tuhannennen " + "kahdeksannensadannenyhdeksännenkymmenennen", + "miljarditta " + "kahdettasadattakolmattakymmenettäneljättä" + "miljoonatta " + "viidettäsadattakuudettakymmenettäseitsemättä" + "tuhannetta " + "kahdeksattasadattayhdeksättäkymmenettä", + "miljardinnessa " + "kahdennessasadannessakolmannessakymmenennessäneljännessä" + "miljoonannessa " + "viidennessäsadannessakuudennessakymmenennessäseitsemännessä" + "tuhannennessa " + "kahdeksannessasadannessayhdeksännessäkymmenennessä", + "miljardinnesta " + "kahdennestasadannestakolmannestakymmenennestäneljännestä" + "miljoonannesta " + "viidennestäsadannestakuudennestakymmenennestäseitsemännestä" + "tuhannennesta " + "kahdeksannestasadannestayhdeksännestäkymmenennestä", + "miljardinteen " + "kahdenteensadanteenkolmanteenkymmenenteenneljänteen" + "miljoonanteen " + "viidenteensadanteenkuudenteenkymmenenteenseitsemänteen" + "tuhannenteen " + "kahdeksanteensadanteenyhdeksänteenkymmenenteen", + "miljardinnella " + "kahdennellasadannellakolmannellakymmenennelläneljännellä" + "miljoonannella " + "viidennelläsadannellakuudennellakymmenennelläseitsemännellä" + "tuhannennella " + "kahdeksannellasadannellayhdeksännelläkymmenennellä", + "miljardinnelta " + "kahdenneltasadanneltakolmanneltakymmenenneltäneljänneltä" + "miljoonannelta " + "viidenneltäsadanneltakuudenneltakymmenenneltäseitsemänneltä" + "tuhannennelta " + "kahdeksanneltasadanneltayhdeksänneltäkymmenenneltä", + "miljardinnelle " + "kahdennellesadannellekolmannellekymmenennelleneljännelle" + "miljoonannelle " + "viidennellesadannellekuudennellekymmenennelleseitsemännelle" + "tuhannennelle " + "kahdeksannellesadannelleyhdeksännellekymmenennelle", + "miljardintena " + "kahdentenasadantenakolmantenakymmenentenäneljäntenä" + "miljoonantena " + "viidentenäsadantenakuudentenakymmenentenäseitsemäntenä" + "tuhannentena " + "kahdeksantenasadantenayhdeksäntenäkymmenentenä", + "miljardinneksi " + "kahdenneksisadanneksikolmanneksikymmenenneksineljänneksi" + "miljoonanneksi " + "viidenneksisadanneksikuudenneksikymmenenneksiseitsemänneksi" + "tuhannenneksi " + "kahdeksanneksisadanneksiyhdeksänneksikymmenenneksi", + "miljardinsin " + "kahdensinsadansinkolmansinkymmenensinneljänsin" + "miljoonansin " + "viidensinsadansinkuudensinkymmenensinseitsemänsin" + "tuhannensin " + "kahdeksansinsadansinyhdeksänsinkymmenensin", + "miljardinnetta " + "kahdennettasadannettakolmannettakymmenennettäneljännettä" + "miljoonannetta " + "viidennettäsadannettakuudennettakymmenennettäseitsemännettä" + "tuhannennetta " + "kahdeksannettasadannettayhdeksännettäkymmenennettä", + "miljardinsine " + "kahdensinesadansinekolmansinekymmenensineneljänsine" + "miljoonansine " + "viidensinesadansinekuudensinekymmenensineseitsemänsine" + "tuhannensine " + "kahdeksansinesadansineyhdeksänsinekymmenensine" + ) + ) + self.assertEqual( + tuple(n2f(1234567890, to="ordinal", case=c, plural=True) + for c in CASES), + ( + "miljardinnet " + "kahdennetsadannetkolmannetkymmenennetneljännet" + "miljoonannet " + "viidennetsadannetkuudennetkymmenennetseitsemännet" + "tuhannennet " + "kahdeksannetsadannetyhdeksännetkymmenennet", + "miljardinsien " + "kahdensiensadansienkolmansienkymmenensienneljänsien" + "miljoonansien " + "viidensiensadansienkuudensienkymmenensienseitsemänsien" + "tuhannensien " + "kahdeksansiensadansienyhdeksänsienkymmenensien", + "miljardinsia " + "kahdensiasadansiakolmansiakymmenensiäneljänsiä" + "miljoonansia " + "viidensiäsadansiakuudensiakymmenensiäseitsemänsiä" + "tuhannensia " + "kahdeksansiasadansiayhdeksänsiäkymmenensiä", + "miljardinsissa " + "kahdensissasadansissakolmansissakymmenensissäneljänsissä" + "miljoonansissa " + "viidensissäsadansissakuudensissakymmenensissäseitsemänsissä" + "tuhannensissa " + "kahdeksansissasadansissayhdeksänsissäkymmenensissä", + "miljardinsista " + "kahdensistasadansistakolmansistakymmenensistäneljänsistä" + "miljoonansista " + "viidensistäsadansistakuudensistakymmenensistäseitsemänsistä" + "tuhannensista " + "kahdeksansistasadansistayhdeksänsistäkymmenensistä", + "miljardinsiin " + "kahdensiinsadansiinkolmansiinkymmenensiinneljänsiin" + "miljoonansiin " + "viidensiinsadansiinkuudensiinkymmenensiinseitsemänsiin" + "tuhannensiin " + "kahdeksansiinsadansiinyhdeksänsiinkymmenensiin", + "miljardinsilla " + "kahdensillasadansillakolmansillakymmenensilläneljänsillä" + "miljoonansilla " + "viidensilläsadansillakuudensillakymmenensilläseitsemänsillä" + "tuhannensilla " + "kahdeksansillasadansillayhdeksänsilläkymmenensillä", + "miljardinsilta " + "kahdensiltasadansiltakolmansiltakymmenensiltäneljänsiltä" + "miljoonansilta " + "viidensiltäsadansiltakuudensiltakymmenensiltäseitsemänsiltä" + "tuhannensilta " + "kahdeksansiltasadansiltayhdeksänsiltäkymmenensiltä", + "miljardinsille " + "kahdensillesadansillekolmansillekymmenensilleneljänsille" + "miljoonansille " + "viidensillesadansillekuudensillekymmenensilleseitsemänsille" + "tuhannensille " + "kahdeksansillesadansilleyhdeksänsillekymmenensille", + "miljardinsina " + "kahdensinasadansinakolmansinakymmenensinäneljänsinä" + "miljoonansina " + "viidensinäsadansinakuudensinakymmenensinäseitsemänsinä" + "tuhannensina " + "kahdeksansinasadansinayhdeksänsinäkymmenensinä", + "miljardinsiksi " + "kahdensiksisadansiksikolmansiksikymmenensiksineljänsiksi" + "miljoonansiksi " + "viidensiksisadansiksikuudensiksikymmenensiksiseitsemänsiksi" + "tuhannensiksi " + "kahdeksansiksisadansiksiyhdeksänsiksikymmenensiksi", + "miljardinsin " + "kahdensinsadansinkolmansinkymmenensinneljänsin" + "miljoonansin " + "viidensinsadansinkuudensinkymmenensinseitsemänsin" + "tuhannensin " + "kahdeksansinsadansinyhdeksänsinkymmenensin", + "miljardinsitta " + "kahdensittasadansittakolmansittakymmenensittäneljänsittä" + "miljoonansitta " + "viidensittäsadansittakuudensittakymmenensittäseitsemänsittä" + "tuhannensitta " + "kahdeksansittasadansittayhdeksänsittäkymmenensittä", + "miljardinsine " + "kahdensinesadansinekolmansinekymmenensineneljänsine" + "miljoonansine " + "viidensinesadansinekuudensinekymmenensineseitsemänsine" + "tuhannensine " + "kahdeksansinesadansineyhdeksänsinekymmenensine" + ) + ) + + # one trillion (short scale) + self.assertEqual( + tuple(n2f((10**6)**2, to="ordinal", case=c) for c in CASES), + ("biljoonas", "biljoonannen", "biljoonatta", + "biljoonannessa", "biljoonannesta", "biljoonanteen", + "biljoonannella", "biljoonannelta", "biljoonannelle", + "biljoonantena", "biljoonanneksi", + "biljoonansin", "biljoonannetta", "biljoonansine") + ) + self.assertEqual( + tuple(n2f((10**6)**2, to="ordinal", case=c, plural=True) + for c in CASES), + ("biljoonannet", "biljoonansien", "biljoonansia", + "biljoonansissa", "biljoonansista", "biljoonansiin", + "biljoonansilla", "biljoonansilta", "biljoonansille", + "biljoonansina", "biljoonansiksi", + "biljoonansin", "biljoonansitta", "biljoonansine") + ) + + # one quintillion (short scale) + self.assertEqual( + tuple(n2f((10**6)**3, to="ordinal", case=c) for c in CASES), + ("triljoonas", "triljoonannen", "triljoonatta", + "triljoonannessa", "triljoonannesta", "triljoonanteen", + "triljoonannella", "triljoonannelta", "triljoonannelle", + "triljoonantena", "triljoonanneksi", + "triljoonansin", "triljoonannetta", "triljoonansine") + ) + self.assertEqual( + tuple(n2f((10**6)**3, to="ordinal", case=c, plural=True) + for c in CASES), + ("triljoonannet", "triljoonansien", "triljoonansia", + "triljoonansissa", "triljoonansista", "triljoonansiin", + "triljoonansilla", "triljoonansilta", "triljoonansille", + "triljoonansina", "triljoonansiksi", + "triljoonansin", "triljoonansitta", "triljoonansine") + ) + + def test_negative(self): + self.assertEqual(n2f(-1, to="cardinal"), "miinus yksi") + with self.assertRaises(TypeError): + n2f(-1, to="ordinal") + + def test_cardinal_float(self): + self.assertEqual(n2f(1.5, to="cardinal"), "yksi pilkku viisi") + with self.assertRaises(NotImplementedError): + n2f(1.5, to="cardinal", case="inessive") + + def test_ordinal_num(self): + with self.assertRaises(NotImplementedError): + n2f(1, to="ordinal_num") + + def test_year(self): + self.assertEqual(n2f(2018, to="year"), "kaksituhattakahdeksantoista") + self.assertEqual( + n2f(-99, to="year"), + "yhdeksänkymmentäyhdeksän ennen ajanlaskun alkua") + + def test_currency(self): + self.assertEqual( + n2f(150, to="currency"), "yksi euro ja viisikymmentä senttiä") + self.assertEqual( + n2f(150, to="currency", currency="FIM", adjective=True), + "yksi Suomen markka ja viisikymmentä penniä") diff -Nru python-num2words-0.5.6/tests/test_fr_be.py python-num2words-0.5.9/tests/test_fr_be.py --- python-num2words-0.5.6/tests/test_fr_be.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_fr_be.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA +from __future__ import unicode_literals + +from unittest import TestCase + +from num2words import num2words + +TEST_CASES_CARDINAL = ( + (70, 'septante'), + (79, 'septante-neuf'), + (89, 'quatre-vingt-neuf'), + (95, 'nonante-cinq'), + (729, 'sept cents vingt-neuf'), + (894, 'huit cents nonante-quatre'), + (999, 'neuf cents nonante-neuf'), + (7232, 'sept mille deux cents trente-deux'), + (8569, 'huit mille cinq cents soixante-neuf'), + (9539, 'neuf mille cinq cents trente-neuf'), + (1000000, 'un millions'), + (1000001, 'un millions un'), + (4000000, 'quatre millions'), + (10000000000000, 'dix billions'), + (100000000000000, 'cent billions'), + (1000000000000000000, 'un trillions'), + (1000000000000000000000, 'un trilliards'), + (10000000000000000000000000, 'dix quadrillions') +) + +TEST_CASES_ORDINAL = ( + (1, 'premier'), + (8, 'huitième'), + (12, 'douzième'), + (14, 'quatorzième'), + (28, 'vingt-huitième'), + (100, 'centième'), + (1000, 'millième'), + (1000000, 'un millionsième'), + (1000000000000000, 'un billiardsième'), + (1000000000000000000, 'un trillionsième') # over 1e18 is not supported +) + +TEST_CASES_TO_CURRENCY = ( + (1, 'un euro'), + (2, 'deux euros'), + (8, 'huit euros'), + (12, 'douze euros'), + (21, 'vingt et un euros'), + (81.25, 'quatre-vingt et un euros et vingt-cinq centimes'), + (100, 'cent euros'), +) + +TEST_CASES_TO_CURRENCY_OLD = ( + (1, 'un franc'), + (2, 'deux francs'), + (8, 'huit francs'), + (12, 'douze francs'), + (21, 'vingt et un francs'), + (81.25, 'quatre-vingt et un francs et vingt-cinq centimes'), + (100, 'cent francs'), +) + +# Lang to execute current test +LANG = 'fr_BE' + + +class Num2WordsENTest(TestCase): + def test_ordinal_special_joins(self): + self.assertEqual( + num2words(5, ordinal=True, lang=LANG), "cinquième" + ) + self.assertEqual( + num2words(6, ordinal=True, lang=LANG), "sixième" + ) + self.assertEqual( + num2words(35, ordinal=True, lang=LANG), "trente-cinquième" + ) + self.assertEqual(num2words(9, ordinal=True, lang=LANG), "neuvième") + self.assertEqual( + num2words(49, ordinal=True, lang=LANG), "quarante-neuvième" + ) + self.assertEqual(num2words(71, lang=LANG), "septante et un") + self.assertEqual(num2words(81, lang=LANG), "quatre-vingt et un") + self.assertEqual(num2words(80, lang=LANG), "quatre-vingt") + self.assertEqual( + num2words(880, lang=LANG), "huit cents quatre-vingt") + self.assertEqual( + num2words(91, ordinal=True, lang=LANG), "nonante et unième" + ) + self.assertEqual(num2words(53, lang=LANG), "cinquante-trois") + + def test_number(self): + for test in TEST_CASES_CARDINAL: + self.assertEqual(num2words(test[0], lang=LANG), test[1]) + + def test_ordinal(self): + for test in TEST_CASES_ORDINAL: + self.assertEqual( + num2words(test[0], lang=LANG, ordinal=True), + test[1] + ) + + def test_currency(self): + for test in TEST_CASES_TO_CURRENCY: + self.assertEqual( + num2words(test[0], lang=LANG, to='currency'), + test[1] + ) + + def test_currency_old(self): + for test in TEST_CASES_TO_CURRENCY_OLD: + self.assertEqual( + num2words(test[0], lang=LANG, to='currency', old=True), + test[1] + ) diff -Nru python-num2words-0.5.6/tests/test_fr_ch.py python-num2words-0.5.9/tests/test_fr_ch.py --- python-num2words-0.5.6/tests/test_fr_ch.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_fr_ch.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,6 @@ -# -*- encoding: utf-8 -*- -# Copyright (c) 2015, Savoir-faire Linux inc. All Rights Reserved. +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public diff -Nru python-num2words-0.5.6/tests/test_fr_dz.py python-num2words-0.5.9/tests/test_fr_dz.py --- python-num2words-0.5.6/tests/test_fr_dz.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_fr_dz.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,6 @@ -# -*- encoding: utf-8 -*- -# Copyright (c) 2015, Savoir-faire Linux inc. All Rights Reserved. +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public diff -Nru python-num2words-0.5.6/tests/test_fr.py python-num2words-0.5.9/tests/test_fr.py --- python-num2words-0.5.6/tests/test_fr.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_fr.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,19 +1,19 @@ -# -*- encoding: utf-8 -*- -# Copetright (c) 2015, Savoir-faire Linux inc. All Rights Reserved. - -# This libraret is free software; etou can redistribute it and/or -# modifet it under the terms of the GNU Lesser General Public -# License as published bet the Free Software Foundation; either -# version 2.1 of the License, or (at etour option) anet later version. -# This libraret is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warrantet of +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 # Lesser General Public License for more details. -# You should have received a copet of the GNU Lesser General Public -# License along with this libraret; if not, write to the Free Software +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA - from __future__ import unicode_literals from unittest import TestCase @@ -79,7 +79,12 @@ (1000000, 'un million'), (1000001, 'un million un'), (4000000, 'quatre millions'), + (4000004, 'quatre millions quatre'), + (4300000, 'quatre millions trois cent mille'), + (80000000, 'quatre-vingts millions'), + (300000000, 'trois cents millions'), (10000000000000, 'dix billions'), + (10000000000010, 'dix billions dix'), (100000000000000, 'cent billions'), (1000000000000000000, 'un trillion'), (1000000000000000000000, 'un trilliard'), @@ -117,6 +122,7 @@ (12, 'douze euros'), (21, 'vingt et un euros'), (81.25, 'quatre-vingt-un euros et vingt-cinq centimes'), + (81.2, 'quatre-vingt-un euros et vingt centimes'), (100, 'cent euros'), ) @@ -127,6 +133,7 @@ (12, 'douze francs'), (21, 'vingt et un francs'), (81.25, 'quatre-vingt-un francs et vingt-cinq centimes'), + (81.2, 'quatre-vingt-un francs et vingt centimes'), (100, 'cent francs'), ) diff -Nru python-num2words-0.5.6/tests/test_id.py python-num2words-0.5.9/tests/test_id.py --- python-num2words-0.5.6/tests/test_id.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_id.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or diff -Nru python-num2words-0.5.6/tests/test_it.py python-num2words-0.5.9/tests/test_it.py --- python-num2words-0.5.6/tests/test_it.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_it.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,6 @@ -# -*- encoding: utf-8 -*- -# Copyright (c) 2015, Savoir-faire Linux inc. All Rights Reserved. +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -22,7 +23,6 @@ class Num2WordsITTest(TestCase): - maxDiff = None def test_negative(self): @@ -225,3 +225,11 @@ "novecentouno miliardi, duecentotrentaquattro milioni e " "cinquecentosessantasettemilaottocentonovantesimo" ) + + def test_with_decimals(self): + self.assertAlmostEqual( + num2words(1.0, lang="it"), "uno virgola zero" + ) + self.assertAlmostEqual( + num2words(1.1, lang="it"), "uno virgola uno" + ) diff -Nru python-num2words-0.5.6/tests/test_ja.py python-num2words-0.5.9/tests/test_ja.py --- python-num2words-0.5.6/tests/test_ja.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_ja.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import division, print_function, unicode_literals + +from unittest import TestCase + +from num2words import num2words + + +def n2j(*args, **kwargs): + return num2words(*args, lang='ja', **kwargs) + + +class Num2WordsJATest(TestCase): + def test_low(self): + self.assertEqual(n2j(0), "零") + self.assertEqual(n2j(0, prefer=["〇"]), "〇") + self.assertEqual(n2j(0, reading=True), "ゼロ") + self.assertEqual(n2j(0, reading=True, prefer=["れい"]), "れい") + self.assertEqual(n2j(1), "一") + self.assertEqual(n2j(1, reading=True), "いち") + self.assertEqual(n2j(2), "二") + self.assertEqual(n2j(2, reading=True), "に") + self.assertEqual(n2j(3), "三") + self.assertEqual(n2j(3, reading=True), "さん") + self.assertEqual(n2j(4), "四") + self.assertEqual(n2j(4, reading=True), "よん") + self.assertEqual(n2j(4, reading=True, prefer=["し"]), "し") + self.assertEqual(n2j(5), "五") + self.assertEqual(n2j(5, reading=True), "ご") + self.assertEqual(n2j(6), "六") + self.assertEqual(n2j(6, reading=True), "ろく") + self.assertEqual(n2j(7), "七") + self.assertEqual(n2j(7, reading=True), "なな") + self.assertEqual(n2j(7, reading=True, prefer=["しち"]), "しち") + self.assertEqual(n2j(8), "八") + self.assertEqual(n2j(8, reading=True), "はち") + self.assertEqual(n2j(9), "九") + self.assertEqual(n2j(9, reading=True), "きゅう") + self.assertEqual(n2j(10), "十") + self.assertEqual(n2j(10, reading=True), "じゅう") + self.assertEqual(n2j(11), "十一") + self.assertEqual(n2j(11, reading=True), "じゅういち") + self.assertEqual(n2j(12), "十二") + self.assertEqual(n2j(12, reading=True), "じゅうに") + self.assertEqual(n2j(13), "十三") + self.assertEqual(n2j(13, reading=True), "じゅうさん") + self.assertEqual(n2j(14), "十四") + self.assertEqual(n2j(14, reading=True), "じゅうよん") + self.assertEqual(n2j(14, reading=True, prefer=["し"]), "じゅうし") + self.assertEqual(n2j(15), "十五") + self.assertEqual(n2j(15, reading=True), "じゅうご") + self.assertEqual(n2j(16), "十六") + self.assertEqual(n2j(16, reading=True), "じゅうろく") + self.assertEqual(n2j(17), "十七") + self.assertEqual(n2j(17, reading=True), "じゅうなな") + self.assertEqual(n2j(17, reading=True, prefer=["しち"]), "じゅうしち") + self.assertEqual(n2j(18), "十八") + self.assertEqual(n2j(18, reading=True), "じゅうはち") + self.assertEqual(n2j(19), "十九") + self.assertEqual(n2j(19, reading=True), "じゅうきゅう") + self.assertEqual(n2j(20), "二十") + self.assertEqual(n2j(20, reading=True), "にじゅう") + + def test_mid(self): + self.assertEqual(n2j(100), "百") + self.assertEqual(n2j(100, reading=True), "ひゃく") + self.assertEqual(n2j(123), "百二十三") + self.assertEqual(n2j(123, reading=True), "ひゃくにじゅうさん") + self.assertEqual(n2j(300), "三百") + self.assertEqual(n2j(300, reading=True), "さんびゃく") + self.assertEqual(n2j(400), "四百") + self.assertEqual(n2j(400, reading=True), "よんひゃく") + # 400 --> しひゃく sounds weird, but can be generated with prefer + self.assertEqual(n2j(600), "六百") + self.assertEqual(n2j(600, reading=True), "ろっぴゃく") + self.assertEqual(n2j(700, reading=True, prefer=["しち"]), "しちひゃく") + self.assertEqual(n2j(800, reading=True), "はっぴゃく") + self.assertEqual(n2j(1000), "千") + self.assertEqual(n2j(1000, reading=True), "せん") + self.assertEqual(n2j(3000, reading=True), "さんぜん") + self.assertEqual(n2j(8000, reading=True), "はっせん") + + def test_high(self): + self.assertEqual(n2j(10000), "一万") + self.assertEqual(n2j(10000, reading=True), "いちまん") + self.assertEqual(n2j(12345), "一万二千三百四十五") + self.assertEqual(n2j(12345, reading=True), + "いちまん" + "にせん" + "さんびゃく" + "よんじゅうご") + self.assertEqual(n2j(10**8), "一億") + self.assertEqual(n2j(10**8, reading=True), "いちおく") + self.assertEqual(n2j(123456789), "一億二千三百四十五万六千七百八十九") + self.assertEqual(n2j(123456789, reading=True), + "いちおく" + "にせんさんびゃくよんじゅうごまん" + "ろくせんななひゃく" + "はちじゅうきゅう") + self.assertEqual(n2j(10**12), "一兆") + self.assertEqual(n2j(10**12, reading=True), "いっちょう") + self.assertEqual(n2j(1234567890123), + "一兆二千三百四十五億六千七百八十九万百二十三") + self.assertEqual(n2j(1234567890123, reading=True), + "いっちょう" + "にせんさんびゃくよんじゅうごおく" + "ろくせんななひゃくはちじゅうきゅうまん" + "ひゃくにじゅうさん") + # TODO: tests for 10**16 and above + + def test_cardinal_float(self): + self.assertEqual(n2j(0.0123456789, prefer=["〇"]), + "〇点〇一二三四五六七八九") + self.assertEqual(n2j(0.0123456789, reading=True), + "れいてん" + "れいいち" + "にさん" + "よんご" + "ろくなな" + "はちきゅう") + self.assertEqual(n2j(10**8 + 0.01), "一億点零一") + self.assertEqual(n2j(10**8 + 0.01, reading=True), + "いちおくてんれいいち") + + def test_ordinal(self): + self.assertEqual(n2j(0, to="ordinal"), "零番目") + self.assertEqual(n2j(0, to="ordinal", reading=True, prefer=["れい"]), + "れいばんめ") + self.assertEqual(n2j(2, to="ordinal", counter="人"), "二人目") + self.assertEqual(n2j(3, to="ordinal", counter="つ"), "三つ目") + with self.assertRaises(NotImplementedError): + n2j(4, to="ordinal", reading=True, counter="人") + + def test_ordinal_num(self): + self.assertEqual(n2j(0, to="ordinal_num"), "0番目") + self.assertEqual(n2j(0, to="ordinal_num", reading=True), "0ばんめ") + self.assertEqual(n2j(2, to="ordinal_num", counter="人"), "2人目") + self.assertEqual(n2j(3, to="ordinal_num", counter="つ"), "3つ目") + + def test_currency(self): + self.assertEqual(n2j(123456789, to="currency"), + "一億二千三百四十五万六千七百八十九円") + self.assertEqual(n2j(123456789, to="currency", reading=True), + "いちおく" + "にせんさんびゃくよんじゅうごまん" + "ろくせんななひゃく" + "はちじゅうきゅうえん") + + def test_year(self): + self.assertEqual(n2j(2017, to="year"), "平成二十九年") + self.assertEqual(n2j(2017, to="year", reading=True), + "へいせいにじゅうくねん") + self.assertEqual(n2j(2017, to="year", reading="arabic"), + "平成29年") + self.assertEqual(n2j(2009, to="year", era=False), "二千九年") + self.assertEqual(n2j(2009, to="year", reading=True, era=False), + "にせんくねん") + self.assertEqual(n2j(2000, to="year", era=False), "二千年") + self.assertEqual(n2j(2000, to="year", era=False, reading=True), + "にせんねん") + self.assertEqual(n2j(645, to="year"), "大化元年") + self.assertEqual(n2j(645, to="year", reading=True), "たいかがんねん") + self.assertEqual(n2j(645, to="year"), "大化元年") + self.assertEqual(n2j(645, to="year", reading=True), "たいかがんねん") + self.assertEqual(n2j(-99, to="year", era=False), "紀元前九十九年") + self.assertEqual(n2j(-99, to="year", era=False, reading=True), + "きげんぜんきゅうじゅうくねん") + self.assertEqual(n2j(1375, to="year"), "天授元年") + self.assertEqual(n2j(1375, to="year", prefer=["えいわ"]), "永和元年") diff -Nru python-num2words-0.5.6/tests/test_ko.py python-num2words-0.5.9/tests/test_ko.py --- python-num2words-0.5.6/tests/test_ko.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_ko.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import division, print_function, unicode_literals + +from unittest import TestCase + +from num2words import num2words + + +def n2k(*args, **kwargs): + return num2words(*args, lang='ko', **kwargs) + + +class Num2WordsKOTest(TestCase): + def test_low(self): + cases = [(0, "영"), (1, "일"), (2, "이"), (3, "삼"), (4, "사"), (5, "오"), + (6, "육"), (7, "칠"), (8, "팔"), (9, "구"), (10, "십"), + (11, "십일"), (12, "십이"), (13, "십삼"), (14, "십사"), + (15, "십오"), (16, "십육"), (17, "십칠"), + (18, "십팔"), (19, "십구"), (20, "이십"), (25, "이십오"), + (31, "삼십일"), (42, "사십이"), (54, "오십사"), (63, "육십삼"), + (76, "칠십육"), (89, "팔십구"), (98, "구십팔")] + for num, out in cases: + self.assertEqual(n2k(num), out) + + def test_mid(self): + cases = [(100, "백"), (121, "백이십일"), (160, "백육십"), (256, "이백오십육"), + (285, "이백팔십오"), (486, "사백팔십육"), (627, "육백이십칠"), + (808, "팔백팔"), (999, "구백구십구"), (1004, "천사"), + (2018, "이천십팔"), (7063, "칠천육십삼")] + for num, out in cases: + self.assertEqual(n2k(num), out) + + def test_high(self): + cases = [(10000, "만"), (11020, "만 천이십"), (25891, "이만 오천팔백구십일"), + (64237, "육만 사천이백삼십칠"), (241572, "이십사만 천오백칠십이"), + (100000000, "일억"), (5000500000000, "오조 오억")] + for num, out in cases: + self.assertEqual(n2k(num), out) + + def test_negative(self): + cases = [(-11, "마이너스 십일"), (-15, "마이너스 십오"), + (-18, "마이너스 십팔"), (-241572, "마이너스 이십사만 천오백칠십이")] + for num, out in cases: + self.assertEqual(n2k(num), out) + + def test_year(self): + cases = [(2000, "이천년"), (2002, "이천이년"), (2018, "이천십팔년"), + (1954, "천구백오십사년"), (1910, "천구백십년"), (-1000, "기원전 천년")] + for num, out in cases: + self.assertEqual(n2k(num, to="year"), out) + + def test_currency(self): + cases_krw = [(8350, "팔천삼백오십원"), (14980, "만사천구백팔십원"), + (250004000, "이억오천만사천원")] + cases_usd = [(4, "사달러 영센트"), (19.55, "십구달러 오십오센트")] + cases_jpy = [(15, "십오엔"), (50, "오십엔")] + for num, out in cases_krw: + self.assertEqual(n2k(num, to="currency"), out) + for num, out in cases_usd: + self.assertEqual(n2k(num, to="currency", currency="USD"), out) + for num, out in cases_jpy: + self.assertEqual(n2k(num, to="currency", currency="JPY"), out) + with self.assertRaises(ValueError): + n2k(190.55, to="currency") + with self.assertRaises(NotImplementedError): + n2k(4, to="currency", currency="EUR") + + def test_ordinal(self): + cases = [(1, "첫 번째"), (101, "백 한 번째"), (2, "두 번째"), (5, "다섯 번째"), + (10, "열 번째"), (25, "스물다섯 번째"), (137, "백 서른일곱 번째")] + for num, out in cases: + self.assertEqual(n2k(num, to="ordinal"), out) + + def test_ordinal_num(self): + cases = [(1, "1 번째"), (101, "101 번째"), (25, "25 번째")] + for num, out in cases: + self.assertEqual(n2k(num, to="ordinal_num"), out) diff -Nru python-num2words-0.5.6/tests/test_lt.py python-num2words-0.5.9/tests/test_lt.py --- python-num2words-0.5.6/tests/test_lt.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_lt.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,20 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + from __future__ import unicode_literals from unittest import TestCase @@ -44,9 +60,14 @@ "aštuoni šimtai dvidešimt du trilijonai aštuoni šimtai dvidešimt " "keturi milijardai trys šimtai aštuoniasdešimt keturi milijonai " "du šimtai dvidešimt tūkstančių du šimtai devyniasdešimt vienas") - - # print(fill(n2w(1000000000000000000000000000000))) - # naintilijonas + self.assertEqual( + num2words(-5000, lang='lt'), + 'minus penki tūkstančiai', + ) + self.assertEqual( + num2words(-5000.22, lang='lt'), + 'minus penki tūkstančiai kablelis dvidešimt du', + ) def test_to_ordinal(self): # @TODO: implement to_ordinal @@ -54,20 +75,27 @@ num2words(1, lang='lt', to='ordinal') def test_to_currency(self): + # Test all available currency forms. + # LTL self.assertEqual( num2words(1.0, lang='lt', to='currency', currency='LTL'), 'vienas litas, nulis centų' ) self.assertEqual( + num2words(10.01, lang='lt', to='currency', currency='LTL'), + 'dešimt litų, vienas centas' + ) + self.assertEqual( num2words(1234.56, lang='lt', to='currency', currency='LTL'), 'vienas tūkstantis du šimtai trisdešimt keturi litai, ' 'penkiasdešimt šeši centai' ) + # EUR self.assertEqual( - num2words(-1251985, lang='lt', to='currency', currency='EUR', + num2words(-1251981, lang='lt', to='currency', currency='EUR', cents=False), 'minus dvylika tūkstančių penki šimtai devyniolika eurų, ' - '85 centai' + '81 centas' ) self.assertEqual( num2words(1.0, lang='lt', to='currency', currency='EUR'), @@ -78,3 +106,73 @@ 'vienas tūkstantis du šimtai trisdešimt keturi eurai, ' 'penkiasdešimt šeši centai' ) + self.assertEqual( + num2words(1122.22, lang='lt', to='currency', currency='EUR'), + 'vienas tūkstantis vienas šimtas dvidešimt du eurai, ' + 'dvidešimt du centai' + ) + # USD + self.assertEqual( + num2words(-1281, lang='lt', to='currency', currency='USD', + cents=False), + 'minus dvylika dolerių, 81 centas' + ) + self.assertEqual( + num2words(1.0, lang='lt', to='currency', currency='USD'), + 'vienas doleris, nulis centų' + ) + self.assertEqual( + num2words(5.06, lang='lt', to='currency', currency='USD'), + 'penki doleriai, šeši centai' + ) + # GBP + self.assertEqual( + num2words(-1281, lang='lt', to='currency', currency='GBP', + cents=False), + 'minus dvylika svarų sterlingų, 81 pensas' + ) + self.assertEqual( + num2words(1.0, lang='lt', to='currency', currency='GBP'), + 'vienas svaras sterlingų, nulis pensų' + ) + self.assertEqual( + num2words(5.06, lang='lt', to='currency', currency='GBP'), + 'penki svarai sterlingų, šeši pensai' + ) + # PLN + self.assertEqual( + num2words(-1281, lang='lt', to='currency', currency='PLN', + cents=False), + 'minus dvylika zlotų, 81 grašis' + ) + self.assertEqual( + num2words(1.0, lang='lt', to='currency', currency='PLN'), + 'vienas zlotas, nulis grašių' + ) + self.assertEqual( + num2words(5.06, lang='lt', to='currency', currency='PLN'), + 'penki zlotai, šeši grašiai' + ) + # RUB + self.assertEqual( + num2words(-1281, lang='lt', to='currency', currency='RUB', + cents=False), + 'minus dvylika rublių, 81 kapeika' + ) + self.assertEqual( + num2words(1.0, lang='lt', to='currency', currency='RUB'), + 'vienas rublis, nulis kapeikų' + ) + self.assertEqual( + num2words(5.06, lang='lt', to='currency', currency='RUB'), + 'penki rubliai, šešios kapeikos' + ) + self.assertEqual( + num2words(-12.01, lang='lt', to='currency', currency='RUB'), + 'minus dvylika rublių, viena kapeika' + ) + self.assertEqual( + num2words(1122.22, lang='lt', to='currency', currency='RUB'), + 'vienas tūkstantis vienas šimtas dvidešimt du rubliai, ' + 'dvidešimt dvi kapeikos' + ) diff -Nru python-num2words-0.5.6/tests/test_lv.py python-num2words-0.5.9/tests/test_lv.py --- python-num2words-0.5.6/tests/test_lv.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_lv.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,20 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + from __future__ import unicode_literals from unittest import TestCase @@ -39,9 +55,14 @@ 'divdesmit divi triljoni astoņi simti divdesmit četri ' 'miljardi trīs simti astoņdesmit četri miljoni divi simti ' 'divdesmit tūkstoši divi simti deviņdesmit viens') - - # >>> print(fill(n2w(1000000000000000000000000000000))) - # nontiljons + self.assertEqual( + num2words(-5000, lang='lv'), + 'mīnus pieci tūkstoši', + ) + self.assertEqual( + num2words(-5000.22, lang='lv'), + 'mīnus pieci tūkstoši komats divdesmit divi', + ) self.assertEqual(num2words(0, lang='lv'), 'nulle') self.assertEqual(num2words(5, lang='lv'), "pieci") diff -Nru python-num2words-0.5.6/tests/test_nl.py python-num2words-0.5.9/tests/test_nl.py --- python-num2words-0.5.6/tests/test_nl.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_nl.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,6 @@ -# -*- encoding: utf-8 -*- -# Copyright (c) 2015, Savoir-faire Linux inc. All Rights Reserved. +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -19,6 +20,7 @@ from unittest import TestCase from num2words import num2words +from num2words.lang_NL import Num2Word_NL class Num2WordsNLTest(TestCase): @@ -64,3 +66,43 @@ def test_ordinal_for_floating_numbers(self): self.assertRaises(TypeError, num2words, 2.453, ordinal=True, lang='nl') + + def test_to_currency(self): + self.assertEqual( + num2words('38.4', lang='nl', to='currency', seperator=' en', + cents=False, currency='EUR'), + "achtendertig euro en 40 cent" + ) + self.assertEqual( + num2words('0', lang='nl', to='currency', seperator=' en', + cents=False, currency='EUR'), + "nul euro en 00 cent" + ) + + self.assertEqual( + num2words('1.01', lang='nl', to='currency', seperator=' en', + cents=True, currency='EUR'), + "één euro en één cent" + ) + + self.assertEqual( + num2words('4778.00', lang='nl', to='currency', seperator=' en', + cents=True, currency='EUR'), + 'vierduizendzevenhonderdachtenzeventig euro en nul cent') + + def test_pluralize(self): + n = Num2Word_NL() + # euros always singular + cr1, cr2 = n.CURRENCY_FORMS['EUR'] + self.assertEqual(n.pluralize(1, cr1), 'euro') + self.assertEqual(n.pluralize(2, cr1), 'euro') + self.assertEqual(n.pluralize(1, cr2), 'cent') + self.assertEqual(n.pluralize(2, cr2), 'cent') + + # @TODO other currency + + def test_to_year(self): + self.assertEqual(num2words(2018, lang='nl', to='year'), + 'tweeduizendachttien') + self.assertEqual(num2words(2100, lang='nl', to='year'), + 'eenentwintig honderd') diff -Nru python-num2words-0.5.6/tests/test_pl.py python-num2words-0.5.9/tests/test_pl.py --- python-num2words-0.5.6/tests/test_pl.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_pl.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,6 @@ -# -*- encoding: utf-8 -*- -# Copyright (c) 2015, Savoir-faire Linux inc. All Rights Reserved. +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -46,13 +47,17 @@ "sześćdziesiąt siedem tysięcy osiemset dziewięćdzisiąt" ) self.assertEqual( + num2words(10000000001000000100000, lang='pl'), + "dziesięć tryliardów bilion sto tysięcy" + ) + self.assertEqual( num2words(215461407892039002157189883901676, lang='pl'), "dwieście piętnaście kwintylionów czterysta sześćdziesiąt jeden " "kwadryliardów czterysta siedem kwadrylionów osiemset " "dziewięćdzisiąt dwa tryliardy trzydzieści dziewięć trylionów " "dwa biliardy sto pięćdziesiąt siedem bilionów sto osiemdziesiąt " "dziewięć miliardów osiemset osiemdziesiąt trzy miliony " - "dziewęćset jeden tysięcy sześćset siedemdziesiąt sześć" + "dziewięćset jeden tysięcy sześćset siedemdziesiąt sześć" ) self.assertEqual( num2words(719094234693663034822824384220291, lang='pl'), @@ -64,6 +69,18 @@ "osiemdziesiąt cztery miliony dwieście dwadzieścia " "tysięcy dwieście dziewięćdzisiąt jeden" ) + self.assertEqual( + num2words( + 963301000001918264129471001047146102 * 10**30 + 1007, + lang='pl' + ), + "dziewięćset sześćdziesiąt trzy decyliardy trzysta jeden " + "decylionów nonylion dziewięćset osiemnaście oktyliardów dwieście " + "sześćdziesiąt cztery oktyliony sto dwadzieścia dziewięć " + "septyliardów czterysta siedemdziesiąt jeden septylionów " + "sekstyliard czterdzieści siedem sekstylionów sto czterdzieści " + "sześć kwintyliardów sto dwa kwintyliony tysiąc siedem" + ) def test_to_ordinal(self): # @TODO: implement to_ordinal diff -Nru python-num2words-0.5.6/tests/test_pt_BR.py python-num2words-0.5.9/tests/test_pt_BR.py --- python-num2words-0.5.6/tests/test_pt_BR.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_pt_BR.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,6 @@ -# -*- encoding: utf-8 -*- -# Copyright (c) 2015, Savoir-faire Linux inc. All Rights Reserved. +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public diff -Nru python-num2words-0.5.6/tests/test_pt.py python-num2words-0.5.9/tests/test_pt.py --- python-num2words-0.5.6/tests/test_pt.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_pt.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,455 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +from decimal import Decimal +from unittest import TestCase + +from num2words import num2words +from num2words.lang_PT import Num2Word_PT + + +class Num2WordsPTTest(TestCase): + def setUp(self): + super(Num2WordsPTTest, self).setUp() + self.n2w = Num2Word_PT() + + def test_cardinal_integer(self): + self.assertEqual(num2words(1, lang='pt'), 'um') + self.assertEqual(num2words(2, lang='pt'), 'dois') + self.assertEqual(num2words(3, lang='pt'), 'três') + self.assertEqual(num2words(4, lang='pt'), 'quatro') + self.assertEqual(num2words(5, lang='pt'), 'cinco') + self.assertEqual(num2words(6, lang='pt'), 'seis') + self.assertEqual(num2words(7, lang='pt'), 'sete') + self.assertEqual(num2words(8, lang='pt'), 'oito') + self.assertEqual(num2words(9, lang='pt'), 'nove') + self.assertEqual(num2words(10, lang='pt'), 'dez') + self.assertEqual(num2words(11, lang='pt'), 'onze') + self.assertEqual(num2words(12, lang='pt'), 'doze') + self.assertEqual(num2words(13, lang='pt'), 'treze') + self.assertEqual(num2words(14, lang='pt'), 'catorze') + self.assertEqual(num2words(15, lang='pt'), 'quinze') + self.assertEqual(num2words(16, lang='pt'), 'dezasseis') + self.assertEqual(num2words(17, lang='pt'), 'dezassete') + self.assertEqual(num2words(18, lang='pt'), 'dezoito') + self.assertEqual(num2words(19, lang='pt'), 'dezanove') + self.assertEqual(num2words(20, lang='pt'), 'vinte') + + self.assertEqual(num2words(21, lang='pt'), 'vinte e um') + self.assertEqual(num2words(22, lang='pt'), 'vinte e dois') + self.assertEqual(num2words(35, lang='pt'), 'trinta e cinco') + self.assertEqual(num2words(99, lang='pt'), 'noventa e nove') + + self.assertEqual(num2words(100, lang='pt'), 'cem') + self.assertEqual(num2words(101, lang='pt'), 'cento e um') + self.assertEqual(num2words(128, lang='pt'), 'cento e vinte e oito') + self.assertEqual(num2words(713, lang='pt'), 'setecentos e treze') + + self.assertEqual(num2words(1000, lang='pt'), 'mil') + self.assertEqual(num2words(1001, lang='pt'), 'mil e um') + self.assertEqual(num2words(1111, lang='pt'), 'mil cento e onze') + self.assertEqual( + num2words(2114, lang='pt'), 'dois mil cento e catorze' + ) + self.assertEqual( + num2words(2200, lang='pt'), + 'dois mil e duzentos' + ) + self.assertEqual( + num2words(2230, lang='pt'), + 'dois mil duzentos e trinta' + ) + self.assertEqual( + num2words(73400, lang='pt'), + 'setenta e três mil e quatrocentos' + ) + self.assertEqual( + num2words(73421, lang='pt'), + 'setenta e três mil quatrocentos e vinte e um' + ) + self.assertEqual(num2words(100000, lang='pt'), 'cem mil') + self.assertEqual( + num2words(250050, lang='pt'), + 'duzentos e cinquenta mil e cinquenta' + ) + self.assertEqual( + num2words(6000000, lang='pt'), 'seis milhões' + ) + self.assertEqual( + num2words(100000000, lang='pt'), 'cem milhões' + ) + self.assertEqual( + num2words(19000000000, lang='pt'), 'dezanove mil milhões' + ) + self.assertEqual( + num2words(145000000002, lang='pt'), + 'cento e quarenta e cinco mil milhões e dois' + ) + self.assertEqual( + num2words(4635102, lang='pt'), + 'quatro milhões seiscentos e trinta e cinco mil cento e dois' + ) + self.assertEqual( + num2words(145254635102, lang='pt'), + 'cento e quarenta e cinco mil duzentos e cinquenta e quatro ' + 'milhões seiscentos e trinta e cinco mil cento e dois' + ) + self.assertEqual( + num2words(1000000000000, lang='pt'), + 'um bilião' + ) + self.assertEqual( + num2words(2000000000000, lang='pt'), + 'dois biliões' + ) + self.assertEqual( + num2words(1000000000000000, lang='pt'), + 'mil biliões' + ) + self.assertEqual( + num2words(2000000000000000, lang='pt'), + 'dois mil biliões' + ) + self.assertEqual( + num2words(1000000000000000000, lang='pt'), + 'um trilião' + ) + self.assertEqual( + num2words(2000000000000000000, lang='pt'), + 'dois triliões' + ) + + def test_cardinal_integer_negative(self): + self.assertEqual(num2words(-1, lang='pt'), 'menos um') + self.assertEqual( + num2words(-256, lang='pt'), 'menos duzentos e cinquenta e seis' + ) + self.assertEqual(num2words(-1000, lang='pt'), 'menos mil') + self.assertEqual(num2words(-1000000, lang='pt'), 'menos um milhão') + self.assertEqual( + num2words(-1234567, lang='pt'), + 'menos um milhão duzentos e trinta e quatro mil quinhentos e ' + 'sessenta e sete' + ) + + def test_cardinal_float(self): + self.assertEqual(num2words(Decimal('1.00'), lang='pt'), 'um') + self.assertEqual(num2words( + Decimal('1.01'), lang='pt'), 'um vírgula zero um') + self.assertEqual(num2words( + Decimal('1.035'), lang='pt'), 'um vírgula zero três cinco' + ) + self.assertEqual(num2words( + Decimal('1.35'), lang='pt'), 'um vírgula três cinco' + ) + self.assertEqual( + num2words(Decimal('3.14159'), lang='pt'), + 'três vírgula um quatro um cinco nove' + ) + self.assertEqual( + num2words(Decimal('101.22'), lang='pt'), + 'cento e um vírgula dois dois' + ) + self.assertEqual( + num2words(Decimal('2345.75'), lang='pt'), + 'dois mil trezentos e quarenta e cinco vírgula sete cinco') + + def test_cardinal_float_negative(self): + self.assertEqual( + num2words(Decimal('-2.34'), lang='pt'), + 'menos dois vírgula três quatro' + ) + self.assertEqual( + num2words(Decimal('-9.99'), lang='pt'), + 'menos nove vírgula nove nove' + ) + self.assertEqual( + num2words(Decimal('-7.01'), lang='pt'), + 'menos sete vírgula zero um' + ) + self.assertEqual( + num2words(Decimal('-222.22'), lang='pt'), + 'menos duzentos e vinte e dois vírgula dois dois' + ) + + def test_ordinal(self): + self.assertEqual(num2words(1, lang='pt', ordinal=True), 'primeiro') + self.assertEqual(num2words(2, lang='pt', ordinal=True), 'segundo') + self.assertEqual(num2words(3, lang='pt', ordinal=True), 'terceiro') + self.assertEqual(num2words(4, lang='pt', ordinal=True), 'quarto') + self.assertEqual(num2words(5, lang='pt', ordinal=True), 'quinto') + self.assertEqual(num2words(6, lang='pt', ordinal=True), 'sexto') + self.assertEqual(num2words(7, lang='pt', ordinal=True), 'sétimo') + self.assertEqual(num2words(8, lang='pt', ordinal=True), 'oitavo') + self.assertEqual(num2words(9, lang='pt', ordinal=True), 'nono') + self.assertEqual(num2words(10, lang='pt', ordinal=True), 'décimo') + self.assertEqual( + num2words(11, lang='pt', ordinal=True), 'décimo primeiro' + ) + self.assertEqual( + num2words(12, lang='pt', ordinal=True), 'décimo segundo' + ) + self.assertEqual( + num2words(13, lang='pt', ordinal=True), 'décimo terceiro' + ) + self.assertEqual( + num2words(14, lang='pt', ordinal=True), 'décimo quarto' + ) + self.assertEqual( + num2words(15, lang='pt', ordinal=True), 'décimo quinto' + ) + self.assertEqual( + num2words(16, lang='pt', ordinal=True), 'décimo sexto' + ) + self.assertEqual( + num2words(17, lang='pt', ordinal=True), 'décimo sétimo' + ) + self.assertEqual( + num2words(18, lang='pt', ordinal=True), 'décimo oitavo' + ) + self.assertEqual( + num2words(19, lang='pt', ordinal=True), 'décimo nono' + ) + self.assertEqual( + num2words(20, lang='pt', ordinal=True), 'vigésimo' + ) + + self.assertEqual( + num2words(21, lang='pt', ordinal=True), 'vigésimo primeiro' + ) + self.assertEqual( + num2words(22, lang='pt', ordinal=True), 'vigésimo segundo' + ) + self.assertEqual( + num2words(35, lang='pt', ordinal=True), 'trigésimo quinto' + ) + self.assertEqual( + num2words(99, lang='pt', ordinal=True), 'nonagésimo nono' + ) + + self.assertEqual( + num2words(100, lang='pt', ordinal=True), 'centésimo' + ) + self.assertEqual( + num2words(101, lang='pt', ordinal=True), 'centésimo primeiro' + ) + self.assertEqual( + num2words(128, lang='pt', ordinal=True), + 'centésimo vigésimo oitavo' + ) + self.assertEqual( + num2words(713, lang='pt', ordinal=True), + 'septigentésimo décimo terceiro' + ) + + self.assertEqual( + num2words(1000, lang='pt', ordinal=True), 'milésimo' + ) + self.assertEqual( + num2words(1001, lang='pt', ordinal=True), 'milésimo primeiro' + ) + self.assertEqual( + num2words(1111, lang='pt', ordinal=True), + 'milésimo centésimo décimo primeiro' + ) + self.assertEqual( + num2words(2114, lang='pt', ordinal=True), + 'segundo milésimo centésimo décimo quarto' + ) + self.assertEqual( + num2words(73421, lang='pt', ordinal=True), + 'septuagésimo terceiro milésimo quadrigentésimo vigésimo primeiro' + ) + + self.assertEqual( + num2words(100000, lang='pt', ordinal=True), + 'centésimo milésimo' + ) + self.assertEqual( + num2words(250050, lang='pt', ordinal=True), + 'ducentésimo quinquagésimo milésimo quinquagésimo' + ) + self.assertEqual( + num2words(6000000, lang='pt', ordinal=True), 'sexto milionésimo' + ) + self.assertEqual( + num2words(19000000000, lang='pt', ordinal=True), + 'décimo nono milésimo milionésimo' + ) + self.assertEqual( + num2words(145000000002, lang='pt', ordinal=True), + 'centésimo quadragésimo quinto milésimo milionésimo segundo' + ) + + def test_currency_integer(self): + self.assertEqual(self.n2w.to_currency(1.00), 'um euro') + self.assertEqual(self.n2w.to_currency(2.00), 'dois euros') + self.assertEqual(self.n2w.to_currency(3.00), 'três euros') + self.assertEqual(self.n2w.to_currency(4.00), 'quatro euros') + self.assertEqual(self.n2w.to_currency(5.00), 'cinco euros') + self.assertEqual(self.n2w.to_currency(6.00), 'seis euros') + self.assertEqual(self.n2w.to_currency(7.00), 'sete euros') + self.assertEqual(self.n2w.to_currency(8.00), 'oito euros') + self.assertEqual(self.n2w.to_currency(9.00), 'nove euros') + self.assertEqual(self.n2w.to_currency(10.00), 'dez euros') + self.assertEqual(self.n2w.to_currency(11.00), 'onze euros') + self.assertEqual(self.n2w.to_currency(12.00), 'doze euros') + self.assertEqual(self.n2w.to_currency(13.00), 'treze euros') + self.assertEqual(self.n2w.to_currency(14.00), 'catorze euros') + self.assertEqual(self.n2w.to_currency(15.00), 'quinze euros') + self.assertEqual(self.n2w.to_currency(16.00), 'dezasseis euros') + self.assertEqual(self.n2w.to_currency(17.00), 'dezassete euros') + self.assertEqual(self.n2w.to_currency(18.00), 'dezoito euros') + self.assertEqual(self.n2w.to_currency(19.00), 'dezanove euros') + self.assertEqual(self.n2w.to_currency(20.00), 'vinte euros') + + self.assertEqual(self.n2w.to_currency(21.00), 'vinte e um euros') + self.assertEqual(self.n2w.to_currency(22.00), 'vinte e dois euros') + self.assertEqual(self.n2w.to_currency(35.00), 'trinta e cinco euros') + self.assertEqual(self.n2w.to_currency(99.00), 'noventa e nove euros') + + self.assertEqual(self.n2w.to_currency(100.00), 'cem euros') + self.assertEqual(self.n2w.to_currency(101.00), 'cento e um euros') + self.assertEqual( + self.n2w.to_currency(128.00), 'cento e vinte e oito euros' + ) + self.assertEqual( + self.n2w.to_currency(713.00), 'setecentos e treze euros') + + self.assertEqual(self.n2w.to_currency(1000.00), 'mil euros') + self.assertEqual(self.n2w.to_currency(1001.00), 'mil e um euros') + self.assertEqual( + self.n2w.to_currency(1111.00), 'mil cento e onze euros') + self.assertEqual( + self.n2w.to_currency(2114.00), 'dois mil cento e catorze euros' + ) + self.assertEqual( + self.n2w.to_currency(73421.00), + 'setenta e três mil quatrocentos e vinte e um euros' + ) + + self.assertEqual(self.n2w.to_currency(100000.00), 'cem mil euros') + self.assertEqual( + self.n2w.to_currency(250050.00), + 'duzentos e cinquenta mil e cinquenta euros' + ) + self.assertEqual( + self.n2w.to_currency(6000000.00), 'seis milhões de euros' + ) + self.assertEqual( + self.n2w.to_currency(19000000000.00), + 'dezanove mil milhões de euros' + ) + self.assertEqual( + self.n2w.to_currency(145000000002.00), + 'cento e quarenta e cinco mil milhões e dois euros' + ) + self.assertEqual(self.n2w.to_currency(1.00, currency='USD'), + 'um dólar') + self.assertEqual(self.n2w.to_currency(1.50, currency='USD'), + 'um dólar e cinquenta cêntimos') + with self.assertRaises(NotImplementedError): + self.n2w.to_currency(1.00, currency='CHF') + + def test_currency_integer_negative(self): + self.assertEqual(self.n2w.to_currency(-1.00), 'menos um euro') + self.assertEqual( + self.n2w.to_currency(-256.00), + 'menos duzentos e cinquenta e seis euros' + ) + self.assertEqual(self.n2w.to_currency(-1000.00), 'menos mil euros') + self.assertEqual( + self.n2w.to_currency(-1000000.00), 'menos um milhão de euros' + ) + self.assertEqual( + self.n2w.to_currency(-1234567.00), + 'menos um milhão duzentos e trinta e quatro mil quinhentos e ' + 'sessenta e sete euros' + ) + + def test_currency_float(self): + self.assertEqual(self.n2w.to_currency(Decimal('1.00')), 'um euro') + self.assertEqual( + self.n2w.to_currency(Decimal('1.01')), 'um euro e um cêntimo' + ) + self.assertEqual( + self.n2w.to_currency(Decimal('1.03')), 'um euro e três cêntimos' + ) + self.assertEqual( + self.n2w.to_currency(Decimal('1.35')), + 'um euro e trinta e cinco cêntimos' + ) + self.assertEqual( + self.n2w.to_currency(Decimal('3.14')), + 'três euros e catorze cêntimos' + ) + self.assertEqual( + self.n2w.to_currency(Decimal('101.22')), + 'cento e um euros e vinte e dois cêntimos' + ) + self.assertEqual( + self.n2w.to_currency(Decimal('2345.75')), + 'dois mil trezentos e quarenta e cinco euros e setenta e cinco ' + 'cêntimos' + ) + + def test_currency_float_negative(self): + self.assertEqual( + self.n2w.to_currency(Decimal('-2.34')), + 'menos dois euros e trinta e quatro cêntimos' + ) + self.assertEqual( + self.n2w.to_currency(Decimal('-9.99')), + 'menos nove euros e noventa e nove cêntimos' + ) + self.assertEqual( + self.n2w.to_currency(Decimal('-7.01')), + 'menos sete euros e um cêntimo' + ) + self.assertEqual( + self.n2w.to_currency(Decimal('-222.22')), + 'menos duzentos e vinte e dois euros e vinte e dois cêntimos' + ) + + def test_year(self): + self.assertEqual(self.n2w.to_year(1001), 'mil e um') + self.assertEqual( + self.n2w.to_year(1789), 'mil setecentos e oitenta e nove' + ) + self.assertEqual( + self.n2w.to_year(1942), 'mil novecentos e quarenta e dois' + ) + self.assertEqual( + self.n2w.to_year(1984), 'mil novecentos e oitenta e quatro' + ) + self.assertEqual(self.n2w.to_year(2000), 'dois mil') + self.assertEqual(self.n2w.to_year(2001), 'dois mil e um') + self.assertEqual(self.n2w.to_year(2016), 'dois mil e dezasseis') + + def test_year_negative(self): + self.assertEqual(self.n2w.to_year(-30), 'trinta antes de Cristo') + self.assertEqual( + self.n2w.to_year(-744), + 'setecentos e quarenta e quatro antes de Cristo' + ) + self.assertEqual(self.n2w.to_year(-10000), 'dez mil antes de Cristo') + + def test_to_ordinal_num(self): + self.assertEqual(self.n2w.to_ordinal_num(1), '1º') + self.assertEqual(self.n2w.to_ordinal_num(100), '100º') diff -Nru python-num2words-0.5.6/tests/test_ro.py python-num2words-0.5.9/tests/test_ro.py --- python-num2words-0.5.6/tests/test_ro.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_ro.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from unittest import TestCase + +from num2words import num2words + + +class Num2WordsROTest(TestCase): + + def test_ordinal(self): + self.assertEqual( + num2words(1, lang='ro', to='ordinal'), + 'primul' + ) + self.assertEqual( + num2words(22, lang='ro', to='ordinal'), + u'al douăzeci și doilea' + ) + self.assertEqual( + num2words(21, lang='ro', to='ordinal'), + u'al douăzeci și unulea' + ) + self.assertEqual( + num2words(12, lang='ro', to='ordinal'), + u'al doisprezecelea' + ) + self.assertEqual( + num2words(130, lang='ro', to='ordinal'), + u'al o sută treizecilea' + ) + self.assertEqual( + num2words(1003, lang='ro', to='ordinal'), + u'al o mie treilea' + ) + + def test_ordinal_num(self): + self.assertEqual( + num2words(1, lang='ro', to='ordinal_num'), + '1-ul' + ) + self.assertEqual( + num2words(10, lang='ro', to='ordinal_num'), + 'al 10-lea' + ) + self.assertEqual(num2words( + 21, lang='ro', to='ordinal_num'), + 'al 21-lea' + ) + self.assertEqual( + num2words(102, lang='ro', to='ordinal_num'), + 'al 102-lea' + ) + self.assertEqual( + num2words(73, lang='ro', to='ordinal_num'), + 'al 73-lea' + ) + + def test_cardinal_for_float_number(self): + self.assertEqual( + num2words(12.5, lang='ro'), + u'doisprezece virgulă cinci' + ) + self.assertEqual( + num2words(12.51, lang='ro'), + u'doisprezece virgulă cinci unu' + ) + self.assertEqual( + num2words(12.53, lang='ro'), + u'doisprezece virgulă cinci trei' + ) + self.assertEqual( + num2words(12.59, lang='ro'), + u'doisprezece virgulă cinci nouă' + ) + + def test_big_numbers(self): + self.assertEqual( + num2words(1000000, lang="ro"), + u"un milion" + ) + self.assertEqual( + num2words(1000000000, lang="ro"), + u"un miliard" + ) + self.assertEqual( + num2words(33000000, lang="ro"), + u"treizeci și trei milioane" + ) + self.assertEqual( + num2words(247000000000, lang="ro"), + u"două sute patruzeci și șapte miliarde" + ) + + def test_overflow(self): + with self.assertRaises(OverflowError): + num2words("100000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000") + + def test_to_currency(self): + self.assertEqual( + num2words(38.4, lang='ro', to='currency'), + u'treizeci și opt lei și patruzeci bani' + ) + + self.assertEqual( + num2words(1.01, lang='ro', to='currency'), + u'un leu și un ban' + ) + + self.assertEqual( + num2words(4778.00, lang='ro', to='currency'), + u'patru mii șapte sute șaptezeci și opt lei') + + self.assertEqual( + num2words(4778.32, lang='ro', to='currency'), + u'patru mii șapte sute șaptezeci și opt lei' + u' și treizeci și doi bani') + + def test_to_year(self): + self.assertEqual(num2words(1989, lang='ro', to='year'), + u'o mie nouă sute optzeci și nouă') + self.assertEqual(num2words(1984, lang='ro', to='year'), + u'o mie nouă sute optzeci și patru') + self.assertEqual(num2words(2018, lang='ro', to='year'), + u'două mii optsprezece') + self.assertEqual(num2words(1066, lang='ro', to='year'), + u'o mie șaizeci și șase') + self.assertEqual(num2words(5000, lang='ro', to='year'), + u'cinci mii') + self.assertEqual(num2words(2001, lang='ro', to='year'), + u'două mii unu') + self.assertEqual(num2words(905, lang='ro', to='year'), + u'nouă sute cinci') + self.assertEqual(num2words(6600, lang='ro', to='year'), + u'șase mii șase sute') + self.assertEqual(num2words(1600, lang='ro', to='year'), + u'o mie șase sute') + self.assertEqual(num2words(700, lang='ro', to='year'), + u'șapte sute') + self.assertEqual(num2words(50, lang='ro', to='year'), + u'cincizeci') + self.assertEqual(num2words(0, lang='ro', to='year'), + u'zero') + self.assertEqual(num2words(10, lang='ro', to='year'), + u'zece') + # suffixes + self.assertEqual(num2words(-44, lang='ro', to='year'), + u'patruzeci și patru î.Hr.') + self.assertEqual(num2words(-44, lang='ro', to='year', + suffix=u'î.e.n.'), u'patruzeci și patru î.e.n.') + self.assertEqual(num2words(1, lang='ro', to='year', suffix='d.Hr.'), + u'unu d.Hr.') + self.assertEqual(num2words(-66000000, lang='ro', to='year'), + u'șaizeci și șase milioane î.Hr.') diff -Nru python-num2words-0.5.6/tests/test_ru.py python-num2words-0.5.9/tests/test_ru.py --- python-num2words-0.5.6/tests/test_ru.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_ru.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,5 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or @@ -13,6 +14,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA + from __future__ import unicode_literals from unittest import TestCase @@ -67,6 +69,9 @@ self.assertEqual( num2words(1000139, lang='ru'), "один миллион сто тридцать девять" ) + self.assertEqual(num2words(-1, lang='ru'), "минус один") + self.assertEqual(num2words(-15, lang='ru'), "минус пятнадцать") + self.assertEqual(num2words(-100, lang='ru'), "минус сто") def test_floating_point(self): self.assertEqual(num2words(5.2, lang='ru'), "пять запятая два") @@ -76,9 +81,75 @@ ) def test_to_ordinal(self): - # @TODO: implement to_ordinal - with self.assertRaises(NotImplementedError): - num2words(1, lang='ru', to='ordinal') + self.assertEqual( + num2words(1, lang='ru', to='ordinal'), + 'первый' + ) + self.assertEqual( + num2words(5, lang='ru', to='ordinal'), + 'пятый' + ) + self.assertEqual( + num2words(10, lang='ru', to='ordinal'), + 'десятый' + ) + + self.assertEqual( + num2words(13, lang='ru', to='ordinal'), + 'тринадцатый' + ) + self.assertEqual( + num2words(20, lang='ru', to='ordinal'), + 'двадцатый' + ) + self.assertEqual( + num2words(23, lang='ru', to='ordinal'), + 'двадцать третий' + ) + self.assertEqual( + num2words(40, lang='ru', to='ordinal'), + 'сороковой' + ) + self.assertEqual( + num2words(70, lang='ru', to='ordinal'), + 'семидесятый' + ) + self.assertEqual( + num2words(100, lang='ru', to='ordinal'), + 'сотый' + ) + self.assertEqual( + num2words(136, lang='ru', to='ordinal'), + 'сто тридцать шестой' + ) + self.assertEqual( + num2words(500, lang='ru', to='ordinal'), + 'пятисотый' + ) + self.assertEqual( + num2words(1000, lang='ru', to='ordinal'), + 'тысячный' + ) + self.assertEqual( + num2words(1001, lang='ru', to='ordinal'), + 'тысяча первый' + ) + self.assertEqual( + num2words(2000, lang='ru', to='ordinal'), + 'двух тысячный' + ) + self.assertEqual( + num2words(10000, lang='ru', to='ordinal'), + 'десяти тысячный' + ) + self.assertEqual( + num2words(1000000, lang='ru', to='ordinal'), + 'миллионный' + ) + self.assertEqual( + num2words(1000000000, lang='ru', to='ordinal'), + 'миллиардный' + ) def test_to_currency(self): self.assertEqual( @@ -127,3 +198,16 @@ cents=False, currency='EUR'), "тридцать восемь евро и 40 центов" ) + self.assertEqual( + num2words('1230.56', lang='ru', to='currency', currency='USD'), + 'одна тысяча двести тридцать долларов, пятьдесят шесть центов' + ) + self.assertEqual( + num2words('1231.56', lang='ru', to='currency', currency='USD'), + 'одна тысяча двести тридцать один доллар, пятьдесят шесть центов' + ) + self.assertEqual( + num2words('1234.56', lang='ru', to='currency', currency='USD'), + 'одна тысяча двести тридцать четыре доллара, пятьдесят шесть ' + 'центов' + ) diff -Nru python-num2words-0.5.6/tests/test_sl.py python-num2words-0.5.9/tests/test_sl.py --- python-num2words-0.5.6/tests/test_sl.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_sl.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,5 +1,6 @@ -# -*- encoding: utf-8 -*- -# Copyright (c) 2015, Savoir-faire Linux inc. All Rights Reserved. +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public diff -Nru python-num2words-0.5.6/tests/test_sr.py python-num2words-0.5.9/tests/test_sr.py --- python-num2words-0.5.6/tests/test_sr.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_sr.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,243 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +from unittest import TestCase + +from num2words import num2words + + +class Num2WordsSRTest(TestCase): + + def test_cardinal(self): + self.assertEqual("sto", num2words(100, lang='sr')) + self.assertEqual("sto jedan", num2words(101, lang='sr')) + self.assertEqual("sto deset", num2words(110, lang='sr')) + self.assertEqual("sto petnaest", num2words(115, lang='sr')) + self.assertEqual( + "sto dvadeset tri", num2words(123, lang='sr') + ) + self.assertEqual( + "jedna hiljada", num2words(1000, lang='sr') + ) + self.assertEqual( + "jedna hiljada jedan", num2words(1001, lang='sr') + ) + self.assertEqual( + "dve hiljade dvanaest", num2words(2012, lang='sr') + ) + self.assertEqual( + "dvanaest hiljada petsto devetnaest zapeta osamdeset pet", + num2words(12519.85, lang='sr') + ) + self.assertEqual( + "jedan bilion dvesta trideset četiri miliona petsto " + "šezdeset sedam hiljada osamsto devedeset", + num2words(1234567890, lang='sr') + ) + self.assertEqual( + "dvesta petnaest noniliona četristo šezdeset jedan " + "oktilion četristo sedam septiliona osamsto devedeset " + "dva sekstiliona trideset devet kvintiliona dva kvadriliona " + "sto pedeset sedam triliona sto osamdeset devet biliona " + "osamsto osamdeset tri miliona devetsto jedna hiljada " + "šesto sedamdeset šest", + num2words(215461407892039002157189883901676, lang='sr') + ) + self.assertEqual( + "sedamsto devetnaest noniliona devedeset četiri oktiliona " + "dvesta trideset četiri septiliona šesto devedeset tri " + "sekstiliona šesto šezdeset tri kvintiliona trideset " + "četiri kvadriliona osamsto dvadeset dva triliona osamsto " + "dvadeset četiri biliona trista osamdeset četiri miliona " + "dvesta dvadeset hiljada dvesta devedeset jedan", + num2words(719094234693663034822824384220291, lang='sr') + ) + self.assertEqual("pet", num2words(5, lang='sr')) + self.assertEqual("petnaest", num2words(15, lang='sr')) + self.assertEqual("sto pedeset četiri", num2words(154, lang='sr')) + self.assertEqual( + "jedna hiljada sto trideset pet", + num2words(1135, lang='sr') + ) + self.assertEqual( + "četristo osamnaest hiljada petsto trideset jedan", + num2words(418531, lang='sr'), + ) + self.assertEqual( + "jedan milion sto trideset devet", + num2words(1000139, lang='sr') + ) + + def test_floating_point(self): + self.assertEqual("pet zapeta dva", num2words(5.2, lang='sr')) + self.assertEqual( + "petsto šezdeset jedan zapeta četrdeset dva", + num2words(561.42, lang='sr') + ) + + def test_to_ordinal(self): + # @TODO: implement to_ordinal + with self.assertRaises(NotImplementedError): + num2words(1, lang='sr', to='ordinal') + + def test_to_currency(self): + self.assertEqual( + 'jedan evro, nula centi', + num2words(1.0, lang='sr', to='currency', currency='EUR') + + ) + self.assertEqual( + 'dva evra, nula centi', + num2words(2.0, lang='sr', to='currency', currency='EUR') + + ) + self.assertEqual( + 'pet evra, nula centi', + num2words(5.0, lang='sr', to='currency', currency='EUR') + + ) + self.assertEqual( + 'dva evra, jedan cent', + num2words(2.01, lang='sr', to='currency', currency='EUR') + + ) + + self.assertEqual( + 'dva evra, dva centa', + num2words(2.02, lang='sr', to='currency', currency='EUR') + + ) + self.assertEqual( + 'dva evra, pet centi', + num2words(2.05, lang='sr', to='currency', currency='EUR') + + ) + self.assertEqual( + 'dve rublje, nula kopejki', + num2words(2.0, lang='sr', to='currency', currency='RUB') + + ) + self.assertEqual( + 'dve rublje, jedna kopejka', + num2words(2.01, lang='sr', to='currency', currency='RUB') + + ) + self.assertEqual( + 'dve rublje, dve kopejke', + num2words(2.02, lang='sr', to='currency', currency='RUB') + + ) + self.assertEqual( + 'dve rublje, pet kopejki', + num2words(2.05, lang='sr', to='currency', currency='RUB') + + ) + self.assertEqual( + 'jedan dinar, nula para', + num2words(1.0, lang='sr', to='currency', currency='RSD') + ) + self.assertEqual( + 'dva dinara, dve pare', + num2words(2.02, lang='sr', to='currency', currency='RSD') + + ) + self.assertEqual( + 'pet dinara, pet para', + num2words(5.05, lang='sr', to='currency', currency='RSD') + + ) + self.assertEqual( + 'jedanaest dinara, jedanaest para', + num2words(11.11, lang='sr', to='currency', currency='RSD') + + ) + self.assertEqual( + 'dvadeset jedan dinar, dvadeset jedna para', + num2words(21.21, lang='sr', to='currency', currency='RSD') + + ) + self.assertEqual( + 'dvadeset jedan evro, dvadeset jedan cent', + num2words(21.21, lang='sr', to='currency', currency='EUR') + + ) + self.assertEqual( + 'dvadeset jedna rublja, dvadeset jedna kopejka', + num2words(21.21, lang='sr', to='currency', currency='RUB') + + ) + self.assertEqual( + 'jedna hiljada dvesta trideset četiri evra, ' + 'pedeset šest centi', + num2words( + 1234.56, lang='sr', to='currency', currency='EUR' + ) + ) + self.assertEqual( + 'jedna hiljada dvesta trideset četiri rublje, ' + 'pedeset šest kopejki', + num2words( + 1234.56, lang='sr', to='currency', currency='RUB' + ) + ) + self.assertEqual( + 'sto jedan evro i jedanaest centi', + num2words( + 10111, + lang='sr', + to='currency', + currency='EUR', + seperator=' i' + ) + ) + self.assertEqual( + 'sto jedna rublja i dvadeset jedna kopejka', + num2words( + 10121, + lang='sr', + to='currency', + currency='RUB', + seperator=' i' + ) + ) + self.assertEqual( + 'sto jedna rublja i dvadeset dve kopejke', + num2words(10122, lang='sr', to='currency', currency='RUB', + seperator=' i') + ) + self.assertEqual( + 'sto jedan evro i dvadeset jedan cent', + num2words(10121, lang='sr', to='currency', currency='EUR', + seperator=' i'), + ) + self.assertEqual( + 'minus dvanaest hiljada petsto devetnaest evra, 85 centi', + num2words( + -1251985, + lang='sr', + to='currency', + currency='EUR', + cents=False + ) + ) + self.assertEqual( + "trideset osam evra i 40 centi", + num2words('38.4', lang='sr', to='currency', seperator=' i', + cents=False, currency='EUR'), + ) diff -Nru python-num2words-0.5.6/tests/test_th.py python-num2words-0.5.9/tests/test_th.py --- python-num2words-0.5.6/tests/test_th.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_th.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,208 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +from unittest import TestCase + +from num2words import num2words +from num2words.lang_TH import Num2Word_TH + + +class TestNumWord(TestCase): + + def test_0(self): + self.assertEqual(num2words(0, lang='th'), "ศูนย์") + + def test_end_with_1(self): + self.assertEqual(num2words(21, lang='th'), "ยี่สิบเอ็ด") + self.assertEqual(num2words(11, lang='th'), "สิบเอ็ด") + self.assertEqual(num2words(101, lang='th'), "หนึ่งร้อยเอ็ด") + self.assertEqual(num2words(1201, lang='th'), "หนึ่งพันสองร้อยเอ็ด") + + def test_start_20(self): + self.assertEqual(num2words(22, lang='th'), "ยี่สิบสอง") + self.assertEqual(num2words(27, lang='th'), "ยี่สิบเจ็ด") + + def test_start_10(self): + self.assertEqual(num2words(10, lang='th'), "สิบ") + self.assertEqual(num2words(18, lang='th'), "สิบแปด") + + def test_1_to_9(self): + self.assertEqual(num2words(1, lang='th'), "หนึ่ง") + self.assertEqual(num2words(5, lang='th'), "ห้า") + self.assertEqual(num2words(9, lang='th'), "เก้า") + + def test_31_to_99(self): + self.assertEqual(num2words(31, lang='th'), "สามสิบเอ็ด") + self.assertEqual(num2words(48, lang='th'), "สี่สิบแปด") + self.assertEqual(num2words(76, lang='th'), "เจ็ดสิบหก") + + def test_100_to_999(self): + self.assertEqual(num2words(100, lang='th'), "หนึ่งร้อย") + self.assertEqual(num2words(123, lang='th'), "หนึ่งร้อยยี่สิบสาม") + self.assertEqual(num2words(456, lang='th'), "สี่ร้อยห้าสิบหก") + self.assertEqual(num2words(721, lang='th'), "เจ็ดร้อยยี่สิบเอ็ด") + + def test_1000_to_9999(self): + self.assertEqual(num2words(1000, lang='th'), "หนึ่งพัน") + self.assertEqual( + num2words(2175, lang='th'), "สองพันหนึ่งร้อยเจ็ดสิบห้า" + ) + self.assertEqual(num2words(4582, lang='th'), "สี่พันห้าร้อยแปดสิบสอง") + self.assertEqual(num2words(9346, lang='th'), "เก้าพันสามร้อยสี่สิบหก") + + def test_10000_to_99999(self): + self.assertEqual( + num2words(11111, lang='th'), "หนึ่งหมื่นหนึ่งพันหนึ่งร้อยสิบเอ็ด" + ) + self.assertEqual( + num2words(22222, lang='th'), "สองหมื่นสองพันสองร้อยยี่สิบสอง" + ) + self.assertEqual( + num2words(84573, lang='th'), "แปดหมื่นสี่พันห้าร้อยเจ็ดสิบสาม" + ) + + def test_100000_to_999999(self): + self.assertEqual( + num2words(153247, lang='th'), + "หนึ่งแสนห้าหมื่นสามพันสองร้อยสี่สิบเจ็ด" + ) + self.assertEqual( + num2words(562442, lang='th'), + "ห้าแสนหกหมื่นสองพันสี่ร้อยสี่สิบสอง" + ) + self.assertEqual( + num2words(999999, lang='th'), + "เก้าแสนเก้าหมื่นเก้าพันเก้าร้อยเก้าสิบเก้า" + ) + + def test_more_than_million(self): + self.assertEqual( + num2words(1000000, lang='th'), + "หนึ่งล้าน" + ) + self.assertEqual( + num2words(1000001, lang='th'), + "หนึ่งล้านเอ็ด" + ) + self.assertEqual( + num2words(42478941, lang='th'), + "สี่สิบสองล้านสี่แสนเจ็ดหมื่นแปดพันเก้าร้อยสี่สิบเอ็ด" + ) + self.assertEqual( + num2words(712696969, lang='th'), + "เจ็ดร้อยสิบสองล้านหกแสนเก้าหมื่นหกพันเก้าร้อยหกสิบเก้า" + ) + self.assertEqual( + num2words(1000000000000000001, lang='th'), + "หนึ่งล้านล้านล้านเอ็ด" + ) + + def test_decimal(self): + self.assertEqual( + num2words(0.0, lang='th'), "ศูนย์" + ) + self.assertEqual( + num2words(0.0038, lang='th'), "ศูนย์จุดศูนย์ศูนย์สามแปด" + ) + self.assertEqual( + num2words(0.01, lang='th'), "ศูนย์จุดศูนย์หนึ่ง" + ) + self.assertEqual( + num2words(1.123, lang='th'), "หนึ่งจุดหนึ่งสองสาม" + ) + self.assertEqual( + num2words(35.37, lang='th'), "สามสิบห้าจุดสามเจ็ด" + ) + self.assertEqual( + num2words(1000000.01, lang='th'), "หนึ่งล้านจุดศูนย์หนึ่ง" + ) + + def test_currency(self): + self.assertEqual( + num2words(100, lang='th', to='currency', currency='THB'), + "หนึ่งร้อยบาทถ้วน" + ) + self.assertEqual( + num2words(100, lang='th', to='currency', currency='USD'), + "หนึ่งร้อยดอลลาร์" + ) + self.assertEqual( + num2words(100, lang='th', to='currency', currency='EUR'), + "หนึ่งร้อยยูโร" + ) + + def test_currency_decimal(self): + self.assertEqual( + num2words(0.00, lang='th', to='currency'), "ศูนย์บาทถ้วน" + ) + self.assertEqual( + num2words(0.05, lang='th', to='currency'), "ห้าสตางค์" + ) + self.assertEqual( + num2words(0.50, lang='th', to='currency'), "ห้าสิบสตางค์" + ) + self.assertEqual( + num2words(0.99, lang='th', to='currency'), "เก้าสิบเก้าสตางค์" + ) + self.assertEqual( + num2words(100.00, lang='th', to='currency'), "หนึ่งร้อยบาทถ้วน" + ) + self.assertEqual( + num2words(100.23, lang='th', to='currency', currency='USD'), + "หนึ่งร้อยดอลลาร์ยี่สิบสามเซนต์" + ) + self.assertEqual( + num2words(100.24, lang='th', to='currency', currency='EUR'), + "หนึ่งร้อยยูโรยี่สิบสี่เซนต์" + ) + + def test_negative(self): + self.assertEqual(num2words(-10, lang='th'), "ติดลบสิบ") + self.assertEqual(num2words(-10.50, lang='th'), "ติดลบสิบจุดห้า") + self.assertEqual( + num2words(-100.00, lang='th', to='currency'), + "ติดลบหนึ่งร้อยบาทถ้วน" + ) + + def test_round_2_decimal(self): + n2wTH = Num2Word_TH() + self.assertEqual(n2wTH.round_2_decimal(0.004), ('0.00', False)) + self.assertEqual(n2wTH.round_2_decimal(0.005), ('0.01', False)) + self.assertEqual(n2wTH.round_2_decimal(0.006), ('0.01', False)) + self.assertEqual(n2wTH.round_2_decimal(0.0005), + ('0.00', False)) + self.assertEqual(n2wTH.round_2_decimal(0.984), ('0.98', False)) + self.assertEqual(n2wTH.round_2_decimal(0.989), ('0.99', False)) + self.assertEqual(n2wTH.round_2_decimal(0.994), ('0.99', False)) + self.assertEqual(n2wTH.round_2_decimal(0.999), ('1.00', False)) + self.assertEqual(n2wTH.round_2_decimal(-0.994), ('0.99', True)) + self.assertEqual(n2wTH.round_2_decimal(-0.999), ('1.00', True)) + # self.assertEqual(n2wTH.round_2_decimal(0.985), ('0.99', False)) + # Expect 0.99 get 0.98 + # self.assertEqual(n2wTH.round_2_decimal(0.995), ('1.00', False)) + # Expect 1.00 get 0.99 + + def test_split_six(self): + n2wTH = Num2Word_TH() + self.assertEqual(n2wTH.split_six(str(123456789)), + ['987654', '321']) + self.assertEqual(n2wTH.split_six(str(12345)), + ['54321']) + self.assertEqual(n2wTH.split_six(str(1234567)), + ['765432', '1']) diff -Nru python-num2words-0.5.6/tests/test_tr.py python-num2words-0.5.9/tests/test_tr.py --- python-num2words-0.5.6/tests/test_tr.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_tr.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,6 +1,6 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. -# Copyright (c) 2017, Tufan Kaynak, Framras. All Rights Reserved. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public diff -Nru python-num2words-0.5.6/tests/test_uk.py python-num2words-0.5.9/tests/test_uk.py --- python-num2words-0.5.6/tests/test_uk.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_uk.py 2019-01-11 01:09:08.000000000 +0000 @@ -1,4 +1,5 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # This library is free software; you can redistribute it and/or @@ -13,6 +14,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA + from __future__ import unicode_literals from unittest import TestCase @@ -81,7 +83,7 @@ def test_to_currency(self): # self.assertEqual( # num2words(1.0, lang='uk', to='currency', currency='EUR'), - # "один евро, нуль центiв" + # "один євро, нуль центiв" # ) self.assertEqual( num2words(1.0, lang='uk', to='currency', currency='UAH'), @@ -89,7 +91,7 @@ ) self.assertEqual( num2words(1234.56, lang='uk', to='currency', currency='EUR'), - "одна тисяча двiстi тридцять чотири евро, п'ятдесят шiсть центiв" + "одна тисяча двiстi тридцять чотири євро, п'ятдесят шiсть центiв" ) self.assertEqual( num2words(1234.56, lang='uk', to='currency', currency='UAH'), @@ -99,7 +101,7 @@ # self.assertEqual( # num2words(10111, lang='uk', to='currency', currency='EUR', # seperator=u' та'), - # "сто один евро та одинадцять центiв" + # "сто один євро та одинадцять центiв" # ) self.assertEqual( num2words(10121, lang='uk', to='currency', currency='UAH', @@ -119,15 +121,15 @@ # self.assertEqual( # num2words(10121, lang='uk', to='currency', currency='EUR', # seperator=u' та'), - # "сто один евро та двадцять один цент" + # "сто один євро та двадцять один цент" # ) self.assertEqual( num2words(-1251985, lang='uk', to='currency', currency='EUR', cents=False), - "мiнус дванадцять тисяч п'ятсот дев'ятнадцять евро, 85 центiв" + "мiнус дванадцять тисяч п'ятсот дев'ятнадцять євро, 85 центiв" ) self.assertEqual( num2words('38.4', lang='uk', to='currency', seperator=' и', cents=False, currency='EUR'), - "тридцять вiсiм евро и 40 центiв" + "тридцять вiсiм євро и 40 центiв" ) diff -Nru python-num2words-0.5.6/tests/test_utils.py python-num2words-0.5.9/tests/test_utils.py --- python-num2words-0.5.6/tests/test_utils.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_utils.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from unittest import TestCase + +from num2words.utils import splitbyx + + +class TestUtils(TestCase): + def test_splitbyx(self): + self.assertEqual(list(splitbyx(str(12), 3)), [12]) + self.assertEqual(list(splitbyx(str(1234), 3)), [1, 234]) + self.assertEqual(list(splitbyx(str(12345678900), 3)), + [12, 345, 678, 900] + ) + self.assertEqual(list(splitbyx(str(1000000), 6)), [1, 0]) + + self.assertEqual(list(splitbyx(str(12), 3, format_int=False)), ['12']) + self.assertEqual(list(splitbyx(str(1234), 3, format_int=False)), + ['1', '234'] + ) + self.assertEqual(list(splitbyx(str(12345678900), 3, format_int=False)), + ['12', '345', '678', '900'] + ) + self.assertEqual(list(splitbyx(str(1000000), 6, format_int=False)), + ['1', '000000'] + ) diff -Nru python-num2words-0.5.6/tests/test_vi.py python-num2words-0.5.9/tests/test_vi.py --- python-num2words-0.5.6/tests/test_vi.py 1970-01-01 00:00:00.000000000 +0000 +++ python-num2words-0.5.9/tests/test_vi.py 2019-01-11 01:09:08.000000000 +0000 @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library 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 +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +from unittest import TestCase + +from num2words import num2words + + +class Num2WordsVITest(TestCase): + + def test_0(self): + self.assertEqual(num2words(0, lang="vi"), "không") + + def test_1_to_10(self): + self.assertEqual(num2words(1, lang="vi"), "một") + self.assertEqual(num2words(2, lang="vi"), "hai") + self.assertEqual(num2words(7, lang="vi"), "bảy") + self.assertEqual(num2words(10, lang="vi"), "mười") + + def test_11_to_19(self): + self.assertEqual(num2words(11, lang="vi"), "mười một") + self.assertEqual(num2words(13, lang="vi"), "mười ba") + self.assertEqual(num2words(14, lang="vi"), "mười bốn") + self.assertEqual(num2words(15, lang="vi"), "mười lăm") + self.assertEqual(num2words(16, lang="vi"), "mười sáu") + self.assertEqual(num2words(19, lang="vi"), "mười chín") + + def test_20_to_99(self): + self.assertEqual(num2words(20, lang="vi"), "hai mươi") + self.assertEqual(num2words(23, lang="vi"), "hai mươi ba") + self.assertEqual(num2words(28, lang="vi"), "hai mươi tám") + self.assertEqual(num2words(31, lang="vi"), "ba mươi mốt") + self.assertEqual(num2words(40, lang="vi"), "bốn mươi") + self.assertEqual(num2words(66, lang="vi"), "sáu mươi sáu") + self.assertEqual(num2words(92, lang="vi"), "chín mươi hai") + + def test_100_to_999(self): + self.assertEqual(num2words(100, lang="vi"), "một trăm") + self.assertEqual(num2words(150, lang="vi"), "một trăm năm mươi") + self.assertEqual( + num2words(196, lang="vi"), "một trăm chín mươi sáu" + ) + self.assertEqual(num2words(200, lang="vi"), "hai trăm") + self.assertEqual(num2words(210, lang="vi"), "hai trăm mười") + + def test_1000_to_9999(self): + self.assertEqual(num2words(1000, lang="vi"), "một nghìn") + self.assertEqual(num2words(1500, lang="vi"), "một nghìn năm trăm") + self.assertEqual( + num2words(7378, lang="vi"), "bảy nghìn ba trăm bảy mươi tám" + ) + self.assertEqual(num2words(2000, lang="vi"), "hai nghìn") + self.assertEqual(num2words(2100, lang="vi"), "hai nghìn một trăm") + self.assertEqual( + num2words(6870, lang="vi"), "sáu nghìn tám trăm bảy mươi" + ) + self.assertEqual(num2words(10000, lang="vi"), "mười nghìn") + self.assertEqual(num2words(100000, lang="vi"), "một trăm nghìn") + self.assertEqual( + num2words(523456, lang="vi"), + "năm trăm hai mươi ba nghìn bốn trăm năm mươi sáu" + ) + + def test_big(self): + self.assertEqual(num2words(1000000, lang="vi"), "một triệu") + self.assertEqual( + num2words(1200000, lang="vi"), "một triệu hai trăm nghìn" + ) + self.assertEqual(num2words(3000000, lang="vi"), "ba triệu") + self.assertEqual( + num2words(3800000, lang="vi"), "ba triệu tám trăm nghìn" + ) + self.assertEqual(num2words(1000000000, lang="vi"), "một tỷ") + self.assertEqual(num2words(2000000000, lang="vi"), "hai tỷ") + self.assertEqual( + num2words(2000001000, lang="vi"), "hai tỷ một nghìn" + ) + self.assertEqual( + num2words(1234567890, lang="vi"), + "một tỷ hai trăm ba mươi bốn triệu năm trăm sáu mươi bảy nghìn " + "tám trăm chín mươi" + ) + + def test_decimal_number(self): + self.assertEqual( + num2words(1000.11, lang="vi"), "một nghìn phẩy mười một" + ) + self.assertEqual( + num2words(1000.21, lang="vi"), "một nghìn phẩy hai mươi mốt" + ) + + def test_special_number(self): + """ + Some number will have some specail rule + """ + self.assertEqual(num2words(21, lang="vi"), "hai mươi mốt") + self.assertEqual(num2words(25, lang="vi"), "hai mươi lăm") + # >100 + self.assertEqual(num2words(101, lang="vi"), "một trăm lẻ một") + self.assertEqual(num2words(105, lang="vi"), "một trăm lẻ năm") + self.assertEqual(num2words(701, lang="vi"), "bảy trăm lẻ một") + self.assertEqual(num2words(705, lang="vi"), "bảy trăm lẻ năm") + + # >1000 + self.assertEqual(num2words(1001, lang="vi"), "một nghìn lẻ một") + self.assertEqual(num2words(1005, lang="vi"), "một nghìn lẻ năm") + self.assertEqual( + num2words(98765, lang="vi"), + "chín mươi tám nghìn bảy trăm sáu mươi lăm" + ) + + # > 1000000 + self.assertEqual(num2words(3000005, lang="vi"), "ba triệu lẻ năm") + self.assertEqual(num2words(1000007, lang="vi"), "một triệu lẻ bảy") + + # > 1000000000 + self.assertEqual( + num2words(1000000017, lang="vi"), "một tỷ lẻ mười bảy" + ) + self.assertEqual( + num2words(1000101017, lang="vi"), + "một tỷ một trăm lẻ một nghìn lẻ mười bảy" + ) diff -Nru python-num2words-0.5.6/tests/test_vn.py python-num2words-0.5.9/tests/test_vn.py --- python-num2words-0.5.6/tests/test_vn.py 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tests/test_vn.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -# -*- encoding: utf-8 -*- -# Copyright (c) 2015, Savoir-faire Linux inc. All Rights Reserved. - -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# This library 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 -# Lesser General Public License for more details. -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301 USA - -from __future__ import unicode_literals - -from unittest import TestCase - -from num2words import num2words - - -class Num2WordsVNTest(TestCase): - - def test_0(self): - self.assertEqual(num2words(0, lang="vi_VN"), "không") - - def test_1_to_10(self): - self.assertEqual(num2words(1, lang="vi_VN"), "một") - self.assertEqual(num2words(2, lang="vi_VN"), "hai") - self.assertEqual(num2words(7, lang="vi_VN"), "bảy") - self.assertEqual(num2words(10, lang="vi_VN"), "mười") - - def test_11_to_19(self): - self.assertEqual(num2words(11, lang="vi_VN"), "mười một") - self.assertEqual(num2words(13, lang="vi_VN"), "mười ba") - self.assertEqual(num2words(14, lang="vi_VN"), "mười bốn") - self.assertEqual(num2words(15, lang="vi_VN"), "mười lăm") - self.assertEqual(num2words(16, lang="vi_VN"), "mười sáu") - self.assertEqual(num2words(19, lang="vi_VN"), "mười chín") - - def test_20_to_99(self): - self.assertEqual(num2words(20, lang="vi_VN"), "hai mươi") - self.assertEqual(num2words(23, lang="vi_VN"), "hai mươi ba") - self.assertEqual(num2words(28, lang="vi_VN"), "hai mươi tám") - self.assertEqual(num2words(31, lang="vi_VN"), "ba mươi mốt") - self.assertEqual(num2words(40, lang="vi_VN"), "bốn mươi") - self.assertEqual(num2words(66, lang="vi_VN"), "sáu mươi sáu") - self.assertEqual(num2words(92, lang="vi_VN"), "chín mươi hai") - - def test_100_to_999(self): - self.assertEqual(num2words(100, lang="vi_VN"), "một trăm") - self.assertEqual(num2words(150, lang="vi_VN"), "một trăm năm mươi") - self.assertEqual( - num2words(196, lang="vi_VN"), "một trăm chín mươi sáu" - ) - self.assertEqual(num2words(200, lang="vi_VN"), "hai trăm") - self.assertEqual(num2words(210, lang="vi_VN"), "hai trăm mười") - - def test_1000_to_9999(self): - self.assertEqual(num2words(1000, lang="vi_VN"), "một nghìn") - self.assertEqual(num2words(1500, lang="vi_VN"), "một nghìn năm trăm") - self.assertEqual( - num2words(7378, lang="vi_VN"), "bảy nghìn ba trăm bảy mươi tám" - ) - self.assertEqual(num2words(2000, lang="vi_VN"), "hai nghìn") - self.assertEqual(num2words(2100, lang="vi_VN"), "hai nghìn một trăm") - self.assertEqual( - num2words(6870, lang="vi_VN"), "sáu nghìn tám trăm bảy mươi" - ) - self.assertEqual(num2words(10000, lang="vi_VN"), "mười nghìn") - self.assertEqual(num2words(100000, lang="vi_VN"), "một trăm nghìn") - self.assertEqual( - num2words(523456, lang="vi_VN"), - "năm trăm hai mươi ba nghìn bốn trăm năm mươi sáu" - ) - - def test_big(self): - self.assertEqual(num2words(1000000, lang="vi_VN"), "một triệu") - self.assertEqual( - num2words(1200000, lang="vi_VN"), "một triệu hai trăm nghìn" - ) - self.assertEqual(num2words(3000000, lang="vi_VN"), "ba triệu") - self.assertEqual( - num2words(3800000, lang="vi_VN"), "ba triệu tám trăm nghìn" - ) - self.assertEqual(num2words(1000000000, lang="vi_VN"), "một tỷ") - self.assertEqual(num2words(2000000000, lang="vi_VN"), "hai tỷ") - self.assertEqual( - num2words(2000001000, lang="vi_VN"), "hai tỷ một nghìn" - ) - self.assertEqual( - num2words(1234567890, lang="vi_VN"), - "một tỷ hai trăm ba mươi bốn triệu năm trăm sáu mươi bảy nghìn " - "tám trăm chín mươi" - ) - - def test_decimal_number(self): - self.assertEqual( - num2words(1000.11, lang="vi_VN"), "một nghìn phẩy mười một" - ) - self.assertEqual( - num2words(1000.21, lang="vi_VN"), "một nghìn phẩy hai mươi mốt" - ) - - def test_special_number(self): - """ - Some number will have some specail rule - """ - self.assertEqual(num2words(21, lang="vi_VN"), "hai mươi mốt") - self.assertEqual(num2words(25, lang="vi_VN"), "hai mươi lăm") - # >100 - self.assertEqual(num2words(101, lang="vi_VN"), "một trăm lẻ một") - self.assertEqual(num2words(105, lang="vi_VN"), "một trăm lẻ năm") - self.assertEqual(num2words(701, lang="vi_VN"), "bảy trăm lẻ một") - self.assertEqual(num2words(705, lang="vi_VN"), "bảy trăm lẻ năm") - - # >1000 - self.assertEqual(num2words(1001, lang="vi_VN"), "một nghìn lẻ một") - self.assertEqual(num2words(1005, lang="vi_VN"), "một nghìn lẻ năm") - self.assertEqual( - num2words(98765, lang="vi_VN"), - "chín mươi tám nghìn bảy trăm sáu mươi lăm" - ) - - # > 1000000 - self.assertEqual(num2words(3000005, lang="vi_VN"), "ba triệu lẻ năm") - self.assertEqual(num2words(1000007, lang="vi_VN"), "một triệu lẻ bảy") - - # > 1000000000 - self.assertEqual( - num2words(1000000017, lang="vi_VN"), "một tỷ lẻ mười bảy" - ) - self.assertEqual( - num2words(1000101017, lang="vi_VN"), - "một tỷ một trăm lẻ một nghìn lẻ mười bảy" - ) diff -Nru python-num2words-0.5.6/tox.ini python-num2words-0.5.9/tox.ini --- python-num2words-0.5.6/tox.ini 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/tox.ini 2019-01-11 01:09:08.000000000 +0000 @@ -1,15 +1,28 @@ [tox] -envlist = flake8, isort, py27,py34,py35,py36 +envlist = flake8,isort,py27,py34,py35,py36,py37 [testenv] passenv = TRAVIS TRAVIS_* deps = - -r{toxinidir}/requirements-test.txt + coverage + delegator.py commands = - flake8 - isort --check-only --recursive --diff num2words tests - coverage erase coverage run -m unittest discover - coverage report --fail-under=75 --omit=.tox/*,/usr/* - coveralls + coverage report --fail-under=75 --omit=.tox/*,tests/*,/usr/* + coverage report --fail-under=100 --include=tests/* --skip-covered + +[testenv:flake8] +changedir = {toxinidir} +deps = + flake8 + flake8-copyright +commands = + flake8 +[testenv:isort] +changedir = {toxinidir} +deps = + isort + delegator.py +commands = + isort --check-only --recursive --diff num2words tests diff -Nru python-num2words-0.5.6/.travis.yml python-num2words-0.5.9/.travis.yml --- python-num2words-0.5.6/.travis.yml 2017-11-22 19:35:46.000000000 +0000 +++ python-num2words-0.5.9/.travis.yml 2019-01-11 01:09:08.000000000 +0000 @@ -5,5 +5,16 @@ - "3.4" - "3.5" - "3.6" -install: pip install tox-travis +matrix: + include: + - { python: 3.6, env: TOXENV=flake8 } + - { python: 3.6, env: TOXENV=isort } + # Py37 requires xenial distrubution and sudo + # See travis-ci/travis-ci#9069 + - { python: 3.7, dist: xenial, sudo: true } + +install: + - pip install tox-travis + - pip install coveralls script: tox +after_success: if [ -e .coverage ]; then coveralls; fi