Skip to content

Commit 3bfaa5c

Browse files
committed
Blacklist fn accepts custop functions
1 parent f987818 commit 3bfaa5c

3 files changed

Lines changed: 71 additions & 47 deletions

File tree

python/humbug/blacklist.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""
2+
Various implementations of the blacklist functionality.
3+
"""
4+
from typing import Any, Dict, List, Optional
5+
6+
7+
def filter_parameters_by_key(
8+
blacklist_keys: List[str],
9+
parameters: Dict[str, Any],
10+
) -> Dict[str, Any]:
11+
"""
12+
Applies blacklist filter to provided parameters and to 2nd layer of
13+
inner dictionary parameter if exists.
14+
"""
15+
whitelisted_parameters: Dict[str, Any] = {}
16+
17+
for key in parameters.keys():
18+
if key.lower() in blacklist_keys:
19+
continue
20+
21+
key_as_dict: Optional[Dict[str, Any]] = None
22+
for d in dir(parameters[key]):
23+
if d == "keys":
24+
key_as_dict = parameters[key]
25+
break
26+
elif d == "dict": # Pydantic models support
27+
key_as_dict = parameters[key].dict()
28+
break
29+
30+
if key_as_dict is not None:
31+
try:
32+
inner_dict: Dict[str, str] = {}
33+
for inner_key in key_as_dict.keys():
34+
if inner_key.lower() in blacklist_keys:
35+
continue
36+
inner_dict[inner_key] = str(key_as_dict[inner_key])
37+
whitelisted_parameters[key] = inner_dict
38+
continue
39+
except Exception:
40+
pass
41+
42+
whitelisted_parameters[key] = str(parameters[key])
43+
44+
return whitelisted_parameters

python/humbug/report.py

Lines changed: 9 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,10 @@ def __init__(
6060
mode: Modes = Modes.DEFAULT,
6161
url: Optional[str] = None,
6262
tags: Optional[List[str]] = None,
63-
blacklisted_keys: Optional[List[str]] = None,
63+
blacklist_keys: List[str] = [],
64+
blacklist_fn: Optional[
65+
Callable[[List[str], Dict[str, Any]], Dict[str, Any]]
66+
] = None,
6467
):
6568
if url is None:
6669
url = DEFAULT_URL
@@ -94,9 +97,8 @@ def __init__(
9497
if tags is not None:
9598
self.tags = tags
9699

97-
self.blacklisted_keys: List[str] = []
98-
if blacklisted_keys is not None:
99-
self.blacklisted_keys = blacklisted_keys
100+
self.blacklist_keys = blacklist_keys
101+
self.blacklist_fn = blacklist_fn
100102

101103
def wait(self) -> None:
102104
concurrent.futures.wait(
@@ -124,44 +126,6 @@ def system_tags(self) -> List[str]:
124126

125127
return tags
126128

127-
def _apply_blacklist_to_parameters(
128-
self, parameters: Dict[str, Any]
129-
) -> Dict[str, Any]:
130-
"""
131-
Applies blacklist filter to provided parameters and to 2nd layer of
132-
inner dictionary parameter if exists.
133-
"""
134-
whitelisted_parameters: Dict[str, Any] = {}
135-
136-
for key in parameters.keys():
137-
if key in self.blacklisted_keys:
138-
continue
139-
140-
key_as_dict: Optional[Dict[str, Any]] = None
141-
for d in dir(parameters[key]):
142-
if d == "keys":
143-
key_as_dict = parameters[key]
144-
break
145-
elif d == "dict": # Pydantic models support
146-
key_as_dict = parameters[key].dict()
147-
break
148-
149-
if key_as_dict is not None:
150-
try:
151-
inner_dict: Dict[str, str] = {}
152-
for inner_key in key_as_dict.keys():
153-
if inner_key in self.blacklisted_keys:
154-
continue
155-
inner_dict[inner_key] = str(key_as_dict[inner_key])
156-
whitelisted_parameters[key] = inner_dict
157-
continue
158-
except Exception:
159-
pass
160-
161-
whitelisted_parameters[key] = str(parameters[key])
162-
163-
return whitelisted_parameters
164-
165129
def _post_body(self, report: Report) -> Dict[str, Any]:
166130
return {
167131
"title": report.title,
@@ -429,12 +393,12 @@ def feature_report(
429393
tags: Optional[List[str]] = None,
430394
publish: bool = True,
431395
wait: bool = False,
432-
blacklist_apply: bool = True,
396+
apply_blacklist: bool = True,
433397
) -> Report:
434398
title = "Feature used: {name}".format(name=feature_name)
435399

436-
if blacklist_apply:
437-
parameters = self._apply_blacklist_to_parameters(parameters)
400+
if apply_blacklist and self.blacklist_fn is not None:
401+
parameters = self.blacklist_fn(self.blacklist_keys, parameters)
438402

439403
parameters_content = "\n".join(
440404
[

python/humbug/test_report.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import unittest
22
from unittest.mock import MagicMock
33

4-
from . import consent, report
4+
from . import consent, report, blacklist
55

66

77
class TestReporter(unittest.TestCase):
@@ -11,7 +11,8 @@ def setUp(self):
1111
name="TestReporter",
1212
consent=self.consent,
1313
tags=["humbug-unit-test"],
14-
blacklisted_keys=["private"],
14+
blacklist_keys=["private"],
15+
blacklist_fn=blacklist.filter_parameters_by_key,
1516
)
1617
self.reporter.publish = MagicMock()
1718

@@ -92,6 +93,21 @@ def test_feature_report(self):
9293
)
9394
self.assertTrue("parameter:{}={{}}".format("inner") in report.tags)
9495

96+
def test_feature_report_not_apply_blacklist(self):
97+
report = self.reporter.feature_report(
98+
"test_feature_not_apply_blacklist",
99+
{
100+
"private": "confidential",
101+
"inner": {"private": "confidential"},
102+
},
103+
publish=False,
104+
apply_blacklist=False,
105+
)
106+
self.assertTrue(
107+
"parameter:{}={}".format("private", "confidential") in report.tags
108+
)
109+
self.assertTrue("parameter:{}={{}}".format("inner") not in report.tags)
110+
95111
def test_record_call(self):
96112
@self.reporter.record_call
97113
def the_answer(life, universe=None, everything=None):

0 commit comments

Comments
 (0)