Exemple #1
0
    def render_examples(self):

        examples_blocks = []
        for example_name in sorted(self.examples.keys()):
            example_response = self.examples[example_name]['response']

            examples_blocks.append(
                normalize_indentation(
                    '''
                "{example_name}": {example_response}
            ''', 0).format(example_name=example_name,
                           example_response=json.dumps(example_response,
                                                       sort_keys=True,
                                                       indent=4)))

        return normalize_indentation(
            '''
            /**
             * Examples for {self.name}
             */
            export const {command_name}Examples = {{
            {examples}
            }}
        ''', 0).format(self=self,
                       command_name=to_camelcase(self.name),
                       examples=normalize_indentation(
                           ',\n\n'.join(examples_blocks), 4))
Exemple #2
0
    def render(self):

        if self.get_bulk_read_field() and self.method != 'get':
            return normalize_indentation(
                '''
            {self.header}
            public {self.camel_name}({self.signature.input}): Observable<X.{self.response.name}> {{
                return this.client
                    .{self.method}<X.{self.response.name}>({self.signature.call_args})
                    .pipe(map(x => x.{bulk_read_field}));
            }}
            ''', 0).format(  # noqa
                    self=self,
                    bulk_read_field=self.get_bulk_read_field(),
                )

        elif self.get_bulk_read_field() or self.method == 'get':
            return normalize_indentation(
                '''
            {self.header}
            public {self.camel_name}({self.signature.input}): Observable<X.{self.response.name}> {{
                return this.client.get<X.{self.response.name}>({self.signature.call_args});
            }}
            ''', 0).format(self=self)  # noqa

        else:
            return normalize_indentation(
                '''
            {self.header}
            public {self.camel_name}({self.signature.input}): Observable<X.{self.response.name}> {{
                return this.client
                    .{self.method}<X.{self.response.name}>({self.signature.call_args})
                    .pipe(filter(x => !_.isEmpty(x)));
            }}
            ''', 0).format(self=self)  # noqa
Exemple #3
0
    def render_facade(self):

        if self.get_bulk_read_field():
            return normalize_indentation(
                '''
                {self.camel_name}({self.signature.input}): Observable<X.{self.response.name}> {{
                    return this.{self.domain_id}Domain.{self.camel_name}({self.signature.call_args_without_path});
                }}
            ''', 0).format(self=self)  # noqa

        elif self.method == 'get':
            return normalize_indentation(
                '''
                {self.camel_name}({self.signature.input}): Observable<X.{self.response.name}> {{
                    return this.{self.domain_id}Domain.{self.camel_name}({self.signature.call_args_without_path});
                }}
            ''', 0).format(self=self)  # noqa

        else:
            return normalize_indentation(
                '''
                {self.camel_name}({self.signature.input}): Observable<X.{self.response.name}> {{
                    return this.{self.domain_id}Domain.{self.camel_name}({self.signature.call_args_without_path});
                }}
            ''', 0).format(self=self)  # noqa
Exemple #4
0
    def render_domain_ts(self, domain, commands):
        blocks = [
            normalize_indentation(
                '''
                {autogenerated_doc}

                /**
                 * {domain.name} Domain
                 */
                import {{ Injectable }} from '@angular/core';
                import {{ filter }} from 'rxjs/operators';
                import {{ Observable }} from 'rxjs';
                import * as _ from 'underscore';

                import {{ HttpService }} from '../../http.service';

                import * as X from './{domain.id}.models';

                @Injectable()
                export class {domain.camel_id}Domain {{
                    constructor(private client: HttpService) {{}}
            ''', 0).format(  # noqa
                    autogenerated_doc=self.AUTOGENERATED_DOC,
                    domain=domain,
                )
        ]
        for command in commands:
            blocks.append(normalize_indentation(command.render(), 4))

        blocks.append('}')

        path = domain.path.join('{}.domain.ts'.format(domain.id))
        with open(path, 'w') as f:
            f.write('\n\n'.join(blocks))
