python-iso639 2025.2.8__tar.gz → 2025.11.11__tar.gz
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.
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/CHANGELOG.md +21 -1
- {python_iso639-2025.2.8/src/python_iso639.egg-info → python_iso639-2025.11.11}/PKG-INFO +33 -17
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/README.md +21 -6
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/pyproject.toml +10 -10
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/iso639/__init__.py +1 -1
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/iso639/_data/__init__.py +16 -18
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/iso639/_data/iso-639-3.tab +14 -11
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/iso639/_data/iso-639-3_Name_Index.tab +27 -5
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/iso639/_data/iso-639-3_Retirements.tab +20 -22
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/iso639/language.py +93 -39
- {python_iso639-2025.2.8 → python_iso639-2025.11.11/src/python_iso639.egg-info}/PKG-INFO +33 -17
- python_iso639-2025.11.11/src/python_iso639.egg-info/requires.txt +9 -0
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/tests/test_language.py +53 -7
- python_iso639-2025.2.8/src/python_iso639.egg-info/requires.txt +0 -9
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/LICENSE.txt +0 -0
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/MANIFEST.in +0 -0
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/setup.cfg +0 -0
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/iso639/_data/iso-639-3-macrolanguages.tab +0 -0
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/iso639/py.typed +0 -0
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/python_iso639.egg-info/SOURCES.txt +0 -0
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/python_iso639.egg-info/dependency_links.txt +0 -0
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/python_iso639.egg-info/not-zip-safe +0 -0
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/python_iso639.egg-info/top_level.txt +0 -0
- {python_iso639-2025.2.8 → python_iso639-2025.11.11}/tests/test_version_number.py +0 -0
|
@@ -17,10 +17,30 @@ major/minor/micro version numbers like `05` (it'd have to be just `5`).
|
|
|
17
17
|
### Fixed
|
|
18
18
|
### Security
|
|
19
19
|
|
|
20
|
+
## [2025.11.11]
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
* Added support for Python 3.14.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
* Updated the ISO 639 data from SIL to the latest 2025-10-15 release.
|
|
27
|
+
* Case-insensitive matching for `Language.match` is now opt-in.
|
|
28
|
+
The keyword argument has been renamed `strict_case` (from `exact` before),
|
|
29
|
+
defaulting to `True`.
|
|
30
|
+
|
|
31
|
+
### Removed
|
|
32
|
+
* Dropped support for Python 3.9.
|
|
33
|
+
|
|
34
|
+
## [2025.2.18]
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
* `Language.match` now supports case-insensitive matching
|
|
38
|
+
and ignores leading/trailing whitespace by default.
|
|
39
|
+
|
|
20
40
|
## [2025.2.8]
|
|
21
41
|
|
|
22
42
|
### Added
|
|
23
|
-
*
|
|
43
|
+
* Explicitly indicated that the library is type-annotated.
|
|
24
44
|
|
|
25
45
|
## [2025.1.28]
|
|
26
46
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: python-iso639
|
|
3
|
-
Version: 2025.
|
|
3
|
+
Version: 2025.11.11
|
|
4
4
|
Summary: ISO 639 language codes, names, and other associated information
|
|
5
5
|
Author-email: "Jackson L. Lee" <jacksonlunlee@gmail.com>
|
|
6
6
|
License: Apache 2.0
|
|
@@ -15,26 +15,27 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
15
15
|
Classifier: Operating System :: OS Independent
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
17
17
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
21
|
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
23
|
Classifier: Topic :: Text Processing
|
|
24
24
|
Classifier: Topic :: Text Processing :: General
|
|
25
25
|
Classifier: Topic :: Text Processing :: Indexing
|
|
26
26
|
Classifier: Topic :: Text Processing :: Linguistic
|
|
27
|
-
Requires-Python: >=3.
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
28
|
Description-Content-Type: text/markdown
|
|
29
29
|
License-File: LICENSE.txt
|
|
30
30
|
Provides-Extra: dev
|
|
31
|
-
Requires-Dist: black==25.
|
|
32
|
-
Requires-Dist: build==1.
|
|
33
|
-
Requires-Dist: flake8==7.
|
|
34
|
-
Requires-Dist: mypy==1.
|
|
35
|
-
Requires-Dist: pytest==
|
|
36
|
-
Requires-Dist: requests==2.32.
|
|
37
|
-
Requires-Dist: twine==6.
|
|
31
|
+
Requires-Dist: black==25.11.0; extra == "dev"
|
|
32
|
+
Requires-Dist: build==1.3.0; extra == "dev"
|
|
33
|
+
Requires-Dist: flake8==7.3.0; extra == "dev"
|
|
34
|
+
Requires-Dist: mypy==1.18.2; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest==9.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: requests==2.32.5; extra == "dev"
|
|
37
|
+
Requires-Dist: twine==6.2.0; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
38
39
|
|
|
39
40
|
# python-iso639
|
|
40
41
|
|
|
@@ -83,13 +84,13 @@ Create a `Language` instance by one of the class methods.
|
|
|
83
84
|
Language(part3='fra', part2b='fre', part2t='fra', part1='fr', scope='I', type='L', name='French', comment=None, other_names=None, macrolanguage=None, retire_reason=None, retire_change_to=None, retire_remedy=None, retire_date=None)
|
|
84
85
|
```
|
|
85
86
|
|
|
86
|
-
Fast object instantiation for retrieving language information (run on Python 3.13, macOS 15.
|
|
87
|
+
Fast object instantiation for retrieving language information (run on Python 3.13, macOS 15.3.1, Apple M1 Pro)
|
|
87
88
|
|
|
88
89
|
```python
|
|
89
90
|
In [1]: import iso639
|
|
90
91
|
|
|
91
92
|
In [2]: %timeit iso639.Language.from_part3("fra")
|
|
92
|
-
|
|
93
|
+
217 ns ± 0.139 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
|
|
93
94
|
```
|
|
94
95
|
|
|
95
96
|
#### From Another ISO 639 Code Set or a Reference Name
|
|
@@ -154,11 +155,27 @@ Use the `match` classmethod:
|
|
|
154
155
|
True
|
|
155
156
|
```
|
|
156
157
|
|
|
158
|
+
By default, the classmethod `match` supports case-insensitive matching
|
|
159
|
+
and ignores leading/trailing whitespace.
|
|
160
|
+
To enforce exact matching instead, pass in `exact=True`:
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
>>> lang5 = iso639.Language.match('FRA')
|
|
164
|
+
>>> lang6 = iso639.Language.match('fra ')
|
|
165
|
+
>>> lang7 = iso639.Language.match('french')
|
|
166
|
+
>>> lang4 == lang5 == lang6 == lang7
|
|
167
|
+
True
|
|
168
|
+
>>> iso639.Language.match("french", exact=True)
|
|
169
|
+
Traceback (most recent call last):
|
|
170
|
+
File "<stdin>", line 1, in <module>
|
|
171
|
+
LanguageNotFoundError: 'french' isn't an ISO language code or name
|
|
172
|
+
```
|
|
173
|
+
|
|
157
174
|
The classmethod `match` is particularly useful for consistently
|
|
158
175
|
accessing a specific attribute from unknown inputs, e.g., the ISO 639-3 code.
|
|
159
176
|
|
|
160
177
|
```python
|
|
161
|
-
>>> 'fra' == lang1.part3 == lang2.part3 == lang3.part3 == lang4.part3
|
|
178
|
+
>>> 'fra' == lang1.part3 == lang2.part3 == lang3.part3 == lang4.part3 == lang5.part3 == lang6.part3 == lang7.part3
|
|
162
179
|
True
|
|
163
180
|
```
|
|
164
181
|
|
|
@@ -261,7 +278,6 @@ Beyond that, the precise order in matching is as follows:
|
|
|
261
278
|
* ISO 639-3 alternative language names (the "print" ones)
|
|
262
279
|
* ISO 639-3 alternative language names (the "inverted" ones)
|
|
263
280
|
|
|
264
|
-
Only exact matching is done (there's no fuzzy string matching of any sort).
|
|
265
281
|
As soon as a match is found, `Language.match` returns a `Language` instance.
|
|
266
282
|
If there isn't a match, a `LanguageNotFoundError` is raised.
|
|
267
283
|
|
|
@@ -287,7 +303,7 @@ e.g., [`dataclasses.asdict`](https://docs.python.org/3/library/dataclasses.html#
|
|
|
287
303
|
```python
|
|
288
304
|
>>> import iso639
|
|
289
305
|
>>> iso639.DATA_LAST_UPDATED
|
|
290
|
-
datetime.date(2025,
|
|
306
|
+
datetime.date(2025, 10, 15)
|
|
291
307
|
```
|
|
292
308
|
|
|
293
309
|
* `ALL_LANGUAGES`: The list of all `Language` objects based on the included language code data
|
|
@@ -297,7 +313,7 @@ e.g., [`dataclasses.asdict`](https://docs.python.org/3/library/dataclasses.html#
|
|
|
297
313
|
>>> type(iso639.ALL_LANGUAGES)
|
|
298
314
|
<class 'set'>
|
|
299
315
|
>>> len(iso639.ALL_LANGUAGES)
|
|
300
|
-
|
|
316
|
+
8311
|
|
301
317
|
```
|
|
302
318
|
|
|
303
319
|
## Links
|
|
@@ -45,13 +45,13 @@ Create a `Language` instance by one of the class methods.
|
|
|
45
45
|
Language(part3='fra', part2b='fre', part2t='fra', part1='fr', scope='I', type='L', name='French', comment=None, other_names=None, macrolanguage=None, retire_reason=None, retire_change_to=None, retire_remedy=None, retire_date=None)
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
Fast object instantiation for retrieving language information (run on Python 3.13, macOS 15.
|
|
48
|
+
Fast object instantiation for retrieving language information (run on Python 3.13, macOS 15.3.1, Apple M1 Pro)
|
|
49
49
|
|
|
50
50
|
```python
|
|
51
51
|
In [1]: import iso639
|
|
52
52
|
|
|
53
53
|
In [2]: %timeit iso639.Language.from_part3("fra")
|
|
54
|
-
|
|
54
|
+
217 ns ± 0.139 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
#### From Another ISO 639 Code Set or a Reference Name
|
|
@@ -116,11 +116,27 @@ Use the `match` classmethod:
|
|
|
116
116
|
True
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
By default, the classmethod `match` supports case-insensitive matching
|
|
120
|
+
and ignores leading/trailing whitespace.
|
|
121
|
+
To enforce exact matching instead, pass in `exact=True`:
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
>>> lang5 = iso639.Language.match('FRA')
|
|
125
|
+
>>> lang6 = iso639.Language.match('fra ')
|
|
126
|
+
>>> lang7 = iso639.Language.match('french')
|
|
127
|
+
>>> lang4 == lang5 == lang6 == lang7
|
|
128
|
+
True
|
|
129
|
+
>>> iso639.Language.match("french", exact=True)
|
|
130
|
+
Traceback (most recent call last):
|
|
131
|
+
File "<stdin>", line 1, in <module>
|
|
132
|
+
LanguageNotFoundError: 'french' isn't an ISO language code or name
|
|
133
|
+
```
|
|
134
|
+
|
|
119
135
|
The classmethod `match` is particularly useful for consistently
|
|
120
136
|
accessing a specific attribute from unknown inputs, e.g., the ISO 639-3 code.
|
|
121
137
|
|
|
122
138
|
```python
|
|
123
|
-
>>> 'fra' == lang1.part3 == lang2.part3 == lang3.part3 == lang4.part3
|
|
139
|
+
>>> 'fra' == lang1.part3 == lang2.part3 == lang3.part3 == lang4.part3 == lang5.part3 == lang6.part3 == lang7.part3
|
|
124
140
|
True
|
|
125
141
|
```
|
|
126
142
|
|
|
@@ -223,7 +239,6 @@ Beyond that, the precise order in matching is as follows:
|
|
|
223
239
|
* ISO 639-3 alternative language names (the "print" ones)
|
|
224
240
|
* ISO 639-3 alternative language names (the "inverted" ones)
|
|
225
241
|
|
|
226
|
-
Only exact matching is done (there's no fuzzy string matching of any sort).
|
|
227
242
|
As soon as a match is found, `Language.match` returns a `Language` instance.
|
|
228
243
|
If there isn't a match, a `LanguageNotFoundError` is raised.
|
|
229
244
|
|
|
@@ -249,7 +264,7 @@ e.g., [`dataclasses.asdict`](https://docs.python.org/3/library/dataclasses.html#
|
|
|
249
264
|
```python
|
|
250
265
|
>>> import iso639
|
|
251
266
|
>>> iso639.DATA_LAST_UPDATED
|
|
252
|
-
datetime.date(2025,
|
|
267
|
+
datetime.date(2025, 10, 15)
|
|
253
268
|
```
|
|
254
269
|
|
|
255
270
|
* `ALL_LANGUAGES`: The list of all `Language` objects based on the included language code data
|
|
@@ -259,7 +274,7 @@ e.g., [`dataclasses.asdict`](https://docs.python.org/3/library/dataclasses.html#
|
|
|
259
274
|
>>> type(iso639.ALL_LANGUAGES)
|
|
260
275
|
<class 'set'>
|
|
261
276
|
>>> len(iso639.ALL_LANGUAGES)
|
|
262
|
-
|
|
277
|
+
8311
|
|
263
278
|
```
|
|
264
279
|
|
|
265
280
|
## Links
|
|
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-iso639"
|
|
7
|
-
version = "2025.
|
|
7
|
+
version = "2025.11.11"
|
|
8
8
|
description = "ISO 639 language codes, names, and other associated information"
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
requires-python = ">= 3.
|
|
10
|
+
requires-python = ">= 3.10"
|
|
11
11
|
license = { text = "Apache 2.0" }
|
|
12
12
|
authors = [ { name = "Jackson L. Lee", email = "jacksonlunlee@gmail.com" } ]
|
|
13
13
|
keywords = ["ISO 639", "language codes", "languages", "linguistics"]
|
|
@@ -21,11 +21,11 @@ classifiers = [
|
|
|
21
21
|
"Operating System :: OS Independent",
|
|
22
22
|
"Programming Language :: Python :: 3",
|
|
23
23
|
"Programming Language :: Python :: 3 :: Only",
|
|
24
|
-
"Programming Language :: Python :: 3.9",
|
|
25
24
|
"Programming Language :: Python :: 3.10",
|
|
26
25
|
"Programming Language :: Python :: 3.11",
|
|
27
26
|
"Programming Language :: Python :: 3.12",
|
|
28
27
|
"Programming Language :: Python :: 3.13",
|
|
28
|
+
"Programming Language :: Python :: 3.14",
|
|
29
29
|
"Topic :: Text Processing",
|
|
30
30
|
"Topic :: Text Processing :: General",
|
|
31
31
|
"Topic :: Text Processing :: Indexing",
|
|
@@ -34,13 +34,13 @@ classifiers = [
|
|
|
34
34
|
|
|
35
35
|
[project.optional-dependencies]
|
|
36
36
|
dev = [
|
|
37
|
-
"black == 25.
|
|
38
|
-
"build == 1.
|
|
39
|
-
"flake8 == 7.
|
|
40
|
-
"mypy == 1.
|
|
41
|
-
"pytest ==
|
|
42
|
-
"requests == 2.32.
|
|
43
|
-
"twine == 6.
|
|
37
|
+
"black == 25.11.0",
|
|
38
|
+
"build == 1.3.0",
|
|
39
|
+
"flake8 == 7.3.0",
|
|
40
|
+
"mypy == 1.18.2",
|
|
41
|
+
"pytest == 9.0.0",
|
|
42
|
+
"requests == 2.32.5",
|
|
43
|
+
"twine == 6.2.0",
|
|
44
44
|
]
|
|
45
45
|
|
|
46
46
|
[project.urls]
|
|
@@ -9,7 +9,7 @@ from .language import ALL_LANGUAGES, Language, LanguageNotFoundError
|
|
|
9
9
|
# While DATA_LAST_UPDATED is strictly the date for the ISO 639-3 data release,
|
|
10
10
|
# __version__ can be bumped for changes other than data updates.
|
|
11
11
|
__version__ = version("python-iso639")
|
|
12
|
-
DATA_LAST_UPDATED = datetime.date(2025,
|
|
12
|
+
DATA_LAST_UPDATED = datetime.date(2025, 10, 15)
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
__all__ = [
|
|
@@ -5,8 +5,6 @@ import os
|
|
|
5
5
|
from collections import defaultdict
|
|
6
6
|
from enum import Enum
|
|
7
7
|
|
|
8
|
-
from typing import Dict, List, Union
|
|
9
|
-
|
|
10
8
|
|
|
11
9
|
class _CodesColumn(Enum):
|
|
12
10
|
ID = "Id"
|
|
@@ -40,10 +38,10 @@ class _MacrolanguagesColumn(Enum):
|
|
|
40
38
|
STATUS = "I_Status"
|
|
41
39
|
|
|
42
40
|
|
|
43
|
-
_COLUMN_TYPE =
|
|
44
|
-
_CodesColumn
|
|
45
|
-
|
|
46
|
-
_ROW_TYPE =
|
|
41
|
+
_COLUMN_TYPE = (
|
|
42
|
+
_CodesColumn | _NameIndexColumn | _RetirementsColumn | _MacrolanguagesColumn
|
|
43
|
+
)
|
|
44
|
+
_ROW_TYPE = dict[_COLUMN_TYPE, str]
|
|
47
45
|
|
|
48
46
|
|
|
49
47
|
class _Table(Enum):
|
|
@@ -62,56 +60,56 @@ _DATA_TSV_PATHS = {
|
|
|
62
60
|
}
|
|
63
61
|
|
|
64
62
|
|
|
65
|
-
def _load_tsv(table: _Table) ->
|
|
63
|
+
def _load_tsv(table: _Table) -> list[_ROW_TYPE]:
|
|
66
64
|
column = table.value
|
|
67
65
|
with open(_DATA_TSV_PATHS[table], encoding="utf-8", newline="") as tsv_file:
|
|
68
66
|
tsv_reader = csv.DictReader(tsv_file, delimiter="\t")
|
|
69
67
|
return [{column(k): v for k, v in row.items()} for row in tsv_reader]
|
|
70
68
|
|
|
71
69
|
|
|
72
|
-
_PART3_TO_CODES:
|
|
70
|
+
_PART3_TO_CODES: dict[str, _ROW_TYPE] = {
|
|
73
71
|
row[_CodesColumn.ID]: row for row in _load_tsv(_Table.CODES)
|
|
74
72
|
}
|
|
75
73
|
|
|
76
|
-
_part3_to_name_index: defaultdict[str,
|
|
74
|
+
_part3_to_name_index: defaultdict[str, list[_ROW_TYPE]] = defaultdict(list)
|
|
77
75
|
for row in _load_tsv(_Table.NAME_INDEX):
|
|
78
76
|
_part3_to_name_index[row[_NameIndexColumn.ID]].append(row)
|
|
79
|
-
_PART3_TO_NAME_INDEX:
|
|
77
|
+
_PART3_TO_NAME_INDEX: dict[str, list[_ROW_TYPE]] = dict(_part3_to_name_index)
|
|
80
78
|
|
|
81
|
-
_PART3_TO_RETIREMENTS:
|
|
79
|
+
_PART3_TO_RETIREMENTS: dict[str, _ROW_TYPE] = {
|
|
82
80
|
row[_RetirementsColumn.ID]: row for row in _load_tsv(_Table.RETIREMENTS)
|
|
83
81
|
}
|
|
84
|
-
_PART3_TO_MACROLANGUAGES:
|
|
82
|
+
_PART3_TO_MACROLANGUAGES: dict[str, _ROW_TYPE] = {
|
|
85
83
|
row[_MacrolanguagesColumn.ID]: row for row in _load_tsv(_Table.MACROLANGUAGES)
|
|
86
84
|
}
|
|
87
85
|
|
|
88
|
-
_PART2B_TO_PART3:
|
|
86
|
+
_PART2B_TO_PART3: dict[str, str] = {
|
|
89
87
|
row[_CodesColumn.PART2B]: part3
|
|
90
88
|
for part3, row in _PART3_TO_CODES.items()
|
|
91
89
|
if row[_CodesColumn.PART2B]
|
|
92
90
|
}
|
|
93
|
-
_PART2T_TO_PART3:
|
|
91
|
+
_PART2T_TO_PART3: dict[str, str] = {
|
|
94
92
|
row[_CodesColumn.PART2T]: part3
|
|
95
93
|
for part3, row in _PART3_TO_CODES.items()
|
|
96
94
|
if row[_CodesColumn.PART2T]
|
|
97
95
|
}
|
|
98
|
-
_PART1_TO_PART3:
|
|
96
|
+
_PART1_TO_PART3: dict[str, str] = {
|
|
99
97
|
row[_CodesColumn.PART1]: part3
|
|
100
98
|
for part3, row in _PART3_TO_CODES.items()
|
|
101
99
|
if row[_CodesColumn.PART1]
|
|
102
100
|
}
|
|
103
|
-
_REF_NAME_TO_PART3:
|
|
101
|
+
_REF_NAME_TO_PART3: dict[str, str] = {
|
|
104
102
|
row[_CodesColumn.REF_NAME]: part3
|
|
105
103
|
for part3, row in _PART3_TO_CODES.items()
|
|
106
104
|
if row[_CodesColumn.REF_NAME]
|
|
107
105
|
}
|
|
108
|
-
_PRINT_NAME_TO_PART3:
|
|
106
|
+
_PRINT_NAME_TO_PART3: dict[str, str] = {
|
|
109
107
|
row[_NameIndexColumn.PRINT_NAME]: part3
|
|
110
108
|
for part3, rows in _PART3_TO_NAME_INDEX.items()
|
|
111
109
|
for row in rows
|
|
112
110
|
if row[_NameIndexColumn.PRINT_NAME]
|
|
113
111
|
}
|
|
114
|
-
_INVERTED_NAME_TO_PART3:
|
|
112
|
+
_INVERTED_NAME_TO_PART3: dict[str, str] = {
|
|
115
113
|
row[_NameIndexColumn.INVERTED_NAME]: part3
|
|
116
114
|
for part3, rows in _PART3_TO_NAME_INDEX.items()
|
|
117
115
|
for row in rows
|
|
@@ -1297,7 +1297,7 @@ cli I L Chakali
|
|
|
1297
1297
|
clj I L Laitu Chin
|
|
1298
1298
|
clk I L Idu-Mishmi
|
|
1299
1299
|
cll I L Chala
|
|
1300
|
-
clm I L
|
|
1300
|
+
clm I L Klallam
|
|
1301
1301
|
clo I L Lowland Oaxaca Chontal
|
|
1302
1302
|
cls I H Classical Sanskrit
|
|
1303
1303
|
clt I L Lautu Chin
|
|
@@ -2325,7 +2325,7 @@ gyz I L Geji
|
|
|
2325
2325
|
gza I L Ganza
|
|
2326
2326
|
gzi I L Gazi
|
|
2327
2327
|
gzn I L Gane
|
|
2328
|
-
haa I L
|
|
2328
|
+
haa I L Hän
|
|
2329
2329
|
hab I L Hanoi Sign Language
|
|
2330
2330
|
hac I L Gurani
|
|
2331
2331
|
had I L Hatam
|
|
@@ -2892,7 +2892,7 @@ kce I L Kaivi
|
|
|
2892
2892
|
kcf I L Ukaan
|
|
2893
2893
|
kcg I L Tyap
|
|
2894
2894
|
kch I L Vono
|
|
2895
|
-
kci I L
|
|
2895
|
+
kci I L Ngyian
|
|
2896
2896
|
kcj I L Kobiana
|
|
2897
2897
|
kck I L Kalanga
|
|
2898
2898
|
kcl I L Kela (Papua New Guinea)
|
|
@@ -3390,7 +3390,7 @@ kwg I L Sara Kaba Deme
|
|
|
3390
3390
|
kwh I L Kowiai
|
|
3391
3391
|
kwi I L Awa-Cuaiquer
|
|
3392
3392
|
kwj I L Kwanga
|
|
3393
|
-
kwk I L
|
|
3393
|
+
kwk I L Kwak'wala
|
|
3394
3394
|
kwl I L Kofyar
|
|
3395
3395
|
kwm I L Kwambi
|
|
3396
3396
|
kwn I L Kwangali
|
|
@@ -3795,7 +3795,7 @@ lup I L Lumbu
|
|
|
3795
3795
|
luq I L Lucumi
|
|
3796
3796
|
lur I L Laura
|
|
3797
3797
|
lus lus lus I L Lushai
|
|
3798
|
-
lut I
|
|
3798
|
+
lut I E Lushootseed
|
|
3799
3799
|
luu I L Lumba-Yakkha
|
|
3800
3800
|
luv I L Luwati
|
|
3801
3801
|
luw I L Luo (Cameroon)
|
|
@@ -4011,7 +4011,7 @@ mhj I L Mogholi
|
|
|
4011
4011
|
mhk I L Mungaka
|
|
4012
4012
|
mhl I L Mauwake
|
|
4013
4013
|
mhm I L Makhuwa-Moniga
|
|
4014
|
-
mhn I L
|
|
4014
|
+
mhn I L Mòcheno
|
|
4015
4015
|
mho I L Mashi (Zambia)
|
|
4016
4016
|
mhp I L Balinese Malay
|
|
4017
4017
|
mhq I L Mandan
|
|
@@ -4574,7 +4574,7 @@ nes I L Bhoti Kinnauri
|
|
|
4574
4574
|
net I L Nete
|
|
4575
4575
|
neu I C Neo
|
|
4576
4576
|
nev I L Nyaheun
|
|
4577
|
-
new new new I L
|
|
4577
|
+
new new new I L Nepal Bhasa
|
|
4578
4578
|
nex I L Neme
|
|
4579
4579
|
ney I L Neyo
|
|
4580
4580
|
nez I L Nez Perce
|
|
@@ -4916,7 +4916,7 @@ nxo I L Ndambomo
|
|
|
4916
4916
|
nxq I L Naxi
|
|
4917
4917
|
nxr I L Ninggerum
|
|
4918
4918
|
nxx I L Nafri
|
|
4919
|
-
nya nya nya ny I L
|
|
4919
|
+
nya nya nya ny I L Chichewa
|
|
4920
4920
|
nyb I L Nyangbo
|
|
4921
4921
|
nyc I L Nyanga-li
|
|
4922
4922
|
nyd I L Nyore
|
|
@@ -4954,6 +4954,7 @@ nzy I L Nzakambay
|
|
|
4954
4954
|
nzz I L Nanga Dama Dogon
|
|
4955
4955
|
oaa I L Orok
|
|
4956
4956
|
oac I L Oroch
|
|
4957
|
+
oak I L Noakhali
|
|
4957
4958
|
oar I H Old Aramaic (up to 700 BCE)
|
|
4958
4959
|
oav I H Old Avar
|
|
4959
4960
|
obi I E Obispeño
|
|
@@ -5017,6 +5018,7 @@ okv I L Orokaiva
|
|
|
5017
5018
|
okx I L Okpe (Northwestern Edo)
|
|
5018
5019
|
okz I H Old Khmer
|
|
5019
5020
|
ola I L Walungge
|
|
5021
|
+
olb I L Oli-Bodiman
|
|
5020
5022
|
old I L Mochi
|
|
5021
5023
|
ole I L Olekha
|
|
5022
5024
|
olk I E Olkol
|
|
@@ -5088,11 +5090,12 @@ ory I L Odia
|
|
|
5088
5090
|
orz I L Ormu
|
|
5089
5091
|
osa osa osa I L Osage
|
|
5090
5092
|
osc I H Oscan
|
|
5093
|
+
osd I L Digor Ossetic
|
|
5091
5094
|
osi I L Osing
|
|
5092
5095
|
osn I H Old Sundanese
|
|
5093
5096
|
oso I L Ososo
|
|
5094
5097
|
osp I H Old Spanish
|
|
5095
|
-
oss oss oss os I L
|
|
5098
|
+
oss oss oss os I L Iron Ossetic
|
|
5096
5099
|
ost I L Osatu
|
|
5097
5100
|
osu I L Southern One
|
|
5098
5101
|
osx I H Old Saxon
|
|
@@ -5758,6 +5761,7 @@ scu I L Shumcho
|
|
|
5758
5761
|
scv I L Sheni
|
|
5759
5762
|
scw I L Sha
|
|
5760
5763
|
scx I H Sicel
|
|
5764
|
+
scz I L Shaetlan
|
|
5761
5765
|
sda I L Toraja-Sa'dan
|
|
5762
5766
|
sdb I L Shabak
|
|
5763
5767
|
sdc I L Sassarese Sardinian
|
|
@@ -7651,7 +7655,6 @@ yob I E Yoba
|
|
|
7651
7655
|
yog I L Yogad
|
|
7652
7656
|
yoi I L Yonaguni
|
|
7653
7657
|
yok I L Yokuts
|
|
7654
|
-
yol I E Yola
|
|
7655
7658
|
yom I L Yombe
|
|
7656
7659
|
yon I L Yongkom
|
|
7657
7660
|
yor yor yor yo I L Yoruba
|
|
@@ -7833,7 +7836,7 @@ zml I E Matngala
|
|
|
7833
7836
|
zmm I L Marimanindji
|
|
7834
7837
|
zmn I L Mbangwe
|
|
7835
7838
|
zmo I L Molo
|
|
7836
|
-
zmp I L
|
|
7839
|
+
zmp I L Mbuun
|
|
7837
7840
|
zmq I L Mituku
|
|
7838
7841
|
zmr I L Maranunggu
|
|
7839
7842
|
zms I L Mbesa
|
{python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/iso639/_data/iso-639-3_Name_Index.tab
RENAMED
|
@@ -378,6 +378,7 @@ ary Moroccan Arabic Arabic, Moroccan
|
|
|
378
378
|
arz Egyptian Arabic Arabic, Egyptian
|
|
379
379
|
asa Asu (Tanzania) Asu (Tanzania)
|
|
380
380
|
asb Assiniboine Assiniboine
|
|
381
|
+
asb Nakoda Assiniboine Nakoda Assiniboine
|
|
381
382
|
asc Casuarina Coast Asmat Asmat, Casuarina Coast
|
|
382
383
|
ase American Sign Language American Sign Language
|
|
383
384
|
asf Auslan Auslan
|
|
@@ -413,6 +414,7 @@ ate Atemble Atemble
|
|
|
413
414
|
atg Ivbie North-Okpela-Arhe Ivbie North-Okpela-Arhe
|
|
414
415
|
ati Attié Attié
|
|
415
416
|
atj Atikamekw Atikamekw
|
|
417
|
+
atj Nehirowimowin Nehirowimowin
|
|
416
418
|
atk Ati Ati
|
|
417
419
|
atl Mt. Iraya Agta Agta, Mt. Iraya
|
|
418
420
|
atm Ata Ata
|
|
@@ -1340,6 +1342,7 @@ cky Cakfem-Mushere Cakfem-Mushere
|
|
|
1340
1342
|
ckz Cakchiquel-Quiché Mixed Language Cakchiquel-Quiché Mixed Language
|
|
1341
1343
|
cla Ron Ron
|
|
1342
1344
|
clc Chilcotin Chilcotin
|
|
1345
|
+
clc Tsilhqot’in Tsilhqot’in
|
|
1343
1346
|
cld Chaldean Neo-Aramaic Neo-Aramaic, Chaldean
|
|
1344
1347
|
cle Lealao Chinantec Chinantec, Lealao
|
|
1345
1348
|
clh Chilisso Chilisso
|
|
@@ -1348,6 +1351,7 @@ clj Laitu Chin Chin, Laitu
|
|
|
1348
1351
|
clk Idu-Mishmi Idu-Mishmi
|
|
1349
1352
|
cll Chala Chala
|
|
1350
1353
|
clm Clallam Clallam
|
|
1354
|
+
clm Klallam Klallam
|
|
1351
1355
|
clo Lowland Oaxaca Chontal Chontal, Lowland Oaxaca
|
|
1352
1356
|
cls Classical Sanskrit Classical Sanskrit
|
|
1353
1357
|
clt Lautu Chin Chin, Lautu
|
|
@@ -2432,7 +2436,7 @@ gyz Gyaazi Gyaazi
|
|
|
2432
2436
|
gza Ganza Ganza
|
|
2433
2437
|
gzi Gazi Gazi
|
|
2434
2438
|
gzn Gane Gane
|
|
2435
|
-
haa
|
|
2439
|
+
haa Hän Hän
|
|
2436
2440
|
hab Hanoi Sign Language Hanoi Sign Language
|
|
2437
2441
|
hac Gurani Gurani
|
|
2438
2442
|
had Hatam Hatam
|
|
@@ -3042,6 +3046,7 @@ kcf Ukaan Ukaan
|
|
|
3042
3046
|
kcg Tyap Tyap
|
|
3043
3047
|
kch Vono Vono
|
|
3044
3048
|
kci Kamantan Kamantan
|
|
3049
|
+
kci Ngyian Ngyian
|
|
3045
3050
|
kcj Kobiana Kobiana
|
|
3046
3051
|
kck Kalanga Kalanga
|
|
3047
3052
|
kcl Kala Kala
|
|
@@ -3565,6 +3570,7 @@ kwh Kowiai Kowiai
|
|
|
3565
3570
|
kwi Awa-Cuaiquer Awa-Cuaiquer
|
|
3566
3571
|
kwj Kwanga Kwanga
|
|
3567
3572
|
kwk Kwakiutl Kwakiutl
|
|
3573
|
+
kwk Kwak'wala Kwak'wala
|
|
3568
3574
|
kwl Kofyar Kofyar
|
|
3569
3575
|
kwm Kwambi Kwambi
|
|
3570
3576
|
kwn Kwangali Kwangali
|
|
@@ -4217,7 +4223,7 @@ mhj Mogholi Mogholi
|
|
|
4217
4223
|
mhk Mungaka Mungaka
|
|
4218
4224
|
mhl Mauwake Mauwake
|
|
4219
4225
|
mhm Makhuwa-Moniga Makhuwa-Moniga
|
|
4220
|
-
mhn
|
|
4226
|
+
mhn Mòcheno Mòcheno
|
|
4221
4227
|
mho Mashi (Zambia) Mashi (Zambia)
|
|
4222
4228
|
mhp Balinese Malay Malay, Balinese
|
|
4223
4229
|
mhq Mandan Mandan
|
|
@@ -4804,6 +4810,7 @@ net Nete Nete
|
|
|
4804
4810
|
neu Neo Neo
|
|
4805
4811
|
nev Nyaheun Nyaheun
|
|
4806
4812
|
new Nepal Bhasa Bhasa, Nepal
|
|
4813
|
+
new Newar Newar
|
|
4807
4814
|
new Newari Newari
|
|
4808
4815
|
nex Neme Neme
|
|
4809
4816
|
ney Neyo Neyo
|
|
@@ -5202,6 +5209,8 @@ nzy Nzakambay Nzakambay
|
|
|
5202
5209
|
nzz Nanga Dama Dogon Dogon, Nanga Dama
|
|
5203
5210
|
oaa Orok Orok
|
|
5204
5211
|
oac Oroch Oroch
|
|
5212
|
+
oak Noakhailla Noakhailla
|
|
5213
|
+
oak Noakhali Noakhali
|
|
5205
5214
|
oar Ancient Aramaic (up to 700 BCE) Aramaic, Ancient (up to 700 BCE)
|
|
5206
5215
|
oar Old Aramaic (up to 700 BCE) Aramaic, Old (up to 700 BCE)
|
|
5207
5216
|
oav Old Avar Avar, Old
|
|
@@ -5266,6 +5275,7 @@ okv Orokaiva Orokaiva
|
|
|
5266
5275
|
okx Okpe (Northwestern Edo) Okpe (Northwestern Edo)
|
|
5267
5276
|
okz Old Khmer Khmer, Old
|
|
5268
5277
|
ola Walungge Walungge
|
|
5278
|
+
olb Oli-Bodiman Oli-Bodiman
|
|
5269
5279
|
old Mochi Mochi
|
|
5270
5280
|
ole Olekha Olekha
|
|
5271
5281
|
olk Olkol Olkol
|
|
@@ -5338,10 +5348,16 @@ ory Oriya (individual language) Oriya (individual language)
|
|
|
5338
5348
|
orz Ormu Ormu
|
|
5339
5349
|
osa Osage Osage
|
|
5340
5350
|
osc Oscan Oscan
|
|
5351
|
+
osd Digor Digor
|
|
5352
|
+
osd Digor Ossetian Ossetian, Digor
|
|
5353
|
+
osd Digor Ossetic Ossetic, Digor
|
|
5341
5354
|
osi Osing Osing
|
|
5342
5355
|
osn Old Sundanese Sundanese, Old
|
|
5343
5356
|
oso Ososo Ososo
|
|
5344
5357
|
osp Old Spanish Spanish, Old
|
|
5358
|
+
oss Iron Iron
|
|
5359
|
+
oss Iron Ossetian Ossetian, Iron
|
|
5360
|
+
oss Iron Ossetic Ossetic, Iron
|
|
5345
5361
|
oss Ossetian Ossetian
|
|
5346
5362
|
oss Ossetic Ossetic
|
|
5347
5363
|
ost Osatu Osatu
|
|
@@ -5738,7 +5754,7 @@ pyx Pyu (Myanmar) Pyu (Myanmar)
|
|
|
5738
5754
|
pyy Pyen Pyen
|
|
5739
5755
|
pze Pesse Pesse
|
|
5740
5756
|
pzh Pazeh Pazeh
|
|
5741
|
-
pzn Jejara Naga Jejara
|
|
5757
|
+
pzn Jejara Naga Naga, Jejara
|
|
5742
5758
|
pzn Para Naga Naga, Para
|
|
5743
5759
|
qua Quapaw Quapaw
|
|
5744
5760
|
qub Huallaga Huánuco Quechua Quechua, Huallaga Huánuco
|
|
@@ -6043,6 +6059,7 @@ scu Shumcho Shumcho
|
|
|
6043
6059
|
scv Sheni Sheni
|
|
6044
6060
|
scw Sha Sha
|
|
6045
6061
|
scx Sicel Sicel
|
|
6062
|
+
scz Shaetlan Shaetlan
|
|
6046
6063
|
sda Toraja-Sa'dan Toraja-Sa'dan
|
|
6047
6064
|
sdb Shabak Shabak
|
|
6048
6065
|
sdc Sassarese Sardinian Sardinian, Sassarese
|
|
@@ -6066,6 +6083,7 @@ sdz Sallands Sallands
|
|
|
6066
6083
|
sea Semai Semai
|
|
6067
6084
|
seb Shempire Senoufo Senoufo, Shempire
|
|
6068
6085
|
sec Sechelt Sechelt
|
|
6086
|
+
sec She shashishalhem She shashishalhem
|
|
6069
6087
|
sed Sedang Sedang
|
|
6070
6088
|
see Seneca Seneca
|
|
6071
6089
|
sef Cebaara Senoufo Senoufo, Cebaara
|
|
@@ -6130,6 +6148,7 @@ sho Shanga Shanga
|
|
|
6130
6148
|
shp Shipibo-Conibo Shipibo-Conibo
|
|
6131
6149
|
shq Sala Sala
|
|
6132
6150
|
shr Shi Shi
|
|
6151
|
+
shs Secwepemctsín Secwepemctsín
|
|
6133
6152
|
shs Shuswap Shuswap
|
|
6134
6153
|
sht Shasta Shasta
|
|
6135
6154
|
shu Chadian Arabic Arabic, Chadian
|
|
@@ -6335,6 +6354,7 @@ sqq Sou Sou
|
|
|
6335
6354
|
sqr Siculo Arabic Arabic, Siculo
|
|
6336
6355
|
sqs Sri Lankan Sign Language Sri Lankan Sign Language
|
|
6337
6356
|
sqt Soqotri Soqotri
|
|
6357
|
+
squ Sḵwx̱wú7mesh sníchim Sḵwx̱wú7mesh sníchim
|
|
6338
6358
|
squ Squamish Squamish
|
|
6339
6359
|
sqx Kufr Qassem Sign Language (KQSL) Kufr Qassem Sign Language (KQSL)
|
|
6340
6360
|
sra Saruga Saruga
|
|
@@ -6668,11 +6688,14 @@ thk Tharaka Tharaka
|
|
|
6668
6688
|
thl Dangaura Tharu Tharu, Dangaura
|
|
6669
6689
|
thm Aheu Aheu
|
|
6670
6690
|
thn Thachanadan Thachanadan
|
|
6691
|
+
thp Nłeʔkepmxcín Nłeʔkepmxcín
|
|
6671
6692
|
thp Thompson Thompson
|
|
6693
|
+
thp Thompson River Salish Salish, Thompson River
|
|
6672
6694
|
thq Kochila Tharu Tharu, Kochila
|
|
6673
6695
|
thr Rana Tharu Tharu, Rana
|
|
6674
6696
|
ths Thakali Thakali
|
|
6675
6697
|
tht Tahltan Tahltan
|
|
6698
|
+
tht Tāłtān Tāłtān
|
|
6676
6699
|
thu Thuri Thuri
|
|
6677
6700
|
thv Tahaggart Tamahaq Tamahaq, Tahaggart
|
|
6678
6701
|
thy Tha Tha
|
|
@@ -8011,7 +8034,6 @@ yob Yoba Yoba
|
|
|
8011
8034
|
yog Yogad Yogad
|
|
8012
8035
|
yoi Yonaguni Yonaguni
|
|
8013
8036
|
yok Yokuts Yokuts
|
|
8014
|
-
yol Yola Yola
|
|
8015
8037
|
yom Yombe Yombe
|
|
8016
8038
|
yon Yongkom Yongkom
|
|
8017
8039
|
yor Yoruba Yoruba
|
|
@@ -8201,7 +8223,7 @@ zmm Marimanindji Marimanindji
|
|
|
8201
8223
|
zmm Marramaninyshi Marramaninyshi
|
|
8202
8224
|
zmn Mbangwe Mbangwe
|
|
8203
8225
|
zmo Molo Molo
|
|
8204
|
-
zmp
|
|
8226
|
+
zmp Mbuun Mbuun
|
|
8205
8227
|
zmq Mituku Mituku
|
|
8206
8228
|
zmr Maranunggu Maranunggu
|
|
8207
8229
|
zms Mbesa Mbesa
|
{python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/iso639/_data/iso-639-3_Retirements.tab
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Id Ref_Name Ret_Reason Change_To Ret_Remedy Effective
|
|
2
|
-
fri Western Frisian C fry
|
|
2
|
+
fri Western Frisian C fry 2005-11-16
|
|
3
3
|
auv Auvergnat M oci 2007-03-14
|
|
4
4
|
gsc Gascon M oci 2007-03-14
|
|
5
5
|
lms Limousin M oci 2007-03-14
|
|
@@ -18,7 +18,6 @@ mob Moinba S Split into five languages: Chug [cvg]; Lish [lsh]; Kalaktang Monp
|
|
|
18
18
|
mzf Aiku S Split into four languages: Ambrak [aag]; Yangum Dey [yde]; Yangum Gel [ygl]; Yangum Mon [ymo] 2007-07-18
|
|
19
19
|
nhj Tlalitzlipa Nahuatl M nhi 2007-07-18
|
|
20
20
|
nhs Southeastern Puebla Nahuatl S Split into Sierra Negra Nahuatl [nsu] and Southeastern Puebla Nahuatl [npl] 2007-07-18
|
|
21
|
-
occ Occidental D ile 2007-07-18
|
|
22
21
|
tmx Tomyang M ybi 2007-07-18
|
|
23
22
|
tot Patla-Chicontla Totonac S Split into Upper Necaxa Totonac [tku] and Tecpatlán Totonac [tcw] 2007-07-18
|
|
24
23
|
xmi Miarrã N 2007-07-18
|
|
@@ -27,6 +26,7 @@ ztc Lachirioag Zapotec M zty 2007-07-18
|
|
|
27
26
|
atf Atuence N 2007-08-10
|
|
28
27
|
bqe Navarro-Labourdin Basque M eus 2007-08-10
|
|
29
28
|
bsz Souletin Basque M eus 2007-08-10
|
|
29
|
+
occ Occidental D ile 2007-12-07
|
|
30
30
|
aex Amerax M eng 2008-01-14
|
|
31
31
|
ahe Ahe M knx 2008-01-14
|
|
32
32
|
aiz Aari S Split into Aari [aiw] (new identifier) and Gayil [gyl] 2008-01-14
|
|
@@ -169,21 +169,21 @@ cmk Chimakum D xch 2010-01-18
|
|
|
169
169
|
drh Darkhat M khk 2010-01-18
|
|
170
170
|
drw Darwazi M prs 2010-01-18
|
|
171
171
|
gav Gabutamon M dev 2010-01-18
|
|
172
|
-
mof Mohegan-Montauk-Narragansett S
|
|
172
|
+
mof Mohegan-Montauk-Narragansett S Split into Mohegan-Pequot [xpq] and Narragansett [xnt] 2010-01-18
|
|
173
173
|
mst Cataelano Mandaya M mry 2010-01-18
|
|
174
174
|
myt Sangab Mandaya M mry 2010-01-18
|
|
175
|
-
rmr Caló S
|
|
176
|
-
sgl Sanglechi-Ishkashimi S
|
|
175
|
+
rmr Caló S Split into Caló [rmq] and Erromintxela [emx] 2010-01-18
|
|
176
|
+
sgl Sanglechi-Ishkashimi S Split into Sanglechi [sgy] and Ishkashimi [isk] 2010-01-18
|
|
177
177
|
sul Surigaonon S Split into Tandaganon [tgn] and Surigaonon [sgd] (new identifier) 2010-01-18
|
|
178
178
|
sum Sumo-Mayangna S Split into Mayangna [yan] and Ulwa [ulw] 2010-01-18
|
|
179
179
|
tnf Tangshewi M prs 2010-01-18
|
|
180
180
|
wgw Wagawaga S Split into Yaleba [ylb] and Wagawaga [wgb] (new identifier) 2010-01-18
|
|
181
181
|
ayx Ayi (China) D nun 2011-05-18
|
|
182
|
-
bjq Southern Betsimisaraka Malagasy S
|
|
182
|
+
bjq Southern Betsimisaraka Malagasy S Split into Southern Betsimisaraka [bzc] and Tesaka Malagasy [tkg] 2011-05-18
|
|
183
183
|
dha Dhanwar (India) N 2011-05-18
|
|
184
|
-
dkl Kolum So Dogon S
|
|
184
|
+
dkl Kolum So Dogon S Split into Ampari Dogon [aqd] and Mombo Dogon [dmb] 2011-05-18
|
|
185
185
|
mja Mahei N 2011-05-18
|
|
186
|
-
nbf Naxi S
|
|
186
|
+
nbf Naxi S Split into Naxi [nxq] and Narua [nru] 2011-05-18
|
|
187
187
|
noo Nootka S Split into [dtd] Ditidaht and [nuk] Nuu-chah-nulth 2011-05-18
|
|
188
188
|
tie Tingal M ras 2011-05-18
|
|
189
189
|
tkk Takpa D twm 2011-05-18
|
|
@@ -195,15 +195,14 @@ dap Nisi (India) S Split into Nyishi [njz] and Tagin [tgj] 2012-02-03
|
|
|
195
195
|
dwl Walo Kumbe Dogon S Split into Dogon, Bankan Tey (Walo) [dbw] and Dogon, Ben Tey (Beni) [dbt] 2012-02-03
|
|
196
196
|
elp Elpaputih N 2012-02-03
|
|
197
197
|
gbc Garawa S Split into Garrwa [wrk] and Wanyi [wny] 2012-02-03
|
|
198
|
-
gio Gelao S Split into Qau [gqu] and A'ou [aou]
|
|
198
|
+
gio Gelao S Split into Qau [gqu] and A'ou [aou] 2012-02-03
|
|
199
199
|
hrr Horuru M jal 2012-02-03
|
|
200
200
|
ibi Ibilo M opa 2012-02-03
|
|
201
|
-
jar Jarawa (Nigeria) S
|
|
202
|
-
kdv Kado S
|
|
201
|
+
jar Jarawa (Nigeria) S Split into Gwak [jgk] and Bankal [jjr] 2012-02-03
|
|
202
|
+
kdv Kado S Split into Kadu [zkd] and Kanan [zkn] 2012-02-03
|
|
203
203
|
kgh Upper Tanudan Kalinga M kml 2012-02-03
|
|
204
204
|
kpp Paku Karen S Split into Paku Karen [jkp] and Mobwa Karen [jkm] 2012-02-03
|
|
205
205
|
kzh Kenuzi-Dongola S Split into Andaandi (Dongolawi) [dgl] and Kenzi (Mattoki) [xnz] 2012-02-03
|
|
206
|
-
lcq Luhu M ppr 2012-02-03
|
|
207
206
|
mgx Omati S Split into Barikewa [jbk] and Mouwase [jmw] 2012-02-03
|
|
208
207
|
nln Durango Nahuatl S Split into Eastern Durango Nahuatl [azd] and Western Durango Nahuatl [azn] 2012-02-03
|
|
209
208
|
pbz Palu N 2012-02-03
|
|
@@ -248,7 +247,6 @@ aue ǂKxʼauǁʼein D ktz 2015-01-12
|
|
|
248
247
|
bmy Bemba (Democratic Republic of Congo) N 2015-01-12
|
|
249
248
|
bxx Borna (Democratic Republic of Congo) N 2015-01-12
|
|
250
249
|
byy Buya N 2015-01-12
|
|
251
|
-
dzd Daza N 2015-01-12
|
|
252
250
|
gfx Mangetti Dune ǃXung M vaj 2015-01-12
|
|
253
251
|
gti Gbati-ri M nyc 2015-01-12
|
|
254
252
|
ime Imeraguen N 2015-01-12
|
|
@@ -265,7 +263,6 @@ sgo Songa N 2015-01-12
|
|
|
265
263
|
thx The D oyb 2015-01-12
|
|
266
264
|
tsf Southwestern Tamang M taj 2015-01-12
|
|
267
265
|
uok Uokha M ema 2015-01-12
|
|
268
|
-
xsj Subi D suj 2015-01-12
|
|
269
266
|
yds Yiddish Sign Language N 2015-01-12
|
|
270
267
|
ymt Mator-Taygi-Karagas D mtm 2015-01-12
|
|
271
268
|
ynh Yangho N 2015-01-12
|
|
@@ -276,9 +273,9 @@ cbh Cagua N 2016-01-15
|
|
|
276
273
|
coy Coyaima M pij 2016-01-15
|
|
277
274
|
cqu Chilean Quechua M quh 2016-01-15
|
|
278
275
|
cum Cumeral N 2016-01-15
|
|
279
|
-
duj Dhuwal S
|
|
276
|
+
duj Dhuwal S Split into [dwu] Dhuwal and [dwy] Dhuwaya 2016-01-15
|
|
280
277
|
ggn Eastern Gurung M gvr 2016-01-15
|
|
281
|
-
ggo Southern Gondi S
|
|
278
|
+
ggo Southern Gondi S Split into [esg] Aheri Gondi and [wsg] Adilabad Gondi 2016-01-15
|
|
282
279
|
guv Gey M duz 2016-01-15
|
|
283
280
|
iap Iapama N 2016-01-15
|
|
284
281
|
ill Iranun S Split into Iranun (Philippines) [ilp] and Iranun (Malaysia) [ilm] 2016-01-15
|
|
@@ -349,7 +346,7 @@ plp Palpa N 2020-01-23
|
|
|
349
346
|
sdm Semandang S Split into Semandang [sdq], Beginci [ebc] and Gerai [gef] 2020-01-23
|
|
350
347
|
tbb Tapeba N 2020-01-23
|
|
351
348
|
xrq Karranga M dmw 2020-01-23
|
|
352
|
-
xtz Tasmanian S Split into [xpv] Northern Tasman, [xph] North Midlands Tasman, [xpb] Northeastern Tasman, [xpd] Oyster Bay
|
|
349
|
+
xtz Tasmanian S Split into [xpv] Northern Tasman, [xph] North Midlands Tasman, [xpb] Northeastern Tasman, [xpd] Oyster Bay Tasman, [xpf] Southeast Tasman, [xpx] Southwestern Tasman, [xpw] Northwestern Tasman, [xpl] Port Sorell Tasman, and [xpz] Bruny Island Tasman 2020-01-23
|
|
353
350
|
zir Ziriya D scv 2020-01-23
|
|
354
351
|
thw Thudam M ola 2020-03-19
|
|
355
352
|
bic Bikaru M bir 2021-01-15
|
|
@@ -361,7 +358,7 @@ ngo Ngoni S Split into Ngoni (Tanzania) [xnj] and Ngoni (Mozambique) [xnq] 2021
|
|
|
361
358
|
pat Papitalai M kxr 2021-01-15
|
|
362
359
|
vki Ija-Zuba S Split into Koro Nulu [vkn] and Koro Zuba [vkz] 2021-01-15
|
|
363
360
|
wra Warapu S Split into Bauni [bpe], Uni [uni] and Bouni [suo] 2021-01-15
|
|
364
|
-
ajt Judeo-Tunisian Arabic
|
|
361
|
+
ajt Judeo-Tunisian Arabic M aeb 2022-01-20
|
|
365
362
|
cug Chungmboko S Split into Chung [cnq] and Mbuk [bpc] 2022-01-20
|
|
366
363
|
lak Laka (Nigeria) M ksp 2022-01-20
|
|
367
364
|
lno Lango (South Sudan) S Split into Lango [lgo], Imotong [imt], Logir [lqr] and Okolie [oie] 2022-01-20
|
|
@@ -373,7 +370,9 @@ wrd Warduji N 2022-01-20
|
|
|
373
370
|
wya Wyandot S Split into Wyandot [wyn] and Wendat [wdt] 2022-01-20
|
|
374
371
|
ajp South Levantine Arabic M apc 2023-01-20
|
|
375
372
|
kgm Karipúna D plu 2023-01-20
|
|
373
|
+
ksa Shuwa-Zamani S Split into [rsw] Rishiwa and [izm] Kizamani 2023-01-20
|
|
376
374
|
nom Nocamán M cbr 2023-01-20
|
|
375
|
+
plj Polci S Split into Pesse [pze], Nyamzak-Dir-Mbarimi [nzr], Zul [zlu], and Buli [uly] 2023-01-20
|
|
377
376
|
pmk Pamlico M crr 2023-01-20
|
|
378
377
|
prp Parsi M guj 2023-01-20
|
|
379
378
|
slq Salchuq N 2023-01-20
|
|
@@ -383,7 +382,6 @@ tpw Tupí D tpn 2023-01-20
|
|
|
383
382
|
xss Assan M zko 2023-01-20
|
|
384
383
|
zkb Koibal D kjh 2023-01-20
|
|
385
384
|
zua Zeem S Split into [tvi] Tulai, [dyr] Dyarim, [dsk] Dokshi, [cxh] Cha'ari, and [zem] Zeem 2023-01-20
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
nte Nathembo M eko 2024-09-09
|
|
385
|
+
dek Dek D sqm 2024-10-15
|
|
386
|
+
nte Nathembo M eko 2024-10-15
|
|
387
|
+
yol Yola M enm 2025-10-15
|
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import datetime
|
|
6
6
|
from dataclasses import dataclass
|
|
7
7
|
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import NoReturn
|
|
9
9
|
|
|
10
10
|
from ._data import (
|
|
11
11
|
_PART3_TO_CODES,
|
|
@@ -26,6 +26,9 @@ from ._data import (
|
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
|
|
29
|
+
_STRING_CLEANING_FUNCS = [lambda x: x.lower(), lambda x: x.title()]
|
|
30
|
+
|
|
31
|
+
|
|
29
32
|
class LanguageNotFoundError(Exception):
|
|
30
33
|
pass
|
|
31
34
|
|
|
@@ -67,31 +70,26 @@ class Language:
|
|
|
67
70
|
|
|
68
71
|
# From the "codes" table
|
|
69
72
|
part3: str
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
# When support for Python 3.9 is dropped, we will switch to the pipe syntax
|
|
74
|
-
# for `... | None`.
|
|
75
|
-
part2b: Union[str, None]
|
|
76
|
-
part2t: Union[str, None]
|
|
77
|
-
part1: Union[str, None]
|
|
73
|
+
part2b: str | None
|
|
74
|
+
part2t: str | None
|
|
75
|
+
part1: str | None
|
|
78
76
|
scope: str
|
|
79
|
-
type:
|
|
77
|
+
type: str | None
|
|
80
78
|
status: str
|
|
81
79
|
name: str
|
|
82
|
-
comment:
|
|
80
|
+
comment: str | None
|
|
83
81
|
|
|
84
82
|
# From the "name_index" table
|
|
85
|
-
other_names:
|
|
83
|
+
other_names: list[Name] | None
|
|
86
84
|
|
|
87
85
|
# From the "macrolanguages" table
|
|
88
|
-
macrolanguage:
|
|
86
|
+
macrolanguage: str | None
|
|
89
87
|
|
|
90
88
|
# From the "retirements" table
|
|
91
|
-
retire_reason:
|
|
92
|
-
retire_change_to:
|
|
93
|
-
retire_remedy:
|
|
94
|
-
retire_date:
|
|
89
|
+
retire_reason: str | None
|
|
90
|
+
retire_change_to: str | None
|
|
91
|
+
retire_remedy: str | None
|
|
92
|
+
retire_date: datetime.date | None
|
|
95
93
|
|
|
96
94
|
def __hash__(self) -> int:
|
|
97
95
|
return hash(self.part3)
|
|
@@ -100,13 +98,19 @@ class Language:
|
|
|
100
98
|
return isinstance(other, Language) and self.part3 == other.part3
|
|
101
99
|
|
|
102
100
|
@classmethod
|
|
103
|
-
def match(cls, user_input: str,
|
|
101
|
+
def match(cls, user_input: str, /, *, strict_case: bool = True) -> Language:
|
|
104
102
|
"""Return a ``Language`` instance by matching on the user input.
|
|
105
103
|
|
|
106
104
|
Parameters
|
|
107
105
|
----------
|
|
108
106
|
user_input : str
|
|
109
107
|
A language code or name.
|
|
108
|
+
strict_case : bool, optional
|
|
109
|
+
Defaults to ``True``, for enforcing strict case sensitivity.
|
|
110
|
+
If ``False`` and if ``user_input`` doesn't find a match,
|
|
111
|
+
further match attempts will be made with the all-lowercase version of
|
|
112
|
+
``user_input`` (``"foobar"``) and the title-case version of ``user_input``
|
|
113
|
+
(``"Foobar"``).
|
|
110
114
|
|
|
111
115
|
Returns
|
|
112
116
|
-------
|
|
@@ -130,7 +134,7 @@ class Language:
|
|
|
130
134
|
# Order of columns to query the data tables.
|
|
131
135
|
# Bias towards (and therefore prioritize) the user input being
|
|
132
136
|
# a language code rather than a language name.
|
|
133
|
-
query_order:
|
|
137
|
+
query_order: list[_COLUMN_TYPE] = [
|
|
134
138
|
_CodesColumn.ID,
|
|
135
139
|
_CodesColumn.PART2B,
|
|
136
140
|
_CodesColumn.PART2T,
|
|
@@ -140,42 +144,48 @@ class Language:
|
|
|
140
144
|
_NameIndexColumn.PRINT_NAME,
|
|
141
145
|
_NameIndexColumn.INVERTED_NAME,
|
|
142
146
|
]
|
|
143
|
-
return _PART3_TO_LANGUAGES[_get_part3(user_input, query_order)]
|
|
147
|
+
return _PART3_TO_LANGUAGES[_get_part3(user_input, query_order, strict_case)]
|
|
144
148
|
|
|
145
149
|
@classmethod
|
|
146
150
|
def from_part3(cls, user_input: str, /) -> Language:
|
|
147
151
|
"""Return a ``Language`` instance from an ISO 639-3 code."""
|
|
148
152
|
return _PART3_TO_LANGUAGES[
|
|
149
|
-
|
|
153
|
+
_get_part3_exact(user_input, [_CodesColumn.ID, _RetirementsColumn.ID])
|
|
150
154
|
]
|
|
151
155
|
|
|
152
156
|
@classmethod
|
|
153
157
|
def from_part2b(cls, user_input: str, /) -> Language:
|
|
154
158
|
"""Return a ``Language`` instance from an ISO 639-2 (bibliographic) code."""
|
|
155
|
-
return _PART3_TO_LANGUAGES[
|
|
159
|
+
return _PART3_TO_LANGUAGES[_get_part3_exact(user_input, [_CodesColumn.PART2B])]
|
|
156
160
|
|
|
157
161
|
@classmethod
|
|
158
162
|
def from_part2t(cls, user_input: str, /) -> Language:
|
|
159
163
|
"""Return a ``Language`` instance from an ISO 639-2 (terminological) code."""
|
|
160
|
-
return _PART3_TO_LANGUAGES[
|
|
164
|
+
return _PART3_TO_LANGUAGES[_get_part3_exact(user_input, [_CodesColumn.PART2T])]
|
|
161
165
|
|
|
162
166
|
@classmethod
|
|
163
167
|
def from_part1(cls, user_input: str, /) -> Language:
|
|
164
168
|
"""Return a ``Language`` instance from an ISO 639-1 code."""
|
|
165
|
-
return _PART3_TO_LANGUAGES[
|
|
169
|
+
return _PART3_TO_LANGUAGES[_get_part3_exact(user_input, [_CodesColumn.PART1])]
|
|
166
170
|
|
|
167
171
|
@classmethod
|
|
168
172
|
def from_name(cls, user_input: str, /) -> Language:
|
|
169
173
|
"""Return a ``Language`` instance from an ISO 639-3 reference language name."""
|
|
170
|
-
query_order:
|
|
174
|
+
query_order: list[_COLUMN_TYPE] = [
|
|
171
175
|
_CodesColumn.REF_NAME,
|
|
172
176
|
_NameIndexColumn.PRINT_NAME,
|
|
173
177
|
_NameIndexColumn.INVERTED_NAME,
|
|
174
178
|
]
|
|
175
|
-
return _PART3_TO_LANGUAGES[
|
|
179
|
+
return _PART3_TO_LANGUAGES[_get_part3_exact(user_input, query_order)]
|
|
180
|
+
|
|
176
181
|
|
|
182
|
+
def _raise_language_not_found_error(user_input: str) -> NoReturn:
|
|
183
|
+
raise LanguageNotFoundError(f"{user_input!r} isn't an ISO language code or name")
|
|
177
184
|
|
|
178
|
-
|
|
185
|
+
|
|
186
|
+
def _get_part3(
|
|
187
|
+
user_input: str, query_order: list[_COLUMN_TYPE], strict_case: bool = True
|
|
188
|
+
) -> str:
|
|
179
189
|
"""Get the part 3 code of a language.
|
|
180
190
|
|
|
181
191
|
Parameters
|
|
@@ -184,6 +194,53 @@ def _get_part3(user_input: str, query_order: List[_COLUMN_TYPE]) -> str:
|
|
|
184
194
|
The user-provided language code or name.
|
|
185
195
|
query_order : List[_COLUMN_TYPE]
|
|
186
196
|
A list of columns to specify query order.
|
|
197
|
+
strict_case : bool, optional
|
|
198
|
+
Defaults to ``True``, for enforcing strict case sensitivity.
|
|
199
|
+
If ``False`` and if ``user_input`` doesn't find a match,
|
|
200
|
+
further match attempts will be made with the all-lowercase version of
|
|
201
|
+
``user_input`` (``"foobar"``) and the title-case version of ``user_input``
|
|
202
|
+
(``"Foobar"``).
|
|
203
|
+
|
|
204
|
+
Returns
|
|
205
|
+
-------
|
|
206
|
+
str
|
|
207
|
+
|
|
208
|
+
Raises
|
|
209
|
+
------
|
|
210
|
+
LanguageNotFoundError
|
|
211
|
+
If `part3` isn't a language name or code
|
|
212
|
+
"""
|
|
213
|
+
try:
|
|
214
|
+
return _get_part3_exact(user_input, query_order)
|
|
215
|
+
except LanguageNotFoundError as e:
|
|
216
|
+
if strict_case:
|
|
217
|
+
raise e
|
|
218
|
+
else:
|
|
219
|
+
for func in _STRING_CLEANING_FUNCS:
|
|
220
|
+
try:
|
|
221
|
+
return _get_part3_exact(func(user_input), query_order, user_input)
|
|
222
|
+
except LanguageNotFoundError:
|
|
223
|
+
continue
|
|
224
|
+
else:
|
|
225
|
+
_raise_language_not_found_error(user_input)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def _get_part3_exact(
|
|
229
|
+
user_input: str,
|
|
230
|
+
query_order: list[_COLUMN_TYPE],
|
|
231
|
+
original_user_input: str | None = None,
|
|
232
|
+
) -> str:
|
|
233
|
+
"""Get the part 3 code of a language.
|
|
234
|
+
|
|
235
|
+
Parameters
|
|
236
|
+
----------
|
|
237
|
+
user_input : str
|
|
238
|
+
The user-provided language code or name.
|
|
239
|
+
query_order : list[_COLUMN_TYPE]
|
|
240
|
+
A list of columns to specify query order.
|
|
241
|
+
original_user_input : str, optional
|
|
242
|
+
The original user input. Default is `None`.
|
|
243
|
+
This argument is used when the user input has been cleaned.
|
|
187
244
|
|
|
188
245
|
Returns
|
|
189
246
|
-------
|
|
@@ -194,12 +251,12 @@ def _get_part3(user_input: str, query_order: List[_COLUMN_TYPE]) -> str:
|
|
|
194
251
|
LanguageNotFoundError
|
|
195
252
|
If `part3` isn't a language name or code
|
|
196
253
|
"""
|
|
197
|
-
|
|
254
|
+
user_input = user_input.strip()
|
|
255
|
+
part3: str | None = None
|
|
198
256
|
for column in query_order:
|
|
199
257
|
if column == _CodesColumn.ID:
|
|
200
258
|
if user_input in _PART3_TO_CODES:
|
|
201
|
-
|
|
202
|
-
break
|
|
259
|
+
return user_input
|
|
203
260
|
elif column == _CodesColumn.PART2B:
|
|
204
261
|
part3 = _PART2B_TO_PART3.get(user_input)
|
|
205
262
|
elif column == _CodesColumn.PART2T:
|
|
@@ -208,8 +265,7 @@ def _get_part3(user_input: str, query_order: List[_COLUMN_TYPE]) -> str:
|
|
|
208
265
|
part3 = _PART1_TO_PART3.get(user_input)
|
|
209
266
|
elif column == _RetirementsColumn.ID:
|
|
210
267
|
if user_input in _PART3_TO_RETIREMENTS:
|
|
211
|
-
|
|
212
|
-
break
|
|
268
|
+
return user_input
|
|
213
269
|
elif column == _CodesColumn.REF_NAME:
|
|
214
270
|
part3 = _REF_NAME_TO_PART3.get(user_input)
|
|
215
271
|
elif column == _NameIndexColumn.PRINT_NAME:
|
|
@@ -222,9 +278,7 @@ def _get_part3(user_input: str, query_order: List[_COLUMN_TYPE]) -> str:
|
|
|
222
278
|
break
|
|
223
279
|
|
|
224
280
|
if part3 is None:
|
|
225
|
-
|
|
226
|
-
f"{user_input!r} isn't an ISO language code or name"
|
|
227
|
-
)
|
|
281
|
+
_raise_language_not_found_error(original_user_input or user_input)
|
|
228
282
|
|
|
229
283
|
return part3
|
|
230
284
|
|
|
@@ -251,7 +305,7 @@ def _get_language(part3: str) -> Language:
|
|
|
251
305
|
else from_retirements[_RetirementsColumn.REF_NAME] # type: ignore
|
|
252
306
|
)
|
|
253
307
|
|
|
254
|
-
other_names:
|
|
308
|
+
other_names: list[Name] | None = []
|
|
255
309
|
for row in _PART3_TO_NAME_INDEX.get(part3, []):
|
|
256
310
|
p, i = row[_NameIndexColumn.PRINT_NAME], row[_NameIndexColumn.INVERTED_NAME]
|
|
257
311
|
if not ref_name == p == i:
|
|
@@ -314,7 +368,7 @@ def _get_language(part3: str) -> Language:
|
|
|
314
368
|
return language
|
|
315
369
|
|
|
316
370
|
|
|
317
|
-
def _get_all_languages() ->
|
|
371
|
+
def _get_all_languages() -> dict[str, Language]:
|
|
318
372
|
languages = {}
|
|
319
373
|
for part3 in _PART3_TO_CODES:
|
|
320
374
|
languages[part3] = _get_language(part3)
|
|
@@ -323,6 +377,6 @@ def _get_all_languages() -> Dict[str, Language]:
|
|
|
323
377
|
return languages
|
|
324
378
|
|
|
325
379
|
|
|
326
|
-
_PART3_TO_LANGUAGES:
|
|
380
|
+
_PART3_TO_LANGUAGES: dict[str, Language] = _get_all_languages()
|
|
327
381
|
|
|
328
|
-
ALL_LANGUAGES:
|
|
382
|
+
ALL_LANGUAGES: set[Language] = set(_PART3_TO_LANGUAGES.values())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: python-iso639
|
|
3
|
-
Version: 2025.
|
|
3
|
+
Version: 2025.11.11
|
|
4
4
|
Summary: ISO 639 language codes, names, and other associated information
|
|
5
5
|
Author-email: "Jackson L. Lee" <jacksonlunlee@gmail.com>
|
|
6
6
|
License: Apache 2.0
|
|
@@ -15,26 +15,27 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
15
15
|
Classifier: Operating System :: OS Independent
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
17
17
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
21
|
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
23
|
Classifier: Topic :: Text Processing
|
|
24
24
|
Classifier: Topic :: Text Processing :: General
|
|
25
25
|
Classifier: Topic :: Text Processing :: Indexing
|
|
26
26
|
Classifier: Topic :: Text Processing :: Linguistic
|
|
27
|
-
Requires-Python: >=3.
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
28
|
Description-Content-Type: text/markdown
|
|
29
29
|
License-File: LICENSE.txt
|
|
30
30
|
Provides-Extra: dev
|
|
31
|
-
Requires-Dist: black==25.
|
|
32
|
-
Requires-Dist: build==1.
|
|
33
|
-
Requires-Dist: flake8==7.
|
|
34
|
-
Requires-Dist: mypy==1.
|
|
35
|
-
Requires-Dist: pytest==
|
|
36
|
-
Requires-Dist: requests==2.32.
|
|
37
|
-
Requires-Dist: twine==6.
|
|
31
|
+
Requires-Dist: black==25.11.0; extra == "dev"
|
|
32
|
+
Requires-Dist: build==1.3.0; extra == "dev"
|
|
33
|
+
Requires-Dist: flake8==7.3.0; extra == "dev"
|
|
34
|
+
Requires-Dist: mypy==1.18.2; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest==9.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: requests==2.32.5; extra == "dev"
|
|
37
|
+
Requires-Dist: twine==6.2.0; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
38
39
|
|
|
39
40
|
# python-iso639
|
|
40
41
|
|
|
@@ -83,13 +84,13 @@ Create a `Language` instance by one of the class methods.
|
|
|
83
84
|
Language(part3='fra', part2b='fre', part2t='fra', part1='fr', scope='I', type='L', name='French', comment=None, other_names=None, macrolanguage=None, retire_reason=None, retire_change_to=None, retire_remedy=None, retire_date=None)
|
|
84
85
|
```
|
|
85
86
|
|
|
86
|
-
Fast object instantiation for retrieving language information (run on Python 3.13, macOS 15.
|
|
87
|
+
Fast object instantiation for retrieving language information (run on Python 3.13, macOS 15.3.1, Apple M1 Pro)
|
|
87
88
|
|
|
88
89
|
```python
|
|
89
90
|
In [1]: import iso639
|
|
90
91
|
|
|
91
92
|
In [2]: %timeit iso639.Language.from_part3("fra")
|
|
92
|
-
|
|
93
|
+
217 ns ± 0.139 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
|
|
93
94
|
```
|
|
94
95
|
|
|
95
96
|
#### From Another ISO 639 Code Set or a Reference Name
|
|
@@ -154,11 +155,27 @@ Use the `match` classmethod:
|
|
|
154
155
|
True
|
|
155
156
|
```
|
|
156
157
|
|
|
158
|
+
By default, the classmethod `match` supports case-insensitive matching
|
|
159
|
+
and ignores leading/trailing whitespace.
|
|
160
|
+
To enforce exact matching instead, pass in `exact=True`:
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
>>> lang5 = iso639.Language.match('FRA')
|
|
164
|
+
>>> lang6 = iso639.Language.match('fra ')
|
|
165
|
+
>>> lang7 = iso639.Language.match('french')
|
|
166
|
+
>>> lang4 == lang5 == lang6 == lang7
|
|
167
|
+
True
|
|
168
|
+
>>> iso639.Language.match("french", exact=True)
|
|
169
|
+
Traceback (most recent call last):
|
|
170
|
+
File "<stdin>", line 1, in <module>
|
|
171
|
+
LanguageNotFoundError: 'french' isn't an ISO language code or name
|
|
172
|
+
```
|
|
173
|
+
|
|
157
174
|
The classmethod `match` is particularly useful for consistently
|
|
158
175
|
accessing a specific attribute from unknown inputs, e.g., the ISO 639-3 code.
|
|
159
176
|
|
|
160
177
|
```python
|
|
161
|
-
>>> 'fra' == lang1.part3 == lang2.part3 == lang3.part3 == lang4.part3
|
|
178
|
+
>>> 'fra' == lang1.part3 == lang2.part3 == lang3.part3 == lang4.part3 == lang5.part3 == lang6.part3 == lang7.part3
|
|
162
179
|
True
|
|
163
180
|
```
|
|
164
181
|
|
|
@@ -261,7 +278,6 @@ Beyond that, the precise order in matching is as follows:
|
|
|
261
278
|
* ISO 639-3 alternative language names (the "print" ones)
|
|
262
279
|
* ISO 639-3 alternative language names (the "inverted" ones)
|
|
263
280
|
|
|
264
|
-
Only exact matching is done (there's no fuzzy string matching of any sort).
|
|
265
281
|
As soon as a match is found, `Language.match` returns a `Language` instance.
|
|
266
282
|
If there isn't a match, a `LanguageNotFoundError` is raised.
|
|
267
283
|
|
|
@@ -287,7 +303,7 @@ e.g., [`dataclasses.asdict`](https://docs.python.org/3/library/dataclasses.html#
|
|
|
287
303
|
```python
|
|
288
304
|
>>> import iso639
|
|
289
305
|
>>> iso639.DATA_LAST_UPDATED
|
|
290
|
-
datetime.date(2025,
|
|
306
|
+
datetime.date(2025, 10, 15)
|
|
291
307
|
```
|
|
292
308
|
|
|
293
309
|
* `ALL_LANGUAGES`: The list of all `Language` objects based on the included language code data
|
|
@@ -297,7 +313,7 @@ e.g., [`dataclasses.asdict`](https://docs.python.org/3/library/dataclasses.html#
|
|
|
297
313
|
>>> type(iso639.ALL_LANGUAGES)
|
|
298
314
|
<class 'set'>
|
|
299
315
|
>>> len(iso639.ALL_LANGUAGES)
|
|
300
|
-
|
|
316
|
+
8311
|
|
301
317
|
```
|
|
302
318
|
|
|
303
319
|
## Links
|
|
@@ -6,19 +6,62 @@ from iso639.language import Name
|
|
|
6
6
|
import pytest
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
@pytest.mark.parametrize(
|
|
10
|
+
"user_input, strict_case, expected_part3",
|
|
11
|
+
[
|
|
12
|
+
("fra", True, "fra"),
|
|
13
|
+
(" fra ", True, "fra"),
|
|
14
|
+
("fra", False, "fra"),
|
|
15
|
+
("FRA", True, None),
|
|
16
|
+
("FRA", False, "fra"),
|
|
17
|
+
(" FRA ", False, "fra"),
|
|
18
|
+
("Fra", True, None),
|
|
19
|
+
("Fra", False, "fra"),
|
|
20
|
+
(" Fra ", False, "fra"),
|
|
21
|
+
("French", True, "fra"),
|
|
22
|
+
("French", False, "fra"),
|
|
23
|
+
("FRENCH", True, None),
|
|
24
|
+
("FRENCH", False, "fra"),
|
|
25
|
+
(" FRENCH ", False, "fra"),
|
|
26
|
+
("french", True, None),
|
|
27
|
+
("french", False, "fra"),
|
|
28
|
+
(" french ", False, "fra"),
|
|
29
|
+
("Castilian", True, "spa"),
|
|
30
|
+
],
|
|
31
|
+
)
|
|
32
|
+
def test_match(user_input, strict_case, expected_part3):
|
|
33
|
+
if expected_part3 is None:
|
|
34
|
+
with pytest.raises(LanguageNotFoundError):
|
|
35
|
+
Language.match(user_input, strict_case=strict_case)
|
|
36
|
+
else:
|
|
37
|
+
actual_part3 = Language.match(user_input, strict_case=strict_case).part3
|
|
38
|
+
assert actual_part3 == expected_part3
|
|
39
|
+
|
|
40
|
+
|
|
9
41
|
@pytest.mark.parametrize(
|
|
10
42
|
"user_input, expected_part3",
|
|
11
43
|
[
|
|
12
44
|
("fra", "fra"),
|
|
13
|
-
("
|
|
14
|
-
("
|
|
45
|
+
(" fra ", "fra"),
|
|
46
|
+
("FRA", None),
|
|
47
|
+
(" FRA ", None),
|
|
48
|
+
("Fra", None),
|
|
49
|
+
(" Fra ", None),
|
|
15
50
|
("French", "fra"),
|
|
51
|
+
("FRENCH", None),
|
|
52
|
+
(" FRENCH ", None),
|
|
53
|
+
("french", None),
|
|
54
|
+
(" french ", None),
|
|
16
55
|
("Castilian", "spa"),
|
|
17
56
|
],
|
|
18
57
|
)
|
|
19
|
-
def
|
|
20
|
-
|
|
21
|
-
|
|
58
|
+
def test_match_no_strict_case_kwarg(user_input, expected_part3):
|
|
59
|
+
if expected_part3 is None:
|
|
60
|
+
with pytest.raises(LanguageNotFoundError):
|
|
61
|
+
Language.match(user_input)
|
|
62
|
+
else:
|
|
63
|
+
actual_part3 = Language.match(user_input).part3
|
|
64
|
+
assert actual_part3 == expected_part3
|
|
22
65
|
|
|
23
66
|
|
|
24
67
|
def test_name():
|
|
@@ -89,12 +132,15 @@ def test_invalid_inputs():
|
|
|
89
132
|
|
|
90
133
|
|
|
91
134
|
def test_data_last_updated():
|
|
92
|
-
assert DATA_LAST_UPDATED == datetime.date(2025,
|
|
135
|
+
assert DATA_LAST_UPDATED == datetime.date(2025, 10, 15), "Need to update README.md"
|
|
93
136
|
|
|
94
137
|
|
|
95
138
|
def test_all_languages():
|
|
96
139
|
assert type(ALL_LANGUAGES) is set
|
|
97
|
-
|
|
140
|
+
# Defining `len_all_languages` so that when the assertion fails,
|
|
141
|
+
# the error message is more informative.
|
|
142
|
+
len_all_languages = len(ALL_LANGUAGES)
|
|
143
|
+
assert len_all_languages == 8311, "Need to update README.md"
|
|
98
144
|
lang = list(ALL_LANGUAGES)[0]
|
|
99
145
|
assert type(lang) is Language
|
|
100
146
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/iso639/_data/iso-639-3-macrolanguages.tab
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/python_iso639.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
{python_iso639-2025.2.8 → python_iso639-2025.11.11}/src/python_iso639.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|