Attach numerical code to Qt OSErrors and fix tests.

This fixes tests with tox < 2.0.0 on systems with a non-english locale, as it's
no longer the errorString which gets compared.

Fixes #806.
This commit is contained in:
Florian Bruhin 2015-07-12 11:20:28 +02:00
parent 0037b0db7e
commit ca5a78dfc7
2 changed files with 30 additions and 12 deletions

View File

@ -50,6 +50,26 @@ MINVALS = {
}
class QtOSError(OSError):
"""An OSError triggered by a QFileDevice.
Attributes:
qt_errno: The error attribute of the given QFileDevice, if applicable.
"""
def __init__(self, dev, msg=None):
if msg is None:
msg = dev.errorString()
super().__init__(msg)
try:
self.qt_errno = dev.error()
except AttributeError:
self.qt_errno = None
def version_check(version, op=operator.ge):
"""Check if the Qt runtime version is the version supplied or newer.
@ -183,7 +203,7 @@ def savefile_open(filename, binary=False, encoding='utf-8'):
try:
ok = f.open(QIODevice.WriteOnly)
if not ok:
raise OSError(f.errorString())
raise QtOSError(f)
if binary:
new_f = PyQIODevice(f)
else:
@ -198,7 +218,7 @@ def savefile_open(filename, binary=False, encoding='utf-8'):
finally:
commit_ok = f.commit()
if not commit_ok and not cancelled:
raise OSError("Commit failed!")
raise QtOSError(f, msg="Commit failed!")
@contextlib.contextmanager
@ -266,7 +286,7 @@ class PyQIODevice(io.BufferedIOBase):
"""
ok = self.dev.open(mode)
if not ok:
raise OSError(self.dev.errorString())
raise QtOSError(self.dev)
return contextlib.closing(self)
def close(self):
@ -289,7 +309,7 @@ class PyQIODevice(io.BufferedIOBase):
raise io.UnsupportedOperation("whence = {} is not "
"supported!".format(whence))
if not ok:
raise OSError("seek failed!")
raise QtOSError(self.dev, msg="seek failed!")
def truncate(self, size=None): # pylint: disable=unused-argument
raise io.UnsupportedOperation
@ -329,7 +349,7 @@ class PyQIODevice(io.BufferedIOBase):
buf = self.dev.read(size)
if buf is None:
raise OSError(self.dev.errorString())
raise QtOSError(self.dev)
return buf
def seekable(self):
@ -348,7 +368,7 @@ class PyQIODevice(io.BufferedIOBase):
self._check_writable()
num = self.dev.write(b)
if num == -1 or num < len(b):
raise OSError(self.dev.errorString())
raise QtOSError(self.dev)
return num
def read(self, size=-1):
@ -359,7 +379,7 @@ class PyQIODevice(io.BufferedIOBase):
else:
buf = self.dev.read(size)
if buf is None:
raise OSError(self.dev.errorString())
raise QtOSError(self.dev)
return buf

View File

@ -34,7 +34,7 @@ import pytest
import unittest
import unittest.mock
from PyQt5.QtCore import (QDataStream, QPoint, QUrl, QByteArray, QIODevice,
QTimer, QBuffer, QFile, QProcess)
QTimer, QBuffer, QFile, QProcess, QFileDevice)
from PyQt5.QtWidgets import QApplication
from qutebrowser import qutebrowser
@ -700,11 +700,9 @@ class TestPyQIODevice:
"""Test open() which fails (because it's an existant directory)."""
qf = QFile(str(tmpdir))
dev = qtutils.PyQIODevice(qf)
with pytest.raises(OSError) as excinfo:
with pytest.raises(qtutils.QtOSError) as excinfo:
dev.open(QIODevice.WriteOnly)
errors = ['Access is denied.', # Linux/OS X
'Is a directory'] # Windows
assert str(excinfo.value) in errors
assert excinfo.value.qt_errno == QFileDevice.OpenError
assert dev.closed
def test_fileno(self, pyqiodev):