Exemple #5
0
    def render_models_ts(self, domain, commands):

        model_enums = []
        models = []
        for command in commands:
            # -- REQUEST_QUERY
            b, enums = command.request_query.render()
            if b:
                models.append(b)

            if enums:
                model_enums.extend(enums)

            # -- REQUEST_BODY
            b, enums = command.request_body.render()
            if b:
                models.append(b)

            if enums:
                model_enums.extend(enums)

            # -- RESPONSE
            b, enums = command.response.render()
            if b:
                models.append(b)

            if enums:
                model_enums.extend(enums)

        enums_block = ''
        if model_enums:
            sorted_enum_names = sorted(set([e.name for e in model_enums]))

            enums_block = normalize_indentation(
                '''
                import {{ {enums} }} from '../../shared/enums';
            ''', 0).format(enums=', '.join(sorted_enum_names))

        blocks = [
            normalize_indentation(
                '''
                {autogenerated_doc}

                {enums_block}

                /**
                 * {domain_name} Domain Models
                 */
            ''', 0).format(enums_block=enums_block,
                           autogenerated_doc=self.AUTOGENERATED_DOC,
                           domain_name=domain.name),
            *models,
        ]

        path = domain.path.join('{}.models.ts'.format(domain.id))
        with open(path, 'w') as f:
            f.write('\n\n'.join(blocks))
Exemple #6
0
    def render_api_ts(self, commands_by_domain):

        blocks = [
            normalize_indentation(
                '''
                {autogenerated_doc}

                /**
                 * Facade API Service for all domains
                 */
                import {{ Injectable, Injector }} from '@angular/core';
                import {{ Observable }} from 'rxjs';

                import * as X from '../domains/index';

                @Injectable()
                export class APIService {{

                    constructor(private injector: Injector) {{}}

            ''', 0).format(autogenerated_doc=self.AUTOGENERATED_DOC, )
        ]

        for domain in sorted(commands_by_domain.keys(), key=lambda x: x.id):
            commands = commands_by_domain[domain]
            blocks.append(
                normalize_indentation(
                    '''
                /**
                 * {domain.name} domain
                 */
                private _{domain.id}Domain: X.{domain.camel_id}Domain;

                public get {domain.id}Domain(): X.{domain.camel_id}Domain {{
                    if (!this._{domain.id}Domain) {{
                        this._{domain.id}Domain = this.injector.get(X.{domain.camel_id}Domain);
                    }}

                    return this._{domain.id}Domain;
                }}
            ''', 4).format(  # noqa
                        domain=domain, ))

            for command_name in sorted(commands.keys()):
                command = commands[command_name]
                blocks.append(normalize_indentation(command.render_facade(),
                                                    4))

        blocks.append('}')

        path = os.path.join(self.repo.base_path,
                            'projects/client/src/services/api.service.ts')
        with open(path, 'w') as f:
            f.write('\n\n'.join(blocks))
Exemple #7
0
    def test_render_access_ts(self):

        shared_path = str(self.src_dir.mkdir('shared'))
        commands = [
            Mock(render_access=Mock(
                return_value=(
                    'BULK_READ_WHAT: [AccountType.LEARNER, AccountType.MENTOR]'
                ))),
            Mock(render_access=Mock(return_value='BULK_DELETE_THIS: null')),
            Mock(
                render_access=Mock(
                    return_value='CREATE: [AccountType.ADMIN]')),
        ]

        assert os.listdir(shared_path) == []

        self.renderer.render_access_ts(shared_path, commands)

        assert os.listdir(shared_path) == ['access.ts']
        with open(os.path.join(shared_path, 'access.ts'), 'r') as f:
            result = f.read()
            assert result == normalize_indentation('''
                /**
                  * THIS FILE WAS AUTOGENERATED, ALL MANUAL CHANGES CAN BE
                  * OVERWRITTEN
                  */

                import { AccountType } from './enums';

                export const Access = {
                  BULK_READ_WHAT: [AccountType.LEARNER, AccountType.MENTOR],
                  BULK_DELETE_THIS: null,
                  CREATE: [AccountType.ADMIN],
                }
            ''', 0)  # noqa
