feat: Android-pyApi v1.0 - 全面翻译 Android SDK API 为 Python
52 个模块覆盖 Android + Java + org.json 标准库
This commit is contained in:
commit
bfe27fdc08
104 files changed
+58750
No files matched your search
@@ -0,0 +1,697 @@
|
||||
"""
|
||||
Java zip standard library APIs implemented in Python.
|
||||
java.util.zip package - ZipFile, ZipEntry, GZIP, CRC, Deflater, Inflater.
|
||||
"""
|
||||
|
||||
from .._core import Stub
|
||||
from .io import IOException, Closeable, Flushable
|
||||
import zipfile as _zipfile
|
||||
import gzip as _gzip
|
||||
import zlib as _zlib
|
||||
import io as _pyio
|
||||
import os as _os
|
||||
from datetime import datetime as _datetime
|
||||
|
||||
__all__ = [
|
||||
"ZipFile", "ZipEntry", "ZipOutputStream", "ZipInputStream",
|
||||
"GZIPInputStream", "GZIPOutputStream",
|
||||
"CRC32", "CheckedInputStream", "CheckedOutputStream",
|
||||
"Adler32",
|
||||
"DataFormatException", "ZipException",
|
||||
"Deflater", "Inflater",
|
||||
"DeflaterOutputStream", "InflaterInputStream",
|
||||
]
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Exception classes
|
||||
# ============================================================
|
||||
|
||||
class ZipException(IOException):
|
||||
pass
|
||||
|
||||
class DataFormatException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
# ============================================================
|
||||
# CRC32
|
||||
# ============================================================
|
||||
|
||||
class CRC32(Stub):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._value = 0
|
||||
|
||||
def getValue(self):
|
||||
return self._value
|
||||
|
||||
def reset(self):
|
||||
self._value = 0
|
||||
|
||||
def update(self, b, off=None, length=None):
|
||||
if isinstance(b, int):
|
||||
self._value = _zlib.crc32(bytes([b & 0xFF]), self._value) & 0xFFFFFFFF
|
||||
elif isinstance(b, (bytes, bytearray)):
|
||||
if off is not None and length is not None:
|
||||
self._value = _zlib.crc32(bytes(b[off:off+length]), self._value) & 0xFFFFFFFF
|
||||
else:
|
||||
self._value = _zlib.crc32(bytes(b), self._value) & 0xFFFFFFFF
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Adler32
|
||||
# ============================================================
|
||||
|
||||
class Adler32(Stub):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._value = 1
|
||||
|
||||
def getValue(self):
|
||||
return self._value
|
||||
|
||||
def reset(self):
|
||||
self._value = 1
|
||||
|
||||
def update(self, b, off=None, length=None):
|
||||
if isinstance(b, int):
|
||||
self._value = _zlib.adler32(bytes([b & 0xFF]), self._value) & 0xFFFFFFFF
|
||||
elif isinstance(b, (bytes, bytearray)):
|
||||
if off is not None and length is not None:
|
||||
self._value = _zlib.adler32(bytes(b[off:off+length]), self._value) & 0xFFFFFFFF
|
||||
else:
|
||||
self._value = _zlib.adler32(bytes(b), self._value) & 0xFFFFFFFF
|
||||
|
||||
|
||||
# ============================================================
|
||||
# CheckedInputStream / CheckedOutputStream
|
||||
# ============================================================
|
||||
|
||||
class CheckedInputStream(Closeable):
|
||||
def __init__(self, inp, cksum):
|
||||
super().__init__()
|
||||
self._in = inp
|
||||
self._cksum = cksum
|
||||
|
||||
def read(self, b=None, off=None, length=None):
|
||||
if b is None:
|
||||
result = self._in.read()
|
||||
if result >= 0:
|
||||
self._cksum.update(result)
|
||||
return result
|
||||
if off is None:
|
||||
off = 0
|
||||
if length is None:
|
||||
length = len(b)
|
||||
result = self._in.read(b, off, length)
|
||||
if result > 0:
|
||||
self._cksum.update(b[off:off+result])
|
||||
return result
|
||||
|
||||
def getChecksum(self):
|
||||
return self._cksum
|
||||
|
||||
def close(self):
|
||||
self._in.close()
|
||||
|
||||
def skip(self, n):
|
||||
return self._in.skip(n)
|
||||
|
||||
|
||||
class CheckedOutputStream(Closeable, Flushable):
|
||||
def __init__(self, out, cksum):
|
||||
super().__init__()
|
||||
self._out = out
|
||||
self._cksum = cksum
|
||||
|
||||
def write(self, b, off=None, length=None):
|
||||
if isinstance(b, int):
|
||||
self._out.write(b)
|
||||
self._cksum.update(b)
|
||||
else:
|
||||
if off is not None and length is not None:
|
||||
data = bytes(b[off:off+length])
|
||||
else:
|
||||
data = bytes(b)
|
||||
self._out.write(data)
|
||||
self._cksum.update(data)
|
||||
|
||||
def getChecksum(self):
|
||||
return self._cksum
|
||||
|
||||
def flush(self):
|
||||
self._out.flush()
|
||||
|
||||
def close(self):
|
||||
self._out.close()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ZipEntry
|
||||
# ============================================================
|
||||
|
||||
class ZipEntry(Stub):
|
||||
STORED = 0
|
||||
DEFLATED = 8
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__()
|
||||
self._name = name
|
||||
self._method = ZipEntry.DEFLATED
|
||||
self._size = 0
|
||||
self._compressed_size = 0
|
||||
self._crc = 0
|
||||
self._comment = ""
|
||||
self._time = 0
|
||||
self._extra = b""
|
||||
self._is_directory = name.endswith("/")
|
||||
|
||||
def getName(self):
|
||||
return self._name
|
||||
|
||||
def getMethod(self):
|
||||
return self._method
|
||||
|
||||
def setMethod(self, method):
|
||||
self._method = method
|
||||
|
||||
def getSize(self):
|
||||
return self._size
|
||||
|
||||
def setSize(self, size):
|
||||
self._size = size
|
||||
|
||||
def getCompressedSize(self):
|
||||
return self._compressed_size
|
||||
|
||||
def setCompressedSize(self, size):
|
||||
self._compressed_size = size
|
||||
|
||||
def getCrc(self):
|
||||
return self._crc
|
||||
|
||||
def setCrc(self, crc):
|
||||
self._crc = crc
|
||||
|
||||
def getComment(self):
|
||||
return self._comment
|
||||
|
||||
def setComment(self, comment):
|
||||
self._comment = comment
|
||||
|
||||
def getTime(self):
|
||||
return self._time
|
||||
|
||||
def setTime(self, time):
|
||||
self._time = time
|
||||
|
||||
def getExtra(self):
|
||||
return self._extra
|
||||
|
||||
def setExtra(self, extra):
|
||||
self._extra = extra
|
||||
|
||||
def isDirectory(self):
|
||||
return self._is_directory
|
||||
|
||||
def toString(self):
|
||||
return self._name
|
||||
|
||||
def __str__(self):
|
||||
return self._name
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ZipFile
|
||||
# ============================================================
|
||||
|
||||
class ZipFile(Closeable):
|
||||
OPEN_READ = 1
|
||||
OPEN_DELETE = 2
|
||||
|
||||
def __init__(self, file, mode="r"):
|
||||
super().__init__()
|
||||
if isinstance(file, str):
|
||||
path = file
|
||||
else:
|
||||
path = file.getPath()
|
||||
self._path = path
|
||||
self._mode = mode
|
||||
try:
|
||||
self._zfile = _zipfile.ZipFile(path, mode)
|
||||
except Exception as e:
|
||||
raise ZipException(str(e))
|
||||
|
||||
def entries(self):
|
||||
return iter(self._zfile.infolist())
|
||||
|
||||
def getEntry(self, name):
|
||||
try:
|
||||
info = self._zfile.getinfo(name)
|
||||
entry = ZipEntry(info.filename)
|
||||
entry.setMethod(info.compress_type)
|
||||
entry.setSize(info.file_size)
|
||||
entry.setCompressedSize(info.compress_size)
|
||||
entry.setCrc(info.CRC)
|
||||
entry.setTime(int(_datetime(*info.date_time).timestamp() * 1000) if info.date_time else 0)
|
||||
return entry
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def getInputStream(self, entry):
|
||||
try:
|
||||
data = self._zfile.read(entry.getName() if isinstance(entry, ZipEntry) else entry)
|
||||
from ..io import ByteArrayInputStream
|
||||
return ByteArrayInputStream(data)
|
||||
except Exception as e:
|
||||
raise ZipException(str(e))
|
||||
|
||||
def close(self):
|
||||
self._zfile.close()
|
||||
|
||||
def size(self):
|
||||
return len(self._zfile.namelist())
|
||||
|
||||
def getName(self):
|
||||
return self._path
|
||||
|
||||
def getComment(self):
|
||||
return ""
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ZipOutputStream
|
||||
# ============================================================
|
||||
|
||||
class ZipOutputStream(Closeable, Flushable):
|
||||
STORED = 0
|
||||
DEFLATED = 8
|
||||
|
||||
def __init__(self, out):
|
||||
super().__init__()
|
||||
self._out = out
|
||||
self._zfile = _zipfile.ZipFile(out, "w", _zipfile.ZIP_DEFLATED)
|
||||
self._method = ZipOutputStream.DEFLATED
|
||||
self._level = -1
|
||||
self._comment = ""
|
||||
|
||||
def putNextEntry(self, entry):
|
||||
zi = _zipfile.ZipInfo(entry.getName() if isinstance(entry, ZipEntry) else str(entry))
|
||||
if hasattr(entry, 'getTime') and entry.getTime():
|
||||
dt = _datetime.fromtimestamp(entry.getTime() / 1000.0)
|
||||
zi.date_time = dt.timetuple()[:6]
|
||||
self._zfile.writestr(zi, b"")
|
||||
|
||||
def closeEntry(self):
|
||||
pass
|
||||
|
||||
def write(self, b, off=None, length=None):
|
||||
if off is not None and length is not None:
|
||||
self._zfile._zout.write(bytes(b[off:off+length]))
|
||||
else:
|
||||
self._zfile._zout.write(bytes(b) if not isinstance(b, (bytes, bytearray)) else b)
|
||||
|
||||
def finish(self):
|
||||
self._zfile.close()
|
||||
|
||||
def close(self):
|
||||
self._zfile.close()
|
||||
|
||||
def setMethod(self, method):
|
||||
self._method = method
|
||||
|
||||
def setLevel(self, level):
|
||||
self._level = level
|
||||
|
||||
def setComment(self, comment):
|
||||
self._comment = comment
|
||||
|
||||
def flush(self):
|
||||
self._zfile._zout.flush() if hasattr(self._zfile._zout, 'flush') else None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ZipInputStream
|
||||
# ============================================================
|
||||
|
||||
class ZipInputStream(Closeable):
|
||||
def __init__(self, inp):
|
||||
super().__init__()
|
||||
self._inp = inp
|
||||
self._zfile = _zipfile.ZipFile(inp)
|
||||
self._entries = iter(self._zfile.infolist())
|
||||
self._current_entry = None
|
||||
self._current_data = b""
|
||||
self._current_pos = 0
|
||||
|
||||
def getNextEntry(self):
|
||||
try:
|
||||
info = next(self._entries)
|
||||
entry = ZipEntry(info.filename)
|
||||
entry.setMethod(info.compress_type)
|
||||
entry.setSize(info.file_size)
|
||||
entry.setCompressedSize(info.compress_size)
|
||||
entry.setCrc(info.CRC)
|
||||
self._current_entry = info
|
||||
self._current_data = self._zfile.read(info)
|
||||
self._current_pos = 0
|
||||
return entry
|
||||
except StopIteration:
|
||||
self._current_entry = None
|
||||
self._current_data = b""
|
||||
return None
|
||||
|
||||
def read(self, b=None, off=None, length=None):
|
||||
if self._current_entry is None:
|
||||
return -1
|
||||
avail = len(self._current_data) - self._current_pos
|
||||
if avail <= 0:
|
||||
return -1
|
||||
if b is None:
|
||||
val = self._current_data[self._current_pos]
|
||||
self._current_pos += 1
|
||||
return val
|
||||
if off is None:
|
||||
off = 0
|
||||
if length is None:
|
||||
length = len(b)
|
||||
n = min(length, avail)
|
||||
if isinstance(b, bytearray):
|
||||
b[off:off+n] = self._current_data[self._current_pos:self._current_pos+n]
|
||||
self._current_pos += n
|
||||
return n
|
||||
|
||||
def closeEntry(self):
|
||||
self._current_entry = None
|
||||
self._current_data = b""
|
||||
|
||||
def available(self):
|
||||
if self._current_entry is None:
|
||||
return 0
|
||||
return len(self._current_data) - self._current_pos
|
||||
|
||||
def close(self):
|
||||
self._zfile.close()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# GZIPInputStream
|
||||
# ============================================================
|
||||
|
||||
class GZIPInputStream(Closeable):
|
||||
def __init__(self, inp, size=512):
|
||||
super().__init__()
|
||||
self._inp = inp
|
||||
self._gzip_file = _gzip.GzipFile(fileobj=_pyio.BufferedReader(inp) if hasattr(inp, 'read') else inp)
|
||||
|
||||
def read(self, b=None, off=None, length=None):
|
||||
if b is None:
|
||||
data = self._gzip_file.read(1)
|
||||
return data[0] if data else -1
|
||||
if off is None:
|
||||
off = 0
|
||||
if length is None:
|
||||
length = len(b)
|
||||
data = self._gzip_file.read(length)
|
||||
if not data:
|
||||
return -1
|
||||
n = len(data)
|
||||
if isinstance(b, bytearray):
|
||||
b[off:off+n] = data
|
||||
else:
|
||||
ba = bytearray(b)
|
||||
ba[off:off+n] = data
|
||||
b[:] = bytes(ba)
|
||||
return n
|
||||
|
||||
def close(self):
|
||||
self._gzip_file.close()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# GZIPOutputStream
|
||||
# ============================================================
|
||||
|
||||
class GZIPOutputStream(Closeable, Flushable):
|
||||
def __init__(self, out, size=512):
|
||||
super().__init__()
|
||||
self._out = out
|
||||
self._gzip_file = _gzip.GzipFile(fileobj=out, mode="wb")
|
||||
|
||||
def write(self, b, off=None, length=None):
|
||||
if isinstance(b, int):
|
||||
self._gzip_file.write(bytes([b & 0xFF]))
|
||||
elif isinstance(b, (bytes, bytearray)):
|
||||
if off is not None and length is not None:
|
||||
self._gzip_file.write(bytes(b[off:off+length]))
|
||||
else:
|
||||
self._gzip_file.write(bytes(b))
|
||||
|
||||
def finish(self):
|
||||
self._gzip_file.close()
|
||||
|
||||
def close(self):
|
||||
self._gzip_file.close()
|
||||
|
||||
def flush(self):
|
||||
self._gzip_file.flush()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Deflater
|
||||
# ============================================================
|
||||
|
||||
class Deflater(Stub):
|
||||
BEST_COMPRESSION = 9
|
||||
BEST_SPEED = 1
|
||||
DEFAULT_COMPRESSION = -1
|
||||
DEFAULT_STRATEGY = 0
|
||||
FILTERED = 1
|
||||
HUFFMAN_ONLY = 2
|
||||
NO_COMPRESSION = 0
|
||||
NO_FLUSH = 0
|
||||
SYNC_FLUSH = 2
|
||||
FULL_FLUSH = 3
|
||||
|
||||
def __init__(self, level=-1, nowrap=False):
|
||||
super().__init__()
|
||||
self._level = level
|
||||
self._nowrap = nowrap
|
||||
self._compress = _zlib.compressobj(level=level if level >= 0 else 6,
|
||||
method=_zlib.DEFLATED,
|
||||
wbits=-_zlib.MAX_WBITS if nowrap else _zlib.MAX_WBITS)
|
||||
self._input_buffer = b""
|
||||
self._finished = False
|
||||
|
||||
def setInput(self, data, off=0, length=-1):
|
||||
if length < 0:
|
||||
length = len(data) - off
|
||||
self._input_buffer = bytes(data[off:off+length])
|
||||
|
||||
def needsInput(self):
|
||||
return len(self._input_buffer) == 0
|
||||
|
||||
def setDictionary(self, dictionary):
|
||||
pass
|
||||
|
||||
def getTotalIn(self):
|
||||
return len(self._input_buffer)
|
||||
|
||||
def getTotalOut(self):
|
||||
return 0
|
||||
|
||||
def deflate(self, output, off=0, length=-1):
|
||||
if length < 0:
|
||||
length = len(output) - off
|
||||
data = self._compress.compress(self._input_buffer)
|
||||
self._input_buffer = b""
|
||||
n = min(len(data), length)
|
||||
if isinstance(output, bytearray):
|
||||
output[off:off+n] = data[:n]
|
||||
else:
|
||||
ba = bytearray(output)
|
||||
ba[off:off+n] = data[:n]
|
||||
output[:] = bytes(ba)
|
||||
return n
|
||||
|
||||
def finish(self):
|
||||
self._finished = True
|
||||
|
||||
def finished(self):
|
||||
return self._finished
|
||||
|
||||
def end(self):
|
||||
pass
|
||||
|
||||
def getAdler(self):
|
||||
return 1
|
||||
|
||||
def reset(self):
|
||||
self._compress = _zlib.compressobj(level=self._level if self._level >= 0 else 6,
|
||||
method=_zlib.DEFLATED,
|
||||
wbits=-_zlib.MAX_WBITS if self._nowrap else _zlib.MAX_WBITS)
|
||||
self._input_buffer = b""
|
||||
self._finished = False
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Inflater
|
||||
# ============================================================
|
||||
|
||||
class Inflater(Stub):
|
||||
def __init__(self, nowrap=False):
|
||||
super().__init__()
|
||||
self._nowrap = nowrap
|
||||
wbits = -_zlib.MAX_WBITS if nowrap else _zlib.MAX_WBITS
|
||||
self._decompress = _zlib.decompressobj(wbits)
|
||||
self._input_buffer = b""
|
||||
self._finished = False
|
||||
|
||||
def setInput(self, data, off=0, length=-1):
|
||||
if length < 0:
|
||||
length = len(data) - off
|
||||
self._input_buffer = bytes(data[off:off+length])
|
||||
|
||||
def needsInput(self):
|
||||
return len(self._input_buffer) == 0
|
||||
|
||||
def setDictionary(self, dictionary):
|
||||
pass
|
||||
|
||||
def getTotalIn(self):
|
||||
return len(self._input_buffer)
|
||||
|
||||
def getTotalOut(self):
|
||||
return 0
|
||||
|
||||
def inflate(self, output, off=0, length=-1):
|
||||
if length < 0:
|
||||
length = len(output) - off
|
||||
try:
|
||||
data = self._decompress.decompress(self._input_buffer)
|
||||
self._input_buffer = b""
|
||||
n = min(len(data), length)
|
||||
if isinstance(output, bytearray):
|
||||
output[off:off+n] = data[:n]
|
||||
else:
|
||||
ba = bytearray(output)
|
||||
ba[off:off+n] = data[:n]
|
||||
output[:] = bytes(ba)
|
||||
return n
|
||||
except _zlib.error as e:
|
||||
raise DataFormatException(str(e))
|
||||
|
||||
def finished(self):
|
||||
return self._finished
|
||||
|
||||
def end(self):
|
||||
pass
|
||||
|
||||
def getAdler(self):
|
||||
return 1
|
||||
|
||||
def needsDictionary(self):
|
||||
return False
|
||||
|
||||
def reset(self):
|
||||
wbits = -_zlib.MAX_WBITS if self._nowrap else _zlib.MAX_WBITS
|
||||
self._decompress = _zlib.decompressobj(wbits)
|
||||
self._input_buffer = b""
|
||||
self._finished = False
|
||||
|
||||
|
||||
# ============================================================
|
||||
# DeflaterOutputStream
|
||||
# ============================================================
|
||||
|
||||
class DeflaterOutputStream(Closeable, Flushable):
|
||||
def __init__(self, out, deflater=None, size=512):
|
||||
super().__init__()
|
||||
self._out = out
|
||||
self._deflater = deflater or Deflater()
|
||||
self._buffer = bytearray(size)
|
||||
|
||||
def write(self, b, off=None, length=None):
|
||||
if isinstance(b, int):
|
||||
self._out.write(bytes([b & 0xFF]))
|
||||
else:
|
||||
if off is not None and length is not None:
|
||||
self._out.write(bytes(b[off:off+length]))
|
||||
else:
|
||||
self._deflater.setInput(bytes(b) if isinstance(b, (bytes, bytearray)) else bytes(b))
|
||||
while not self._deflater.needsInput():
|
||||
n = self._deflater.deflate(self._buffer)
|
||||
if n > 0:
|
||||
self._out.write(bytes(self._buffer[:n]))
|
||||
|
||||
def finish(self):
|
||||
self._deflater.finish()
|
||||
while not self._deflater.finished():
|
||||
n = self._deflater.deflate(self._buffer)
|
||||
if n > 0:
|
||||
self._out.write(bytes(self._buffer[:n]))
|
||||
|
||||
def close(self):
|
||||
self.finish()
|
||||
self._deflater.end()
|
||||
self._out.close()
|
||||
|
||||
def flush(self):
|
||||
self._out.flush()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# InflaterInputStream
|
||||
# ============================================================
|
||||
|
||||
class InflaterInputStream(Closeable):
|
||||
def __init__(self, inp, inflater=None, size=512):
|
||||
super().__init__()
|
||||
self._in = inp
|
||||
self._inflater = inflater or Inflater()
|
||||
self._buffer = bytearray(size)
|
||||
|
||||
def read(self, b=None, off=None, length=None):
|
||||
if b is None:
|
||||
buf = bytearray(1)
|
||||
n = self._read_from_inflater(buf, 0, 1)
|
||||
return buf[0] if n > 0 else -1
|
||||
if off is None:
|
||||
off = 0
|
||||
if length is None:
|
||||
length = len(b)
|
||||
return self._read_from_inflater(b, off, length)
|
||||
|
||||
def _read_from_inflater(self, b, off, length):
|
||||
while not self._inflater.finished():
|
||||
if self._inflater.needsInput():
|
||||
data = self._in.read(self._buffer)
|
||||
if data is None or data == -1 or data == 0:
|
||||
break
|
||||
if isinstance(data, int):
|
||||
break
|
||||
self._inflater.setInput(data)
|
||||
try:
|
||||
n = self._inflater.inflate(b, off, length)
|
||||
if n > 0:
|
||||
return n
|
||||
except DataFormatException:
|
||||
break
|
||||
return -1
|
||||
|
||||
def available(self):
|
||||
return 0
|
||||
|
||||
def close(self):
|
||||
self._inflater.end()
|
||||
self._in.close()
|
||||
|
||||
def mark(self, readlimit):
|
||||
pass
|
||||
|
||||
def reset(self):
|
||||
raise IOException("mark/reset not supported")
|
||||
|
||||
def markSupported(self):
|
||||
return False
|
||||
Reference in new issue
Block a user