|
| 1 | +:mod:`deflate` -- deflate compression & decompression |
| 2 | +===================================================== |
| 3 | + |
| 4 | +.. module:: deflate |
| 5 | + :synopsis: deflate compression & decompression |
| 6 | + |
| 7 | +This module allows compression and decompression of binary data with the |
| 8 | +`DEFLATE algorithm <https://en.wikipedia.org/wiki/DEFLATE>`_ |
| 9 | +(commonly used in the zlib library and gzip archiver). |
| 10 | + |
| 11 | +**Availability:** |
| 12 | + |
| 13 | +* Added in MicroPython v1.21. |
| 14 | + |
| 15 | +* Decompression: Enabled via the ``MICROPY_PY_DEFLATE`` build option, on by default |
| 16 | + on ports with the "extra features" level or higher (which is most boards). |
| 17 | + |
| 18 | +* Compression: Enabled via the ``MICROPY_PY_DEFLATE_COMPRESS`` build option, on |
| 19 | + by default on ports with the "full features" level or higher (generally this means |
| 20 | + you need to build your own firmware to enable this). |
| 21 | + |
| 22 | +Classes |
| 23 | +------- |
| 24 | + |
| 25 | +.. class:: DeflateIO(stream, format=AUTO, wbits=0, close=False, /) |
| 26 | + |
| 27 | + This class can be used to wrap a *stream* which is any |
| 28 | + :term:`stream-like <stream>` object such as a file, socket, or stream |
| 29 | + (including :class:`io.BytesIO`). It is itself a stream and implements the |
| 30 | + standard read/readinto/write/close methods. |
| 31 | + |
| 32 | + The *stream* must be a blocking stream. Non-blocking streams are currently |
| 33 | + not supported. |
| 34 | + |
| 35 | + The *format* can be set to any of the constants defined below, and defaults |
| 36 | + to ``AUTO`` which for decompressing will auto-detect gzip or zlib streams, |
| 37 | + and for compressing it will generate a raw stream. |
| 38 | + |
| 39 | + The *wbits* parameter sets the base-2 logarithm of the DEFLATE dictionary |
| 40 | + window size. So for example, setting *wbits* to ``10`` sets the window size |
| 41 | + to 1024 bytes. Valid values are ``5`` to ``15`` inclusive (corresponding to |
| 42 | + window sizes of 32 to 32k bytes). |
| 43 | + |
| 44 | + If *wbits* is set to ``0`` (the default), then a window size of 256 bytes |
| 45 | + will be used (corresponding to *wbits* set to ``8``), except when |
| 46 | + :ref:`decompressing a zlib stream <deflate_wbits_zlib>`. |
| 47 | + |
| 48 | + See the :ref:`window size <deflate_wbits>` notes below for more information |
| 49 | + about the window size, zlib, and gzip streams. |
| 50 | + |
| 51 | + If *close* is set to ``True`` then the underlying stream will be closed |
| 52 | + automatically when the :class:`deflate.DeflateIO` stream is closed. This is |
| 53 | + useful if you want to return a :class:`deflate.DeflateIO` stream that wraps |
| 54 | + another stream and not have the caller need to know about managing the |
| 55 | + underlying stream. |
| 56 | + |
| 57 | + If compression is enabled, a given :class:`deflate.DeflateIO` instance |
| 58 | + supports both reading and writing. For example, a bidirectional stream like |
| 59 | + a socket can be wrapped, which allows for compression/decompression in both |
| 60 | + directions. |
| 61 | + |
| 62 | +Constants |
| 63 | +--------- |
| 64 | + |
| 65 | +.. data:: deflate.AUTO |
| 66 | + deflate.RAW |
| 67 | + deflate.ZLIB |
| 68 | + deflate.GZIP |
| 69 | + |
| 70 | + Supported values for the *format* parameter. |
| 71 | + |
| 72 | +Examples |
| 73 | +-------- |
| 74 | + |
| 75 | +A typical use case for :class:`deflate.DeflateIO` is to read or write a compressed |
| 76 | +file from storage: |
| 77 | + |
| 78 | +.. code:: python |
| 79 | +
|
| 80 | + import deflate |
| 81 | +
|
| 82 | + # Writing a zlib-compressed stream (uses the default window size of 256 bytes). |
| 83 | + with open("data.gz", "wb") as f: |
| 84 | + with deflate.DeflateIO(f, deflate.ZLIB) as d: |
| 85 | + # Use d.write(...) etc |
| 86 | +
|
| 87 | + # Reading a zlib-compressed stream (auto-detect window size). |
| 88 | + with open("data.z", "rb") as f: |
| 89 | + with deflate.DeflateIO(f, deflate.ZLIB) as d: |
| 90 | + # Use d.read(), d.readinto(), etc. |
| 91 | +
|
| 92 | +Because :class:`deflate.DeflateIO` is a stream, it can be used for example |
| 93 | +with :meth:`json.dump` and :meth:`json.load` (and any other places streams can |
| 94 | +be used): |
| 95 | + |
| 96 | +.. code:: python |
| 97 | +
|
| 98 | + import deflate, json |
| 99 | +
|
| 100 | + # Write a dictionary as JSON in gzip format, with a |
| 101 | + # small (64 byte) window size. |
| 102 | + config = { ... } |
| 103 | + with open("config.gz", "wb") as f: |
| 104 | + with deflate.DeflateIO(f, deflate.GZIP, 6) as f: |
| 105 | + json.dump(config, f) |
| 106 | +
|
| 107 | + # Read back that dictionary. |
| 108 | + with open("config.gz", "rb") as f: |
| 109 | + with deflate.DeflateIO(f, deflate.GZIP, 6) as f: |
| 110 | + config = json.load(f) |
| 111 | +
|
| 112 | +If your source data is not in a stream format, you can use :class:`io.BytesIO` |
| 113 | +to turn it into a stream suitable for use with :class:`deflate.DeflateIO`: |
| 114 | + |
| 115 | +.. code:: python |
| 116 | +
|
| 117 | + import deflate, io |
| 118 | +
|
| 119 | + # Decompress a bytes/bytearray value. |
| 120 | + compressed_data = get_data_z() |
| 121 | + with deflate.DeflateIO(io.BytesIO(compressed_data), deflate.ZLIB) as d: |
| 122 | + decompressed_data = d.read() |
| 123 | +
|
| 124 | + # Compress a bytes/bytearray value. |
| 125 | + uncompressed_data = get_data() |
| 126 | + stream = io.BytesIO() |
| 127 | + with deflate.DeflateIO(stream, deflate.ZLIB) as d: |
| 128 | + d.write(uncompressed_data) |
| 129 | + compressed_data = stream.getvalue() |
| 130 | +
|
| 131 | +.. _deflate_wbits: |
| 132 | + |
| 133 | +Deflate window size |
| 134 | +------------------- |
| 135 | + |
| 136 | +The window size limits how far back in the stream the (de)compressor can |
| 137 | +reference. Increasing the window size will improve compression, but will |
| 138 | +require more memory. |
| 139 | + |
| 140 | +However, just because a given window size is used for compression, this does not |
| 141 | +mean that the stream will require the same size window for decompression, as |
| 142 | +the stream may not reference data as far back as the window allows (for example, |
| 143 | +if the length of the input is smaller than the window size). |
| 144 | + |
| 145 | +If the decompressor uses a smaller window size than necessary for the input data |
| 146 | +stream, it will fail mid-way through decompression with :exc:`OSError`. |
| 147 | + |
| 148 | +.. _deflate_wbits_zlib: |
| 149 | + |
| 150 | +The zlib format includes a header which specifies the window size used to |
| 151 | +compress the data (which due to the above, may be larger than the size required |
| 152 | +for the decompressor). |
| 153 | + |
| 154 | +If this header value is lower than the specified *wbits* value, then the header |
| 155 | +value will be used instead in order to reduce the memory allocation size. If |
| 156 | +the *wbits* parameter is zero (the default), then the header value will only be |
| 157 | +used if it is less than the maximum value of ``15`` (which is default value |
| 158 | +used by most compressors [#f1]_). |
| 159 | + |
| 160 | +In other words, if the source zlib stream has been compressed with a custom window |
| 161 | +size (i.e. less than ``15``), then using the default *wbits* parameter of zero |
| 162 | +will decompress any such stream. |
| 163 | + |
| 164 | +The gzip file format does not include the window size in the header. |
| 165 | +Additionally, most compressor libraries (including CPython's implementation |
| 166 | +of :class:`gzip.GzipFile`) will default to the maximum possible window size. |
| 167 | +This makes it difficult to decompress most gzip streams on MicroPython unless |
| 168 | +your board has a lot of free RAM. |
| 169 | + |
| 170 | +If you control the source of the compressed data, then prefer to use the zlib |
| 171 | +format, with a window size that is suitable for your target device. |
| 172 | + |
| 173 | +.. rubric:: Footnotes |
| 174 | + |
| 175 | +.. [#f1] The assumption here is that if the header value is the default used by |
| 176 | + most compressors, then nothing is known about the likely required window |
| 177 | + size and we should ignore it. |
0 commit comments