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): def version_check(version, op=operator.ge):
"""Check if the Qt runtime version is the version supplied or newer. """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: try:
ok = f.open(QIODevice.WriteOnly) ok = f.open(QIODevice.WriteOnly)
if not ok: if not ok:
raise OSError(f.errorString()) raise QtOSError(f)
if binary: if binary:
new_f = PyQIODevice(f) new_f = PyQIODevice(f)
else: else:
@ -198,7 +218,7 @@ def savefile_open(filename, binary=False, encoding='utf-8'):
finally: finally:
commit_ok = f.commit() commit_ok = f.commit()
if not commit_ok and not cancelled: if not commit_ok and not cancelled:
raise OSError("Commit failed!") raise QtOSError(f, msg="Commit failed!")
@contextlib.contextmanager @contextlib.contextmanager
@ -266,7 +286,7 @@ class PyQIODevice(io.BufferedIOBase):
""" """
ok = self.dev.open(mode) ok = self.dev.open(mode)
if not ok: if not ok:
raise OSError(self.dev.errorString()) raise QtOSError(self.dev)
return contextlib.closing(self) return contextlib.closing(self)
def close(self): def close(self):
@ -289,7 +309,7 @@ class PyQIODevice(io.BufferedIOBase):
raise io.UnsupportedOperation("whence = {} is not " raise io.UnsupportedOperation("whence = {} is not "
"supported!".format(whence)) "supported!".format(whence))
if not ok: if not ok:
raise OSError("seek failed!") raise QtOSError(self.dev, msg="seek failed!")
def truncate(self, size=None): # pylint: disable=unused-argument def truncate(self, size=None): # pylint: disable=unused-argument
raise io.UnsupportedOperation raise io.UnsupportedOperation
@ -329,7 +349,7 @@ class PyQIODevice(io.BufferedIOBase):
buf = self.dev.read(size) buf = self.dev.read(size)
if buf is None: if buf is None:
raise OSError(self.dev.errorString()) raise QtOSError(self.dev)
return buf return buf
def seekable(self): def seekable(self):
@ -348,7 +368,7 @@ class PyQIODevice(io.BufferedIOBase):
self._check_writable() self._check_writable()
num = self.dev.write(b) num = self.dev.write(b)
if num == -1 or num < len(b): if num == -1 or num < len(b):
raise OSError(self.dev.errorString()) raise QtOSError(self.dev)
return num return num
def read(self, size=-1): def read(self, size=-1):
@ -359,7 +379,7 @@ class PyQIODevice(io.BufferedIOBase):
else: else:
buf = self.dev.read(size) buf = self.dev.read(size)
if buf is None: if buf is None:
raise OSError(self.dev.errorString()) raise QtOSError(self.dev)
return buf return buf

View File

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