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

funilrys / PyFunceble / 3607917966

pending completion
3607917966

push

github-actions

funilrys
fixup! Introduction of the changeip SPECIAL rule.

11094 of 11508 relevant lines covered (96.4%)

11.55 hits per line

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

63.83
/PyFunceble/checker/availability/extras/base.py
1
"""
2
The tool to check the availability or syntax of domain, IP or URL.
3

4
::
5

6

7
    ██████╗ ██╗   ██╗███████╗██╗   ██╗███╗   ██╗ ██████╗███████╗██████╗ ██╗     ███████╗
8
    ██╔══██╗╚██╗ ██╔╝██╔════╝██║   ██║████╗  ██║██╔════╝██╔════╝██╔══██╗██║     ██╔════╝
9
    ██████╔╝ ╚████╔╝ █████╗  ██║   ██║██╔██╗ ██║██║     █████╗  ██████╔╝██║     █████╗
10
    ██╔═══╝   ╚██╔╝  ██╔══╝  ██║   ██║██║╚██╗██║██║     ██╔══╝  ██╔══██╗██║     ██╔══╝
11
    ██║        ██║   ██║     ╚██████╔╝██║ ╚████║╚██████╗███████╗██████╔╝███████╗███████╗
12
    ╚═╝        ╚═╝   ╚═╝      ╚═════╝ ╚═╝  ╚═══╝ ╚═════╝╚══════╝╚═════╝ ╚══════╝╚══════╝
13

14
Provides the base of all extra handlers.
15

16
Author:
17
    Nissar Chababy, @funilrys, contactTATAfunilrysTODTODcom
18

19
Special thanks:
20
    https://pyfunceble.github.io/#/special-thanks
21

22
Contributors:
23
    https://pyfunceble.github.io/#/contributors
24

25
Project link:
26
    https://github.com/funilrys/PyFunceble
27

28
Project documentation:
29
    https://pyfunceble.readthedocs.io/en/dev/
30

31
Project homepage:
32
    https://pyfunceble.github.io/
33

34
License:
35
::
36

37

38
    Copyright 2017, 2018, 2019, 2020, 2022 Nissar Chababy
39

40
    Licensed under the Apache License, Version 2.0 (the "License");
41
    you may not use this file except in compliance with the License.
42
    You may obtain a copy of the License at
43

44
        http://www.apache.org/licenses/LICENSE-2.0
45

46
    Unless required by applicable law or agreed to in writing, software
47
    distributed under the License is distributed on an "AS IS" BASIS,
48
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
49
    See the License for the specific language governing permissions and
50
    limitations under the License.
51
"""
52

53
import functools
12✔
54
from typing import Callable, List, Optional
12✔
55

56
import requests
12✔
57

58
import PyFunceble.factory
12✔
59
from PyFunceble.checker.availability.status import AvailabilityCheckerStatus
12✔
60
from PyFunceble.query.dns.query_tool import DNSQueryTool
12✔
61

62

63
class ExtraRuleHandlerBase:
12✔
64
    """
65
    Provides the base of all extra rules handler.
66

67
    :param statatus:
68
        The previously gathered status.
69
    :type status:
70
        :class:`~PyFunceble.checker.availability.status.AvailabilityCheckerStatus`
71
    """
72

73
    _status: Optional[AvailabilityCheckerStatus] = None
12✔
74
    req: Optional[requests.Response] = None
12✔
75
    dns_query_tool: Optional[DNSQueryTool] = None
12✔
76
    req_url: Optional[str] = None
12✔
77

78
    def __init__(self, status: Optional[AvailabilityCheckerStatus] = None) -> None:
79
        if status is not None:
80
            self.status = status
81

82
        # Be sure that all settings are loaded proprely!!
83
        PyFunceble.factory.Requester.guess_all_settings()
84
        self.dns_query_tool = DNSQueryTool()
85

86
    def ensure_status_is_given(
12✔
87
        func: Callable[..., "ExtraRuleHandlerBase"]
88
    ):  # pylint: disable=no-self-argument
89
        """
90
        Ensures that the status is given before running the decorated method.
91

92
        :raise TypeError:
93
            If the subject is not a string.
94
        """
95

96
        @functools.wraps(func)
12✔
97
        def wrapper(self, *args, **kwargs):  # pragma: no cover ## Safety!
98
            if not self.status:
99
                raise TypeError(
100
                    f"<self.status> should be {AvailabilityCheckerStatus}, "
101
                    f"{type(self.status)} given."
102
                )
103

104
            return func(self, *args, **kwargs)  # pylint: disable=not-callable
105

106
        return wrapper
12✔
107

108
    def setup_status_before(
12✔
109
        func: Callable[..., "ExtraRuleHandlerBase"]
110
    ):  # pylint: disable=no-self-argument
