kotobase 0.1.0__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 (53) hide show
  1. kotobase-0.1.0/LICENSE +21 -0
  2. kotobase-0.1.0/MANIFEST.in +1 -0
  3. kotobase-0.1.0/PKG-INFO +149 -0
  4. kotobase-0.1.0/README.md +123 -0
  5. kotobase-0.1.0/pyproject.toml +42 -0
  6. kotobase-0.1.0/setup.cfg +4 -0
  7. kotobase-0.1.0/src/kotobase/__init__.py +20 -0
  8. kotobase-0.1.0/src/kotobase/api.py +130 -0
  9. kotobase-0.1.0/src/kotobase/cli.py +202 -0
  10. kotobase-0.1.0/src/kotobase/core/__init__.py +2 -0
  11. kotobase-0.1.0/src/kotobase/core/datatypes.py +257 -0
  12. kotobase-0.1.0/src/kotobase/db/__init__.py +3 -0
  13. kotobase-0.1.0/src/kotobase/db/database.py +51 -0
  14. kotobase-0.1.0/src/kotobase/db/models.py +180 -0
  15. kotobase-0.1.0/src/kotobase/db_builder/__init__.py +17 -0
  16. kotobase-0.1.0/src/kotobase/db_builder/build_database.py +254 -0
  17. kotobase-0.1.0/src/kotobase/db_builder/config.py +76 -0
  18. kotobase-0.1.0/src/kotobase/db_builder/data/__init__.py +0 -0
  19. kotobase-0.1.0/src/kotobase/db_builder/data/processed/__init__.py +0 -0
  20. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/__init__.py +0 -0
  21. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/grammar_n1.json +73 -0
  22. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/grammar_n2.json +65 -0
  23. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/grammar_n3.json +65 -0
  24. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/grammar_n4.json +52 -0
  25. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/grammar_n5.json +42 -0
  26. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/kanji_n1.json +7688 -0
  27. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/kanji_n2.json +2438 -0
  28. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/kanji_n3.json +2774 -0
  29. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/kanji_n4.json +1082 -0
  30. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/kanji_n5.json +524 -0
  31. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/vocab_n1.json +17227 -0
  32. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/vocab_n2.json +8987 -0
  33. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/vocab_n3.json +9137 -0
  34. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/vocab_n4.json +3172 -0
  35. kotobase-0.1.0/src/kotobase/db_builder/data/processed/jlpt/vocab_n5.json +3347 -0
  36. kotobase-0.1.0/src/kotobase/db_builder/download.py +56 -0
  37. kotobase-0.1.0/src/kotobase/db_builder/process_jmdict.py +137 -0
  38. kotobase-0.1.0/src/kotobase/db_builder/process_jmnedict.py +133 -0
  39. kotobase-0.1.0/src/kotobase/db_builder/process_kanjidic.py +92 -0
  40. kotobase-0.1.0/src/kotobase/db_builder/process_tatoeba.py +47 -0
  41. kotobase-0.1.0/src/kotobase/db_builder/pull.py +34 -0
  42. kotobase-0.1.0/src/kotobase/repos/__init__.py +11 -0
  43. kotobase-0.1.0/src/kotobase/repos/jlpt.py +56 -0
  44. kotobase-0.1.0/src/kotobase/repos/jmdict.py +81 -0
  45. kotobase-0.1.0/src/kotobase/repos/jmnedict.py +53 -0
  46. kotobase-0.1.0/src/kotobase/repos/kanji.py +76 -0
  47. kotobase-0.1.0/src/kotobase/repos/sentences.py +35 -0
  48. kotobase-0.1.0/src/kotobase.egg-info/PKG-INFO +149 -0
  49. kotobase-0.1.0/src/kotobase.egg-info/SOURCES.txt +51 -0
  50. kotobase-0.1.0/src/kotobase.egg-info/dependency_links.txt +1 -0
  51. kotobase-0.1.0/src/kotobase.egg-info/entry_points.txt +2 -0
  52. kotobase-0.1.0/src/kotobase.egg-info/requires.txt +8 -0
  53. kotobase-0.1.0/src/kotobase.egg-info/top_level.txt +1 -0
kotobase-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 svdc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ graft src/kotobase/db_builder/data
@@ -0,0 +1,149 @@
1
+ Metadata-Version: 2.4
2
+ Name: kotobase
3
+ Version: 0.1.0
4
+ Summary: Python package for accessing a comprehensive Japanese language database.
5
+ Author-email: svdc <svdc1mail@gmail.com>
6
+ Maintainer-email: svdc <svdc1mail@gmail.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/svdC1/kotobase
9
+ Project-URL: Issues, https://github.com/svdC1/kotobase/issues
10
+ Keywords: Japanese,Dictionary,Language
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Intended Audience :: Developers
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: requests
18
+ Requires-Dist: sqlalchemy
19
+ Requires-Dist: alembic
20
+ Requires-Dist: beautifulsoup4
21
+ Requires-Dist: lxml
22
+ Requires-Dist: pypdf
23
+ Requires-Dist: click
24
+ Requires-Dist: gdown
25
+ Dynamic: license-file
26
+
27
+ # Kotobase
28
+
29
+ **Kotobase is a Japanese language Python package which provides simple programmatic access to various data sources via a pre-built database which is updated weekly via a GitHub action.**
30
+
31
+ ## Data Sources
32
+
33
+ Kotobase uses data from these sources to build its Database.
34
+
35
+ - [`JMDict`](http://www.edrdg.org/jmdict/j_jmdict.html) : Japanese-Multilingual Dictionary.
36
+
37
+ - [`JMnedict`](http://www.edrdg.org/enamdict/enamdict_doc.html) : A dictionary of Japanese proper names.
38
+
39
+ - [`KanjiDic2`](http://www.edrdg.org/kanjidic/kanjd2index_legacy.html) : A comprehensive kanji dictionary.
40
+
41
+ - [`Tatoeba`](https://tatoeba.org/en/) : A large database of example sentences.
42
+
43
+ - [`JLPT Lists`](http://www.tanos.co.uk/) : Curated list of Grammar, Vocabulary and Kanji separated by Japanese Language Proficiency Test levels, made available on Jonathan Weller's website.
44
+
45
+ ### Licenses
46
+
47
+ > The licenses of these data sources and the NOTICE is available at `docs/licenses` in this repository.
48
+
49
+ ## Features
50
+
51
+ - **Comprehensive Lookups** &rarr; Search for words (kanji, kana, or romaji), kanji, and proper names.
52
+
53
+ - **Organized Data** &rarr; Get detailed information including readings, senses, parts of speech, kanji stroke counts, meanings, and JLPT levels formatted into Python Data Objects.
54
+
55
+ - **Example Sentences** &rarr; Find example sentences from Tatoeba that contain the searched query.
56
+
57
+ - **Wildcard Search** &rarr; Use `*` or `%` for wildcard searches.
58
+
59
+ - **Command-Line Interface** &rarr; User-friendly CLI for quick lookups from the terminal.
60
+
61
+ - **Self-Contained** &rarr; All data is stored in a local SQLite database, so it's fast and works offline.
62
+
63
+ - **Easy Database Management** &rarr; Includes commands to automatically download the latest pre-built database from the public Drive or download source files and build the database locally.
64
+
65
+ ## Installation
66
+
67
+ ```bash
68
+ pip install kotobase
69
+ ```
70
+
71
+ This will install the `kotobase` package and its dependencies, and it will also make the `kotobase` command-line tool available in your shell.
72
+
73
+ ## Usage
74
+
75
+ Kotobase can be used as a command-line tool or as a Python library.
76
+
77
+ ### Command-Line Interface
78
+
79
+ The `kotobase` command provides several subcommands for different types of lookups.
80
+
81
+ #### General Lookup
82
+
83
+ The `lookup` command is the most comprehensive way to search for a word.
84
+
85
+ ```bash
86
+ kotobase lookup 日本語
87
+ ```
88
+
89
+ This will show you dictionary entries, kanji information, JLPT levels, and example sentences for the word "日本語".
90
+
91
+ **Options:**
92
+
93
+ - `-n`, `--names`: Include proper names from JMnedict in the search.
94
+ - `-w`, `--wildcard`: Treat `*` or `%` as wildcards in the search term.
95
+ - `-s`, `--sentences`: Specify the number of example sentences to show.
96
+ - `--json-out`: Output the full results as a JSON object.
97
+
98
+ #### Kanji Lookup
99
+
100
+ To get information about a specific kanji character:
101
+
102
+ ```bash
103
+ kotobase kanji 語
104
+ ```
105
+
106
+ This will display the kanji's grade, stroke count, meanings, on'yomi, and kun'yomi readings, and JLPT level.
107
+
108
+ #### JLPT Lookup
109
+
110
+ To check the JLPT level for a word or kanji:
111
+
112
+ ```bash
113
+ kotobase jlpt 勉強
114
+ ```
115
+
116
+ ### Python API
117
+
118
+ You can also use Kotobase in your own Python code.
119
+
120
+ ```python
121
+ from kotobase import Kotobase
122
+
123
+ kb = Kotobase()
124
+
125
+ # Comprehensive lookup
126
+ result = kb.lookup("日本語")
127
+ print(result.to_json(indent=2, ensure_ascii=False))
128
+
129
+ # Get info for a single kanji
130
+ kanji_info = kb.kanji("語")
131
+ print(kanji_info)
132
+
133
+ # Get example sentences
134
+ sentences = kb.sentences("勉強")
135
+ for sentence in sentences:
136
+ print(sentence.text)
137
+ ```
138
+
139
+ ## Database
140
+
141
+ Kotobase relies on a local SQLite database.
142
+
143
+ You can also build it from the source files yourself.
144
+
145
+ The following commands are available for managing the database:
146
+
147
+ - `kotobase pull-db`: Downloads the pre-built SQLite database from a public [`Google Drive Folder`](https://drive.google.com/drive/u/0/folders/14wbgMyp0TubFyFaUy0W_CnK9_z7fo_Fv). This file is overwritten every week with a rebuilt database from updated sources. The rebuilding and overwriting is managed by a GitHub action in this repository.
148
+
149
+ - `kotobase build`: Builds the SQLite database from the raw source files. This will download the latest version of the source files (_Except Tanos JLPT lists which are shipped with the package itself._) and build the database locally.
@@ -0,0 +1,123 @@
1
+ # Kotobase
2
+
3
+ **Kotobase is a Japanese language Python package which provides simple programmatic access to various data sources via a pre-built database which is updated weekly via a GitHub action.**
4
+
5
+ ## Data Sources
6
+
7
+ Kotobase uses data from these sources to build its Database.
8
+
9
+ - [`JMDict`](http://www.edrdg.org/jmdict/j_jmdict.html) : Japanese-Multilingual Dictionary.
10
+
11
+ - [`JMnedict`](http://www.edrdg.org/enamdict/enamdict_doc.html) : A dictionary of Japanese proper names.
12
+
13
+ - [`KanjiDic2`](http://www.edrdg.org/kanjidic/kanjd2index_legacy.html) : A comprehensive kanji dictionary.
14
+
15
+ - [`Tatoeba`](https://tatoeba.org/en/) : A large database of example sentences.
16
+
17
+ - [`JLPT Lists`](http://www.tanos.co.uk/) : Curated list of Grammar, Vocabulary and Kanji separated by Japanese Language Proficiency Test levels, made available on Jonathan Weller's website.
18
+
19
+ ### Licenses
20
+
21
+ > The licenses of these data sources and the NOTICE is available at `docs/licenses` in this repository.
22
+
23
+ ## Features
24
+
25
+ - **Comprehensive Lookups** &rarr; Search for words (kanji, kana, or romaji), kanji, and proper names.
26
+
27
+ - **Organized Data** &rarr; Get detailed information including readings, senses, parts of speech, kanji stroke counts, meanings, and JLPT levels formatted into Python Data Objects.
28
+
29
+ - **Example Sentences** &rarr; Find example sentences from Tatoeba that contain the searched query.
30
+
31
+ - **Wildcard Search** &rarr; Use `*` or `%` for wildcard searches.
32
+
33
+ - **Command-Line Interface** &rarr; User-friendly CLI for quick lookups from the terminal.
34
+
35
+ - **Self-Contained** &rarr; All data is stored in a local SQLite database, so it's fast and works offline.
36
+
37
+ - **Easy Database Management** &rarr; Includes commands to automatically download the latest pre-built database from the public Drive or download source files and build the database locally.
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ pip install kotobase
43
+ ```
44
+
45
+ This will install the `kotobase` package and its dependencies, and it will also make the `kotobase` command-line tool available in your shell.
46
+
47
+ ## Usage
48
+
49
+ Kotobase can be used as a command-line tool or as a Python library.
50
+
51
+ ### Command-Line Interface
52
+
53
+ The `kotobase` command provides several subcommands for different types of lookups.
54
+
55
+ #### General Lookup
56
+
57
+ The `lookup` command is the most comprehensive way to search for a word.
58
+
59
+ ```bash
60
+ kotobase lookup 日本語
61
+ ```
62
+
63
+ This will show you dictionary entries, kanji information, JLPT levels, and example sentences for the word "日本語".
64
+
65
+ **Options:**
66
+
67
+ - `-n`, `--names`: Include proper names from JMnedict in the search.
68
+ - `-w`, `--wildcard`: Treat `*` or `%` as wildcards in the search term.
69
+ - `-s`, `--sentences`: Specify the number of example sentences to show.
70
+ - `--json-out`: Output the full results as a JSON object.
71
+
72
+ #### Kanji Lookup
73
+
74
+ To get information about a specific kanji character:
75
+
76
+ ```bash
77
+ kotobase kanji 語
78
+ ```
79
+
80
+ This will display the kanji's grade, stroke count, meanings, on'yomi, and kun'yomi readings, and JLPT level.
81
+
82
+ #### JLPT Lookup
83
+
84
+ To check the JLPT level for a word or kanji:
85
+
86
+ ```bash
87
+ kotobase jlpt 勉強
88
+ ```
89
+
90
+ ### Python API
91
+
92
+ You can also use Kotobase in your own Python code.
93
+
94
+ ```python
95
+ from kotobase import Kotobase
96
+
97
+ kb = Kotobase()
98
+
99
+ # Comprehensive lookup
100
+ result = kb.lookup("日本語")
101
+ print(result.to_json(indent=2, ensure_ascii=False))
102
+
103
+ # Get info for a single kanji
104
+ kanji_info = kb.kanji("語")
105
+ print(kanji_info)
106
+
107
+ # Get example sentences
108
+ sentences = kb.sentences("勉強")
109
+ for sentence in sentences:
110
+ print(sentence.text)
111
+ ```
112
+
113
+ ## Database
114
+
115
+ Kotobase relies on a local SQLite database.
116
+
117
+ You can also build it from the source files yourself.
118
+
119
+ The following commands are available for managing the database:
120
+
121
+ - `kotobase pull-db`: Downloads the pre-built SQLite database from a public [`Google Drive Folder`](https://drive.google.com/drive/u/0/folders/14wbgMyp0TubFyFaUy0W_CnK9_z7fo_Fv). This file is overwritten every week with a rebuilt database from updated sources. The rebuilding and overwriting is managed by a GitHub action in this repository.
122
+
123
+ - `kotobase build`: Builds the SQLite database from the raw source files. This will download the latest version of the source files (_Except Tanos JLPT lists which are shipped with the package itself._) and build the database locally.
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0.3"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "kotobase"
7
+ version = "0.1.0"
8
+ authors = [{ name = "svdc", email = "svdc1mail@gmail.com" }]
9
+ maintainers = [{ name = "svdc", email = "svdc1mail@gmail.com" }]
10
+ description = "Python package for accessing a comprehensive Japanese language database."
11
+ keywords = ["Japanese", "Dictionary", "Language"]
12
+ readme = "README.md"
13
+ requires-python = ">=3.9"
14
+ classifiers = [
15
+ "Programming Language :: Python :: 3",
16
+ "Operating System :: OS Independent",
17
+ "Intended Audience :: Developers",
18
+ ]
19
+ license = "MIT"
20
+ license-files = ["LICEN[CS]E*"]
21
+ dependencies = [
22
+ "requests",
23
+ "sqlalchemy",
24
+ "alembic",
25
+ "beautifulsoup4",
26
+ "lxml",
27
+ "pypdf",
28
+ "click",
29
+ "gdown",
30
+ ]
31
+
32
+ [project.scripts]
33
+ kotobase = "kotobase.cli:main"
34
+
35
+ [project.urls]
36
+ Homepage = "https://github.com/svdC1/kotobase"
37
+ Issues = "https://github.com/svdC1/kotobase/issues"
38
+
39
+ [tool.setuptools]
40
+ include-package-data = true
41
+ [tool.setuptools.packages.find]
42
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,20 @@
1
+ from .db.database import get_db
2
+ from .api import Kotobase
3
+ from .db import models
4
+ from . import (core,
5
+ api,
6
+ db,
7
+ db_builder,
8
+ repos,
9
+ cli)
10
+
11
+
12
+ __all__ = ["Kotobase",
13
+ "get_db",
14
+ "models",
15
+ "core",
16
+ "api",
17
+ "db",
18
+ "db_builder",
19
+ "repos",
20
+ "cli"]
@@ -0,0 +1,130 @@
1
+ from __future__ import annotations
2
+
3
+ import concurrent.futures as _cf
4
+ from functools import lru_cache
5
+ from typing import (List,
6
+ Dict,
7
+ Optional)
8
+
9
+ from kotobase.core.datatypes import (
10
+ LookupResult,
11
+ KanjiDTO,
12
+ JMDictEntryDTO,
13
+ JMNeDictEntryDTO,
14
+ )
15
+ from kotobase.repos.jmdict import JMDictRepo
16
+ from kotobase.repos.jmnedict import JMNeDictRepo
17
+ from kotobase.repos.kanji import KanjiRepo
18
+ from kotobase.repos.jlpt import JLPTRepo
19
+ from kotobase.repos.sentences import SentenceRepo
20
+
21
+
22
+ class Kotobase:
23
+ """
24
+ Stateless class that orchestrates the individual repositories and
25
+ returns rich, serialisable objects.
26
+ """
27
+ # Core
28
+ def lookup(
29
+ self,
30
+ word: str,
31
+ *,
32
+ wildcard: bool = False,
33
+ include_names: bool = False,
34
+ sentence_limit: int = 50,
35
+ ) -> LookupResult:
36
+ """
37
+ Comprehensive word lookup.
38
+
39
+ Parameters
40
+ ----------
41
+ word : str
42
+ The query string (kana, kanji, or romaji transliteration).
43
+ Supports SQL wildcards '*' or '%'.
44
+ wildcard : bool, default False
45
+ If True, passes wildcards through unchanged. If False,
46
+ the search is exact (JMdict) but Tatoeba uses `%word%`
47
+ containment.
48
+ include_names : bool, default False
49
+ Also query JMnedict (proper names). Can be slow on very
50
+ broad wildcards.
51
+ sentence_limit : int, default 50
52
+ Maximum number of Tatoeba sentences to fetch.
53
+
54
+ Returns
55
+ -------
56
+ LookupResult
57
+ """
58
+ # 1. Find dictionary entries (JMdict & optionally JMnedict)
59
+ entries: List[JMDictEntryDTO | JMNeDictEntryDTO] = []
60
+ entries.extend(
61
+ JMDictRepo.search_form(word, limit=None if wildcard else 50))
62
+ if include_names:
63
+ entries.extend(JMNeDictRepo.search(word, limit=50))
64
+
65
+ # 2. Extract unique kanji found in the *query* itself
66
+ kanji_chars = [c for c in word if "\u4e00" <= c <= "\u9fff"]
67
+ kanji_info: List[KanjiDTO] = KanjiRepo.bulk_fetch(kanji_chars)
68
+
69
+ # 3. Parallel extra look-ups (JLPT + sentences) -----------------
70
+ with _cf.ThreadPoolExecutor(max_workers=3) as pool:
71
+ f_vocab = pool.submit(JLPTRepo.vocab_by_word, word)
72
+ f_levels = pool.submit(JLPTRepo.kanji_levels, kanji_chars)
73
+ f_grammar = pool.submit(JLPTRepo.grammar_entries_like, word)
74
+ f_sent = pool.submit(
75
+ SentenceRepo.search_containing,
76
+ word,
77
+ limit=sentence_limit,
78
+ wildcard=wildcard,
79
+ )
80
+
81
+ jlpt_vocab = f_vocab.result()
82
+ jlpt_kanji_levels: Dict[str, int] = f_levels.result()
83
+ jlpt_grammar = f_grammar.result()
84
+ sentences = f_sent.result()
85
+
86
+ # 4. Aggregate
87
+ return LookupResult(
88
+ word=word,
89
+ entries=entries,
90
+ kanji=kanji_info,
91
+ jlpt_vocab=jlpt_vocab,
92
+ jlpt_kanji_levels=jlpt_kanji_levels,
93
+ jlpt_grammar=jlpt_grammar,
94
+ examples=sentences,
95
+ )
96
+
97
+ # Convenience Wrappers
98
+
99
+ @staticmethod
100
+ @lru_cache(maxsize=10_000)
101
+ def kanji(literal: str):
102
+ """Return a single KanjiDTO (or None)."""
103
+ return KanjiRepo.by_literal(literal)
104
+
105
+ @staticmethod
106
+ @lru_cache(maxsize=20_000)
107
+ def jlpt_level(word: str) -> Optional[int]:
108
+ """Shortcut – just return JLPT vocab level for a word."""
109
+ dto = JLPTRepo.vocab_by_word(word)
110
+ return dto.level if dto else None
111
+
112
+ @staticmethod
113
+ def sentences(text: str, *, limit: int = 20):
114
+ """Fetch Japanese Tatoeba sentences containing *text*."""
115
+ return SentenceRepo.search_containing(text, limit=limit)
116
+
117
+ def __call__(self, word: str, **kwargs):
118
+ """Alias for `lookup` so you can `Kotobase()(word)`."""
119
+ return self.lookup(word, **kwargs)
120
+
121
+ # Context Manager
122
+ def __enter__(self):
123
+ return self
124
+
125
+ def __exit__(self, exc_type, exc, tb):
126
+ # Propagate Exceptions
127
+ return False
128
+
129
+
130
+ __all__ = ["Kotobase"]