Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/brotli/python/bro.py @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 #! /usr/bin/env python | |
| 2 """Compression/decompression utility using the Brotli algorithm.""" | |
| 3 | |
| 4 # Note: Python2 has been deprecated long ago, but some projects out in | |
| 5 # the wide world may still use it nevertheless. This should not | |
| 6 # deprive them from being able to run Brotli. | |
| 7 from __future__ import print_function | |
| 8 | |
| 9 import argparse | |
| 10 import os | |
| 11 import platform | |
| 12 import sys | |
| 13 | |
| 14 import brotli | |
| 15 | |
| 16 | |
| 17 # default values of encoder parameters | |
| 18 _DEFAULT_PARAMS = { | |
| 19 'mode': brotli.MODE_GENERIC, | |
| 20 'quality': 11, | |
| 21 'lgwin': 22, | |
| 22 'lgblock': 0, | |
| 23 } | |
| 24 | |
| 25 | |
| 26 def get_binary_stdio(stream): | |
| 27 """Return the specified stdin/stdout/stderr stream. | |
| 28 | |
| 29 If the stdio stream requested (i.e. sys.(stdin|stdout|stderr)) | |
| 30 has been replaced with a stream object that does not have a `.buffer` | |
| 31 attribute, this will return the original stdio stream's buffer, i.e. | |
| 32 `sys.__(stdin|stdout|stderr)__.buffer`. | |
| 33 | |
| 34 Args: | |
| 35 stream: One of 'stdin', 'stdout', 'stderr'. | |
| 36 | |
| 37 Returns: | |
| 38 The stream, as a 'raw' buffer object (i.e. io.BufferedIOBase subclass | |
| 39 instance such as io.Bufferedreader/io.BufferedWriter), suitable for | |
| 40 reading/writing binary data from/to it. | |
| 41 """ | |
| 42 if stream == 'stdin': stdio = sys.stdin | |
| 43 elif stream == 'stdout': stdio = sys.stdout | |
| 44 elif stream == 'stderr': stdio = sys.stderr | |
| 45 else: | |
| 46 raise ValueError('invalid stream name: %s' % (stream,)) | |
| 47 if sys.version_info[0] < 3: | |
| 48 if sys.platform == 'win32': | |
| 49 # set I/O stream binary flag on python2.x (Windows) | |
| 50 runtime = platform.python_implementation() | |
| 51 if runtime == 'PyPy': | |
| 52 # the msvcrt trick doesn't work in pypy, so use fdopen(). | |
| 53 mode = 'rb' if stream == 'stdin' else 'wb' | |
| 54 stdio = os.fdopen(stdio.fileno(), mode, 0) | |
| 55 else: | |
| 56 # this works with CPython -- untested on other implementations | |
| 57 import msvcrt | |
| 58 msvcrt.setmode(stdio.fileno(), os.O_BINARY) | |
| 59 return stdio | |
| 60 else: | |
| 61 try: | |
| 62 return stdio.buffer | |
| 63 except AttributeError: | |
| 64 # The Python reference explains | |
| 65 # (-> https://docs.python.org/3/library/sys.html#sys.stdin) | |
| 66 # that the `.buffer` attribute might not exist, since | |
| 67 # the standard streams might have been replaced by something else | |
| 68 # (such as an `io.StringIO()` - perhaps via | |
| 69 # `contextlib.redirect_stdout()`). | |
| 70 # We fall back to the original stdio in these cases. | |
| 71 if stream == 'stdin': return sys.__stdin__.buffer | |
| 72 if stream == 'stdout': return sys.__stdout__.buffer | |
| 73 if stream == 'stderr': return sys.__stderr__.buffer | |
| 74 assert False, 'Impossible Situation.' | |
| 75 | |
| 76 | |
| 77 def main(args=None): | |
| 78 | |
| 79 parser = argparse.ArgumentParser( | |
| 80 prog=os.path.basename(__file__), description=__doc__) | |
| 81 parser.add_argument( | |
| 82 '--version', action='version', version=brotli.version) | |
| 83 parser.add_argument( | |
| 84 '-i', | |
| 85 '--input', | |
| 86 metavar='FILE', | |
| 87 type=str, | |
| 88 dest='infile', | |
| 89 help='Input file', | |
| 90 default=None) | |
| 91 parser.add_argument( | |
| 92 '-o', | |
| 93 '--output', | |
| 94 metavar='FILE', | |
| 95 type=str, | |
| 96 dest='outfile', | |
| 97 help='Output file', | |
| 98 default=None) | |
| 99 parser.add_argument( | |
| 100 '-f', | |
| 101 '--force', | |
| 102 action='store_true', | |
| 103 help='Overwrite existing output file', | |
| 104 default=False) | |
| 105 parser.add_argument( | |
| 106 '-d', | |
| 107 '--decompress', | |
| 108 action='store_true', | |
| 109 help='Decompress input file', | |
| 110 default=False) | |
| 111 params = parser.add_argument_group('optional encoder parameters') | |
| 112 params.add_argument( | |
| 113 '-m', | |
| 114 '--mode', | |
| 115 metavar='MODE', | |
| 116 type=int, | |
| 117 choices=[0, 1, 2], | |
| 118 help='The compression mode can be 0 for generic input, ' | |
| 119 '1 for UTF-8 encoded text, or 2 for WOFF 2.0 font data. ' | |
| 120 'Defaults to 0.') | |
| 121 params.add_argument( | |
| 122 '-q', | |
| 123 '--quality', | |
| 124 metavar='QUALITY', | |
| 125 type=int, | |
| 126 choices=list(range(0, 12)), | |
| 127 help='Controls the compression-speed vs compression-density ' | |
| 128 'tradeoff. The higher the quality, the slower the ' | |
| 129 'compression. Range is 0 to 11. Defaults to 11.') | |
| 130 params.add_argument( | |
| 131 '--lgwin', | |
| 132 metavar='LGWIN', | |
| 133 type=int, | |
| 134 choices=list(range(10, 25)), | |
| 135 help='Base 2 logarithm of the sliding window size. Range is ' | |
| 136 '10 to 24. Defaults to 22.') | |
| 137 params.add_argument( | |
| 138 '--lgblock', | |
| 139 metavar='LGBLOCK', | |
| 140 type=int, | |
| 141 choices=[0] + list(range(16, 25)), | |
| 142 help='Base 2 logarithm of the maximum input block size. ' | |
| 143 'Range is 16 to 24. If set to 0, the value will be set based ' | |
| 144 'on the quality. Defaults to 0.') | |
| 145 # set default values using global _DEFAULT_PARAMS dictionary | |
| 146 parser.set_defaults(**_DEFAULT_PARAMS) | |
| 147 | |
| 148 options = parser.parse_args(args=args) | |
| 149 | |
| 150 if options.infile: | |
| 151 try: | |
| 152 with open(options.infile, 'rb') as infile: | |
| 153 data = infile.read() | |
| 154 except OSError: | |
| 155 parser.error('Could not read --infile: %s' % (infile,)) | |
| 156 else: | |
| 157 if sys.stdin.isatty(): | |
| 158 # interactive console, just quit | |
| 159 parser.error('No input (called from interactive terminal).') | |
| 160 infile = get_binary_stdio('stdin') | |
| 161 data = infile.read() | |
| 162 | |
| 163 if options.outfile: | |
| 164 # Caution! If `options.outfile` is a broken symlink, will try to | |
| 165 # redirect the write according to symlink. | |
| 166 if os.path.exists(options.outfile) and not options.force: | |
| 167 parser.error(('Target --outfile=%s already exists, ' | |
| 168 'but --force was not requested.') % (outfile,)) | |
| 169 outfile = open(options.outfile, 'wb') | |
| 170 did_open_outfile = True | |
| 171 else: | |
| 172 outfile = get_binary_stdio('stdout') | |
| 173 did_open_outfile = False | |
| 174 try: | |
| 175 try: | |
| 176 if options.decompress: | |
| 177 data = brotli.decompress(data) | |
| 178 else: | |
| 179 data = brotli.compress( | |
| 180 data, | |
| 181 mode=options.mode, | |
| 182 quality=options.quality, | |
| 183 lgwin=options.lgwin, | |
| 184 lgblock=options.lgblock) | |
| 185 outfile.write(data) | |
| 186 finally: | |
| 187 if did_open_outfile: outfile.close() | |
| 188 except brotli.error as e: | |
| 189 parser.exit(1, | |
| 190 'bro: error: %s: %s' % (e, options.infile or '{stdin}')) | |
| 191 | |
| 192 | |
| 193 if __name__ == '__main__': | |
| 194 main() |
