"""
Grammalecte - Conjugueur
"""
# License: GPL 3
import re
import traceback
from .conj_data import lVtyp as _lVtyp
from .conj_data import lTags as _lTags
from .conj_data import dPatternConj as _dPatternConj
from .conj_data import dVerb as _dVerb
_zStartVoy = re.compile("^[aeéiouœê]")
_zNeedTeuph = re.compile("[tdc]$")
#_zNEEDACCENTWITHJE = re.compile("[^i]e$")
_dProSuj = { ":1s": "je", ":1ś": "je", ":2s": "tu", ":3s": "il", ":1p": "nous", ":2p": "vous", ":3p": "ils" }
_dProObj = { ":1s": "me ", ":1ś": "me ", ":2s": "te ", ":3s": "se ", ":1p": "nous ", ":2p": "vous ", ":3p": "se " }
_dProObjEl = { ":1s": "m’", ":1ś": "m’", ":2s": "t’", ":3s": "s’", ":1p": "nous ", ":2p": "vous ", ":3p": "s’" }
_dImpePro = { ":2s": "-toi", ":1p": "-nous", ":2p": "-vous" }
_dImpeProNeg = { ":2s": "ne te ", ":1p": "ne nous ", ":2p": "ne vous " }
_dImpeProEn = { ":2s": "-t’en", ":1p": "-nous-en", ":2p": "-vous-en" }
_dImpeProNegEn = { ":2s": "ne t’en ", ":1p": "ne nous en ", ":2p": "ne vous en " }
_dGroup = { "0": "auxiliaire", "1": "1ᵉʳ groupe", "2": "2ᵉ groupe", "3": "3ᵉ groupe" }
_dTenseIdx = { ":PQ": 0, ":Ip": 1, ":Iq": 2, ":Is": 3, ":If": 4, ":K": 5, ":Sp": 6, ":Sq": 7, ":E": 8 }
def isVerb (sVerb):
"return True if it’s a existing verb"
return sVerb in _dVerb
def getConj (sVerb, sTense, sWho):
"returns conjugation (can be an empty string)"
if sVerb not in _dVerb:
return None
return _modifyStringWithSuffixCode(sVerb, _dPatternConj[sTense][_lTags[_dVerb[sVerb][1]][_dTenseIdx[sTense]]].get(sWho, ""))
def hasConj (sVerb, sTense, sWho):
"returns False if no conjugation (also if empty) else True"
if sVerb not in _dVerb:
return False
if _dPatternConj[sTense][_lTags[_dVerb[sVerb][1]][_dTenseIdx[sTense]]].get(sWho, False):
return True
return False
def getVtyp (sVerb):
"returns raw informations about sVerb"
if sVerb not in _dVerb:
return None
return _lVtyp[_dVerb[sVerb][0]]
def getSimil (sWord, sMorph, bSubst=False):
"returns a set of verbal forms similar to <sWord>, according to <sMorph>"
if ":V" not in sMorph:
return set()
sInfi = sMorph[1:sMorph.find("/")]
aSugg = set()
tTags = _getTags(sInfi)
if tTags:
if not bSubst:
# we suggest conjugated forms
if ":V1" in sMorph:
aSugg.add(sInfi)
aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":3s"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":2p"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":1s"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":3s"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":3p"))
elif ":V2" in sMorph:
aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":1s"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":3s"))
elif ":V3" in sMorph:
aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":1s"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":3s"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":Is", ":1s"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":Is", ":3s"))
elif ":V0a" in sMorph:
aSugg.add("eus")
aSugg.add("eut")
else:
aSugg.add("étais")
aSugg.add("était")
aSugg.discard("")
else:
# we suggest past participles
aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q1"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q2"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q3"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q4"))
aSugg.discard("")
# if there is only one past participle (epi inv), unreliable.
if len(aSugg) == 1:
aSugg.clear()
return aSugg
def getConjSimilInfiV1 (sInfi):
"returns verbal forms phonetically similar to infinitive form (for verb in group 1)"
if sInfi not in _dVerb:
return set()
aSugg = set()
tTags = _getTags(sInfi)
if tTags:
aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":2s"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":3s"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":3p"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":Is", ":1s"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":2p"))
aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":2p"))
aSugg.discard("")
return aSugg
def _getTags (sVerb):
"returns tuple of tags (usable with functions _getConjWithTags and _hasConjWithTags)"
if sVerb not in _dVerb:
return None
return _lTags[_dVerb[sVerb][1]]
def _getConjWithTags (sVerb, tTags, sTense, sWho):
"returns conjugation (can be an empty string)"
return _modifyStringWithSuffixCode(sVerb, _dPatternConj[sTense][tTags[_dTenseIdx[sTense]]].get(sWho, ""))
def _hasConjWithTags (tTags, sTense, sWho):
"returns False if no conjugation (also if empty) else True"
if _dPatternConj[sTense][tTags[_dTenseIdx[sTense]]].get(sWho, False):
return True
return False
def _modifyStringWithSuffixCode (sWord, sSfx):
"returns sWord modified by sSfx"
if not sSfx:
return ""
if sSfx == "0":
return sWord
try:
return sWord[:-(ord(sSfx[0])-48)] + sSfx[1:] if sSfx[0] != '0' else sWord + sSfx[1:] # 48 is the ASCII code for "0"
except (IndexError, TypeError):
return "## erreur, code : " + str(sSfx) + " ##"
class Verb ():
"Verb and its conjugation"
def __init__ (self, sVerb, sVerbPattern=""):
# conjugate a unknown verb with rules from sVerbPattern
if not isinstance(sVerb, str):
raise TypeError("sVerb should be a string")
if not sVerb:
raise ValueError("Empty string.")
if sVerbPattern == "":
sVerbPattern = sVerb
self.sVerb = sVerb
self.sVerbAux = ""
self._sRawInfo = getVtyp(sVerbPattern)
self.sInfo = self._readableInfo()
self.bProWithEn = (self._sRawInfo[5] == "e")
self._tTags = _getTags(sVerbPattern)
if not self._tTags:
raise ValueError("Unknown verb.")
self._tTagsAux = _getTags(self.sVerbAux)
self.cGroup = self._sRawInfo[0];
self.dConj = {
":Y": {
"label": "Infinitif",
":": sVerb,
},
":P": {
"label": "Participe présent",
":": _getConjWithTags(sVerb, self._tTags, ":PQ", ":P"),
},
":Q": {
"label": "Participes passés",
":Q1": _getConjWithTags(sVerb, self._tTags, ":PQ", ":Q1"),
":Q2": _getConjWithTags(sVerb, self._tTags, ":PQ", ":Q2"),
":Q3": _getConjWithTags(sVerb, self._tTags, ":PQ", ":Q3"),
":Q4": _getConjWithTags(sVerb, self._tTags, ":PQ", ":Q4"),
},
":Ip": {
"label": "Présent",
":1s": _getConjWithTags(sVerb, self._tTags, ":Ip", ":1s"),
":1ś": _getConjWithTags(sVerb, self._tTags, ":Ip", ":1ś"),
":2s": _getConjWithTags(sVerb, self._tTags, ":Ip", ":2s"),
":3s": _getConjWithTags(sVerb, self._tTags, ":Ip", ":3s"),
":1p": _getConjWithTags(sVerb, self._tTags, ":Ip", ":1p"),
":2p": _getConjWithTags(sVerb, self._tTags, ":Ip", ":2p"),
":3p": _getConjWithTags(sVerb, self._tTags, ":Ip", ":3p"),
},
":Iq": {
"label": "Imparfait",
":1s": _getConjWithTags(sVerb, self._tTags, ":Iq", ":1s"),
":2s": _getConjWithTags(sVerb, self._tTags, ":Iq", ":2s"),
":3s": _getConjWithTags(sVerb, self._tTags, ":Iq", ":3s"),
":1p": _getConjWithTags(sVerb, self._tTags, ":Iq", ":1p"),
":2p": _getConjWithTags(sVerb, self._tTags, ":Iq", ":2p"),
":3p": _getConjWithTags(sVerb, self._tTags, ":Iq", ":3p"),
},
":Is": {
"label": "Passé simple",
":1s": _getConjWithTags(sVerb, self._tTags, ":Is", ":1s"),
":2s": _getConjWithTags(sVerb, self._tTags, ":Is", ":2s"),
":3s": _getConjWithTags(sVerb, self._tTags, ":Is", ":3s"),
":1p": _getConjWithTags(sVerb, self._tTags, ":Is", ":1p"),
":2p": _getConjWithTags(sVerb, self._tTags, ":Is", ":2p"),
":3p": _getConjWithTags(sVerb, self._tTags, ":Is", ":3p"),
},
":If": {
"label": "Futur",
":1s": _getConjWithTags(sVerb, self._tTags, ":If", ":1s"),
":2s": _getConjWithTags(sVerb, self._tTags, ":If", ":2s"),
":3s": _getConjWithTags(sVerb, self._tTags, ":If", ":3s"),
":1p": _getConjWithTags(sVerb, self._tTags, ":If", ":1p"),
":2p": _getConjWithTags(sVerb, self._tTags, ":If", ":2p"),
":3p": _getConjWithTags(sVerb, self._tTags, ":If", ":3p"),
},
":Sp": {
"label": "Présent subjonctif",
":1s": _getConjWithTags(sVerb, self._tTags, ":Sp", ":1s"),
":1ś": _getConjWithTags(sVerb, self._tTags, ":Sp", ":1ś"),
":2s": _getConjWithTags(sVerb, self._tTags, ":Sp", ":2s"),
":3s": _getConjWithTags(sVerb, self._tTags, ":Sp", ":3s"),
":1p": _getConjWithTags(sVerb, self._tTags, ":Sp", ":1p"),
":2p": _getConjWithTags(sVerb, self._tTags, ":Sp", ":2p"),
":3p": _getConjWithTags(sVerb, self._tTags, ":Sp", ":3p"),
},
":Sq": {
"label": "Imparfait subjonctif",
":1s": _getConjWithTags(sVerb, self._tTags, ":Sq", ":1s"),
":1ś": _getConjWithTags(sVerb, self._tTags, ":Sq", ":1ś"),
":2s": _getConjWithTags(sVerb, self._tTags, ":Sq", ":2s"),
":3s": _getConjWithTags(sVerb, self._tTags, ":Sq", ":3s"),
":1p": _getConjWithTags(sVerb, self._tTags, ":Sq", ":1p"),
":2p": _getConjWithTags(sVerb, self._tTags, ":Sq", ":2p"),
":3p": _getConjWithTags(sVerb, self._tTags, ":Sq", ":3p"),
},
":K": {
"label": "Conditionnel",
":1s": _getConjWithTags(sVerb, self._tTags, ":K", ":1s"),
":2s": _getConjWithTags(sVerb, self._tTags, ":K", ":2s"),
":3s": _getConjWithTags(sVerb, self._tTags, ":K", ":3s"),
":1p": _getConjWithTags(sVerb, self._tTags, ":K", ":1p"),
":2p": _getConjWithTags(sVerb, self._tTags, ":K", ":2p"),
":3p": _getConjWithTags(sVerb, self._tTags, ":K", ":3p"),
},
":E": {
"label": "Impératif",
":2s": _getConjWithTags(sVerb, self._tTags, ":E", ":2s"),
":1p": _getConjWithTags(sVerb, self._tTags, ":E", ":1p"),
":2p": _getConjWithTags(sVerb, self._tTags, ":E", ":2p"),
},
}
def _readableInfo (self):
"returns readable infos about sVerb"
try:
if not self._sRawInfo:
return "verbe inconnu"
if self._sRawInfo[7:8] == "e":
self.sVerbAux = "être"
else:
self.sVerbAux = "avoir"
sGroup = _dGroup.get(self._sRawInfo[0], "# erreur ")
sInfo = ""
if self._sRawInfo[3:4] == "t":
sInfo = "transitif"
elif self._sRawInfo[4:5] == "n":
sInfo = "transitif indirect"
elif self._sRawInfo[2:3] == "i":
sInfo = "intransitif"
elif self._sRawInfo[5:6] == "r":
sInfo = "pronominal réciproque"
elif self._sRawInfo[5:6] == "p":
sInfo = "pronominal"
if self._sRawInfo[5:6] in ["q", "u", "v", "e"]:
sInfo = sInfo + " (+ usage pronominal)"
if self._sRawInfo[6:7] == "m":
sInfo = sInfo + " impersonnel"
if not sInfo:
sInfo = "# erreur - code : " + self._sRawInfo
return sGroup + " · " + sInfo
except:
traceback.print_exc()
return "# erreur"
def infinitif (self, bPro, bNeg, bTpsCo, bInt, bFem):
try:
if bTpsCo:
sInfi = self.sVerbAux if not bPro else "être"
else:
sInfi = self.sVerb
if bPro:
if self.bProWithEn:
sInfi = "s’en " + sInfi
else:
sInfi = "s’" + sInfi if _zStartVoy.search(sInfi) else "se " + sInfi
if bNeg:
sInfi = "ne pas " + sInfi
if bTpsCo:
sInfi += " " + self._seekPpas(bPro, bFem, self._sRawInfo[5] == "r")
if bInt:
sInfi += " … ?"
return sInfi
except:
traceback.print_exc()
return "# erreur"
def participePasse (self, sWho):
try:
return self.dConj[":Q"][sWho]
except:
traceback.print_exc()
return "# erreur"
def participePresent (self, bPro, bNeg, bTpsCo, bInt, bFem):
try:
if not self.dConj[":P"][":"]:
return ""
if bTpsCo:
sPartPre = _getConjWithTags(self.sVerbAux, self._tTagsAux, ":PQ", ":P") if not bPro else getConj("être", ":PQ", ":P")
else:
sPartPre = self.dConj[":P"][":"]
if not sPartPre:
return ""
bEli = True if _zStartVoy.search(sPartPre) else False
if bPro:
if self.bProWithEn:
sPartPre = "s’en " + sPartPre
else:
sPartPre = "s’" + sPartPre if bEli else "se " + sPartPre
if bNeg:
if bEli and not bPro:
sPartPre = "n’" + sPartPre + " pas"
else:
sPartPre = "ne " + sPartPre + " pas"
if bTpsCo:
sPartPre += " " + self._seekPpas(bPro, bFem, self._sRawInfo[5] == "r")
if bInt:
sPartPre += " … ?"
return sPartPre
except:
traceback.print_exc()
return "# erreur"
def conjugue (self, sTemps, sWho, bPro, bNeg, bTpsCo, bInt, bFem):
try:
if not self.dConj[sTemps][sWho]:
return ""
if not bTpsCo and bInt and sWho == ":1s" and self.dConj[sTemps].get(":1ś", False):
sWho = ":1ś"
if bTpsCo:
sConj = _getConjWithTags(self.sVerbAux, self._tTagsAux, sTemps, sWho) if not bPro else getConj("être", sTemps, sWho)
else:
sConj = self.dConj[sTemps][sWho]
if not sConj:
return ""
bEli = True if _zStartVoy.search(sConj) else False
if bPro:
if not self.bProWithEn:
sConj = _dProObjEl[sWho] + sConj if bEli else _dProObj[sWho] + sConj
else:
sConj = _dProObjEl[sWho] + "en " + sConj
if bNeg:
sConj = "n’" + sConj if bEli and not bPro else "ne " + sConj
if bInt:
if sWho == ":3s" and not _zNeedTeuph.search(sConj):
sConj += "-t"
sConj += "-" + self._getPronom(sWho, bFem)
else:
if sWho == ":1s" and bEli and not bNeg and not bPro:
sConj = "j’" + sConj
else:
sConj = self._getPronom(sWho, bFem) + " " + sConj
if bNeg:
sConj += " pas"
if bTpsCo:
sConj += " " + self._seekPpas(bPro, bFem, sWho.endswith("p") or self._sRawInfo[5] == "r")
if bInt:
sConj += " … ?"
return sConj
except:
traceback.print_exc()
return "# erreur"
def _getPronom (self, sWho, bFem):
try:
if sWho == ":3s":
if self._sRawInfo[5] == "r":
return "on"
elif bFem:
return "elle"
elif sWho == ":3p" and bFem:
return "elles"
return _dProSuj[sWho]
except:
traceback.print_exc()
return "# erreur"
def imperatif (self, sWho, bPro, bNeg, bTpsCo, bFem):
try:
if not self.dConj[":E"][sWho]:
return ""
if bTpsCo:
sImpe = _getConjWithTags(self.sVerbAux, self._tTagsAux, ":E", sWho) if not bPro else getConj(u"être", ":E", sWho)
else:
sImpe = self.dConj[":E"][sWho]
if not sImpe:
return ""
bEli = True if _zStartVoy.search(sImpe) else False
if bNeg:
if bPro:
if not self.bProWithEn:
if bEli and sWho == ":2s":
sImpe = "ne t’" + sImpe + " pas"
else:
sImpe = _dImpeProNeg[sWho] + sImpe + " pas"
else:
sImpe = _dImpeProNegEn[sWho] + sImpe + " pas"
else:
sImpe = "n’" + sImpe + " pas" if bEli else "ne " + sImpe + " pas"
elif bPro:
sImpe = sImpe + _dImpeProEn[sWho] if self.bProWithEn else sImpe + _dImpePro[sWho]
if bTpsCo:
return sImpe + " " + self._seekPpas(bPro, bFem, sWho.endswith("p") or self._sRawInfo[5] == "r")
return sImpe
except:
traceback.print_exc()
return "# erreur"
def _seekPpas (self, bPro, bFem, bPlur):
try:
if not bPro and self.sVerbAux == "avoir":
return self.dConj[":Q"][":Q1"]
if not bFem:
return self.dConj[":Q"][":Q2"] if bPlur and self.dConj[":Q"][":Q2"] else self.dConj[":Q"][":Q1"]
if not bPlur:
return self.dConj[":Q"][":Q3"] if self.dConj[":Q"][":Q3"] else self.dConj[":Q"][":Q1"]
return self.dConj[":Q"][":Q4"] if self.dConj[":Q"][":Q4"] else self.dConj[":Q"][":Q1"]
except:
traceback.print_exc()
return "# erreur"