plint

French poetry validator
git clone https://a3nm.net/git/plint/
Log | Files | Refs | README

error.py (4725B)


      1 import common
      2 
      3 
      4 class ErrorCollection:
      5   keys = {'hiatus': 'H', 'ambiguous': 'A', 'illegal': 'I'}
      6 
      7   @property
      8   def prefix(self):
      9     return "stdin:%d: " % self.line_no
     10 
     11   def __init__(self, line_no, line, pattern, verse, errors=[]):
     12     self.line_no = line_no
     13     self.line = line
     14     self.errors = errors
     15     self.pattern = pattern
     16     self.verse = verse
     17 
     18   def say(self, l, short):
     19     return l if short else self.prefix + l
     20 
     21   def align(self):
     22     chunks = self.verse.chunks
     23     keys = ['original', 'error']
     24     if len(self.verse.possible) == 0:
     25       keys.append('weights')
     26       if len(self.pattern.hemistiches) > 0:
     27         keys.append('hemis')
     28     formatters = {'weights': lambda x, y: '-'.join([str(a) for a in x]),
     29         'error': lambda x, y: ErrorCollection.keys.get(x, '') *
     30         len(chunk['original'])}
     31     def render(chunk, key):
     32       if key == 'error' and chunk.get('error', '') == 'illegal':
     33         return chunk['illegal_str']
     34       return (formatters.get(key, lambda x, y: str(x)))(chunk.get(key, ""), chunk)
     35     lines = {}
     36     for key in keys:
     37       lines[key] = ""
     38     for chunk in chunks:
     39       l = max(len(render(chunk, key)) for key in keys)
     40       for key in keys:
     41         lines[key] += ('{:^'+str(l)+'}').format(render(chunk, key))
     42     if 'weights' in keys:
     43       bounds = [0, 0]
     44       for chunk in self.verse.chunks:
     45         weights = chunk.get("weights", [0, 0])
     46         bounds[0] += weights[0]
     47         if len(weights) == 2:
     48           bounds[1] += weights[1]
     49         else:
     50           bounds[1] += weights[0]
     51       bounds = [str(x) for x in bounds]
     52       lines['weights'] += " (total: " + ('-'.join(bounds)
     53           if bounds[1] > bounds[0] else bounds[0]) + ")"
     54     return ["> " + lines[key] for key in keys if len(lines[key].strip()) > 0]
     55 
     56   def lines(self, short=False):
     57     l = []
     58     if self.verse.possible != None:
     59       l.append([self.say(x, short) for x in self.align()])
     60     for e in self.errors:
     61       l.append([self.say(e.report(self.pattern), short)])
     62     return l
     63 
     64   def report(self, short=False):
     65     return '\n'.join(sum(self.lines(short), []))
     66 
     67 class ErrorBadElement:
     68   def report(self, pattern):
     69     return (self.message
     70         + _(" (see '%s' above)") % ErrorCollection.keys[self.key])
     71 
     72 class ErrorBadCharacters(ErrorBadElement):
     73   @property
     74   def message(self):
     75     return _("Illegal characters")
     76   key = "illegal"
     77 
     78 class ErrorForbiddenPattern(ErrorBadElement):
     79   @property
     80   def message(self):
     81     return _("Illegal ambiguous pattern")
     82   key = "ambiguous"
     83 
     84 class ErrorHiatus(ErrorBadElement):
     85   @property
     86   def message(self):
     87     return _("Illegal hiatus")
     88   key = "hiatus"
     89 
     90 class ErrorBadRhyme:
     91   def __init__(self, expected, inferred, old_phon=None):
     92     self.expected = expected
     93     self.inferred = inferred
     94     self.old_phon = old_phon
     95 
     96   def report(self, pattern):
     97     return (_("%s for type %s (expected %s, inferred %s)")
     98         % (self.kind, self.get_id(pattern), self.fmt(self.expected),
     99           self.fmt(self.inferred)))
    100 
    101 class ErrorBadRhymeGenre(ErrorBadRhyme):
    102   @property
    103   def kind(self):
    104     return _("Bad rhyme genre")
    105 
    106   def fmt(self, l):
    107     result = _(' or ').join(list(l))
    108     if result == '':
    109       result = "?"
    110     return "\"" + result + "\""
    111 
    112   def get_id(self, pattern):
    113     return pattern.femid
    114 
    115 class ErrorBadRhymeObject(ErrorBadRhyme):
    116   def get_id(self, pattern):
    117     return pattern.myid
    118 
    119 class ErrorBadRhymeSound(ErrorBadRhymeObject):
    120   @property
    121   def kind(self):
    122     return _("Bad rhyme sound")
    123 
    124   def fmt(self, l):
    125     return '/'.join("\"" + common.to_xsampa(x) + "\"" for x in
    126       l.sufficient_phon())
    127 
    128 class ErrorBadRhymeEye(ErrorBadRhymeObject):
    129   @property
    130   def kind(self):
    131     return _("Bad rhyme ending")
    132 
    133   def fmt(self, l):
    134     return "\"-" + l.sufficient_eye(self.old_phon) + "\""
    135 
    136 class ErrorBadMetric:
    137   def report(self, pattern):
    138     return (_("Illegal metric: expected %d syllable%s%s") %
    139         (pattern.length, '' if pattern.length == 1 else 's',
    140           '' if len(pattern.hemistiches) == 0
    141             else (_(" with hemistiche%s at ") %
    142             '' if len(pattern.hemistiches) == 1 else 's')
    143             + ','.join(str(a) for a in pattern.hemistiches)))
    144 
    145 class ErrorMultipleWordOccurrence:
    146   def __init__(self, word, occurrences):
    147     self.word = word
    148     self.occurrences = occurrences
    149 
    150   def report(self, pattern):
    151     return (_("Too many occurrences of word \"%s\" for rhyme %s")
    152         % (self.word, pattern.myid))
    153 
    154 class ErrorIncompleteTemplate:
    155   def report(self, pattern):
    156     return _("Poem is not complete")
    157 
    158 class ErrorOverflowedTemplate:
    159   def report(self, pattern):
    160     return _("Verse is beyond end of poem")
    161 
    162 class TemplateLoadError(BaseException):
    163   def __init__(self, msg):
    164     self.msg = msg
    165