366 lines
14 KiB
Python
366 lines
14 KiB
Python
|
|
"""Testcases for cssutils.codec"""
|
||
|
|
|
||
|
|
import codecs
|
||
|
|
import io
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
|
||
|
|
from cssutils import codec
|
||
|
|
|
||
|
|
iostream = io.BytesIO
|
||
|
|
|
||
|
|
|
||
|
|
class Queue:
|
||
|
|
"""
|
||
|
|
queue: write bytes at one end, read bytes from the other end
|
||
|
|
"""
|
||
|
|
|
||
|
|
def __init__(self):
|
||
|
|
self._buffer = b""
|
||
|
|
|
||
|
|
def write(self, chars):
|
||
|
|
# TODO ???
|
||
|
|
if isinstance(chars, str):
|
||
|
|
chars = chars.encode()
|
||
|
|
elif isinstance(chars, int):
|
||
|
|
chars = bytes([chars])
|
||
|
|
|
||
|
|
self._buffer += chars
|
||
|
|
|
||
|
|
def read(self, size=-1):
|
||
|
|
if size < 0:
|
||
|
|
s = self._buffer
|
||
|
|
self._buffer = b""
|
||
|
|
return s
|
||
|
|
else:
|
||
|
|
s = self._buffer[:size]
|
||
|
|
self._buffer = self._buffer[size:]
|
||
|
|
return s
|
||
|
|
|
||
|
|
|
||
|
|
class TestCodec:
|
||
|
|
def test_detectencoding_str(self):
|
||
|
|
"codec.detectencoding_str()"
|
||
|
|
assert codec.detectencoding_str(b'') == (None, False)
|
||
|
|
assert codec.detectencoding_str(b'\xef') == (None, False)
|
||
|
|
assert codec.detectencoding_str('\xef\x33'.encode()) == ("utf-8", False)
|
||
|
|
assert codec.detectencoding_str('\xc3\xaf3'.encode()) == ("utf-8", False)
|
||
|
|
assert codec.detectencoding_str(b'\xef\xbb') == (None, False)
|
||
|
|
assert codec.detectencoding_str('\xef\xbb\x33'.encode()) == (
|
||
|
|
"utf-8",
|
||
|
|
False,
|
||
|
|
)
|
||
|
|
assert codec.detectencoding_str('\xef\xbb\xbf'.encode("utf-8-sig")) == (
|
||
|
|
"utf-8-sig",
|
||
|
|
True,
|
||
|
|
)
|
||
|
|
assert codec.detectencoding_str(b'\xff') == (None, False)
|
||
|
|
assert codec.detectencoding_str('\xff\x33'.encode()) == ("utf-8", False)
|
||
|
|
assert codec.detectencoding_str(b'\xff\xfe') == (None, False)
|
||
|
|
assert codec.detectencoding_str('\xff\xfe\x33'.encode("utf-16")) == (
|
||
|
|
"utf-16",
|
||
|
|
True,
|
||
|
|
)
|
||
|
|
assert codec.detectencoding_str(b'\xff\xfe\x00') == (
|
||
|
|
None,
|
||
|
|
False,
|
||
|
|
)
|
||
|
|
assert codec.detectencoding_str('\xff\xfe\x00\x33'.encode("utf-16")) == (
|
||
|
|
"utf-16",
|
||
|
|
True,
|
||
|
|
)
|
||
|
|
assert codec.detectencoding_str('\xff\xfe\x00\x00'.encode("utf-32")) == (
|
||
|
|
"utf-32",
|
||
|
|
True,
|
||
|
|
)
|
||
|
|
assert codec.detectencoding_str('\x00'.encode()) == (None, False)
|
||
|
|
assert codec.detectencoding_str('\x00\x33'.encode()) == ("utf-8", False)
|
||
|
|
assert codec.detectencoding_str('\x00\x00'.encode()) == (None, False)
|
||
|
|
assert codec.detectencoding_str('\x00\x00\x33'.encode()) == ("utf-8", False)
|
||
|
|
assert codec.detectencoding_str(b'\x00\x00\xfe') == (
|
||
|
|
None,
|
||
|
|
False,
|
||
|
|
)
|
||
|
|
assert codec.detectencoding_str('\x00\x00\x00\x33'.encode()) == ("utf-8", False)
|
||
|
|
assert codec.detectencoding_str('\x00\x00\x00@'.encode()) == (
|
||
|
|
"utf-32-be",
|
||
|
|
False,
|
||
|
|
)
|
||
|
|
assert codec.detectencoding_str('\x00\x00\xfe\xff'.encode('utf-32')) == (
|
||
|
|
"utf-32",
|
||
|
|
True,
|
||
|
|
)
|
||
|
|
assert codec.detectencoding_str(b'@') == (None, False)
|
||
|
|
assert codec.detectencoding_str('@\x33'.encode()) == ("utf-8", False)
|
||
|
|
assert codec.detectencoding_str('@\x00'.encode()) == (None, False)
|
||
|
|
assert codec.detectencoding_str('@\x00\x33'.encode()) == ("utf-8", False)
|
||
|
|
assert codec.detectencoding_str('@\x00\x00'.encode()) == (None, False)
|
||
|
|
assert codec.detectencoding_str('@\x00\x00\x33'.encode()) == ("utf-8", False)
|
||
|
|
assert codec.detectencoding_str('@\x00\x00\x00'.encode()) == (
|
||
|
|
"utf-32-le",
|
||
|
|
False,
|
||
|
|
)
|
||
|
|
assert codec.detectencoding_str(b'@c') == (None, False)
|
||
|
|
assert codec.detectencoding_str(b'@ch') == (None, False)
|
||
|
|
assert codec.detectencoding_str(b'@cha') == (None, False)
|
||
|
|
assert codec.detectencoding_str(b'@char') == (None, False)
|
||
|
|
assert codec.detectencoding_str(b'@chars') == (None, False)
|
||
|
|
assert codec.detectencoding_str(b'@charse') == (None, False)
|
||
|
|
assert codec.detectencoding_str(b'@charset') == (None, False)
|
||
|
|
assert codec.detectencoding_str(b'@charset ') == (None, False)
|
||
|
|
assert codec.detectencoding_str(b'@charset "') == (None, False)
|
||
|
|
assert codec.detectencoding_str(b'@charset "x') == (None, False)
|
||
|
|
assert codec.detectencoding_str(b'@charset ""') == ("", True)
|
||
|
|
assert codec.detectencoding_str(b'@charset "x"') == ("x", True)
|
||
|
|
assert codec.detectencoding_str(b"@", False) == (None, False)
|
||
|
|
assert codec.detectencoding_str(b"@", True) == ("utf-8", False)
|
||
|
|
assert codec.detectencoding_str(b"@c", False) == (None, False)
|
||
|
|
assert codec.detectencoding_str(b"@c", True) == ("utf-8", False)
|
||
|
|
|
||
|
|
def test_detectencoding_unicode(self):
|
||
|
|
"codec.detectencoding_unicode()"
|
||
|
|
# Unicode version (only parses the header)
|
||
|
|
assert codec.detectencoding_unicode('@charset "x') == (None, False)
|
||
|
|
assert codec.detectencoding_unicode('a {}') == ("utf-8", False)
|
||
|
|
assert codec.detectencoding_unicode('@charset "x', True) == (None, False)
|
||
|
|
assert codec.detectencoding_unicode('@charset "x"') == ("x", True)
|
||
|
|
|
||
|
|
def test_fixencoding(self):
|
||
|
|
"codec._fixencoding()"
|
||
|
|
s = '@charset "'
|
||
|
|
assert codec._fixencoding(s, "utf-8") is None
|
||
|
|
|
||
|
|
s = '@charset "x'
|
||
|
|
assert codec._fixencoding(s, "utf-8") is None
|
||
|
|
|
||
|
|
s = '@charset "x'
|
||
|
|
assert codec._fixencoding(s, "utf-8", True) == s
|
||
|
|
|
||
|
|
s = '@charset x'
|
||
|
|
assert codec._fixencoding(s, "utf-8") == s
|
||
|
|
|
||
|
|
s = '@charset "x"'
|
||
|
|
assert codec._fixencoding(s, "utf-8") == s.replace('"x"', '"utf-8"')
|
||
|
|
|
||
|
|
def test_decoder(self): # noqa: C901
|
||
|
|
"codecs.decoder"
|
||
|
|
|
||
|
|
def checkauto(encoding, input='@charset "x";g\xfcrk\u20ac{}'):
|
||
|
|
outputencoding = encoding
|
||
|
|
if outputencoding == "utf-8-sig":
|
||
|
|
outputencoding = "utf-8"
|
||
|
|
# Check stateless decoder with encoding autodetection
|
||
|
|
d = codecs.getdecoder("css")
|
||
|
|
assert d(input.encode(encoding))[0] == input.replace(
|
||
|
|
'"x"', '"%s"' % outputencoding
|
||
|
|
)
|
||
|
|
|
||
|
|
# Check stateless decoder with specified encoding
|
||
|
|
assert d(input.encode(encoding), encoding=encoding)[0] == input.replace(
|
||
|
|
'"x"', '"%s"' % outputencoding
|
||
|
|
)
|
||
|
|
|
||
|
|
if hasattr(codec, "getincrementaldecoder"):
|
||
|
|
# Check incremental decoder with encoding autodetection
|
||
|
|
id = codecs.getincrementaldecoder("css")()
|
||
|
|
assert "".join(id.iterdecode(input.encode(encoding))) == input.replace(
|
||
|
|
'"x"', '"%s"' % outputencoding
|
||
|
|
)
|
||
|
|
|
||
|
|
# Check incremental decoder with specified encoding
|
||
|
|
id = codecs.getincrementaldecoder("css")(encoding=encoding)
|
||
|
|
assert "".join(id.iterdecode(input.encode(encoding))) == input.replace(
|
||
|
|
'"x"', '"%s"' % outputencoding
|
||
|
|
)
|
||
|
|
|
||
|
|
# Check stream reader with encoding autodetection
|
||
|
|
q = Queue()
|
||
|
|
sr = codecs.getreader("css")(q)
|
||
|
|
result = []
|
||
|
|
# TODO: py3 only???
|
||
|
|
for c in input.encode(encoding):
|
||
|
|
q.write(c)
|
||
|
|
result.append(sr.read())
|
||
|
|
assert "".join(result) == input.replace('"x"', '"%s"' % outputencoding)
|
||
|
|
|
||
|
|
# Check stream reader with specified encoding
|
||
|
|
q = Queue()
|
||
|
|
sr = codecs.getreader("css")(q, encoding=encoding)
|
||
|
|
result = []
|
||
|
|
for c in input.encode(encoding):
|
||
|
|
q.write(c)
|
||
|
|
result.append(sr.read())
|
||
|
|
assert "".join(result) == input.replace('"x"', '"%s"' % outputencoding)
|
||
|
|
|
||
|
|
# Autodetectable encodings
|
||
|
|
checkauto("utf-8-sig")
|
||
|
|
checkauto("utf-16")
|
||
|
|
checkauto("utf-16-le")
|
||
|
|
checkauto("utf-16-be")
|
||
|
|
checkauto("utf-32")
|
||
|
|
checkauto("utf-32-le")
|
||
|
|
checkauto("utf-32-be")
|
||
|
|
|
||
|
|
def checkdecl(encoding, input='@charset "%s";g\xfcrk{}'):
|
||
|
|
# Check stateless decoder with encoding autodetection
|
||
|
|
d = codecs.getdecoder("css")
|
||
|
|
input = input % encoding
|
||
|
|
outputencoding = encoding
|
||
|
|
if outputencoding == "utf-8-sig":
|
||
|
|
outputencoding = "utf-8"
|
||
|
|
assert d(input.encode(encoding))[0] == input
|
||
|
|
|
||
|
|
# Check stateless decoder with specified encoding
|
||
|
|
assert d(input.encode(encoding), encoding=encoding)[0] == input
|
||
|
|
|
||
|
|
if hasattr(codec, "getincrementaldecoder"):
|
||
|
|
# Check incremental decoder with encoding autodetection
|
||
|
|
id = codecs.getincrementaldecoder("css")()
|
||
|
|
assert "".join(id.iterdecode(input.encode(encoding))) == input
|
||
|
|
|
||
|
|
# Check incremental decoder with specified encoding
|
||
|
|
id = codecs.getincrementaldecoder("css")(encoding)
|
||
|
|
assert "".join(id.iterdecode(input.encode(encoding))) == input
|
||
|
|
|
||
|
|
# Check stream reader with encoding autodetection
|
||
|
|
q = Queue()
|
||
|
|
sr = codecs.getreader("css")(q)
|
||
|
|
result = []
|
||
|
|
for c in input.encode(encoding):
|
||
|
|
q.write(c)
|
||
|
|
result.append(sr.read())
|
||
|
|
assert "".join(result) == input
|
||
|
|
|
||
|
|
# Check stream reader with specified encoding
|
||
|
|
q = Queue()
|
||
|
|
sr = codecs.getreader("css")(q, encoding=encoding)
|
||
|
|
result = []
|
||
|
|
for c in input.encode(encoding):
|
||
|
|
q.write(c)
|
||
|
|
result.append(sr.read())
|
||
|
|
assert "".join(result) == input
|
||
|
|
|
||
|
|
# Use correct declaration
|
||
|
|
checkdecl("utf-8")
|
||
|
|
checkdecl("iso-8859-1", '@charset "%s";g\xfcrk')
|
||
|
|
checkdecl("iso-8859-15")
|
||
|
|
checkdecl("cp1252")
|
||
|
|
|
||
|
|
# No recursion
|
||
|
|
with pytest.raises(ValueError):
|
||
|
|
b'@charset "css";div{}'.decode("css")
|
||
|
|
|
||
|
|
def test_encoder(self):
|
||
|
|
"codec.encoder"
|
||
|
|
|
||
|
|
def check(encoding, input='@charset "x";g\xfcrk\u20ac{}'):
|
||
|
|
outputencoding = encoding
|
||
|
|
if outputencoding == "utf-8-sig":
|
||
|
|
outputencoding = "utf-8"
|
||
|
|
|
||
|
|
# Check stateless encoder with encoding autodetection
|
||
|
|
e = codecs.getencoder("css")
|
||
|
|
inputdecl = input.replace('"x"', '"%s"' % encoding)
|
||
|
|
outputdecl = input.replace('"x"', '"%s"' % outputencoding)
|
||
|
|
assert e(inputdecl)[0].decode(encoding) == outputdecl
|
||
|
|
|
||
|
|
# Check stateless encoder with specified encoding
|
||
|
|
assert e(input, encoding=encoding)[0].decode(encoding) == outputdecl
|
||
|
|
|
||
|
|
if hasattr(codec, "getincrementalencoder"):
|
||
|
|
# Check incremental encoder with encoding autodetection
|
||
|
|
ie = codecs.getincrementalencoder("css")()
|
||
|
|
assert "".join(ie.iterencode(inputdecl)).decode(encoding) == outputdecl
|
||
|
|
|
||
|
|
# Check incremental encoder with specified encoding
|
||
|
|
ie = codecs.getincrementalencoder("css")(encoding=encoding)
|
||
|
|
assert "".join(ie.iterencode(input)).decode(encoding) == outputdecl
|
||
|
|
|
||
|
|
# Check stream writer with encoding autodetection
|
||
|
|
q = Queue()
|
||
|
|
sw = codecs.getwriter("css")(q)
|
||
|
|
for c in inputdecl: # .encode(outputencoding): # TODO: .encode()???
|
||
|
|
sw.write(c)
|
||
|
|
assert q.read().decode(encoding) == input.replace(
|
||
|
|
'"x"', '"%s"' % outputencoding
|
||
|
|
)
|
||
|
|
|
||
|
|
# Check stream writer with specified encoding
|
||
|
|
q = Queue()
|
||
|
|
sw = codecs.getwriter("css")(q, encoding=encoding)
|
||
|
|
for c in input:
|
||
|
|
sw.write(c)
|
||
|
|
assert q.read().decode(encoding) == input.replace(
|
||
|
|
'"x"', '"%s"' % outputencoding
|
||
|
|
)
|
||
|
|
|
||
|
|
# Autodetectable encodings
|
||
|
|
check("utf-8-sig")
|
||
|
|
check("utf-16")
|
||
|
|
check("utf-16-le")
|
||
|
|
check("utf-16-be")
|
||
|
|
check("utf-32")
|
||
|
|
check("utf-32-le")
|
||
|
|
check("utf-32-be")
|
||
|
|
check("utf-8")
|
||
|
|
check("iso-8859-1", '@charset "x";g\xfcrk{}')
|
||
|
|
check("iso-8859-15")
|
||
|
|
check("cp1252")
|
||
|
|
|
||
|
|
# No recursion
|
||
|
|
with pytest.raises(ValueError):
|
||
|
|
'@charset "css";div{}'.encode("css")
|
||
|
|
|
||
|
|
def test_decode_force(self):
|
||
|
|
"codec.decode (force)"
|
||
|
|
info = codecs.lookup("css")
|
||
|
|
|
||
|
|
def decodeall(input, **kwargs):
|
||
|
|
# Py 2.5: info.decode('@charset "utf-8"; x')
|
||
|
|
return info[1](input, **kwargs)[0]
|
||
|
|
|
||
|
|
def incdecode(input, **kwargs):
|
||
|
|
decoder = info.incrementaldecoder(**kwargs)
|
||
|
|
return decoder.decode(input)
|
||
|
|
|
||
|
|
def streamdecode(input, **kwargs):
|
||
|
|
stream = iostream(input) # py3 .decode('utf-8') but still error?!
|
||
|
|
reader = info.streamreader(stream, **kwargs)
|
||
|
|
return reader.read()
|
||
|
|
|
||
|
|
for d in (decodeall, incdecode, streamdecode):
|
||
|
|
# input = '@charset "utf-8"; \xc3\xbf'
|
||
|
|
# output = u'@charset "utf-8"; \xff'
|
||
|
|
# self.assertEqual(d(input), output)
|
||
|
|
#
|
||
|
|
# input = '@charset "utf-8"; \xc3\xbf'
|
||
|
|
# output = u'@charset "iso-8859-1"; \xc3\xbf'
|
||
|
|
# self.assertEqual(d(input, encoding="iso-8859-1", force=True), output)
|
||
|
|
#
|
||
|
|
# input = '\xc3\xbf'
|
||
|
|
# output = u'\xc3\xbf'
|
||
|
|
# self.assertEqual(d(input, encoding="iso-8859-1", force=True), output)
|
||
|
|
#
|
||
|
|
# input = '@charset "utf-8"; \xc3\xbf'
|
||
|
|
# output = u'@charset "utf-8"; \xff'
|
||
|
|
# self.assertEqual(d(input, encoding="iso-8859-1", force=False), output)
|
||
|
|
|
||
|
|
input = '@charset "utf-8"; \xff'.encode()
|
||
|
|
output = '@charset "utf-8"; \xff'
|
||
|
|
assert d(input) == output
|
||
|
|
|
||
|
|
# input = b'@charset "utf-8"; \xc3\xbf'
|
||
|
|
input = '@charset "utf-8"; \xff'.encode()
|
||
|
|
output = '@charset "iso-8859-1"; \xc3\xbf'
|
||
|
|
assert d(input, encoding="iso-8859-1", force=True) == output
|
||
|
|
|
||
|
|
# input = b'\xc3\xbf'
|
||
|
|
input = '\xff'.encode()
|
||
|
|
output = '\xc3\xbf'
|
||
|
|
assert d(input, encoding="iso-8859-1", force=True) == output
|
||
|
|
|
||
|
|
# input = b'@charset "utf-8"; \xc3\xbf'
|
||
|
|
input = '@charset "utf-8"; \xff'.encode()
|
||
|
|
output = '@charset "utf-8"; \xff'
|
||
|
|
assert d(input, encoding="iso-8859-1", force=False) == output
|