<s> class Range ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , ranges ) : <EOL> for begin , end in ranges : <EOL> assert end is None or end >= <NUM_LIT:0> , "<STR_LIT>" % ranges <EOL> self . ranges = ranges <EOL> def satisfiable ( self , length ) : <EOL> """<STR_LIT>""" <EOL> for begin , end in self . ranges : <EOL> if end is not None and end >= length : <EOL> return False <EOL> return True <EOL> def range_for_length ( self , length ) : <EOL> """<STR_LIT>""" <EOL> if length is None or len ( self . ranges ) != <NUM_LIT:1> : <EOL> return None <EOL> start , end = self . ranges [ <NUM_LIT:0> ] <EOL> if end is None : <EOL> end = length <EOL> if start < <NUM_LIT:0> : <EOL> start += length <EOL> if _is_content_range_valid ( start , end , length ) : <EOL> stop = min ( end , length ) <EOL> return ( start , stop ) <EOL> else : <EOL> return None <EOL> def content_range ( self , length ) : <EOL> """<STR_LIT>""" <EOL> range = self . range_for_length ( length ) <EOL> if range is None : <EOL> return None <EOL> return ContentRange ( range [ <NUM_LIT:0> ] , range [ <NUM_LIT:1> ] , length ) <EOL> def __str__ ( self ) : <EOL> parts = [ ] <EOL> for begin , end in self . ranges : <EOL> if end is None : <EOL> if begin >= <NUM_LIT:0> : <EOL> parts . append ( '<STR_LIT>' % begin ) <EOL> else : <EOL> parts . append ( str ( begin ) ) <EOL> else : <EOL> if begin < <NUM_LIT:0> : <EOL> raise ValueError ( "<STR_LIT>" <EOL> % ( begin , end ) ) <EOL> if end <= <NUM_LIT:0> : <EOL> raise ValueError ( "<STR_LIT>" <EOL> % ( begin , end ) ) <EOL> parts . append ( '<STR_LIT>' % ( begin , end - <NUM_LIT:1> ) ) <EOL> return '<STR_LIT>' % '<STR_LIT:U+002C>' . join ( parts ) <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( <EOL> self . __class__ . __name__ , <EOL> '<STR_LIT:U+002CU+0020>' . join ( map ( repr , self . ranges ) ) ) <EOL> @ classmethod <EOL> def parse ( cls , header ) : <EOL> """<STR_LIT>""" <EOL> bytes = cls . parse_bytes ( header ) <EOL> if bytes is None : <EOL> return None <EOL> units , ranges = bytes <EOL> if units != '<STR_LIT>' or ranges is None : <EOL> return None <EOL> return cls ( ranges ) <EOL> @ staticmethod <EOL> def parse_bytes ( header ) : <EOL> """<STR_LIT>""" <EOL> if not header : <EOL> raise TypeError ( "<STR_LIT>" ) <EOL> ranges = [ ] <EOL> last_end = <NUM_LIT:0> <EOL> try : <EOL> ( units , range ) = header . split ( "<STR_LIT:=>" , <NUM_LIT:1> ) <EOL> units = units . strip ( ) . lower ( ) <EOL> for item in range . split ( "<STR_LIT:U+002C>" ) : <EOL> if '<STR_LIT:->' not in item : <EOL> raise ValueError ( ) <EOL> if item . startswith ( '<STR_LIT:->' ) : <EOL> if last_end < <NUM_LIT:0> : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> begin = int ( item ) <EOL> end = None <EOL> last_end = - <NUM_LIT:1> <EOL> else : <EOL> ( begin , end ) = item . split ( "<STR_LIT:->" , <NUM_LIT:1> ) <EOL> begin = int ( begin ) <EOL> if begin < last_end or last_end < <NUM_LIT:0> : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> if end . strip ( ) : <EOL> end = int ( end ) + <NUM_LIT:1> <EOL> if begin >= end : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> else : <EOL> end = None <EOL> last_end = end <EOL> ranges . append ( ( begin , end ) ) <EOL> except ValueError , e : <EOL> return None <EOL> return ( units , ranges ) <EOL> class ContentRange ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , start , stop , length ) : <EOL> if not _is_content_range_valid ( start , stop , length ) : <EOL> raise ValueError ( "<STR_LIT>" % ( start , stop , length ) ) <EOL> self . start = start <EOL> self . stop = stop <EOL> self . length = length <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . __class__ . __name__ , self ) <EOL> def __str__ ( self ) : <EOL> if self . length is None : <EOL> length = '<STR_LIT:*>' <EOL> else : <EOL> length = self . length <EOL> if self . start is None : <EOL> assert self . stop is None <EOL> return '<STR_LIT>' % length <EOL> stop = self . stop - <NUM_LIT:1> <EOL> return '<STR_LIT>' % ( self . start , stop , length ) <EOL> def __iter__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return iter ( [ self . start , self . stop , self . length ] ) <EOL> @ classmethod <EOL> def parse ( cls , value ) : <EOL> """<STR_LIT>""" <EOL> if value is None : <EOL> return None <EOL> value = value . strip ( ) <EOL> if not value . startswith ( '<STR_LIT>' ) : <EOL> return None <EOL> value = value [ len ( '<STR_LIT>' ) : ] . strip ( ) <EOL> if '<STR_LIT:/>' not in value : <EOL> return None <EOL> range , length = value . split ( '<STR_LIT:/>' , <NUM_LIT:1> ) <EOL> if length == '<STR_LIT:*>' : <EOL> length = None <EOL> elif length . isdigit ( ) : <EOL> length = int ( length ) <EOL> else : <EOL> return None <EOL> if range == '<STR_LIT:*>' : <EOL> return cls ( None , None , length ) <EOL> elif '<STR_LIT:->' not in range : <EOL> return None <EOL> else : <EOL> start , stop = range . split ( '<STR_LIT:->' , <NUM_LIT:1> ) <EOL> try : <EOL> start = int ( start ) <EOL> stop = int ( stop ) <EOL> stop += <NUM_LIT:1> <EOL> except ValueError : <EOL> return None <EOL> if _is_content_range_valid ( start , stop , length , response = True ) : <EOL> return cls ( start , stop , length ) <EOL> return None <EOL> def _is_content_range_valid ( start , stop , length , response = False ) : <EOL> if ( start is None ) != ( stop is None ) : <EOL> return False <EOL> elif start is None : <EOL> return length is None or length >= <NUM_LIT:0> <EOL> elif length is None : <EOL> return <NUM_LIT:0> <= start < stop <EOL> elif start >= stop : <EOL> return False <EOL> elif response and stop > length : <EOL> return False <EOL> else : <EOL> return <NUM_LIT:0> <= start < length </s>
