diff options
author | Aleksandr Mishchenko <AMishchenko@luxoft.com> | 2020-03-27 01:32:46 +0100 |
---|---|---|
committer | Aleksandr Mishchenko <AMishchenko@luxoft.com> | 2020-03-27 01:32:46 +0100 |
commit | cdc374e39c4eec6e529db16fec28c3d21c4be60e (patch) | |
tree | 41f40d9f2eada1612544399e46322891a813af0b | |
parent | ede8a54d8f35cbb6a7985a1e04a87a2b842fe5cb (diff) | |
download | sdl_ios-cdc374e39c4eec6e529db16fec28c3d21c4be60e.tar.gz |
reserved keywords
-rw-r--r-- | generator/generator.py | 77 | ||||
m--------- | generator/rpc_spec | 0 | ||||
-rw-r--r-- | generator/test/test_enums.py | 10 | ||||
-rw-r--r-- | generator/test/test_functions.py | 8 | ||||
-rw-r--r-- | generator/test/test_structs.py | 22 | ||||
-rw-r--r-- | generator/transformers/common_producer.py | 41 | ||||
-rw-r--r-- | generator/transformers/enums_producer.py | 10 | ||||
-rw-r--r-- | generator/transformers/functions_producer.py | 13 | ||||
-rw-r--r-- | generator/transformers/structs_producer.py | 11 |
9 files changed, 137 insertions, 55 deletions
diff --git a/generator/generator.py b/generator/generator.py index 058484645..8d2a8d63d 100644 --- a/generator/generator.py +++ b/generator/generator.py @@ -244,35 +244,66 @@ class Generator: self.logger.info('Parser type: %s, version %s,\tGenerator version %s', basename(getfile(Parser().__class__)), parser_origin, generator_origin) + def get_file_content(self, file_name: Path) -> list: + """ + + :param file_name: + :return: + """ + try: + with file_name.open('r') as file: + content = file.readlines() + return content + except FileNotFoundError as message1: + self.logger.error(message1) + return [] + + def get_key_words(self, file_name=ROOT.joinpath('rpc_spec/RpcParser/RESERVED_KEYWORDS')): + """ + :param file_name: + :return: + """ + content = self.get_file_content(file_name) + content = tuple(map(lambda e: re.sub(r'\n', r'', e).strip().casefold(), content)) + try: + start_index = content.index('# ios library') + content = content[start_index + 1:len(content)] + content = tuple(filter(lambda e: not re.search(r'^#+\s+.+|^$', e), content)) + self.logger.debug('key_words: %s', ', '.join(content)) + return content + except (IndexError, ValueError, StopIteration) as error1: + self.logger.error('Error while getting key_words, %s %s', type(error1).__name__, error1) + return [] + def get_paths(self, file_name: Path = ROOT.joinpath('paths.ini')): """ Getting and validating parent classes names :param file_name: path to file with container :return: namedtuple with container to key elements """ - data = OrderedDict() - try: - with file_name.open('r') as file: - for line in file: - if line.startswith('#'): - self.logger.warning('commented property %s, which will be skipped', line.strip()) - continue - if re.match(r'^(\w+)\s?=\s?(.+)', line): - if len(line.split('=')) > 2: - self.logger.critical('can not evaluate value, too many separators %s', str(line)) - sys.exit(1) - name, var = line.partition('=')[::2] - if name.strip() in data: - self.logger.critical('duplicate key %s', name) - sys.exit(1) - data[name.strip().lower()] = var.strip() - except FileNotFoundError as message1: - self.logger.critical(message1) + content = self.get_file_content(file_name) + if not content: + self.logger.critical('%s not found', file_name) sys.exit(1) + data = OrderedDict() + + for line in content: + if line.startswith('#'): + self.logger.warning('commented property %s, which will be skipped', line.strip()) + continue + if re.match(r'^(\w+)\s?=\s?(.+)', line): + if len(line.split('=')) > 2: + self.logger.critical('can not evaluate value, too many separators %s', str(line)) + sys.exit(1) + name, var = line.partition('=')[::2] + if name.strip() in data: + self.logger.critical('duplicate key %s', name) + sys.exit(1) + data[name.strip().lower()] = var.strip() missed = list(set(self.paths_named._fields) - set(data.keys())) if missed: - self.logger.critical('in %s missed fields: %s ', file, str(missed)) + self.logger.critical('in %s missed fields: %s ', content, str(missed)) sys.exit(1) return self.paths_named(**data) @@ -439,13 +470,15 @@ class Generator: filtered, names = self.filter_pattern(interface, args.regex_pattern) tasks = [] - functions_transformer = FunctionsProducer(paths, names) + key_words = self.get_key_words() + + functions_transformer = FunctionsProducer(paths, names, key_words) if args.enums and filtered.enums: tasks.append(self.process_main(args.skip, args.overwrite, filtered.enums, - EnumsProducer(paths.enum_class))) + EnumsProducer(paths.enum_class, key_words))) if args.structs and filtered.structs: tasks.append(self.process_main(args.skip, args.overwrite, filtered.structs, - StructsProducer(paths.struct_class, names))) + StructsProducer(paths.struct_class, names, key_words))) if args.functions and filtered.functions: tasks.append(self.process_main(args.skip, args.overwrite, filtered.functions, functions_transformer)) tasks.append(self.process_function_name(args.skip, args.overwrite, interface.functions, diff --git a/generator/rpc_spec b/generator/rpc_spec -Subproject bf14662066e3d9c2e7b32b56f1fa8e9dad8dceb +Subproject c5132e0016cf34b30fec2a2687c59cbfd44c543 diff --git a/generator/test/test_enums.py b/generator/test/test_enums.py index 912dafe30..b3a5a7f42 100644 --- a/generator/test/test_enums.py +++ b/generator/test/test_enums.py @@ -1,6 +1,11 @@ from collections import OrderedDict from unittest import TestCase +try: + from generator import Generator +except ImportError as error: + from generator.generator import Generator + from model.enum import Enum from model.enum_element import EnumElement from transformers.enums_producer import EnumsProducer @@ -20,8 +25,9 @@ class TestEnumsProducer(TestCase): def setUp(self): self.maxDiff = None + key_words = Generator().get_key_words() - self.producer = EnumsProducer('SDLEnum') + self.producer = EnumsProducer('SDLEnum', key_words) def test_FunctionID(self): """ @@ -65,7 +71,7 @@ class TestEnumsProducer(TestCase): expected['name'] = 'SDLTextFieldName' expected['imports'] = {'.h': {'SDLEnum'}, '.m': {'SDLEnum'}} expected['params'] = ( - self.producer.param_named(description=[], name='Success', origin='SUCCESS', since=None), + self.producer.param_named(description=[], name='SuccessParam', origin='SUCCESS_PARAM', since=None), self.producer.param_named(description=[], name='MainField1', origin='mainField1', since=None), self.producer.param_named(description=[], name='H264', origin='H264', since=None), self.producer.param_named(description=[], name='UnsupportedRequest', origin='UNSUPPORTED_REQUEST', diff --git a/generator/test/test_functions.py b/generator/test/test_functions.py index 44af42c7e..af858d5b8 100644 --- a/generator/test/test_functions.py +++ b/generator/test/test_functions.py @@ -2,6 +2,11 @@ import re from collections import namedtuple, OrderedDict from unittest import TestCase +try: + from generator import Generator +except ImportError as error: + from generator.generator import Generator + from model.array import Array from model.boolean import Boolean from model.enum import Enum @@ -29,6 +34,7 @@ class TestFunctionsProducer(TestCase): def setUp(self): self.maxDiff = None + key_words = Generator().get_key_words() Paths = namedtuple('Paths', 'request_class response_class notification_class function_names parameter_names') paths = Paths(request_class='SDLRPCRequest', @@ -38,7 +44,7 @@ class TestFunctionsProducer(TestCase): parameter_names='SDLRPCParameterNames') names = ('FileType', 'Language', 'SyncMsgVersion', 'TemplateColorScheme', 'TTSChunk', 'Choice') - self.producer = FunctionsProducer(paths, names) + self.producer = FunctionsProducer(paths, names, key_words) def test_process_function_name(self): """ diff --git a/generator/test/test_structs.py b/generator/test/test_structs.py index 838e13254..9ddd8fef9 100644 --- a/generator/test/test_structs.py +++ b/generator/test/test_structs.py @@ -1,6 +1,11 @@ from collections import OrderedDict from unittest import TestCase +try: + from generator import Generator +except ImportError as error: + from generator.generator import Generator + from model.integer import Integer from model.param import Param from model.string import String @@ -22,8 +27,9 @@ class TestStructsProducer(TestCase): def setUp(self): self.maxDiff = None + key_words = Generator().get_key_words() - self.producer = StructsProducer('SDLRPCStruct', ['Image']) + self.producer = StructsProducer('SDLRPCStruct', ['Image'], key_words) def test_CloudAppProperties(self): """ @@ -71,19 +77,19 @@ class TestStructsProducer(TestCase): expected['imports'] = {'.h': {'enum': {'SDLRPCStruct'}, 'struct': set()}, '.m': set()} expected['params'] = ( self.producer.param_named( - constructor_argument='touchEventId', constructor_argument_override=None, - constructor_prefix='TouchEventId', deprecated=False, + constructor_argument='idParam', constructor_argument_override=None, + constructor_prefix='IdParam', deprecated=False, description=['{"default_value": null, "max_value": 9, "min_value": 0}'], for_name='object', - mandatory=True, method_suffix='TouchEventId', modifier='strong', of_class='NSNumber.class', - origin='touchEventId', since=None, type_native='UInt8', type_sdl='NSNumber<SDLUInt> *'),) + mandatory=True, method_suffix='IdParam', modifier='strong', of_class='NSNumber.class', + origin='idParam', since=None, type_native='UInt8', type_sdl='NSNumber<SDLUInt> *'),) argument = [ - self.producer.argument_named(variable='touchEventId', deprecated=False, - constructor_argument='@(touchEventId)', origin='touchEventId')] + self.producer.argument_named(variable='idParam', deprecated=False, + constructor_argument='@(idParam)', origin='idParam')] expected['constructors'] = (self.producer.constructor_named( all=argument, arguments=argument, deprecated=False, self='', - init='TouchEventId:(UInt8)touchEventId'),) + init='IdParam:(UInt8)idParam'),) actual = self.producer.transform(item) self.assertDictEqual(expected, actual) diff --git a/generator/transformers/common_producer.py b/generator/transformers/common_producer.py index 3b2adab76..4719a48e6 100644 --- a/generator/transformers/common_producer.py +++ b/generator/transformers/common_producer.py @@ -5,7 +5,7 @@ import json import logging import re import textwrap -from abc import ABC +from abc import ABC, abstractmethod from collections import OrderedDict, namedtuple from model.array import Array @@ -24,10 +24,10 @@ class InterfaceProducerCommon(ABC): All Enums/Structs/Functions Producer are inherited from this class and using features of it """ - def __init__(self, container_name, names=()): + def __init__(self, names=(), key_words=()): self.logger = logging.getLogger(self.__class__.__name__) - self.container_name = container_name self.names = list(map(lambda e: self.replace_sync(e), names)) + self.key_words = key_words self.param_named = namedtuple('param_named', 'origin constructor_argument constructor_prefix deprecated mandatory since ' 'method_suffix of_class type_native type_sdl modifier for_name description ' @@ -35,6 +35,11 @@ class InterfaceProducerCommon(ABC): self.constructor_named = namedtuple('constructor', 'init self arguments all deprecated') self.argument_named = namedtuple('argument', 'origin constructor_argument variable deprecated') + @property + @abstractmethod + def container_name(self): + pass + def transform(self, item: (Enum, Function, Struct), render: dict) -> dict: """ Main entry point for transforming each Enum/Function/Struct into output dictionary, @@ -55,9 +60,9 @@ class InterfaceProducerCommon(ABC): render['params'] = OrderedDict() for param in getattr(item, self.container_name).values(): - param.name = self.replace_sync(param.name) - if param.name.lower() == 'id': - param.name = self.minimize_first(item.name) + self.title(param.name) + # if param.name.lower() == 'id': + # param.name = self.minimize_first(item.name) + self.title(param.name) + param.name = self.replace_keywords(param.name) render['params'][param.name] = self.extract_param(param) if isinstance(item, (Struct, Function)): self.extract_imports(param, render['imports']) @@ -68,13 +73,29 @@ class InterfaceProducerCommon(ABC): render['params'] = tuple(render['params'].values()) return render + def replace_keywords(self, name: str = '') -> str: + """ + if :param name in self.key_words, :return: name += 'Param' + :param name: string with item name + """ + if name.casefold() in self.key_words: + origin = name + if name.isupper(): + name += '_PARAM' + else: + name += 'Param' + self.logger.debug('Replacing %s with %s', origin, name) + return self.replace_sync(name) + @staticmethod - def replace_sync(name: str = '') -> str: + def replace_sync(name): """ :param name: string with item name - :return: string with replaced 'sync' to 'sdl' + :return: string with replaced 'sync' to 'Sdl' """ - return re.sub(r'^([sS])ync(.+)$', r'\1dl\2', name) + if name: + name = re.sub(r'^([sS])ync(.+)$', r'\1dl\2', name) + return name def extract_imports(self, param: Param, imports: dict): """ @@ -226,7 +247,7 @@ class InterfaceProducerCommon(ABC): :return: dictionary with evaluated output types """ if hasattr(instance, 'name'): - instance.name = self.replace_sync(instance.name) + instance.name = self.replace_keywords(instance.name) data = OrderedDict() if isinstance(instance, Enum): data['for_name'] = 'enum' diff --git a/generator/transformers/enums_producer.py b/generator/transformers/enums_producer.py index e9f1c71dd..cd44a640d 100644 --- a/generator/transformers/enums_producer.py +++ b/generator/transformers/enums_producer.py @@ -15,13 +15,17 @@ class EnumsProducer(InterfaceProducerCommon): Enums transformer """ - def __init__(self, enum_class): - super(EnumsProducer, self).__init__( - container_name='elements') + def __init__(self, enum_class, key_words): + super(EnumsProducer, self).__init__(key_words=key_words) + self._container_name = 'elements' self.enum_class = enum_class self.logger = logging.getLogger(self.__class__.__name__) self.param_named = namedtuple('param_named', 'origin description name since') + @property + def container_name(self): + return self._container_name + def transform(self, item: Enum, render: dict = None) -> dict: """ Main entry point for transforming each Enum into output dictionary, diff --git a/generator/transformers/functions_producer.py b/generator/transformers/functions_producer.py index bad4d0f0f..8eaf5fbc4 100644 --- a/generator/transformers/functions_producer.py +++ b/generator/transformers/functions_producer.py @@ -14,10 +14,9 @@ class FunctionsProducer(InterfaceProducerCommon): Functions transformer """ - def __init__(self, paths, names): - super(FunctionsProducer, self).__init__( - container_name='params', - names=names) + def __init__(self, paths, names, key_words): + super(FunctionsProducer, self).__init__(names=names, key_words=key_words) + self._container_name = 'params' self.request_class = paths.request_class self.response_class = paths.response_class self.notification_class = paths.notification_class @@ -26,6 +25,10 @@ class FunctionsProducer(InterfaceProducerCommon): self.logger = logging.getLogger(self.__class__.__name__) self.common_names = namedtuple('common_names', 'name origin description since') + @property + def container_name(self): + return self._container_name + def transform(self, item: Function, render: dict = None) -> dict: """ Main entry point for transforming each Enum/Function/Struct into output dictionary, @@ -68,7 +71,7 @@ class FunctionsProducer(InterfaceProducerCommon): """ render = OrderedDict() for item in items.values(): - tmp = {'name': self.title(self.replace_sync(item.name)), + tmp = {'name': self.title(self.replace_keywords(item.name)), 'origin': item.name, 'description': self.extract_description(item.description), 'since': item.since} diff --git a/generator/transformers/structs_producer.py b/generator/transformers/structs_producer.py index beb652a3a..154d34f81 100644 --- a/generator/transformers/structs_producer.py +++ b/generator/transformers/structs_producer.py @@ -14,13 +14,16 @@ class StructsProducer(InterfaceProducerCommon): Structs transformer """ - def __init__(self, struct_class, enum_names): - super(StructsProducer, self).__init__( - container_name='members', - names=enum_names) + def __init__(self, struct_class, enum_names, key_words): + super(StructsProducer, self).__init__(names=enum_names, key_words=key_words) + self._container_name = 'members' self.struct_class = struct_class self.logger = logging.getLogger(self.__class__.__name__) + @property + def container_name(self): + return self._container_name + def transform(self, item: Struct, render: dict = None) -> dict: """ Main entry point for transforming each Enum/Function/Struct into output dictionary, |