mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-11-03 19:17:13 -05:00 
			
		
		
		
	Merge branch 'dev'
This commit is contained in:
		
						commit
						2b692c6fc8
					
				@ -53,7 +53,7 @@
 | 
				
			|||||||
            <label class="form-check-label" for="task{{task.id}}"></label>
 | 
					            <label class="form-check-label" for="task{{task.id}}"></label>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </th>
 | 
					        </th>
 | 
				
			||||||
        <td class="overflow-auto">{{ task.task_file_name }}</td>
 | 
					        <td class="overflow-auto name-col">{{ task.task_file_name }}</td>
 | 
				
			||||||
        <td class="d-none d-lg-table-cell">{{ task.date_created | customDate:'short' }}</td>
 | 
					        <td class="d-none d-lg-table-cell">{{ task.date_created | customDate:'short' }}</td>
 | 
				
			||||||
        <td class="d-none d-lg-table-cell" *ngIf="activeTab !== 'started' && activeTab !== 'queued'">
 | 
					        <td class="d-none d-lg-table-cell" *ngIf="activeTab !== 'started' && activeTab !== 'queued'">
 | 
				
			||||||
          <div *ngIf="task.result?.length > 50" class="result" (click)="expandTask(task); $event.stopPropagation();"
 | 
					          <div *ngIf="task.result?.length > 50" class="result" (click)="expandTask(task); $event.stopPropagation();"
 | 
				
			||||||
 | 
				
			|||||||
