From 211af774f24abc2fb065d93c7b66cdd6264e3c01 Mon Sep 17 00:00:00 2001 From: Gleb Nikonorov Date: Fri, 18 Dec 2020 23:54:54 -0500 Subject: [PATCH 1/6] Add untested change --- src/pytest_html/html_report.py | 13 +++++++++++++ src/pytest_html/plugin.py | 6 ++++++ 2 files changed, 19 insertions(+) diff --git a/src/pytest_html/html_report.py b/src/pytest_html/html_report.py index e1aa3973..66e10f07 100644 --- a/src/pytest_html/html_report.py +++ b/src/pytest_html/html_report.py @@ -2,6 +2,7 @@ import datetime import json import os +import re import time from collections import defaultdict from collections import OrderedDict @@ -226,6 +227,10 @@ def _generate_environment(self, config): for key in keys: value = metadata[key] + if self._is_redactable_environment_variable(key, config): + black_box_ascii_value = 0x2593 + value = "".join(chr(black_box_ascii_value) for char in str(value)) + if isinstance(value, str) and value.startswith("http"): value = html.a(value, href=value, target="_blank") elif isinstance(value, (list, tuple, set)): @@ -239,6 +244,14 @@ def _generate_environment(self, config): environment.append(html.table(rows, id="environment")) return environment + def _is_redactable_environment_variable(self, environment_variable, config): + redactable_regexes = config.getini("environment_table_redact_list") + for redactable_regex in redactable_regexes: + if re.match(redactable_regex, environment_variable): + return True + + return False + def _save_report(self, report_content): dir_name = os.path.dirname(self.logfile) assets_dir = os.path.join(dir_name, "assets") diff --git a/src/pytest_html/plugin.py b/src/pytest_html/plugin.py index 6a0ef7a4..7afda7c0 100644 --- a/src/pytest_html/plugin.py +++ b/src/pytest_html/plugin.py @@ -53,6 +53,12 @@ def pytest_addoption(parser): help="set the maximum filename length for assets " "attached to the html report.", ) + parser.addini( + "environment_table_redact_list", + type="linelist", + help="A list of regexes corresponding to environment " + "table keys whose values should be redacted from the report", + ) def pytest_configure(config): From 417d50604213633b3edb62835962f3c75f9d2167 Mon Sep 17 00:00:00 2001 From: Gleb Nikonorov Date: Sat, 19 Dec 2020 01:19:26 -0500 Subject: [PATCH 2/6] Add tests --- testing/test_pytest_html.py | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/testing/test_pytest_html.py b/testing/test_pytest_html.py index b2d23af9..239f96b6 100644 --- a/testing/test_pytest_html.py +++ b/testing/test_pytest_html.py @@ -1209,3 +1209,56 @@ def test_show_capture_no(): assert extra_log_div_regex.search(html) is not None else: assert extra_log_div_regex.search(html) is None + + def test_environment_table_redact_list(self, testdir): + testdir.makeini( + """ + [pytest] + environment_table_redact_list = foo$ + .*redact.* + bar + """ + ) + + testdir.makeconftest( + """ + def pytest_configure(config): + config._metadata["foo"] = "will not appear a" + config._metadata["foos"] = "will appear" + config._metadata["redact"] = "will not appear ab" + config._metadata["will_redact"] = "will not appear abc" + config._metadata["redacted_item"] = "will not appear abcd" + config._metadata["unrelated_item"] = "will appear" + config._metadata["bar"] = "will not appear abcde" + config._metadata["bars"] = "will not appear abcdef" + """ + ) + + testdir.makepyfile( + """ + def test_pass(): + assert True + """ + ) + + result, html = run(testdir) + assert result.ret == 0 + assert_results(html) + + black_box_ascii_value = 0x2593 + expected_environment_values = { + "foo": "".join(chr(black_box_ascii_value) for value in range(17)), + "foos": "will appear", + "redact": "".join(chr(black_box_ascii_value) for value in range(18)), + "will_redact": "".join(chr(black_box_ascii_value) for value in range(19)), + "redacted_item": "".join(chr(black_box_ascii_value) for value in range(20)), + "unrelated_item": "will appear", + "bar": "".join(chr(black_box_ascii_value) for value in range(21)), + "bars": "".join(chr(black_box_ascii_value) for value in range(22)), + } + for variable in expected_environment_values: + variable_value = expected_environment_values[variable] + variable_value_regex = re.compile( + f"\n.*{variable}\n.*{variable_value}" + ) + assert variable_value_regex.search(html) is not None, str(html) From 7c2f9a47d71b9de3897d9a742f08b2164cd1b192 Mon Sep 17 00:00:00 2001 From: Gleb Nikonorov Date: Sat, 19 Dec 2020 09:56:37 -0500 Subject: [PATCH 3/6] Add documentation --- docs/user_guide.rst | 16 ++++++++++++++-- testing/test_pytest_html.py | 4 +++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/docs/user_guide.rst b/docs/user_guide.rst index 072c714c..fc374b5c 100644 --- a/docs/user_guide.rst +++ b/docs/user_guide.rst @@ -80,8 +80,20 @@ Note that in the above example `@pytest.hookimpl(tryfirst=True)`_ is important, If this line is omitted, then the *Environment* table will **not** be updated since the :code:`pytest_sessionfinish` of the plugins will execute first, and thus not pick up your change. -The generated table will be sorted alphabetically unless the metadata is a -:code:`collections.OrderedDict`. +The generated table will be sorted alphabetically unless the metadata is a :code:`collections.OrderedDict`. + +It is also possible to redact variables from the environment table. Redacted variables will have their keys displayed, but their values grayed out. +This can be achieved by setting :code:`environment_table_redact_list` in your INI configuration file (e.g.: :code:`pytest.ini`). +:code:`environment_table_redact_list` is a :code:`linelist` of regexes. Any environment table key that matches a regex in this list has its value redacted. + +For example, the below will redact all environment table values whose keys match the regexes :code:`^foo$`, :code:`.*redact.*`, or :code:`bar`: + +.. code-block:: ini + + [pytest] + environment_table_redact_list = ^foo$ + .*redact.* + bar Additional summary information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/testing/test_pytest_html.py b/testing/test_pytest_html.py index 239f96b6..83c8ca80 100644 --- a/testing/test_pytest_html.py +++ b/testing/test_pytest_html.py @@ -1214,7 +1214,7 @@ def test_environment_table_redact_list(self, testdir): testdir.makeini( """ [pytest] - environment_table_redact_list = foo$ + environment_table_redact_list = ^foo$ .*redact.* bar """ @@ -1224,6 +1224,7 @@ def test_environment_table_redact_list(self, testdir): """ def pytest_configure(config): config._metadata["foo"] = "will not appear a" + config._metadata["afoo"] = "will appear" config._metadata["foos"] = "will appear" config._metadata["redact"] = "will not appear ab" config._metadata["will_redact"] = "will not appear abc" @@ -1248,6 +1249,7 @@ def test_pass(): black_box_ascii_value = 0x2593 expected_environment_values = { "foo": "".join(chr(black_box_ascii_value) for value in range(17)), + "afoo": "will appear", "foos": "will appear", "redact": "".join(chr(black_box_ascii_value) for value in range(18)), "will_redact": "".join(chr(black_box_ascii_value) for value in range(19)), From 9cd8ca34c60cc6ed41961e93a49e9c1a744f3099 Mon Sep 17 00:00:00 2001 From: Gleb Nikonorov Date: Sat, 19 Dec 2020 10:18:14 -0500 Subject: [PATCH 4/6] Add the changelog entry --- docs/changelog.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index ceeca76d..02d075d0 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -13,6 +13,10 @@ Version History * Thanks to `@gnikonorov `_ for the PR +* Implement :code:`environment_table_redact_list` to allow for redaction of environment table values. (`#233 `_) + + * Thanks to `@fenchu `_ for reporting and `@gnikonorov `_ for the PR + 3.1.1 (2020-12-13) ~~~~~~~~~~~~~~~~~~ From d11e414e2230694c9e82d8ae73487630871a99c9 Mon Sep 17 00:00:00 2001 From: Gleb Nikonorov Date: Sat, 19 Dec 2020 10:26:34 -0500 Subject: [PATCH 5/6] remove debug code from test --- testing/test_pytest_html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/test_pytest_html.py b/testing/test_pytest_html.py index 83c8ca80..69341caf 100644 --- a/testing/test_pytest_html.py +++ b/testing/test_pytest_html.py @@ -1263,4 +1263,4 @@ def test_pass(): variable_value_regex = re.compile( f"\n.*{variable}\n.*{variable_value}" ) - assert variable_value_regex.search(html) is not None, str(html) + assert variable_value_regex.search(html) is not None From 01d08d492d96d3cd23260816dafdd3d38f5c0784 Mon Sep 17 00:00:00 2001 From: Gleb Nikonorov Date: Sun, 20 Dec 2020 10:08:44 -0500 Subject: [PATCH 6/6] Change wording of documentation --- docs/user_guide.rst | 6 +++--- src/pytest_html/plugin.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/user_guide.rst b/docs/user_guide.rst index fc374b5c..21340154 100644 --- a/docs/user_guide.rst +++ b/docs/user_guide.rst @@ -82,11 +82,11 @@ and thus not pick up your change. The generated table will be sorted alphabetically unless the metadata is a :code:`collections.OrderedDict`. -It is also possible to redact variables from the environment table. Redacted variables will have their keys displayed, but their values grayed out. +It is possible to redact variables from the environment table. Redacted variables will have their names displayed, but their values grayed out. This can be achieved by setting :code:`environment_table_redact_list` in your INI configuration file (e.g.: :code:`pytest.ini`). -:code:`environment_table_redact_list` is a :code:`linelist` of regexes. Any environment table key that matches a regex in this list has its value redacted. +:code:`environment_table_redact_list` is a :code:`linelist` of regexes. Any environment table variable that matches a regex in this list has its value redacted. -For example, the below will redact all environment table values whose keys match the regexes :code:`^foo$`, :code:`.*redact.*`, or :code:`bar`: +For example, the following will redact all environment table variables that match the regexes :code:`^foo$`, :code:`.*redact.*`, or :code:`bar`: .. code-block:: ini diff --git a/src/pytest_html/plugin.py b/src/pytest_html/plugin.py index 7afda7c0..0034da19 100644 --- a/src/pytest_html/plugin.py +++ b/src/pytest_html/plugin.py @@ -57,7 +57,7 @@ def pytest_addoption(parser): "environment_table_redact_list", type="linelist", help="A list of regexes corresponding to environment " - "table keys whose values should be redacted from the report", + "table variables whose values should be redacted from the report", )