summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksandr Mishchenko <AMishchenko@luxoft.com>2020-03-18 20:39:00 +0100
committerAleksandr Mishchenko <AMishchenko@luxoft.com>2020-03-18 20:39:00 +0100
commita94c956876980df6680ffe78bd3f268351f39442 (patch)
treefd6eb07c41564b3a991b8b096e557bd67359e389
parent66e1fbab4c5c601b0c7b105aceed067bcd1b8abc (diff)
downloadsdl_ios-a94c956876980df6680ffe78bd3f268351f39442.tar.gz
Apply suggestions from code review
-rw-r--r--generator/generator.py136
-rw-r--r--generator/templates/base_struct_function.h2
-rw-r--r--generator/templates/base_struct_function.m4
-rw-r--r--generator/templates/description.jinja3
-rw-r--r--generator/templates/description_param.jinja1
-rw-r--r--generator/templates/enums/template.h3
-rw-r--r--generator/templates/enums/template_numeric.h10
-rw-r--r--generator/templates/functions/template.h1
-rw-r--r--generator/templates/functions/template.m1
-rw-r--r--generator/templates/structs/template.h1
-rw-r--r--generator/templates/structs/template.m1
-rw-r--r--generator/test/runner.py4
-rwxr-xr-xgenerator/test/test_CodeFormatAndQuality.py21
-rw-r--r--generator/test/test_enums.py9
-rw-r--r--generator/test/test_functions.py131
-rw-r--r--generator/test/test_structs.py47
-rw-r--r--generator/transformers/common_producer.py173
-rw-r--r--generator/transformers/enums_producer.py20
-rw-r--r--generator/transformers/functions_producer.py63
-rw-r--r--generator/transformers/generate_error.py12
-rw-r--r--generator/transformers/structs_producer.py12
21 files changed, 371 insertions, 284 deletions
diff --git a/generator/generator.py b/generator/generator.py
index 96901bbe4..fbef269e7 100644
--- a/generator/generator.py
+++ b/generator/generator.py
@@ -41,7 +41,7 @@ class Generator:
This class contains only technical features, as follow:
- parsing command-line arguments, or evaluating required container interactively;
- calling parsers to get Model from xml;
- - calling producers to transform initial Model to dict used in jinja2 templates
+ - calling producers to transform initial Model to dict used in Jinja2 templates
Not required to be covered by unit tests cause contains only technical features.
"""
@@ -53,20 +53,30 @@ class Generator:
self.paths_named = namedtuple('paths_named', 'enum_class struct_class request_class response_class '
'notification_class function_names parameter_names')
+ _version = '1.0.0'
+
@property
- def output_directory(self) -> Path:
+ def get_version(self) -> str:
+ """
+ version of the entire generator
+ :return: current entire generator version
"""
+ return self._version
- :return:
+ @property
+ def output_directory(self) -> Path:
+ """
+ Getter for output directory
+ :return: output directory Path
"""
return self._output_directory
@output_directory.setter
- def output_directory(self, output_directory):
+ def output_directory(self, output_directory: str):
"""
-
- :param output_directory:
- :return:
+ Setting and validating output directory
+ :param output_directory: path to output directory
+ :return: None
"""
if output_directory.startswith('/'):
path = Path(output_directory).absolute().resolve()
@@ -84,17 +94,17 @@ class Generator:
@property
def env(self) -> Environment:
"""
-
- :return:
+ Getter for Jinja2 instance
+ :return: initialized Jinja2 instance
"""
return self._env
@env.setter
- def env(self, paths):
+ def env(self, paths: list):
"""
-
- :param paths:
- :return:
+ Initiating Jinja2 instance
+ :param paths: list with paths to all Jinja2 templates
+ :return: None
"""
loaders = list(filter(lambda l: Path(l).exists(), paths))
if not loaders:
@@ -107,27 +117,19 @@ class Generator:
self._env.globals['year'] = date.today().year
@staticmethod
- def title(name):
- """
-
- :param name:
- :return:
+ def title(name: str):
"""
- return name[:1].upper() + name[1:]
-
- @property
- def get_version(self):
- """
-
- :return:
+ Capitalizing only first character in string. Using for appropriate filter in Jinja2
+ :param name: string to be capitalized first character
+ :return: initial parameter with capitalized first character
"""
- return Common.version
+ return Common.title(name)
def config_logging(self, verbose):
"""
-
- :param verbose:
- :return:
+ Configuring logging for all application
+ :param verbose: if True setting logging.DEBUG else logging.ERROR
+ :return: None
"""
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter(fmt='%(asctime)s.%(msecs)03d - %(levelname)s - %(message)s',
@@ -147,8 +149,8 @@ class Generator:
def get_parser(self):
"""
- Parsing command-line arguments, or evaluating required container interactively.
- :return: an instance of argparse.ArgumentParser
+ Parsing and evaluating command-line arguments
+ :return: object with parsed and validated CLI arguments
"""
if len(sys.argv) == 2 and sys.argv[1] in ('-v', '--version'):
print(self.get_version)
@@ -174,11 +176,11 @@ class Generator:
help='only elements matched with defined regex pattern will be parsed and generated')
parser.add_argument('--verbose', action='store_true', help='display additional details like logs etc')
parser.add_argument('-e', '--enums', required=False, action='store_true',
- help='all enums will be generated, if present')
+ help='if present, all enums will be generated')
parser.add_argument('-s', '--structs', required=False, action='store_true',
- help='all structs will be generated, if present')
+ help='if present, all structs will be generated')
parser.add_argument('-m', '-f', '--functions', required=False, action='store_true',
- help='all functions will be generated, if present')
+ help='if present, all functions will be generated')
parser.add_argument('-y', '--overwrite', action='store_true',
help='force overwriting of existing files in output directory, ignore confirmation message')
parser.add_argument('-n', '--skip', action='store_true',
@@ -220,11 +222,11 @@ class Generator:
return args
def versions_compatibility_validating(self):
- """version of generator script requires the same or lesser version of parser script.
+ """
+ Version of generator script requires the same or lesser version of parser script.
if the parser script needs to fix a bug (and becomes, e.g. 1.0.1) and the generator script stays at 1.0.0.
As long as the generator script is the same or greater major version, it should be parsable.
This requires some level of backward compatibility. E.g. they have to be the same major version.
-
"""
regex = r'(\d+\.\d+).(\d)'
@@ -245,8 +247,9 @@ class Generator:
self.logger.info('Parser type: %s, version %s,\tGenerator version %s',
basename(getfile(Parser().__class__)), parser_origin, generator_origin)
- def get_paths(self, file_name=ROOT.joinpath('paths.ini')):
+ 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
"""
@@ -277,7 +280,7 @@ class Generator:
return self.paths_named(**data)
- async def get_mappings(self, file=ROOT.joinpath('mapping.json')):
+ async def get_mappings(self, file: Path = ROOT.joinpath('mapping.json')):
"""
The key name in *.json is equal to property named in jinja2 templates
:param file: path to file with manual mappings
@@ -291,13 +294,13 @@ class Generator:
self.logger.error('Failure to get mappings %s', error1)
return OrderedDict()
- def write_file(self, file, templates, data):
+ def write_file(self, file: Path, templates: list, data: dict):
"""
Calling producer/transformer instance to transform initial Model to dict used in jinja2 templates.
Applying transformed dict to jinja2 templates and writing to appropriate file
- :param file: output js file
- :param templates: name of template
- :param data: an instance of transformer for particular item
+ :param file: output file name
+ :param templates: list with templates
+ :param data: Dictionary with prepared output data, ready to be applied to Jinja2 template
"""
try:
render = self.env.get_or_select_template(templates).render(data)
@@ -307,7 +310,7 @@ class Generator:
as error1:
self.logger.error('skipping %s, template not found %s', file.as_posix(), error1)
- async def process_main(self, skip, overwrite, items, transformer):
+ async def process_main(self, skip: bool, overwrite: bool, items: dict, transformer):
"""
Process each item from initial Model. According to provided arguments skipping, overriding or asking what to to.
:param skip: if file exist skip it
@@ -333,14 +336,15 @@ class Generator:
await asyncio.gather(*tasks)
- async def process_function_name(self, skip, overwrite, functions, structs, transformer):
+ async def process_function_name(self, skip: bool, overwrite: bool, functions: dict, structs: dict,
+ transformer: FunctionsProducer):
"""
-
- :param skip:
- :param overwrite:
- :param functions:
- :param structs:
- :param transformer:
+ Processing output for SDLRPCFunctionNames and SDLRPCParameterNames
+ :param skip: if target file exist it will be skipped
+ :param overwrite: if target file exist it will be overwritten
+ :param functions: Dictionary with all functions
+ :param structs: Dictionary with all structs
+ :param transformer: FunctionsProducer (transformer) instance
:return:
"""
tasks = []
@@ -360,15 +364,15 @@ class Generator:
await asyncio.gather(*tasks)
- async def process_common(self, skip, overwrite, file_with_suffix, data, templates):
+ async def process_common(self, skip: bool, overwrite: bool, file_with_suffix: Path, data: dict, templates: list):
"""
-
- :param skip:
- :param overwrite:
- :param file_with_suffix:
- :param data:
- :param templates:
- :return:
+ Processing output common
+ :param skip: if target file exist it will be skipped
+ :param overwrite: if target file exist it will be overwritten
+ :param file_with_suffix: output file name
+ :param data: Dictionary with prepared output data, ready to be applied to Jinja2 template
+ :param templates: list with paths to Jinja2 templates
+ :return: None
"""
if file_with_suffix.is_file():
if skip:
@@ -400,10 +404,10 @@ class Generator:
@staticmethod
def filter_pattern(interface, pattern):
"""
-
- :param interface:
- :param pattern:
- :return:
+ Filtering Model to match with regex pattern
+ :param interface: Initial (original) Model, obtained from module 'rpc_spec/InterfaceParser'
+ :param pattern: regex pattern (string)
+ :return: Model with items which match with regex pattern
"""
names = tuple(interface.enums.keys()) + tuple(interface.structs.keys())
@@ -419,10 +423,10 @@ class Generator:
async def parser(self, source_xml, source_xsd):
"""
-
- :param source_xml:
- :param source_xsd:
- :return:
+ Getting Model from source_xml, parsed and validated by module 'rpc_spec/InterfaceParser'
+ :param source_xml: path to xml file
+ :param source_xsd: path to xsd file
+ :return: Model, obtained from module 'rpc_spec/InterfaceParser'
"""
try:
start = datetime.now()
diff --git a/generator/templates/base_struct_function.h b/generator/templates/base_struct_function.h
index 75c157eb2..57fb1a6de 100644
--- a/generator/templates/base_struct_function.h
+++ b/generator/templates/base_struct_function.h
@@ -1,3 +1,5 @@
+{#- To avoid code duplication was crated this parent file, which contain common part used in:
+ "templates/functions/template.h" and "templates/structs/template.h". -#}
{% include 'copyright.txt' %}
{% block imports %}
{%- for import in imports.enum %}
diff --git a/generator/templates/base_struct_function.m b/generator/templates/base_struct_function.m
index 4e69b7745..610a31d90 100644
--- a/generator/templates/base_struct_function.m
+++ b/generator/templates/base_struct_function.m
@@ -1,3 +1,5 @@
+{#- To avoid code duplication was crated this parent file, which contain common part used in:
+ "templates/functions/template.m" and "templates/structs/template.m". -#}
{% include 'copyright.txt' %}
{%- block imports %}
#import "{{name}}.h"
@@ -17,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
{%- endif %}
- self = [{{'self' if c.self else 'super'}} init{{'With'+c.self if c.self}}];
+ self = [{{ 'self' if c.self else 'super' }} init{{ 'With' + c.self if c.self and c.self is string }}];
{%- if c.deprecated %}
#pragma clang diagnostic pop
{%- endif %}
diff --git a/generator/templates/description.jinja b/generator/templates/description.jinja
index 4eff1614e..fb4932270 100644
--- a/generator/templates/description.jinja
+++ b/generator/templates/description.jinja
@@ -1,3 +1,4 @@
+{#- Content of this file include into every item (Enum/Struct/Function) between imports and typedef/@interface declaration -#}
{% if description or since or history %}
/**
{%- if description %}
@@ -18,6 +19,6 @@
{%- endif %}
*/
{%- endif -%}
-{%- if deprecated and deprecated is sameas true %}
+{%- if deprecated %}
__deprecated
{%- endif -%}
diff --git a/generator/templates/description_param.jinja b/generator/templates/description_param.jinja
index c2926a1f1..cb0cc4244 100644
--- a/generator/templates/description_param.jinja
+++ b/generator/templates/description_param.jinja
@@ -1,3 +1,4 @@
+{#- Content of this file include into every Param/sub-element of (Enum/Struct/Function) -#}
{% if param.description or param.since or param.history %}
/**
{%- if param.description %}
diff --git a/generator/templates/enums/template.h b/generator/templates/enums/template.h
index 0c98e6a00..033626c1c 100644
--- a/generator/templates/enums/template.h
+++ b/generator/templates/enums/template.h
@@ -1,3 +1,4 @@
+{#- String based enum. If the enum element doesn't have values it going to be string enum -#}
{% include 'copyright.txt' %}
{% block imports -%}
{%- for import in imports %}
@@ -8,7 +9,7 @@
{% include 'description.jinja' %}
typedef SDLEnum {{ name }} SDL_SWIFT_ENUM{{ending}};
{% for param in params %}
-{% include 'description_param.jinja' %}
+{%- include 'description_param.jinja' %}
extern {{ name }} const {{ name }}{{param.name}}{{ " __deprecated" if param.deprecated and param.deprecated is sameas true }};
{% endfor -%}
{% endblock -%}
diff --git a/generator/templates/enums/template_numeric.h b/generator/templates/enums/template_numeric.h
index a6493c6eb..f16e8f834 100644
--- a/generator/templates/enums/template_numeric.h
+++ b/generator/templates/enums/template_numeric.h
@@ -1,11 +1,13 @@
+{#- Numeric based enum. If the enum element values are numeric the enum should be a numerical.
+ This template extends base "templates/enums/template.h" and overriding block body -#}
{% extends "template.h" %}
{%- block body %}
{% include 'description.jinja' %}
-typedef NS_ENUM(NSUInteger, SDL{{ name }}){
+typedef NS_ENUM(NSUInteger, {{ name }}){
{% for param in params %}
-{%- macro someop() -%}{% include 'description_param.jinja' %}{%- endmacro -%}
-{{ someop()|indent(4, True) }}
- SDL{{ name }}{{ param.name }} = {{ param.value }}{{ " __deprecated" if param.deprecated and param.deprecated is sameas true }};
+{%- macro description_param() -%}{% include 'description_param.jinja' %}{%- endmacro -%}
+{{ description_param()|indent(4, True) }}
+ {{ name }}{{ param.name }} = {{ param.value }}{{ " __deprecated" if param.deprecated }}{{',' if not loop.last }}
{% endfor -%}
};
{% endblock -%} \ No newline at end of file
diff --git a/generator/templates/functions/template.h b/generator/templates/functions/template.h
index 51f426c26..b2301dba3 100644
--- a/generator/templates/functions/template.h
+++ b/generator/templates/functions/template.h
@@ -1 +1,2 @@
+{#- This template creates RPC requests, responses, and notification .h files -#}
{% extends "base_struct_function.h" %} \ No newline at end of file
diff --git a/generator/templates/functions/template.m b/generator/templates/functions/template.m
index 3327a6495..6b23240ae 100644
--- a/generator/templates/functions/template.m
+++ b/generator/templates/functions/template.m
@@ -1,3 +1,4 @@
+{#- This template creates RPC requests, responses, and notification .m files -#}
{% extends "base_struct_function.m" %}
{% block imports %}
{{super()}}
diff --git a/generator/templates/structs/template.h b/generator/templates/structs/template.h
index 51f426c26..af44cb710 100644
--- a/generator/templates/structs/template.h
+++ b/generator/templates/structs/template.h
@@ -1 +1,2 @@
+{#- This template creates RPC struct .h files -#}
{% extends "base_struct_function.h" %} \ No newline at end of file
diff --git a/generator/templates/structs/template.m b/generator/templates/structs/template.m
index c81f652cf..0d4c1b760 100644
--- a/generator/templates/structs/template.m
+++ b/generator/templates/structs/template.m
@@ -1,3 +1,4 @@
+{#- This template creates RPC struct .m files -#}
{% extends "base_struct_function.m" %}
{% block imports %}
{{super()}}
diff --git a/generator/test/runner.py b/generator/test/runner.py
index 5268b3bb4..ac72c6a2e 100644
--- a/generator/test/runner.py
+++ b/generator/test/runner.py
@@ -23,7 +23,7 @@ except ImportError as error:
def config_logging():
"""
- :return: None
+ Configuring logging for all application
"""
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter(fmt='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
@@ -36,7 +36,7 @@ def config_logging():
def main():
"""
- :return: None
+ Entry point for parser and generator
"""
config_logging()
suite = TestSuite()
diff --git a/generator/test/test_CodeFormatAndQuality.py b/generator/test/test_CodeFormatAndQuality.py
index b512823c8..c9b34e06f 100755
--- a/generator/test/test_CodeFormatAndQuality.py
+++ b/generator/test/test_CodeFormatAndQuality.py
@@ -1,7 +1,6 @@
-"""Interface model unit test
-
"""
-import subprocess
+Interface model unit test
+"""
import unittest
from os import walk
from os.path import join
@@ -12,28 +11,22 @@ from flake8.api import legacy as flake8
class CodeFormatAndQuality(unittest.TestCase):
def setUp(self):
- """Searching for all python files to be checked
-
- """
self.list_of_files = []
for (directory, _, filenames) in walk(Path(__file__).absolute().parents[1].as_posix()):
self.list_of_files += [join(directory, file) for file in filenames
if file.endswith('.py') and 'test' not in directory
and 'rpc_spec' not in directory]
- def test_check(self):
- """Performing checks by flake8
-
+ def test_checkCodeFormatAndQuality(self):
+ """
+ Performing checks of Code Format And Quality by flake8
+ If any inconvenient low quality code will be found, this will be shown in stdout and
+ each such cases will be reflected with report.total_errors number
"""
-
style_guide = flake8.get_style_guide(max_line_length=120)
report = style_guide.check_files(self.list_of_files)
self.assertEqual(report.total_errors, 0)
- process = subprocess.Popen(["flake8", '--exclude=rpc_spec,test', '..'], stdout=subprocess.PIPE)
- (output, err) = process.communicate()
- print(output.decode("utf-8"))
-
if __name__ == '__main__':
unittest.main()
diff --git a/generator/test/test_enums.py b/generator/test/test_enums.py
index d18a6c2ac..b7205e984 100644
--- a/generator/test/test_enums.py
+++ b/generator/test/test_enums.py
@@ -1,4 +1,4 @@
-from collections import OrderedDict, defaultdict
+from collections import OrderedDict
from unittest import TestCase
from model.enum import Enum
@@ -7,6 +7,13 @@ from transformers.enums_producer import EnumsProducer
class TestEnumsProducer(TestCase):
+ """
+ The structures of tests in this class was prepared to cover all possible combinations of code branching in tested
+ class EnumsProducer.
+ All names of Enums and nested elements doesn't reflating with real Enums
+ and could be replaces with some meaningless names.
+ """
+
def setUp(self):
self.maxDiff = None
diff --git a/generator/test/test_functions.py b/generator/test/test_functions.py
index 8b9867bc6..a481317c3 100644
--- a/generator/test/test_functions.py
+++ b/generator/test/test_functions.py
@@ -1,5 +1,5 @@
import re
-from collections import namedtuple, OrderedDict, defaultdict
+from collections import namedtuple, OrderedDict
from unittest import TestCase
from model.array import Array
@@ -16,6 +16,13 @@ from transformers.functions_producer import FunctionsProducer
class TestFunctionsProducer(TestCase):
+ """
+ The structures of tests in this class was prepared to cover all possible combinations of code branching in tested
+ class FunctionsProducer.
+ All names of Functions and nested elements doesn't reflating with real Enums
+ and could be replaces with some meaningless names.
+ """
+
def setUp(self):
self.maxDiff = None
@@ -68,12 +75,13 @@ class TestFunctionsProducer(TestCase):
origin='availableHdChannelsAvailable'),
self.producer.common_names(description=[], name='Ignore', origin='ignore', since=None),
self.producer.common_names(description=['image description'], name='Image', origin='image', since='1.0.0'),
- self.producer.common_names(description=[], name='PresetBankCapabilities', origin='PresetBankCapabilities', since=None),
+ self.producer.common_names(description=[], name='PresetBankCapabilities', origin='PresetBankCapabilities',
+ since=None),
self.producer.common_names(description=[], name='SoftButton', origin='SoftButton', since=None),
- self.producer.common_names(description=['syncMsgVersion description'], name='SyncMsgVersion',
+ self.producer.common_names(description=['syncMsgVersion description'], name='SdlMsgVersion',
origin='syncMsgVersion', since='3.5.0')]
actual = self.producer.get_simple_params(functions, structs)
- self.assertListEqual(expected, actual['params'])
+ self.assertCountEqual(expected, actual['params'])
def test_RegisterAppInterfaceRequest(self):
params = OrderedDict()
@@ -102,18 +110,18 @@ class TestFunctionsProducer(TestCase):
expected['name'] = 'SDLRegisterAppInterface'
expected['extends_class'] = 'SDLRPCRequest'
expected['imports'] = {
- '.h': {'enum': {'SDLRPCRequest'}, 'struct': {'SDLTemplateColorScheme', 'SDLTTSChunk', 'SDLSyncMsgVersion'}},
- '.m': {'SDLTemplateColorScheme', 'SDLTTSChunk', 'SDLSyncMsgVersion'}}
+ '.h': {'enum': {'SDLRPCRequest'}, 'struct': {'SDLTemplateColorScheme', 'SDLTTSChunk', 'SDLSdlMsgVersion'}},
+ '.m': {'SDLTemplateColorScheme', 'SDLTTSChunk', 'SDLSdlMsgVersion'}}
expected['description'] = ['Establishes an interface with a mobile application. Before registerAppInterface no '
'other commands will be', 'accepted/executed.']
expected['since'] = '1.0.0'
expected['params'] = (
self.producer.param_named(
- constructor_argument='syncMsgVersion', constructor_argument_override=None,
- constructor_prefix='SyncMsgVersion', deprecated=False, description=['See SyncMsgVersion'],
- for_name='object', mandatory=True, method_suffix='SyncMsgVersion', modifier='strong',
- of_class='SDLSyncMsgVersion.class', origin='syncMsgVersion', since=None,
- type_native='SDLSyncMsgVersion *', type_sdl='SDLSyncMsgVersion *'),
+ constructor_argument='sdlMsgVersion', constructor_argument_override=None,
+ constructor_prefix='SdlMsgVersion', deprecated=False, description=['See SyncMsgVersion'],
+ for_name='object', mandatory=True, method_suffix='SdlMsgVersion', modifier='strong',
+ of_class='SDLSdlMsgVersion.class', origin='sdlMsgVersion', since=None,
+ type_native='SDLSdlMsgVersion *', type_sdl='SDLSdlMsgVersion *'),
self.producer.param_named(
constructor_argument='fullAppID', constructor_argument_override=None, constructor_prefix='FullAppID',
deprecated=False, description=['ID used',
@@ -140,8 +148,8 @@ class TestFunctionsProducer(TestCase):
origin='isMediaApplication', since=None, type_native='BOOL', type_sdl='NSNumber<SDLBool> *'))
mandatory_arguments = [
- self.producer.argument_named(variable='syncMsgVersion', deprecated=False, origin='syncMsgVersion',
- constructor_argument='syncMsgVersion'),
+ self.producer.argument_named(variable='sdlMsgVersion', deprecated=False, origin='sdlMsgVersion',
+ constructor_argument='sdlMsgVersion'),
self.producer.argument_named(variable='isMediaApplication', deprecated=False, origin='isMediaApplication',
constructor_argument='@(isMediaApplication)')]
not_mandatory_arguments = [
@@ -151,13 +159,13 @@ class TestFunctionsProducer(TestCase):
constructor_argument='dayColorScheme'),
self.producer.argument_named(variable='ttsName', deprecated=False, origin='ttsName',
constructor_argument='ttsName')]
- mandatory_init = 'SyncMsgVersion:(SDLSyncMsgVersion *)syncMsgVersion ' \
+ mandatory_init = 'SdlMsgVersion:(SDLSdlMsgVersion *)sdlMsgVersion ' \
'isMediaApplication:(BOOL)isMediaApplication'
expected['constructors'] = (
self.producer.constructor_named(
all=mandatory_arguments, arguments=mandatory_arguments, deprecated=False,
- init=mandatory_init, self=''),
+ init=mandatory_init, self=True),
self.producer.constructor_named(
all=mandatory_arguments + not_mandatory_arguments, arguments=not_mandatory_arguments, deprecated=False,
init=mandatory_init + ' fullAppID:(nullable NSString *)fullAppID dayColorScheme:(nullable '
@@ -253,7 +261,7 @@ class TestFunctionsProducer(TestCase):
constructor_argument='hmiLevel')]
expected['constructors'] = (self.producer.constructor_named(
- all=arguments, arguments=arguments, deprecated=False, self='', init='HmiLevel:(SDLHMILevel)hmiLevel'),)
+ all=arguments, arguments=arguments, deprecated=False, self=True, init='HmiLevel:(SDLHMILevel)hmiLevel'),)
actual = self.producer.transform(item)
self.assertDictEqual(expected, actual)
@@ -265,6 +273,8 @@ class TestFunctionsProducer(TestCase):
params['position'] = Param(name='position', param_type=Integer(default_value=1000, max_value=1000, min_value=0))
params['speed'] = Param(name='speed', param_type=Float(max_value=700.0, min_value=0.0))
params['offset'] = Param(name='offset', param_type=Integer(max_value=100000000000, min_value=0))
+ params['duplicateUpdatesFromWindowID'] = Param(name='duplicateUpdatesFromWindowID', param_type=Integer(),
+ is_mandatory=False)
item = Function(name='CreateWindow', function_id=EnumElement(name='CreateWindowID'),
message_type=EnumElement(name='request'), params=params)
@@ -300,23 +310,41 @@ class TestFunctionsProducer(TestCase):
constructor_argument='offset', constructor_argument_override=None, constructor_prefix='Offset',
deprecated=False, description=['{"default_value": null, "max_value": 100000000000, "min_value": 0}'],
for_name='object', mandatory=True, method_suffix='Offset', modifier='strong', of_class='NSNumber.class',
- origin='offset', since=None, type_native='UInt64', type_sdl='NSNumber<SDLUInt> *'))
-
- expected_arguments = [self.producer.argument_named(variable='windowID', deprecated=False, origin='windowID',
- constructor_argument='@(windowID)'),
- self.producer.argument_named(variable='cmdID', deprecated=False, origin='cmdID',
- constructor_argument='@(cmdID)'),
- self.producer.argument_named(variable='position', deprecated=False, origin='position',
- constructor_argument='@(position)'),
- self.producer.argument_named(variable='speed', deprecated=False, origin='speed',
- constructor_argument='@(speed)'),
- self.producer.argument_named(variable='offset', deprecated=False, origin='offset',
- constructor_argument='@(offset)')]
+ origin='offset', since=None, type_native='UInt64', type_sdl='NSNumber<SDLUInt> *'),
+ self.producer.param_named(
+ constructor_argument='duplicateUpdatesFromWindowID', constructor_argument_override=None,
+ constructor_prefix='DuplicateUpdatesFromWindowID', deprecated=False,
+ description=['{"default_value": null, "max_value": null, "min_value": null}'], for_name='object',
+ mandatory=False, method_suffix='DuplicateUpdatesFromWindowID', modifier='strong',
+ of_class='NSNumber.class', origin='duplicateUpdatesFromWindowID', since=None,
+ type_native='NSNumber<SDLInt> *', type_sdl='NSNumber<SDLInt> *'))
- expected['constructors'] = (self.producer.constructor_named(
- all=expected_arguments, arguments=expected_arguments, deprecated=False, self='',
- init='WindowID:(UInt32)windowID cmdID:(UInt32)cmdID position:(UInt16)position speed:(float)speed '
- 'offset:(UInt64)offset'),)
+ not_mandatory_arguments = [
+ self.producer.argument_named(variable='windowID', deprecated=False, origin='windowID',
+ constructor_argument='@(windowID)'),
+ self.producer.argument_named(variable='cmdID', deprecated=False, origin='cmdID',
+ constructor_argument='@(cmdID)'),
+ self.producer.argument_named(variable='position', deprecated=False, origin='position',
+ constructor_argument='@(position)'),
+ self.producer.argument_named(variable='speed', deprecated=False, origin='speed',
+ constructor_argument='@(speed)'),
+ self.producer.argument_named(variable='offset', deprecated=False, origin='offset',
+ constructor_argument='@(offset)')]
+ mandatory_arguments = [self.producer.argument_named(
+ variable='duplicateUpdatesFromWindowID', deprecated=False, origin='duplicateUpdatesFromWindowID',
+ constructor_argument='duplicateUpdatesFromWindowID')]
+
+ expected['constructors'] = (
+ self.producer.constructor_named(
+ all=not_mandatory_arguments, arguments=not_mandatory_arguments, deprecated=False, self=True,
+ init='WindowID:(UInt32)windowID cmdID:(UInt32)cmdID position:(UInt16)position speed:(float)speed '
+ 'offset:(UInt64)offset'),
+ self.producer.constructor_named(
+ all=not_mandatory_arguments + mandatory_arguments, arguments=mandatory_arguments,
+ deprecated=False, self='WindowID:windowID cmdID:cmdID position:position speed:speed offset:offset',
+ init='WindowID:(UInt32)windowID cmdID:(UInt32)cmdID position:(UInt16)position speed:(float)speed '
+ 'offset:(UInt64)offset duplicateUpdatesFromWindowID:(nullable NSNumber<SDLInt> *)'
+ 'duplicateUpdatesFromWindowID'))
actual = self.producer.transform(item)
self.assertDictEqual(expected, actual)
@@ -344,8 +372,45 @@ class TestFunctionsProducer(TestCase):
origin='choiceSet')]
expected['constructors'] = (self.producer.constructor_named(
- all=argument, arguments=argument, deprecated=False, self='',
+ all=argument, arguments=argument, deprecated=False, self=True,
init='ChoiceSet:(NSArray<SDLChoice *> *)choiceSet'),)
actual = self.producer.transform(item)
self.assertDictEqual(expected, actual)
+
+ def test_SetDisplayLayout(self):
+ params = OrderedDict()
+ params['displayLayout'] = Param(name='displayLayout', param_type=String(max_length=500, min_length=1))
+ item = Function(name='SetDisplayLayout', function_id=EnumElement(name='SetDisplayLayoutID'),
+ message_type=EnumElement(name='request'), params=params, history=[
+ Function(name='SetDisplayLayout', function_id=EnumElement(name='SetDisplayLayoutID'),
+ message_type=EnumElement(name='request'), params={}, history=None, since='3.0.0',
+ until='6.0.0')
+ ], since='6.0.0', until=None, deprecated='true')
+
+ expected = OrderedDict()
+ expected['origin'] = 'SetDisplayLayout'
+ expected['name'] = 'SDLSetDisplayLayout'
+ expected['extends_class'] = 'SDLRPCRequest'
+ expected['imports'] = {'.h': {'enum': {'SDLRPCRequest'}, 'struct': set()}, '.m': set()}
+ expected['since'] = '6.0.0'
+ expected['history'] = '3.0.0'
+ expected['deprecated'] = True
+ expected['params'] = (
+ self.producer.param_named(
+ constructor_argument='displayLayout', constructor_argument_override=None,
+ constructor_prefix='DisplayLayout', deprecated=False,
+ description=['{"default_value": null, "max_length": 500, "min_length": 1}'], for_name='object',
+ mandatory=True, method_suffix='DisplayLayout', modifier='strong', of_class='NSString.class',
+ origin='displayLayout', since=None, type_native='NSString *', type_sdl='NSString *'),)
+
+ argument = [
+ self.producer.argument_named(variable='displayLayout', deprecated=False,
+ constructor_argument='displayLayout', origin='displayLayout')]
+
+ expected['constructors'] = (self.producer.constructor_named(
+ all=argument, arguments=argument, deprecated=False, self=True,
+ init='DisplayLayout:(NSString *)displayLayout'),)
+
+ actual = self.producer.transform(item)
+ self.assertDictEqual(expected, actual)
diff --git a/generator/test/test_structs.py b/generator/test/test_structs.py
index 9fc65b476..77186799e 100644
--- a/generator/test/test_structs.py
+++ b/generator/test/test_structs.py
@@ -1,7 +1,7 @@
-import re
-from collections import OrderedDict, defaultdict
+from collections import OrderedDict
from unittest import TestCase
+from model.integer import Integer
from model.param import Param
from model.string import String
from model.struct import Struct
@@ -9,16 +9,18 @@ from transformers.structs_producer import StructsProducer
class TestStructsProducer(TestCase):
+ """
+ The structures of tests in this class was prepared to cover all possible combinations of code branching in tested
+ class StructsProducer.
+ All names of Structs and nested elements doesn't reflating with real Enums
+ and could be replaces with some meaningless names.
+ """
+
def setUp(self):
self.maxDiff = None
self.producer = StructsProducer('SDLRPCStruct', ['Image'])
- def test_Version(self):
- version = self.producer.get_version
- self.assertIsNotNone(version)
- self.assertTrue(re.match(r'^\d*\.\d*\.\d*$', version))
-
def test_CloudAppProperties(self):
item = Struct(name='CloudAppProperties', members={
'appID': Param(name='appID', param_type=String())
@@ -33,10 +35,11 @@ class TestStructsProducer(TestCase):
constructor_argument='appID', constructor_argument_override=None, constructor_prefix='AppID',
deprecated=False, description=['{"default_value": null, "max_length": null, "min_length": null}'],
for_name='object', mandatory=True, method_suffix='AppID', modifier='strong', of_class='NSString.class',
- origin='appID', since=None, type_native='NSString *', type_sdl='NSString *', ),)
+ origin='appID', since=None, type_native='NSString *', type_sdl='NSString *'),)
argument = [
- self.producer.argument_named(variable='appID', deprecated=False, constructor_argument='appID', origin='appID')]
+ self.producer.argument_named(variable='appID', deprecated=False, constructor_argument='appID',
+ origin='appID')]
expected['constructors'] = (self.producer.constructor_named(
all=argument, arguments=argument, deprecated=False, self='',
@@ -45,28 +48,30 @@ class TestStructsProducer(TestCase):
actual = self.producer.transform(item)
self.assertDictEqual(expected, actual)
- def test_not_mandatory_NS_DESIGNATED_INITIALIZER(self):
- item = Struct(name='CloudAppProperties', members={
- 'appID': Param(name='appID', param_type=String(), is_mandatory=False)
+ def test_TouchEvent(self):
+ item = Struct(name='TouchEvent', members={
+ 'id': Param(name='id', param_type=Integer(max_value=9, min_value=0))
})
expected = OrderedDict()
- expected['origin'] = 'CloudAppProperties'
- expected['name'] = 'SDLCloudAppProperties'
+ expected['origin'] = 'TouchEvent'
+ expected['name'] = 'SDLTouchEvent'
expected['extends_class'] = 'SDLRPCStruct'
- expected['imports'] = {'.m': set(), '.h': {'enum': {'SDLRPCStruct'}, 'struct': set()}}
+ expected['imports'] = {'.h': {'enum': {'SDLRPCStruct'}, 'struct': set()}, '.m': set()}
expected['params'] = (
self.producer.param_named(
- constructor_argument='appID', constructor_argument_override=None, constructor_prefix='AppID',
- deprecated=False, description=['{"default_value": null, "max_length": null, "min_length": null}'],
- for_name='object', mandatory=False, method_suffix='AppID', modifier='strong', of_class='NSString.class',
- origin='appID', since=None, type_native='NSString *', type_sdl='NSString *', ),)
+ constructor_argument='touchEventId', constructor_argument_override=None,
+ constructor_prefix='TouchEventId', 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> *'),)
argument = [
- self.producer.argument_named(variable='appID', deprecated=False, constructor_argument='appID', origin='appID')]
+ self.producer.argument_named(variable='touchEventId', deprecated=False,
+ constructor_argument='@(touchEventId)', origin='touchEventId')]
expected['constructors'] = (self.producer.constructor_named(
all=argument, arguments=argument, deprecated=False, self='',
- init='AppID:(nullable NSString *)appID'),)
+ init='TouchEventId:(UInt8)touchEventId'),)
actual = self.producer.transform(item)
self.assertDictEqual(expected, actual)
diff --git a/generator/transformers/common_producer.py b/generator/transformers/common_producer.py
index 1d44956e5..3b2adab76 100644
--- a/generator/transformers/common_producer.py
+++ b/generator/transformers/common_producer.py
@@ -1,5 +1,5 @@
"""
-Common transformer
+All Enums/Structs/Functions Producer are inherited from this class and using features of it
"""
import json
import logging
@@ -21,15 +21,13 @@ from model.struct import Struct
class InterfaceProducerCommon(ABC):
"""
- Common transformer
+ All Enums/Structs/Functions Producer are inherited from this class and using features of it
"""
- version = '1.0.0'
-
def __init__(self, container_name, names=()):
self.logger = logging.getLogger(self.__class__.__name__)
self.container_name = container_name
- self.names = names
+ self.names = list(map(lambda e: self.replace_sync(e), names))
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 '
@@ -37,20 +35,13 @@ class InterfaceProducerCommon(ABC):
self.constructor_named = namedtuple('constructor', 'init self arguments all deprecated')
self.argument_named = namedtuple('argument', 'origin constructor_argument variable deprecated')
- @property
- def get_version(self):
- """
-
- :return:
- """
- return self.version
-
def transform(self, item: (Enum, Function, Struct), render: dict) -> dict:
"""
-
- :param item:
- :param render:
- :return:
+ Main entry point for transforming each Enum/Function/Struct into output dictionary,
+ which going to be applied to Jinja2 template
+ :param item: instance of Enum/Function/Struct
+ :param render: dictionary with pre filled entries, which going to be filled/changed by reference
+ :return: dictionary which going to be applied to Jinja2 template
"""
if item.description:
render['description'] = self.extract_description(item.description)
@@ -58,65 +49,77 @@ class InterfaceProducerCommon(ABC):
render['since'] = item.since
if item.history:
render['history'] = item.history.pop().since
- if item.deprecated and item.deprecated.lower() == 'true':
+ if item.deprecated and str(item.deprecated).lower() == 'true':
render['deprecated'] = True
render['params'] = OrderedDict()
for param in getattr(item, self.container_name).values():
- if param.name.lower() in ['id']:
+ param.name = self.replace_sync(param.name)
+ if param.name.lower() == 'id':
param.name = self.minimize_first(item.name) + self.title(param.name)
render['params'][param.name] = self.extract_param(param)
if isinstance(item, (Struct, Function)):
self.extract_imports(param, render['imports'])
if 'constructors' not in render and isinstance(item, (Struct, Function)):
- designated_initializer = render['designated_initializer'] if 'designated_initializer' in render else False
- render['constructors'] = self.extract_constructors(render['params'], designated_initializer)
+ render['constructors'] = self.extract_constructors(render['params'])
render['params'] = tuple(render['params'].values())
return render
- def extract_imports(self, param: Param, imports):
+ @staticmethod
+ def replace_sync(name: str = '') -> str:
"""
-
- :param param:
- :param imports:
- :return:
+ :param name: string with item name
+ :return: string with replaced 'sync' to 'sdl'
"""
+ return re.sub(r'^([sS])ync(.+)$', r'\1dl\2', name)
- def evaluate(element):
- if isinstance(element, (Struct, Enum)):
- return element.name, type(element).__name__.lower()
- return None, None
+ def extract_imports(self, param: Param, imports: dict):
+ """
+ Extracting appropriate imports and updating in render['imports'] by reference
+ :param param: instance of Param, which is sub element of Enum/Function/Struct
+ :param imports: dictionary from render['imports']
+ :return: dictionary with extracted imports
+ """
if isinstance(param.param_type, Array):
- type_origin, kind = evaluate(param.param_type.element_type)
+ type_origin, kind = self.evaluate_import(param.param_type.element_type)
else:
- type_origin, kind = evaluate(param.param_type)
+ type_origin, kind = self.evaluate_import(param.param_type)
- if type_origin in self.names:
+ if type_origin and (type_origin in self.names or self.title(type_origin) in self.names):
name = 'SDL' + type_origin
imports['.h'][kind].add(name)
imports['.m'].add(name)
return imports
- @staticmethod
- def title(name):
+ def evaluate_import(self, element):
+ """
+ :param element: instance of param.param_type
+ :return: tuple with element.name, type(element).__name__.lower()
"""
+ if isinstance(element, (Struct, Enum)):
+ return self.replace_sync(element.name), type(element).__name__.lower()
+ return None, None
- :param name:
- :return:
+ @staticmethod
+ def title(name: str = '') -> str:
+ """
+ Capitalizing only first character in string.
+ :param name: string to be capitalized first character
+ :return: initial parameter with capitalized first character
"""
return name[:1].upper() + name[1:]
@staticmethod
- def minimize_first(name):
+ def minimize_first(name: str = '') -> str:
"""
-
- :param name:
- :return:
+ Minimizing only first character in string.
+ :param name: string to be minimized first character
+ :return: initial parameter with minimized first character
"""
return name[:1].lower() + name[1:]
@@ -125,7 +128,7 @@ class InterfaceProducerCommon(ABC):
"""
Evaluate, align and delete @TODO
:param data: list with description
- :param length:
+ :param length: length of the string to be split
:return: evaluated string
"""
if not data:
@@ -135,12 +138,12 @@ class InterfaceProducerCommon(ABC):
return textwrap.wrap(re.sub(r'(\s{2,}|\n|\[@TODO.+)', ' ', data).strip(), length)
@staticmethod
- def nullable(type_native, mandatory):
+ def nullable(type_native: str, mandatory: bool) -> str:
"""
-
- :param type_native:
- :param mandatory:
- :return:
+ Used for adding nullable modificator into initiator (constructor) parameter
+ :param type_native: native type
+ :param mandatory: is parameter mandatory
+ :return: string with modificator
"""
if mandatory or re.match(r'BOOL|float|double', type_native):
return ''
@@ -149,9 +152,9 @@ class InterfaceProducerCommon(ABC):
@staticmethod
def wrap(item):
"""
-
- :param item:
- :return:
+ Used for wrapping appropriate initiator (constructor) parameter with '@({})'
+ :param item: named tup[le with initiator (constructor) parameter
+ :return: wrapped parameter
"""
if re.match(r'\w*Int\d*|BOOL|float|double', item.type_native):
return '@({})'.format(item.constructor_argument)
@@ -159,10 +162,10 @@ class InterfaceProducerCommon(ABC):
def extract_constructor(self, data: list, mandatory: bool) -> dict:
"""
-
- :param data:
- :param mandatory:
- :return:
+ Preparing dictionary with initial initiator (constructor)
+ :param data: list with prepared parameters
+ :param mandatory: is parameter mandatory
+ :return: dictionary with initial initiator (constructor)
"""
data = list(data)
@@ -179,15 +182,14 @@ class InterfaceProducerCommon(ABC):
self.nullable(param.type_native, mandatory),
param.type_native.strip(), param.constructor_argument)
init.append(init_str)
+ _self = True if 'functions' in self.__class__.__name__.lower() and mandatory else ''
+ return {'init': ' '.join(init), 'self': _self, 'arguments': arguments, 'all': arguments, 'deprecated': False}
- return {'init': ' '.join(init), 'self': '', 'arguments': arguments, 'all': arguments, 'deprecated': False}
-
- def extract_constructors(self, data: dict, designated_initializer: bool = None) -> tuple:
+ def extract_constructors(self, data: dict) -> tuple:
"""
-
- :param data:
- :param designated_initializer:
- :return:
+ Preparing tuple with all initiators (constructors)
+ :param data: list with prepared parameters
+ :return: tuple with all initiators (constructors)
"""
mandatory = []
not_mandatory = []
@@ -210,25 +212,21 @@ class InterfaceProducerCommon(ABC):
not_mandatory['all'] = mandatory['arguments'] + not_mandatory['arguments']
not_mandatory['deprecated'] = any([m.deprecated for m in mandatory if hasattr(m, 'deprecated')])
not_mandatory['self'] = re.sub(r'([\w\d]+:)\([\w\d\s<>*]*\)([\w\d]+\s*)', r'\1\2', mandatory['init'])
- if not mandatory and designated_initializer:
- not_mandatory['init'] = not_mandatory['init'] + ' NS_DESIGNATED_INITIALIZER'
result.append(self.constructor_named(**not_mandatory))
if mandatory:
- if designated_initializer:
- mandatory['init'] = mandatory['init'] + ' NS_DESIGNATED_INITIALIZER'
result.insert(0, self.constructor_named(**mandatory))
return tuple(result)
- @staticmethod
- def evaluate_type(instance, mandatory) -> dict:
+ def evaluate_type(self, instance) -> dict:
"""
-
- :param instance:
- :param mandatory:
- :return:
+ Extracting dictionary with evaluated output types
+ :param instance: param_type of Param
+ :return: dictionary with evaluated output types
"""
+ if hasattr(instance, 'name'):
+ instance.name = self.replace_sync(instance.name)
data = OrderedDict()
if isinstance(instance, Enum):
data['for_name'] = 'enum'
@@ -262,8 +260,6 @@ class InterfaceProducerCommon(ABC):
data['type_sdl'] = 'SDLUInt'
data['of_class'] = 'NSNumber.class'
data['type_sdl'] = 'NSNumber<{}> *'.format(data['type_sdl'])
- if not mandatory:
- data['type_native'] = data['type_sdl']
elif isinstance(instance, String):
data['of_class'] = 'NSString.class'
data['type_sdl'] = data['type_native'] = 'NSString *'
@@ -275,24 +271,29 @@ class InterfaceProducerCommon(ABC):
def extract_type(self, param: Param) -> dict:
"""
-
- :param param:
- :return:
+ Preparing dictionary with output types information
+ :param param: sub element of Enum/Function/Struct
+ :return: dictionary with output types information
"""
if isinstance(param.param_type, Array):
- data = self.evaluate_type(param.param_type.element_type, param.is_mandatory)
+ data = self.evaluate_type(param.param_type.element_type)
data['for_name'] = data['for_name'] + 's'
data['type_sdl'] = data['type_native'] = 'NSArray<{}> *'.format(data['type_sdl'].strip())
- return data
- return self.evaluate_type(param.param_type, param.is_mandatory)
+ else:
+ data = self.evaluate_type(param.param_type)
+
+ if not param.is_mandatory and re.match(r'\w*Int\d*', data['type_native']):
+ data['type_native'] = data['type_sdl']
+
+ return data
@staticmethod
- def param_origin_change(name):
+ def param_origin_change(name) -> dict:
"""
-
- :param name:
- :return:
+ Based on name preparing common part of output types information
+ :param name: Param name
+ :return: dictionary with part of output types information
"""
return {'origin': name,
'constructor_argument': name,
@@ -301,9 +302,9 @@ class InterfaceProducerCommon(ABC):
def extract_param(self, param: Param):
"""
-
- :param param:
- :return:
+ Preparing self.param_named with prepared params
+ :param param: Param from initial Model
+ :return: self.param_named with prepared params
"""
data = {'constructor_argument_override': None,
'description': self.extract_description(param.description),
diff --git a/generator/transformers/enums_producer.py b/generator/transformers/enums_producer.py
index dd072544a..f458e243f 100644
--- a/generator/transformers/enums_producer.py
+++ b/generator/transformers/enums_producer.py
@@ -22,13 +22,15 @@ class EnumsProducer(InterfaceProducerCommon):
self.logger = logging.getLogger(self.__class__.__name__)
self.param_named = namedtuple('param_named', 'origin description name since value')
- def transform(self, item: Enum, render=None) -> dict:
+ def transform(self, item: Enum, render: dict = None) -> dict:
"""
-
- :param item:
- :param render:
- :return:
+ Main entry point for transforming each Enum into output dictionary,
+ which going to be applied to Jinja2 template
+ :param item: instance of Enum
+ :param render: empty dictionary, present in parameter for code consistency
+ :return: dictionary which going to be applied to Jinja2 template
"""
+ item.name = self.replace_sync(item.name)
name = 'SDL{}{}'.format(item.name[:1].upper(), item.name[1:])
tmp = {self.enum_class}
imports = {'.h': tmp, '.m': tmp}
@@ -44,9 +46,9 @@ class EnumsProducer(InterfaceProducerCommon):
def extract_param(self, param: EnumElement):
"""
-
- :param param:
- :return:
+ Preparing self.param_named with prepared params
+ :param param: EnumElement from initial Model
+ :return: self.param_named with prepared params
"""
data = {'origin': param.name, 'description': self.extract_description(param.description, 113),
'since': param.since}
@@ -54,7 +56,7 @@ class EnumsProducer(InterfaceProducerCommon):
if re.match(r'^[A-Z]{1,2}\d|\d[A-Z]{1,2}$', param.name):
data['name'] = param.name
elif re.match(r'(^[a-z\d]+$|^[A-Z\d]+$)', param.name):
- data['name'] = param.name.title() # .capitalize()
+ data['name'] = param.name.title()
elif re.match(r'^(?=\w*[a-z])(?=\w*[A-Z])\w+$', param.name):
if param.name.endswith('ID'):
data['name'] = param.name[:-2]
diff --git a/generator/transformers/functions_producer.py b/generator/transformers/functions_producer.py
index 5cb562047..01110ac18 100644
--- a/generator/transformers/functions_producer.py
+++ b/generator/transformers/functions_producer.py
@@ -26,18 +26,18 @@ class FunctionsProducer(InterfaceProducerCommon):
self.logger = logging.getLogger(self.__class__.__name__)
self.common_names = namedtuple('common_names', 'name origin description since')
- def transform(self, item: Function, render=None) -> dict:
+ def transform(self, item: Function, render: dict = None) -> dict:
"""
-
- :param item:
- :param render:
- :return:
+ Main entry point for transforming each Enum/Function/Struct into output dictionary,
+ which going to be applied to Jinja2 template
+ :param item: instance of Enum/Function/Struct
+ :param render: dictionary with pre filled entries, which going to be filled/changed by reference
+ :return: dictionary which going to be applied to Jinja2 template
"""
list(map(item.params.__delitem__, filter(item.params.__contains__, ['success', 'resultCode', 'info'])))
-
+ item.name = self.replace_sync(item.name)
name = 'SDL' + item.name
- imports = {'.h': {'enum': set(), 'struct': set()},
- '.m': set()}
+ imports = {'.h': {'enum': set(), 'struct': set()}, '.m': set()}
extends_class = None
if item.message_type.name == 'response':
extends_class = self.response_class
@@ -62,13 +62,13 @@ class FunctionsProducer(InterfaceProducerCommon):
def get_function_names(self, items: dict) -> dict:
"""
-
- :param items:
- :return: dict
+ Standalone method used for preparing SDLRPCFunctionNames collection ready to be applied to Jinja2 template
+ :param items: collection with all functions from initial Model
+ :return: collection with transformed element ready to be applied to Jinja2 template
"""
render = OrderedDict()
for item in items.values():
- tmp = {'name': self.title(item.name),
+ tmp = {'name': self.title(self.replace_sync(item.name)),
'origin': item.name,
'description': self.extract_description(item.description),
'since': item.since}
@@ -76,31 +76,38 @@ class FunctionsProducer(InterfaceProducerCommon):
return {'params': sorted(render.values(), key=lambda a: a.name)}
- def get_simple_params(self, functions: dict, structs: dict) -> dict:
+ def evaluate(self, element) -> dict:
"""
- :param functions:
- :param structs:
- :return:
+ Internal evaluator used for preparing SDLRPCParameterNames collection
+ :param element: Param from initial Model
+ :return: dictionary with evaluated part of output collection
"""
+ origin = element.name
+ name = self.replace_sync(element.name)
+ # if isinstance(element.param_type, (Integer, Float, Boolean, String)):
+ return {name: self.common_names(**{
+ 'name': self.title(name),
+ 'origin': origin,
+ 'description': self.extract_description(element.description),
+ 'since': element.since})}
+ # return OrderedDict()
- def evaluate(element):
- # if isinstance(element.param_type, (Integer, Float, Boolean, String)):
- return {element.name: self.common_names(**{
- 'name': self.title(element.name),
- 'origin': element.name,
- 'description': self.extract_description(element.description),
- 'since': element.since})}
- # return OrderedDict()
-
+ def get_simple_params(self, functions: dict, structs: dict) -> dict:
+ """
+ Standalone method used for preparing SDLRPCParameterNames collection ready to be applied to Jinja2 template
+ :param functions: collection with all functions from initial Model
+ :param structs: collection with all structs from initial Model
+ :return: collection with transformed element ready to be applied to Jinja2 template
+ """
render = OrderedDict()
for func in functions.values():
for param in func.params.values():
- render.update(evaluate(param))
+ render.update(self.evaluate(param))
for struct in structs.values():
- render.update(evaluate(struct))
+ render.update(self.evaluate(struct))
for param in struct.members.values():
- render.update(evaluate(param))
+ render.update(self.evaluate(param))
return {'params': sorted(render.values(), key=lambda a: a.name)}
diff --git a/generator/transformers/generate_error.py b/generator/transformers/generate_error.py
deleted file mode 100644
index 3fe1a75ed..000000000
--- a/generator/transformers/generate_error.py
+++ /dev/null
@@ -1,12 +0,0 @@
-"""
-Generate error.
-"""
-
-
-class GenerateError(Exception):
- """Generate error.
-
- This exception is raised when generator is unable to create
- output from given model.
-
- """
diff --git a/generator/transformers/structs_producer.py b/generator/transformers/structs_producer.py
index 86a596095..beb652a3a 100644
--- a/generator/transformers/structs_producer.py
+++ b/generator/transformers/structs_producer.py
@@ -21,13 +21,15 @@ class StructsProducer(InterfaceProducerCommon):
self.struct_class = struct_class
self.logger = logging.getLogger(self.__class__.__name__)
- def transform(self, item: Struct, render=None) -> dict:
+ def transform(self, item: Struct, render: dict = None) -> dict:
"""
-
- :param item:
- :param render:
- :return:
+ Main entry point for transforming each Enum/Function/Struct into output dictionary,
+ which going to be applied to Jinja2 template
+ :param item: instance of Enum/Function/Struct
+ :param render: dictionary with pre filled entries, which going to be filled/changed by reference
+ :return: dictionary which going to be applied to Jinja2 template
"""
+ item.name = self.replace_sync(item.name)
name = 'SDL' + item.name
imports = {'.h': {'enum': set(), 'struct': set()}, '.m': set()}
imports['.h']['enum'].add(self.struct_class)