Repository: biolab/orange3-text

Issue:
Import Documents: crashes if folder contains no readable files
**Describe the bug**
Import Documents widget crashes when trying to load a folder with no readable files.

**To Reproduce**
Steps to reproduce the behavior:
Load a random folder without any .txt, .pdf or other files that the widget can read.

**Expected behavior**
No crash. None on output. Error: "Folder contains no readable files."

**Orange version:**
3.28.0.dev

**Text add-on version:**
1.3.1

**Additional context**
```
Traceback (most recent call last):
  File "/Users/ajda/orange/orange3-text/orangecontrib/text/widgets/owimportdocuments.py", line 547, in __onRunFinished
    self.corpus.name = "Documents"
AttributeError: 'NoneType' object has no attribute 'name'
```



Discussion:
Additional issue when trying to cancel the above task:
```
Traceback (most recent call last):
  File "/Users/ajda/orange/orange3-text/orangecontrib/text/widgets/owimportdocuments.py", line 563, in cancel
    assert self.__pendingTask is not None
AssertionError
```
I have same error just after I updated text add-on from 1.2.0 to 1.3.1.

Resolving patch:
diff --git a/orangecontrib/text/import_documents.py b/orangecontrib/text/import_documents.py
--- a/orangecontrib/text/import_documents.py
+++ b/orangecontrib/text/import_documents.py
@@ -44,6 +44,10 @@
 log = logging.getLogger(__name__)
 
 
+class NoDocumentsException(Exception):
+    pass
+
+
 class Reader(metaclass=Registry):
     def __init__(self, path, replace_white_space=False):
         self.path = path
@@ -168,6 +172,9 @@ def run(self):
         n_paths = len(paths)
         batch = []
 
+        if n_paths == 0:
+            raise NoDocumentsException()
+
         for path in paths:
             if len(batch) == 1 and self._report_progress is not None:
                 self._report_progress(
diff --git a/orangecontrib/text/widgets/owimportdocuments.py b/orangecontrib/text/widgets/owimportdocuments.py
--- a/orangecontrib/text/widgets/owimportdocuments.py
+++ b/orangecontrib/text/widgets/owimportdocuments.py
@@ -34,7 +34,8 @@
 from Orange.widgets.widget import Output
 
 from orangecontrib.text.corpus import Corpus
-from orangecontrib.text.import_documents import ImportDocuments
+from orangecontrib.text.import_documents import ImportDocuments, \
+    NoDocumentsException
 
 try:
     from orangecanvas.preview.previewbrowser import TextLabel
@@ -526,13 +527,15 @@ def __onRunFinished(self):
         task = self.__pendingTask
         self.__pendingTask = None
 
+        corpus, errors = None, []
         try:
             corpus, errors = task.future.result()
+        except NoDocumentsException:
+            state = State.Error
+            self.error("Folder contains no readable files.")
         except Exception:
             sys.excepthook(*sys.exc_info())
             state = State.Error
-            corpus = None
-            errors = []
             self.error(traceback.format_exc())
         else:
             state = State.Done
@@ -544,7 +547,8 @@ def __onRunFinished(self):
                 if corpus.domain.class_var else 0
 
         self.corpus = corpus
-        self.corpus.name = "Documents"
+        if self.corpus:
+            self.corpus.name = "Documents"
         self.skipped_documents = errors
 
         if len(errors):


Test patch:
diff --git a/orangecontrib/text/widgets/tests/test_owimportdocuments.py b/orangecontrib/text/widgets/tests/test_owimportdocuments.py
--- a/orangecontrib/text/widgets/tests/test_owimportdocuments.py
+++ b/orangecontrib/text/widgets/tests/test_owimportdocuments.py
@@ -1,5 +1,6 @@
 import os
 import unittest
+from unittest.mock import patch, Mock
 
 from Orange.widgets.tests.base import WidgetTest
 from orangecontrib.text.widgets.owimportdocuments import OWImportDocuments
@@ -81,6 +82,16 @@ def test_info_box(self):
             "No document set selected", self.widget.info_area.text()
         )
 
+    @patch("orangecontrib.text.import_documents.ImportDocuments.scan",
+           Mock(return_value=[]))
+    def test_load_empty_folder(self):
+        widget = self.create_widget(OWImportDocuments)
+        path = os.path.join(os.path.dirname(__file__), "data/documents")
+        widget.setCurrentPath(path)
+        widget.reload()
+        self.wait_until_finished(widget=widget)
+        self.assertIsNone(self.get_output(widget.Outputs.data))
+
 
 if __name__ == "__main__":
     unittest.main()