~testing-cabal/ubuntu/natty/subunit/daily-build-packaging

« back to all changes in this revision

Viewing changes to python/subunit/chunked.py

  • Committer: Jelmer Vernooij
  • Date: 2011-02-28 09:32:28 UTC
  • mfrom: (135.1.5 python3)
  • Revision ID: jelmer@samba.org-20110228093228-1hyelaw7zkfe91e1
Tags: 0.0.6+bzr140-0ubuntu1
Merge new upstream snapshot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#
2
2
#  subunit: extensions to python unittest to get test results from subprocesses.
3
3
#  Copyright (C) 2005  Robert Collins <robertc@robertcollins.net>
 
4
#  Copyright (C) 2011  Martin Pool <mbp@sourcefrog.net>
4
5
#
5
6
#  Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
6
7
#  license at the users choice. A copy of both licenses are available in the
7
8
#  project source as Apache-2.0 and BSD. You may not use this file except in
8
9
#  compliance with one of these two licences.
9
 
#  
 
10
#
10
11
#  Unless required by applicable law or agreed to in writing, software
11
12
#  distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
12
13
#  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
19
20
class Decoder(object):
20
21
    """Decode chunked content to a byte stream."""
21
22
 
22
 
    def __init__(self, output):
 
23
    def __init__(self, output, strict=True):
23
24
        """Create a decoder decoding to output.
24
25
 
25
26
        :param output: A file-like object. Bytes written to the Decoder are
29
30
            when no more data is available, to detect short streams; the
30
31
            write method will return none-None when the end of a stream is
31
32
            detected.
 
33
 
 
34
        :param strict: If True (the default), the decoder will not knowingly
 
35
            accept input that is not conformant to the HTTP specification.
 
36
            (This does not imply that it will catch every nonconformance.)
 
37
            If False, it will accept incorrect input that is still
 
38
            unambiguous.
32
39
        """
33
40
        self.output = output
34
41
        self.buffered_bytes = []
35
42
        self.state = self._read_length
36
43
        self.body_length = 0
 
44
        self.strict = strict
37
45
 
38
46
    def close(self):
39
47
        """Close the decoder.
72
80
 
73
81
    def _read_length(self):
74
82
        """Try to decode a length from the bytes."""
75
 
        count = -1
76
83
        match_chars = "0123456789abcdefABCDEF\r\n"
77
84
        count_chars = []
78
85
        for bytes in self.buffered_bytes:
87
94
        if count_chars[-1][-1] != '\n':
88
95
            return
89
96
        count_str = ''.join(count_chars)
90
 
        self.body_length = int(count_str[:-2], 16)
 
97
        if self.strict:
 
98
            if count_str[-2:] != '\r\n':
 
99
                raise ValueError("chunk header invalid: %r" % count_str)
 
100
            if '\r' in count_str[:-2]:
 
101
                raise ValueError("too many CRs in chunk header %r" % count_str)
 
102
        self.body_length = int(count_str.rstrip('\n\r'), 16)
91
103
        excess_bytes = len(count_str)
92
104
        while excess_bytes:
93
105
            if excess_bytes >= len(self.buffered_bytes[0]):
107
119
 
108
120
    def write(self, bytes):
109
121
        """Decode bytes to the output stream.
110
 
        
 
122
 
111
123
        :raises ValueError: If the stream has already seen the end of file
112
124
            marker.
113
125
        :returns: None, or the excess bytes beyond the end of file marker.
133
145
 
134
146
    def flush(self, extra_len=0):
135
147
        """Flush the encoder to the output stream.
136
 
        
 
148
 
137
149
        :param extra_len: Increase the size of the chunk by this many bytes
138
150
            to allow for a subsequent write.
139
151
        """