Coverage for src/gitlabracadabra/tests/vcrfuncs.py: 97%
64 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-14 23:10 +0200
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-14 23:10 +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 if header_name == "Accept-Encoding":
68 if header_value == "*":
69 header_value = "gzip, deflate"
70 elif header_name == "Authorization":
71 if header_value.startswith("Basic "):
72 userpass = standard_b64decode(header_value.removeprefix("Basic ")).split(b":")
73 userpass[1] = b"my-pass"
74 basic_value = standard_b64encode(b":".join(userpass)).decode("ascii")
75 header_value = f"Basic {basic_value}"
76 elif header_value.startswith("Bearer "): 76 ↛ 87line 76 didn't jump to line 87 because the condition on line 76 was always true
77 header_value = "Bearer some-value"
78 elif header_name == "Content-Length":
79 header_value = "42"
80 elif header_name == "Content-Type":
81 if header_value.startswith("multipart/form-data; boundary="):
82 header_value = "multipart/form-data; boundary=some-boundary"
83 elif header_name == "PRIVATE-TOKEN":
84 header_value = "MY-TOKEN"
85 elif header_name in {"Content-type", "Cookie", "User-Agent"}:
86 continue
87 new_headers[header_name] = header_value
88 return new_headers
91def _gitlabracadabra_headers_matcher(r1, r2):
92 r1_headers = _gitlabracadabra_headers(r1.headers)
93 r2_headers = _gitlabracadabra_headers(r2.headers)
94 if r1_headers != r2_headers:
95 msg = f"{r1_headers} != {r2_headers}"
96 raise AssertionError(msg)
97 return r1_headers == r2_headers # compat
100my_vcr = VCR(
101 match_on=["method", "gitlabracadabra_uri", "body", "gitlabracadabra_headers"],
102 func_path_generator=_gitlabracadabra_func_path_generator,
103 record_mode="none", # change to 'once' or 'new_episodes'
104 inject_cassette=True,
105 decode_compressed_response=True,
106)
107my_vcr.register_matcher("gitlabracadabra_uri", _gitlabracadabra_uri_matcher)
108my_vcr.register_matcher("gitlabracadabra_body", _gitlabracadabra_body_matcher)
109my_vcr.register_matcher("gitlabracadabra_headers", _gitlabracadabra_headers_matcher)