andy29485 / embypy

python wrapper for the emby rest api
GNU Lesser General Public License v3.0
16 stars 7 forks source link

TypeError: cannot unpack non-iterable coroutine object #8

Open itsalljustdata opened 2 years ago

itsalljustdata commented 2 years ago

` server = serverConfig( Path('file').parent.parent.joinpath('config.yaml'))

for l in [m for m in server.emby.movies if re.search(r'^[1|2]\d{3}.', m.name)]:
    newName = f"{l.name[5:].replace('.', ' ')} ({l.name[0:4]})"
    l.name = newName
    l.post()

`

I'm trying to do somere-titling of some movies ("nnnn.Title" to "Title (nnnn)"), but I'm getting this horrible looking "TypeError: cannot unpack non-iterable coroutine object" exception on the "post" call to send the update back to the server.

my serverConfig class is just an object wrapper which reads in a config file and then creates the emby connection, it's connecting and retrieving the movies from the server OK.

Any ideas?

Python 3.9.6 embypy 0.6.2.3

andy29485 commented 2 years ago

Check if the commit fixes it (I just did some testing and it seems to work).

itsalljustdata commented 2 years ago

OK. that worked! Next question is - why is the update to the name not actually happening?

andy29485 commented 2 years ago

That's strange... are you using v0.6.2.3.4 or v0.6.2.4.0 now?

itsalljustdata commented 2 years ago

for my own sanity I just blew away my venv and started afresh using 0.6.3.0

still doesn't seem to be updating

from classes import serverConfig
import re
from pathlib import Path

from icecream import ic

def doRename():

    ic.configureOutput(includeContext=True)
    server = serverConfig(
        Path('__file__').parent.parent.joinpath('config.yaml'))

    src = server.emby.search('Rocky Horror')
    for l in src:
        ic(l.name)

    for l in [m for m in src if re.search(r'^[1|2]\d{3}.', m.name)]:
        l.name = f"{l.name[5:].replace('.', ' ')} ({l.name[0:4]})"
        ic(l.name)
        l.send()
        ic(l.name)

    src = server.emby.search('Rocky Horror')
    for l in src:
        ic(l.name)

if __name__ == '__main__':
    doRename()
ic| __main__.py:17 in doRename()
    l.name: '1975.The.Rocky.Horror.Picture.Show'
ic| __main__.py:21 in doRename()
    l.name: 'The Rocky Horror Picture Show (1975)'
ic| __main__.py:23 in doRename()
    l.name: '1975.The.Rocky.Horror.Picture.Show'
ic| __main__.py:27 in doRename()
    l.name: '1975.The.Rocky.Horror.Picture.Show'
andy29485 commented 2 years ago

Sorry about that, made a mistake when committing (shouldn't have tried to split it into two versions).

hotfix v0.6.3.1 should fix that issue

itsalljustdata commented 2 years ago

still the same. no update is actually happening. :(

andy29485 commented 2 years ago

Welp, not sure where to go from this point. I've got it working on my instance of jellyfin (switched a while ago). Emby's api / code examples seem to do the same thing that I do.

I've created a new version that has the post/send method return an http status/message that comes from emby/jellyfin. This should help you debug what the issue is (try doing a ic(l.send()) instead of just a send).

Side note, for your regex I think you meant to do either r'^(1|2)\d{3}\.' or r'^[12]\d{3}.'. Side note 2, embypy will prefer to use an internal cache for things, so unless you do an item.update()(for items) or emby.movies_force() (for all movie items). It'll just keep re-using what it thinks is the right value not what's actually stored by the server.

So something like this:

for item in server.emby.search('Rocky Horror'):
    ic(item.name)
    if match := re.search(r'^([12]\d{3})\.\s*(.*)', item.name):  # python 3.8
        item.name = f"{match.group(2)} ({match.group(1)})"
        ic(item.name)
        ic(item.send())
        item.update()  # without this you'll keep seeing the cached version that you just set not what's on the server
        ic(item.name)
itsalljustdata commented 2 years ago

now i'm confused...

    status: 400
    resp: "Value cannot be null. (Parameter 'source')"

emby 4.6.4.0

itsalljustdata commented 2 years ago

and throwing it at a jellyfin server gives me a more verbose exception....

(embyAPI) root@skynet:/mnt/user/code/embyAPI# python app
ic| __main__.py:19 in doRename()- l.name: '1976.Rocky'
ic| __main__.py:22 in doRename()- l.name: 'Rocky (1976)'
call 1 : 400 Error processing request.
Traceback (most recent call last):
  File "/mnt/user/code/embyAPI/embypy/embypy/utils/connector.py", line 347, in resp_to_json
    return await resp.json()
  File "/root/.local/share/virtualenvs/embyAPI-qd3ssg_h/lib64/python3.9/site-packages/aiohttp/client_reqrep.py", line 1097, in json
    raise ContentTypeError(
aiohttp.client_exceptions.ContentTypeError: 0, message='Attempt to decode JSON with unexpected mimetype: text/plain', url=URL('http://127.0.0.1:8096/Users/xxxxxxxxxxxx/Items/xxxxxxxxxxxxxxxxx?Fields=Path,Overview&api_key=xxxxxxxxxxxxxxxx&deviceId=badgersPython')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib64/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib64/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/mnt/user/code/embyAPI/app/__main__.py", line 38, in <module>
    doRename()
  File "/mnt/user/code/embyAPI/app/__main__.py", line 25, in doRename
    status, resp = l.send()
  File "/mnt/user/code/embyAPI/embypy/embypy/utils/asyncio.py", line 24, in tmp_func
    return _run_func(func, *args, **kargs)
  File "/mnt/user/code/embyAPI/embypy/embypy/utils/asyncio.py", line 61, in _run_func
    return _get_loop().run_until_complete(out)
  File "/usr/lib64/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/mnt/user/code/embyAPI/embypy/embypy/objects/object.py", line 326, in send
    await EmbyObject(self.object_dict, self.connector).update()
  File "/mnt/user/code/embyAPI/embypy/embypy/objects/object.py", line 276, in update
    info = await self.connector.getJson(
  File "/mnt/user/code/embyAPI/embypy/embypy/utils/connector.py", line 573, in getJson
    return await Connector.resp_to_json(resp)
  File "/mnt/user/code/embyAPI/embypy/embypy/utils/connector.py", line 349, in resp_to_json
    raise RuntimeError(
RuntimeError: Unexpected JSON output (status: 400): "Error processing request."
andy29485 commented 2 years ago

status: 400 resp: "Value cannot be null. (Parameter 'source')" This was always a strange error to debug because there isn't a parameter named source anywhere in the api (usually meant something else that I was doing was wrong).

and throwing it at a jellyfin server gives me a more verbose exception.... Just the last line is the error. The string coming back from the server (Error processing request.) isn't valid json so it's throwing an exception. This is basically as generic of an error as they get and doesn't actually say much sadly (just that embypy is sending some bad values to the server... probably).

So, this def seems like an issue with embypy, but one that should have been fixed. Make sure that you're on the right version. Here's an example output of my (hand run) test:

>>> #setup
>>> import embypy
>>> conf = {"watching": {}, "auth": {"userid": "xxx", "api_key": "yyy", "device_id": "zzz"}, "address": "https://example.com"}
>>> conn = embypy.Emby(conf['address'], **conf['auth'])
>>> 
>>> embypy.__version__ # make sure that this matches (or is at least '0.6.3.1')
'0.6.3.2'
>>> item = conn.info('209fb14b2f109d7b8f963afc99d72a6f')
>>> item.name
'The Rocky Horror Picture Show'
>>> item.name = 'The Rocky Horror Picture Show (1975)'
>>> item.name
'The Rocky Horror Picture Show (1975)'
>>> item.send()  # first part of the return value of this should be in the 200s
(204, '')
>>> item.update()  # updated the cached version with what's on the server
<Movie 209fb14b2f109d7b8f963afc99d72a6f>
>>> item.name  # name has changed
'The Rocky Horror Picture Show (1975)'
>>>