mirror of
https://github.com/LukeHagar/connexion.git
synced 2025-12-07 12:27:46 +00:00
Provide CLI support for runnning specifications
This commit is contained in:
56
connexion/cli.py
Normal file
56
connexion/cli.py
Normal file
@@ -0,0 +1,56 @@
|
||||
import logging
|
||||
import sys
|
||||
from os import path
|
||||
|
||||
import click
|
||||
from connexion import App
|
||||
|
||||
from clickclick import AliasedGroup
|
||||
|
||||
main = AliasedGroup(context_settings=dict(help_option_names=[
|
||||
'-h', '--help']))
|
||||
|
||||
|
||||
@main.command()
|
||||
@click.argument('spec_file')
|
||||
@click.argument('base_path', required=False)
|
||||
@click.option('--port', '-p', default=5000, type=int, help='Port to listen.')
|
||||
@click.option('--server', '-s', default='gevent',
|
||||
type=click.Choice(['gevent', 'tornado']),
|
||||
help='Which WSGI server to use.')
|
||||
@click.option('--hide-spec',
|
||||
help='Hides the API spec in JSON format which is by default available at `/swagger.json`.',
|
||||
is_flag=True, default=True)
|
||||
@click.option('--hide-swagger-ui',
|
||||
help='Hides the the Swagger UI which is by default available at `/ui`.',
|
||||
is_flag=True, default=True)
|
||||
@click.option('--swagger-ui-url', metavar='URL',
|
||||
help='Personalize what URL path the Swagger UI will be mounted.')
|
||||
@click.option('--swagger-ui-from', metavar='PATH',
|
||||
help='Path to a customized Swagger UI dashboard.')
|
||||
@click.option('--auth-all-paths',
|
||||
help='Enable authentication to paths not defined in the spec.',
|
||||
is_flag=True, default=False)
|
||||
@click.option('--debug', '-d', help='Show debugging information.',
|
||||
is_flag=True, default=False)
|
||||
def run(spec_file, base_path, port, server, debug):
|
||||
"""
|
||||
Runs a server using the passed OpenAPI/Swagger 2.0 Specification file.
|
||||
|
||||
Possible arguments:
|
||||
|
||||
- SPEC_FILE: specification file of the API to run.
|
||||
|
||||
- BASE_PATH (optional): filesystem path from where to import the API handlers.
|
||||
"""
|
||||
logging_level = logging.ERROR
|
||||
if debug:
|
||||
logging_level = logging.DEBUG
|
||||
logging.basicConfig(level=logging_level)
|
||||
|
||||
sys.path.insert(1, path.abspath(base_path or '.'))
|
||||
|
||||
app = App(__name__)
|
||||
app.add_api(path.abspath(spec_file))
|
||||
click.echo('Running at http://localhost:{}/...'.format(port))
|
||||
app.run(port=port, server=server)
|
||||
@@ -20,7 +20,6 @@ import string
|
||||
import flask
|
||||
import werkzeug.wrappers
|
||||
|
||||
|
||||
PATH_PARAMETER = re.compile(r'\{([^}]*)\}')
|
||||
|
||||
# map Swagger type to flask path converter
|
||||
|
||||
@@ -5,3 +5,4 @@ requests>=2.9.1
|
||||
six>=1.7
|
||||
strict-rfc3339>=0.6
|
||||
swagger_spec_validator>=2.0.2
|
||||
clickclick>=1.1
|
||||
|
||||
3
setup.py
3
setup.py
@@ -88,5 +88,6 @@ setup(
|
||||
'Topic :: Software Development :: Libraries :: Application Frameworks'
|
||||
],
|
||||
include_package_data=True, # needed to include swagger-ui (see MANIFEST.in)
|
||||
|
||||
entry_points={'console_scripts': ['connexion = connexion.cli:main',
|
||||
'cnx = connexion.cli:main']}
|
||||
)
|
||||
|
||||
@@ -287,5 +287,3 @@ def test_args_kwargs(simple_app):
|
||||
resp = app_client.get('/v1.0/query-params-as-kwargs?foo=a&bar=b')
|
||||
assert resp.status_code == 200
|
||||
assert json.loads(resp.data.decode()) == {'foo': 'a'}
|
||||
|
||||
|
||||
|
||||
52
tests/test_cli.py
Normal file
52
tests/test_cli.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import logging
|
||||
|
||||
from click.testing import CliRunner
|
||||
from connexion import App, __version__
|
||||
from connexion.cli import main
|
||||
|
||||
import pytest
|
||||
from conftest import FIXTURES_FOLDER
|
||||
from mock import MagicMock
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def mock_app_run(monkeypatch):
|
||||
test_server = MagicMock(wraps=App(__name__))
|
||||
test_server.run = MagicMock(return_value=True)
|
||||
test_app = MagicMock(return_value=test_server)
|
||||
monkeypatch.setattr('connexion.cli.App', test_app)
|
||||
return test_server
|
||||
|
||||
|
||||
def test_run_missing_spec():
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main, ['run'], catch_exceptions=False)
|
||||
assert "Missing argument" in result.output
|
||||
|
||||
|
||||
def test_run_simple_spec(mock_app_run):
|
||||
spec_file = str(FIXTURES_FOLDER / 'simple/swagger.yaml')
|
||||
default_port = 5000
|
||||
default_server = 'gevent'
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main,
|
||||
['run', spec_file],
|
||||
catch_exceptions=False)
|
||||
|
||||
mock_app_run.run.assert_called_with(port=default_port, server=default_server)
|
||||
assert 'Running at' in result.output
|
||||
|
||||
|
||||
def test_run_in_debug_mode(mock_app_run, monkeypatch):
|
||||
spec_file = str(FIXTURES_FOLDER / 'simple/swagger.yaml')
|
||||
|
||||
logging_config = MagicMock(name='connexion.cli.logging.basicConfig')
|
||||
monkeypatch.setattr('connexion.cli.logging.basicConfig',
|
||||
logging_config)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main,
|
||||
['run', spec_file, '-d'],
|
||||
catch_exceptions=False)
|
||||
|
||||
logging_config.assert_called_with(level=logging.DEBUG)
|
||||
Reference in New Issue
Block a user