Exemple #8
0
    def test_render__get_bulk_read_field__get(self):

        self.mocker.patch.object(Command,
                                 'get_bulk_read_field').return_value = 'people'
        command = Command(
            'READ_TASK', {
                'method': 'GET',
                'meta': {
                    'title': 'Read Task',
                    'domain': {
                        'id': 'tasks',
                        'name': 'Tasks Management',
                    }
                },
                'access': {
                    'is_private': True,
                    'access_list': ['LEARNER'],
                },
                'path_conf': {
                    'path': '/tasks/{task_id}',
                    'parameters': [
                        {
                            'name': 'task_id',
                            'type': 'integer',
                        },
                    ]
                },
                'schemas': {
                    'input_query': {
                        'schema': {
                            'hi': 'there'
                        },
                        'uri': ''
                    },
                    'input_body': None,
                    'output': {
                        'schema': {
                            'type': 'object',
                            'required': ['people'],
                            'properties': {
                                'people': {
                                    'type': 'array',
                                },
                            },
                        },
                        'uri': '',
                    },
                },
                'examples': {},
            })

        assert command.render() == normalize_indentation(
            '''
            /**
             * Read Task
             */
            public readTask(taskId: any, params: X.ReadTaskQuery): Observable<X.ReadTaskResponse> {
                return this.client.get<X.ReadTaskResponse>(`/tasks/${taskId}`, { params, authorizationRequired: true });
            }
        ''', 0)  # noqa
    def test_command__default_values(self):

        render = self.mocker.patch.object(AngularClientRenderer, 'render')
        render.return_value = '1.0.19'

        result = self.runner.invoke(command, ['origin', 'super'])

        assert result.exit_code == 0
        assert normalize_indentation(result.output,
                                     0) == normalize_indentation(
                                         '''
                - Successfully rendered and pushed Angular Client version: 1.0.19
            ''', 0)  # noqa
        assert render.call_args_list == [
            call(exclude_domains=(), include_domains=(), only_build=None),
        ]
Exemple #10
0
    def test_render_examples_ts(self):

        paths_path = str(self.domains_dir.mkdir('paths'))
        domain = Domain('paths', 'Path Management')
        commands = [
            Mock(render_examples=Mock(return_value='command 1')),
            Mock(render_examples=Mock(return_value='command 2')),
        ]

        assert os.listdir(paths_path) == []

        self.renderer.render_examples_ts(domain, commands)

        assert os.listdir(paths_path) == ['paths.examples.ts']
        with open(os.path.join(paths_path, 'paths.examples.ts'), 'r') as f:
            assert f.read() == normalize_indentation('''
                /**
                  * THIS FILE WAS AUTOGENERATED, ALL MANUAL CHANGES CAN BE
                  * OVERWRITTEN
                  */

                /**
                 * Path Management Domain Examples
                 */

                command 1

                command 2
            ''', 0)  # noqa
Exemple #11
0
 def header(self):
     return normalize_indentation(
         '''
     /**
      * {self.title}
      */
     ''', 0).format(self=self)
Exemple #12
0
 def render_index_ts(self, domain):
     with open(domain.path.join('index.ts'), 'w') as f:
         f.write(
             normalize_indentation(
                 '''
                 export * from './{domain.id}.domain';
                 export * from './{domain.id}.models';
             ''', 0).format(domain=domain))
Exemple #13
0
    def test_render__numerical(self):

        enum0 = Enum('position', [0, 1])
        enum1 = Enum('position', ['0', '1', '2'])

        assert enum0.render() == normalize_indentation('''
            export enum Position {
                VALUE_0 = 0,
                VALUE_1 = 1,
            }
        ''', 0)
        assert enum1.render() == normalize_indentation('''
            export enum Position {
                VALUE_0 = '0',
                VALUE_1 = '1',
                VALUE_2 = '2',
            }
        ''', 0)
