commit 7f93dfb1a042560e57035786c8bab5b5e719bf81
parent 9ec20de861e47bd1b7c0f31c31de5e7c684c6441
Author: Antoine Amarilli <a3nm@a3nm.net>
Date: Wed, 30 Jan 2013 22:52:01 +0100
Add repeat_ok and incomplete_ok options
Following Robert Rapilly's suggestion
<49CB20FF-7AB0-4A7D-9EE6-A9E1FF2CDC48@orange.fr>.
Diffstat:
8 files changed, 68 insertions(+), 10 deletions(-)
diff --git a/error.py b/error.py
@@ -26,11 +26,13 @@ class Error:
msg = _("Line is: %s") % (self.line)
if short:
if t != []:
- l.append(msg)
+ if self.line.strip() != "":
+ l.append(msg)
for x in t:
l.append(x)
else:
- l.append(self.say(msg))
+ if self.line.strip() != "":
+ l.append(self.say(msg))
for x in t:
l.append(self.say(x))
return '\n'.join(l)
@@ -197,3 +199,13 @@ class ErrorMultipleWordOccurrence(Error):
return Error.report(self, _("Too many occurrences of word %s for rhyme %s")
% (self.word, self.get_id()), short)
+class ErrorIncompleteTemplate(Error):
+ def report(self, short=False):
+ return Error.report(self, _("Poem is not complete"),
+ short)
+
+class ErrorOverflowedTemplate(Error):
+ def report(self, short=False):
+ return Error.report(self, _("Verse is beyond end of poem"),
+ short)
+
diff --git a/plint.py b/plint.py
@@ -9,14 +9,18 @@ def run():
f2 = None
if len(sys.argv) == 3:
f2 = open(sys.argv[2], 'w')
+ should_end = False
while True:
line = sys.stdin.readline()
if not line:
- break
- errors = template.check(line, f2)
+ should_end = True
+ line = ""
+ errors = template.check(line, f2, last=should_end)
for error in errors:
print(error.report(), file=sys.stderr)
ok = False
+ if should_end:
+ break
return ok
if __name__ == '__main__':
diff --git a/static/tpl/french_abab.tpl b/static/tpl/french_abab.tpl
@@ -1,3 +1,4 @@
+! incomplete_ok:no repeat_ok:no
6/6 A x
6/6 B X
6/6 A X
diff --git a/static/tpl/french_abba.tpl b/static/tpl/french_abba.tpl
@@ -1,3 +1,4 @@
+! incomplete_ok:no repeat_ok:no
6/6 A x
6/6 B X
6/6 B X
diff --git a/static/tpl/italian_abab.tpl b/static/tpl/italian_abab.tpl
@@ -1,3 +1,4 @@
+! incomplete_ok:no repeat_ok:no
6/6 A x
6/6 B X
6/6 A X
diff --git a/static/tpl/italian_abba.tpl b/static/tpl/italian_abba.tpl
@@ -1,3 +1,4 @@
+! incomplete_ok:no repeat_ok:no
6/6 A x
6/6 B X
6/6 B X
diff --git a/template.py b/template.py
@@ -48,6 +48,9 @@ class Template:
self.forbidden_ok = False
self.hiatus_ok = False
self.normande_ok = True
+ self.repeat_ok = True
+ self.overflowed = False
+ self.incomplete_ok = True
self.check_end_hemistiche = True
self.check_occurrences = True
self.diaeresis = "classical"
@@ -81,6 +84,10 @@ class Template:
self.check_end_hemistiche = str2bool(value)
elif key in ["check_occurrences", "verifie_occurrences"]:
self.check_occurrences = str2bool(value)
+ elif key in ["repeat_ok"]:
+ self.repeat_ok = str2bool(value)
+ elif key in ["incomplete_ok"]:
+ self.incomplete_ok = str2bool(value)
else:
raise ValueError
@@ -114,12 +121,23 @@ class Template:
return ((1+len(hemis.keys()))*abs(pattern.length - c)
+ sum([1 for x in hemis.values() if x != "ok"]))
- def match(self, line, ofile=None, quiet=False):
+ def match(self, line, ofile=None, quiet=False, last=False):
"""Check a line against current pattern, return errors"""
+ was_incomplete = last and not self.beyond
+
errors = []
pattern = self.get()
+ if last:
+ if was_incomplete:
+ errors.append(error.ErrorIncompleteTemplate())
+ return errors, pattern
+
+ if self.overflowed:
+ errors.append(error.ErrorOverflowedTemplate())
+ return errors, pattern
+
# check characters
illegal = set()
for x in line:
@@ -213,7 +231,7 @@ class Template:
errors.append(error.ErrorMultipleWordOccurrence(last_word,
self.occenv[pattern.myid][last_word]))
- # rhyme genres
+ # rhyme genres
# inequality constraint
# TODO this is simplistic and order-dependent
if pattern.femid.swapcase() in self.femenv.keys():
@@ -274,13 +292,19 @@ class Template:
self.femenv = self.reset_conditional(self.femenv)
self.occenv = {} # always reset
+ @property
+ def beyond(self):
+ return self.position >= len(self.template)
+
def get(self):
"""Get next state, resetting if needed"""
self.old_position = self.position
self.old_env = copy.deepcopy(self.env)
self.old_femenv = copy.deepcopy(self.femenv)
self.old_occenv = copy.deepcopy(self.occenv)
- if self.position >= len(self.template):
+ if self.beyond:
+ if not self.repeat_ok:
+ self.overflowed = True
self.reset_state()
result = self.template[self.position]
self.position += 1
@@ -293,15 +317,15 @@ class Template:
self.femenv = copy.deepcopy(self.old_femenv)
self.occenv = copy.deepcopy(self.old_occenv)
- def check(self, line, ofile=None, quiet=False):
+ def check(self, line, ofile=None, quiet=False, last=False):
"""Check line (wrapper)"""
self.line_no += 1
line = line.rstrip()
- if normalize(line) == '':
+ if normalize(line) == '' and not last:
return []
#possible = [compute(p) for p in possible]
#possible = sorted(possible, key=rate)
- errors, pattern = self.match(line, ofile, quiet=quiet)
+ errors, pattern = self.match(line, ofile, quiet=quiet, last=last)
for error in errors:
if error != None:
# update errors with line position and pattern
diff --git a/views/about.html b/views/about.html
@@ -143,6 +143,13 @@ options suivantes sont reconnues :</p>
approximations plus permissives qui accepteront à peu près n'importe quelle
diérèse ou synérèse phonétiquement plausible. La valeur par défaut est
"classical".</dd>
+ <dt>repeat_ok</dt>
+ <dd>Si cette valeur est false, le modèle ne se répétera pas, un poème plus
+ long que le modèle provoquera une erreur. Par défaut, la valeur est true.</dd>
+ <dt>incomplete_ok</dt>
+ <dd>Si cette valeur est false, le poème devrait avoir exactement la longueur
+ du modèle (ou un multiple, si repeat_ok est true), ne pas aller jusqu'à la fin
+ du modèle provoquera une erreur. Par défaut, la valeur est true.</dd>
</dl>
<p>Désolé si tout cela semble un peu obscur. Vous pouvez regarder les modèles
@@ -301,6 +308,13 @@ form option:value and separated by spaces, with the following possibilities:</p>
rules of classical verse or "permissive" to enforce a more permissive
approximations which will allow mostly all phonetically reasonable diérèses
and synérèses. Default is "classical".</dd>
+ <dt>repeat_ok</dt>
+ <dd>If the value is false, the template will not repeat, and going beyond its
+ end will be an error. Default is true.</dd>
+ <dt>incomplete_ok</dt>
+ <dd>If the value is false, the poem should match the length of the template
+ (or a multiple thereof is repeat_ok was set), and not completing a template
+ run will be an error. Default is true.</dd>
</dl>
<p>Sorry if all of this is a bit obscure. You can have a look to the predefined