From f8032e98401a630620bf1ef1bf49755f5ed2e476 Mon Sep 17 00:00:00 2001 From: tbsch Date: Sun, 15 Sep 2024 14:53:57 +0200 Subject: [PATCH] Improve error message parsing (#298) * Improve error message parsing * Reformat line * Update CI as parts are broken (#299) * Update deps * Change coverage generation --------- Co-authored-by: tb1337 --- .github/workflows/tests.yml | 10 +++------- poetry.lock | 6 +++--- pyproject.toml | 1 + src/pypaperless/exceptions.py | 33 +++++++++++++++++++++++++-------- tests/test_common.py | 12 +++++++++--- 5 files changed, 41 insertions(+), 21 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b0b9f53..5eb36e2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -37,12 +37,12 @@ jobs: - name: 🏗 Install Python dependencies run: poetry install --no-interaction - name: 🚀 Run pytest - run: poetry run pytest --cov pypaperless tests + run: poetry run pytest -v --cov-report xml:coverage.xml --cov src tests - name: ⬆️ Upload coverage artifact uses: actions/upload-artifact@v4.4.0 with: name: coverage-${{ matrix.python }} - path: .coverage + path: coverage.xml coverage: runs-on: ubuntu-latest @@ -68,12 +68,8 @@ jobs: poetry config virtualenvs.in-project true - name: 🏗 Install dependencies run: poetry install --no-interaction - - name: 🚀 Process coverage results - run: | - poetry run coverage combine coverage*/.coverage* - poetry run coverage xml -i - name: 🚀 Upload coverage report uses: codecov/codecov-action@v4.5.0 with: - fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: true diff --git a/poetry.lock b/poetry.lock index b63a020..9d05d38 100644 --- a/poetry.lock +++ b/poetry.lock @@ -505,13 +505,13 @@ files = [ [[package]] name = "identify" -version = "2.6.0" +version = "2.6.1" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.6.0-py2.py3-none-any.whl", hash = "sha256:e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0"}, - {file = "identify-2.6.0.tar.gz", hash = "sha256:cb171c685bdc31bcc4c1734698736a7d5b6c8bf2e0c15117f4d469c8640ae5cf"}, + {file = "identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0"}, + {file = "identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98"}, ] [package.extras] diff --git a/pyproject.toml b/pyproject.toml index 4fde4d6..c491b06 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,6 +58,7 @@ yamllint = "^1.35.1" [tool.coverage.run] plugins = ["covdefaults"] +source = ["pypaperless"] [tool.coverage.report] fail_under = 95 diff --git a/src/pypaperless/exceptions.py b/src/pypaperless/exceptions.py index 5b996ff..22f2e99 100644 --- a/src/pypaperless/exceptions.py +++ b/src/pypaperless/exceptions.py @@ -23,16 +23,33 @@ class JsonResponseWithError(PaperlessError): def __init__(self, payload: Any) -> None: """Initialize a `JsonResponseWithError` instance.""" - key: str = "error" - message: Any = "unknown error" - if isinstance(payload, dict): - key = "error" if "error" in payload else set(payload.keys()).pop() - message = payload[key] - if isinstance(message, list): - message = message.pop() + def _parse_payload(payload: Any, key: list[str] | None = None) -> tuple[list[str], str]: + """Parse first suitable error from payload.""" + if key is None: + key = [] - super().__init__(f"Paperless: {key} - {message}") + if isinstance(payload, list): + return _parse_payload(payload.pop(0), key) + if isinstance(payload, dict): + if "error" in payload: + key.append("error") + return _parse_payload(payload["error"], key) + + new_key = next(iter(payload)) + key.append(new_key) + + return _parse_payload(payload[new_key], key) + + return key, payload + + key, message = _parse_payload(payload) + + if len(key) == 0: + key.append("error") + key_chain = " -> ".join(key) + + super().__init__(f"Paperless [{key_chain}]: {message}") # Models diff --git a/tests/test_common.py b/tests/test_common.py index 8d313e5..e638b61 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -111,19 +111,25 @@ async def test_jsonresponsewitherror(self) -> None: payload = "sample string" raise JsonResponseWithError(payload) # noqa: TRY301 except JsonResponseWithError as exc: - assert exc.args[0] == "Paperless: error - unknown error" # noqa: PT017 + assert exc.args[0] == "Paperless [error]: sample string" # noqa: PT017 try: payload = {"failure": "something failed"} raise JsonResponseWithError(payload) # noqa: TRY301 except JsonResponseWithError as exc: - assert exc.args[0] == "Paperless: failure - something failed" # noqa: PT017 + assert exc.args[0] == "Paperless [failure]: something failed" # noqa: PT017 try: payload = {"error": ["that", "should", "have", "been", "never", "happened"]} raise JsonResponseWithError(payload) # noqa: TRY301 except JsonResponseWithError as exc: - assert exc.args[0] == "Paperless: error - happened" # noqa: PT017 + assert exc.args[0] == "Paperless [error]: that" # noqa: PT017 + + try: + payload = [{"some": [[{"weird": {"error": ["occurred"]}}]]}] + raise JsonResponseWithError(payload) # noqa: TRY301 + except JsonResponseWithError as exc: + assert exc.args[0] == "Paperless [some -> weird -> error]: occurred" # noqa: PT017 async def test_request(self, resp: aioresponses) -> None: """Test generate request."""