tb1337 / paperless-api

Little api client for paperless(-ngx).
https://pypi.org/p/pypaperless/
MIT License
25 stars 5 forks source link

Patching any document fails: created - Datetime has wrong format #113

Closed The-Compiler closed 4 months ago

The-Compiler commented 4 months ago

First of all, thanks for this project! I'm quite impressed that you went for asyncio for your first Python project - despite using Python for some 13 years, this was the first time I used asyncio for something non-trivial, and (even being no stranger to async concepts in general, thanks to PyQt): Phew!

If you're curious, here is what I did before running into what I believe to be a bug (described below):


With Python 3.11.7, pypaperless 3.0.1 and Paperless-ngx 2.5.4 configured with PAPERLESS_TIME_ZONE=Europe/Zurich, any patch operation fails:

import os
import asyncio
from pypaperless import Paperless

PAPERLESS_HOST = os.environ["PAPERLESS_HOST"]
PAPERLESS_TOKEN = os.environ["PAPERLESS_TOKEN"]

async def main():
    async with Paperless(PAPERLESS_HOST, PAPERLESS_TOKEN) as p:
        async for doc in p.documents:
            await doc.update()
            break

if __name__ == "__main__":
    asyncio.run(main())

results in:

Traceback (most recent call last):
  File "/home/florian/proj/2024-02-26-paperless-import/bug.py", line 15, in <module>
    asyncio.run(main())
  File "/usr/lib/python3.11/asyncio/runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/home/florian/proj/2024-02-26-paperless-import/bug.py", line 11, in main
    await doc.update()
  File "/home/florian/proj/2024-02-26-paperless-import/.venv/lib/python3.11/site-packages/pypaperless/models/mixins/models/updatable.py", line 32, in update
    updated = await self._patch_fields()
              ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/florian/proj/2024-02-26-paperless-import/.venv/lib/python3.11/site-packages/pypaperless/models/mixins/models/updatable.py", line 51, in _patch_fields
    self._data = await self._api.request_json(
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/florian/proj/2024-02-26-paperless-import/.venv/lib/python3.11/site-packages/pypaperless/api.py", line 224, in request_json
    raise JsonResponseWithError(payload)
pypaperless.exceptions.JsonResponseWithError: Paperless: created - Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].

because what's being sent to the API is:

{
  "created": "2013-01-01T00:00:00+01:00Z",
  "modified": "2024-02-26T17:19:29.443261+01:00Z",
  "added": "2024-02-26T17:19:29.351168+01:00Z"
}

but that makes no sense (both +01:00 but also Z, which stands for a zero offset from UTC).

This seems to be due to the result = result.rstrip("Z") + "Z" here:

https://github.com/tb1337/paperless-api/blob/6a819f0b6e16324ee0ec5a0f85c43ebda5057fd9/pypaperless/models/utils/__init__.py#L41-L46

added in:

and I can't quite wrap my head around it. The only place where it would make a difference is when datetime.datetime.isoformat() would have multiple Z suffixes (or +00:00Z), which I don't think ever happens? If there is a Z (or +00:00) already, this is a no-op - but crucially, if there is a different timezone, this adds a Z, causing things to explode.

Simply removing that line (and the if) makes things work just fine for me - but it's unclear to me if there's a good reason why it's there which I'm missing.

szaiser commented 4 months ago

@The-Compiler I have basically the same setup as you and can reproduce the problem with

paperless = get_paperless()
async with paperless as p:
    document = await paperless.documents(844)
    success = await document.update()

JsonResponseWithError: Paperless: created - Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z]. A nasty workaround is to modify created..

paperless = get_paperless()
async with paperless as p:
    document = await paperless.documents(844)
    document.created = datetime.datetime(10,10,10).isoformat()
    success = await document.update()
tb1337 commented 4 months ago

Hi folks, thank you for throwing in that issue. That'll gonna be fixed soon :)

tb1337 commented 4 months ago

Thank you! Gonna release the bugfix today.