Use Jinja 2 templates to generate the `metadata` file
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 20 Aug 2020 19:52:48 +0000 (15:52 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 20 Aug 2020 19:52:48 +0000 (15:52 -0400)
The goal of this patch is to, as much as possible, and as long as
everything remains as readable as possible, move any `metadata` file
templating outside of pure Python code to improve template readability,
maintenability, and reuse.

This patch does the following:

1. Adds a Jinja 2 dependency to `pyproject.toml`.

2. Adds the `template` module which contains helpers to create and
   render a Jinja 2 template.

   The _create_template() function uses a `jinja2.PackageLoader` object
   to load a named package from the `barectf` packet's `templates`
   directory.

   It creates an environment with common parameters and common
   filters:

   `indent_tab`:
       Like Jinja 2's built-in `indent`, but uses tabs instead of
       spaces.

   `escape_sq`:
       Escapes a double-quoted string (backslashes and double quotes).

   Jinja 2 templates can expect to have access to the `barectf_config`
   and `barectf_version` modules, as well as, possibly, the current
   barectf configuration as the `cfg` variable.

   The _render_template() function renders a given template with a given
   context, keeping a single newline at the end if `is_file_template` is
   `True`.

3. Adds Jinja 2 templates to generate the `metadata` file:

   `metadata.j2`:
       Top-level template for the whole file.

   `metadata-enum-ft.j2`:
       Enumeration field type block template.

   `metadata-int-ft.j2`:
       Integer field type block template.

   `metadata-real-ft.j2`:
       Real field type block template.

   `metadata-str-ft.j2`:
       String field type block template.

   `metadata-struct-ft.j2`:
       Structure field type block template.

4. Changes `barectf/tsdl182gen.py` so as to use 2. with 3.

   `barectf/tsdl182gen.py` defines custom Jinja 2 filters to help the
   templates of 3.:

   `bo_str`:
       Converts a `barectf.ByteOrder` value to the `le` or `be` string.

   `disp_base_int`:
       Converts a `barectf.DisplayBase` value to an equivalent integer.

   `int_ft_str`:
       Converts an integer field type object to its TSDL string
       equivalent.

       The first line is not indented.

   `ft_str`:
       Converts any field type object to its TSDL string equivalent.

       The first line is not indented.

5. Adds the `barectf.TraceType.clock_types` property to easily access
   the set of required clock types (by all stream types).

   This is required by 3.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
barectf/config.py
barectf/template.py [new file with mode: 0644]
barectf/templates/metadata-enum-ft.j2 [new file with mode: 0644]
barectf/templates/metadata-int-ft.j2 [new file with mode: 0644]
barectf/templates/metadata-real-ft.j2 [new file with mode: 0644]
barectf/templates/metadata-str-ft.j2 [new file with mode: 0644]
barectf/templates/metadata-struct-ft.j2 [new file with mode: 0644]
barectf/templates/metadata.j2 [new file with mode: 0644]
barectf/tsdl182gen.py
poetry.lock
pyproject.toml

index edf1bfe217a421a5075ca2e143c0a635b5350533..e438cfb47bccdafd048f2bb513fbd5f7ba56dad6 100644 (file)
@@ -740,6 +740,16 @@ class TraceType:
     def features(self) -> TraceTypeFeatures:
         return self._features
 
+    @property
+    def clock_types(self) -> Set[ClockType]:
+        clk_types = set()
+
+        for stream_type in self._stream_types:
+            if stream_type.default_clock_type is not None:
+                clk_types.add(stream_type.default_clock_type)
+
+        return clk_types
+
 
 _EnvEntry = Union[str, int]
 _EnvEntries = Mapping[str, _EnvEntry]
diff --git a/barectf/template.py b/barectf/template.py
new file mode 100644 (file)
index 0000000..7329996
--- /dev/null
@@ -0,0 +1,87 @@
+# The MIT License (MIT)
+#
+# Copyright (c) 2020 Philippe Proulx <pproulx@efficios.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+import jinja2
+import barectf.config as barectf_config
+import barectf.version as barectf_version
+from barectf.typing import Count
+from typing import Callable, Optional, Any, Mapping
+
+
+def _filt_indent_tab(text: str, count: Count = Count(1), indent_first: bool = False) -> str:
+    in_lines = text.split('\n')
+    out_lines = []
+    tab = '\t'
+
+    for index, in_line in enumerate(in_lines):
+        in_line = in_line.rstrip()
+
+        if len(in_line) == 0 or (index == 0 and not indent_first):
+            out_lines.append(in_line)
+            continue
+
+        out_lines.append(f'{tab * count}{in_line}')
+
+    return '\n'.join(out_lines)
+
+
+def _filt_escape_dq(text: str) -> str:
+    return text.replace('\\', '\\\\').replace('"', '\\"')
+
+
+_Filter = Callable[[Any], Any]
+_Filters = Mapping[str, _Filter]
+_Test = Callable[[Any], bool]
+_Tests = Mapping[str, _Test]
+
+
+def _create_template(name: str, cfg: Optional[barectf_config.Configuration] = None,
+                     filters: Optional[_Filters] = None,
+                     tests: Optional[_Test] = None) -> jinja2.Template:
+    env = jinja2.Environment(trim_blocks=True, lstrip_blocks=True,
+                             loader=jinja2.PackageLoader('barectf', 'templates'))
+    env.globals.update({
+        'cfg': cfg,
+        'barectf_config': barectf_config,
+        'barectf_version': barectf_version,
+    })
+
+    env.filters['indent_tab'] = _filt_indent_tab
+    env.filters['escape_dq'] = _filt_escape_dq
+
+    if filters is not None:
+        env.filters.update(filters)
+
+    if tests is not None:
+        env.tests.update(tests)
+
+    return env.get_template(name)
+
+
+def _render_template(templ: jinja2.Template, is_file_template: bool = False, **kwargs) -> str:
+    text = templ.render(**kwargs)
+
+    if is_file_template:
+        text = text.strip() + '\n'
+
+    return text
diff --git a/barectf/templates/metadata-enum-ft.j2 b/barectf/templates/metadata-enum-ft.j2
new file mode 100644 (file)
index 0000000..1dc2783
--- /dev/null
@@ -0,0 +1,12 @@
+enum : {{ ft | int_ft_str }} {
+{% for label, mapping in ft.mappings.items() %}
+{% for rg in mapping.ranges %}
+       {% if rg.lower == rg.upper %}
+               {% set rg_str = rg.lower %}
+       {% else %}
+               {% set rg_str %}{{ rg.lower }} ... {{ rg.upper }}{% endset %}
+       {% endif %}
+       "{{ label | escape_dq }}" = {{ rg_str }},
+{% endfor %}
+{% endfor %}
+}
diff --git a/barectf/templates/metadata-int-ft.j2 b/barectf/templates/metadata-int-ft.j2
new file mode 100644 (file)
index 0000000..50e6513
--- /dev/null
@@ -0,0 +1,10 @@
+integer {
+       signed = {{ 'true' if is_signed else 'false' }};
+       size = {{ ft.size }};
+       align = {{ ft.alignment }};
+       byte_order = {{ ft.byte_order | bo_str }};
+       base = {{ ft.preferred_display_base | disp_base_int }};
+       {% if ft._mapped_clk_type_name %}
+       map = clock.{{ ft._mapped_clk_type_name }}.value;
+       {% endif %}
+}
diff --git a/barectf/templates/metadata-real-ft.j2 b/barectf/templates/metadata-real-ft.j2
new file mode 100644 (file)
index 0000000..d70fbfd
--- /dev/null
@@ -0,0 +1,6 @@
+floating_point {
+       mant_dig = {{ 24 if ft.size == 32 else 53 }};
+       exp_dig = {{ 8 if ft.size == 32 else 11 }};
+       align = {{ ft.alignment }};
+       byte_order = {{ ft.byte_order | bo_str }};
+}
diff --git a/barectf/templates/metadata-str-ft.j2 b/barectf/templates/metadata-str-ft.j2
new file mode 100644 (file)
index 0000000..6de8a2b
--- /dev/null
@@ -0,0 +1,3 @@
+string {
+       encoding = UTF8;
+}
diff --git a/barectf/templates/metadata-struct-ft.j2 b/barectf/templates/metadata-struct-ft.j2
new file mode 100644 (file)
index 0000000..dcfb05d
--- /dev/null
@@ -0,0 +1,11 @@
+struct {
+{% for name, member in ft.members.items() %}
+{#
+`chain` is a list of static array field types terminated with a
+non-array field type (the most nested).
+#}
+{% set chain = ft_chain(member.field_type) %}
+       {{ chain[-1] | ft_str | indent_tab }} {{ name }}
+       {%- for array_ft in chain[:-1] %}[{{ array_ft.length }}]{% endfor %};
+{% endfor %}
+} align({{ ft.minimum_alignment }})
diff --git a/barectf/templates/metadata.j2 b/barectf/templates/metadata.j2
new file mode 100644 (file)
index 0000000..f4d5612
--- /dev/null
@@ -0,0 +1,109 @@
+/* CTF 1.8 */
+
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ *
+ * The following TSDL code was generated by barectf v{{ barectf_version.__version__ }}
+ * on {{ cfg.trace.environment['barectf_gen_date'] }}.
+ *
+ * For more details, see <https://barectf.org/>.
+ */
+{#
+Generates a root field type string named `name` for the field type `rft`
+with all the lines except the first one indented with a single tab.
+#}
+{% macro root_ft(name, rft) -%}
+{{ name }} := {{ rft | ft_str | indent_tab }};
+{%- endmacro %}
+
+trace {
+       major = 1;
+       minor = 8;
+       byte_order = {{ cfg.trace.type.default_byte_order | bo_str }};
+       {% if cfg.trace.type.uuid %}
+       uuid = "{{ cfg.trace.type.uuid }}";
+       {% endif %}
+       {% if cfg.trace.type._pkt_header_ft %}
+       {{ root_ft('packet.header', cfg.trace.type._pkt_header_ft) }}
+       {% endif %}
+};
+
+env {
+{% for name, value in cfg.trace.environment.items() %}
+       {{ name }} = {{ value if value is number else '"{}"'.format(value | escape_dq) }};
+{% endfor %}
+};
+
+{# all clock types (stream types's default clock types) #}
+{% for clk_type in cfg.trace.type.clock_types | sort %}
+clock {
+       name = {{ clk_type.name }};
+       {% if clk_type.description %}
+       description = "{{ clk_type.description | escape_dq }}";
+       {% endif %}
+       {% if clk_type.uuid %}
+       uuid = "{{ clk_type.uuid }}";
+       {% endif %}
+       freq = {{ clk_type.frequency }};
+       precision = {{ clk_type.precision }};
+       offset_s = {{ clk_type.offset.seconds }};
+       offset = {{ clk_type.offset.cycles }};
+       absolute = {{ 'true' if clk_type.origin_is_unix_epoch else 'false' }};
+};
+
+{% endfor %}
+{# stream types and their event types #}
+{%- for stream_type in cfg.trace.type.stream_types | sort %}
+/* Stream type `{{ stream_type.name }}` */
+stream {
+       id = {{ stream_type.id }};
+       {{ root_ft('packet.context', stream_type._pkt_ctx_ft) }}
+       {% if stream_type._ev_header_ft %}
+       {{ root_ft('event.header', stream_type._ev_header_ft) }}
+       {% endif %}
+       {% if stream_type.event_common_context_field_type %}
+       {{ root_ft('event.context', stream_type.event_common_context_field_type) }}
+       {% endif %}
+};
+
+{# stream type's event types #}
+{% for ev_type in stream_type.event_types | sort %}
+event {
+       id = {{ ev_type.id }};
+       stream_id = {{ stream_type.id }};
+       name = "{{ ev_type.name }}";
+       {% if ev_type.log_level %}
+       loglevel = {{ ev_type.log_level }};
+       {% endif %}
+       {% if ev_type.specific_context_field_type %}
+       {{ root_ft('context', ev_type.specific_context_field_type) }}
+       {% endif %}
+       {% if ev_type.payload_field_type %}
+       {{ root_ft('fields', ev_type.payload_field_type) }}
+       {% endif %}
+};
+
+{% endfor %}
+{% endfor %}
index 99e3063b6bd650c023b26dac4986fc7f47c05728..aa53e769ccccca843c94d82968a6bd63280199f6 100644 (file)
 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-import barectf.codegen as barectf_codegen
-import barectf.version as barectf_version
 import barectf.config as barectf_config
+import barectf.template as barectf_template
+import jinja2
+from typing import List, Optional
+import typing
 
 
-def _bool_to_string(b):
-    return 'true' if b else 'false'
+def _filt_bo_str(bo: barectf_config.ByteOrder) -> str:
+    return {
+        barectf_config.ByteOrder.LITTLE_ENDIAN: 'le',
+        barectf_config.ByteOrder.BIG_ENDIAN: 'be',
+    }[bo]
 
 
-_byte_order_to_string_map = {
-    barectf_config.ByteOrder.LITTLE_ENDIAN: 'le',
-    barectf_config.ByteOrder.BIG_ENDIAN: 'be',
-}
-
-
-def _byte_order_to_string(byte_order):
-    return _byte_order_to_string_map[byte_order]
-
-
-_display_base_to_int_map = {
-    barectf_config.DisplayBase.BINARY: 2,
-    barectf_config.DisplayBase.OCTAL: 8,
-    barectf_config.DisplayBase.DECIMAL: 10,
-    barectf_config.DisplayBase.HEXADECIMAL: 16,
-}
-
-
-def _display_base_to_int(disp_base):
-    return _display_base_to_int_map[disp_base]
-
-
-def _gen_int_ft(ft, cg):
-    cg.add_line('integer {')
-    cg.indent()
-    cg.add_line(f'size = {ft.size};')
-    cg.add_line(f'align = {ft.alignment};')
-    is_signed = isinstance(ft, barectf_config.SignedIntegerFieldType)
-    cg.add_line(f'signed = {_bool_to_string(is_signed)};')
-    cg.add_line(f'byte_order = {_byte_order_to_string(ft.byte_order)};')
-    cg.add_line(f'base = {_display_base_to_int(ft.preferred_display_base)};')
-
-    if isinstance(ft, barectf_config.UnsignedIntegerFieldType) and ft._mapped_clk_type_name is not None:
-        cg.add_line(f'map = clock.{ft._mapped_clk_type_name}.value;')
-
-    cg.unindent()
-    cg.add_line('}')
-
-
-def _gen_enum_ft(ft, cg):
-    cg.add_line('enum : ')
-    cg.add_glue()
-    _gen_int_ft(ft, cg)
-    cg.append_to_last_line(' {')
-    cg.indent()
-
-    for label, mapping in ft.mappings.items():
-        for rg in mapping.ranges:
-            if rg.lower == rg.upper:
-                rg_str = str(rg.lower)
-            else:
-                rg_str = f'{rg.lower} ... {rg.upper}'
-
-        line = f'"{label}" = {rg_str},'
-        cg.add_line(line)
-
-    cg.unindent()
-    cg.add_line('}')
-
+def _filt_disp_base_int(disp_base: barectf_config.DisplayBase) -> int:
+    return {
+        barectf_config.DisplayBase.BINARY: 2,
+        barectf_config.DisplayBase.OCTAL: 8,
+        barectf_config.DisplayBase.DECIMAL: 10,
+        barectf_config.DisplayBase.HEXADECIMAL: 16,
+    }[disp_base]
 
-def _gen_real_ft(ft, cg):
-    cg.add_line('floating_point {')
-    cg.indent()
 
-    if ft.size == 32:
-        exp_dig = 8
-        mant_dig = 24
-    else:
-        assert ft.size == 64
-        exp_dig = 11
-        mant_dig = 53
+def _filt_int_ft_str(ft: barectf_config._FieldType) -> str:
+    return barectf_template._render_template(_INT_FT_TEMPL, ft=ft,
+                                             is_signed=isinstance(ft, barectf_config.SignedIntegerFieldType))
 
-    cg.add_line(f'exp_dig = {exp_dig};')
-    cg.add_line(f'mant_dig = {mant_dig};')
-    cg.add_line(f'align = {ft.alignment};')
-    cg.add_line(f'byte_order = {_byte_order_to_string(ft.byte_order)};')
-    cg.unindent()
-    cg.add_line('}')
 
+def _gen_enum_ft(ft: barectf_config._FieldType) -> str:
+    return barectf_template._render_template(_ENUM_FT_TEMPL, ft=ft)
 
-def _gen_string_ft(ft, cg):
-    cg.add_line('string {')
-    cg.indent()
-    cg.add_line('encoding = UTF8;')
-    cg.unindent()
-    cg.add_line('}')
 
+def _gen_real_ft(ft: barectf_config._FieldType) -> str:
+    return barectf_template._render_template(_REAL_FT_TEMPL, ft=ft)
 
-def _find_deepest_array_ft_element_ft(ft):
-    if isinstance(ft, barectf_config._ArrayFieldType):
-        return _find_deepest_array_ft_element_ft(ft.element_field_type)
 
-    return ft
+def _gen_str_ft(ft: barectf_config._FieldType) -> str:
+    return barectf_template._render_template(_STR_FT_TEMPL, ft=ft)
 
 
-def _static_array_ft_lengths(ft, lengths):
-    if type(ft) is barectf_config.StaticArrayFieldType:
-        lengths.append(ft.length)
-        _static_array_ft_lengths(ft.element_field_type, lengths)
+def _ft_chain(ft: barectf_config._FieldType) -> List[barectf_config._FieldType]:
+    chain: List[barectf_config._FieldType] = []
 
+    while isinstance(ft, barectf_config.StaticArrayFieldType):
+        chain.append(ft)
+        ft = ft.element_field_type
 
-def _gen_struct_ft_entry(name, ft, cg):
-    elem_ft = _find_deepest_array_ft_element_ft(ft)
-    _gen_ft(elem_ft, cg)
-    cg.append_to_last_line(f' {name}')
+    chain.append(ft)
+    return chain
 
-    # array
-    lengths = []
-    _static_array_ft_lengths(ft, lengths)
 
-    if lengths:
-        for length in reversed(lengths):
-            cg.append_to_last_line(f'[{length}]')
+def _gen_struct_ft(ft: barectf_config._FieldType) -> str:
+    return barectf_template._render_template(_STRUCT_FT_TEMPL, ft=ft, ft_chain=_ft_chain)
 
-    cg.append_to_last_line(';')
 
-
-def _gen_struct_ft(ft, cg):
-    cg.add_line('struct {')
-    cg.indent()
-
-    for name, member in ft.members.items():
-        _gen_struct_ft_entry(name, member.field_type, cg)
-
-    cg.unindent()
-
-    if len(ft.members) == 0:
-        cg.add_glue()
-
-    cg.add_line(f'}} align({ft.minimum_alignment})')
-
-
-_ft_to_gen_ft_func = {
-    barectf_config.UnsignedIntegerFieldType: _gen_int_ft,
-    barectf_config.SignedIntegerFieldType: _gen_int_ft,
+_FT_CLS_TO_GEN_FT_FUNC = {
+    barectf_config.UnsignedIntegerFieldType: _filt_int_ft_str,
+    barectf_config.SignedIntegerFieldType: _filt_int_ft_str,
     barectf_config.UnsignedEnumerationFieldType: _gen_enum_ft,
     barectf_config.SignedEnumerationFieldType: _gen_enum_ft,
     barectf_config.RealFieldType: _gen_real_ft,
-    barectf_config.StringFieldType: _gen_string_ft,
+    barectf_config.StringFieldType: _gen_str_ft,
     barectf_config.StructureFieldType: _gen_struct_ft,
 }
 
 
-def _gen_ft(ft, cg):
-    _ft_to_gen_ft_func[type(ft)](ft, cg)
-
-
-def _gen_root_ft(name, ft, cg):
-    cg.add_line('{} := '.format(name))
-    cg.add_glue()
-    _gen_ft(ft, cg)
-    cg.append_to_last_line(';')
-
-
-def _try_gen_root_ft(name, ft, cg):
-    if ft is None:
-        return
-
-    _gen_root_ft(name, ft, cg)
-
-
-def _gen_start_block(name, cg):
-    cg.add_line(f'{name} {{')
-    cg.indent()
-
-
-def _gen_end_block(cg):
-    cg.unindent()
-    cg.add_line('};')
-    cg.add_empty_line()
-
+def _filt_ft_str(ft: barectf_config._FieldType) -> str:
+    return _FT_CLS_TO_GEN_FT_FUNC[type(ft)](ft)
 
-def _gen_trace_type_block(config, cg):
-    trace_type = config.trace.type
-    _gen_start_block('trace', cg)
-    cg.add_line('major = 1;')
-    cg.add_line('minor = 8;')
-    default_byte_order = trace_type.default_byte_order
 
-    if default_byte_order is None:
-        default_byte_order = barectf_config.ByteOrder.LITTLE_ENDIAN
-
-    cg.add_line(f'byte_order = {_byte_order_to_string(default_byte_order)};')
-
-    if trace_type.uuid is not None:
-        cg.add_line(f'uuid = "{trace_type.uuid}";')
-
-    _try_gen_root_ft('packet.header', trace_type._pkt_header_ft, cg)
-    _gen_end_block(cg)
-
-
-def _escape_literal_string(s):
-    esc = s.replace('\\', '\\\\')
-    esc = esc.replace('\n', '\\n')
-    esc = esc.replace('\r', '\\r')
-    esc = esc.replace('\t', '\\t')
-    esc = esc.replace('"', '\\"')
-    return esc
-
-
-def _gen_trace_env_block(config, cg):
-    env = config.trace.environment
-    assert env is not None
-    _gen_start_block('env', cg)
-
-    for name, value in env.items():
-        if type(value) is int:
-            value_string = str(value)
-        else:
-            value_string = f'"{_escape_literal_string(value)}"'
-
-        cg.add_line(f'{name} = {value_string};')
-
-    _gen_end_block(cg)
-
-
-def _gen_clk_type_block(clk_type, cg):
-    _gen_start_block('clock', cg)
-    cg.add_line(f'name = {clk_type.name};')
-
-    if clk_type.description is not None:
-        cg.add_line(f'description = "{_escape_literal_string(clk_type.description)}";')
-
-    if clk_type.uuid is not None:
-        cg.add_line(f'uuid = "{clk_type.uuid}";')
-
-    cg.add_line(f'freq = {clk_type.frequency};')
-    cg.add_line(f'offset_s = {clk_type.offset.seconds};')
-    cg.add_line(f'offset = {clk_type.offset.cycles};')
-    cg.add_line(f'precision = {clk_type.precision};')
-    cg.add_line(f'absolute = {_bool_to_string(clk_type.origin_is_unix_epoch)};')
-    _gen_end_block(cg)
-
-
-def _gen_clk_type_blocks(config, cg):
-    for stream_type in sorted(config.trace.type.stream_types):
-        if stream_type.default_clock_type is not None:
-            _gen_clk_type_block(stream_type.default_clock_type, cg)
-
-
-def _gen_stream_type_block(config, stream_type, cg):
-    cg.add_cc_line(stream_type.name.replace('/', ''))
-    _gen_start_block('stream', cg)
-
-    if config.trace.type.features.stream_type_id_field_type is not None:
-        cg.add_line(f'id = {stream_type.id};')
-
-    _try_gen_root_ft('packet.context', stream_type._pkt_ctx_ft, cg)
-    _try_gen_root_ft('event.header', stream_type._ev_header_ft, cg)
-    _try_gen_root_ft('event.context', stream_type.event_common_context_field_type, cg)
-    _gen_end_block(cg)
-
-
-def _gen_ev_type_block(config, stream_type, ev_type, cg):
-    _gen_start_block('event', cg)
-    cg.add_line(f'name = "{ev_type.name}";')
-
-    if stream_type.features.event_features.type_id_field_type is not None:
-        cg.add_line(f'id = {ev_type.id};')
-
-    if config.trace.type.features.stream_type_id_field_type is not None:
-        cg.add_line(f'stream_id = {stream_type.id};')
-        cg.append_cc_to_last_line(f'Stream type `{stream_type.name.replace("/", "")}`')
-
-    if ev_type.log_level is not None:
-        cg.add_line(f'loglevel = {ev_type.log_level};')
-
-    _try_gen_root_ft('context', ev_type.specific_context_field_type, cg)
-    payload_ft = ev_type.payload_field_type
-
-    if payload_ft is None:
-        payload_ft = barectf_config.StructureFieldType(8)
-
-    _try_gen_root_ft('fields', ev_type.payload_field_type, cg)
-    _gen_end_block(cg)
-
-
-def _gen_stream_type_ev_type_blocks(config, cg):
-    for stream_type in sorted(config.trace.type.stream_types):
-        _gen_stream_type_block(config, stream_type, cg)
-
-        for ev_type in sorted(stream_type.event_types):
-            _gen_ev_type_block(config, stream_type, ev_type, cg)
-
-
-def _from_config(config):
-    cg = barectf_codegen._CodeGenerator('\t')
+_TEMPL_FILTERS = {
+    'bo_str': _filt_bo_str,
+    'disp_base_int': _filt_disp_base_int,
+    'int_ft_str': _filt_int_ft_str,
+    'ft_str': _filt_ft_str,
+}
 
-    # version/magic
-    cg.add_line('/* CTF 1.8 */')
-    cg.add_empty_line()
-    cg.add_line('''/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- *''')
-    cg.add_line(f' * The following TSDL code was generated by barectf v{barectf_version.__version__}')
-    cg.add_line(f' * on {config.trace.environment["barectf_gen_date"]}.')
-    cg.add_line(' *')
-    cg.add_line(' * For more details, see <https://barectf.org/>.')
-    cg.add_line(' */')
-    cg.add_empty_line()
 
-    # trace type block
-    _gen_trace_type_block(config, cg)
+def _create_template(name: str,
+                     cfg: Optional[barectf_config.Configuration] = None) -> jinja2.Template:
+    return barectf_template._create_template(name, cfg,
+                                             typing.cast(barectf_template._Filters, _TEMPL_FILTERS))
 
-    # trace environment block
-    _gen_trace_env_block(config, cg)
 
-    # clock type blocks
-    _gen_clk_type_blocks(config, cg)
+_ENUM_FT_TEMPL = _create_template('metadata-enum-ft.j2')
+_INT_FT_TEMPL = _create_template('metadata-int-ft.j2')
+_REAL_FT_TEMPL = _create_template('metadata-real-ft.j2')
+_STR_FT_TEMPL = _create_template('metadata-str-ft.j2')
+_STRUCT_FT_TEMPL = _create_template('metadata-struct-ft.j2')
 
-    # stream and type blocks
-    _gen_stream_type_ev_type_blocks(config, cg)
 
-    return cg.code
+def _from_config(cfg: barectf_config.Configuration) -> str:
+    return barectf_template._render_template(_create_template('metadata.j2', cfg),
+                                             is_file_template=True)
index ea8cadc4e149a25f01461e64d5bc27a3dbb2705f..adf4eed4f80e2b477a4b4213674010bf3a873049 100644 (file)
@@ -28,6 +28,20 @@ zipp = ">=0.5"
 docs = ["sphinx", "rst.linker"]
 testing = ["packaging", "pep517", "importlib-resources (>=1.3)"]
 
+[[package]]
+category = "main"
+description = "A very fast and expressive template engine."
+name = "jinja2"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "2.11.2"
+
+[package.dependencies]
+MarkupSafe = ">=0.23"
+
+[package.extras]
+i18n = ["Babel (>=0.8)"]
+
 [[package]]
 category = "main"
 description = "An implementation of JSON Schema validation for Python"
@@ -50,6 +64,14 @@ version = "*"
 format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"]
 format_nongpl = ["idna", "jsonpointer (>1.13)", "webcolors", "rfc3986-validator (>0.1.0)", "rfc3339-validator"]
 
+[[package]]
+category = "main"
+description = "Safely add untrusted strings to HTML/XML markup."
+name = "markupsafe"
+optional = false
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
+version = "1.1.1"
+
 [[package]]
 category = "main"
 description = "Persistent/Functional/Immutable data structures"
@@ -99,7 +121,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
 testing = ["jaraco.itertools", "func-timeout"]
 
 [metadata]
-content-hash = "2f2cf818db3b560712dbd0c7900be46cb0135efdd4de5decc1df157991693279"
+content-hash = "a4409c00d57cf44d61809d0073fe1433379ea22afdd4cb25a2fd1f7a4b8951d4"
 python-versions = '^3.6'
 
 [metadata.files]
@@ -111,10 +133,49 @@ importlib-metadata = [
     {file = "importlib_metadata-1.7.0-py2.py3-none-any.whl", hash = "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"},
     {file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"},
 ]
+jinja2 = [
+    {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"},
+    {file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"},
+]
 jsonschema = [
     {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"},
     {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"},
 ]
+markupsafe = [
+    {file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"},
+    {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"},
+    {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183"},
+    {file = "MarkupSafe-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b"},
+    {file = "MarkupSafe-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e"},
+    {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f"},
+    {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1"},
+    {file = "MarkupSafe-1.1.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5"},
+    {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1"},
+    {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735"},
+    {file = "MarkupSafe-1.1.1-cp34-cp34m-win32.whl", hash = "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21"},
+    {file = "MarkupSafe-1.1.1-cp34-cp34m-win_amd64.whl", hash = "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235"},
+    {file = "MarkupSafe-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b"},
+    {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f"},
+    {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905"},
+    {file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"},
+    {file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"},
+    {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"},
+    {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"},
+    {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"},
+    {file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"},
+    {file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"},
+    {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"},
+    {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"},
+    {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"},
+    {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"},
+    {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"},
+    {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"},
+    {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"},
+    {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"},
+    {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"},
+    {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"},
+    {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"},
+]
 pyrsistent = [
     {file = "pyrsistent-0.16.0.tar.gz", hash = "sha256:28669905fe725965daa16184933676547c5bb40a5153055a8dee2a4bd7933ad3"},
 ]
index 076ccedb61069e07a2a592fd145e017b6e8d6c6b..59c2ca33da268e8ce635248184f328d17363a2fd 100644 (file)
@@ -59,6 +59,7 @@ termcolor = '^1.1'
 pyyaml = '^5.3'
 jsonschema = '^3.2'
 setuptools = '*'
+jinja2 = '^2.11'
 
 [tool.poetry.scripts]
 barectf = 'barectf.cli:_run'
This page took 0.035013 seconds and 4 git commands to generate.