num2words2 0.1.0.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- num2words2/README.md +69 -0
- num2words2/__init__.py +196 -0
- num2words2/_version.py +3 -0
- num2words2/base.py +377 -0
- num2words2/compat.py +29 -0
- num2words2/currency.py +60 -0
- num2words2/lang_AF.py +202 -0
- num2words2/lang_AM.py +193 -0
- num2words2/lang_AR.py +435 -0
- num2words2/lang_AS.py +119 -0
- num2words2/lang_AZ.py +208 -0
- num2words2/lang_BA.py +119 -0
- num2words2/lang_BE.py +356 -0
- num2words2/lang_BG.py +393 -0
- num2words2/lang_BN.py +242 -0
- num2words2/lang_BO.py +122 -0
- num2words2/lang_BR.py +135 -0
- num2words2/lang_BS.py +189 -0
- num2words2/lang_CA.py +476 -0
- num2words2/lang_CE.py +546 -0
- num2words2/lang_CS.py +260 -0
- num2words2/lang_CY.py +574 -0
- num2words2/lang_DA.py +170 -0
- num2words2/lang_DE.py +180 -0
- num2words2/lang_EL.py +338 -0
- num2words2/lang_EN.py +118 -0
- num2words2/lang_EN_IN.py +26 -0
- num2words2/lang_EN_NG.py +45 -0
- num2words2/lang_EO.py +130 -0
- num2words2/lang_ES.py +399 -0
- num2words2/lang_ES_CO.py +37 -0
- num2words2/lang_ES_CR.py +38 -0
- num2words2/lang_ES_GT.py +37 -0
- num2words2/lang_ES_NI.py +35 -0
- num2words2/lang_ES_VE.py +43 -0
- num2words2/lang_ET.py +393 -0
- num2words2/lang_EU.py +158 -0
- num2words2/lang_EUR.py +104 -0
- num2words2/lang_FA.py +187 -0
- num2words2/lang_FI.py +759 -0
- num2words2/lang_FO.py +136 -0
- num2words2/lang_FR.py +133 -0
- num2words2/lang_FR_BE.py +49 -0
- num2words2/lang_FR_CH.py +48 -0
- num2words2/lang_FR_DZ.py +35 -0
- num2words2/lang_GL.py +135 -0
- num2words2/lang_GU.py +172 -0
- num2words2/lang_HA.py +293 -0
- num2words2/lang_HAW.py +144 -0
- num2words2/lang_HE.py +314 -0
- num2words2/lang_HI.py +243 -0
- num2words2/lang_HR.py +304 -0
- num2words2/lang_HT.py +136 -0
- num2words2/lang_HU.py +189 -0
- num2words2/lang_HY.py +364 -0
- num2words2/lang_ID.py +242 -0
- num2words2/lang_IS.py +208 -0
- num2words2/lang_IT.py +265 -0
- num2words2/lang_JA.py +615 -0
- num2words2/lang_JW.py +136 -0
- num2words2/lang_KA.py +169 -0
- num2words2/lang_KK.py +136 -0
- num2words2/lang_KM.py +173 -0
- num2words2/lang_KN.py +182 -0
- num2words2/lang_KO.py +175 -0
- num2words2/lang_KZ.py +161 -0
- num2words2/lang_LA.py +135 -0
- num2words2/lang_LB.py +135 -0
- num2words2/lang_LN.py +136 -0
- num2words2/lang_LO.py +149 -0
- num2words2/lang_LT.py +283 -0
- num2words2/lang_LV.py +266 -0
- num2words2/lang_MG.py +143 -0
- num2words2/lang_MI.py +151 -0
- num2words2/lang_MK.py +136 -0
- num2words2/lang_ML.py +159 -0
- num2words2/lang_MN.py +319 -0
- num2words2/lang_MR.py +187 -0
- num2words2/lang_MS.py +293 -0
- num2words2/lang_MT.py +159 -0
- num2words2/lang_MY.py +152 -0
- num2words2/lang_NE.py +157 -0
- num2words2/lang_NL.py +204 -0
- num2words2/lang_NN.py +136 -0
- num2words2/lang_NO.py +143 -0
- num2words2/lang_OC.py +135 -0
- num2words2/lang_PA.py +159 -0
- num2words2/lang_PL.py +336 -0
- num2words2/lang_PS.py +136 -0
- num2words2/lang_PT.py +280 -0
- num2words2/lang_PT_BR.py +224 -0
- num2words2/lang_RO.py +183 -0
- num2words2/lang_RU.py +570 -0
- num2words2/lang_SA.py +136 -0
- num2words2/lang_SD.py +136 -0
- num2words2/lang_SI.py +152 -0
- num2words2/lang_SK.py +250 -0
- num2words2/lang_SL.py +306 -0
- num2words2/lang_SN.py +447 -0
- num2words2/lang_SO.py +136 -0
- num2words2/lang_SQ.py +252 -0
- num2words2/lang_SR.py +254 -0
- num2words2/lang_SU.py +136 -0
- num2words2/lang_SV.py +169 -0
- num2words2/lang_SW.py +219 -0
- num2words2/lang_TA.py +303 -0
- num2words2/lang_TE.py +169 -0
- num2words2/lang_TET.py +285 -0
- num2words2/lang_TG.py +149 -0
- num2words2/lang_TH.py +214 -0
- num2words2/lang_TK.py +136 -0
- num2words2/lang_TL.py +145 -0
- num2words2/lang_TR.py +882 -0
- num2words2/lang_TT.py +136 -0
- num2words2/lang_UK.py +1101 -0
- num2words2/lang_UR.py +168 -0
- num2words2/lang_UZ.py +136 -0
- num2words2/lang_VI.py +143 -0
- num2words2/lang_WO.py +136 -0
- num2words2/lang_YI.py +135 -0
- num2words2/lang_YO.py +136 -0
- num2words2/lang_ZH.py +296 -0
- num2words2/lang_ZH_CN.py +85 -0
- num2words2/lang_ZH_HK.py +48 -0
- num2words2/lang_ZH_TW.py +198 -0
- num2words2/utils.py +35 -0
- num2words2-0.1.0.dev1.data/scripts/num2words2 +98 -0
- num2words2-0.1.0.dev1.dist-info/METADATA +244 -0
- num2words2-0.1.0.dev1.dist-info/RECORD +133 -0
- num2words2-0.1.0.dev1.dist-info/WHEEL +5 -0
- num2words2-0.1.0.dev1.dist-info/entry_points.txt +2 -0
- num2words2-0.1.0.dev1.dist-info/licenses/COPYING +145 -0
- num2words2-0.1.0.dev1.dist-info/top_level.txt +1 -0
num2words2/lang_FI.py
ADDED
|
@@ -0,0 +1,759 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
|
3
|
+
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
|
4
|
+
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License as published by the Free Software Foundation; either
|
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
12
|
+
# Lesser General Public License for more details.
|
|
13
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
14
|
+
# License along with this library; if not, write to the Free Software
|
|
15
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
16
|
+
# MA 02110-1301 USA
|
|
17
|
+
|
|
18
|
+
from __future__ import division, print_function, unicode_literals
|
|
19
|
+
|
|
20
|
+
from collections import OrderedDict
|
|
21
|
+
|
|
22
|
+
from . import lang_EUR
|
|
23
|
+
|
|
24
|
+
GENERIC_CENTS = ('sentti', 'senttiä')
|
|
25
|
+
GENERIC_CENTAVOS = ('centavo', 'centavoa')
|
|
26
|
+
|
|
27
|
+
# grammatical cases
|
|
28
|
+
NOM = 10 # nominative: the dictionary form
|
|
29
|
+
GEN = 11 # genitive: ~of/'s
|
|
30
|
+
ACC = 12 # accusative: not used; either nominative or genitive
|
|
31
|
+
PTV = 13 # partitive: as an object
|
|
32
|
+
# locative cases (internal)
|
|
33
|
+
INE = 14 # inessive: in
|
|
34
|
+
ELA = 15 # elative: from/out of
|
|
35
|
+
ILL = 16 # illative: into
|
|
36
|
+
# locative cases (external)
|
|
37
|
+
ADE = 17 # adessive: at/on
|
|
38
|
+
ABL = 18 # ablative: from (after being at/on, not in)
|
|
39
|
+
ALL = 19 # allative: to
|
|
40
|
+
# essive
|
|
41
|
+
ESS = 20 # essive: as (in the role of)
|
|
42
|
+
TRANSL = 21 # translative: to (the role of; being sth)
|
|
43
|
+
# rare
|
|
44
|
+
INSTRUC = 22 # instructive: with (plural is the same as singular)
|
|
45
|
+
ABE = 23 # abessive: without
|
|
46
|
+
COM = 24 # comitative: together with (plural = singular)
|
|
47
|
+
|
|
48
|
+
NAME_TO_CASE = {
|
|
49
|
+
'nominative': NOM,
|
|
50
|
+
'genitive': GEN,
|
|
51
|
+
'accusative': ACC,
|
|
52
|
+
'partitive': PTV,
|
|
53
|
+
'inessive': INE,
|
|
54
|
+
'elative': ELA,
|
|
55
|
+
'illative': ILL,
|
|
56
|
+
'adessive': ADE,
|
|
57
|
+
'ablative': ABL,
|
|
58
|
+
'allative': ALL,
|
|
59
|
+
'essive': ESS,
|
|
60
|
+
'translative': TRANSL,
|
|
61
|
+
'instructive': INSTRUC,
|
|
62
|
+
'abessive': ABE,
|
|
63
|
+
'comitative': COM,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# https://en.wikibooks.org/wiki/Finnish/Grammar-Vowel_harmony
|
|
67
|
+
BACK_TO_FRONT = {
|
|
68
|
+
'a': 'ä',
|
|
69
|
+
'o': 'ö',
|
|
70
|
+
'u': 'y',
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# https://en.wiktionary.org/wiki/Appendix:Finnish_nominal_inflection
|
|
74
|
+
# CASE: (SINGULAR_SUFFIX+, PLURAL_SUFFIX+)
|
|
75
|
+
KOTUS_TYPE = {
|
|
76
|
+
|
|
77
|
+
# Kotus type 5/risti, no gradation
|
|
78
|
+
5: {
|
|
79
|
+
# grammatical
|
|
80
|
+
NOM: ('i', 'it'),
|
|
81
|
+
GEN: ('in', 'ien'),
|
|
82
|
+
PTV: ('ia', 'eja'),
|
|
83
|
+
# locative, internal
|
|
84
|
+
INE: ('issa', 'eissa'),
|
|
85
|
+
ELA: ('ista', 'eista'),
|
|
86
|
+
ILL: ('iin', 'eihin'),
|
|
87
|
+
# locative, external
|
|
88
|
+
ADE: ('illa', 'eilla'),
|
|
89
|
+
ABL: ('ilta', 'eilta'),
|
|
90
|
+
ALL: ('ille', 'eille'),
|
|
91
|
+
# essive
|
|
92
|
+
ESS: ('ina', 'eina'),
|
|
93
|
+
TRANSL: ('iksi', 'eiksi'),
|
|
94
|
+
# rare
|
|
95
|
+
INSTRUC: ('ein', 'ein'),
|
|
96
|
+
ABE: ('itta', 'eitta'),
|
|
97
|
+
COM: ('eine', 'eine'), # works better
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
# Kotus type 7/ovi, no gradation
|
|
101
|
+
7: {
|
|
102
|
+
# grammatical
|
|
103
|
+
NOM: ('i', 'et'),
|
|
104
|
+
GEN: ('en', 'ien'),
|
|
105
|
+
PTV: ('ea', 'ia'),
|
|
106
|
+
# locative, internal
|
|
107
|
+
INE: ('essa', 'issa'),
|
|
108
|
+
ELA: ('esta', 'ista'),
|
|
109
|
+
ILL: ('een', 'iin'),
|
|
110
|
+
# locative, external
|
|
111
|
+
ADE: ('ella', 'illa'),
|
|
112
|
+
ABL: ('elta', 'ilta'),
|
|
113
|
+
ALL: ('elle', 'ille'),
|
|
114
|
+
# essive
|
|
115
|
+
ESS: ('ena', 'ina'),
|
|
116
|
+
TRANSL: ('eksi', 'iksi'),
|
|
117
|
+
# rare
|
|
118
|
+
INSTRUC: ('in', 'in'),
|
|
119
|
+
ABE: ('etta', 'itta'),
|
|
120
|
+
COM: ('ine', 'ine'), # works better
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
# Kotus type 8/nalle, no gradation
|
|
124
|
+
8: {
|
|
125
|
+
# grammatical
|
|
126
|
+
NOM: ('e', 'et'),
|
|
127
|
+
GEN: ('en', ('ejen', 'ein')),
|
|
128
|
+
PTV: ('ea', 'eja'),
|
|
129
|
+
# locative, internal
|
|
130
|
+
INE: ('essa', 'eissa'),
|
|
131
|
+
ELA: ('esta', 'eista'),
|
|
132
|
+
ILL: ('een', 'eihin'),
|
|
133
|
+
# locative, external
|
|
134
|
+
ADE: ('ella', 'eilla'),
|
|
135
|
+
ABL: ('elta', 'eilta'),
|
|
136
|
+
ALL: ('elle', 'eille'),
|
|
137
|
+
# essive
|
|
138
|
+
ESS: ('ena', 'eina'),
|
|
139
|
+
TRANSL: ('eksi', 'eiksi'),
|
|
140
|
+
# rare
|
|
141
|
+
INSTRUC: ('ein', 'ein'),
|
|
142
|
+
ABE: ('etta', 'eitta'),
|
|
143
|
+
COM: ('eine', 'eine'), # works better
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
# Kotus type 9/kala, t-d gradation (sata)
|
|
147
|
+
109: {
|
|
148
|
+
# grammatical
|
|
149
|
+
NOM: ('ta', 'dat'),
|
|
150
|
+
GEN: ('dan', ('tojen', 'tain')),
|
|
151
|
+
PTV: ('taa', 'toja'),
|
|
152
|
+
# locative, internal
|
|
153
|
+
INE: ('dassa', 'doissa'),
|
|
154
|
+
ELA: ('dasta', 'doista'),
|
|
155
|
+
ILL: ('taan', 'toihin'),
|
|
156
|
+
# locative, external
|
|
157
|
+
ADE: ('dalla', 'doilla'),
|
|
158
|
+
ABL: ('dalta', 'doilta'),
|
|
159
|
+
ALL: ('dalle', 'doille'),
|
|
160
|
+
# essive
|
|
161
|
+
ESS: ('tana', 'toina'),
|
|
162
|
+
TRANSL: ('daksi', 'doiksi'),
|
|
163
|
+
# rare
|
|
164
|
+
INSTRUC: ('doin', 'doin'),
|
|
165
|
+
ABE: ('datta', 'doitta'),
|
|
166
|
+
COM: ('toine', 'toine'), # works better
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
# Kotus type 10/koira, no gradation
|
|
170
|
+
10: {
|
|
171
|
+
# grammatical
|
|
172
|
+
NOM: ('a', 'at'),
|
|
173
|
+
GEN: ('an', ('ien', 'ain')),
|
|
174
|
+
PTV: ('aa', 'ia'),
|
|
175
|
+
# locative, internal
|
|
176
|
+
INE: ('assa', 'issa'),
|
|
177
|
+
ELA: ('asta', 'ista'),
|
|
178
|
+
ILL: ('aan', 'iin'),
|
|
179
|
+
# locative, external
|
|
180
|
+
ADE: ('alla', 'illa'),
|
|
181
|
+
ABL: ('alta', 'ilta'),
|
|
182
|
+
ALL: ('alle', 'ille'),
|
|
183
|
+
# essive
|
|
184
|
+
ESS: ('ana', 'ina'),
|
|
185
|
+
TRANSL: ('aksi', 'iksi'),
|
|
186
|
+
# rare
|
|
187
|
+
INSTRUC: ('in', 'in'),
|
|
188
|
+
ABE: ('atta', 'itta'),
|
|
189
|
+
COM: ('ine', 'ine'), # works better
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
# Kotus type 27/käsi, t-d gradation
|
|
193
|
+
27: {
|
|
194
|
+
# grammatical
|
|
195
|
+
NOM: ('si', 'det'),
|
|
196
|
+
GEN: ('den', ('sien', 'tten')),
|
|
197
|
+
PTV: ('tta', 'sia'),
|
|
198
|
+
# locative, internal
|
|
199
|
+
INE: ('dessa', 'sissa'),
|
|
200
|
+
ELA: ('desta', 'sista'),
|
|
201
|
+
ILL: ('teen', 'siin'),
|
|
202
|
+
# locative, external
|
|
203
|
+
ADE: ('della', 'silla'),
|
|
204
|
+
ABL: ('delta', 'silta'),
|
|
205
|
+
ALL: ('delle', 'sille'),
|
|
206
|
+
# essive
|
|
207
|
+
ESS: ('tena', 'sina'),
|
|
208
|
+
TRANSL: ('deksi', 'siksi'),
|
|
209
|
+
# rare
|
|
210
|
+
INSTRUC: ('sin', 'sin'),
|
|
211
|
+
ABE: ('detta', 'sitta'),
|
|
212
|
+
COM: ('sine', 'sine'), # works better
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
# Kotus type 31/kaksi, t-d gradation
|
|
216
|
+
31: {
|
|
217
|
+
# grammatical
|
|
218
|
+
NOM: ('ksi', 'hdet'),
|
|
219
|
+
GEN: ('hden', 'ksien'),
|
|
220
|
+
PTV: ('hta', 'ksia'),
|
|
221
|
+
# locative, internal
|
|
222
|
+
INE: ('hdessa', 'ksissa'),
|
|
223
|
+
ELA: ('hdesta', 'ksista'),
|
|
224
|
+
ILL: ('hteen', 'ksiin'),
|
|
225
|
+
# locative, external
|
|
226
|
+
ADE: ('hdella', 'ksilla'),
|
|
227
|
+
ABL: ('hdelta', 'ksilta'),
|
|
228
|
+
ALL: ('hdelle', 'ksille'),
|
|
229
|
+
# essive
|
|
230
|
+
ESS: ('htena', 'ksina'),
|
|
231
|
+
TRANSL: ('hdeksi', 'ksiksi'),
|
|
232
|
+
# rare
|
|
233
|
+
INSTRUC: ('ksin', 'ksin'),
|
|
234
|
+
ABE: ('hdetta', 'ksitta'),
|
|
235
|
+
COM: ('ksine', 'ksine'), # works better
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
# Kotus type 32/sisar, no gradation
|
|
239
|
+
32: {
|
|
240
|
+
# grammatical
|
|
241
|
+
NOM: ('', 'et'),
|
|
242
|
+
GEN: ('en', ('ien', 'ten')),
|
|
243
|
+
PTV: ('ta', 'ia'),
|
|
244
|
+
# locative, internal
|
|
245
|
+
INE: ('essa', 'issa'),
|
|
246
|
+
ELA: ('esta', 'ista'),
|
|
247
|
+
ILL: ('een', 'iin'),
|
|
248
|
+
# locative, external
|
|
249
|
+
ADE: ('ella', 'illa'),
|
|
250
|
+
ABL: ('elta', 'ilta'),
|
|
251
|
+
ALL: ('elle', 'ille'),
|
|
252
|
+
# essive
|
|
253
|
+
ESS: ('ena', 'ina'),
|
|
254
|
+
TRANSL: ('eksi', 'iksi'),
|
|
255
|
+
# rare
|
|
256
|
+
INSTRUC: ('in', 'in'),
|
|
257
|
+
ABE: ('etta', 'itta'),
|
|
258
|
+
COM: ('ine', 'ine'), # works better
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
# Kotus type 38/nainen, no gradation
|
|
262
|
+
38: {
|
|
263
|
+
# grammatical
|
|
264
|
+
NOM: ('nen', 'set'),
|
|
265
|
+
GEN: ('sen', ('sten', 'sien')),
|
|
266
|
+
PTV: ('sta', 'sia'),
|
|
267
|
+
# locative, internal
|
|
268
|
+
INE: ('sessa', 'sissa'),
|
|
269
|
+
ELA: ('sesta', 'sista'),
|
|
270
|
+
ILL: ('seen', 'siin'),
|
|
271
|
+
# locative, external
|
|
272
|
+
ADE: ('sella', 'silla'),
|
|
273
|
+
ABL: ('selta', 'silta'),
|
|
274
|
+
ALL: ('selle', 'sille'),
|
|
275
|
+
# essive
|
|
276
|
+
ESS: ('sena', 'sina'),
|
|
277
|
+
TRANSL: ('seksi', 'siksi'),
|
|
278
|
+
# rare
|
|
279
|
+
INSTRUC: ('sin', 'sin'),
|
|
280
|
+
ABE: ('setta', 'sitta'),
|
|
281
|
+
COM: ('sine', 'sine'), # works better
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
# Kotus type 45/kahdeksas, nt-nn gradation
|
|
285
|
+
45: {
|
|
286
|
+
# grammatical
|
|
287
|
+
NOM: ('s', 'nnet'),
|
|
288
|
+
GEN: ('nnen', 'nsien'),
|
|
289
|
+
PTV: ('tta', 'nsia'),
|
|
290
|
+
# locative, internal
|
|
291
|
+
INE: ('nnessa', 'nsissa'),
|
|
292
|
+
ELA: ('nnesta', 'nsista'),
|
|
293
|
+
ILL: ('nteen', 'nsiin'),
|
|
294
|
+
# locative, external
|
|
295
|
+
ADE: ('nnella', 'nsilla'),
|
|
296
|
+
ABL: ('nnelta', 'nsilta'),
|
|
297
|
+
ALL: ('nnelle', 'nsille'),
|
|
298
|
+
# essive
|
|
299
|
+
ESS: ('ntena', 'nsina'),
|
|
300
|
+
TRANSL: ('nneksi', 'nsiksi'),
|
|
301
|
+
# rare
|
|
302
|
+
INSTRUC: ('nsin', 'nsin'),
|
|
303
|
+
ABE: ('nnetta', 'nsitta'),
|
|
304
|
+
COM: ('nsine', 'nsine'), # works better
|
|
305
|
+
},
|
|
306
|
+
|
|
307
|
+
# Kotus type 46/tuhat, nt-nn gradation
|
|
308
|
+
46: {
|
|
309
|
+
# grammatical
|
|
310
|
+
NOM: ('t', 'nnet'),
|
|
311
|
+
GEN: ('nnen', ('nsien', 'nten')),
|
|
312
|
+
PTV: ('tta', 'nsia'),
|
|
313
|
+
# locative, internal
|
|
314
|
+
INE: ('nnessa', 'nsissa'),
|
|
315
|
+
ELA: ('nnesta', 'nsista'),
|
|
316
|
+
ILL: ('nteen', 'nsiin'),
|
|
317
|
+
# locative, external
|
|
318
|
+
ADE: ('nnella', 'nsilla'),
|
|
319
|
+
ABL: ('nnelta', 'nsilta'),
|
|
320
|
+
ALL: ('nnelle', 'nsille'),
|
|
321
|
+
# essive
|
|
322
|
+
ESS: ('ntena', 'nsina'),
|
|
323
|
+
TRANSL: ('nneksi', 'nsiksi'),
|
|
324
|
+
# rare
|
|
325
|
+
INSTRUC: ('nsin', 'nsin'),
|
|
326
|
+
ABE: ('nnetta', 'nsitta'),
|
|
327
|
+
COM: ('nsine', 'nsine'), # works better
|
|
328
|
+
},
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
# kolme
|
|
332
|
+
KOTUS_TYPE[108] = {
|
|
333
|
+
c: (KOTUS_TYPE[8][c][0], KOTUS_TYPE[7][c][1])
|
|
334
|
+
for c in KOTUS_TYPE[8]
|
|
335
|
+
}
|
|
336
|
+
KOTUS_TYPE[108][INSTRUC] = ('en', 'in')
|
|
337
|
+
KOTUS_TYPE[108][ABE] = ('etta', 'itta')
|
|
338
|
+
KOTUS_TYPE[108][COM] = ('ine', 'ine')
|
|
339
|
+
|
|
340
|
+
# seitsemän, kahdeksan, yhdeksän
|
|
341
|
+
KOTUS_TYPE[110] = KOTUS_TYPE[10].copy()
|
|
342
|
+
KOTUS_TYPE[110][NOM] = ('an', 'at')
|
|
343
|
+
|
|
344
|
+
# kymmenen
|
|
345
|
+
KOTUS_TYPE[132] = KOTUS_TYPE[32].copy()
|
|
346
|
+
KOTUS_TYPE[132][NOM] = ('en', 'et')
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def inflect(parts, options):
|
|
350
|
+
if not isinstance(parts, list):
|
|
351
|
+
parts = [parts]
|
|
352
|
+
|
|
353
|
+
out = ''
|
|
354
|
+
for part in parts:
|
|
355
|
+
# part is plain text, concat and continue
|
|
356
|
+
if not isinstance(part, tuple):
|
|
357
|
+
out += part
|
|
358
|
+
continue
|
|
359
|
+
# predefined case (kaksikymmentä, ...)
|
|
360
|
+
tmp_case = options.case
|
|
361
|
+
if len(part) == 3:
|
|
362
|
+
# override singular nominative only
|
|
363
|
+
if options.case == NOM and not options.plural:
|
|
364
|
+
tmp_case = part[2]
|
|
365
|
+
part = part[:2]
|
|
366
|
+
# stem and suffix
|
|
367
|
+
stem, kotus_type = part
|
|
368
|
+
suffix = KOTUS_TYPE[kotus_type][tmp_case][options.plural]
|
|
369
|
+
# many choices, choose preferred or first
|
|
370
|
+
if isinstance(suffix, tuple):
|
|
371
|
+
common = set(suffix) & set(options.prefer or set())
|
|
372
|
+
if len(common) == 1:
|
|
373
|
+
suffix = common.pop()
|
|
374
|
+
else:
|
|
375
|
+
suffix = suffix[0]
|
|
376
|
+
# apply vowel harmony
|
|
377
|
+
if not set(BACK_TO_FRONT) & set(stem):
|
|
378
|
+
for back, front in BACK_TO_FRONT.items():
|
|
379
|
+
suffix = suffix.replace(back, front)
|
|
380
|
+
# concat
|
|
381
|
+
out += stem + suffix
|
|
382
|
+
|
|
383
|
+
return out
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
class Options(object):
|
|
387
|
+
def __init__(self, ordinal, case, plural, prefer):
|
|
388
|
+
self.ordinal = ordinal
|
|
389
|
+
self.case = case
|
|
390
|
+
self.plural = plural
|
|
391
|
+
self.prefer = prefer
|
|
392
|
+
|
|
393
|
+
def variation(self, ordinal=None, case=None, plural=None, prefer=None):
|
|
394
|
+
return Options(
|
|
395
|
+
ordinal if ordinal is not None else self.ordinal,
|
|
396
|
+
case if case is not None else self.case,
|
|
397
|
+
plural if plural is not None else self.plural,
|
|
398
|
+
prefer if prefer is not None else self.prefer,
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
class Num2Word_FI(lang_EUR.Num2Word_EUR):
|
|
403
|
+
CURRENCY_FORMS = {
|
|
404
|
+
'BRL': (('real', 'realia'), GENERIC_CENTAVOS),
|
|
405
|
+
'CHF': (('frangi', 'frangia'), ('rappen', 'rappenia')),
|
|
406
|
+
'CNY': (('juan', 'juania'), ('fen', 'feniä')),
|
|
407
|
+
'EUR': (('euro', 'euroa'), GENERIC_CENTS),
|
|
408
|
+
'FIM': (('markka', 'markkaa'), ('penni', 'penniä')), # historical
|
|
409
|
+
'INR': (('rupia', 'rupiaa'), ('paisa', 'paisaa')),
|
|
410
|
+
'JPY': (('jeni', 'jeniä'), ('sen', 'seniä')), # rare subunit
|
|
411
|
+
'KRW': (('won', 'wonia'), ('jeon', 'jeonia')), # rare subunit
|
|
412
|
+
'KPW': (('won', 'wonia'), ('chon', 'chonia')), # rare subunit
|
|
413
|
+
'MXN': (('peso', 'pesoa'), GENERIC_CENTAVOS),
|
|
414
|
+
'RUB': (('rupla', 'ruplaa'), ('kopeekka', 'kopeekkaa')),
|
|
415
|
+
'TRY': (('liira', 'liiraa'), ('kuruş', 'kuruşia')),
|
|
416
|
+
'ZAR': (('randi', 'randia'), GENERIC_CENTS),
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
# crowns
|
|
420
|
+
for curr_code in 'DKK', 'ISK', 'NOK', 'SEK':
|
|
421
|
+
CURRENCY_FORMS[curr_code] = (('kruunu', 'kruunua'), ('äyri', 'äyriä'))
|
|
422
|
+
|
|
423
|
+
# dollars
|
|
424
|
+
for curr_code in 'AUD', 'CAD', 'HKD', 'NZD', 'SGD', 'USD':
|
|
425
|
+
CURRENCY_FORMS[curr_code] = (
|
|
426
|
+
('dollari', 'dollaria'), GENERIC_CENTS)
|
|
427
|
+
|
|
428
|
+
# pounds
|
|
429
|
+
for curr_code in ('GBP',):
|
|
430
|
+
CURRENCY_FORMS[curr_code] = (('punta', 'puntaa'), ('penny', 'pennyä'))
|
|
431
|
+
|
|
432
|
+
CURRENCY_ADJECTIVES = {
|
|
433
|
+
'AUD': 'Australian',
|
|
434
|
+
'BRL': 'Brasilian',
|
|
435
|
+
'CAD': 'Kanadan',
|
|
436
|
+
'CHF': 'Sveitsin',
|
|
437
|
+
'DKK': 'Tanskan',
|
|
438
|
+
'FIM': 'Suomen', # historical
|
|
439
|
+
'GBP': 'Englannin',
|
|
440
|
+
'HKD': 'Hongkongin',
|
|
441
|
+
'INR': 'Intian',
|
|
442
|
+
'ISK': 'Islannin',
|
|
443
|
+
'KRW': 'Etelä-Korean',
|
|
444
|
+
'KPW': 'Pohjois-Korean',
|
|
445
|
+
'MXN': 'Meksikon',
|
|
446
|
+
'NOK': 'Norjan',
|
|
447
|
+
'NZD': 'Uuden-Seelannin',
|
|
448
|
+
'RUB': 'Venäjän',
|
|
449
|
+
'SEK': 'Ruotsin',
|
|
450
|
+
'SGD': 'Singaporen',
|
|
451
|
+
'TRY': 'Turkin',
|
|
452
|
+
'USD': 'Yhdysvaltain',
|
|
453
|
+
'ZAR': 'Etelä-Afrikan',
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
def __init__(self):
|
|
457
|
+
self.ords = OrderedDict()
|
|
458
|
+
super(Num2Word_FI, self).__init__()
|
|
459
|
+
|
|
460
|
+
def set_numwords(self):
|
|
461
|
+
self.set_high_numwords(self.high_numwords)
|
|
462
|
+
self.set_mid_numwords(self.mid_numwords, self.mid_ords)
|
|
463
|
+
self.set_low_numwords(self.low_numwords, self.low_ords)
|
|
464
|
+
|
|
465
|
+
def set_high_numwords(self, high):
|
|
466
|
+
# references:
|
|
467
|
+
# https://fi.wikipedia.org/wiki/Suurten_lukujen_nimet
|
|
468
|
+
# https://en.wikipedia.org/wiki/Names_of_large_numbers#Standard_dictionary_numbers
|
|
469
|
+
|
|
470
|
+
# translate to Finnish
|
|
471
|
+
replacements = [
|
|
472
|
+
("qu", "kv"),
|
|
473
|
+
("x", "ks"),
|
|
474
|
+
("c", "k"),
|
|
475
|
+
("kent", "sent"), # applied after c -> k to cent
|
|
476
|
+
]
|
|
477
|
+
translated = []
|
|
478
|
+
for i, numword in enumerate(high):
|
|
479
|
+
# notes:
|
|
480
|
+
# - 1e6**9 can be either noviljoona or noniljoona
|
|
481
|
+
# - 1e6**38 and above are untested
|
|
482
|
+
|
|
483
|
+
# 1e6**6 is sekstiljoona but 1e6**16 is sedekiljoona
|
|
484
|
+
if numword.startswith("sex") and numword != "sext":
|
|
485
|
+
numword = numword.replace("sex", "se")
|
|
486
|
+
# 1e6**7 is septiljoona but 1e6**17 is septendekiljoona
|
|
487
|
+
elif numword.startswith("sept") and numword != "sept":
|
|
488
|
+
numword = "septen" + numword[len("sept"):]
|
|
489
|
+
# 1e6**8 is oktiljoona but 1e6**18 is duodevigintiljoona
|
|
490
|
+
# (2 from 20)
|
|
491
|
+
elif numword.startswith("octo"):
|
|
492
|
+
numword = high[i + -10]
|
|
493
|
+
numword = "duode" + numword[len("octo"):]
|
|
494
|
+
# 1e6**9 is noniljoona but 1e6**19 is undevigintiljoona (1 from 20)
|
|
495
|
+
elif numword.startswith("nove"):
|
|
496
|
+
numword = high[i + -10]
|
|
497
|
+
numword = "unde" + numword[len("nove") + 1:]
|
|
498
|
+
|
|
499
|
+
# apply general replacements to all numwords
|
|
500
|
+
for repl in replacements:
|
|
501
|
+
numword = numword.replace(repl[0], repl[1])
|
|
502
|
+
translated.append(numword)
|
|
503
|
+
|
|
504
|
+
max = 6 * len(translated)
|
|
505
|
+
for word, n in zip(translated, range(max, 0, -6)):
|
|
506
|
+
if n == 6:
|
|
507
|
+
# irregularity considering short scale and long scale
|
|
508
|
+
self.cards[10 ** 9] = ("miljard", 5)
|
|
509
|
+
self.ords[10 ** 9] = ("miljardi", 45)
|
|
510
|
+
self.cards[10 ** n] = (word + "iljoon", 10)
|
|
511
|
+
self.ords[10 ** n] = (word + "iljoona", 45)
|
|
512
|
+
|
|
513
|
+
def set_mid_numwords(self, cards, ords):
|
|
514
|
+
for key, val in cards:
|
|
515
|
+
self.cards[key] = val
|
|
516
|
+
for key, val in ords:
|
|
517
|
+
self.ords[key] = val
|
|
518
|
+
|
|
519
|
+
def set_low_numwords(self, cards, ords):
|
|
520
|
+
for key, val in cards:
|
|
521
|
+
self.cards[key] = val
|
|
522
|
+
for key, val in ords:
|
|
523
|
+
self.ords[key] = val
|
|
524
|
+
|
|
525
|
+
def setup(self):
|
|
526
|
+
super(Num2Word_FI, self).setup()
|
|
527
|
+
|
|
528
|
+
self.negword = "miinus "
|
|
529
|
+
self.pointword = "pilkku"
|
|
530
|
+
self.exclude_title = ["pilkku", "miinus"]
|
|
531
|
+
|
|
532
|
+
self.mid_numwords = [
|
|
533
|
+
(1000, ("tuha", 46)),
|
|
534
|
+
(100, ("sa", 109)),
|
|
535
|
+
(90, [("yhdeks", 110), ("kymmen", 132, PTV)]),
|
|
536
|
+
(80, [("kahdeks", 110), ("kymmen", 132, PTV)]),
|
|
537
|
+
(70, [("seitsem", 110), ("kymmen", 132, PTV)]),
|
|
538
|
+
(60, [("kuu", 27), ("kymmen", 132, PTV)]),
|
|
539
|
+
(50, [("vii", 27), ("kymmen", 132, PTV)]),
|
|
540
|
+
(40, [("nelj", 10), ("kymmen", 132, PTV)]),
|
|
541
|
+
(30, [("kolm", 108), ("kymmen", 132, PTV)]),
|
|
542
|
+
]
|
|
543
|
+
|
|
544
|
+
self.mid_ords = [
|
|
545
|
+
(1000, ("tuhanne", 45)),
|
|
546
|
+
(100, ("sada", 45)),
|
|
547
|
+
(90, [("yhdeksä", 45), ("kymmene", 45)]),
|
|
548
|
+
(80, [("kahdeksa", 45), ("kymmene", 45)]),
|
|
549
|
+
(70, [("seitsemä", 45), ("kymmene", 45)]),
|
|
550
|
+
(60, [("kuude", 45), ("kymmene", 45)]),
|
|
551
|
+
(50, [("viide", 45), ("kymmene", 45)]),
|
|
552
|
+
(40, [("neljä", 45), ("kymmene", 45)]),
|
|
553
|
+
(30, [("kolma", 45), ("kymmene", 45)]),
|
|
554
|
+
]
|
|
555
|
+
|
|
556
|
+
self.low_numwords = [
|
|
557
|
+
(20, [("ka", 31), ("kymmen", 132, PTV)]),
|
|
558
|
+
(19, [("yhdeks", 110), "toista"]),
|
|
559
|
+
(18, [("kahdeks", 110), "toista"]),
|
|
560
|
+
(17, [("seitsem", 110), "toista"]),
|
|
561
|
+
(16, [("kuu", 27), "toista"]),
|
|
562
|
+
(15, [("vii", 27), "toista"]),
|
|
563
|
+
(14, [("nelj", 10), "toista"]),
|
|
564
|
+
(13, [("kolm", 108), "toista"]),
|
|
565
|
+
(12, [("ka", 31), "toista"]),
|
|
566
|
+
(11, [("y", 31), "toista"]),
|
|
567
|
+
(10, ("kymmen", 132)),
|
|
568
|
+
(9, ("yhdeks", 110)),
|
|
569
|
+
(8, ("kahdeks", 110)),
|
|
570
|
+
(7, ("seitsem", 110)),
|
|
571
|
+
(6, ("kuu", 27)),
|
|
572
|
+
(5, ("vii", 27)),
|
|
573
|
+
(4, ("nelj", 10)),
|
|
574
|
+
(3, ("kolm", 108)),
|
|
575
|
+
(2, ("ka", 31)),
|
|
576
|
+
(1, ("y", 31)),
|
|
577
|
+
(0, ("noll", 10)),
|
|
578
|
+
]
|
|
579
|
+
|
|
580
|
+
self.low_ords = [
|
|
581
|
+
(20, [("kahde", 45), ("kymmene", 45)]),
|
|
582
|
+
(19, [("yhdeksä", 45), "toista"]),
|
|
583
|
+
(18, [("kahdeksa", 45), "toista"]),
|
|
584
|
+
(17, [("seitsemä", 45), "toista"]),
|
|
585
|
+
(16, [("kuude", 45), "toista"]),
|
|
586
|
+
(15, [("viide", 45), "toista"]),
|
|
587
|
+
(14, [("neljä", 45), "toista"]),
|
|
588
|
+
(13, [("kolma", 45), "toista"]),
|
|
589
|
+
(12, [("kahde", 45), "toista"]),
|
|
590
|
+
(11, [("yhde", 45), "toista"]),
|
|
591
|
+
(10, ("kymmene", 45)),
|
|
592
|
+
(9, ("yhdeksä", 45)),
|
|
593
|
+
(8, ("kahdeksa", 45)),
|
|
594
|
+
(7, ("seitsemä", 45)),
|
|
595
|
+
(6, ("kuude", 45)),
|
|
596
|
+
(5, ("viide", 45)),
|
|
597
|
+
(4, ("neljä", 45)),
|
|
598
|
+
(3, ("kolma", 45)),
|
|
599
|
+
(2, ("toi", 38)),
|
|
600
|
+
(1, ("ensimmäi", 38)),
|
|
601
|
+
(0, ("nolla", 45)),
|
|
602
|
+
]
|
|
603
|
+
|
|
604
|
+
def merge(self, lpair, rpair, options):
|
|
605
|
+
ltext, lnum = lpair
|
|
606
|
+
rtext, rnum = rpair
|
|
607
|
+
|
|
608
|
+
# http://www.kielitoimistonohjepankki.fi/ohje/49
|
|
609
|
+
fmt = "%s%s"
|
|
610
|
+
# ignore lpair if lnum is 1
|
|
611
|
+
if lnum == 1:
|
|
612
|
+
rtext = inflect(rtext, options)
|
|
613
|
+
return (rtext, rnum)
|
|
614
|
+
# rnum is added to lnum
|
|
615
|
+
elif lnum > rnum:
|
|
616
|
+
ltext = inflect(ltext, options)
|
|
617
|
+
rtext = inflect(rtext, options)
|
|
618
|
+
# separate groups with space
|
|
619
|
+
if lnum >= 1000:
|
|
620
|
+
fmt = "%s %s"
|
|
621
|
+
return (fmt % (ltext, rtext), lnum + rnum)
|
|
622
|
+
# rnum is multiplied by lnum
|
|
623
|
+
elif lnum < rnum:
|
|
624
|
+
if options.ordinal:
|
|
625
|
+
# kahdessadas, not toinensadas
|
|
626
|
+
if lnum == 2:
|
|
627
|
+
ltext = ("kahde", 45)
|
|
628
|
+
rtext = inflect(rtext, options)
|
|
629
|
+
else:
|
|
630
|
+
# kaksituhatta but kahdettuhannet
|
|
631
|
+
rcase = options.case
|
|
632
|
+
if options.case == NOM and not options.plural:
|
|
633
|
+
rcase = PTV
|
|
634
|
+
rtext = inflect(rtext, options.variation(case=rcase))
|
|
635
|
+
ltext = inflect(ltext, options)
|
|
636
|
+
return (fmt % (ltext, rtext), lnum * rnum)
|
|
637
|
+
|
|
638
|
+
def to_cardinal(self, value, case='nominative', plural=False, prefer=None):
|
|
639
|
+
case = NAME_TO_CASE[case]
|
|
640
|
+
options = Options(False, case, plural, prefer)
|
|
641
|
+
try:
|
|
642
|
+
assert int(value) == value
|
|
643
|
+
except (ValueError, TypeError, AssertionError):
|
|
644
|
+
if case != NOM:
|
|
645
|
+
raise NotImplementedError(
|
|
646
|
+
"Cases other than nominative are not implemented for "
|
|
647
|
+
"cardinal floating point numbers.")
|
|
648
|
+
return self.to_cardinal_float(value)
|
|
649
|
+
|
|
650
|
+
out = ""
|
|
651
|
+
if value < 0:
|
|
652
|
+
value = abs(value)
|
|
653
|
+
out = self.negword
|
|
654
|
+
|
|
655
|
+
if value >= self.MAXVAL:
|
|
656
|
+
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
|
657
|
+
|
|
658
|
+
val = self.splitnum(value, options)
|
|
659
|
+
words, num = self.clean(val, options)
|
|
660
|
+
return self.title(out + words)
|
|
661
|
+
|
|
662
|
+
def to_ordinal(self, value, case='nominative', plural=False, prefer=None):
|
|
663
|
+
case = NAME_TO_CASE[case]
|
|
664
|
+
options = Options(True, case, plural, prefer)
|
|
665
|
+
|
|
666
|
+
self.verify_ordinal(value)
|
|
667
|
+
if value >= self.MAXVAL:
|
|
668
|
+
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
|
669
|
+
|
|
670
|
+
val = self.splitnum(value, options)
|
|
671
|
+
words, num = self.clean(val, options)
|
|
672
|
+
return self.title(words)
|
|
673
|
+
|
|
674
|
+
def to_ordinal_num(self, value, case='nominative', plural=False):
|
|
675
|
+
"""Convert to abbreviated ordinal form (1., 2., 3. etc)"""
|
|
676
|
+
return str(value) + '.'
|
|
677
|
+
|
|
678
|
+
def to_year(self, val, suffix=None, longval=True):
|
|
679
|
+
suffix = suffix or ""
|
|
680
|
+
if val < 0:
|
|
681
|
+
val = abs(val)
|
|
682
|
+
suffix = suffix or " ennen ajanlaskun alkua"
|
|
683
|
+
return self.to_cardinal(val).replace(" ", "") + suffix
|
|
684
|
+
|
|
685
|
+
def to_currency(self, val, currency="EUR", cents=True, separator=" ja",
|
|
686
|
+
adjective=False):
|
|
687
|
+
# Handle integers specially - just add currency name without cents
|
|
688
|
+
if isinstance(val, int):
|
|
689
|
+
try:
|
|
690
|
+
cr1, cr2 = self.CURRENCY_FORMS[currency]
|
|
691
|
+
except (KeyError, AttributeError):
|
|
692
|
+
# Fallback to base implementation for unknown currency
|
|
693
|
+
return super(Num2Word_FI, self).to_currency(
|
|
694
|
+
val, currency=currency, cents=cents, separator=separator,
|
|
695
|
+
adjective=adjective)
|
|
696
|
+
|
|
697
|
+
minus_str = self.negword if val < 0 else ""
|
|
698
|
+
abs_val = abs(val)
|
|
699
|
+
money_str = self.to_cardinal(abs_val)
|
|
700
|
+
|
|
701
|
+
# Proper pluralization for currency
|
|
702
|
+
if abs_val == 1:
|
|
703
|
+
currency_str = cr1[0] if isinstance(cr1, tuple) else cr1
|
|
704
|
+
else:
|
|
705
|
+
currency_str = cr1[1] if isinstance(cr1, tuple) and len(cr1) > 1 else (cr1[0] if isinstance(cr1, tuple) else cr1)
|
|
706
|
+
|
|
707
|
+
return (u'%s %s %s' % (minus_str, money_str, currency_str)).strip()
|
|
708
|
+
|
|
709
|
+
# For floats, use the parent class implementation
|
|
710
|
+
return super(Num2Word_FI, self).to_currency(
|
|
711
|
+
val, currency=currency, cents=cents, separator=separator,
|
|
712
|
+
adjective=adjective)
|
|
713
|
+
|
|
714
|
+
def splitnum(self, value, options):
|
|
715
|
+
elems = self.ords if options.ordinal else self.cards
|
|
716
|
+
for elem in elems:
|
|
717
|
+
if elem > value:
|
|
718
|
+
continue
|
|
719
|
+
|
|
720
|
+
out = []
|
|
721
|
+
if value == 0:
|
|
722
|
+
div, mod = 1, 0
|
|
723
|
+
else:
|
|
724
|
+
div, mod = divmod(value, elem)
|
|
725
|
+
|
|
726
|
+
if div == 1:
|
|
727
|
+
out.append((elems[1], 1))
|
|
728
|
+
else:
|
|
729
|
+
if div == value: # The system tallies, eg Roman Numerals
|
|
730
|
+
return [(div * elems[elem], div * elem)]
|
|
731
|
+
out.append(self.splitnum(div, options))
|
|
732
|
+
|
|
733
|
+
out.append((elems[elem], elem))
|
|
734
|
+
|
|
735
|
+
if mod:
|
|
736
|
+
out.append(self.splitnum(mod, options))
|
|
737
|
+
|
|
738
|
+
return out
|
|
739
|
+
|
|
740
|
+
def clean(self, val, options):
|
|
741
|
+
out = val
|
|
742
|
+
while len(val) != 1:
|
|
743
|
+
out = []
|
|
744
|
+
left, right = val[:2]
|
|
745
|
+
if isinstance(left, tuple) and isinstance(right, tuple):
|
|
746
|
+
out.append(self.merge(left, right, options))
|
|
747
|
+
if val[2:]:
|
|
748
|
+
out.append(val[2:])
|
|
749
|
+
else:
|
|
750
|
+
for elem in val:
|
|
751
|
+
if isinstance(elem, list):
|
|
752
|
+
if len(elem) == 1:
|
|
753
|
+
out.append(elem[0])
|
|
754
|
+
else:
|
|
755
|
+
out.append(self.clean(elem, options))
|
|
756
|
+
else:
|
|
757
|
+
out.append(elem)
|
|
758
|
+
val = out
|
|
759
|
+
return out[0]
|