5
5
6
6
from generators import ecs_helpers
7
7
8
- # jinja2 setup
9
- TEMPLATE_DIR = path .join (path .dirname (path .abspath (__file__ )), '../templates' )
10
- template_loader = jinja2 .FileSystemLoader (searchpath = TEMPLATE_DIR )
11
- template_env = jinja2 .Environment (loader = template_loader )
12
-
13
8
14
9
def generate (nested , ecs_version , out_dir ):
15
10
save_asciidoc (path .join (out_dir , 'fields.asciidoc' ), page_field_index (nested , ecs_version ))
@@ -19,6 +14,64 @@ def generate(nested, ecs_version, out_dir):
19
14
# Helpers
20
15
21
16
17
+ def render_fieldset_reuse_text (fieldset ):
18
+ """Renders the expected nesting locations
19
+ if the the `reusable` object is present.
20
+
21
+ :param fieldset: The fieldset to evaluate
22
+ """
23
+ if not fieldset .get ('reusable' ):
24
+ return None
25
+ reusable_fields = fieldset ['reusable' ]['expected' ]
26
+ sorted_fields = sorted (reusable_fields , key = lambda k : k ['full' ])
27
+ return map (lambda f : f ['full' ], sorted_fields )
28
+
29
+
30
+ def render_nestings_reuse_section (fieldset ):
31
+ """Renders the reuse section entries.
32
+
33
+ :param fieldset: The target fieldset
34
+ """
35
+ if not fieldset .get ('reused_here' ):
36
+ return None
37
+ rows = []
38
+ for reused_here_entry in fieldset ['reused_here' ]:
39
+ rows .append ({
40
+ 'flat_nesting' : "{}.*" .format (reused_here_entry ['full' ]),
41
+ 'name' : reused_here_entry ['schema_name' ],
42
+ 'short' : reused_here_entry ['short' ]
43
+ })
44
+
45
+ return sorted (rows , key = lambda x : x ['flat_nesting' ])
46
+
47
+
48
+ def extract_allowed_values_key_names (field ):
49
+ """Extracts the `name` keys from the field's
50
+ allowed_values if present in the field
51
+ object.
52
+
53
+ :param field: The target field
54
+ """
55
+ if not field .get ('allowed_values' ):
56
+ return []
57
+ return ecs_helpers .list_extract_keys (field ['allowed_values' ], 'name' )
58
+
59
+
60
+ def sort_fields (fieldset ):
61
+ """Prepares a fieldset's fields for being
62
+ passed into the j2 template for rendering. This
63
+ includes sorting them into a list of objects and
64
+ adding a field for the names of any allowed values
65
+ for the field, if present.
66
+
67
+ :param fieldset: The target fieldset
68
+ """
69
+ fields_list = list (fieldset ['fields' ].values ())
70
+ for field in fields_list :
71
+ field ['allowed_value_names' ] = extract_allowed_values_key_names (field )
72
+ return sorted (fields_list , key = lambda field : field ['name' ])
73
+
74
+
22
75
def templated (template_name ):
23
76
"""Decorator function to simplify rendering a template.
24
77
@@ -53,210 +106,47 @@ def save_asciidoc(f, text):
53
106
with open (f , "w" ) as outfile :
54
107
outfile .write (text )
55
108
109
+ # jinja2 setup
110
+
111
+
112
+ TEMPLATE_DIR = path .join (path .dirname (path .abspath (__file__ )), '../templates' )
113
+ template_loader = jinja2 .FileSystemLoader (searchpath = TEMPLATE_DIR )
114
+ template_env = jinja2 .Environment (loader = template_loader )
56
115
57
116
# Rendering schemas
58
117
59
118
# Field Index
60
119
61
- @templated ('fields_template.j2' )
120
+
121
+ @templated ('fields.j2' )
62
122
def page_field_index (nested , ecs_version ):
63
123
fieldsets = ecs_helpers .dict_sorted_by_keys (nested , ['group' , 'name' ])
64
124
return dict (ecs_version = ecs_version , fieldsets = fieldsets )
65
125
66
126
67
127
# Field Details Page
68
128
69
-
70
129
def page_field_details (nested ):
71
- page_text = ''
72
- for fieldset in ecs_helpers .dict_sorted_by_keys (nested , ['group' , 'name' ]):
73
- page_text += render_fieldset (fieldset , nested )
74
- return page_text
75
-
76
-
77
- def render_fieldset (fieldset , nested ):
78
- text = field_details_table_header (
79
- title = fieldset ['title' ],
80
- name = fieldset ['name' ],
81
- description = fieldset ['description' ]
82
- )
83
-
84
- text += render_fields (fieldset ['fields' ])
85
-
86
- text += table_footer ()
87
-
88
- text += render_fieldset_reuse_section (fieldset , nested )
89
-
90
- return text
91
-
92
-
93
- def render_fields (fields ):
94
- text = ''
95
- for _ , field in sorted (fields .items ()):
96
- # Skip fields nested in this field set
97
- if 'original_fieldset' not in field :
98
- text += render_field_details_row (field )
99
- return text
100
-
101
-
102
- def render_field_allowed_values (field ):
103
- if not 'allowed_values' in field :
104
- return ''
105
- allowed_values = ', ' .join (ecs_helpers .list_extract_keys (field ['allowed_values' ], 'name' ))
106
-
107
- return field_acceptable_value_names (
108
- allowed_values = allowed_values ,
109
- flat_name = field ['flat_name' ],
110
- dashed_name = field ['dashed_name' ]
111
- )
112
-
113
-
114
- def render_field_details_row (field ):
115
- example = ''
116
- if 'allowed_values' in field :
117
- example = render_field_allowed_values (field )
118
- elif 'example' in field :
119
- example = "example: `{}`" .format (str (field ['example' ]))
120
-
121
- field_type_with_mf = field ['type' ]
122
- if 'multi_fields' in field :
123
- field_type_with_mf += "\n \n Multi-fields:\n \n "
124
- for mf in field ['multi_fields' ]:
125
- field_type_with_mf += "* {} (type: {})\n \n " .format (mf ['flat_name' ], mf ['type' ])
126
-
127
- field_normalization = ''
128
- if 'array' in field ['normalize' ]:
129
- field_normalization = "\n Note: this field should contain an array of values.\n \n "
130
-
131
- text = field_details_row (
132
- flat_name = field ['flat_name' ],
133
- description = field ['description' ],
134
- field_type = field_type_with_mf ,
135
- example = example ,
136
- normalization = field_normalization ,
137
- level = field ['level' ]
138
- )
139
-
140
- return text
141
-
142
-
143
- def render_fieldset_reuse_section (fieldset , nested ):
144
- '''Render the section on where field set can be nested, and which field sets can be nested here'''
145
- if not ('nestings' in fieldset or 'reusable' in fieldset ):
146
- return ''
147
-
148
- text = field_reuse_section (
149
- reuse_of_fieldset = render_fieldset_reuses_text (fieldset )
150
- )
151
-
152
- if 'nestings' in fieldset :
153
- text += nestings_table_header (
154
- name = fieldset ['name' ],
155
- title = fieldset ['title' ]
156
- )
157
- rows = []
158
- for reused_here_entry in fieldset ['reused_here' ]:
159
- rows .append ({
160
- 'flat_nesting' : "{}.*" .format (reused_here_entry ['full' ]),
161
- 'name' : reused_here_entry ['schema_name' ],
162
- 'short' : reused_here_entry ['short' ]
163
- })
164
-
165
- for row in sorted (rows , key = lambda x : x ['flat_nesting' ]):
166
- text += nestings_row (
167
- nesting_name = row ['name' ],
168
- flat_nesting = row ['flat_nesting' ],
169
- nesting_short = row ['short' ]
170
- )
171
-
172
- text += table_footer ()
173
- return text
174
-
175
-
176
- def render_fieldset_reuses_text (fieldset ):
177
- '''Render where a given field set is expected to be reused'''
178
- if 'reusable' not in fieldset :
179
- return ''
180
-
181
- section_name = fieldset ['name' ]
182
- sorted_fields = sorted (fieldset ['reusable' ]['expected' ], key = lambda k : k ['full' ])
183
- rendered_fields = map (lambda f : "`{}`" .format (f ['full' ]), sorted_fields )
184
- text = "The `{}` fields are expected to be nested at: {}.\n \n " .format (
185
- section_name , ', ' .join (rendered_fields ))
186
-
187
- if 'top_level' in fieldset ['reusable' ] and fieldset ['reusable' ]['top_level' ]:
188
- template = "Note also that the `{}` fields may be used directly at the root of the events.\n \n "
189
- else :
190
- template = "Note also that the `{}` fields are not expected to " + \
191
- "be used directly at the root of the events.\n \n "
192
- text += template .format (section_name )
193
- return text
194
-
195
-
196
- # Templates
197
-
198
- def table_footer ():
199
- return '''
200
- |=====
201
- '''
202
-
203
- # Field Details Page
204
-
205
- # Main Fields Table
206
-
207
-
208
- @templated ('field_details/table_header.j2' )
209
- def field_details_table_header (title , name , description ):
210
- return dict (name = name , title = title , description = description )
211
-
212
-
213
- @templated ('field_details/row.j2' )
214
- def field_details_row (flat_name , description , field_type , normalization , example , level ):
215
- return dict (
216
- flat_name = flat_name ,
217
- description = description ,
218
- field_type = field_type ,
219
- normalization = normalization ,
220
- example = example ,
221
- level = level
222
- )
223
-
224
-
225
- @templated ('field_details/acceptable_value_names.j2' )
226
- def field_acceptable_value_names (allowed_values , dashed_name , flat_name ):
227
- return dict (
228
- allowed_values = allowed_values ,
229
- dashed_name = dashed_name ,
230
- flat_name = flat_name
231
- )
232
-
233
-
234
- # Field reuse
235
-
236
- @templated ('field_details/field_reuse_section.j2' )
237
- def field_reuse_section (reuse_of_fieldset ):
238
- return dict (reuse_of_fieldset = reuse_of_fieldset )
239
-
240
-
241
- # Nestings table
242
-
243
- @templated ('field_details/nestings_table_header.j2' )
244
- def nestings_table_header (name , title ):
245
- return dict (name = name , title = title )
130
+ fieldsets = ecs_helpers .dict_sorted_by_keys (nested , ['group' , 'name' ])
131
+ results = (generate_field_details_page (fieldset ) for fieldset in fieldsets )
132
+ return '' .join (results )
246
133
247
134
248
- @templated ('field_details/nestings_row.j2' )
249
- def nestings_row (nesting_name , flat_nesting , nesting_short ):
250
- return dict (
251
- nesting_name = nesting_name ,
252
- flat_nesting = flat_nesting ,
253
- nesting_short = nesting_short
254
- )
135
+ @templated ('field_details.j2' )
136
+ def generate_field_details_page (fieldset ):
137
+ # render field reuse text section
138
+ sorted_reuse_fields = render_fieldset_reuse_text (fieldset )
139
+ render_nestings_reuse_fields = render_nestings_reuse_section (fieldset )
140
+ sorted_fields = sort_fields (fieldset )
141
+ return dict (fieldset = fieldset ,
142
+ sorted_reuse_fields = sorted_reuse_fields ,
143
+ render_nestings_reuse_section = render_nestings_reuse_fields ,
144
+ sorted_fields = sorted_fields )
255
145
256
146
257
147
# Allowed values section
258
148
259
- @templated ('field_values_template .j2' )
149
+ @templated ('field_values .j2' )
260
150
def page_field_values (nested , template_name = 'field_values_template.j2' ):
261
151
category_fields = ['event.kind' , 'event.category' , 'event.type' , 'event.outcome' ]
262
152
nested_fields = []
0 commit comments