jonathan-s / django-sockpuppet

Build reactive applications with the django tooling you already know and love.
https://github.com/jonathan-s/django-sockpuppet
MIT License
450 stars 22 forks source link

The example reflex isn't being picked up by consumer.py on Windows #9

Closed DamnedScholar closed 4 years ago

DamnedScholar commented 4 years ago

Description

It seems that consumer.py is unable to find the example reflex provided with this repo. I did some digging and found why.

What I Did

I cloned this repo, installed all dependencies, got the server up and running, and navigated to the test page. Nothing happened when I clicked the increment button, so I checked the log.

Exception inside application: SockpuppetConsumer failed to invoke ExampleReflex#increment, with url http://127.0.0.1:8000/test/, TypeError: 'NoneType' object is not callable
Traceback (most recent call last):
  File "C:\Python36-32\lib\site-packages\asgiref\sync.py", line 176, in main_wrap
    raise exc_info[1]
  File "D:\github\django-sockpuppet\sockpuppet\consumer.py", line 141, in receive_json
    reflex = ReflexClass(self, url=url, element=element, selectors=selectors)
TypeError: 'NoneType' object is not callable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Python36-32\lib\site-packages\channels\sessions.py", line 183, in __call__
    return await self.inner(receive, self.send)
  File "C:\Python36-32\lib\site-packages\channels\middleware.py", line 41, in coroutine_call
    await inner_instance(receive, send)
  File "C:\Python36-32\lib\site-packages\channels\consumer.py", line 59, in __call__
    [receive, self.channel_receive], self.dispatch
  File "C:\Python36-32\lib\site-packages\channels\utils.py", line 51, in await_many_dispatch
    await dispatch(result)
  File "C:\Python36-32\lib\site-packages\asgiref\sync.py", line 269, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "C:\Python36-32\lib\asyncio\tasks.py", line 333, in wait_for
    return (yield from fut)
  File "C:\Python36-32\lib\concurrent\futures\thread.py", line 55, in run
    result = self.fn(*self.args, **self.kwargs)
  File "C:\Python36-32\lib\site-packages\channels\db.py", line 14, in thread_handler
    return super().thread_handler(loop, *args, **kwargs)
  File "C:\Python36-32\lib\site-packages\asgiref\sync.py", line 314, in thread_handler
    return func(*args, **kwargs)
  File "C:\Python36-32\lib\site-packages\channels\consumer.py", line 105, in dispatch
    handler(message)
  File "C:\Python36-32\lib\site-packages\channels\generic\websocket.py", line 60, in websocket_receive
    self.receive(text_data=message["text"])
  File "C:\Python36-32\lib\site-packages\channels\generic\websocket.py", line 125, in receive
    self.receive_json(self.decode_json(text_data), **kwargs)
  File "D:\github\django-sockpuppet\sockpuppet\consumer.py", line 149, in receive_json
    raise SockpuppetError(msg)
sockpuppet.consumer.SockpuppetError: SockpuppetConsumer failed to invoke ExampleReflex#increment, with url http://127.0.0.1:8000/test/, TypeError: 'NoneType' object is not callable

I did a little digging around and discovered that the reflex search algorithm matches the first conditional (which is supposed to look for reflexes.py) in the example app, when it should be the second (for files in reflexes/). After toying around for a bit (and outputting everything in walk(path) to a text file), I remembered that Windows uses backslashes for its paths, and that's why the second conditional never evaluates to true, because it concatenates a comparison string with a forward slash. Even though Python is great at interoperability, a string match doesn't use any of Python's cross-platform goodness. Using os.path.join() fixes this for all platforms.

Unless I'm missing something, the first conditional should look for reflexes.py in filenames, not dirnames, since it's looking for a single file.

I've fixed the code for Windows (and changed the path variable to a portmanteau of "module path" to get it out of the way of the os.path object) in the attached pull request.

jonathan-s commented 4 years ago

Fixed by #10