Exemple #14
0
    def test_render(self):

        enum = Enum('age', ['AA', 'BB'])

        assert enum.render() == normalize_indentation('''
            export enum Age {
                AA = 'AA',
                BB = 'BB',
            }
        ''', 0)
    def test_command__makes_the_right_calls(self):

        renderer = self.mocker.patch(  # noqa
            'lily.docs.management.commands.render_angular'
            '.AngularClientRenderer')

        result = self.runner.invoke(command,
                                    ['origin', 'super', '--only_build'])

        assert result.exit_code == 0
        assert normalize_indentation(result.output,
                                     0) == normalize_indentation(
                                         '''
                - Successfully rendered and built Angular Client [NO PUSHING TO REMOTE]
            ''', 0)  # noqa
        assert renderer.call_args_list == [call('origin', 'super')]
        assert renderer.return_value.render.call_args_list == [
            call(exclude_domains=(), include_domains=(), only_build=True),
        ]
Exemple #16
0
    def test_render__removes_duplicates(self):

        enum = Enum('class', ['AA', 'BB', 'AA'])

        assert enum.render() == normalize_indentation('''
            export enum Class {
                AA = 'AA',
                BB = 'BB',
            }
        ''', 0)
Exemple #17
0
    def test_render__starts_from_number(self):

        enum = Enum('quality', ['240p', '720p', '1080p'])

        assert enum.render() == normalize_indentation('''
            export enum Quality {
                VALUE_1080P = '1080p',
                VALUE_240P = '240p',
                VALUE_720P = '720p',
            }
        ''', 0)
Exemple #18
0
    def test_render__sorts_values(self):

        enum = Enum('category', ['XX', 'AA', 'BB'])

        assert enum.render() == normalize_indentation('''
            export enum Category {
                AA = 'AA',
                BB = 'BB',
                XX = 'XX',
            }
        ''', 0)
Exemple #19
0
    def render_examples_ts(self, domain, commands):
        blocks = [
            normalize_indentation(
                '''
                {autogenerated_doc}

                /**
                 * {domain.name} Domain Examples
                 */
            ''', 0).format(  # noqa
                    autogenerated_doc=self.AUTOGENERATED_DOC,
                    domain=domain,
                )
        ]
        for command in commands:
            blocks.append(normalize_indentation(command.render_examples(), 0))

        path = domain.path.join('{}.examples.ts'.format(domain.id))
        with open(path, 'w') as f:
            f.write('\n\n'.join(blocks))
Exemple #20
0
    def test_render__contains_extra_characters(self):

        enum = Enum(
            'content_type',
            ['image/svg+xml', 'video/png', 'audio/ogg-what'])

        assert enum.render() == normalize_indentation('''
            export enum ContentType {
                AUDIO_OGG_WHAT = 'audio/ogg-what',
                IMAGE_SVG_XML = 'image/svg+xml',
                VIDEO_PNG = 'video/png',
            }
        ''', 0)
Exemple #21
0
def command(client_origin, client_prefix, only_build, include_domain,
            exclude_domain):
    """Render Angular Client based on the declared commands."""

    rendered_version = AngularClientRenderer(
        client_origin, client_prefix).render(only_build=only_build,
                                             include_domains=include_domain,
                                             exclude_domains=exclude_domain)

    if only_build:
        click.secho(normalize_indentation(
            '''
            - Successfully rendered and built Angular Client [NO PUSHING TO REMOTE]
        ''', 0),
                    fg='green')  # noqa

    else:
        click.secho(normalize_indentation(
            '''
            - Successfully rendered and pushed Angular Client version: {version}
        '''.format(version=rendered_version), 0),
                    fg='green')  # noqa
Exemple #22
0
    def test_render_index_ts(self):

        paths_path = str(self.domains_dir.mkdir('paths'))

        assert os.listdir(paths_path) == []

        self.renderer.render_index_ts(Domain('paths', 'Path Management'))

        assert os.listdir(paths_path) == ['index.ts']
        with open(os.path.join(paths_path, 'index.ts'), 'r') as f:
            assert f.read() == normalize_indentation('''
                export * from './paths.domain';
                export * from './paths.models';
            ''', 0)