111
        """
112
        Ensures that the status is given before running the decorated method.
113

114
        :raise TypeError:
115
            If the subject is not a string.
116
        """
117

118
        @functools.wraps(func)
12✔
119
        def wrapper(self, *args, **kwargs):  # pragma: no cover ## Safety!
120
            self.status.status_before_extra_rules = self.status.status
121
            self.status.status_source_before_extra_rules = self.status.status_source
122

123
            return func(self, *args, **kwargs)  # pylint: disable=not-callable
124

125
        return wrapper
12✔
126

127
    def setup_status_after(
12✔
128
        func: Callable[..., "ExtraRuleHandlerBase"]
129
    ):  # pylint: disable=no-self-argument
130
        """
131
        Ensures that the status is given before running the decorated method.
132

133
        :raise TypeError:
134
            If the subject is not a string.
135
        """
136

137
        @functools.wraps(func)
12✔
138
        def wrapper(self, *args, **kwargs):  # pragma: no cover ## Safety!
139
            result = func(self, *args, **kwargs)  # pylint: disable=not-callable
140

141
            if self.status.status_after_extra_rules:
142
                self.status.status = self.status.status_after_extra_rules
143
                self.status.status_source = self.status.status_source_after_extra_rules
144

145
                PyFunceble.facility.Logger.info(
146
                    "Could define the status of %r from our own set of rules.",
147
                    self.status.idna_subject,
148
                )
149
            else:
150
                self.status.status_before_extra_rules = None
151
                self.status.status_source_before_extra_rules = None
152
                self.status.status_after_extra_rules = None
153
                self.status.status_source_after_extra_rules = None
154

155
            return result
156

157
        return wrapper
12✔
158

159
    @property
12✔
160
    def status(self) -> Optional[AvailabilityCheckerStatus]:
12✔
161
        """
162
        Provides the current state of the :code:`_status` attribute.
163
        """
164

165
        return self._status
×
166

167
    @status.setter
12✔
168
    def status(self, value: AvailabilityCheckerStatus) -> None:
12✔
169
        """
170
        Sets the status to work with.
171

172
        :param value:
173
            The status to work with.
174

175
        :raise TypeError:
176
            When the given :code:`value` is not a
177
            :class:`~PyFunceble.checker.availability.status.AvailabilityCheckerStatus`.
178
        """
179

180
        if not isinstance(value, AvailabilityCheckerStatus):
×
181
            raise TypeError(
×
182
                f"<value> should be {AvailabilityCheckerStatus}, {type(value)} given."
183
            )
184

185
        self._status = value
×
186

187
    def set_status(self, value: AvailabilityCheckerStatus) -> "ExtraRuleHandlerBase":
12✔
188
        """
189
        Sets the status to work with.
190

191
        :param value:
192
            The status to work with.
193
        """
194

195
        self.status = value
×
196

197
        return self
×
198

199
    def do_request(self, *, allow_redirects: bool = True) -> requests.Response:
12✔
200
        """
201
        Do a request and store its response into the `req` attribute.
202

203
        :param bool allow_redirects:
204
            Whether we shoold follow the redirection - or not.
205
        """
206

207
        if any(self.status.idna_subject.startswith(x) for x in ("http:", "https:")):
×
208
            self.req_url = url = self.status.idna_subject
×
209
        else:
210
            self.req_url = url = f"http://{self.status.idna_subject}:80"
×
211

212
        self.req = PyFunceble.factory.Requester.get(
×
213
            url, allow_redirects=allow_redirects
214
        )
215

216
        return self
×
217

218
    def do_dns_lookup(self, *, subject: str, query_type: str) -> List[str]:
12✔
219
        """
220
        Do a DNS lookup and return its response.
221

222
        :param subject:
223
            The subject to query.
224
        :param query_type:
225
            The query type.
226
        """
227

228
        return (
×
229
            self.dns_query_tool.set_query_record_type(query_type)
230
            .set_subject(subject)
231
            .query()
232
        )
233

234
    def start(self) -> "ExtraRuleHandlerBase":
12✔
235
        """
236
        Starts the gathering process.
237
        """
238

239
        raise NotImplementedError()
240

241
    def switch_to_down(self) -> "ExtraRuleHandlerBase":
12✔
242
        """
243
        Switches the status to inactive.
244
        """
245

246
        self.status.status_after_extra_rules = PyFunceble.storage.STATUS.down
×
247
        self.status.status_source_after_extra_rules = "SPECIAL"
×
248

249
        return self
×
250

251
    def switch_to_up(self) -> "ExtraRuleHandlerBase":
12✔
252
        """
253
        Switches the status to active.
254
        """
255

256
        self.status.status_after_extra_rules = PyFunceble.storage.STATUS.up
×
257
        self.status.status_source_after_extra_rules = "SPECIAL"
×
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

© 2026 Coveralls, Inc