~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/rio.py

  • Committer: Aaron Bentley
  • Date: 2007-02-06 14:52:16 UTC
  • mfrom: (2266 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2268.
  • Revision ID: abentley@panoramicfeedback.com-20070206145216-fcpi8o3ufvuzwbp9
Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
44
44
 
45
45
    def write_stanza(self, stanza):
46
46
        if self._soft_nl:
47
 
            self._to_file.write('\n')
 
47
            print >>self._to_file
48
48
        stanza.write(self._to_file)
49
49
        self._soft_nl = True
50
50
 
116
116
 
117
117
    def add(self, tag, value):
118
118
        """Append a name and value to the stanza."""
119
 
        if not valid_tag(tag):
120
 
            raise ValueError("invalid tag %r" % (tag,))
 
119
        assert valid_tag(tag), \
 
120
            ("invalid tag %r" % tag)
121
121
        if isinstance(value, str):
122
122
            value = unicode(value)
123
123
        elif isinstance(value, unicode):
165
165
            return []
166
166
        result = []
167
167
        for tag, value in self.items:
 
168
            assert isinstance(tag, str), type(tag)
 
169
            assert isinstance(value, unicode)
168
170
            if value == '':
169
171
                result.append(tag + ': \n')
170
172
            elif '\n' in value:
233
235
        """
234
236
        d = {}
235
237
        for tag, value in self.items:
 
238
            assert tag not in d
236
239
            d[tag] = value
237
240
        return d
238
241
         
288
291
            break       # end of file
289
292
        if line == '\n':
290
293
            break       # end of stanza
 
294
        assert line.endswith('\n')
291
295
        real_l = line
292
296
        if line[0] == '\t': # continues previous value
293
297
            if tag is None:
302
306
                raise ValueError('tag/value separator not found in line %r'
303
307
                                 % real_l)
304
308
            tag = str(line[:colon_index])
305
 
            if not valid_tag(tag):
306
 
                raise ValueError("invalid rio tag %r" % (tag,))
 
309
            assert valid_tag(tag), \
 
310
                    "invalid rio tag %r" % tag
307
311
            accum_value = line[colon_index+2:-1]
308
312
 
309
313
    if tag is not None: # add last tag-value
311
315
        return stanza
312
316
    else:     # didn't see any content
313
317
        return None    
314
 
 
315
 
 
316
 
def to_patch_lines(stanza, max_width=72):
317
 
    """Convert a stanza into RIO-Patch format lines.
318
 
 
319
 
    RIO-Patch is a RIO variant designed to be e-mailed as part of a patch.
320
 
    It resists common forms of damage such as newline conversion or the removal
321
 
    of trailing whitespace, yet is also reasonably easy to read.
322
 
 
323
 
    :param max_width: The maximum number of characters per physical line.
324
 
    :return: a list of lines
325
 
    """
326
 
    if max_width <= 6:
327
 
        raise ValueError(max_width)
328
 
    max_rio_width = max_width - 4
329
 
    lines = []
330
 
    for pline in stanza.to_lines():
331
 
        for line in pline.split('\n')[:-1]:
332
 
            line = re.sub('\\\\', '\\\\\\\\', line)
333
 
            while len(line) > 0:
334
 
                partline = line[:max_rio_width]
335
 
                line = line[max_rio_width:]
336
 
                if len(line) > 0 and line[0] != [' ']:
337
 
                    break_index = -1
338
 
                    break_index = partline.rfind(' ', -20)
339
 
                    if break_index < 3:
340
 
                        break_index = partline.rfind('-', -20)
341
 
                        break_index += 1
342
 
                    if break_index < 3:
343
 
                        break_index = partline.rfind('/', -20)
344
 
                    if break_index >= 3:
345
 
                        line = partline[break_index:] + line
346
 
                        partline = partline[:break_index]
347
 
                if len(line) > 0:
348
 
                    line = '  ' + line
349
 
                partline = re.sub('\r', '\\\\r', partline)
350
 
                blank_line = False
351
 
                if len(line) > 0:
352
 
                    partline += '\\'
353
 
                elif re.search(' $', partline):
354
 
                    partline += '\\'
355
 
                    blank_line = True
356
 
                lines.append('# ' + partline + '\n')
357
 
                if blank_line:
358
 
                    lines.append('#   \n')
359
 
    return lines
360
 
 
361
 
 
362
 
def _patch_stanza_iter(line_iter):
363
 
    map = {'\\\\': '\\',
364
 
           '\\r' : '\r',
365
 
           '\\\n': ''}
366
 
    def mapget(match):
367
 
        return map[match.group(0)]
368
 
 
369
 
    last_line = None
370
 
    for line in line_iter:
371
 
        if line.startswith('# '):
372
 
            line = line[2:]
373
 
        elif line.startswith('#'):
374
 
            line = line[1:]
375
 
        else:
376
 
            raise ValueError("bad line %r" % (line,))
377
 
        if last_line is not None and len(line) > 2:
378
 
            line = line[2:]
379
 
        line = re.sub('\r', '', line)
380
 
        line = re.sub('\\\\(.|\n)', mapget, line)
381
 
        if last_line is None:
382
 
            last_line = line
383
 
        else:
384
 
            last_line += line
385
 
        if last_line[-1] == '\n':
386
 
            yield last_line
387
 
            last_line = None
388
 
    if last_line is not None:
389
 
        yield last_line
390
 
 
391
 
 
392
 
def read_patch_stanza(line_iter):
393
 
    """Convert an iterable of RIO-Patch format lines into a Stanza.
394
 
 
395
 
    RIO-Patch is a RIO variant designed to be e-mailed as part of a patch.
396
 
    It resists common forms of damage such as newline conversion or the removal
397
 
    of trailing whitespace, yet is also reasonably easy to read.
398
 
 
399
 
    :return: a Stanza
400
 
    """
401
 
    return read_stanza(_patch_stanza_iter(line_iter))