diff options
author | Juergen Bocklage-Ryannel <juergen.bocklage-ryannel@pelagicore.com> | 2017-01-30 10:56:04 +0100 |
---|---|---|
committer | Juergen Bocklage-Ryannel <juergen.bocklage-ryannel@pelagicore.com> | 2017-01-30 10:56:04 +0100 |
commit | ee1ef38757970c93932e5028f8fe86fc1aa8d7e0 (patch) | |
tree | c319e263e849d47e9dd1ec9e1f16412449c62e6a | |
parent | 67992af4d5dad3ed8eb7952694cfa58af1ba9de3 (diff) | |
download | qtivi-qface-ee1ef38757970c93932e5028f8fe86fc1aa8d7e0.tar.gz |
Added initial support for external annotation files using the YAML syntax. See grammar documentation
-rw-r--r-- | docs/grammar.rst | 29 | ||||
-rw-r--r-- | qface/generator.py | 28 | ||||
-rw-r--r-- | tests/in/com.pelagicore.ivi.tuner.yaml | 2 | ||||
-rw-r--r-- | tests/test_tags.py | 7 |
4 files changed, 61 insertions, 5 deletions
diff --git a/docs/grammar.rst b/docs/grammar.rst index f7977ce..c858e77 100644 --- a/docs/grammar.rst +++ b/docs/grammar.rst @@ -105,7 +105,36 @@ Below is an example of a QFace file. } +Tags / Annotations +================== +Tags allows an interface author to extend the existing grammar with additional meta information, called tags, aka annotations. One or several annotations can stand in from of a module, interface, struct or enum. They are also allowed before an operation, property or event. Everywhere where a documentation comment is allowed you can also add annotations. + +An annotation looks like this:: + + @service(port=12345) + interface Tuner { + } + +A annotation format is very similar to an operation signature prefixed with an `@` sign and no return value. + +The annotation are available later when navigating the domain model. + +.. note:: QFace does not specify specific annotations, but defines just the annotation format. The set of annotations supported must be defined and documented by the generator. + +.. rubric:: Annotation Documents + +QFace allows also to specify these annotations in external documents using the `YAML` syntax. For this you need to create a document with the same name as the QFace document but with the extension `.yaml`. It should have roughly the following format + +.. code-block:: yaml + + com.pelagicore.ivi.Tuner: + service: + port: 12345 + +On the root level should be a fully qualified name of a symbol. The symbol will be looked up and the following annotation information merged with the existing annotations form the QFace document. + +.. warning:: External annotation with the same name will override the QFace document annotation with the same name on the specified symbol. diff --git a/qface/generator.py b/qface/generator.py index 0da3613..01e7dfb 100644 --- a/qface/generator.py +++ b/qface/generator.py @@ -7,6 +7,7 @@ from antlr4.error import DiagnosticErrorListener import shelve import logging import hashlib +import yaml from .idl.parser.TLexer import TLexer from .idl.parser.TParser import TParser @@ -96,15 +97,17 @@ class FileSystem(object): """QFace helper functions to work with the file system""" @staticmethod - def parse_document(path: str, system: System = None): + def parse_document(document: Path, system: System = None): """Parses a document and returns the resulting domain system :param path: document path to parse :param system: system to be used (optional) """ - logger.debug('parse document: {0}'.format(path)) - stream = FileStream(str(path), encoding='utf-8') - return FileSystem._parse_stream(stream, system) + logger.debug('parse document: {0}'.format(document)) + stream = FileStream(str(document), encoding='utf-8') + system = FileSystem._parse_stream(stream, system) + FileSystem._merge_meta_information(system, document) + return system @staticmethod def _parse_stream(stream, system: System = None): @@ -121,6 +124,20 @@ class FileSystem(object): return system @staticmethod + def _merge_meta_information(system, document): + """Tries to find a YAML document named after the qface document and + for each root symbol identifier updated the tag information of that symbol + """ + path = document.stripext() + '.yaml' + if path.exists(): + click.secho('merge tags from {0}'.format(path), fg='blue') + meta = yaml.load(path.text()) + for identifier, data in meta.items(): + symbol = system.lookup(identifier) + if symbol: + symbol.tags.update(data) + + @staticmethod def parse(input, identifier: str = None, use_cache=False, clear_cache=True, pattern="*.qface"): """Input can be either a file or directory or a list of files or directory. A directory will be parsed recursively. The function returns the resulting system. @@ -131,7 +148,7 @@ class FileSystem(object): :param clear_cache: clears the domain cache (defaults to true) """ inputs = input if isinstance(input, (list, tuple)) else [input] - logging.debug('parse input={0}'.format(inputs)) + logger.debug('parse input={0}'.format(inputs)) identifier = 'system' if not identifier else identifier system = System() cache = None @@ -150,6 +167,7 @@ class FileSystem(object): else: for document in path.walkfiles(pattern): FileSystem.parse_document(document, system) + if use_cache: cache[identifier] = system return system diff --git a/tests/in/com.pelagicore.ivi.tuner.yaml b/tests/in/com.pelagicore.ivi.tuner.yaml new file mode 100644 index 0000000..948c50c --- /dev/null +++ b/tests/in/com.pelagicore.ivi.tuner.yaml @@ -0,0 +1,2 @@ +com.pelagicore.ivi.tuner.Tuner: + port: 12345 diff --git a/tests/test_tags.py b/tests/test_tags.py index e8f8ca7..527b623 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -37,3 +37,10 @@ def test_tag(): assert enum is module.lookup('Waveband') assert 'default' in enum.tags assert enum.attribute('default', 'value') == 'FM' + + +def test_meta_tags(): + system = loadTuner() + interface = system.lookup('com.pelagicore.ivi.tuner.Tuner') + assert interface + assert 'port' in interface.tags |