Skip to content
This repository has been archived by the owner on Jan 11, 2021. It is now read-only.

cigar_example documentation - RuntimeError: Unable to use callback invalid closure/function specified. #71

Closed
sdg9 opened this issue Mar 8, 2014 · 17 comments

Comments

@sdg9
Copy link

sdg9 commented Mar 8, 2014

I'm using Django 1.6.2, django-rest-framework 2.3.12, and python 3.3.4

Running the cigar_example locally errors out when trying to view the swagger documentation at http://127.0.0.1:8000/. http://127.0.0.1:8000/api/cigars/ loads properly (when including trailing slash) and the remainder of the documentation loads properly if I remove the cigars route in cigar_example/restapi/urls.py.

The documentation page gives the error - Unable to read api 'cigars' from path http://127.0.0.1:8000/api-docs/api/cigars (server returned undefined)
The stack trace is below.
[08/Mar/2014 11:59:59] "GET /api-docs/ HTTP/1.1" 200 215
Internal Server Error: /api-docs/api/cigars
Traceback (most recent call last):
File "D:\Development\virtualenv\aws-django\lib\site-packages\django\core\handlers\base.py", line 114, in get_response
response = wrapped_callback(request, _callback_args, *_callback_kwargs)
File "D:\Development\virtualenv\aws-django\lib\site-packages\django\views\generic\base.py", line 69, in view
return self.dispatch(request, _args, *_kwargs)
File "D:\Development\virtualenv\aws-django\lib\site-packages\django\views\decorators\csrf.py", line 57, in wrapped_view
return view_func(_args, *_kwargs)
File "D:\Development\virtualenv\aws-django\lib\site-packages\rest_framework\views.py", line 399, in dispatch
response = self.handle_exception(exc)
File "D:\Development\virtualenv\aws-django\lib\site-packages\rest_framework\views.py", line 396, in dispatch
response = handler(request, _args, *_kwargs)
File "D:\Development\virtualenv\aws-django\lib\site-packages\rest_framework_swagger\views.py", line 84, in get
'apis': generator.generate(apis),
File "D:\Development\virtualenv\aws-django\lib\site-packages\rest_framework_swagger\docgenerator.py", line 21, in generate
'operations': self.get_operations(api),
File "D:\Development\virtualenv\aws-django\lib\site-packages\rest_framework_swagger\docgenerator.py", line 41, in get_operations
for method_introspector in introspector:
File "D:\Development\virtualenv\aws-django\lib\site-packages\rest_framework_swagger\introspectors.py", line 285, in iter
methods = self._resolve_methods()
File "D:\Development\virtualenv\aws-django\lib\site-packages\rest_framework_swagger\introspectors.py", line 294, in _resolve_methods
raise RuntimeError('Unable to use callback invalid closure/function specified.')
RuntimeError: Unable to use callback invalid closure/function specified.
[08/Mar/2014 11:59:59] "GET /api-docs/api/manufacturers HTTP/1.1" 200 3514
[08/Mar/2014 11:59:59] "GET /api-docs/api/custom HTTP/1.1" 200 931
[08/Mar/2014 11:59:59] "GET /api-docs/api/countries HTTP/1.1" 200 2694
[08/Mar/2014 12:00:00] "GET /api-docs/api/cigars HTTP/1.1" 500 122324

@hashstat
Copy link

hashstat commented Apr 1, 2014

The problem is that func_code and func_closure were renamed code and closure in Python 3. Below is a patch that allows the introspection to work with both Python 2.x and 3.x.

--- old/introspectors.py
+++ new/introspectors.py
@@ -287,14 +287,20 @@
             yield ViewSetMethodIntrospector(self, methods[method], method)

     def _resolve_methods(self):
-        if not hasattr(self.pattern.callback, 'func_code') or \
-                not hasattr(self.pattern.callback, 'func_closure') or \
-                not hasattr(self.pattern.callback.func_code, 'co_freevars') or \
-                'actions' not in self.pattern.callback.func_code.co_freevars:
+        callback = self.pattern.callback
+        try:
+            try:
+                closure = callback.func_closure
+            except AttributeError:
+                closure = callback.__closure__
+            try:
+                code = callback.func_code
+            except AttributeError:
+                code = callback.__code__
+            freevars = code.co_freevars
+        except AttributeError:
             raise RuntimeError('Unable to use callback invalid closure/function specified.')
-
-        idx = self.pattern.callback.func_code.co_freevars.index('actions')
-        return self.pattern.callback.func_closure[idx].cell_contents
+        return closure[freevars.index('actions')].cell_contents


 class ViewSetMethodIntrospector(BaseMethodIntrospector):

The 2to3 tool automatically handles renaming the attributes, rendering the inner try-except blocks unnecessary. The code could become:

    def _resolve_methods(self):
        callback = self.pattern.callback
        try:
            closure = callback.func_closure
            freevars = callback.func_code.co_freevars
        except AttributeError:
            raise RuntimeError('Unable to use callback invalid closure/function specified.')
        return closure[freevars.index('actions')].cell_contents

@linuxlewis
Copy link

+1

@jeffself
Copy link

I've updated the _resolve_methods method in my introspectors.py to look like this:

def _resolve_methods(self):
    callback = self.pattern.callback
    try:
        closure = callback.func_closure
        freevars = callback.func_code.co_freevars
    except AttributeError:
        raise RuntimeError('Unable to use callback invalid closure/function specified.')
    return closure[freevars.index('actions')].cell_contents
    idx = self.pattern.callback.__code__.co_freevars.index('actions')
    return self.pattern.callback.__closure__[idx].cell_contents

However, I'm still getting a 'Unable to use callback invalid closure/function specified.' error. I'm running Python 3.4.1. Any thoughts?

@jason-kane
Copy link

Did github mangle your code somehow? The snippet doesn't make very much sense to me.

I'm using (with Python 3.4):

    def _resolve_methods(self):
        callback = self.pattern.callback
        try:
            try:
                closure = callback.func_closure
            except AttributeError:
                closure = callback.__closure__
            try:
                code = callback.func_code
            except AttributeError:
                code = callback.__code__
            freevars = code.co_freevars
        except AttributeError:
            raise RuntimeError('Unable to use callback invalid closure/function specified.')

        return closure[freevars.index('actions')].cell_contents

@jeffself
Copy link

Yeah, not sure what happened there. Here's what I've got:

def _resolve_methods(self):
    callback = self.pattern.callback
    try:
        closure = callback.func_closure
        freevars = callback.func_code.co_freevars
    except AttributeError:
        raise RuntimeError('Unable to use callback invalid closure/function specified.')
    return closure[freevars.index('actions')].cell_contents

Still getting same error message.

@jason-kane
Copy link

As far as I know that is supposed to work but I don't trust the 2to3 black magic. Try the long winded explicit version I posted above.

@jeffself
Copy link

Works! Thanks!

@johansja
Copy link

Thanks for the snippet too. I am wondering if this will be patched into the code someday?

nicodmf added a commit to nicodmf/django-rest-swagger that referenced this issue Aug 30, 2014
Base on the change list here marcgibbons#71, wich resolv my problem
@nielsole
Copy link

nielsole commented Oct 5, 2014

Hey, this worked to let the error message go away, but instead I now get a Value error:
tuple.index(x): x not in tuple
from this line
return closure[freevars.index('actions')].cell_contents
freevars only contains: ('view_func',)
I used the code from @jason-kane .
Did anyone else experience this problem?

@jason-kane
Copy link

Haven't seen that; it looks like there must be something missing in the function it is trying to introspect. 'actions' looks like it comes from DRF itself not the swagger addition. Does the DRF browser work?

@nielsole
Copy link

nielsole commented Oct 6, 2014

I am using Django 1.7 and DRF 2.4.3. The DRF browser works fine.

@jason-kane
Copy link

looks like #123 is biting you. Symptoms are identical to #129

@nielsole
Copy link

nielsole commented Oct 6, 2014

you are right. Did not see them. Thank you. Too bad this repository is not maintained.

@jason-kane
Copy link

I added what looks like a suitable fix to pull request #85 ; I haven't actually tried it against DRF 2.4.3 yet.

@FlogFr
Copy link

FlogFr commented Oct 9, 2014

sorry but still having the issue from installing by pip. Is it merged and updated to pypi ?

@allardhoeve
Copy link

Same here. Doesn't work with Django REST Framework 2.4.3 and Django 1.7.

@ariovistus
Copy link
Contributor

fixed in develop.

nicopace added a commit to nicopace/django-rest-swagger that referenced this issue Oct 27, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants