Skip to content

Commit 2875478

Browse files
committed
textimport: Mark encoding errors in the preview
1 parent 4376a88 commit 2875478

File tree

1 file changed

+22
-14
lines changed

1 file changed

+22
-14
lines changed

Orange/widgets/utils/textimport.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -991,9 +991,11 @@ def __resetPreview(self):
991991
base = CachedBytesIOWrapper(self.__sample, self.__buffer)
992992

993993
wrapper = io.TextIOWrapper(
994-
base, encoding=self.encoding(), errors="replace"
994+
base, encoding=self.encoding(),
995+
# use surrogate escape to validate/detect encoding errors in
996+
# delegates
997+
errors="surrogateescape"
995998
)
996-
997999
rows = csv.reader(
9981000
wrapper, dialect=self.dialect()
9991001
)
@@ -1372,6 +1374,11 @@ def sizeHint(self):
13721374
return sh.expandedTo(QSize(8 * hsection, 20 * vsection))
13731375

13741376

1377+
def is_surrogate_escaped(text: str) -> bool:
1378+
"""Does `text` contain any surrogate escape characters."""
1379+
return any("\udc80" <= c <= "\udcff" for c in text)
1380+
1381+
13751382
class PreviewItemDelegate(QStyledItemDelegate):
13761383
def initStyleOption(self, option, index):
13771384
# type: (QStyleOptionViewItem, QModelIndex) -> None
@@ -1389,6 +1396,18 @@ def initStyleOption(self, option, index):
13891396
if coltype == ColumnType.Numeric or coltype == ColumnType.Time:
13901397
option.displayAlignment = Qt.AlignRight | Qt.AlignVCenter
13911398

1399+
if not self.validate(option.text):
1400+
option.palette.setBrush(
1401+
QPalette.All, QPalette.Text, QBrush(Qt.red, Qt.SolidPattern)
1402+
)
1403+
option.palette.setBrush(
1404+
QPalette.All, QPalette.HighlightedText,
1405+
QBrush(Qt.red, Qt.SolidPattern)
1406+
)
1407+
1408+
def validate(self, value: str) -> bool: # pylint: disable=no-self-use
1409+
return not is_surrogate_escaped(value)
1410+
13921411
def helpEvent(self, event, view, option, index):
13931412
# type: (QHelpEvent, QAbstractItemView, QStyleOptionViewItem, QModelIndex) -> bool
13941413
if event.type() == QEvent.ToolTip:
@@ -1467,17 +1486,6 @@ def __init__(self, *args, converter=None, **kwargs):
14671486
super().__init__(*args, **kwargs)
14681487
self.converter = converter or float
14691488

1470-
def initStyleOption(self, option, index):
1471-
super().initStyleOption(option, index)
1472-
if not self.validate(option.text):
1473-
option.palette.setBrush(
1474-
QPalette.All, QPalette.Text, QBrush(Qt.red, Qt.SolidPattern)
1475-
)
1476-
option.palette.setBrush(
1477-
QPalette.All, QPalette.HighlightedText,
1478-
QBrush(Qt.red, Qt.SolidPattern)
1479-
)
1480-
14811489
def validate(self, value):
14821490
if value in {"NA", "Na", "na", "n/a", "N/A", "?", "", "."}:
14831491
return True
@@ -1486,7 +1494,7 @@ def validate(self, value):
14861494
except ValueError:
14871495
return False
14881496
else:
1489-
return True
1497+
return super().validate(value)
14901498

14911499

14921500
def number_parser(groupsep, decimalsep):

0 commit comments

Comments
 (0)