Coverage for src/gitlabracadabra/tests/vcrfuncs.py: 97%
61 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-23 06:44 +0200
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-23 06:44 +0200
1#
2# Copyright (C) 2019-2025 Mathieu Parent <math.parent@gmail.com>
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Lesser General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Lesser General Public License for more details.
13#
14# You should have received a copy of the GNU Lesser General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
17import inspect
18import os
19import re
20from base64 import standard_b64decode, standard_b64encode
22from vcr import VCR
23from vcr.matchers import body
26def _gitlabracadabra_func_path_generator(function):
27 func_file = inspect.getfile(function)
28 method_name = function.__name__ # test_no_create
29 instance_name = function.__self__.__class__.__name__ # TestUser
30 fixture_name = re.sub(r"^Test", r"", instance_name) + "_" + re.sub(r"^test_", r"", method_name) + ".yaml"
31 return os.path.join(
32 os.path.dirname(func_file),
33 "fixtures",
34 fixture_name,
35 )
38def _gitlabracadabra_uri_matcher(r1, r2):
39 r1_uri = r1.uri
40 r2_uri = r2.uri
41 # Workaround 'all=True' in API calls
42 # with python-gitlab < 1.8.0
43 # See https://github.com/python-gitlab/python-gitlab/pull/701
44 if r1_uri.endswith("all=True"): 44 ↛ 45line 44 didn't jump to line 45 because the condition on line 44 was never true
45 r1_uri = r1_uri[0:-9]
46 # Ignore host and port
47 r1_uri = re.sub(r"^https?://[^:/]+(:\d+)?/", "http://localhost/", r1_uri)
48 r2_uri = re.sub(r"^https?://[^:/]+(:\d+)?/", "http://localhost/", r2_uri)
49 return r1_uri == r2_uri
52def _gitlabracadabra_body_matcher(r1, r2):
53 if r1.method == "POST" and r1.method == r2.method and r1.url == r2.url:
54 _, _, r1_boundary = r1.headers.get("Content-Type", "").partition("multipart/form-data; boundary=")
55 _, _, r2_boundary = r2.headers.get("Content-Type", "").partition("multipart/form-data; boundary=")
56 return (
57 r1_boundary and r2_boundary and r1.body.split(r1_boundary.encode()) == r2.body.split(r2_boundary.encode())
58 )
59 return body(r1, r2)
62def _gitlabracadabra_headers(headers: dict[str, str]) -> dict[str, str]:
63 new_headers: dict[str, str] = {}
64 for header_name, header_value in headers.items():
65 if header_name == "Accept" and header_value != "*/*":
66 header_value = "boilerplate"
67 elif header_name == "Authorization":
68 if header_value.startswith("Basic "):
69 userpass = standard_b64decode(header_value.removeprefix("Basic ")).split(b":")
70 userpass[1] = b"my-pass"
71 basic_value = standard_b64encode(b":".join(userpass)).decode("ascii")
72 header_value = f"Basic {basic_value}"
73 elif header_value.startswith("Bearer "): 73 ↛ 84line 73 didn't jump to line 84 because the condition on line 73 was always true
74 header_value = "Bearer some-value"
75 elif header_name == "Content-Length":
76 header_value = "42"
77 elif header_name == "Content-Type":
78 if header_value.startswith("multipart/form-data; boundary="):
79 header_value = "multipart/form-data; boundary=some-boundary"
80 elif header_name == "PRIVATE-TOKEN":
81 header_value = "MY-TOKEN"
82 elif header_name in {"Accept-Encoding", "Content-type", "Cookie", "User-Agent"}:
83 continue
84 new_headers[header_name] = header_value
85 return new_headers
88def _gitlabracadabra_headers_matcher(r1, r2):
89 r1_headers = _gitlabracadabra_headers(r1.headers)
90 r2_headers = _gitlabracadabra_headers(r2.headers)
91 if r1_headers != r2_headers:
92 msg = f"{r1_headers} != {r2_headers}"
93 raise AssertionError(msg)
94 return r1_headers == r2_headers # compat
97my_vcr = VCR(
98 match_on=["method", "gitlabracadabra_uri", "body", "gitlabracadabra_headers"],
99 func_path_generator=_gitlabracadabra_func_path_generator,
100 record_mode="none", # change to 'once' or 'new_episodes'
101 inject_cassette=True,
102 decode_compressed_response=True,
103)
104my_vcr.register_matcher("gitlabracadabra_uri", _gitlabracadabra_uri_matcher)
105my_vcr.register_matcher("gitlabracadabra_body", _gitlabracadabra_body_matcher)
106my_vcr.register_matcher("gitlabracadabra_headers", _gitlabracadabra_headers_matcher)