File: base.py

package info (click to toggle)
python-proton-core 0.4.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 540 kB
  • sloc: python: 3,574; makefile: 15
file content (99 lines) | stat: -rw-r--r-- 3,219 bytes parent folder | download
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
"""
Copyright (c) 2023 Proton AG

This file is part of Proton.

Proton is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Proton is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with ProtonVPN.  If not, see <https://www.gnu.org/licenses/>.
"""
import weakref
from dataclasses import dataclass
from typing import Optional, Any, Tuple


@dataclass
class RawResponse:
    """
    A response that contains the status code and headers along with the body
    as json. This gives more context to clients when receiving a response.
    This type is returned where return_raw is set to True.

    :param status_code: The status code of the response
    :param headers: The headers in the response
    :param json: The body the response parsed as json
    """
    status_code: int
    headers: Tuple[Tuple[str, Any]]
    json: Optional[dict]

    def find_first_header(self, key, default=None):
        """
        Searches for the given key in the headers and returns the first value
        if found, otherwise returns the default value.
        """
        for k, v in self.headers:
            if key == k:
                return v
        return default


class Transport:
    """
    The base class of all transports. This class should be subclassed to
    implement the async_api_request method, which is the main method that
    is used to make requests to the API.

    A transport abstracts away the details of how requests are made to the API,
    for example, it could be using requests, aiohttp, or any other library.
    """
    def __init__(self, session):
        self.__session = weakref.ref(session)
    
    @property
    def _session(self):
        return self.__session()

    @property
    def _environment(self):
        #Shortcut to access environment
        return self._session.environment

    def __eq__(self, other):
        # It's the same transport if it's the same type (that's what users would generally assume)
        return self.__class__ == other.__class__

    async def is_working(self):
        try:
            return await self.async_api_request('/tests/ping').get('Code') == '1000'
        except:
            return False

    async def async_api_request(
        self, endpoint,
        jsondata=None, additional_headers=None,
        method=None, params=None
    ):
        raise NotImplementedError("async_api_request should be implemented")

class TransportFactory:
    def __init__(self, cls, *args, **kwargs):
        self._cls = cls
        self._args = args
        self._kwargs = kwargs

    def __call__(self, session):
        return self._cls(session, *self._args, **self._kwargs)

    def __eq__(self, other):
        # It's the same transport if it's the same type (that's what users would generally assume)
        return self._cls == other._cls