diff --git a/pyswaggerclient/client.py b/pyswaggerclient/client.py index 8230935..fd33742 100644 --- a/pyswaggerclient/client.py +++ b/pyswaggerclient/client.py @@ -64,8 +64,8 @@ def _update(self): self._update_magic() def _update_magic(self): - self.models = type('Models', (object,), dict(self._create_models())) - self.actions = type('Actions', (object,), dict(self._create_actions())) + setattr(self, 'models', type('Models', (object,), dict(self._create_models()))) + setattr(self, 'actions', type('Actions', (object,), dict(self._create_actions()))) def _create_models(self): for model_name, model in self._app.m.items(): diff --git a/pyswaggerclient/client.py.in b/pyswaggerclient/client.py.in new file mode 100644 index 0000000..b1a8fe4 --- /dev/null +++ b/pyswaggerclient/client.py.in @@ -0,0 +1,55 @@ +from pyswaggerclient import SwaggerClient +from typing import Optional, Union, List, Dict, Any +from dataclasses import dataclass + +{% for model_name, model in client._app.m.items() %} +{% set model_name_slug = slugify(model_name) %} +@dataclass +class {{ classname }}{{ model_name_slug.capitalize() }}Model: + {% for model_property_key, model_property_value in model.properties.items() %} + {% set model_property_key_slug = slugify(model_property_key) %} + {{ model_property_key_slug }}: {{ swagger_type_to_python_type(model_property_value) }} + {% endfor %} +{% endfor %} + +@dataclass +class {{ classname }}Models: + {% for model_name, model in client._app.m.items() %} + {% set model_name_slug = slugify(model_name) %} + {{ model_name_slug }}: {{ classname }}{{ model_name_slug.capitalize() }}Model + {% endfor %} + +{% for action_name, action_value in client._app.op.items() %} +{% set action_name_slug = slugify(action_name.split('!##!')[-1]) %} +class {{ classname }}{{ action_name_slug.capitalize() }}Action: + ''' {{ client._create_doc(action_value) }} ''' + def __init__(self, client): + self.client = client + + def call( + self, + {% for param in action_value.parameters %} + {% set param_name_slug = slugify(param.name) %} + {{ param_name_slug }}: {{ swagger_type_to_python_type(param) }} = None, + {% endfor %} + ) -> {{ swagger_type_to_python_type(list(action_value.responses.values())) }}: + ''' {{ client._create_doc(action_value) }} ''' + return self.client._client_request( + '{{ action_name }}', + {% for param in action_value.parameters %} + {% set param_name_slug = slugify(param.name) %} + {{ param_name_slug }}={{ param_name_slug }}, + {% endfor %} + ) +{% endfor %} + +@dataclass +class {{ classname }}Actions: + {% for action_name, action_value in client._app.op.items() %} + {% set action_name_slug = slugify(action_name.split('!##!')[-1]) %} + {{ action_name_slug }}: {{ classname }}{{ action_name_slug.capitalize() }}Action + {% endfor %} + +class {{ classname }}(SwaggerClient): + models: {{ classname }}Models + actions: {{ classname }}Actions diff --git a/pyswaggerclient/static.py b/pyswaggerclient/static.py new file mode 100644 index 0000000..9617e36 --- /dev/null +++ b/pyswaggerclient/static.py @@ -0,0 +1,56 @@ +''' Usage: +python3 -m pyswaggerclient your_swagger_url > your_client.py + +This has the added benefit of being statically introspectable by i.e. jedi. +''' +import os +import re +from jinja2 import Environment, FileSystemLoader +from pyswaggerclient.client import SwaggerClient + +def slugify(val): + return re.sub(r'[^A-Za-z0-9_]+', '', val).lower() + +type_lookup = { + None: lambda o: 'None', + 'string': lambda o: 'str', + 'number': lambda o: 'float', + 'integer': lambda o: 'int', + 'boolean': lambda o: 'bool', + 'array': lambda o: 'List[{}]'.format(swagger_type_to_python_type(o.items)), + 'object': lambda o: 'Dict[str, {}]'.format(swagger_type_to_python_type(o.additionalProperties or 'Any')), +} +def swagger_type_to_python_type(o): + if type(o) == list: + if len(o) > 1: + return 'Union[{}]'.format(','.join(map(swagger_type_to_python_type, o))) + else: + return swagger_type_to_python_type(o[0]) + elif type(o) == dict: + if 'type' not in o and 'schema' in o: + return swagger_type_to_python_type(o['schema']) + if 'type' not in o and 'content' in o: + return swagger_type_to_python_type(o['content']) + return type_lookup[o['type']](o) + elif type(o) == bool: + return 'Any' + else: + if getattr(o, 'type', None) is None and getattr(o, 'schema', None) is not None: + return swagger_type_to_python_type(getattr(o, 'schema')) + if getattr(o, 'type', None) is None and getattr(o, 'content', None) is not None: + return swagger_type_to_python_type(getattr(o, 'content')) + return type_lookup[o.type](o) + +def generate_static_client(classname, url): + client = SwaggerClient(url) + return Environment( + loader=FileSystemLoader( + os.path.realpath(os.path.dirname(__file__)), + ), + ).get_template('./client.py.in').render( + swagger_type_to_python_type=swagger_type_to_python_type, + list=list, + slugify=slugify, + classname=classname, + client=client, + ) diff --git a/requirements.txt b/requirements.txt index 0fafdc9..edb730d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +Jinja2==2.11.2 pyaml==17.12.1 pyswagger==0.8.37 requests==2.20.0 \ No newline at end of file