reglem 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.
@@ -0,0 +1,29 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Install uv
18
+ uses: astral-sh/setup-uv@v5
19
+ with:
20
+ python-version: ${{ matrix.python-version }}
21
+
22
+ - name: Install dependencies
23
+ run: uv sync --all-extras --dev
24
+
25
+ - name: Run pre-commit
26
+ run: uv run pre-commit run --all-files
27
+
28
+ - name: Run tests
29
+ run: uv run pytest
@@ -0,0 +1,43 @@
1
+ name: Publish
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Install uv
15
+ uses: astral-sh/setup-uv@v5
16
+
17
+ - name: Build
18
+ run: uv build
19
+
20
+ - name: Check package
21
+ run: uvx twine check dist/*
22
+
23
+ - name: Upload build artifacts
24
+ uses: actions/upload-artifact@v4
25
+ with:
26
+ name: dist
27
+ path: dist/
28
+
29
+ publish:
30
+ needs: build
31
+ runs-on: ubuntu-latest
32
+ environment: pypi
33
+ permissions:
34
+ id-token: write # PyPI Trusted Publishing (OIDC) -- no stored token needed
35
+ steps:
36
+ - name: Download build artifacts
37
+ uses: actions/download-artifact@v4
38
+ with:
39
+ name: dist
40
+ path: dist/
41
+
42
+ - name: Publish to PyPI
43
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,14 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .venv/
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ .mypy_cache/
7
+ .hypothesis/
8
+ htmlcov/
9
+ .coverage
10
+ .coverage.*
11
+ dist/
12
+ build/
13
+ *.egg-info/
14
+ .DS_Store
@@ -0,0 +1,25 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v5.0.0
4
+ hooks:
5
+ - id: check-yaml
6
+ - id: check-toml
7
+ - id: check-added-large-files
8
+ - id: end-of-file-fixer
9
+ - id: trailing-whitespace
10
+
11
+ - repo: https://github.com/astral-sh/ruff-pre-commit
12
+ rev: v0.15.0
13
+ hooks:
14
+ - id: ruff-check
15
+ args: [--fix]
16
+ - id: ruff-format
17
+
18
+ - repo: local
19
+ hooks:
20
+ - id: basedpyright
21
+ name: basedpyright
22
+ entry: uv run basedpyright
23
+ language: system
24
+ types: [python]
25
+ pass_filenames: false
@@ -0,0 +1,38 @@
1
+ # Changelog
2
+
3
+ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
4
+ Versioning: [Semantic Versioning](https://semver.org/).
5
+
6
+ ## [Unreleased]
7
+
8
+ ## [0.1.0] - 2026-08-31
9
+
10
+ ### Added
11
+
12
+ - Core:
13
+ `build_pattern` / `build_anki_search`,
14
+ lemma normalization,
15
+ per-language spelling-variant expansion,
16
+ Greek macron table.
17
+ - Core:
18
+ per-lemma terminator exceptions (`Language.excluded_terminators`),
19
+ and a Greek exception denying space/NBSP right after any of the 19
20
+ definite-article forms, so `ὁ` no longer false-matches entries like
21
+ `ὁ σοφός, -ή, -όν` or `ἡ ἀρίστη`.
22
+ - `/` (slash) added to `DEFAULT_TERMINATORS`,
23
+ so slash-separated citations (`ὁ/ἡ/τό`, `ἀγαθός/ή/όν`) still match.
24
+ - CLI:
25
+ `reglem` console script
26
+ (file / stdin / `-w` input, `--macrons`, `--raw`, `--list-languages`).
27
+ - Packaging:
28
+ strict ruff + basedpyright,
29
+ pytest with coverage gate,
30
+ pre-commit,
31
+ CI,
32
+ PyPI Trusted Publishing workflow.
33
+
34
+ ### Changed
35
+
36
+ - A Greek definite-article lemma (`ὁ`, `ἡ`, `τό`, and the rest of the
37
+ paradigm) followed by a non-breaking space no longer matches —
38
+ NBSP is now excluded the same as a plain space for these lemmas.
reglem-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 jaycrick
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
7
+ deal in the Software without restriction, including without limitation the
8
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9
+ sell 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
13
+ all 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
20
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
+ IN THE SOFTWARE.
reglem-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,154 @@
1
+ Metadata-Version: 2.5
2
+ Name: reglem
3
+ Version: 0.1.0
4
+ Summary: Build anchored regex alternations over word lemmas, with optional per-language spelling variants.
5
+ Project-URL: Homepage, https://github.com/jaycrick/reglem
6
+ Project-URL: Issues, https://github.com/jaycrick/reglem/issues
7
+ Project-URL: Changelog, https://github.com/jaycrick/reglem/blob/main/CHANGELOG.md
8
+ Author-email: jaycrick <114450568+jaycrick@users.noreply.github.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: anki,greek,lemma,linguistics,regex
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Text Processing :: Linguistic
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: pydantic>=2.7
25
+ Description-Content-Type: text/markdown
26
+
27
+ # reglem
28
+
29
+ Turn list of word lemmas into one anchored regex alternation.
30
+ Optional per-language spelling variants (Greek macrons, for now).
31
+ Optional Anki `field:re:...` search-string wrapper.
32
+
33
+ Greek only today.
34
+ Language layer built so more languages drop in later without touching core.
35
+
36
+ ## Why
37
+
38
+ Building `re:` search for Anki (or any regex-search tool) by hand from a word list is fiddly:
39
+ prefix leaks (`ox` matching `oxen`),
40
+ Rust `regex` crate has no lookahead so `(?=...)` breaks in Anki,
41
+ spelling variants (accents, long-vowel marks) multiply the work.
42
+ This package does that once, correctly, tested.
43
+
44
+ ## Install
45
+
46
+ ```bash
47
+ uv add reglem
48
+ # or
49
+ pip install reglem
50
+ ```
51
+
52
+ ## Quickstart — library
53
+
54
+ ```python
55
+ from reglem import build_anki_search, build_pattern, SearchOptions
56
+
57
+ # bare regex
58
+ build_pattern(["cat", "dog"])
59
+ # '^(dog|cat)([ ,. ]|$)'
60
+
61
+ # Anki search string
62
+ build_anki_search(["ὁ", "καί", "ἀγαθός"], SearchOptions(field="Greek", with_macrons=True))
63
+ # '"Greek:re:^(...)([ ,. ]|$)"'
64
+ ```
65
+
66
+ Paste that string into Anki's Browse search bar.
67
+ It matches notes whose field *starts* with one of the given lemmas,
68
+ followed by space, comma, period, or end of field.
69
+
70
+ ## Quickstart — CLI
71
+
72
+ ```bash
73
+ reglem lemmas.txt # Anki search string, one lemma per line in file
74
+ cat lemmas.txt | reglem - # same, from stdin
75
+ reglem -w ὁ -w καί -w ἀγαθός --macrons
76
+ reglem lemmas.txt --raw # bare regex, no Anki wrapper
77
+ reglem --list-languages
78
+ ```
79
+
80
+ `lemmas.txt`: one lemma per line, blank lines and `#` comments skipped.
81
+
82
+ ## Flags
83
+
84
+ | flag | default | does |
85
+ |---|---|---|
86
+ | `-w/--word LEMMA` | — | add one lemma; repeatable; overrides file/stdin |
87
+ | `-f/--field NAME` | `Greek` | Anki field name in output search string |
88
+ | `--macrons` | off | expand ambiguous-length vowels into macron alternatives |
89
+ | `--strip-trailing-digits` | off | strip trailing homograph digit (`lead2` → `lead`) before matching |
90
+ | `--terminators CHARS` | `" ,. /"` (space, comma, period, NBSP, slash) | chars allowed right after a matched lemma |
91
+ | `--raw` | off | print bare regex, skip the `"field:re:..."` wrapper |
92
+ | `--language NAME` | `greek` | which variant tables to use for `--macrons` |
93
+ | `--list-languages` | — | print known language names, exit |
94
+
95
+ ## Why prefix-anchored, no lookahead
96
+
97
+ Anki's `re:` search uses the Rust `regex` crate (no lookaround support),
98
+ and field regexes are unanchored by default.
99
+ So a naive `word(?=[ ,])` breaks two ways:
100
+ it's invalid syntax in Anki,
101
+ and without `^` it'd match `word` inside `password` too.
102
+ reglem builds `^(alt1|alt2|...)([terminators]|$)` instead —
103
+ one alternation, explicit anchor, ordinary terminator class.
104
+ When a language excludes a terminator for a specific lemma (see Greek article,
105
+ below), that lemma gets its own terminator group in a separate branch instead —
106
+ still no lookahead.
107
+
108
+ ## Greek macrons
109
+
110
+ See `docs/greek.md` for the full story —
111
+ why unmarked Greek text is vowel-length-ambiguous,
112
+ and how the macron expansion table is built.
113
+
114
+ ## Greek article
115
+
116
+ A plain space isn't allowed right after any of the 19 forms of the Greek
117
+ definite article (`ὁ`, `ἡ`, `τό`, `τῶν`, `τούς`, ...): unlike an ordinary
118
+ headword, the article is never immediately followed by running Greek text in
119
+ its own dictionary entry — it's cited with punctuation instead, `ὁ, ἡ, τό` or
120
+ `ὁ/ἡ/τό`. Without the exception, `ὁ` as a lemma would match the start of
121
+ every entry that *begins* with the article, like `ὁ σοφός, -ή, -όν wise` or
122
+ `ἡ ἀρίστη`, which are entries for other words entirely.
123
+
124
+ ```python
125
+ build_pattern(["ὁ"])
126
+ # matches: "ὁ, ἡ, τό the" "ὁ/ἡ/τό" "ὁ" (end of field)
127
+ # doesn't match: "ὁ σοφός, -ή, -όν wise" "ἡ ἀρίστη"
128
+ ```
129
+
130
+ This is why `/` is in `DEFAULT_TERMINATORS`: it's how a slash-separated
131
+ article citation (`ὁ/ἡ/τό`) still matches. See `docs/greek.md` for the full
132
+ list of forms and why grave-accented running-text forms (`τὸν`, `τὰς`, ...)
133
+ are intentionally excluded.
134
+
135
+ ## Development
136
+
137
+ ```bash
138
+ uv sync
139
+ uv run pytest # coverage gate: 95%
140
+ uv run ruff check .
141
+ uv run ruff format --check .
142
+ uv run basedpyright
143
+ uv run pre-commit run --all-files
144
+ ```
145
+
146
+ ## Publish
147
+
148
+ Tag `vX.Y.Z`, push tag.
149
+ CI builds, checks with `twine`, publishes via PyPI Trusted Publishing (OIDC) —
150
+ no stored token.
151
+
152
+ ## License
153
+
154
+ MIT.
reglem-0.1.0/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # reglem
2
+
3
+ Turn list of word lemmas into one anchored regex alternation.
4
+ Optional per-language spelling variants (Greek macrons, for now).
5
+ Optional Anki `field:re:...` search-string wrapper.
6
+
7
+ Greek only today.
8
+ Language layer built so more languages drop in later without touching core.
9
+
10
+ ## Why
11
+
12
+ Building `re:` search for Anki (or any regex-search tool) by hand from a word list is fiddly:
13
+ prefix leaks (`ox` matching `oxen`),
14
+ Rust `regex` crate has no lookahead so `(?=...)` breaks in Anki,
15
+ spelling variants (accents, long-vowel marks) multiply the work.
16
+ This package does that once, correctly, tested.
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ uv add reglem
22
+ # or
23
+ pip install reglem
24
+ ```
25
+
26
+ ## Quickstart — library
27
+
28
+ ```python
29
+ from reglem import build_anki_search, build_pattern, SearchOptions
30
+
31
+ # bare regex
32
+ build_pattern(["cat", "dog"])
33
+ # '^(dog|cat)([ ,. ]|$)'
34
+
35
+ # Anki search string
36
+ build_anki_search(["ὁ", "καί", "ἀγαθός"], SearchOptions(field="Greek", with_macrons=True))
37
+ # '"Greek:re:^(...)([ ,. ]|$)"'
38
+ ```
39
+
40
+ Paste that string into Anki's Browse search bar.
41
+ It matches notes whose field *starts* with one of the given lemmas,
42
+ followed by space, comma, period, or end of field.
43
+
44
+ ## Quickstart — CLI
45
+
46
+ ```bash
47
+ reglem lemmas.txt # Anki search string, one lemma per line in file
48
+ cat lemmas.txt | reglem - # same, from stdin
49
+ reglem -w ὁ -w καί -w ἀγαθός --macrons
50
+ reglem lemmas.txt --raw # bare regex, no Anki wrapper
51
+ reglem --list-languages
52
+ ```
53
+
54
+ `lemmas.txt`: one lemma per line, blank lines and `#` comments skipped.
55
+
56
+ ## Flags
57
+
58
+ | flag | default | does |
59
+ |---|---|---|
60
+ | `-w/--word LEMMA` | — | add one lemma; repeatable; overrides file/stdin |
61
+ | `-f/--field NAME` | `Greek` | Anki field name in output search string |
62
+ | `--macrons` | off | expand ambiguous-length vowels into macron alternatives |
63
+ | `--strip-trailing-digits` | off | strip trailing homograph digit (`lead2` → `lead`) before matching |
64
+ | `--terminators CHARS` | `" ,. /"` (space, comma, period, NBSP, slash) | chars allowed right after a matched lemma |
65
+ | `--raw` | off | print bare regex, skip the `"field:re:..."` wrapper |
66
+ | `--language NAME` | `greek` | which variant tables to use for `--macrons` |
67
+ | `--list-languages` | — | print known language names, exit |
68
+
69
+ ## Why prefix-anchored, no lookahead
70
+
71
+ Anki's `re:` search uses the Rust `regex` crate (no lookaround support),
72
+ and field regexes are unanchored by default.
73
+ So a naive `word(?=[ ,])` breaks two ways:
74
+ it's invalid syntax in Anki,
75
+ and without `^` it'd match `word` inside `password` too.
76
+ reglem builds `^(alt1|alt2|...)([terminators]|$)` instead —
77
+ one alternation, explicit anchor, ordinary terminator class.
78
+ When a language excludes a terminator for a specific lemma (see Greek article,
79
+ below), that lemma gets its own terminator group in a separate branch instead —
80
+ still no lookahead.
81
+
82
+ ## Greek macrons
83
+
84
+ See `docs/greek.md` for the full story —
85
+ why unmarked Greek text is vowel-length-ambiguous,
86
+ and how the macron expansion table is built.
87
+
88
+ ## Greek article
89
+
90
+ A plain space isn't allowed right after any of the 19 forms of the Greek
91
+ definite article (`ὁ`, `ἡ`, `τό`, `τῶν`, `τούς`, ...): unlike an ordinary
92
+ headword, the article is never immediately followed by running Greek text in
93
+ its own dictionary entry — it's cited with punctuation instead, `ὁ, ἡ, τό` or
94
+ `ὁ/ἡ/τό`. Without the exception, `ὁ` as a lemma would match the start of
95
+ every entry that *begins* with the article, like `ὁ σοφός, -ή, -όν wise` or
96
+ `ἡ ἀρίστη`, which are entries for other words entirely.
97
+
98
+ ```python
99
+ build_pattern(["ὁ"])
100
+ # matches: "ὁ, ἡ, τό the" "ὁ/ἡ/τό" "ὁ" (end of field)
101
+ # doesn't match: "ὁ σοφός, -ή, -όν wise" "ἡ ἀρίστη"
102
+ ```
103
+
104
+ This is why `/` is in `DEFAULT_TERMINATORS`: it's how a slash-separated
105
+ article citation (`ὁ/ἡ/τό`) still matches. See `docs/greek.md` for the full
106
+ list of forms and why grave-accented running-text forms (`τὸν`, `τὰς`, ...)
107
+ are intentionally excluded.
108
+
109
+ ## Development
110
+
111
+ ```bash
112
+ uv sync
113
+ uv run pytest # coverage gate: 95%
114
+ uv run ruff check .
115
+ uv run ruff format --check .
116
+ uv run basedpyright
117
+ uv run pre-commit run --all-files
118
+ ```
119
+
120
+ ## Publish
121
+
122
+ Tag `vX.Y.Z`, push tag.
123
+ CI builds, checks with `twine`, publishes via PyPI Trusted Publishing (OIDC) —
124
+ no stored token.
125
+
126
+ ## License
127
+
128
+ MIT.
@@ -0,0 +1,119 @@
1
+ # Greek macron expansion
2
+
3
+ ## Problem
4
+
5
+ Word lists that mark accent/breathing but not vowel length leave α, ι, υ ambiguous:
6
+ short or long, no way to tell from the text alone.
7
+ Pedagogical texts, by contrast,
8
+ often mark long instances of these three vowels with a macron
9
+ layered on top of whatever accent/breathing the vowel already carries.
10
+ Example:
11
+ a long alpha with smooth breathing appears as ᾱ̓ in a macron-marked text,
12
+ but as plain ἀ in a macron-less source.
13
+
14
+ `reglem`'s `--macrons` flag (`SearchOptions(with_macrons=True)` in the library)
15
+ expands each ambiguous vowel in a lemma into `(?:plain|macron)`,
16
+ so one search matches both spellings.
17
+
18
+ ## Unicode detail
19
+
20
+ Precomposed macron-vowel characters exist: ᾱ ῑ ῡ.
21
+ Precomposed macron+breathing or macron+accent characters do NOT exist —
22
+ those are the macron-vowel codepoint followed by ordinary *combining* marks:
23
+
24
+ - U+0313 combining comma above (smooth breathing, psili)
25
+ - U+0314 combining reversed comma above (rough breathing, dasia)
26
+ - U+0301 combining acute accent (oxia)
27
+ - U+0300 combining grave accent (varia)
28
+
29
+ Order: breathing before accent.
30
+ Verified against Python `unicodedata`, both directions:
31
+
32
+ ```python
33
+ >>> import unicodedata
34
+ >>> unicodedata.normalize("NFC", "ᾱ" + "̓" + "́") == "ᾱ" + "̓" + "́"
35
+ True # already canonical, NFC doesn't reorder/recompose further
36
+ ```
37
+
38
+ Also verified:
39
+ NFC always resolves the alpha/iota/upsilon + acute double-encoding
40
+ (polytonic U+1F71 vs. monotonic U+03AC "tonos") down to one codepoint.
41
+ Most Greek lemma sources give NFC text already,
42
+ so no dual-encoding to handle on the plain side.
43
+
44
+ ## Circumflex excluded on purpose
45
+
46
+ Circumflex forms (ᾶ, ἆ, ἇ, ι/υ equivalents) are NOT in the macron table.
47
+ A circumflex accent can only sit on a long vowel —
48
+ already unambiguous, no separate macron form needed.
49
+
50
+ ## Known simplification
51
+
52
+ The table maps every bare/accented/breathed α, ι, υ,
53
+ including ones that are actually the first or second vowel of a diphthong
54
+ (αι, αυ, ει, ευ, οι, ου, υι) —
55
+ positions where a macron would never really be written.
56
+ Effect:
57
+ a generated pattern gets a few extra alternation branches that can never match anything real.
58
+ Not incorrect, just slightly bigger than the minimum.
59
+ Reliable diphthong detection would be much more machinery
60
+ than the false-positive cost justifies.
61
+
62
+ ## Table size
63
+
64
+ 27 entries:
65
+ 9 each for α, ι, υ
66
+ (bare, acute, grave, smooth, rough, smooth+acute, rough+acute, smooth+grave, rough+grave).
67
+
68
+ ## Greek article: no space allowed
69
+
70
+ ### Problem
71
+
72
+ A lemma pattern normally allows a plain space right after a matched lemma —
73
+ that's how `καί and, also` matches the lemma `καί`.
74
+ The Greek definite article breaks that assumption.
75
+ It's never immediately followed by running Greek text in its own dictionary entry;
76
+ it's cited on its own, joined to its other forms by punctuation:
77
+ `ὁ, ἡ, τό the` or `ὁ/ἡ/τό`.
78
+ In running text, though, it's immediately followed by the word it modifies:
79
+ `ὁ σοφός, -ή, -όν` (the wise man), `ἡ ἀρίστη` (the best woman).
80
+
81
+ Without an exception,
82
+ the lemma `ὁ` matches the start of every one of those unrelated entries too —
83
+ a large, silent source of false positives for a single-letter lemma.
84
+
85
+ ### Fix
86
+
87
+ `reglem` denies a plain space, and a non-breaking space (U+00A0),
88
+ right after any of the 19 forms of the Greek definite article.
89
+ Comma, period, slash, and end-of-field are still allowed.
90
+ That's implemented as `Language.excluded_terminators`,
91
+ a per-lemma map of terminator characters to exclude —
92
+ see `build.py`'s module docstring for how the pattern splits into per-terminator
93
+ branches when this map applies.
94
+
95
+ NBSP is excluded for the same reason it's a default terminator at all:
96
+ it renders as an invisible space in the Anki editor
97
+ while still separating words in field HTML.
98
+
99
+ ### The 19 forms
100
+
101
+ ```
102
+ ὁ ἡ τό
103
+ τοῦ τῆς τῷ τῇ τόν τήν
104
+ τώ τοῖν
105
+ οἱ αἱ τά τῶν τοῖς ταῖς τούς τάς
106
+ ```
107
+
108
+ Masculine, feminine, neuter; nominative, genitive, dative, accusative;
109
+ singular, dual, plural.
110
+
111
+ ### Grave-accented forms excluded on purpose
112
+
113
+ Running text writes the article with a grave accent before another word —
114
+ `τὸν`, `τὴν`, `τοὺς`, `τὰς` —
115
+ where the citation form carries an acute (`τόν`, `τήν`, `τούς`, `τάς`).
116
+ A lemma list cites the acute form,
117
+ so there's nothing to exclude a terminator from for the grave spellings —
118
+ they're not in `ARTICLE_FORMS`.
119
+ Adding them would be a one-line extension if a source ever needs it.
@@ -0,0 +1,85 @@
1
+ [project]
2
+ name = "reglem"
3
+ version = "0.1.0"
4
+ description = "Build anchored regex alternations over word lemmas, with optional per-language spelling variants."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ authors = [{ name = "jaycrick", email = "114450568+jaycrick@users.noreply.github.com" }]
9
+ requires-python = ">=3.10"
10
+ keywords = ["regex", "lemma", "anki", "greek", "linguistics"]
11
+ classifiers = [
12
+ "Development Status :: 3 - Alpha",
13
+ "Intended Audience :: Developers",
14
+ "License :: OSI Approved :: MIT License",
15
+ "Operating System :: OS Independent",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.10",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
+ "Topic :: Text Processing :: Linguistic",
22
+ "Typing :: Typed",
23
+ ]
24
+ dependencies = ["pydantic>=2.7"]
25
+
26
+ [project.urls]
27
+ Homepage = "https://github.com/jaycrick/reglem"
28
+ Issues = "https://github.com/jaycrick/reglem/issues"
29
+ Changelog = "https://github.com/jaycrick/reglem/blob/main/CHANGELOG.md"
30
+
31
+ [project.scripts]
32
+ reglem = "reglem.cli:main"
33
+
34
+ [dependency-groups]
35
+ dev = [
36
+ "pytest>=8.0",
37
+ "pytest-cov>=5.0",
38
+ "hypothesis>=6.100",
39
+ "ruff>=0.15",
40
+ "basedpyright>=1.18",
41
+ "pre-commit>=3.7",
42
+ ]
43
+
44
+ [build-system]
45
+ requires = ["hatchling"]
46
+ build-backend = "hatchling.build"
47
+
48
+ [tool.hatch.build.targets.wheel]
49
+ packages = ["src/reglem"]
50
+
51
+ [tool.ruff]
52
+ line-length = 96
53
+ target-version = "py310"
54
+
55
+ [tool.ruff.lint]
56
+ select = ["ALL"]
57
+ ignore = [
58
+ "D203", # one-blank-line-before-class -- conflicts with D211
59
+ "D213", # multi-line-summary-second-line -- conflicts with D212
60
+ "COM812", # trailing comma -- formatter handles this
61
+ "CPY001", # copyright header -- not used in this project
62
+ "RUF001", # ambiguous-unicode-character-string -- constant false positive on Greek text
63
+ "RUF002", # same, in docstrings
64
+ "RUF003", # same, in comments
65
+ ]
66
+
67
+ [tool.ruff.lint.per-file-ignores]
68
+ "tests/**" = ["S101", "PLR2004", "D", "INP001", "FBT001"]
69
+ "src/reglem/cli.py" = ["T201"] # CLI output is meant to print to stdout
70
+
71
+ [tool.ruff.lint.pydocstyle]
72
+ convention = "google"
73
+
74
+ [tool.basedpyright]
75
+ include = ["src", "tests"]
76
+ typeCheckingMode = "strict"
77
+ pythonVersion = "3.10"
78
+ reportMissingTypeStubs = true
79
+
80
+ [tool.pytest.ini_options]
81
+ addopts = "--strict-markers --strict-config --cov=reglem --cov-report=term-missing --cov-fail-under=95"
82
+ testpaths = ["tests"]
83
+
84
+ [tool.coverage.run]
85
+ source = ["src/reglem"]