• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mozilla / relman-auto-nag / #4767

13 Oct 2023 01:27AM CUT coverage: 22.091%. Remained the same
#4767

push

coveralls-python

suhaibmujahid
Format the .pre-commit-config.yaml file

716 of 3558 branches covered (0.0%)

1925 of 8714 relevant lines covered (22.09%)

0.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.49
/bugbot/auto_mock.py
1
# This Source Code Form is subject to the terms of the Mozilla Public
2
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
3
# You can obtain one at http://mozilla.org/MPL/2.0/.
4
#
5
# This file was originally copied from https://github.com/mozilla/libmozdata/blob/v0.1.82/tests/auto_mock.py
6

7
import hashlib
1✔
8
import json
1✔
9
import os
1✔
10
import re
1✔
11
import unittest
1✔
12
from typing import List
1✔
13
from urllib.error import HTTPError
1✔
14
from urllib.parse import parse_qsl, urlparse
1✔
15
from urllib.request import Request, urlopen
1✔
16

17
import responses
1✔
18

19
from bugbot import logger
1✔
20

21
MOCKS_DIR = os.path.join(os.path.dirname(__file__), "../tests/mocks")
1✔
22

23

24
class MockTestCase(unittest.TestCase):
1✔
25
    """
26
    Mock responses from any webserver (through requests)
27
    Register local responses when none are found
28
    """
29

30
    mock_urls: List[str] = []
1✔
31

32
    def setUp(self):
1✔
33
        # Setup mock callbacks
34
        for mock_url in self.mock_urls:
1✔
35
            url_re = re.compile(rf"^{mock_url}")
1✔
36
            responses.add_callback(
1✔
37
                responses.GET,
38
                url_re,
39
                callback=self._request_callback,
40
                content_type="application/json",
41
            )
42

43
    def _request_callback(self, request):
1✔
44
        logger.debug("Mock request %s %s", request.method, request.url)
1✔
45
        path = self._build_path(request.method, request.url)
1✔
46

47
        if os.path.exists(path):
1!
48
            # Load local file
49
            logger.info("Using mock file %s", path)
1✔
50
            with open(path, "r") as file:
1✔
51
                response = json.load(file)
1✔
52
        else:
53
            # Build from actual request
54
            logger.info("Building mock file %s", path)
×
55
            response = self._real_request(request)
×
56

57
            # Save in local file for future use
58
            with open(path, "w") as file:
×
59
                file.write(json.dumps(response))
×
60

61
        return (response["status"], response["headers"], response["body"])
1✔
62

63
    def _build_path(self, method, url):
1✔
64
        """
65
        Build a unique filename from method & url
66
        """
67
        # Build directory to request
68
        out = urlparse(url)
1✔
69
        parts = [f"{out.scheme}_{out.hostname}"]
1✔
70
        parts += filter(None, out.path.split("/"))
1✔
71
        directory = os.path.join(MOCKS_DIR, *parts)
1✔
72

73
        # Build sorted query filename
74
        query = sorted(parse_qsl(out.query))
1✔
75
        query = [f"""{k}={v.replace("/", "_")}""" for k, v in query if k != "date"]
1✔
76
        query_str = "_".join(query)
1✔
77

78
        # Use hashes to avoid too long names
79
        if len(query_str) > 150:
1✔
80
            hashed_query = hashlib.md5(query_str.encode("utf-8")).hexdigest()
1✔
81
            query_str = f"{query_str[0:100]}_{hashed_query}"
1✔
82
        filename = f"{method}_{query_str}.json"
1✔
83

84
        # Build directory
85
        if not os.path.isdir(directory):
1!
86
            try:
×
87
                os.makedirs(directory)
×
88
            except Exception as error:
×
89
                logger.error("Concurrency error when building directories: %s", error)
×
90

91
        return os.path.join(directory, filename)
1✔
92

93
    def _real_request(self, request):
1✔
94
        """
95
        Do a real request towards the target
96
        to build a mockup, using low level urllib
97
        Can't use requests: it's wrapped by unittest.mock
98
        """
99

100
        # No gzip !
101
        headers = {key.lower(): value for key, value in request.headers.items()}
×
102
        if "accept-encoding" in headers:
×
103
            del headers["accept-encoding"]
×
104

105
        real_req = Request(
×
106
            request.url, request.body, headers=headers, method=request.method
107
        )
108

109
        try:
×
110
            resp = urlopen(real_req)
×
111
        except HTTPError as error:
×
112
            logger.error("HTTP Error saved for %s: %s", request.url, error)
×
113
            return {"status": error.code, "headers": {}, "body": ""}
×
114

115
        return {
×
116
            "status": resp.code,
117
            # TODO: fix cookie usage bug
118
            # 'headers': dict(resp.getheaders()),
119
            "headers": {},
120
            "body": resp.read().decode("utf-8"),
121
        }
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc