Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connexion throws error: AttributeError: module 'typing' has no attribute 'GenericMeta' while using python 3.7.0 #739

Closed
tniharika opened this issue Oct 30, 2018 · 7 comments

Comments

@tniharika
Copy link

tniharika commented Oct 30, 2018

Description

While using python 3.7.0 with Swagger 2.0 server side python-flask code, we are getting the error "AttributeError: module 'typing' has no attribute 'GenericMeta'"
See line number 12

---Code---
1 def add_procedure(ProcedureItem=None): # noqa: E501
2 """adds an Procedure item
3
4 Adds an item to the system # noqa: E501
5
6 :param ProcedureItem: Procedure item to add
7 :type ProcedureItem: dict | bytes
8
9 :rtype: None
10 """
11 if connexion.request.is_json:
12 ProcedureItem = proc_item.from_dict(connexion.request.get_json()) # noqa: E501 -> Error here
13 return 'do some magic!'

Expected behaviour

Has to process the request and return " do some magic!"

Actual behaviour

throwing error at line 12
"AttributeError: module 'typing' has no attribute 'GenericMeta'"

Steps to reproduce

Download swagger python flask server side code and run with python 3.7

Additional info:

We ran the same file with python 3.6.7 and it worked as expected and returned, "do some magic!"

Output of the commands:
Just read the README document while downloading from swagger

@jmcs
Copy link
Contributor

jmcs commented Oct 30, 2018

Can you post the entire exception?

@cassinaooo
Copy link

cassinaooo commented Nov 9, 2018

Hi @jmcs , here's a complete Trace:

Looks somewhat related to sphinx-doc/sphinx#4490

I think I can get away with editing util.py by myself, will try and post the results.

I also think it is a swagger-code-gen issue, if it is a connexion issue, I could try a PR if you guide me through it.

-------------------- >> begin captured logging << --------------------
flask.app: ERROR: Exception on /v1/orders/1000/invoices [PUT]
Traceback (most recent call last):
  File "/home/lightbringer/scudra/scudra-backend-api/.tox/py37/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/lightbringer/scudra/scudra-backend-api/.tox/py37/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/lightbringer/scudra/scudra-backend-api/.tox/py37/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/lightbringer/scudra/scudra-backend-api/.tox/py37/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File "/home/lightbringer/scudra/scudra-backend-api/.tox/py37/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/lightbringer/scudra/scudra-backend-api/.tox/py37/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/lightbringer/scudra/scudra-backend-api/.tox/py37/lib/python3.7/site-packages/connexion/decorators/decorator.py", line 66, in wrapper
    response = function(request)
  File "/home/lightbringer/scudra/scudra-backend-api/.tox/py37/lib/python3.7/site-packages/connexion/decorators/validation.py", line 122, in wrapper
    response = function(request)
  File "/home/lightbringer/scudra/scudra-backend-api/.tox/py37/lib/python3.7/site-packages/connexion/decorators/validation.py", line 293, in wrapper
    return function(request)
  File "/home/lightbringer/scudra/scudra-backend-api/.tox/py37/lib/python3.7/site-packages/connexion/decorators/decorator.py", line 42, in wrapper
    response = function(request)
  File "/home/lightbringer/scudra/scudra-backend-api/.tox/py37/lib/python3.7/site-packages/connexion/decorators/parameter.py", line 218, in wrapper
    return function(**kwargs)
  File "/home/lightbringer/scudra/scudra-backend-api/api/controllers/orders_controller.py", line 64, in orders_order_id_invoices_put
    api_invoice = Invoice.from_dict(connexion.request.get_json())  # noqa: E501
  File "/home/lightbringer/scudra/scudra-backend-api/api/models/invoice.py", line 69, in from_dict
    return util.deserialize_model(dikt, cls)
  File "/home/lightbringer/scudra/scudra-backend-api/api/util.py", line 110, in deserialize_model
    setattr(instance, attr, _deserialize(value, attr_type))
  File "/home/lightbringer/scudra/scudra-backend-api/api/util.py", line 25, in _deserialize
    elif type(klass) == typing.GenericMeta:
AttributeError: module 'typing' has no attribute 'GenericMeta'
--------------------- >> end captured logging << ---------------------

Thanks a lot for the the lib. :)

@cassinaooo
Copy link

Ok, if anyone have the same problem, you can edit util.py in the following way:

Change

elif type(klass) == typing.GenericMeta:
    if klass.__extra__ == list:
        return _deserialize_list(data, klass.__args__[0])
    if klass.__extra__ == dict:
        return _deserialize_dict(data, klass.__args__[1])

In util.py , to

elif hasattr(klass, '__origin__'):
    if klass.__origin__ == list:
        return _deserialize_list(data, klass.__args__[0])
    if klass.__origin__ == dict:
        return _deserialize_dict(data, klass.__args__[1])

I used some google-fu and found this answer in stack overflow

@dtkav
Copy link
Collaborator

dtkav commented Nov 15, 2018

@willianscfa Is that change backward compatible with python 2.7 / 3.5 / 3.6?

@cassinaooo
Copy link

cassinaooo commented Nov 15, 2018

Unfortunately not @dtka. In python < 3.7 it worked just fine using __extra__. This error appeared for me after I had to upgrade to python 3.7 while maintaining code generated using swagger-code-gen because of a generic type serialization issue. See python/typing#511.

This is a breaking change within the typing module itself. However, the commit associated with the sphinx issue linked above uses a backward compatible solution. They specifically check for the python version before accessing some properties. See tk0miya/sphinx@e2389b4.

Anyway, util.py is a file generated by swagger-code-gen, and any solution (backwards compatible or not), should be implemented by them. See an example: https://github.com/swagger-api/swagger-codegen/blob/master/samples/server/petstore/flaskConnexion/swagger_server/util.py. In any case I think I will problably open an issue there and see if someone could guide me through a first PR. =)

@dtkav
Copy link
Collaborator

dtkav commented Nov 15, 2018

ok awesome. I'll close the issue against connexion for now then.
Thanks for the detailed explanation!

@GioPat
Copy link

GioPat commented Jul 23, 2019

Ok, if anyone have the same problem, you can edit util.py in the following way:

Change

elif type(klass) == typing.GenericMeta:
    if klass.__extra__ == list:
        return _deserialize_list(data, klass.__args__[0])
    if klass.__extra__ == dict:
        return _deserialize_dict(data, klass.__args__[1])

In util.py , to

elif hasattr(klass, '__origin__'):
    if klass.__origin__ == list:
        return _deserialize_list(data, klass.__args__[0])
    if klass.__origin__ == dict:
        return _deserialize_dict(data, klass.__args__[1])

I used some google-fu and found this answer in stack overflow

By using this modification I have problem with python 3.6.5 in deserializing subobjects.
I am trying to find another solution!
Solved with

 elif hasattr(klass, '__origin__'):
     if klass.__origin__ == list or klass.__origin__ == typing.List:
         return _deserialize_list(data, klass.__args__[0])
     if klass.__origin__ == dict:
         return _deserialize_dict(data, klass.__args__[1])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants