Welcome to mirror list, hosted at ThFree Co, Russian Federation.

requests.py « util « sphinx - github.com/sphinx-doc/sphinx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 8241bc60b488e46bbcdc507d4d778c693d0335b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
"""Simple requests package loader

    :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
    :license: BSD, see LICENSE for details.
"""

import sys
import warnings
from contextlib import contextmanager
from typing import Any, Generator, Union
from urllib.parse import urlsplit

import requests

import sphinx
from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx50Warning

try:
    from requests.packages.urllib3.exceptions import SSLError
except ImportError:
    # python-requests package in Debian jessie does not provide ``requests.packages.urllib3``.
    # So try to import the exceptions from urllib3 package.
    from urllib3.exceptions import SSLError

try:
    from requests.packages.urllib3.exceptions import InsecureRequestWarning
except ImportError:
    try:
        # for Debian-jessie
        from urllib3.exceptions import InsecureRequestWarning
    except ImportError:
        # for requests < 2.4.0
        InsecureRequestWarning = None


useragent_header = [('User-Agent',
                     'Mozilla/5.0 (X11; Linux x86_64; rv:25.0) Gecko/20100101 Firefox/25.0')]


def is_ssl_error(exc: Exception) -> bool:
    """Check an exception is SSLError."""
    warnings.warn(
        "is_ssl_error() is outdated and likely returns incorrect results "
        "for modern versions of Requests.",
        RemovedInSphinx50Warning)
    if isinstance(exc, SSLError):
        return True
    else:
        args = getattr(exc, 'args', [])
        if args and isinstance(args[0], SSLError):
            return True
        else:
            return False


@contextmanager
def ignore_insecure_warning(**kwargs: Any) -> Generator[None, None, None]:
    with warnings.catch_warnings():
        if not kwargs.get('verify') and InsecureRequestWarning:
            # ignore InsecureRequestWarning if verify=False
            warnings.filterwarnings("ignore", category=InsecureRequestWarning)
        yield


def _get_tls_cacert(url: str, config: Config) -> Union[str, bool]:
    """Get additional CA cert for a specific URL.

    This also returns ``False`` if verification is disabled.
    And returns ``True`` if additional CA cert not found.
    """
    if not config.tls_verify:
        return False

    certs = getattr(config, 'tls_cacerts', None)
    if not certs:
        return True
    elif isinstance(certs, (str, tuple)):
        return certs  # type: ignore
    else:
        hostname = urlsplit(url)[1]
        if '@' in hostname:
            hostname = hostname.split('@')[1]

        return certs.get(hostname, True)


def _get_user_agent(config: Config) -> str:
    if config.user_agent:
        return config.user_agent
    else:
        return ' '.join([
            'Sphinx/%s' % sphinx.__version__,
            'requests/%s' % requests.__version__,
            'python/%s' % '.'.join(map(str, sys.version_info[:3])),
        ])


def get(url: str, **kwargs: Any) -> requests.Response:
    """Sends a GET request like requests.get().

    This sets up User-Agent header and TLS verification automatically."""
    headers = kwargs.setdefault('headers', {})
    config = kwargs.pop('config', None)
    if config:
        kwargs.setdefault('verify', _get_tls_cacert(url, config))
        headers.setdefault('User-Agent', _get_user_agent(config))
    else:
        headers.setdefault('User-Agent', useragent_header[0][1])

    with ignore_insecure_warning(**kwargs):
        return requests.get(url, **kwargs)


def head(url: str, **kwargs: Any) -> requests.Response:
    """Sends a HEAD request like requests.head().

    This sets up User-Agent header and TLS verification automatically."""
    headers = kwargs.setdefault('headers', {})
    config = kwargs.pop('config', None)
    if config:
        kwargs.setdefault('verify', _get_tls_cacert(url, config))
        headers.setdefault('User-Agent', _get_user_agent(config))
    else:
        headers.setdefault('User-Agent', useragent_header[0][1])

    with ignore_insecure_warning(**kwargs):
        return requests.head(url, **kwargs)