diff options
author | Juergen Bocklage-Ryannel <jbocklage-ryannel@luxoft.com> | 2017-08-03 12:20:44 +0200 |
---|---|---|
committer | Juergen Bocklage-Ryannel <jbocklage-ryannel@luxoft.com> | 2017-08-03 12:20:44 +0200 |
commit | 4368a2109bd847b900b6cf44cde924f4472b2ac5 (patch) | |
tree | 2e9dd467193bf9133515e0b4f68dd9c6eaa6575b | |
parent | 9c1e691e2c9eac21136c3a7bd959e411dca5371a (diff) | |
parent | 24ae273aaf51c51fb1e71c2997e768a5cec4a00e (diff) |
Merge branch 'release/1.8'1.8
-rw-r--r-- | docs/extending.rst | 36 | ||||
-rw-r--r-- | qface/__about__.py | 2 | ||||
-rw-r--r-- | qface/generator.py | 41 |
3 files changed, 64 insertions, 15 deletions
diff --git a/docs/extending.rst b/docs/extending.rst index 010c810..dc42cb8 100644 --- a/docs/extending.rst +++ b/docs/extending.rst @@ -75,7 +75,7 @@ The `RuleGenerator` allows you to extract the documentation rules into an extern generator = RuleGenerator(search_path=here/'templates', destination=output) generator.process_rules(here/'docs.yaml', system) -The rules document is divided into several targets. Each target can have an own destination. A target is typical for exampe and app, client, server. Each target can have rules for the different symbols (system, module, interface, struct, enum). An each rule finally consists of a destination modifier, additional context and a documents collection. +The rules document is divided into several targets. Each target can have an own destination. A target is typical for example and app, client, server. Each target can have rules for the different symbols (system, module, interface, struct, enum). An each rule finally consists of a destination modifier, additional context and a documents collection. .. code-block:: python @@ -123,3 +123,37 @@ Here is an example (``docs.yaml``) The rule generator adds the ``dst``, ``project`` as also the corresponding symbols to the context automatically. On each level you are able to change the destination or update the context. + +.. rubric:: Features + +The rules document allows to conditional write files based on a feature set. The feature set must be a set of tags indicating the features which will then be checked in the ``when`` section of a rule. + +The features are passed to the generator in your custom generator code. The existence of a feature tells the rules engine to check if a ``when`` section exists conditionally execute this rule. + +.. code-block:: yaml + + plugin: + when: plugin_enabled + destination: '{{dst}}/plugin' + module: + ... + +Here the plugin rule will only be run when the feature set contains a 'plugin_enabled' string. + +.. rubric:: Preserve + +Documents can be marked as preserved to prevent them to be overwritten when the user has edited them. the rules documents has an own marker for this called ``preserve``. This is a list of target documents which shall be be marked preserved by the generator. + + +.. code-block:: yaml + + plugin: + interface: + documents: + '{{interface|lower}}.h': 'plugin/interface.h' + '{{interface|lower}}.cpp': 'plugin/interface.cpp' + preserve: + - '{{interface|lower}}.h' + - '{{interface|lower}}.cpp' + +In the example above the two interface documents will not be overwritten during a second generator call and can be edited by the user. diff --git a/qface/__about__.py b/qface/__about__.py index 4fbd624..c16b3dd 100644 --- a/qface/__about__.py +++ b/qface/__about__.py @@ -9,7 +9,7 @@ except NameError: __title__ = "qface" __summary__ = "A generator framework based on a common modern IDL" __url__ = "https://pelagicore.github.io/qface/" -__version__ = "1.7" +__version__ = "1.8" __author__ = "JRyannel" __author_email__ = "qface-generator@googlegroups.com" __copyright__ = "2017 Pelagicore" diff --git a/qface/generator.py b/qface/generator.py index 572cedf..ef02062 100644 --- a/qface/generator.py +++ b/qface/generator.py @@ -137,9 +137,9 @@ class Generator(object): data = self.render(template, context) if self._has_different_content(data, path): if path.exists() and preserve: - click.secho('preserve changed file: {0}'.format(path), fg='blue') + click.secho('preserve: {0}'.format(path), fg='blue') else: - click.secho('write changed file: {0}'.format(path), fg='blue') + click.secho('create: {0}'.format(path), fg='blue') path.open('w', encoding='utf-8').write(data) def _has_different_content(self, data, path): @@ -156,24 +156,28 @@ class Generator(object): class RuleGenerator(Generator): """Generates documents based on a rule YAML document""" - def __init__(self, search_path: str, destination: Path, context: dict= {}): + def __init__(self, search_path: str, destination:Path, context:dict={}, features:set=set()): super().__init__(search_path, context) self.context.update({ 'dst': destination, 'project': Path(destination).name, }) self.destination = '{{dst}}' + self.features = features - def process_rules(self, document: Path, system: System): + def process_rules(self, path: Path, system: System, features:set=set()): """writes the templates read from the rules document""" + self.features.update(features) self.context.update({'system': system}) - rules = FileSystem.load_yaml(document, required=True) - for name, target in rules.items(): - click.secho('process target: {0}'.format(name), fg='green') - self._process_target(target, system) + document = FileSystem.load_yaml(path, required=True) + for module, rules in document.items(): + click.secho('module: {0}'.format(module), fg='green') + self._process_rules(rules, system) - def _process_target(self, rules: dict, system: System): + def _process_rules(self, rules: dict, system: System): """ process a set of rules for a target """ + if not self._shall_proceed(rules): + return self.context.update(rules.get('context', {})) self.destination = rules.get('destination', '{{dst}}') self._process_rule(rules.get('system', None), {'system': system}) @@ -188,13 +192,24 @@ class RuleGenerator(Generator): def _process_rule(self, rule: dict, context: dict): """ process a single rule """ - if not rule: + if not rule or not self._shall_proceed(rule): return self.context.update(context) self.context.update(rule.get('context', {})) self.destination = rule.get('destination', None) + preserved = rule.get('preserve', []) for target, source in rule.get('documents', {}).items(): - self.write(target, source) + preserve = target in preserved + self.write(target, source, preserve=preserve) + + def _shall_proceed(self, obj): + conditions = obj.get('when', []) + if not conditions: + return True + if not isinstance(conditions, list): + conditions = [conditions] + result = self.features.intersection(set(conditions)) + return bool(len(result)) class FileSystem(object): @@ -249,7 +264,7 @@ class FileSystem(object): updates the tag information of that symbol """ meta = FileSystem.load_yaml(document) - click.secho('merge tags from {0}'.format(document), fg='blue') + click.secho('merge: {0}'.format(document.name), fg='blue') for identifier, data in meta.items(): symbol = system.lookup(identifier) if symbol: @@ -300,5 +315,5 @@ class FileSystem(object): try: return yaml.load(document.text(), Loader=Loader) except yaml.YAMLError as exc: - click.secho(exc, fg='red') + click.secho(str(exc), fg='red') return {} |