Exemple #23
0
    def test_render_models_ts__without_enums(self):

        paths_path = str(self.domains_dir.mkdir('paths'))
        domain = Domain('paths', 'Path Management')
        commands = [
            Mock(
                request_query=Mock(
                    render=Mock(return_value=['request 1', []])),
                request_body=Mock(
                    render=Mock(return_value=['', []])),
                response=Mock(
                    render=Mock(return_value=['response 1', []])),
            ),
            Mock(
                request_query=Mock(
                    render=Mock(return_value=['request 2', []])),
                request_body=Mock(
                    render=Mock(return_value=['', []])),
                response=Mock(
                    render=Mock(return_value=['response 2', []])),
            ),
        ]

        assert os.listdir(paths_path) == []

        self.renderer.render_models_ts(domain, commands)

        assert os.listdir(paths_path) == ['paths.models.ts']
        with open(os.path.join(paths_path, 'paths.models.ts'), 'r') as f:
            assert f.read() == normalize_indentation('''
                /**
                  * THIS FILE WAS AUTOGENERATED, ALL MANUAL CHANGES CAN BE
                  * OVERWRITTEN
                  */



                /**
                 * Path Management Domain Models
                 */

                request 1

                response 1

                request 2

                response 2
            ''', 0)
Exemple #24
0
    def test_render__post(self):

        command = Command(
            'READ_TASK', {
                'method': 'POST',
                'meta': {
                    'title': 'Create Path',
                    'domain': {
                        'id': 'paths',
                        'name': 'Paths Management',
                    }
                },
                'access': {
                    'is_private': True,
                    'access_list': ['LEARNER'],
                },
                'path_conf': {
                    'path': '/paths/',
                    'parameters': []
                },
                'schemas': {
                    'input_query': None,
                    'input_body': {
                        'schema': {
                            'hi': 'there'
                        },
                        'uri': ''
                    },
                    'output': {
                        'schema': {
                            'hi': 'there'
                        },
                        'uri': ''
                    },
                },
                'examples': {},
            })

        assert command.render() == normalize_indentation(
            '''
            /**
             * Create Path
             */
            public readTask(body: X.ReadTaskBody): Observable<X.ReadTaskResponse> {
                return this.client
                    .post<X.ReadTaskResponse>('/paths/', body, { authorizationRequired: true })
                    .pipe(filter(x => !_.isEmpty(x)));
            }
        ''', 0)  # noqa
Exemple #25
0
    def test_render_facade__get(self):

        command = Command(
            'READ_TASK', {
                'method': 'GET',
                'meta': {
                    'title': 'Read Task',
                    'domain': {
                        'id': 'tasks',
                        'name': 'Tasks Management',
                    }
                },
                'access': {
                    'is_private': True,
                    'access_list': ['LEARNER'],
                },
                'path_conf': {
                    'path': '/tasks/{task_id}',
                    'parameters': [
                        {
                            'name': 'task_id',
                            'type': 'integer',
                        },
                    ]
                },
                'schemas': {
                    'input_query': {
                        'schema': {
                            'hi': 'there'
                        },
                        'uri': ''
                    },
                    'input_body': None,
                    'output': {
                        'schema': {
                            'hi': 'there'
                        },
                        'uri': ''
                    },
                },
                'examples': {},
            })

        assert command.render_facade() == normalize_indentation(
            '''
            readTask(taskId: any, params: X.ReadTaskQuery): Observable<X.ReadTaskResponse> {
                return this.tasksDomain.readTask(taskId, params);
            }
        ''', 0)  # noqa
Exemple #26
0
    def test_render_api_index_ts(self):

        commands_by_domain = {
            Domain('cards', 'Cards Management'): {},
            Domain('recall', 'Recall Management'): {},
            Domain('paths', 'Path Management'): {},
        }

        self.renderer.render_api_index_ts(commands_by_domain)

        assert os.listdir(self.domains_dir) == ['index.ts']
        assert (
            self.domains_dir.join('index.ts').read() ==
            normalize_indentation('''
                export * from './cards/index';
                export * from './paths/index';
                export * from './recall/index';
            ''', 0))  # noqa
