diff --git a/scaffold.py b/scaffold.py index e3889e62d..77cc997c5 100755 --- a/scaffold.py +++ b/scaffold.py @@ -2,6 +2,7 @@ import os import click +import jinja2 from prompt_toolkit import ( prompt ) @@ -15,6 +16,12 @@ import boto3 from implementation_coverage import ( get_moto_implementation ) +TEMPLATE_DIR = './template' + + +def print_progress(title, body, color): + click.secho('\t{}\t'.format(title), fg=color, nl=False) + click.echo(body) def select_service_and_operation(): @@ -54,33 +61,77 @@ def select_service_and_operation(): return service_name, operation_name -def create_dirs(service, operation): +def get_lib_dir(service): + return os.path.join('moto', service) + +def get_test_dir(service): + return os.path.join('tests', 'test_{}'.format(service)) + + +def render_teamplte(tmpl_dir, tmpl_filename, context, service, alt_filename=None): + is_test = True if 'test' in tmpl_dir else False + rendered = jinja2.Environment( + loader=jinja2.FileSystemLoader(tmpl_dir) + ).get_template(tmpl_filename).render(context) + + dirname = get_test_dir(service) if is_test else get_lib_dir(service) + filename = alt_filename or os.path.splitext(tmpl_filename)[0] + filepath = os.path.join(dirname, filename) + + if os.path.exists(filepath): + print_progress('skip creating', filepath, 'yellow') + else: + print_progress('creating', filepath, 'green') + with open(filepath, 'w') as f: + f.write(rendered) + + +def initialize_service(service, operation): """create lib and test dirs if not exist """ lib_dir = os.path.join('moto', service) - test_dir = os.path.join('test', 'test_{}'.format(service)) + test_dir = os.path.join('tests', 'test_{}'.format(service)) + + print_progress('Initializing service', service, 'green') + + service_class = boto3.client(service).__class__.__name__ + + tmpl_context = { + 'service': service, + 'service_class': service_class + } + + # initialize service directory if os.path.exists(lib_dir): - return + print_progress('skip creating', lib_dir, 'yellow') + else: + print_progress('creating', lib_dir, 'green') + os.makedirs(lib_dir) - click.secho('\tInitializing service\t', fg='green', nl=False) - click.secho(service) + tmpl_dir = os.path.join(TEMPLATE_DIR, 'lib') + for tmpl_filename in os.listdir(tmpl_dir): + render_teamplte( + tmpl_dir, tmpl_filename, tmpl_context, service + ) - click.secho('\tcraeting\t', fg='green', nl=False) - click.echo(lib_dir) - os.mkdirs(lib_dir) - # do init lib dir - - if not os.path.exists(test_dir): - click.secho('\tcraeting\t', fg='green', nl=False) - click.echo(test_dir) - os.mkdirs(test_dir) - # do init test dir + # initialize test directory + if os.path.exists(test_dir): + print_progress('skip creating', test_dir, 'yellow') + else: + print_progress('creating', test_dir, 'green') + os.makedirs(test_dir) + tmpl_dir = os.path.join(TEMPLATE_DIR, 'test') + for tmpl_filename in os.listdir(tmpl_dir): + alt_filename = 'test_{}.py'.format(service) if tmpl_filename == 'test_service.py.j2' else None + render_teamplte( + tmpl_dir, tmpl_filename, tmpl_context, service, alt_filename + ) @click.command() def main(): service, operation = select_service_and_operation() - create_dirs(service, operation) + initialize_service(service, operation) if __name__ == '__main__': main() diff --git a/template/lib/__init__.py.j2 b/template/lib/__init__.py.j2 new file mode 100644 index 000000000..8e5bf50c7 --- /dev/null +++ b/template/lib/__init__.py.j2 @@ -0,0 +1,7 @@ +from __future__ import unicode_literals +from .models import {{ service }}_backends +from ..core.models import base_decorator + +{{ service }}_backend = {{ service }}_backends['us-east-1'] +mock_{{ service }} = base_decorator({{ service }}_backends) + diff --git a/template/lib/exceptions.py.j2 b/template/lib/exceptions.py.j2 new file mode 100644 index 000000000..2e9a72b1a --- /dev/null +++ b/template/lib/exceptions.py.j2 @@ -0,0 +1,4 @@ +from __future__ import unicode_literals +from moto.core.exceptions import RESTError + + diff --git a/template/lib/models.py.j2 b/template/lib/models.py.j2 new file mode 100644 index 000000000..2a0097c1d --- /dev/null +++ b/template/lib/models.py.j2 @@ -0,0 +1,20 @@ +from __future__ import unicode_literals +import boto3 +from moto.core import BaseBackend, BaseModel + + +class {{ service_class }}Backend(BaseBackend): + def __init__(self, region_name=None): + super({{ service_class }}Backend, self).__init__() + self.region_name = region_name + + def reset(self): + region_name = self.region_name + self.__dict__ = {} + self.__init__(region_name) + + # add methods from here + + +available_regions = boto3.session.Session().get_available_regions("{{ service }}") +{{ service }}_backends = {region: {{ service_class }}Backend for region in available_regions} diff --git a/template/lib/responses.py.j2 b/template/lib/responses.py.j2 new file mode 100644 index 000000000..b27da5b9f --- /dev/null +++ b/template/lib/responses.py.j2 @@ -0,0 +1,15 @@ +from __future__ import unicode_literals +from moto.core.responses import BaseResponse +from .models import {{ service }}_backends + + +class {{ service_class }}Response(BaseResponse): + @property + def {{ service }}_backend(self): + return {{ service }}_backends[self.region] + + # add methods from here + + +# add teampltes from here + diff --git a/template/test/test_server.py.j2 b/template/test/test_server.py.j2 new file mode 100644 index 000000000..f3963a743 --- /dev/null +++ b/template/test/test_server.py.j2 @@ -0,0 +1,16 @@ +from __future__ import unicode_literals + +import sure # noqa + +import moto.server as server +from moto import mock_{{ service }} + +''' +Test the different server responses +''' + +@mock_{{ service }} +def test_{{ service }}_list(): + backend = server.create_backend_app("{{ service }}") + test_client = backend.test_client() + # do test diff --git a/template/test/test_service.py.j2 b/template/test/test_service.py.j2 new file mode 100644 index 000000000..076f92e27 --- /dev/null +++ b/template/test/test_service.py.j2 @@ -0,0 +1,11 @@ +from __future__ import unicode_literals + +import boto3 +import sure # noqa +from moto import mock_{{ service }} + + +@mock_{{ service }} +def test_list(): + # do test + pass