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

Can't get the directory structure to resolve #969

Closed
arnmishra opened this issue Jun 6, 2019 · 7 comments
Closed

Can't get the directory structure to resolve #969

arnmishra opened this issue Jun 6, 2019 · 7 comments

Comments

@arnmishra
Copy link

Description

I've spent the better part of a day trying to figure this out. Essentially I have his directory structure:
my_project
-- app.py
-- src
---- init.py
---- views.py
---- models.py
---- swagger
------ api.yml

app.py is just:

from src import connex_app
if __name__ == '__main__':
    connex_app.run(debug=True)

In src/__init__.py, I define the app:

connex_app = connexion.App(__name__, specification_dir='swagger/')
connex_app.add_api('api.yml')
app = connex_app.app

and then in src/views.py, I define the endpoints such as

@app.route('/user/<uuid>/register', methods=['POST'])
def register_account(uuid):
    # implementation here

and finally in my swagger specs (src/swagger/api.yml) I have

swagger: "2.0"

info:
  title: "Api"
  version: "0.1"

basePath: /

paths:
  /user/{id}/register:
    post:
      summary: Register User Account
      description: Registers a User Account
      operationId: src.views.register_account
      parameters:
        - name: id
          in: path
          type: string
          required: true
          description: id of User
      responses:
        200:
          description: The name of the user
          schema:
            type: object
            properties:
              name:
                type: string
                example: John

Expected behaviour

Render correctly

Actual behaviour

I get the following error that claims that register_account isn't in my views. Is it something to do with my directory structure?:

Failed to add operation for POST /user/{uuid}/register
Failed to add operation for POST /user/{uuid}/register
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/connexion/apis/abstract.py", line 206, in add_paths
    self.add_operation(path, method)
  File "/usr/local/lib/python3.7/site-packages/connexion/apis/abstract.py", line 170, in add_operation
    pass_context_arg_name=self.pass_context_arg_name
  File "/usr/local/lib/python3.7/site-packages/connexion/operations/__init__.py", line 8, in make_operation
    return spec.operation_cls.from_spec(spec, *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/connexion/operations/swagger2.py", line 137, in from_spec
    **kwargs
  File "/usr/local/lib/python3.7/site-packages/connexion/operations/swagger2.py", line 96, in __init__
    pass_context_arg_name=pass_context_arg_name
  File "/usr/local/lib/python3.7/site-packages/connexion/operations/abstract.py", line 99, in __init__
    self._resolution = resolver.resolve(self)
  File "/usr/local/lib/python3.7/site-packages/connexion/resolver.py", line 40, in resolve
    return Resolution(self.resolve_function_from_operation_id(operation_id), operation_id)
  File "/usr/local/lib/python3.7/site-packages/connexion/resolver.py", line 66, in resolve_function_from_operation_id
    raise ResolverError(str(e), sys.exc_info())
connexion.exceptions.ResolverError: <ResolverError: module 'src.views' has no attribute 'register_account'>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "app.py", line 2, in <module>
    from src import connex_app
  File "/Users/arnavmishra/Repos/prism/gateway/src/__init__.py", line 11, in <module>
    connex_app.add_api('api.yml')
  File "/usr/local/lib/python3.7/site-packages/connexion/apps/flask_app.py", line 54, in add_api
    api = super(FlaskApp, self).add_api(specification, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/connexion/apps/abstract.py", line 155, in add_api
    options=api_options.as_dict())
  File "/usr/local/lib/python3.7/site-packages/connexion/apis/abstract.py", line 108, in __init__
    self.add_paths()
  File "/usr/local/lib/python3.7/site-packages/connexion/apis/abstract.py", line 213, in add_paths
    self._handle_add_operation_error(path, method, err.exc_info)
  File "/usr/local/lib/python3.7/site-packages/connexion/apis/abstract.py", line 227, in _handle_add_operation_error
    six.reraise(*exc_info)
  File "/usr/local/lib/python3.7/site-packages/six.py", line 693, in reraise
    raise value
  File "/usr/local/lib/python3.7/site-packages/connexion/resolver.py", line 61, in resolve_function_from_operation_id
    return self.function_resolver(operation_id)
  File "/usr/local/lib/python3.7/site-packages/connexion/utils.py", line 87, in get_function_from_name
    module = importlib.import_module(module_name)
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "/Users/arnavmishra/Repos/prism/gateway/src/views.py", line 7, in <module>
    from src.__init__ import app
  File "/Users/arnavmishra/Repos/prism/gateway/src/__init__.py", line 11, in <module>
    connex_app.add_api('api.yml')
  File "/usr/local/lib/python3.7/site-packages/connexion/apps/flask_app.py", line 54, in add_api
    api = super(FlaskApp, self).add_api(specification, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/connexion/apps/abstract.py", line 155, in add_api
    options=api_options.as_dict())
  File "/usr/local/lib/python3.7/site-packages/connexion/apis/abstract.py", line 108, in __init__
    self.add_paths()
  File "/usr/local/lib/python3.7/site-packages/connexion/apis/abstract.py", line 213, in add_paths
    self._handle_add_operation_error(path, method, err.exc_info)
  File "/usr/local/lib/python3.7/site-packages/connexion/apis/abstract.py", line 227, in _handle_add_operation_error
    six.reraise(*exc_info)
  File "/usr/local/lib/python3.7/site-packages/six.py", line 693, in reraise
    raise value
  File "/usr/local/lib/python3.7/site-packages/connexion/resolver.py", line 61, in resolve_function_from_operation_id
    return self.function_resolver(operation_id)
  File "/usr/local/lib/python3.7/site-packages/connexion/utils.py", line 96, in get_function_from_name
    function = deep_getattr(module, attr_path)
  File "/usr/local/lib/python3.7/site-packages/connexion/utils.py", line 55, in deep_getattr
    return functools.reduce(getattr, attr.split('.'), obj)
AttributeError: module 'src.views' has no attribute 'register_account'

Steps to reproduce

the above statements

Additional info:

Output of the commands:

  • python --version
    Python 3.7.3
  • pip show connexion | grep "^Version\:"
    Version: 2.2.0
@drummerwolli
Copy link
Contributor

remove the line @app.route('/user/<uuid>/register', methods=['POST']) from your views file. this is exactly the part which connexion does for you, linking the swagger file (where you defined this endpoint already) to your python function.

@arnmishra
Copy link
Author

Hmm, tried removing that and got the same error.

@drummerwolli
Copy link
Contributor

mh, i copied your example here: https://github.com/drummerwolli/tmp_connexion_issue_969 ... this works for me ... can you maybe post your example somewhere, so we can have a closer look?

@arnmishra
Copy link
Author

arnmishra commented Jun 10, 2019

just cloned your example - for my app I need to import other functions/values from within the src package. i.e. if I want to use a logger, I have to set it up as:

file_handler = logging.FileHandler('app.log')
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)

to add logging, I will have to then import app from __init__.py to views.py. In your example, if I just add from src import app or from src.__init__ import app, it fails however in a non-connexion app, I could run the first command (and probably the second?) and it would work.

If I remove all imports from under src (including any scripts/utils in packages under src), then it renders the API Specs properly (but then the API obviously doesn't work because none of the imports resolve). So it seems like for some reason connexion doesn't allow imports from within the src package.

@arnmishra
Copy link
Author

@drummerwolli any ideas?

@madhurabhogate
Copy link

@drummerwolli : Did you find what was the problem ? I am facing similar issue

@drummerwolli
Copy link
Contributor

sry, i have had no time lately to investigate this 😞

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

4 participants