Skip to content

Commit 5f0daed

Browse files
feat: add params parameter to the multiscan of ggclient
1 parent bba60b1 commit 5f0daed

File tree

4 files changed

+77
-0
lines changed

4 files changed

+77
-0
lines changed

pygitguardian/client.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ def multi_content_scan(
273273
self,
274274
documents: List[Dict[str, str]],
275275
extra_headers: Optional[Dict[str, str]] = None,
276+
ignore_known_secrets: Optional[bool] = None,
276277
) -> Union[Detail, MultiScanResult]:
277278
"""
278279
multi_content_scan handles the /multiscan endpoint of the API.
@@ -284,6 +285,7 @@ def multi_content_scan(
284285
and, optionally, filename.
285286
example: [{"document":"example content","filename":"intro.py"}]
286287
:param extra_headers: additional headers to add to the request
288+
:param ignore_known_secrets: indicates whether known secrets should be ignored
287289
:return: Detail or ScanResult response and status code
288290
"""
289291
if len(documents) > MULTI_DOCUMENT_LIMIT:
@@ -298,10 +300,16 @@ def multi_content_scan(
298300
else:
299301
raise TypeError("each document must be a dict")
300302

303+
params = (
304+
{"ignore_known_secrets": ignore_known_secrets}
305+
if ignore_known_secrets
306+
else {}
307+
)
301308
resp = self.post(
302309
endpoint="multiscan",
303310
data=request_obj,
304311
extra_headers=extra_headers,
312+
params=params,
305313
)
306314

307315
obj: Union[Detail, MultiScanResult]

pygitguardian/models.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ class PolicyBreakSchema(BaseSchema):
205205
break_type = fields.String(data_key="type", required=True)
206206
policy = fields.String(required=True)
207207
validity = fields.String(required=False, load_default=None, dump_default=None)
208+
known_secret = fields.Boolean(required=False, load_default=False, dump_default=None)
208209
matches = fields.List(fields.Nested(MatchSchema), required=True)
209210

210211
@post_load
@@ -228,12 +229,14 @@ def __init__(
228229
policy: str,
229230
validity: str,
230231
matches: List[Match],
232+
known_secret: bool = False,
231233
**kwargs: Any,
232234
) -> None:
233235
super().__init__()
234236
self.break_type = break_type
235237
self.policy = policy
236238
self.validity = validity
239+
self.known_secret = known_secret
237240
self.matches = matches
238241

239242
@property

tests/test_client.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,52 @@ def test_extra_headers(
548548
assert expected_headers == kwargs["headers"]
549549

550550

551+
@patch("requests.Session.request")
552+
def test_multiscan_parameters(
553+
request_mock: Mock,
554+
client: GGClient,
555+
):
556+
"""
557+
GIVEN a ggclient
558+
WHEN calling multi_content_scan with parameters
559+
THEN the parameters are passed in the request
560+
"""
561+
mock_response = Mock(spec=Response)
562+
mock_response.headers = {"content-type": "application/json"}
563+
mock_response.status_code = 200
564+
mock_response.json.return_value = [
565+
{
566+
"policy_break_count": 1,
567+
"policies": ["pol"],
568+
"policy_breaks": [
569+
{
570+
"type": "break",
571+
"policy": "mypol",
572+
"matches": [
573+
{
574+
"match": "hello",
575+
"type": "hello",
576+
}
577+
],
578+
}
579+
],
580+
}
581+
]
582+
583+
request_mock.return_value = mock_response
584+
585+
params = {"ignore_known_secrets": True}
586+
587+
client.multi_content_scan(
588+
[{"filename": FILENAME, "document": DOCUMENT}],
589+
ignore_known_secrets=True,
590+
)
591+
592+
assert request_mock.called
593+
# 1 is for kwargs
594+
assert request_mock.call_args[1]["params"] == params
595+
596+
551597
def test_quota_overview(client: GGClient):
552598
with my_vcr.use_cassette("quota.yaml"):
553599
quota_response = client.quota_overview()

tests/test_models.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,23 @@ def test_detail_renames_error_field(self):
147147
"""
148148
detail = Detail.SCHEMA.load({"error": "An error message"})
149149
assert detail.detail == "An error message"
150+
151+
@pytest.mark.parametrize("known_secret", [True, False])
152+
def test_policy_break_known_secret_field(self, known_secret):
153+
"""
154+
GIVEN the data with policy breaks
155+
WHEN loading using the schema
156+
THEN known_secret is parsed correctly with the default value set to False
157+
"""
158+
data = {
159+
"type": "hello",
160+
"policy": "hello",
161+
"validity": "hey",
162+
"matches": [{"match": "hello", "type": "hello"}],
163+
}
164+
if known_secret:
165+
data["known_secret"] = True
166+
167+
obj = PolicyBreakSchema().load(data)
168+
169+
assert obj.known_secret is known_secret

0 commit comments

Comments
 (0)