mirror of
https://github.com/python/cpython.git
synced 2025-08-31 14:07:50 +00:00
Make test_zipfile pass.
The zipfile module now does all I/O in binary mode using bytes. (Maybe we should support wrapping a TextIOWrapper around it when text mode reading is requested?) Even the password is a bytes array now. Had to fix py_compile.py to use bytes while I was at it. The _struct needed a patch to support bytes, str8 and str for the 's' and 'p' formats.
This commit is contained in:
parent
94ca1c620e
commit
d6ca546091
4 changed files with 177 additions and 146 deletions
|
@ -3,10 +3,8 @@ try:
|
|||
import zlib
|
||||
except ImportError:
|
||||
zlib = None
|
||||
import zipfile, os, unittest, sys, shutil, struct, io
|
||||
|
||||
import zipfile, os, unittest, sys, shutil, struct
|
||||
|
||||
from StringIO import StringIO
|
||||
from tempfile import TemporaryFile
|
||||
from random import randint, random
|
||||
|
||||
|
@ -18,9 +16,10 @@ FIXEDTEST_SIZE = 10
|
|||
|
||||
class TestsWithSourceFile(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.line_gen = ("Zipfile test line %d. random float: %f" % (i, random())
|
||||
for i in range(FIXEDTEST_SIZE))
|
||||
self.data = '\n'.join(self.line_gen) + '\n'
|
||||
self.line_gen = (bytes("Zipfile test line %d. random float: %f" %
|
||||
(i, random()))
|
||||
for i in range(FIXEDTEST_SIZE))
|
||||
self.data = b'\n'.join(self.line_gen) + b'\n'
|
||||
|
||||
# Make a source file with some lines
|
||||
fp = open(TESTFN, "wb")
|
||||
|
@ -45,14 +44,8 @@ class TestsWithSourceFile(unittest.TestCase):
|
|||
self.assertEqual(zipfp.read("strfile"), self.data)
|
||||
|
||||
# Print the ZIP directory
|
||||
fp = StringIO()
|
||||
stdout = sys.stdout
|
||||
try:
|
||||
sys.stdout = fp
|
||||
|
||||
zipfp.printdir()
|
||||
finally:
|
||||
sys.stdout = stdout
|
||||
fp = io.StringIO()
|
||||
zipfp.printdir(file=fp)
|
||||
|
||||
directory = fp.getvalue()
|
||||
lines = directory.splitlines()
|
||||
|
@ -95,7 +88,7 @@ class TestsWithSourceFile(unittest.TestCase):
|
|||
zipfp.close()
|
||||
|
||||
def testStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
def zipOpenTest(self, f, compression):
|
||||
|
@ -119,12 +112,12 @@ class TestsWithSourceFile(unittest.TestCase):
|
|||
break
|
||||
zipdata2.append(read_data)
|
||||
|
||||
self.assertEqual(''.join(zipdata1), self.data)
|
||||
self.assertEqual(''.join(zipdata2), self.data)
|
||||
self.assertEqual(b''.join(zipdata1), self.data)
|
||||
self.assertEqual(b''.join(zipdata2), self.data)
|
||||
zipfp.close()
|
||||
|
||||
def testOpenStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipOpenTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
def zipRandomOpenTest(self, f, compression):
|
||||
|
@ -140,11 +133,11 @@ class TestsWithSourceFile(unittest.TestCase):
|
|||
break
|
||||
zipdata1.append(read_data)
|
||||
|
||||
self.assertEqual(''.join(zipdata1), self.data)
|
||||
self.assertEqual(b''.join(zipdata1), self.data)
|
||||
zipfp.close()
|
||||
|
||||
def testRandomOpenStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipRandomOpenTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
def zipReadlineTest(self, f, compression):
|
||||
|
@ -181,40 +174,40 @@ class TestsWithSourceFile(unittest.TestCase):
|
|||
zipfp.close()
|
||||
|
||||
def testReadlineStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipReadlineTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
def testReadlinesStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipReadlinesTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
def testIterlinesStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipIterlinesTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
if zlib:
|
||||
def testDeflated(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipTest(f, zipfile.ZIP_DEFLATED)
|
||||
|
||||
def testOpenDeflated(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipOpenTest(f, zipfile.ZIP_DEFLATED)
|
||||
|
||||
def testRandomOpenDeflated(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipRandomOpenTest(f, zipfile.ZIP_DEFLATED)
|
||||
|
||||
def testReadlineDeflated(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipReadlineTest(f, zipfile.ZIP_DEFLATED)
|
||||
|
||||
def testReadlinesDeflated(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipReadlinesTest(f, zipfile.ZIP_DEFLATED)
|
||||
|
||||
def testIterlinesDeflated(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipIterlinesTest(f, zipfile.ZIP_DEFLATED)
|
||||
|
||||
def testLowCompression(self):
|
||||
|
@ -227,8 +220,8 @@ class TestsWithSourceFile(unittest.TestCase):
|
|||
# Get an open object for strfile
|
||||
zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_DEFLATED)
|
||||
openobj = zipfp.open("strfile")
|
||||
self.assertEqual(openobj.read(1), '1')
|
||||
self.assertEqual(openobj.read(1), '2')
|
||||
self.assertEqual(openobj.read(1), b'1')
|
||||
self.assertEqual(openobj.read(1), b'2')
|
||||
|
||||
def testAbsoluteArcnames(self):
|
||||
zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED)
|
||||
|
@ -251,8 +244,9 @@ class TestZip64InSmallFiles(unittest.TestCase):
|
|||
self._limit = zipfile.ZIP64_LIMIT
|
||||
zipfile.ZIP64_LIMIT = 5
|
||||
|
||||
line_gen = ("Test of zipfile line %d." % i for i in range(0, FIXEDTEST_SIZE))
|
||||
self.data = '\n'.join(line_gen)
|
||||
line_gen = (bytes("Test of zipfile line %d." % i)
|
||||
for i in range(0, FIXEDTEST_SIZE))
|
||||
self.data = b'\n'.join(line_gen)
|
||||
|
||||
# Make a source file with some lines
|
||||
fp = open(TESTFN, "wb")
|
||||
|
@ -272,7 +266,7 @@ class TestZip64InSmallFiles(unittest.TestCase):
|
|||
zipfp.close()
|
||||
|
||||
def testLargeFileException(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.largeFileExceptionTest(f, zipfile.ZIP_STORED)
|
||||
self.largeFileExceptionTest2(f, zipfile.ZIP_STORED)
|
||||
|
||||
|
@ -291,14 +285,8 @@ class TestZip64InSmallFiles(unittest.TestCase):
|
|||
self.assertEqual(zipfp.read("strfile"), self.data)
|
||||
|
||||
# Print the ZIP directory
|
||||
fp = StringIO()
|
||||
stdout = sys.stdout
|
||||
try:
|
||||
sys.stdout = fp
|
||||
|
||||
zipfp.printdir()
|
||||
finally:
|
||||
sys.stdout = stdout
|
||||
fp = io.StringIO()
|
||||
zipfp.printdir(fp)
|
||||
|
||||
directory = fp.getvalue()
|
||||
lines = directory.splitlines()
|
||||
|
@ -343,13 +331,13 @@ class TestZip64InSmallFiles(unittest.TestCase):
|
|||
zipfp.close()
|
||||
|
||||
def testStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
|
||||
if zlib:
|
||||
def testDeflated(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipTest(f, zipfile.ZIP_DEFLATED)
|
||||
|
||||
def testAbsoluteArcnames(self):
|
||||
|
@ -440,7 +428,7 @@ class OtherTests(unittest.TestCase):
|
|||
os.unlink(TESTFN)
|
||||
|
||||
filename = 'testfile.txt'
|
||||
content = 'hello, world. this is some content.'
|
||||
content = b'hello, world. this is some content.'
|
||||
|
||||
try:
|
||||
zf = zipfile.ZipFile(TESTFN, 'a')
|
||||
|
@ -483,7 +471,7 @@ class OtherTests(unittest.TestCase):
|
|||
# This test checks that the is_zipfile function correctly identifies
|
||||
# a file that is a zip file
|
||||
zipf = zipfile.ZipFile(TESTFN, mode="w")
|
||||
zipf.writestr("foo.txt", "O, for a Muse of Fire!")
|
||||
zipf.writestr("foo.txt", b"O, for a Muse of Fire!")
|
||||
zipf.close()
|
||||
chk = zipfile.is_zipfile(TESTFN)
|
||||
self.assert_(chk is True)
|
||||
|
@ -504,7 +492,7 @@ class OtherTests(unittest.TestCase):
|
|||
|
||||
def testClosedZipRaisesRuntimeError(self):
|
||||
# Verify that testzip() doesn't swallow inappropriate exceptions.
|
||||
data = StringIO()
|
||||
data = io.BytesIO()
|
||||
zipf = zipfile.ZipFile(data, mode="w")
|
||||
zipf.writestr("foo.txt", "O, for a Muse of Fire!")
|
||||
zipf.close()
|
||||
|
@ -525,15 +513,15 @@ class DecryptionTests(unittest.TestCase):
|
|||
# ZIP file
|
||||
|
||||
data = (
|
||||
'PK\x03\x04\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00\x1a\x00'
|
||||
'\x00\x00\x08\x00\x00\x00test.txt\xfa\x10\xa0gly|\xfa-\xc5\xc0=\xf9y'
|
||||
'\x18\xe0\xa8r\xb3Z}Lg\xbc\xae\xf9|\x9b\x19\xe4\x8b\xba\xbb)\x8c\xb0\xdbl'
|
||||
'PK\x01\x02\x14\x00\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00'
|
||||
'\x1a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00 \x00\xb6\x81'
|
||||
'\x00\x00\x00\x00test.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x006\x00'
|
||||
'\x00\x00L\x00\x00\x00\x00\x00' )
|
||||
b'PK\x03\x04\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00\x1a\x00'
|
||||
b'\x00\x00\x08\x00\x00\x00test.txt\xfa\x10\xa0gly|\xfa-\xc5\xc0=\xf9y'
|
||||
b'\x18\xe0\xa8r\xb3Z}Lg\xbc\xae\xf9|\x9b\x19\xe4\x8b\xba\xbb)\x8c\xb0\xdbl'
|
||||
b'PK\x01\x02\x14\x00\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00'
|
||||
b'\x1a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00 \x00\xb6\x81'
|
||||
b'\x00\x00\x00\x00test.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x006\x00'
|
||||
b'\x00\x00L\x00\x00\x00\x00\x00' )
|
||||
|
||||
plain = 'zipfile.py encryption test'
|
||||
plain = b'zipfile.py encryption test'
|
||||
|
||||
def setUp(self):
|
||||
fp = open(TESTFN, "wb")
|
||||
|
@ -551,18 +539,19 @@ class DecryptionTests(unittest.TestCase):
|
|||
self.assertRaises(RuntimeError, self.zip.read, "test.txt")
|
||||
|
||||
def testBadPassword(self):
|
||||
self.zip.setpassword("perl")
|
||||
self.zip.setpassword(b"perl")
|
||||
self.assertRaises(RuntimeError, self.zip.read, "test.txt")
|
||||
|
||||
def testGoodPassword(self):
|
||||
self.zip.setpassword("python")
|
||||
self.zip.setpassword(b"python")
|
||||
self.assertEquals(self.zip.read("test.txt"), self.plain)
|
||||
|
||||
|
||||
class TestsWithRandomBinaryFiles(unittest.TestCase):
|
||||
def setUp(self):
|
||||
datacount = randint(16, 64)*1024 + randint(1, 1024)
|
||||
self.data = ''.join((struct.pack('<f', random()*randint(-1000, 1000)) for i in range(datacount)))
|
||||
self.data = b''.join(struct.pack('<f', random()*randint(-1000, 1000))
|
||||
for i in range(datacount))
|
||||
|
||||
# Make a source file with some lines
|
||||
fp = open(TESTFN, "wb")
|
||||
|
@ -592,7 +581,7 @@ class TestsWithRandomBinaryFiles(unittest.TestCase):
|
|||
zipfp.close()
|
||||
|
||||
def testStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
def zipOpenTest(self, f, compression):
|
||||
|
@ -616,17 +605,17 @@ class TestsWithRandomBinaryFiles(unittest.TestCase):
|
|||
break
|
||||
zipdata2.append(read_data)
|
||||
|
||||
testdata1 = ''.join(zipdata1)
|
||||
testdata1 = b''.join(zipdata1)
|
||||
self.assertEqual(len(testdata1), len(self.data))
|
||||
self.assertEqual(testdata1, self.data)
|
||||
|
||||
testdata2 = ''.join(zipdata2)
|
||||
testdata2 = b''.join(zipdata2)
|
||||
self.assertEqual(len(testdata1), len(self.data))
|
||||
self.assertEqual(testdata1, self.data)
|
||||
zipfp.close()
|
||||
|
||||
def testOpenStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipOpenTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
def zipRandomOpenTest(self, f, compression):
|
||||
|
@ -642,13 +631,13 @@ class TestsWithRandomBinaryFiles(unittest.TestCase):
|
|||
break
|
||||
zipdata1.append(read_data)
|
||||
|
||||
testdata = ''.join(zipdata1)
|
||||
testdata = b''.join(zipdata1)
|
||||
self.assertEqual(len(testdata), len(self.data))
|
||||
self.assertEqual(testdata, self.data)
|
||||
zipfp.close()
|
||||
|
||||
def testRandomOpenStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.zipRandomOpenTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
class TestsWithMultipleOpens(unittest.TestCase):
|
||||
|
@ -682,8 +671,8 @@ class TestsWithMultipleOpens(unittest.TestCase):
|
|||
data2 = zopen2.read(500)
|
||||
data1 += zopen1.read(500)
|
||||
data2 += zopen2.read(500)
|
||||
self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
|
||||
self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
|
||||
self.assertEqual(data1, b'1'*FIXEDTEST_SIZE)
|
||||
self.assertEqual(data2, b'2'*FIXEDTEST_SIZE)
|
||||
zipf.close()
|
||||
|
||||
def testInterleaved(self):
|
||||
|
@ -696,8 +685,8 @@ class TestsWithMultipleOpens(unittest.TestCase):
|
|||
data2 = zopen2.read(500)
|
||||
data1 += zopen1.read(500)
|
||||
data2 += zopen2.read(500)
|
||||
self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
|
||||
self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
|
||||
self.assertEqual(data1, b'1'*FIXEDTEST_SIZE)
|
||||
self.assertEqual(data2, b'2'*FIXEDTEST_SIZE)
|
||||
zipf.close()
|
||||
|
||||
def tearDown(self):
|
||||
|
@ -706,13 +695,19 @@ class TestsWithMultipleOpens(unittest.TestCase):
|
|||
|
||||
class UniversalNewlineTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.line_gen = ["Test of zipfile line %d." % i for i in range(FIXEDTEST_SIZE)]
|
||||
self.line_gen = [bytes("Test of zipfile line %d." % i)
|
||||
for i in range(FIXEDTEST_SIZE)]
|
||||
self.seps = ('\r', '\r\n', '\n')
|
||||
self.arcdata, self.arcfiles = {}, {}
|
||||
for n, s in enumerate(self.seps):
|
||||
self.arcdata[s] = s.join(self.line_gen) + s
|
||||
b = s.encode("ascii")
|
||||
self.arcdata[s] = b.join(self.line_gen) + b
|
||||
self.arcfiles[s] = '%s-%d' % (TESTFN, n)
|
||||
file(self.arcfiles[s], "wb").write(self.arcdata[s])
|
||||
f = open(self.arcfiles[s], "wb")
|
||||
try:
|
||||
f.write(self.arcdata[s])
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
def makeTestArchive(self, f, compression):
|
||||
# Create the ZIP archive
|
||||
|
@ -741,7 +736,7 @@ class UniversalNewlineTests(unittest.TestCase):
|
|||
zipopen = zipfp.open(fn, "rU")
|
||||
for line in self.line_gen:
|
||||
linedata = zipopen.readline()
|
||||
self.assertEqual(linedata, line + '\n')
|
||||
self.assertEqual(linedata, line + b'\n')
|
||||
|
||||
zipfp.close()
|
||||
|
||||
|
@ -753,7 +748,7 @@ class UniversalNewlineTests(unittest.TestCase):
|
|||
for sep, fn in self.arcfiles.items():
|
||||
ziplines = zipfp.open(fn, "rU").readlines()
|
||||
for line, zipline in zip(self.line_gen, ziplines):
|
||||
self.assertEqual(zipline, line + '\n')
|
||||
self.assertEqual(zipline, line + b'\n')
|
||||
|
||||
zipfp.close()
|
||||
|
||||
|
@ -764,41 +759,41 @@ class UniversalNewlineTests(unittest.TestCase):
|
|||
zipfp = zipfile.ZipFile(f, "r")
|
||||
for sep, fn in self.arcfiles.items():
|
||||
for line, zipline in zip(self.line_gen, zipfp.open(fn, "rU")):
|
||||
self.assertEqual(zipline, line + '\n')
|
||||
self.assertEqual(zipline, line + b'\n')
|
||||
|
||||
zipfp.close()
|
||||
|
||||
def testReadStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.readTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
def testReadlineStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.readlineTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
def testReadlinesStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.readlinesTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
def testIterlinesStored(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.iterlinesTest(f, zipfile.ZIP_STORED)
|
||||
|
||||
if zlib:
|
||||
def testReadDeflated(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.readTest(f, zipfile.ZIP_DEFLATED)
|
||||
|
||||
def testReadlineDeflated(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.readlineTest(f, zipfile.ZIP_DEFLATED)
|
||||
|
||||
def testReadlinesDeflated(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.readlinesTest(f, zipfile.ZIP_DEFLATED)
|
||||
|
||||
def testIterlinesDeflated(self):
|
||||
for f in (TESTFN2, TemporaryFile(), StringIO()):
|
||||
for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
|
||||
self.iterlinesTest(f, zipfile.ZIP_DEFLATED)
|
||||
|
||||
def tearDown(self):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue