Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
range.py181 linesDownload Raw Back to datastructures
1from __future__ import annotations2 3 4class IfRange:5    """Very simple object that represents the `If-Range` header in parsed6    form.  It will either have neither a etag or date or one of either but7    never both.8 9    .. versionadded:: 0.710    """11 12    def __init__(self, etag=None, date=None):13        #: The etag parsed and unquoted.  Ranges always operate on strong14        #: etags so the weakness information is not necessary.15        self.etag = etag16        #: The date in parsed format or `None`.17        self.date = date18 19    def to_header(self):20        """Converts the object back into an HTTP header."""21        if self.date is not None:22            return http.http_date(self.date)23        if self.etag is not None:24            return http.quote_etag(self.etag)25        return ""26 27    def __str__(self):28        return self.to_header()29 30    def __repr__(self):31        return f"<{type(self).__name__} {str(self)!r}>"32 33 34class Range:35    """Represents a ``Range`` header. All methods only support only36    bytes as the unit. Stores a list of ranges if given, but the methods37    only work if only one range is provided.38 39    :raise ValueError: If the ranges provided are invalid.40 41    .. versionchanged:: 0.1542        The ranges passed in are validated.43 44    .. versionadded:: 0.745    """46 47    def __init__(self, units, ranges):48        #: The units of this range.  Usually "bytes".49        self.units = units50        #: A list of ``(begin, end)`` tuples for the range header provided.51        #: The ranges are non-inclusive.52        self.ranges = ranges53 54        for start, end in ranges:55            if start is None or (end is not None and (start < 0 or start >= end)):56                raise ValueError(f"{(start, end)} is not a valid range.")57 58    def range_for_length(self, length):59        """If the range is for bytes, the length is not None and there is60        exactly one range and it is satisfiable it returns a ``(start, stop)``61        tuple, otherwise `None`.62        """63        if self.units != "bytes" or length is None or len(self.ranges) != 1:64            return None65        start, end = self.ranges[0]66        if end is None:67            end = length68            if start < 0:69                start += length70        if http.is_byte_range_valid(start, end, length):71            return start, min(end, length)72        return None73 74    def make_content_range(self, length):75        """Creates a :class:`~werkzeug.datastructures.ContentRange` object76        from the current range and given content length.77        """78        rng = self.range_for_length(length)79        if rng is not None:80            return ContentRange(self.units, rng[0], rng[1], length)81        return None82 83    def to_header(self):84        """Converts the object back into an HTTP header."""85        ranges = []86        for begin, end in self.ranges:87            if end is None:88                ranges.append(f"{begin}-" if begin >= 0 else str(begin))89            else:90                ranges.append(f"{begin}-{end - 1}")91        return f"{self.units}={','.join(ranges)}"92 93    def to_content_range_header(self, length):94        """Converts the object into `Content-Range` HTTP header,95        based on given length96        """97        range = self.range_for_length(length)98        if range is not None:99            return f"{self.units} {range[0]}-{range[1] - 1}/{length}"100        return None101 102    def __str__(self):103        return self.to_header()104 105    def __repr__(self):106        return f"<{type(self).__name__} {str(self)!r}>"107 108 109def _callback_property(name):110    def fget(self):111        return getattr(self, name)112 113    def fset(self, value):114        setattr(self, name, value)115        if self.on_update is not None:116            self.on_update(self)117 118    return property(fget, fset)119 120 121class ContentRange:122    """Represents the content range header.123 124    .. versionadded:: 0.7125    """126 127    def __init__(self, units, start, stop, length=None, on_update=None):128        assert http.is_byte_range_valid(start, stop, length), "Bad range provided"129        self.on_update = on_update130        self.set(start, stop, length, units)131 132    #: The units to use, usually "bytes"133    units = _callback_property("_units")134    #: The start point of the range or `None`.135    start = _callback_property("_start")136    #: The stop point of the range (non-inclusive) or `None`.  Can only be137    #: `None` if also start is `None`.138    stop = _callback_property("_stop")139    #: The length of the range or `None`.140    length = _callback_property("_length")141 142    def set(self, start, stop, length=None, units="bytes"):143        """Simple method to update the ranges."""144        assert http.is_byte_range_valid(start, stop, length), "Bad range provided"145        self._units = units146        self._start = start147        self._stop = stop148        self._length = length149        if self.on_update is not None:150            self.on_update(self)151 152    def unset(self):153        """Sets the units to `None` which indicates that the header should154        no longer be used.155        """156        self.set(None, None, units=None)157 158    def to_header(self):159        if self.units is None:160            return ""161        if self.length is None:162            length = "*"163        else:164            length = self.length165        if self.start is None:166            return f"{self.units} */{length}"167        return f"{self.units} {self.start}-{self.stop - 1}/{length}"168 169    def __bool__(self):170        return self.units is not None171 172    def __str__(self):173        return self.to_header()174 175    def __repr__(self):176        return f"<{type(self).__name__} {str(self)!r}>"177 178 179# circular dependencies180from .. import http181 
codekingpro/portable-devtools · Team Ai