python-iso639 2024.10.22__tar.gz → 2025.1.28__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.
Files changed (24) hide show
  1. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/CHANGELOG.md +15 -0
  2. {python_iso639-2024.10.22/src/python_iso639.egg-info → python_iso639-2025.1.28}/PKG-INFO +16 -14
  3. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/README.md +9 -8
  4. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/pyproject.toml +7 -6
  5. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/src/iso639/__init__.py +2 -9
  6. python_iso639-2025.1.28/src/iso639/_data/__init__.py +119 -0
  7. python_iso639-2025.1.28/src/iso639/_data/iso-639-3-macrolanguages.tab +460 -0
  8. python_iso639-2025.1.28/src/iso639/_data/iso-639-3.tab +7923 -0
  9. python_iso639-2025.1.28/src/iso639/_data/iso-639-3_Name_Index.tab +8297 -0
  10. python_iso639-2025.1.28/src/iso639/_data/iso-639-3_Retirements.tab +389 -0
  11. python_iso639-2025.1.28/src/iso639/language.py +328 -0
  12. {python_iso639-2024.10.22 → python_iso639-2025.1.28/src/python_iso639.egg-info}/PKG-INFO +16 -14
  13. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/src/python_iso639.egg-info/SOURCES.txt +5 -1
  14. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/src/python_iso639.egg-info/requires.txt +4 -3
  15. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/tests/test_language.py +33 -15
  16. python_iso639-2024.10.22/src/iso639/language.py +0 -275
  17. python_iso639-2024.10.22/src/iso639/languages.db +0 -0
  18. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/LICENSE.txt +0 -0
  19. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/MANIFEST.in +0 -0
  20. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/setup.cfg +0 -0
  21. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/src/python_iso639.egg-info/dependency_links.txt +0 -0
  22. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/src/python_iso639.egg-info/not-zip-safe +0 -0
  23. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/src/python_iso639.egg-info/top_level.txt +0 -0
  24. {python_iso639-2024.10.22 → python_iso639-2025.1.28}/tests/test_version_number.py +0 -0
