Index: gc_core/js/tests.js ================================================================== --- gc_core/js/tests.js +++ gc_core/js/tests.js @@ -193,12 +193,17 @@ let lAllFoundSuggs = sAllFoundSuggs.split("|||"); if (lAllExpectedSuggs.length != lAllFoundSuggs.length) { return false; } for (let i = 0; i < lAllExpectedSuggs.length; i++) { - let aExpectedSuggs = new Set(lAllExpectedSuggs[i].split("|")); - let aFoundSuggs = new Set(lAllFoundSuggs[i].split("|")); + let lExpectedSuggs = lAllExpectedSuggs[i].split("|"); + let lFoundSuggs = lAllFoundSuggs[i].split("|"); + if (lExpectedSuggs.length != lFoundSuggs.length) { + return false; + } + let aExpectedSuggs = new Set(lExpectedSuggs); + let aFoundSuggs = new Set(lFoundSuggs); if (aExpectedSuggs.size !== aFoundSuggs.size || ![...aExpectedSuggs].every(value => aFoundSuggs.has(value))) { return false; } } return true; Index: gc_core/py/lang_core/tests_core.py ================================================================== --- gc_core/py/lang_core/tests_core.py +++ gc_core/py/lang_core/tests_core.py @@ -175,11 +175,13 @@ lAllExpectedSuggs = sAllExceptedSuggs.split("|||") lAllFoundSuggs = sAllFoundSuggs.split("|||") if len(lAllExpectedSuggs) != len(lAllFoundSuggs): return False for sExceptedSuggs, sFoundSuggs in zip(lAllExpectedSuggs, lAllFoundSuggs): - if set(sExceptedSuggs.split("|")) != set(sFoundSuggs.split("|")): + lExpectedSuggs = sExceptedSuggs.split("|") + lFoundSuggs = sFoundSuggs.split("|") + if len(lExpectedSuggs) != len(lFoundSuggs) or set(lExpectedSuggs) != set(lFoundSuggs): return False return True def purgeMessage (sMessage): Index: gc_lang/fr/modules/gce_suggestions.py ================================================================== --- gc_lang/fr/modules/gce_suggestions.py +++ gc_lang/fr/modules/gce_suggestions.py @@ -21,11 +21,11 @@ def suggVerb (sFlex, sWho, funcSugg2=None, bVC=False): "change conjugation according to " if bVC: sFlex, sSfx = splitVerb(sFlex) - aSugg = [] + dSugg = {} for sStem in _oSpellChecker.getLemma(sFlex): tTags = conj._getTags(sStem) if tTags: # we get the tense aTense = {} # we use dict as ordered set @@ -43,19 +43,19 @@ aTense[m.group(1)] = "" for sTense in aTense.keys(): if sWho == ":1ś" and not conj._hasConjWithTags(tTags, sTense, ":1ś"): sWho = ":1s" if conj._hasConjWithTags(tTags, sTense, sWho): - aSugg.append(conj._getConjWithTags(sStem, tTags, sTense, sWho)) + dSugg[conj._getConjWithTags(sStem, tTags, sTense, sWho)] = "" if funcSugg2: sSugg2 = funcSugg2(sFlex) if sSugg2: - aSugg.append(sSugg2) - if aSugg: + dSugg[sSugg2] = "" + if dSugg: if bVC: - aSugg = [ joinVerbAndSuffix(sSugg, sSfx) for sSugg in aSugg ] - return "|".join(aSugg) + return "|".join([ joinVerbAndSuffix(sSugg, sSfx) for sSugg in dSugg.keys() ]) + return "|".join(dSugg.keys()) return "" def joinVerbAndSuffix (sFlex, sSfx): if sSfx.startswith(("-t-", "-T-")) and sFlex.endswith(("t", "d", "T", "D")): @@ -68,54 +68,54 @@ return sFlex + sSfx def suggVerbPpas (sFlex, sPattern=None): "suggest past participles for " - aSugg = [] + dSugg = {} for sStem in _oSpellChecker.getLemma(sFlex): tTags = conj._getTags(sStem) if tTags: if not sPattern: - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = "" if conj._hasConjWithTags(tTags, ":PQ", ":Q2"): - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q2")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q2")] = "" if conj._hasConjWithTags(tTags, ":PQ", ":Q3"): - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q3")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q3")] = "" if conj._hasConjWithTags(tTags, ":PQ", ":Q4"): - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q4")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q4")] = "" elif sPattern == ":m:s": - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = "" elif sPattern == ":m:p": if conj._hasConjWithTags(tTags, ":PQ", ":Q2"): - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q2")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q2")] = "" else: - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = "" elif sPattern == ":f:s": if conj._hasConjWithTags(tTags, ":PQ", ":Q3"): - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q3")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q3")] = "" else: - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = "" elif sPattern == ":f:p": if conj._hasConjWithTags(tTags, ":PQ", ":Q4"): - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q4")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q4")] = "" else: - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = "" elif sPattern == ":s": - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = "" if conj._hasConjWithTags(tTags, ":PQ", ":Q3"): - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q3")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q3")] = "" elif sPattern == ":p": if conj._hasConjWithTags(tTags, ":PQ", ":Q2"): - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q2")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q2")] = "" else: - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = "" if conj._hasConjWithTags(tTags, ":PQ", ":Q4"): - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q4")) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q4")] = "" else: - aSugg.append(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")) - if aSugg: - return "|".join(aSugg) + dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = "" + if dSugg: + return "|".join(dSugg) return "" def suggVerbTense (sFlex, sTense, sWho): "change to a verb according to and " @@ -128,24 +128,24 @@ return "" def suggVerbFrom (sStem, sFlex, sWho=""): "conjugate according to (and eventually )" - aSugg = [] + dSugg = {} for sMorph in _oSpellChecker.getMorph(sFlex): lTenses = [ m.group(0) for m in re.finditer(":(?:Y|I[pqsf]|S[pq]|K|P|Q)", sMorph) ] if sWho: for sTense in lTenses: if conj.hasConj(sStem, sTense, sWho): - aSugg.append(conj.getConj(sStem, sTense, sWho)) + dSugg[conj.getConj(sStem, sTense, sWho)] = "" else: for sTense in lTenses: for sWho in [ m.group(0) for m in re.finditer(":[123][sp]", sMorph) ]: if conj.hasConj(sStem, sTense, sWho): - aSugg.append(conj.getConj(sStem, sTense, sWho)) - if aSugg: - return "|".join(aSugg) + dSugg[conj.getConj(sStem, sTense, sWho)] = "" + if dSugg: + return "|".join(dSugg.keys()) return "" def suggVerbImpe (sFlex, bVC=False): "change to a verb at imperative form" @@ -185,19 +185,19 @@ elif cMode.startswith((":I", ":S")): lMode = [cMode] else: return "" sWho = _dQuiEst.get(sSuj.lower(), ":3s") - aSugg = [] + dSugg = {} for sStem in _oSpellChecker.getLemma(sFlex): tTags = conj._getTags(sStem) if tTags: for sTense in lMode: if conj._hasConjWithTags(tTags, sTense, sWho): - aSugg.append(conj._getConjWithTags(sStem, tTags, sTense, sWho)) - if aSugg: - return "|".join(aSugg) + dSugg[conj._getConjWithTags(sStem, tTags, sTense, sWho)] = "" + if dSugg: + return "|".join(dSugg.keys()) return "" ## Nouns and adjectives @@ -255,112 +255,112 @@ return "" def suggMasSing (sFlex, bSuggSimil=False): "returns masculine singular forms" - aSugg = [] + dSugg = {} for sMorph in _oSpellChecker.getMorph(sFlex): if not ":V" in sMorph: # not a verb if ":m" in sMorph or ":e" in sMorph: - aSugg.append(suggSing(sFlex)) + dSugg[suggSing(sFlex)] = "" else: sStem = cr.getLemmaOfMorph(sMorph) if mfsp.isMasForm(sStem): - aSugg.append(sStem) + dSugg[sStem] = "" else: # a verb sVerb = cr.getLemmaOfMorph(sMorph) if conj.hasConj(sVerb, ":PQ", ":Q1") and conj.hasConj(sVerb, ":PQ", ":Q3"): # We also check if the verb has a feminine form. # If not, we consider it’s better to not suggest the masculine one, as it can be considered invariable. - aSugg.append(conj.getConj(sVerb, ":PQ", ":Q1")) + dSugg[conj.getConj(sVerb, ":PQ", ":Q1")] = "" if bSuggSimil: for e in phonet.selectSimil(sFlex, ":m:[si]"): - aSugg.append(e) - if aSugg: - return "|".join(aSugg) + dSugg[e] = "" + if dSugg: + return "|".join(dSugg.keys()) return "" def suggMasPlur (sFlex, bSuggSimil=False): "returns masculine plural forms" - aSugg = [] + dSugg = {} for sMorph in _oSpellChecker.getMorph(sFlex): if not ":V" in sMorph: # not a verb if ":m" in sMorph or ":e" in sMorph: - aSugg.append(suggPlur(sFlex)) + dSugg[suggPlur(sFlex)] = "" else: sStem = cr.getLemmaOfMorph(sMorph) if mfsp.isMasForm(sStem): - aSugg.append(suggPlur(sStem, True)) + dSugg[suggPlur(sStem, True)] = "" else: # a verb sVerb = cr.getLemmaOfMorph(sMorph) if conj.hasConj(sVerb, ":PQ", ":Q2"): - aSugg.append(conj.getConj(sVerb, ":PQ", ":Q2")) + dSugg[conj.getConj(sVerb, ":PQ", ":Q2")] = "" elif conj.hasConj(sVerb, ":PQ", ":Q1"): sSugg = conj.getConj(sVerb, ":PQ", ":Q1") # it is necessary to filter these flexions, like “succédé” or “agi” that are not masculine plural. if sSugg.endswith("s"): - aSugg.append(sSugg) + dSugg[sSugg] = "" if bSuggSimil: for e in phonet.selectSimil(sFlex, ":m:[pi]"): - aSugg.append(e) - if aSugg: - return "|".join(aSugg) + dSugg[e] = "" + if dSugg: + return "|".join(dSugg.keys()) return "" def suggFemSing (sFlex, bSuggSimil=False): "returns feminine singular forms" - aSugg = [] + dSugg = {} for sMorph in _oSpellChecker.getMorph(sFlex): if not ":V" in sMorph: # not a verb if ":f" in sMorph or ":e" in sMorph: - aSugg.append(suggSing(sFlex)) + dSugg[suggSing(sFlex)] = "" else: sStem = cr.getLemmaOfMorph(sMorph) if mfsp.isMasForm(sStem): - aSugg.extend(mfsp.getFemForm(sStem, False)) + dSugg.update(dict.fromkeys(mfsp.getFemForm(sStem, False), "")) else: # a verb sVerb = cr.getLemmaOfMorph(sMorph) if conj.hasConj(sVerb, ":PQ", ":Q3"): - aSugg.append(conj.getConj(sVerb, ":PQ", ":Q3")) + dSugg[conj.getConj(sVerb, ":PQ", ":Q3")] = "" if bSuggSimil: for e in phonet.selectSimil(sFlex, ":f:[si]"): - aSugg.append(e) - if aSugg: - return "|".join(aSugg) + dSugg[e] = "" + if dSugg: + return "|".join(dSugg.keys()) return "" def suggFemPlur (sFlex, bSuggSimil=False): "returns feminine plural forms" - aSugg = [] + dSugg = {} for sMorph in _oSpellChecker.getMorph(sFlex): if not ":V" in sMorph: # not a verb if ":f" in sMorph or ":e" in sMorph: - aSugg.append(suggPlur(sFlex)) + dSugg[suggPlur(sFlex)] = "" else: sStem = cr.getLemmaOfMorph(sMorph) if mfsp.isMasForm(sStem): - aSugg.extend(mfsp.getFemForm(sStem, True)) + dSugg.update(dict.fromkeys(mfsp.getFemForm(sStem, True))) else: # a verb sVerb = cr.getLemmaOfMorph(sMorph) if conj.hasConj(sVerb, ":PQ", ":Q4"): - aSugg.append(conj.getConj(sVerb, ":PQ", ":Q4")) + dSugg[conj.getConj(sVerb, ":PQ", ":Q4")] = "" if bSuggSimil: for e in phonet.selectSimil(sFlex, ":f:[pi]"): - aSugg.append(e) - if aSugg: - return "|".join(aSugg) + dSugg[e] = "" + if dSugg: + return "|".join(dSugg) return "" def g_suggAgree (dTokenDst, dTokenSrc): "returns suggestions for that matches agreement with " @@ -410,53 +410,53 @@ return False def switchGender (sFlex, bPlur=None): "return feminine or masculine form(s) of " - aSugg = [] + dSugg = {} if bPlur is None: for sMorph in _oSpellChecker.getMorph(sFlex): if ":f" in sMorph: if ":s" in sMorph: - aSugg.append(suggMasSing(sFlex)) + dSugg[suggMasSing(sFlex)] = "" elif ":p" in sMorph: - aSugg.append(suggMasPlur(sFlex)) + dSugg[suggMasPlur(sFlex)] = "" elif ":m" in sMorph: if ":s" in sMorph: - aSugg.append(suggFemSing(sFlex)) + dSugg[suggFemSing(sFlex)] = "" elif ":p" in sMorph: - aSugg.append(suggFemPlur(sFlex)) + dSugg[suggFemPlur(sFlex)] = "" else: - aSugg.append(suggFemSing(sFlex)) - aSugg.append(suggFemPlur(sFlex)) + dSugg[suggFemSing(sFlex)] = "" + dSugg[suggFemPlur(sFlex)] = "" elif bPlur: for sMorph in _oSpellChecker.getMorph(sFlex): if ":f" in sMorph: - aSugg.append(suggMasPlur(sFlex)) + dSugg[suggMasPlur(sFlex)] = "" elif ":m" in sMorph: - aSugg.append(suggFemPlur(sFlex)) + dSugg[suggFemPlur(sFlex)] = "" else: for sMorph in _oSpellChecker.getMorph(sFlex): if ":f" in sMorph: - aSugg.append(suggMasSing(sFlex)) + dSugg[suggMasSing(sFlex)] = "" elif ":m" in sMorph: - aSugg.append(suggFemSing(sFlex)) - if aSugg: - return "|".join(aSugg) + dSugg[suggFemSing(sFlex)] = "" + if dSugg: + return "|".join(dSugg.keys()) return "" def switchPlural (sFlex): "return plural or singular form(s) of " - aSugg = [] + aSugg = {} for sMorph in _oSpellChecker.getMorph(sFlex): if ":s" in sMorph: - aSugg.append(suggPlur(sFlex)) + aSugg[suggPlur(sFlex)] = "" elif ":p" in sMorph: - aSugg.append(suggSing(sFlex)) + aSugg[suggSing(sFlex)] = "" if aSugg: - return "|".join(aSugg) + return "|".join(aSugg.keys()) return "" def hasSimil (sWord, sPattern=None): "return True if there is words phonetically similar to (according to if required)" @@ -465,26 +465,26 @@ def suggSimil (sWord, sPattern=None, bSubst=False, bVC=False): "return list of words phonetically similar to and whom POS is matching " if bVC: sWord, sSfx = splitVerb(sWord) - aSugg = phonet.selectSimil(sWord, sPattern) - if not aSugg and bSubst: + dSugg = dict.fromkeys(phonet.selectSimil(sWord, sPattern), "") + if not dSugg and bSubst: for sMorph in _oSpellChecker.getMorph(sWord): if ":V" in sMorph: sInfi = sMorph[1:sMorph.find("/")] if sPattern: for sName in conj.getNamesFrom(sInfi): if any(re.search(sPattern, sMorph2) for sMorph2 in _oSpellChecker.getMorph(sName)): - aSugg.append(sName) + dSugg[sName] = "" else: - aSugg.extend(conj.getNamesFrom(sInfi)) + dSugg.update(dict.fromkeys(conj.getNamesFrom(sInfi), "")) break - if aSugg: + if dSugg: if bVC: - aSugg = [ joinVerbAndSuffix(sSugg, sSfx) for sSugg in aSugg ] - return "|".join(aSugg) + return "|".join([ joinVerbAndSuffix(sSugg, sSfx) for sSugg in dSugg.keys() ]) + return "|".join(dSugg.keys()) return "" def suggCeOrCet (sWord): "suggest “ce” or “cet” or both according to the first letter of "