summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuergen Bocklage-Ryannel <jbocklage-ryannel@luxoft.com>2017-08-03 11:45:06 +0200
committerJuergen Bocklage-Ryannel <jbocklage-ryannel@luxoft.com>2017-08-03 11:45:06 +0200
commitb25703484348da76179c81997cc59d0349bfd669 (patch)
treef908ac40052bae6c96e3cea3ca02dd9d927f4f91
parent395c0d5afefd8aed4762f0b253c1427e7ce9f84d (diff)
downloadqtivi-qface-b25703484348da76179c81997cc59d0349bfd669.tar.gz
Added features support for rule generator
-rw-r--r--docs/extending.rst36
-rw-r--r--qface/generator.py21
2 files changed, 52 insertions, 5 deletions
diff --git a/docs/extending.rst b/docs/extending.rst
index 010c810..9e1b671 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/generator.py b/qface/generator.py
index ac1baeb..ef02062 100644
--- a/qface/generator.py
+++ b/qface/generator.py
@@ -156,16 +156,18 @@ 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, path: 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})
document = FileSystem.load_yaml(path, required=True)
for module, rules in document.items():
@@ -174,6 +176,8 @@ class RuleGenerator(Generator):
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,7 +192,7 @@ 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', {}))
@@ -198,6 +202,15 @@ class RuleGenerator(Generator):
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):
"""QFace helper functions to work with the file system"""
@@ -302,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 {}