@@ -17,6 +17,21 @@ major/minor/micro version numbers like `05` (it'd have to be just `5`).
17
17
  ### Fixed
18
18
  ### Security
19
19
 
20
+ ## [2025.1.28]
21
+
22
+ ### Changed
23
+ * Sped up the retrieval of `Language` objects during runtime.
24
+
25
+ ## [2025.1.27]
26
+
27
+ ### Changed
28
+ * Updated the ISO 639 data from SIL to the latest 2025-01-15 release.
29
+ * The data tables are now included as the original tab-separated value files
30
+ instead of a compiled SQLite database.
31
+
32
+ ### Fixed
33
+ * Fixed `Language.from_part3` so that it now also works for a retired ISO 639-3 code.
34
+
20
35
  ## [2024.10.22]
21
36
 
22
37
  ### Added
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: python-iso639
3
- Version: 2024.10.22
3
+ Version: 2025.1.28
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
@@ -24,16 +24,17 @@ 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.8
27
+ Requires-Python: >=3.9
28
28
  Description-Content-Type: text/markdown
29
29
  License-File: LICENSE.txt
30
30
  Provides-Extra: dev
31
31
  Requires-Dist: black==24.10.0; extra == "dev"
32
- Requires-Dist: build==1.2.1; extra == "dev"
32
+ Requires-Dist: build==1.2.2; extra == "dev"
33
33
  Requires-Dist: flake8==7.1.1; extra == "dev"
34
- Requires-Dist: pytest==8.3.3; extra == "dev"
34
+ Requires-Dist: mypy==1.14.1; extra == "dev"
35
+ Requires-Dist: pytest==8.3.4; extra == "dev"
35
36
  Requires-Dist: requests==2.32.3; extra == "dev"
36
- Requires-Dist: twine==5.1.1; extra == "dev"
37
+ Requires-Dist: twine==6.1.0; extra == "dev"
37
38
 
38
39
  # python-iso639
39
40
 
@@ -68,7 +69,7 @@ the actual import name during runtime is `iso639`
68
69
 
69
70
  ### Creating `Language` Instances
70
71
 
71
- Create a `Language` instance by one of the methods.
72
+ Create a `Language` instance by one of the class methods.
72
73
 
73
74
  #### `from_part3`, with an ISO 639-3 code
74
75
 
@@ -276,7 +277,7 @@ e.g., [`dataclasses.asdict`](https://docs.python.org/3/library/dataclasses.html#
276
277
  ```python
277
278
  >>> import iso639
278
279
  >>> iso639.DATA_LAST_UPDATED
279
- datetime.date(2024, 4, 15)
280
+ datetime.date(2025, 1, 15)
280
281
  ```
281
282
 
282
283
  * `ALL_LANGUAGES`: The list of all `Language` objects based on the included language code data
@@ -284,11 +285,9 @@ e.g., [`dataclasses.asdict`](https://docs.python.org/3/library/dataclasses.html#
284
285
  ```python
285
286
  >>> import iso639
286
287
  >>> type(iso639.ALL_LANGUAGES)
287
- <class 'list'>
288
+ <class 'set'>
288
289
  >>> len(iso639.ALL_LANGUAGES)
289
- 7920
290
- >>> iso639.ALL_LANGUAGES[0]
291
- Language(part3='aaa', scope='I', type='L', status='A', name='Ghotuo', ...)
290
+ 8307
292
291
  ```
293
292
 
294
293
  ## Links
@@ -304,9 +303,12 @@ for details.
304
303
 
305
304
  The data source that backs this package is the
306
305
  [language code tables published by SIL](https://iso639-3.sil.org/code_tables/download_tables).
306
+ The tables are included in this package under [`src/iso639/_data/`](src/iso639/_data/).
307
+ They are the UTF8-encoded `*.tab` tab-separated files bundled as a ZIP archive file,
308
+ typically found at a URL that looks like
309
+ `https://iso639-3.sil.org/sites/iso639-3/files/downloads/iso-639-3_Code_Tables_YYYYMMDD.zip`
310
+ (replace `YYYYMMDD` with the data release date).
307
311
  Note that SIL resources have their [terms of use](https://www.sil.org/terms-use).
308
- For exactly how the data is included in the package,
309
- see the script at [`scripts/create_languages_db.py`](scripts/create_languages_db.py).
310
312
 
311
313
  ## Why Another ISO 639 Package?
312
314
 
@@ -31,7 +31,7 @@ the actual import name during runtime is `iso639`
31
31
 
32
32
  ### Creating `Language` Instances
33
33
 
34
- Create a `Language` instance by one of the methods.
34
+ Create a `Language` instance by one of the class methods.
35
35
 
36
36
  #### `from_part3`, with an ISO 639-3 code
37
37
 
@@ -239,7 +239,7 @@ e.g., [`dataclasses.asdict`](https://docs.python.org/3/library/dataclasses.html#
239
239
  ```python
240
240
  >>> import iso639
241
241
  >>> iso639.DATA_LAST_UPDATED
242
- datetime.date(2024, 4, 15)
242
+ datetime.date(2025, 1, 15)
243
243
  ```
244
244
 
245
245
  * `ALL_LANGUAGES`: The list of all `Language` objects based on the included language code data
@@ -247,11 +247,9 @@ e.g., [`dataclasses.asdict`](https://docs.python.org/3/library/dataclasses.html#
247
247
  ```python
248
248
  >>> import iso639
249
249
  >>> type(iso639.ALL_LANGUAGES)
250
- <class 'list'>
250
+ <class 'set'>
251
251
  >>> len(iso639.ALL_LANGUAGES)
252
- 7920
253
- >>> iso639.ALL_LANGUAGES[0]
254
- Language(part3='aaa', scope='I', type='L', status='A', name='Ghotuo', ...)
252
+ 8307
255
253
  ```
256
254
 
257
255
  ## Links
@@ -267,9 +265,12 @@ for details.
267
265
 
268
266
  The data source that backs this package is the
269
267
  [language code tables published by SIL](https://iso639-3.sil.org/code_tables/download_tables).
268
+ The tables are included in this package under [`src/iso639/_data/`](src/iso639/_data/).
269
+ They are the UTF8-encoded `*.tab` tab-separated files bundled as a ZIP archive file,
270
+ typically found at a URL that looks like
271
+ `https://iso639-3.sil.org/sites/iso639-3/files/downloads/iso-639-3_Code_Tables_YYYYMMDD.zip`
272
+ (replace `YYYYMMDD` with the data release date).
270
273
  Note that SIL resources have their [terms of use](https://www.sil.org/terms-use).
271
- For exactly how the data is included in the package,
272
- see the script at [`scripts/create_languages_db.py`](scripts/create_languages_db.py).
273
274
 
274
275
  ## Why Another ISO 639 Package?
275
276
 
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-iso639"
7
- version = "2024.10.22"
7
+ version = "2025.1.28"
8
8
  description = "ISO 639 language codes, names, and other associated information"
9
9
  readme = "README.md"
10
- requires-python = ">= 3.8"
10
+ requires-python = ">= 3.9"
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"]
@@ -35,11 +35,12 @@ classifiers = [
35
35
  [project.optional-dependencies]
36
36
  dev = [
37
37
  "black == 24.10.0",
38
- "build == 1.2.1",
38
+ "build == 1.2.2",
39
39
  "flake8 == 7.1.1",
40
- "pytest == 8.3.3",
40
+ "mypy == 1.14.1",
41
+ "pytest == 8.3.4",
41
42
  "requests == 2.32.3",
42
- "twine == 5.1.1",
43
+ "twine == 6.1.0",
43
44
  ]
44
45
 
45
46
  [project.urls]
@@ -51,7 +52,7 @@ where = [ "src" ]
51
52
  [tool.setuptools]
52
53
  zip-safe = false
53
54
  package-dir = { "" = "src" }
54
- package-data = { "iso639" = ["languages.db"] }
55
+ package-data = { "iso639" = ["_data/*.tab"] }
55
56
 
56
57
  [tool.pytest.ini_options]
57
58
  addopts = "-vv --durations=0 --strict-markers"
@@ -1,7 +1,7 @@
1
1
  import datetime
2
2
  from importlib.metadata import version
3
3
 
4
- from .language import Language, LanguageNotFoundError, _get_all_languages
4
+ from .language import ALL_LANGUAGES, Language, LanguageNotFoundError
5
5
 
6
6
 
7
7
  # __version__ is based on calendar versioning (https://calver.org/).
@@ -9,14 +9,7 @@ from .language import Language, LanguageNotFoundError, _get_all_languages
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(2024, 4, 15)
13
-
14
-
15
- def __getattr__(name):
16
- if name == "ALL_LANGUAGES":
17
- return _get_all_languages()
18
- else:
19
- raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
12
+ DATA_LAST_UPDATED = datetime.date(2025, 1, 15)
20
13
 
21
14
 
22
15
  __all__ = [
@@ -0,0 +1,119 @@
1
+ from __future__ import annotations
2
+
3
+ import csv
4
+ import os
5
+ from collections import defaultdict
6
+ from enum import Enum
7
+
8
+ from typing import Dict, List, Union
9
+
10
+
11
+ class _CodesColumn(Enum):
12
+ ID = "Id"
13
+ PART2B = "Part2b"
14
+ PART2T = "Part2t"
15
+ PART1 = "Part1"
16
+ SCOPE = "Scope"
17
+ TYPE = "Language_Type"
18
+ REF_NAME = "Ref_Name"
19
+ COMMENT = "Comment"
20
+
21
+
22
+ class _NameIndexColumn(Enum):
23
+ ID = "Id"
24
+ PRINT_NAME = "Print_Name"
25
+ INVERTED_NAME = "Inverted_Name"
26
+
27
+
28
+ class _RetirementsColumn(Enum):
29
+ ID = "Id"
30
+ REF_NAME = "Ref_Name"
31
+ RET_REASON = "Ret_Reason"
32
+ CHANGE_TO = "Change_To"
33
+ REMEDY = "Ret_Remedy"
34
+ EFFECTIVE = "Effective"
35
+
36
+
37
+ class _MacrolanguagesColumn(Enum):
38
+ ID = "I_Id"
39
+ MID = "M_Id"
40
+ STATUS = "I_Status"
41
+
42
+
43
+ _COLUMN_TYPE = Union[
44
+ _CodesColumn, _NameIndexColumn, _RetirementsColumn, _MacrolanguagesColumn
45
+ ]
46
+ _ROW_TYPE = Dict[_COLUMN_TYPE, str]
47
+
48
+
49
+ class _Table(Enum):
50
+ CODES = _CodesColumn
51
+ NAME_INDEX = _NameIndexColumn
52
+ RETIREMENTS = _RetirementsColumn
53
+ MACROLANGUAGES = _MacrolanguagesColumn
54
+
55
+
56
+ _THIS_DIR = os.path.dirname(__file__)
57
+ _DATA_TSV_PATHS = {
58
+ _Table.CODES: os.path.join(_THIS_DIR, "iso-639-3.tab"),
59
+ _Table.NAME_INDEX: os.path.join(_THIS_DIR, "iso-639-3_Name_Index.tab"),
60
+ _Table.MACROLANGUAGES: os.path.join(_THIS_DIR, "iso-639-3-macrolanguages.tab"),
61
+ _Table.RETIREMENTS: os.path.join(_THIS_DIR, "iso-639-3_Retirements.tab"),
62
+ }
63
+
64
+
65
+ def _load_tsv(table: _Table) -> List[_ROW_TYPE]:
66
+ column = table.value
67
+ with open(_DATA_TSV_PATHS[table], encoding="utf-8", newline="") as tsv_file:
68
+ tsv_reader = csv.DictReader(tsv_file, delimiter="\t")
69
+ return [{column(k): v for k, v in row.items()} for row in tsv_reader]
70
+
71
+
72
+ _PART3_TO_CODES: Dict[str, _ROW_TYPE] = {
73
+ row[_CodesColumn.ID]: row for row in _load_tsv(_Table.CODES)
74
+ }
75
+
76
+ _part3_to_name_index: defaultdict[str, List[_ROW_TYPE]] = defaultdict(list)
77
+ for row in _load_tsv(_Table.NAME_INDEX):
78
+ _part3_to_name_index[row[_NameIndexColumn.ID]].append(row)
79
+ _PART3_TO_NAME_INDEX: Dict[str, List[_ROW_TYPE]] = dict(_part3_to_name_index)
80
+
81
+ _PART3_TO_RETIREMENTS: Dict[str, _ROW_TYPE] = {
82
+ row[_RetirementsColumn.ID]: row for row in _load_tsv(_Table.RETIREMENTS)
83
+ }
84
+ _PART3_TO_MACROLANGUAGES: Dict[str, _ROW_TYPE] = {
85
+ row[_MacrolanguagesColumn.ID]: row for row in _load_tsv(_Table.MACROLANGUAGES)
86
+ }
87
+
88
+ _PART2B_TO_PART3: Dict[str, str] = {
89
+ row[_CodesColumn.PART2B]: part3
90
+ for part3, row in _PART3_TO_CODES.items()
91
+ if row[_CodesColumn.PART2B]
92
+ }
93
+ _PART2T_TO_PART3: Dict[str, str] = {
94
+ row[_CodesColumn.PART2T]: part3
95
+ for part3, row in _PART3_TO_CODES.items()
96
+ if row[_CodesColumn.PART2T]
97
+ }
98
+ _PART1_TO_PART3: Dict[str, str] = {
99
+ row[_CodesColumn.PART1]: part3
100
+ for part3, row in _PART3_TO_CODES.items()
101
+ if row[_CodesColumn.PART1]
102
+ }
103
+ _REF_NAME_TO_PART3: Dict[str, str] = {
104
+ row[_CodesColumn.REF_NAME]: part3
105
+ for part3, row in _PART3_TO_CODES.items()
106
+ if row[_CodesColumn.REF_NAME]
107
+ }
108
+ _PRINT_NAME_TO_PART3: Dict[str, str] = {
109
+ row[_NameIndexColumn.PRINT_NAME]: part3
110
+ for part3, rows in _PART3_TO_NAME_INDEX.items()
111
+ for row in rows
112
+ if row[_NameIndexColumn.PRINT_NAME]
113
+ }
114
+ _INVERTED_NAME_TO_PART3: Dict[str, str] = {
115
+ row[_NameIndexColumn.INVERTED_NAME]: part3
116
+ for part3, rows in _PART3_TO_NAME_INDEX.items()
117
+ for row in rows
118
+ if row[_NameIndexColumn.INVERTED_NAME]
119
+ }