From 6e865a233099a00e9ea08f6a2f911ede3c7b4215 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 11 Dec 2019 16:19:10 -0500 Subject: Add a summary() function for configuration summarization Based on patch from Dylan Baker. Fixes #757 --- docs/markdown/Reference-manual.md | 52 +++++++++++++++++++++++++++++++++++++++ docs/markdown/snippets/summary.md | 37 ++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 docs/markdown/snippets/summary.md (limited to 'docs') diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 4f98025f4..e4c18a176 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -1206,6 +1206,58 @@ This function prints its argument to stdout prefixed with WARNING:. *Added 0.44.0* +### summary() + +``` meson + void summary(section_name, dictionary) +``` + +This function is used to summarize build configuration at the end of the build +process. This function provides a way for projects (and subprojects) to report +this information in a clear way. + +The first argument is a section name, the second argument is a dictionary. +`summary()` can be called multiple times as long as the same dict key doesn't +appear twice in the same section. All sections will be collected and printed at +the end of the configuration in the same order as they have been called. + +Dictionary values can only be lists, integers, booleans or strings. + +Example: +```meson +project('My Project', version : '1.0') +summary('Directories', {'bindir': get_option('bindir'), + 'libdir': get_option('libdir'), + 'datadir': get_option('datadir'), + }) +summary('Configuration', {'Some boolean': false, + 'Another boolean': true, + 'Some string': 'Hello World', + 'A list': ['string', 1, true], + }) +``` + +Output: +``` +My Project 1.0 + + Directories + prefix: /opt/gnome + bindir: bin + libdir: lib/x86_64-linux-gnu + datadir: share + + Configuration + Some boolean: False + Another boolean: True + Some string: Hello World + A list: string + 1 + True +``` + +*Added 0.53.0* + ### project() ``` meson diff --git a/docs/markdown/snippets/summary.md b/docs/markdown/snippets/summary.md new file mode 100644 index 000000000..c5d64fdb5 --- /dev/null +++ b/docs/markdown/snippets/summary.md @@ -0,0 +1,37 @@ +## Add a new summary() function + +A new function [`summary()`](Reference-manual.md#summary) has been added to +summarize build configuration at the end of the build process. + +Example: +```meson +project('My Project', version : '1.0') +summary('Directories', {'bindir': get_option('bindir'), + 'libdir': get_option('libdir'), + 'datadir': get_option('datadir'), + }) +summary('Configuration', {'Some boolean': false, + 'Another boolean': true, + 'Some string': 'Hello World', + 'A list': ['string', 1, true], + }) +``` + +Output: +``` +My Project 1.0 + + Directories + prefix: /opt/gnome + bindir: bin + libdir: lib/x86_64-linux-gnu + datadir: share + + Configuration + Some boolean: False + Another boolean: True + Some string: Hello World + A list: string + 1 + True +``` -- cgit v1.2.3 From 49082f96698fbb74b587ca774dae45b7b5943a16 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 11 Dec 2019 21:00:46 -0500 Subject: summary: Allow section with no title, and passing key/value separately --- docs/markdown/Reference-manual.md | 17 ++++++++---- mesonbuild/interpreter.py | 32 ++++++++++++++++------ run_unittests.py | 11 +++----- test cases/unit/74 summary/meson.build | 6 +--- .../unit/74 summary/subprojects/sub/meson.build | 3 +- 5 files changed, 43 insertions(+), 26 deletions(-) (limited to 'docs') diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index e4c18a176..cf5585b74 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -1209,6 +1209,9 @@ This function prints its argument to stdout prefixed with WARNING:. ### summary() ``` meson + void summary(key, value) + void summary(dictionary) + void summary(section_name, key, value) void summary(section_name, dictionary) ``` @@ -1216,12 +1219,16 @@ This function is used to summarize build configuration at the end of the build process. This function provides a way for projects (and subprojects) to report this information in a clear way. -The first argument is a section name, the second argument is a dictionary. -`summary()` can be called multiple times as long as the same dict key doesn't -appear twice in the same section. All sections will be collected and printed at -the end of the configuration in the same order as they have been called. +The content is a serie of key/value pairs grouped into sections. If the section +argument is omitted, those key/value pairs are implicitly grouped into a section +with no title. key/value pairs can optionally be grouped into a dictionary, +but keep in mind that dictionaries does not guarantee ordering. +`section_name` and `key` must be strings, `value` can only be lists, integers, +booleans or strings. -Dictionary values can only be lists, integers, booleans or strings. +`summary()` can be called multiple times as long as the same section_name/key +pair doesn't appear twice. All sections will be collected and printed at +the end of the configuration in the same order as they have been called. Example: ```meson diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index a8e35fe06..2d937e549 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1775,7 +1775,8 @@ class Summary: mlog.log(self.project_name, mlog.normal_cyan(self.project_version)) for section, values in self.sections.items(): mlog.log('') # newline - mlog.log(' ', mlog.bold(section)) + if section: + mlog.log(' ', mlog.bold(section)) for k, v in values.items(): indent = self.max_key_len - len(k) + 3 mlog.log(' ' * indent, k + ':', v[0]) @@ -2871,13 +2872,28 @@ external dependencies (including libraries) must go to "dependencies".''') @noKwargs @FeatureNew('summary', '0.53.0') def func_summary(self, node, args, kwargs): - if len(args) != 2: - raise InterpreterException('Summary accepts exactly two arguments.') - section, values = args - if not isinstance(section, str): - raise InterpreterException('Argument 1 must be a string.') - if not isinstance(values, dict): - raise InterpreterException('Argument 2 must be a dictionary.') + if len(args) == 1: + if not isinstance(args[0], dict): + raise InterpreterException('Argument 1 must be a dictionary.') + section = '' + values = args[0] + elif len(args) == 2: + if not isinstance(args[0], str): + raise InterpreterException('Argument 1 must be a string.') + if isinstance(args[1], dict): + section, values = args + else: + section = '' + values = {args[0]: args[1]} + elif len(args) == 3: + if not isinstance(args[0], str): + raise InterpreterException('Argument 1 must be a string.') + if not isinstance(args[1], str): + raise InterpreterException('Argument 2 must be a string.') + section, key, value = args + values = {key: value} + else: + raise InterpreterException('Summary accepts at most 3 arguments.') if self.subproject not in self.summary: self.summary[self.subproject] = Summary(self.active_projectname, self.project_version) self.summary[self.subproject].add_section(section, values) diff --git a/run_unittests.py b/run_unittests.py index 9167d1401..cb5086cf2 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -4122,16 +4122,12 @@ recommended as it is not supported on some platforms''') expected = textwrap.dedent(r''' Some Subproject 2.0 - Features - foo: bar + string: bar + integer: 1 + boolean: True My Project 1.0 - Directories - bindir: bin - libdir: lib - datadir: share - Configuration Some boolean: False Another boolean: True @@ -4139,6 +4135,7 @@ recommended as it is not supported on some platforms''') A list: string 1 True + A number: 1 ''') # Dict ordering is not guaranteed and an exact string comparison randomly # fails on the CI because lines are reordered. diff --git a/test cases/unit/74 summary/meson.build b/test cases/unit/74 summary/meson.build index 11f96d089..392d940c5 100644 --- a/test cases/unit/74 summary/meson.build +++ b/test cases/unit/74 summary/meson.build @@ -1,10 +1,5 @@ project('My Project', version : '1.0') -summary('Directories', {'bindir': get_option('bindir'), - 'libdir': get_option('libdir'), - 'datadir': get_option('datadir'), - }) - subproject('sub') subproject('sub2', required : false) @@ -13,3 +8,4 @@ summary('Configuration', {'Some boolean': false, 'Some string': 'Hello World', 'A list': ['string', 1, true], }) +summary('Configuration', 'A number', 1) diff --git a/test cases/unit/74 summary/subprojects/sub/meson.build b/test cases/unit/74 summary/subprojects/sub/meson.build index f47c7b794..e7d783384 100644 --- a/test cases/unit/74 summary/subprojects/sub/meson.build +++ b/test cases/unit/74 summary/subprojects/sub/meson.build @@ -1,3 +1,4 @@ project('Some Subproject', version : '2.0') -summary('Features', {'foo': 'bar'}) +summary('string', 'bar') +summary({'integer': 1, 'boolean': true}) -- cgit v1.2.3 From 38953d8ee32bf025018c44e1e5a5edc04319dd90 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 11 Dec 2019 21:21:21 -0500 Subject: summary: Add bool_yn keyword argument --- docs/markdown/Reference-manual.md | 4 ++++ mesonbuild/interpreter.py | 19 +++++++++++++------ run_unittests.py | 2 ++ test cases/unit/74 summary/meson.build | 2 ++ 4 files changed, 21 insertions(+), 6 deletions(-) (limited to 'docs') diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index cf5585b74..d1fe55b7c 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -1230,6 +1230,10 @@ booleans or strings. pair doesn't appear twice. All sections will be collected and printed at the end of the configuration in the same order as they have been called. +Keyword arguments: +- `bool_yn` if set to true, all boolean values will be replaced by green YES + or red NO. + Example: ```meson project('My Project', version : '1.0') diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 2d937e549..e12c0e91d 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1759,16 +1759,23 @@ class Summary: self.sections = collections.defaultdict(dict) self.max_key_len = 0 - def add_section(self, section, values): + def add_section(self, section, values, kwargs): + bool_yn = kwargs.get('bool_yn', False) + if not isinstance(bool_yn, bool): + raise InterpreterException('bool_yn keyword argument must be boolean') for k, v in values.items(): if k in self.sections[section]: raise InterpreterException('Summary section {!r} already have key {!r}'.format(section, k)) - v = listify(v) - for i in v: + formatted_values = [] + for i in listify(v): if not isinstance(i, (str, int)): m = 'Summary value in section {!r}, key {!r}, must be string, integer or boolean' raise InterpreterException(m.format(section, k)) - self.sections[section][k] = v + if bool_yn and isinstance(i, bool): + formatted_values.append(mlog.green('YES') if i else mlog.red('NO')) + else: + formatted_values.append(i) + self.sections[section][k] = formatted_values self.max_key_len = max(self.max_key_len, len(k)) def dump(self): @@ -2869,7 +2876,7 @@ external dependencies (including libraries) must go to "dependencies".''') mlog.log(mlog.bold('Message:'), argstr) @noArgsFlattening - @noKwargs + @permittedKwargs({'bool_yn'}) @FeatureNew('summary', '0.53.0') def func_summary(self, node, args, kwargs): if len(args) == 1: @@ -2896,7 +2903,7 @@ external dependencies (including libraries) must go to "dependencies".''') raise InterpreterException('Summary accepts at most 3 arguments.') if self.subproject not in self.summary: self.summary[self.subproject] = Summary(self.active_projectname, self.project_version) - self.summary[self.subproject].add_section(section, values) + self.summary[self.subproject].add_section(section, values, kwargs) def _print_summary(self): mlog.log('') # newline diff --git a/run_unittests.py b/run_unittests.py index cb5086cf2..a3a3ac24e 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -4136,6 +4136,8 @@ recommended as it is not supported on some platforms''') 1 True A number: 1 + yes: YES + no: NO ''') # Dict ordering is not guaranteed and an exact string comparison randomly # fails on the CI because lines are reordered. diff --git a/test cases/unit/74 summary/meson.build b/test cases/unit/74 summary/meson.build index 392d940c5..c689f96d8 100644 --- a/test cases/unit/74 summary/meson.build +++ b/test cases/unit/74 summary/meson.build @@ -9,3 +9,5 @@ summary('Configuration', {'Some boolean': false, 'A list': ['string', 1, true], }) summary('Configuration', 'A number', 1) +summary('Configuration', 'yes', true, bool_yn : true) +summary('Configuration', 'no', false, bool_yn : true) -- cgit v1.2.3