@ -20,3 +20,9 @@ pre {
 | 
				
			|||||||
    width: 0.8rem;
 | 
					    width: 0.8rem;
 | 
				
			||||||
    height: 0.8rem;
 | 
					    height: 0.8rem;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media (max-width: 575.98px) {
 | 
				
			||||||
 | 
					    .name-col {
 | 
				
			||||||
 | 
					        max-width: 150px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@ export const environment = {
 | 
				
			|||||||
  apiBaseUrl: document.baseURI + 'api/',
 | 
					  apiBaseUrl: document.baseURI + 'api/',
 | 
				
			||||||
  apiVersion: '3',
 | 
					  apiVersion: '3',
 | 
				
			||||||
  appTitle: 'Paperless-ngx',
 | 
					  appTitle: 'Paperless-ngx',
 | 
				
			||||||
  version: '1.17.3',
 | 
					  version: '1.17.3-dev',
 | 
				
			||||||
  webSocketHost: window.location.host,
 | 
					  webSocketHost: window.location.host,
 | 
				
			||||||
  webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
 | 
					  webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
 | 
				
			||||||
  webSocketBaseUrl: base_url.pathname + 'ws/',
 | 
					  webSocketBaseUrl: base_url.pathname + 'ws/',
 | 
				
			||||||
 | 
				
			|||||||
@ -4962,7 +4962,7 @@
 | 
				
			|||||||
          <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
 | 
					          <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
 | 
				
			||||||
          <context context-type="linenumber">278</context>
 | 
					          <context context-type="linenumber">278</context>
 | 
				
			||||||
        </context-group>
 | 
					        </context-group>
 | 
				
			||||||
        <target state="needs-translation">Error retrieving groups</target>
 | 
					        <target state="translated">Σφάλμα κατά την ανάκτηση ομάδων</target>
 | 
				
			||||||
      </trans-unit>
 | 
					      </trans-unit>
 | 
				
			||||||
      <trans-unit id="1235706724900303689" datatype="html">
 | 
					      <trans-unit id="1235706724900303689" datatype="html">
 | 
				
			||||||
        <source>Error retrieving users</source>
 | 
					        <source>Error retrieving users</source>
 | 
				
			||||||
@ -4970,7 +4970,7 @@
 | 
				
			|||||||
          <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
 | 
					          <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
 | 
				
			||||||
          <context context-type="linenumber">287</context>
 | 
					          <context context-type="linenumber">287</context>
 | 
				
			||||||
        </context-group>
 | 
					        </context-group>
 | 
				
			||||||
        <target state="needs-translation">Error retrieving users</target>
 | 
					        <target state="translated">Σφάλμα στην ανάκτηση χρηστών</target>
 | 
				
			||||||
      </trans-unit>
 | 
					      </trans-unit>
 | 
				
			||||||
      <trans-unit id="5241231471117657636" datatype="html">
 | 
					      <trans-unit id="5241231471117657636" datatype="html">
 | 
				
			||||||
        <source>Error retrieving mail rules</source>
 | 
					        <source>Error retrieving mail rules</source>
 | 
				
			||||||
@ -4978,7 +4978,7 @@
 | 
				
			|||||||
          <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
 | 
					          <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
 | 
				
			||||||
          <context context-type="linenumber">314</context>
 | 
					          <context context-type="linenumber">314</context>
 | 
				
			||||||
        </context-group>
 | 
					        </context-group>
 | 
				
			||||||
        <target state="needs-translation">Error retrieving mail rules</target>
 | 
					        <target state="translated">Σφάλμα κατά την ανάκτηση κανόνων αλληλογραφίας</target>
 | 
				
			||||||
      </trans-unit>
 | 
					      </trans-unit>
 | 
				
			||||||
      <trans-unit id="3178554336792037159" datatype="html">
 | 
					      <trans-unit id="3178554336792037159" datatype="html">
 | 
				
			||||||
        <source>Error retrieving mail accounts</source>
 | 
					        <source>Error retrieving mail accounts</source>
 | 
				
			||||||
@ -4986,7 +4986,7 @@
 | 
				
			|||||||
          <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
 | 
					          <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
 | 
				
			||||||
          <context context-type="linenumber">323</context>
 | 
					          <context context-type="linenumber">323</context>
 | 
				
			||||||
        </context-group>
 | 
					        </context-group>
 | 
				
			||||||
        <target state="needs-translation">Error retrieving mail accounts</target>
 | 
					        <target state="translated">Σφάλμα στην ανάκτηση λογαριασμών αλληλογραφίας</target>
 | 
				
			||||||
      </trans-unit>
 | 
					      </trans-unit>
 | 
				
			||||||
      <trans-unit id="5610279464668232148" datatype="html">
 | 
					      <trans-unit id="5610279464668232148" datatype="html">
 | 
				
			||||||
        <source>Saved view "<x id="PH" equiv-text="savedView.name"/>" deleted.</source>
 | 
					        <source>Saved view "<x id="PH" equiv-text="savedView.name"/>" deleted.</source>
 | 
				
			||||||
 | 
				
			|||||||
@ -450,11 +450,18 @@ class Consumer(LoggingMixin):
 | 
				
			|||||||
            archive_path = document_parser.get_archive_path()
 | 
					            archive_path = document_parser.get_archive_path()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        except ParseError as e:
 | 
					        except ParseError as e:
 | 
				
			||||||
 | 
					            self._fail(
 | 
				
			||||||
 | 
					                str(e),
 | 
				
			||||||
 | 
					                f"Error occurred while consuming document {self.filename}: {e}",
 | 
				
			||||||
 | 
					                exc_info=True,
 | 
				
			||||||
 | 
					                exception=e,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
            document_parser.cleanup()
 | 
					            document_parser.cleanup()
 | 
				
			||||||
            tempdir.cleanup()
 | 
					            tempdir.cleanup()
 | 
				
			||||||
            self._fail(
 | 
					            self._fail(
 | 
				
			||||||
                str(e),
 | 
					                str(e),
 | 
				
			||||||
                f"Error while consuming document {self.filename}: {e}",
 | 
					                f"Unexpected error while consuming document {self.filename}: {e}",
 | 
				
			||||||
                exc_info=True,
 | 
					                exc_info=True,
 | 
				
			||||||
                exception=e,
 | 
					                exception=e,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
@ -544,8 +551,8 @@ class Consumer(LoggingMixin):
 | 
				
			|||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
            self._fail(
 | 
					            self._fail(
 | 
				
			||||||
                str(e),
 | 
					                str(e),
 | 
				
			||||||
                f"The following error occurred while consuming "
 | 
					                f"The following error occurred while storing document "
 | 
				
			||||||
                f"{self.filename}: {e}",
 | 
					                f"{self.filename} after parsing: {e}",
 | 
				
			||||||
                exc_info=True,
 | 
					                exc_info=True,
 | 
				
			||||||
                exception=e,
 | 
					                exception=e,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
				
			|||||||
@ -211,6 +211,18 @@ class FaultyParser(DocumentParser):
 | 
				
			|||||||
        raise ParseError("Does not compute.")
 | 
					        raise ParseError("Does not compute.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FaultyGenericExceptionParser(DocumentParser):
 | 
				
			||||||
 | 
					    def __init__(self, logging_group, scratch_dir):
 | 
				
			||||||
 | 
					        super().__init__(logging_group)
 | 
				
			||||||
 | 
					        _, self.fake_thumb = tempfile.mkstemp(suffix=".webp", dir=scratch_dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_thumbnail(self, document_path, mime_type, file_name=None):
 | 
				
			||||||
 | 
					        return self.fake_thumb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def parse(self, document_path, mime_type, file_name=None):
 | 
				
			||||||
 | 
					        raise Exception("Generic exception.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def fake_magic_from_file(file, mime=False):
 | 
					def fake_magic_from_file(file, mime=False):
 | 
				
			||||||
    if mime:
 | 
					    if mime:
 | 
				
			||||||
        if os.path.splitext(file)[1] == ".pdf":
 | 
					        if os.path.splitext(file)[1] == ".pdf":
 | 
				
			||||||
@ -260,6 +272,13 @@ class TestConsumer(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
 | 
				
			|||||||
    def make_faulty_parser(self, logging_group, progress_callback=None):
 | 
					    def make_faulty_parser(self, logging_group, progress_callback=None):
 | 
				
			||||||
        return FaultyParser(logging_group, self.dirs.scratch_dir)
 | 
					        return FaultyParser(logging_group, self.dirs.scratch_dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def make_faulty_generic_exception_parser(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        logging_group,
 | 
				
			||||||
 | 
					        progress_callback=None,
 | 
				
			||||||
 | 
					    ):
 | 
				
			||||||
 | 
					        return FaultyGenericExceptionParser(logging_group, self.dirs.scratch_dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        super().setUp()
 | 
					        super().setUp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -496,7 +515,29 @@ class TestConsumer(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        self.assertRaisesMessage(
 | 
					        self.assertRaisesMessage(
 | 
				
			||||||
            ConsumerError,
 | 
					            ConsumerError,
 | 
				
			||||||
            "sample.pdf: Error while consuming document sample.pdf: Does not compute.",
 | 
					            "sample.pdf: Error occurred while consuming document sample.pdf: Does not compute.",
 | 
				
			||||||
 | 
					            self.consumer.try_consume_file,
 | 
				
			||||||
 | 
					            self.get_test_file(),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self._assert_first_last_send_progress(last_status="FAILED")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @mock.patch("documents.parsers.document_consumer_declaration.send")
 | 
				
			||||||
 | 
					    def testGenericParserException(self, m):
 | 
				
			||||||
 | 
					        m.return_value = [
 | 
				
			||||||
 | 
					            (
 | 
				
			||||||
 | 
					                None,
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "parser": self.make_faulty_generic_exception_parser,
 | 
				
			||||||
 | 
					                    "mime_types": {"application/pdf": ".pdf"},
 | 
				
			||||||
 | 
					                    "weight": 0,
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertRaisesMessage(
 | 
				
			||||||
 | 
					            ConsumerError,
 | 
				
			||||||
 | 
					            "sample.pdf: Unexpected error while consuming document sample.pdf: Generic exception.",
 | 
				
			||||||
            self.consumer.try_consume_file,
 | 
					            self.consumer.try_consume_file,
 | 
				
			||||||
            self.get_test_file(),
 | 
					            self.get_test_file(),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
@ -510,7 +551,7 @@ class TestConsumer(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        self.assertRaisesMessage(
 | 
					        self.assertRaisesMessage(
 | 
				
			||||||
            ConsumerError,
 | 
					            ConsumerError,
 | 
				
			||||||
            "sample.pdf: The following error occurred while consuming sample.pdf: NO.",
 | 
					            "sample.pdf: The following error occurred while storing document sample.pdf after parsing: NO.",
 | 
				
			||||||
            self.consumer.try_consume_file,
 | 
					            self.consumer.try_consume_file,
 | 
				
			||||||
            filename,
 | 
					            filename,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
				
			|||||||
@ -340,7 +340,10 @@ class RasterisedDocumentParser(DocumentParser):
 | 
				
			|||||||
                    "Ghostscript PDF/A rendering failed, consider setting "
 | 
					                    "Ghostscript PDF/A rendering failed, consider setting "
 | 
				
			||||||
                    "PAPERLESS_OCR_USER_ARGS: '{\"continue_on_soft_render_error\": true}'",  # noqa: E501
 | 
					                    "PAPERLESS_OCR_USER_ARGS: '{\"continue_on_soft_render_error\": true}'",  # noqa: E501
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            raise e
 | 
					
 | 
				
			||||||
 | 
					            raise ParseError(
 | 
				
			||||||
 | 
					                f"SubprocessOutputError: {e!s}. See logs for more information.",
 | 
				
			||||||
 | 
					            ) from e
 | 
				
			||||||
        except (NoTextFoundException, InputFileError) as e:
 | 
					        except (NoTextFoundException, InputFileError) as e:
 | 
				
			||||||
            self.log.warning(
 | 
					            self.log.warning(
 | 
				
			||||||
                f"Encountered an error while running OCR: {e!s}. "
 | 
					                f"Encountered an error while running OCR: {e!s}. "
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,7 @@ from unittest import mock
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from django.test import TestCase
 | 
					from django.test import TestCase
 | 
				
			||||||
from django.test import override_settings
 | 
					from django.test import override_settings
 | 
				
			||||||
 | 
					from ocrmypdf import SubprocessOutputError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from documents.parsers import ParseError
 | 
					from documents.parsers import ParseError
 | 
				
			||||||
from documents.parsers import run_convert
 | 
					from documents.parsers import run_convert
 | 
				
			||||||
@ -827,6 +828,18 @@ class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
 | 
				
			|||||||
        # Copied from the PDF to here.  Don't even look at it
 | 
					        # Copied from the PDF to here.  Don't even look at it
 | 
				
			||||||
        self.assertIn("ةﯾﻠﺧﺎدﻻ ةرازو", parser.get_text())
 | 
					        self.assertIn("ةﯾﻠﺧﺎدﻻ ةرازو", parser.get_text())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @mock.patch("ocrmypdf.ocr")
 | 
				
			||||||
 | 
					    def test_gs_rendering_error(self, m):
 | 
				
			||||||
 | 
					        m.side_effect = SubprocessOutputError("Ghostscript PDF/A rendering failed")
 | 
				
			||||||
 | 
					        parser = RasterisedDocumentParser(None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertRaises(
 | 
				
			||||||
 | 
					            ParseError,
 | 
				
			||||||
 | 
					            parser.parse,
 | 
				
			||||||
 | 
					            os.path.join(self.SAMPLE_FILES, "simple-digital.pdf"),
 | 
				
			||||||
 | 
					            "application/pdf",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestParserFileTypes(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
 | 
					class TestParserFileTypes(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
 | 
				
			||||||
    SAMPLE_FILES = os.path.join(os.path.dirname(__file__), "samples")
 | 
					    SAMPLE_FILES = os.path.join(os.path.dirname(__file__), "samples")
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user