Skip to content

Commit 85156f4

Browse files
Enable logs v2 api (#95)
1 parent 86effae commit 85156f4

File tree

73 files changed

+1042
-810
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+1042
-810
lines changed

.apigentools-info

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
"spec_versions": {
55
"v1": {
66
"apigentools_version": "1.2.0",
7-
"regenerated": "2020-09-30 11:19:01.491807",
8-
"spec_repo_commit": "cbeec4e"
7+
"regenerated": "2020-09-30 14:11:12.314239",
8+
"spec_repo_commit": "8738cfd"
99
},
1010
"v2": {
1111
"apigentools_version": "1.2.0",
12-
"regenerated": "2020-09-30 11:19:13.143953",
13-
"spec_repo_commit": "cbeec4e"
12+
"regenerated": "2020-09-30 14:11:22.976815",
13+
"spec_repo_commit": "8738cfd"
1414
}
1515
}
1616
}

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ tests =
5656
freezegun
5757
jinja2
5858
pytest
59-
pytest-bdd==3.4.0
59+
pytest-bdd>=4.0.1
6060
pytest-black
6161
pytest-cov
6262
pytest-randomly

tests/conftest.py

Lines changed: 80 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
# coding=utf-8
22
"""Define basic fixtures."""
33

4+
import os
5+
46
# First patch httplib
5-
try:
6-
from ddtrace import config, patch, tracer
7+
tracer = None
8+
if "false" != os.getenv("RECORD", "false"):
9+
try:
10+
from ddtrace import config, patch, tracer
711

8-
config.httplib["distributed_tracing"] = True
9-
patch(httplib=True)
10-
except ImportError:
11-
tracer = None
12+
config.httplib["distributed_tracing"] = True
13+
patch(httplib=True)
14+
except ImportError:
15+
pass
1216

1317
import importlib
1418
import json
1519
import logging
16-
import os
1720
import re
1821
import sys
1922
import time
@@ -123,7 +126,10 @@ def pytest_bdd_apply_tag(tag, function):
123126

124127
def snake_case(value):
125128
s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", value)
126-
return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower()
129+
s1 = re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower()
130+
s1 = re.sub(r"\W", "_", s1)
131+
s1 = re.sub(r"_+$", "", s1)
132+
return re.sub(r"__+", "_", s1)
127133

128134

129135
def glom(value, path):
@@ -173,17 +179,28 @@ def __str__(self):
173179

174180

175181
@pytest.fixture
176-
def fixtures(request, unique, unique_lower):
177-
"""Return a mapping with all defined fixtures."""
178-
ctx = {}
182+
def context(vcr_cassette, request, unique, unique_lower):
183+
"""
184+
Return a mapping with all defined fixtures, all objects created by `given` steps,
185+
and the undo operations to perform after a test scenario.
186+
"""
187+
ctx = {"undo_operations": []}
179188
for f in request.fixturenames:
180-
if f == "fixtures":
189+
if f == "context":
181190
continue
182191
try:
183192
ctx[f] = request.getfixturevalue(f)
184193
except Exception:
185194
pass
186-
return ctx
195+
yield ctx
196+
for undo in reversed(ctx["undo_operations"]):
197+
if vcr_cassette.record_mode != "none":
198+
number_of_interactions = len(vcr_cassette.data)
199+
try:
200+
undo()
201+
except Exception as e:
202+
warnings.warn(str(e))
203+
vcr_cassette.data = vcr_cassette.data[:number_of_interactions]
187204

188205

189206
@pytest.fixture(scope="module", autouse=True)
@@ -226,10 +243,11 @@ def freezer(vcr_cassette_name, vcr_cassette, vcr):
226243
if vcr_cassette.record_mode != "none":
227244
tzinfo = datetime.now().astimezone().tzinfo
228245
freeze_at = datetime.now().replace(tzinfo=tzinfo).isoformat()
229-
with open(
230-
os.path.join(vcr.cassette_library_dir, vcr_cassette_name + ".frozen"), "w+",
231-
) as f:
232-
f.write(freeze_at)
246+
if vcr_cassette.record_mode == "all":
247+
with open(
248+
os.path.join(vcr.cassette_library_dir, vcr_cassette_name + ".frozen"), "w+",
249+
) as f:
250+
f.write(freeze_at)
233251
else:
234252
with open(
235253
os.path.join(vcr.cassette_library_dir, vcr_cassette_name + ".frozen"), "r",
@@ -276,25 +294,27 @@ def client(_package, configuration, record_mode, vcr_cassette):
276294

277295

278296
@given(parsers.parse('an instance of "{name}" API'))
279-
def api(package_name, client, name):
297+
def api(context, package_name, client, name):
280298
"""Return an API instance."""
281299
module_name = snake_case(name)
282300
package = importlib.import_module(f"{package_name}.api.{module_name}_api")
283-
return {
301+
context["api"] = {
284302
"api": getattr(package, name + "Api")(client),
285303
"calls": [],
286304
}
287305

306+
288307
@given(parsers.parse('operation "{name}" enabled'))
289308
def operation_enabled(client, name):
290309
"""Enable the unstable operation specific in the clause."""
291310
client.configuration.unstable_operations[snake_case(name)] = True
292311

293312

294313
@given(parsers.parse('new "{name}" request'))
295-
def api_request(api, name):
314+
def api_request(context, name):
296315
"""Call an endpoint."""
297-
return {
316+
api = context["api"]
317+
context["api_request"] = {
298318
"api": api["api"],
299319
"request": getattr(api["api"], snake_case(name)),
300320
"args": [],
@@ -312,22 +332,29 @@ def api_request(api, name):
312332

313333

314334
@given(parsers.parse("body {data}"))
315-
def request_body(fixtures, api_request, data):
335+
def request_body(context, data):
316336
"""Set request body."""
317337
import json
318338
from jinja2 import Template
319339

320-
tpl = Template(data).render(**fixtures)
321-
body = api_request["kwargs"]["body"] = json.loads(tpl)
322-
323-
return body
340+
tpl = Template(data).render(**context)
341+
context["api_request"]["kwargs"]["body"] = json.loads(tpl)
324342

325343

326344
@given(parsers.parse('request contains "{name}" parameter from "{path}"'))
327-
def request_parameter(fixtures, api_request, name, path):
345+
def request_parameter(context, name, path):
328346
"""Set request parameter."""
329-
api_request["kwargs"][name] = parameter = glom(fixtures, path)
330-
return parameter
347+
context["api_request"]["kwargs"][snake_case(name)] = glom(context, path)
348+
349+
350+
@given(parsers.parse('request contains "{name}" parameter with value {value}'))
351+
def request_parameter_with_value(context, name, value):
352+
"""Set request parameter."""
353+
import json
354+
from jinja2 import Template
355+
356+
tpl = Template(value).render(**context)
357+
context["api_request"]["kwargs"][snake_case(name)] = json.loads(tpl)
331358

332359

333360
def undo(api_request, client):
@@ -343,16 +370,24 @@ def undo(api_request, client):
343370
elif operation_id == "create_team":
344371
client.configuration.unstable_operations["delete_team"] = True
345372
return api_request["api"].delete_team(api_request["response"][0].data.id)
346-
elif operation_id in {"update_user", "add_permission_to_role", "add_user_to_role", "send_invitations"}:
373+
elif operation_id in {
374+
"update_user",
375+
"add_permission_to_role",
376+
"add_user_to_role",
377+
"send_invitations",
378+
"aggregate_logs",
379+
"list_logs",
380+
}:
347381
return
348382
elif api_request["request"].settings["http_method"] == "PATCH":
349383
return
350384
raise NotImplementedError(operation_id)
351385

352386

353387
@when("the request is sent")
354-
def execute_request(vcr_cassette, api_request, client):
388+
def execute_request(context, vcr_cassette, client):
355389
"""Execute the prepared request."""
390+
api_request = context["api_request"]
356391
api_request["response"] = api_request["request"].call_with_http_info(
357392
*api_request["args"], **api_request["kwargs"]
358393
)
@@ -369,41 +404,41 @@ def execute_request(vcr_cassette, api_request, client):
369404

370405

371406
@then(parsers.parse('I should get an instance of "{name}"'))
372-
def i_should_get_an_instace_of(package_name, api, name):
407+
def i_should_get_an_instace_of(context, package_name, name):
373408
"""I should get an instace."""
374409
module_name = snake_case(name)
375410
package = importlib.import_module(f"{package_name}.model.{module_name}")
376-
assert isinstance(api_request["response"][0], getattr(package, name))
411+
assert isinstance(context["api_request"]["response"][0], getattr(package, name))
377412

378413

379414
@then(parsers.parse('I should get a list of "{name}" objects'))
380-
def i_should_get_a_list_of_objects(package_name, api, name):
415+
def i_should_get_a_list_of_objects(context, package_name, name):
381416
"""I should get an instace."""
382417
module_name = snake_case(name)
383418
package = importlib.import_module(f"{package_name}.model.{module_name}")
384419
cls = getattr(package, name)
385-
assert all(isinstance(obj, cls) for obj in api_request["response"][0])
420+
assert all(isinstance(obj, cls) for obj in context["api_request"]["response"][0])
386421

387422

388423
@then(parsers.parse("the response status is {status:d} {description}"))
389-
def the_status_is(api_request, status, description):
424+
def the_status_is(context, status, description):
390425
"""Check the status."""
391-
assert status == api_request["response"][1]
426+
assert status == context["api_request"]["response"][1]
392427

393428

394429
@then(parsers.parse('the response "{response_path}" is equal to {value}'))
395-
def expect_equal(api_request, fixtures, response_path, value):
430+
def expect_equal(context, response_path, value):
396431
from jinja2 import Template
397432

398-
response_value = glom(api_request["response"][0], response_path)
399-
test_value = json.loads(Template(value).render(**fixtures))
433+
response_value = glom(context["api_request"]["response"][0], response_path)
434+
test_value = json.loads(Template(value).render(**context))
400435
assert test_value == response_value
401436

402437

403438
@then(parsers.parse('the response "{response_path}" has the same value as "{fixture_path}"'))
404-
def expect_equal_value(api_request, fixtures, response_path, fixture_path):
405-
fixture_value = glom(fixtures, fixture_path)
406-
response_value = glom(api_request["response"][0], response_path)
439+
def expect_equal_value(context, response_path, fixture_path):
440+
fixture_value = glom(context, fixture_path)
441+
response_value = glom(context["api_request"]["response"][0], response_path)
407442
assert fixture_value == response_value
408443

409444

@@ -414,6 +449,6 @@ def expect_equal_value(api_request, fixtures, response_path, fixture_length):
414449

415450

416451
@then(parsers.parse('the response "{response_path}" is false'))
417-
def expect_false(api_request, response_path):
418-
response_value = glom(api_request["response"][0], response_path)
452+
def expect_false(context, response_path):
453+
response_value = glom(context["api_request"]["response"][0], response_path)
419454
assert not response_value
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2020-09-24T15:22:49.668210+02:00

tests/v1/cassettes/test_list_ip_ranges_returns_ok_response.yaml

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ interactions:
99
Dd-Operation-Id:
1010
- GetIpRanges
1111
User-Agent:
12-
- datadog-api-client-python/0.1.dev67+dirty (python 3.8.5; os Darwin; arch x86_64)
12+
- datadog-api-client-python/0.1.dev66+dirty (python 3.8.2; os Darwin; arch x86_64)
1313
x-datadog-parent-id:
14-
- '3810264299572682533'
14+
- '10148525951698483321'
1515
x-datadog-sampling-priority:
1616
- '1'
1717
x-datadog-trace-id:
18-
- '18298303860074712282'
18+
- '10171452926111618949'
1919
method: GET
2020
uri: https://ip-ranges.datadoghq.com/
2121
response:
@@ -316,16 +316,14 @@ interactions:
316316
headers:
317317
Accept-Ranges:
318318
- bytes
319-
Age:
320-
- '32'
321319
Connection:
322320
- keep-alive
323321
Content-Length:
324322
- '27449'
325323
Content-Type:
326324
- application/json
327325
Date:
328-
- Fri, 18 Sep 2020 11:51:12 GMT
326+
- Thu, 24 Sep 2020 13:22:51 GMT
329327
ETag:
330328
- '"a10a4e3f85ed8c2509855388e149972a"'
331329
Last-Modified:
@@ -335,13 +333,13 @@ interactions:
335333
Vary:
336334
- Accept-Encoding
337335
Via:
338-
- 1.1 960b47175d6cfc9ed048624de2747035.cloudfront.net (CloudFront)
336+
- 1.1 bfb83f89a06636844c21e465f3ea5acf.cloudfront.net (CloudFront)
339337
X-Amz-Cf-Id:
340-
- 5ags5K5jwp3hZhwNEgfIo8HYE8a8H1kJQCFA2CCWxvwO9dV6q4JyzQ==
338+
- T8zhfoQyuT0N75mlu4Kmot22acMZbddJm1TLEyMHcHZkborBncUEWQ==
341339
X-Amz-Cf-Pop:
342-
- MAD51-C2
340+
- CDG3-C2
343341
X-Cache:
344-
- Hit from cloudfront
342+
- RefreshHit from cloudfront
345343
status:
346344
code: 200
347345
message: OK
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2020-09-18T13:52:21.913614+02:00
1+
2020-09-24T12:01:15.787127+02:00

0 commit comments

Comments
 (0)