Exemple #27
0
    def test_render_facade__post(self):

        command = Command(
            'READ_TASK', {
                'method': 'POST',
                'meta': {
                    'title': 'Create Path',
                    'domain': {
                        'id': 'paths',
                        'name': 'Paths Management',
                    }
                },
                'access': {
                    'is_private': True,
                    'access_list': ['LEARNER'],
                },
                'path_conf': {
                    'path': '/paths/',
                    'parameters': []
                },
                'schemas': {
                    'input_query': None,
                    'input_body': {
                        'schema': {
                            'hi': 'there'
                        },
                        'uri': ''
                    },
                    'output': {
                        'schema': {
                            'hi': 'there'
                        },
                        'uri': ''
                    },
                },
                'examples': {},
            })

        assert command.render_facade() == normalize_indentation(
            '''
            readTask(body: X.ReadTaskBody): Observable<X.ReadTaskResponse> {
                return this.pathsDomain.readTask(body);
            }
        ''', 0)  # noqa
Exemple #28
0
    def test_render_domain_ts(self):

        paths_path = str(self.domains_dir.mkdir('paths'))
        domain = Domain('paths', 'Path Management')
        commands = [
            Mock(render=Mock(return_value='command 1')),
            Mock(render=Mock(return_value='command 2')),
        ]

        assert os.listdir(paths_path) == []

        self.renderer.render_domain_ts(domain, commands)

        assert os.listdir(paths_path) == ['paths.domain.ts']
        with open(os.path.join(paths_path, 'paths.domain.ts'), 'r') as f:
            assert f.read() == normalize_indentation('''
                /**
                  * THIS FILE WAS AUTOGENERATED, ALL MANUAL CHANGES CAN BE
                  * OVERWRITTEN
                  */

                /**
                 * Path Management Domain
                 */
                import { Injectable } from '@angular/core';
                import { filter } from 'rxjs/operators';
                import { Observable } from 'rxjs';
                import * as _ from 'underscore';

                import { HttpService } from '../../http.service';

                import * as X from './paths.models';

                @Injectable()
                export class PathsDomain {
                    constructor(private client: HttpService) {}

                    command 1

                    command 2

                }
            ''', 0)  # noqa
Exemple #29
0
    def test_render_examples(self):

        conf = deepcopy(CONF)
        conf['examples'] = {
            '404 (NOT_FOUND)': {
                'response': {
                    'where': 'here',
                    'error': 'not found',
                    'status': 404,
                },
            },
            '200 (YO)': {
                'response': {
                    'id': 45,
                    'age': 879,
                },
            },
        }

        command = Command('BULK_READ_TASKS', conf)

        assert (remove_white_chars(
            command.render_examples()) == remove_white_chars(
                normalize_indentation(
                    '''
                /**
                 * Examples for BULK_READ_TASKS
                 */
                export const BulkReadTasksExamples = {
                    "200 (YO)": {
                        "age": 879,
                        "id": 45
                    },

                    "404 (NOT_FOUND)": {
                        "error": "not found",
                        "status": 404,
                        "where": "here"
                    }
                }
            ''', 0)))
Exemple #30
0
    def render_access_ts(self, rel_path, all_commands):
        header = normalize_indentation(
            '''
            {autogenerated_doc}
        ''', 0).format(  # noqa
                autogenerated_doc=self.AUTOGENERATED_DOC)

        access_enum = settings.LILY_AUTHORIZER_ACCESS_ENUM_CLASS
        blocks = [
            command.render_access(access_enum) for command in all_commands
        ]
        blocks = '\n'.join([f'  {b},' for b in blocks])

        abs_path = os.path.join(self.repo.base_path, rel_path)
        with open(os.path.join(abs_path, 'access.ts'), 'w') as f:
            f.write(
                f'{header}\n\n'
                f'import {{ { access_enum } }} from \'./enums\';\n\n'  # noqa
                f'export const Access = {{\n'
                f'{blocks}\n'
                '}')