Skip to content

Commit 4796b97

Browse files
authored
Merge pull request #32 from bretttolbert/typing-wip
Typing wip
2 parents 4592a4f + 7903962 commit 4796b97

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1142
-913
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
- Improved Italian conjugation (verbs conjugated with _essere_)
1616

1717
- 1.10.1 [28 September 2025]
18-
- Properly conjugate h non aspiré en français
18+
- Properly conjugate h non aspiré en FR
1919
- Reverted back to uncompressed XML files
2020

2121
- 1.10.0 [28 September 2025]
@@ -89,7 +89,7 @@
8989
<p><i>--guí</i></p>
9090
```
9191
- With the above template, `conèix` + `--guí` = `jo coneguí` and `reconèix` + `--guí` = `jo reconeguí`
92-
- Added `gender` flag to support feminine pronouns
92+
- Added `gender` flag to support F pronouns
9393
- Modified to put `-` placeholder in conjugation for tenses that aren't conjugated e.g.
9494
```python
9595
"caldre",

README.md

Lines changed: 91 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
[![GitHub Actions CI status](https://github.com/bretttolbert/verbecc/actions/workflows/python-package.yml/badge.svg)](https://github.com/bretttolbert/verbecc/actions/workflows/python-package.yml?query=branch%3Amain)
77

88
##### [EN] Verbs completely conjugated: verb conjugations for French, Spanish, Portuguese, Italian, Romanian and Catalan, enhanced by machine learning
9-
##### [CA] Verbs completament conjugats: conjugacions verbals per a francès, espanyol, portuguès, italià, romanès i català, millorades per l'aprenentatge automàtic
10-
##### [ES] Verbos completamente conjugados: conjugaciones de verbos en francés, español, portugués, italiano, rumano y catalán, mejoradas por aprendizaje automático
11-
##### [FR] Verbes complètement conjugués: conjugaisons des verbes français, espagnol, portugais, italien, roumain et catalan, à l'aide de l'apprentissage automatique
12-
##### [IT] Verbi completamente coniugati: coniugazioni di verbi per francese, spagnolo, portoghese, italiano, rumeno e catalano, migliorate dall'apprendimento automatico
13-
##### [PT] Verbos completamente conjugados: conjugações verbais para francês, espanhol, português, italiano, romeno e catalão, aprimoradas pelo aprendizado de máquina
14-
##### [RO] Verbe complet conjugate: conjugări de verbe pentru franceză, spaniolă, portugheză, italiană, română și catalană, îmbunătățite de învățarea automată
9+
##### [CA] Verbs completament conjugats: conjugacions verbals per a francès, espanyol, portuguès, italià, romanès i CA, millorades per l'aprenentatge automàtic
10+
##### [ES] Verbos completamente conjugados: conjugaciones de verbos en francés, ES, portugués, IT, rumano y catalán, mejoradas por aprendizaje automático
11+
##### [FR] Verbes complètement conjugués: conjugaisons des verbes FR, espagnol, portugais, italien, roumain et catalan, à l'aide de l'apprentissage automatique
12+
##### [IT] Verbi completamente coniugati: coniugazioni di verbi per francese, spagnolo, portoghese, IT, rumeno e catalano, migliorate dall'apprendimento automatico
13+
##### [PT] Verbos completamente conjugados: conjugações verbais para francês, espanhol, PT, IT, romeno e catalão, aprimoradas pelo aprendizado de máquina
14+
##### [RO] Verbe complet conjugate: conjugări de verbe pentru franceză, spaniolă, portugheză, italiană, RO și catalană, îmbunătățite de învățarea automată
1515

1616
### Live Demo
1717
- [Web GUI](http://verbe.cc)
@@ -34,18 +34,25 @@ pip install .
3434

3535
### Examples
3636

37+
In the following examples, this `import` statement will be required:
38+
39+
```python
40+
>>> from verbecc import Conjugator, LangCodeISO639_1 as Lang
41+
```
42+
3743
In the following examples, the following function will be used to make the output more readable:
3844

3945
```python
4046
import json
47+
4148
def printjson(c):
4249
print(json.dumps(c, indent=4, ensure_ascii=False))
4350
```
4451

4552
- [Conjugation Example: French manger (to eat)](#conjugation-example-french-manger-to-eat)
4653
- [ML Prediction Conjugation Example: French uberiser (to Uberize)](#ml-prediction-conjugation-example-french-uberiser-to-uberize)
4754
- [Multi-Language Conjugation](#example-multi-language-conjugation)
48-
- [Multi-Language Conjugation using English mood and tense names via localization module](#example-multi-language-conjugation-using-english-mood-and-tense-names-via-localization-module)
55+
- [Multi-Language Conjugation using EN mood and tense names via localization module](#example-multi-language-conjugation-using-EN-mood-and-tense-names-via-localization-module)
4956
- [Catalan `ser` (to be) - with pronouns, without alternate conjugations (original behavior)](#example-catalan-ser-to-be)
5057
- [Catalan `ser` (to be) - without pronouns, including alternate conjugations (new features in 1.9.7)](#example-catalan-ser-to-be-with-alternate-conjugations-without-pronouns)
5158
- [Spanish ser (to be) - with pronouns, without alternate conjugations (original behavior)](#example-spanish-ser-to-be)
@@ -54,10 +61,39 @@ def printjson(c):
5461
- [Portuguese ser (to be) - with pronouns, without alternate conjugations (original behavior)](#example-portuguese--ser-to-be)
5562
- [Romanian fi (to be) - with pronouns, without alternate conjugations (original behavior)](#conjugation-example-romanian-fi-to-be)
5663

64+
### Typing - Parameter and Data Type Annotations
65+
66+
Originally `verbecc` used strings for most parameters. `verbecc` is now fully type-annotated but strings are still supported for backwards-compatibility and ease of use. This is accomplished using `StrEnum` for parameters and by defining a hierarchy of `typing` type definitions for the returned data objects (See [src/defs/types/conjugation.py](./verbecc/src/defs/types/conjugation.py)).
67+
68+
Typing transition guide:
69+
70+
- Instead of `lang='fr'` use `lang=Lang.fr` after the import `from verbecc import LangCodeISO639_1 as Lang`
71+
- Instead of `mood="indicatif"`
72+
- use `mood=Mood.fr.Indicatif` after the import `from verbecc import Mood`
73+
- or use `mood=Mood.Indicatif` after the import `from verbecc import MoodFr as Mood`
74+
- Instead of `tense="présent"`
75+
- use `tense=Tense.fr.Présent` after the import `from verbecc import Tense`
76+
- or use `tense=Tense.Présent` after the import `from verbecc import TenseFr as Tense`
77+
- Instead of `gender='f'` use `gender=Gender.f` after the import `from verbecc import Gender`
78+
79+
Examples:
80+
81+
```python
82+
>>> from verbecc import grammar_defines, localization, LangCodeISO639_1, Mood, Tense, Gender
83+
>>> xmood = localization.xmood
84+
>>> xtense = localization.xtense
85+
>>> grammar_defines.SUPPORTED_LANGUAGES[LangCodeISO639_1.fr]
86+
'français'
87+
>>> xtense(LangCodeISO639_1.fr, Tense.en.Present)
88+
<TenseFr.Présent: 'présent'>
89+
>>> xmood(LangCodeISO639_1.fr, Mood.en.Subjunctive)
90+
<MoodFr.Subjonctif: 'subjonctif'>
91+
>>> Gender.f
92+
<Gender.f: 'f'>
93+
```
5794

5895
### Conjugation Example: French `manger` (to eat)
5996
```python
60-
>>> from verbecc import Conjugator
6197
>>> cg = Conjugator(lang='fr') # If this is the first run, it will take a minute for the model to train,
6298
# but it should save the model .zip file and run fast subsequently
6399
>>> cg.conjugate('manger')
@@ -416,7 +452,7 @@ In this example, we will conjugate a verb that `verbecc` doesn't explicitly know
416452
['eu sunt', 'tu ești', 'el e', 'noi suntem', 'voi sunteţi', 'ei sunt']
417453
```
418454

419-
### Example: Multi-Language Conjugation using English mood and tense names via `localization` module
455+
### Example: Multi-Language Conjugation using EN mood and tense names via `localization` module
420456

421457
```python
422458
>>> from verbecc import Conjugator
@@ -1149,7 +1185,6 @@ In this example, we will conjugate a verb that `verbecc` doesn't explicitly know
11491185
```python
11501186
>>> cg = Conjugator(lang='it')
11511187
>>> printjson(cg.conjugate('essere'))
1152-
>>> printjson(cg.conjugate('essere'))
11531188
{
11541189
"verb": {
11551190
"infinitive": "essere",
@@ -1194,36 +1229,36 @@ In this example, we will conjugate a verb that `verbecc` doesn't explicitly know
11941229
"loro saranno"
11951230
],
11961231
"passato-prossimo": [
1197-
"io ho ente/essente",
1198-
"tu hai ente/essente",
1199-
"lui ha ente/essente",
1200-
"noi abbiamo ente/essente",
1201-
"voi avete ente/essente",
1202-
"loro hanno ente/essente"
1232+
"io sono stato",
1233+
"tu sei stato",
1234+
"lui è stato",
1235+
"noi siamo stati",
1236+
"voi siete stati",
1237+
"loro sono stati"
12031238
],
12041239
"trapassato-prossimo": [
1205-
"io avevo ente/essente",
1206-
"tu avevi ente/essente",
1207-
"lui aveva ente/essente",
1208-
"noi avevamo ente/essente",
1209-
"voi avevate ente/essente",
1210-
"loro avevano ente/essente"
1240+
"io ero stato",
1241+
"tu eri stato",
1242+
"lui era stato",
1243+
"noi eravamo stati",
1244+
"voi eravate stati",
1245+
"loro erano stati"
12111246
],
12121247
"trapassato-remoto": [
1213-
"io ebbi ente/essente",
1214-
"tu avesti ente/essente",
1215-
"lui ebbe ente/essente",
1216-
"noi avemmo ente/essente",
1217-
"voi aveste ente/essente",
1218-
"loro ebbero ente/essente"
1248+
"io fui stato",
1249+
"tu fosti stato",
1250+
"lui fu stato",
1251+
"noi fummo stati",
1252+
"voi foste stati",
1253+
"loro furono stati"
12191254
],
12201255
"futuro-anteriore": [
1221-
"io avrò ente/essente",
1222-
"tu avrai ente/essente",
1223-
"lui avrà ente/essente",
1224-
"noi avremo ente/essente",
1225-
"voi avrete ente/essente",
1226-
"loro avranno ente/essente"
1256+
"io sarò stato",
1257+
"tu sarai stato",
1258+
"lui sarà stato",
1259+
"noi saremo stati",
1260+
"voi sarete stati",
1261+
"loro saranno stati"
12271262
]
12281263
},
12291264
"congiuntivo": {
@@ -1244,20 +1279,20 @@ In this example, we will conjugate a verb that `verbecc` doesn't explicitly know
12441279
"che loro fossero"
12451280
],
12461281
"passato": [
1247-
"che io abbia ente/essente",
1248-
"che tu abbia ente/essente",
1249-
"che lui abbia ente/essente",
1250-
"che noi abbiamo ente/essente",
1251-
"che voi abbiate ente/essente",
1252-
"che loro abbiano ente/essente"
1282+
"che io sia stato",
1283+
"che tu sia stato",
1284+
"che lui sia stato",
1285+
"che noi siamo stati",
1286+
"che voi siate stati",
1287+
"che loro siano stati"
12531288
],
12541289
"trapassato": [
1255-
"che io avessi ente/essente",
1256-
"che tu avessi ente/essente",
1257-
"che lui avesse ente/essente",
1258-
"che noi avessimo ente/essente",
1259-
"che voi aveste ente/essente",
1260-
"che loro avessero ente/essente"
1290+
"che io fossi stato",
1291+
"che tu fossi stato",
1292+
"che lui fosse stato",
1293+
"che noi fossimo stati",
1294+
"che voi foste stati",
1295+
"che loro fossero stati"
12611296
]
12621297
},
12631298
"condizionale": {
@@ -1270,12 +1305,12 @@ In this example, we will conjugate a verb that `verbecc` doesn't explicitly know
12701305
"loro sarebbero"
12711306
],
12721307
"passato": [
1273-
"io avrei ente/essente",
1274-
"tu avresti ente/essente",
1275-
"lui avrebbe ente/essente",
1276-
"noi avremmo ente/essente",
1277-
"voi avreste ente/essente",
1278-
"loro avrebbero ente/essente"
1308+
"io sarei stato",
1309+
"tu saresti stato",
1310+
"lui sarebbe stato",
1311+
"noi saremmo stati",
1312+
"voi sareste stati",
1313+
"loro sarebbero stati"
12791314
]
12801315
},
12811316
"imperativo": {
@@ -1313,8 +1348,10 @@ In this example, we will conjugate a verb that `verbecc` doesn't explicitly know
13131348
]
13141349
},
13151350
"participio": {
1316-
"participio": [
1317-
"ente/essente",
1351+
"participio-presente": [
1352+
"ente"
1353+
],
1354+
"participio-passato": [
13181355
"stato",
13191356
"stata",
13201357
"stati",

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "verbecc"
7-
version = "1.11.2"
7+
version = "1.11.3"
88
dependencies = [
99
"cython>=3.1.4",
1010
"importlib_resources==6.4.5 ; python_version < '3.13'",

scripts/conjugation_xml_filter.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1-
from lxml import etree, objectify
2-
import os
3-
41
"""
52
This script was used to remove unwanted tense elements
63
(e.g. compound tenses) from the mlconjug conjugation XML files
74
"""
85

6+
from lxml import etree, objectify
7+
import os
8+
from typing import List
9+
from verbecc.src.defs.types.tense import Tense
10+
from verbecc.src.defs.types.mood import Mood
11+
912
working_dir = "../verbecc/data"
1013
in_file = "conjugations-ro.xml"
1114
out_file = "conjugations-ro.mod.xml"
1215

1316

14-
def remove_mood_tense(root, tenses_to_remove):
17+
def remove_mood_tense(root: etree._Element, tenses_to_remove: List[Tense]) -> None:
1518
removed_elem_cnt = 0
1619
for template_elem in root:
1720
if template_elem.tag == "template":
@@ -23,7 +26,7 @@ def remove_mood_tense(root, tenses_to_remove):
2326
print("removed {} elements".format(removed_elem_cnt))
2427

2528

26-
def remove_mood(root, moods_to_remove):
29+
def remove_mood(root: etree._Element, moods_to_remove: List[Mood]) -> None:
2730
removed_elem_cnt = 0
2831
for template_elem in root:
2932
if template_elem.tag == "template":
@@ -34,7 +37,13 @@ def remove_mood(root, moods_to_remove):
3437
print("removed {} elements".format(removed_elem_cnt))
3538

3639

37-
def move_tense(root, tense_name, old_mood, new_mood, remove_old_mood):
40+
def move_tense(
41+
root: etree._Element,
42+
tense: Tense,
43+
old_mood: Mood,
44+
new_mood: Mood,
45+
remove_old_mood: bool,
46+
) -> None:
3847
moved_elem_cnt = 0
3948
for template_elem in root:
4049
if template_elem.tag == "template":
@@ -43,7 +52,7 @@ def move_tense(root, tense_name, old_mood, new_mood, remove_old_mood):
4352
for mood_elem in template_elem:
4453
if mood_elem.tag == old_mood:
4554
for tense_elem in mood_elem:
46-
if tense_elem.tag == tense_name:
55+
if tense_elem.tag == tense:
4756
tense_elem_to_move = tense_elem
4857
mood_elem.remove(tense_elem)
4958
if remove_old_mood:
@@ -58,7 +67,7 @@ def move_tense(root, tense_name, old_mood, new_mood, remove_old_mood):
5867
print("moved {} elements".format(moved_elem_cnt))
5968

6069

61-
def main():
70+
def main() -> None:
6271
parser = etree.XMLParser(dtd_validation=False, encoding="utf-8")
6372
tree = etree.parse(os.path.join(working_dir, in_file), parser)
6473
root = tree.getroot()

0 commit comments

Comments
 (0)