networkpype 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. networkpype-0.1.0/LICENSE +21 -0
  2. networkpype-0.1.0/PKG-INFO +94 -0
  3. networkpype-0.1.0/README.md +80 -0
  4. networkpype-0.1.0/networkpype/__init__.py +0 -0
  5. networkpype-0.1.0/networkpype/auth.py +89 -0
  6. networkpype-0.1.0/networkpype/factory.py +217 -0
  7. networkpype-0.1.0/networkpype/rest/__init__.py +40 -0
  8. networkpype-0.1.0/networkpype/rest/connection.py +105 -0
  9. networkpype-0.1.0/networkpype/rest/manager.py +264 -0
  10. networkpype-0.1.0/networkpype/rest/method.py +15 -0
  11. networkpype-0.1.0/networkpype/rest/processor/__init__.py +20 -0
  12. networkpype-0.1.0/networkpype/rest/processor/base.py +109 -0
  13. networkpype-0.1.0/networkpype/rest/processor/time_synchronizer.py +23 -0
  14. networkpype-0.1.0/networkpype/rest/request.py +65 -0
  15. networkpype-0.1.0/networkpype/rest/response.py +130 -0
  16. networkpype-0.1.0/networkpype/throttler/__init__.py +40 -0
  17. networkpype-0.1.0/networkpype/throttler/context.py +223 -0
  18. networkpype-0.1.0/networkpype/throttler/rate_limit.py +172 -0
  19. networkpype-0.1.0/networkpype/throttler/throttler.py +251 -0
  20. networkpype-0.1.0/networkpype/time_synchronizer.py +176 -0
  21. networkpype-0.1.0/networkpype/websocket/__init__.py +51 -0
  22. networkpype-0.1.0/networkpype/websocket/connection.py +411 -0
  23. networkpype-0.1.0/networkpype/websocket/manager.py +265 -0
  24. networkpype-0.1.0/networkpype/websocket/processor/__init__.py +17 -0
  25. networkpype-0.1.0/networkpype/websocket/processor/base.py +110 -0
  26. networkpype-0.1.0/networkpype/websocket/request.py +138 -0
  27. networkpype-0.1.0/networkpype/websocket/response.py +48 -0
  28. networkpype-0.1.0/pyproject.toml +75 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Gianluca Pagliara
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,94 @@
1
+ Metadata-Version: 2.1
2
+ Name: networkpype
3
+ Version: 0.1.0
4
+ Summary:
5
+ Author: Gianluca Pagliara
6
+ Author-email: pagliara.gianluca@gmail.com
7
+ Requires-Python: >=3.13,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.13
10
+ Requires-Dist: aiohttp (<3.10.0)
11
+ Requires-Dist: aioresponses (>=0.7.8,<0.8.0)
12
+ Requires-Dist: numpy (>=2.2.2,<3.0.0)
13
+ Description-Content-Type: text/markdown
14
+
15
+ # Network Pypeline
16
+
17
+ [![PyPI version](https://badge.fury.io/py/networkpype.svg)](https://badge.fury.io/py/networkpype)
18
+ [![Python](https://img.shields.io/pypi/pyversions/networkpype.svg?style=plastic)](https://badge.fury.io/py/networkpype)
19
+ [![Documentation Status](https://readthedocs.org/projects/networkpype/badge/?version=latest)](https://networkpype.readthedocs.io/en/latest/?badge=latest)
20
+ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
21
+
22
+ A powerful Python library for building efficient network communication pipelines, supporting both REST and WebSocket protocols with built-in rate limiting and time synchronization.
23
+
24
+ ## Features
25
+
26
+ - 🔄 **Dual Protocol Support**: Seamlessly handle both REST and WebSocket communications
27
+ - 🚦 **Rate Limiting**: Built-in throttling mechanism to respect API rate limits
28
+ - ⏰ **Time Synchronization**: Automatic time synchronization for accurate API interactions
29
+ - 🏭 **Factory Pattern**: Easy-to-use factory for creating and managing connections
30
+ - 🔌 **Modular Design**: Extensible processor architecture for custom request/response handling
31
+ - 🛡️ **Type Safety**: Full type hinting support for better development experience
32
+
33
+ ## Installation
34
+
35
+ Install using pip:
36
+
37
+ ```bash
38
+ pip install networkpype
39
+ ```
40
+
41
+ Or with Poetry:
42
+
43
+ ```bash
44
+ poetry add networkpype
45
+ ```
46
+
47
+ ## Quick Start
48
+
49
+ ### REST Example
50
+
51
+ ```python
52
+ from networkpype.factory import ConnectionFactory
53
+ from networkpype.rest.method import Method
54
+
55
+ # Create a REST connection
56
+ factory = ConnectionFactory()
57
+ connection = factory.create_rest_connection(
58
+ base_url="https://api.example.com",
59
+ rate_limit=100 # requests per minute
60
+ )
61
+
62
+ # Make a request
63
+ response = connection.request(
64
+ method=Method.GET,
65
+ endpoint="/users",
66
+ params={"page": 1}
67
+ )
68
+ ```
69
+
70
+ ### WebSocket Example
71
+
72
+ ```python
73
+ from networkpype.factory import ConnectionFactory
74
+
75
+ # Create a WebSocket connection
76
+ factory = ConnectionFactory()
77
+ connection = factory.create_websocket_connection(
78
+ url="wss://ws.example.com"
79
+ )
80
+
81
+ # Subscribe to updates
82
+ connection.subscribe(
83
+ channel="market.btcusdt.trade",
84
+ callback=lambda msg: print(f"Received: {msg}")
85
+ )
86
+ ```
87
+
88
+ ## Documentation
89
+
90
+ For detailed documentation, please visit [networkpype.readthedocs.io](https://networkpype.readthedocs.io/).
91
+
92
+ ## License
93
+
94
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,80 @@
1
+ # Network Pypeline
2
+
3
+ [![PyPI version](https://badge.fury.io/py/networkpype.svg)](https://badge.fury.io/py/networkpype)
4
+ [![Python](https://img.shields.io/pypi/pyversions/networkpype.svg?style=plastic)](https://badge.fury.io/py/networkpype)
5
+ [![Documentation Status](https://readthedocs.org/projects/networkpype/badge/?version=latest)](https://networkpype.readthedocs.io/en/latest/?badge=latest)
6
+ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ A powerful Python library for building efficient network communication pipelines, supporting both REST and WebSocket protocols with built-in rate limiting and time synchronization.
9
+
10
+ ## Features
11
+
12
+ - 🔄 **Dual Protocol Support**: Seamlessly handle both REST and WebSocket communications
13
+ - 🚦 **Rate Limiting**: Built-in throttling mechanism to respect API rate limits
14
+ - ⏰ **Time Synchronization**: Automatic time synchronization for accurate API interactions
15
+ - 🏭 **Factory Pattern**: Easy-to-use factory for creating and managing connections
16
+ - 🔌 **Modular Design**: Extensible processor architecture for custom request/response handling
17
+ - 🛡️ **Type Safety**: Full type hinting support for better development experience
18
+
19
+ ## Installation
20
+
21
+ Install using pip:
22
+
23
+ ```bash
24
+ pip install networkpype
25
+ ```
26
+
27
+ Or with Poetry:
28
+
29
+ ```bash
30
+ poetry add networkpype
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ ### REST Example
36
+
37
+ ```python
38
+ from networkpype.factory import ConnectionFactory
39
+ from networkpype.rest.method import Method
40
+
41
+ # Create a REST connection
42
+ factory = ConnectionFactory()
43
+ connection = factory.create_rest_connection(
44
+ base_url="https://api.example.com",
45
+ rate_limit=100 # requests per minute
46
+ )
47
+
48
+ # Make a request
49
+ response = connection.request(
50
+ method=Method.GET,
51
+ endpoint="/users",
52
+ params={"page": 1}
53
+ )
54
+ ```
55
+
56
+ ### WebSocket Example
57
+
58
+ ```python
59
+ from networkpype.factory import ConnectionFactory
60
+
61
+ # Create a WebSocket connection
62
+ factory = ConnectionFactory()
63
+ connection = factory.create_websocket_connection(
64
+ url="wss://ws.example.com"
65
+ )
66
+
67
+ # Subscribe to updates
68
+ connection.subscribe(
69
+ channel="market.btcusdt.trade",
70
+ callback=lambda msg: print(f"Received: {msg}")
71
+ )
72
+ ```
73
+
74
+ ## Documentation
75
+
76
+ For detailed documentation, please visit [networkpype.readthedocs.io](https://networkpype.readthedocs.io/).
77
+
78
+ ## License
79
+
80
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
File without changes
@@ -0,0 +1,89 @@
1
+ """Authentication module for REST and WebSocket requests.
2
+
3
+ This module provides the base authentication class that can be used to implement
4
+ various authentication schemes for both REST and WebSocket connections. It supports
5
+ time-synchronized authentication methods and can be extended to implement specific
6
+ authentication protocols.
7
+
8
+ Classes:
9
+ Auth: Abstract base class for implementing authentication schemes.
10
+ """
11
+
12
+ from abc import abstractmethod
13
+
14
+ from networkpype.rest.request import RESTRequest
15
+ from networkpype.time_synchronizer import TimeSynchronizer
16
+ from networkpype.websocket.request import WebSocketRequest
17
+
18
+
19
+ class Auth:
20
+ """Abstract base class for authentication objects used by ConnectionManagersFactory.
21
+
22
+ This class provides the foundation for implementing various authentication schemes.
23
+ It can be used to authenticate both REST and WebSocket requests, and supports
24
+ time-synchronized authentication methods.
25
+
26
+ The class can be extended to implement specific authentication protocols such as:
27
+ - API Key authentication
28
+ - OAuth
29
+ - JWT
30
+ - HMAC signatures
31
+ - Custom authentication schemes
32
+
33
+ Attributes:
34
+ time_provider (TimeSynchronizer): Component for handling time synchronization
35
+ in authentication operations.
36
+
37
+ Note:
38
+ If the authentication requires a simple REST request to acquire information from the
39
+ server that is required in the message signature, this class can be passed a
40
+ `RESTConnection` object that it can use to that end.
41
+ """
42
+
43
+ def __init__(
44
+ self,
45
+ time_provider: TimeSynchronizer | None = None,
46
+ ):
47
+ """Initialize the Auth instance with an optional time synchronizer.
48
+
49
+ Args:
50
+ time_provider (TimeSynchronizer | None): Component for handling time
51
+ synchronization. If None, a new TimeSynchronizer instance will be created.
52
+ """
53
+ self.time_provider = time_provider or TimeSynchronizer()
54
+
55
+ @abstractmethod
56
+ async def rest_authenticate(self, request: RESTRequest) -> RESTRequest:
57
+ """Authenticate a REST request.
58
+
59
+ This method should be implemented by subclasses to add authentication
60
+ information to REST requests (e.g., headers, query parameters, etc.).
61
+
62
+ Args:
63
+ request (RESTRequest): The REST request to authenticate.
64
+
65
+ Returns:
66
+ RESTRequest: The authenticated request with added authentication information.
67
+
68
+ Raises:
69
+ NotImplementedError: If the subclass does not implement this method.
70
+ """
71
+ ...
72
+
73
+ @abstractmethod
74
+ async def ws_authenticate(self, request: WebSocketRequest) -> WebSocketRequest:
75
+ """Authenticate a WebSocket request.
76
+
77
+ This method should be implemented by subclasses to add authentication
78
+ information to WebSocket requests (e.g., connection parameters, headers, etc.).
79
+
80
+ Args:
81
+ request (WebSocketRequest): The WebSocket request to authenticate.
82
+
83
+ Returns:
84
+ WebSocketRequest: The authenticated request with added authentication information.
85
+
86
+ Raises:
87
+ NotImplementedError: If the subclass does not implement this method.
88
+ """
89
+ ...
@@ -0,0 +1,217 @@
1
+ """Network communication factory module for REST and WebSocket connections.
2
+
3
+ This module provides factory classes for creating and managing network connections,
4
+ both for REST and WebSocket protocols. It abstracts the underlying network library
5
+ (aiohttp) and provides a clean interface for connection management.
6
+
7
+ Classes:
8
+ ConnectionsFactory: Creates and manages low-level network connections.
9
+ ConnectionManagersFactory: Creates and manages high-level connection managers with additional features.
10
+ """
11
+
12
+ import aiohttp
13
+
14
+ from networkpype.auth import Auth
15
+ from networkpype.rest.connection import RESTConnection
16
+ from networkpype.rest.manager import RESTManager
17
+ from networkpype.rest.processor.base import RESTPostProcessor, RESTPreProcessor
18
+ from networkpype.throttler.throttler import AsyncThrottler
19
+ from networkpype.time_synchronizer import TimeSynchronizer
20
+ from networkpype.websocket.connection import WebSocketConnection
21
+ from networkpype.websocket.manager import WebSocketManager
22
+ from networkpype.websocket.processor.base import (
23
+ WebSocketPostProcessor,
24
+ WebSocketPreProcessor,
25
+ )
26
+
27
+
28
+ class ConnectionsFactory:
29
+ """Factory class for creating and managing network connections.
30
+
31
+ This class is a thin wrapper around the underlying REST and WebSocket third-party library.
32
+ It isolates the general `connection_manager` infrastructure from the underlying library
33
+ (in this case, `aiohttp`) to enable dependency change with minimal refactoring of the code.
34
+
35
+ Attributes:
36
+ _shared_client (aiohttp.ClientSession | None): Shared HTTP client session for all connections.
37
+ """
38
+
39
+ def __init__(self):
40
+ """Initialize the ConnectionsFactory with no active client session."""
41
+ self._shared_client: aiohttp.ClientSession | None = None
42
+
43
+ async def get_rest_connection(self) -> RESTConnection:
44
+ """Create or retrieve a REST connection using the shared client session.
45
+
46
+ Returns:
47
+ RESTConnection: A connection object for making REST API calls.
48
+ """
49
+ shared_client = await self._get_shared_client()
50
+ connection = RESTConnection(aiohttp_client_session=shared_client)
51
+ return connection
52
+
53
+ async def get_ws_connection(self, **kwargs) -> WebSocketConnection:
54
+ """Create or retrieve a WebSocket connection using the shared client session.
55
+
56
+ Args:
57
+ **kwargs: Additional arguments to pass to the client session.
58
+
59
+ Returns:
60
+ WebSocketConnection: A connection object for WebSocket communication.
61
+ """
62
+ shared_client = await self._get_shared_client(**kwargs)
63
+ connection = WebSocketConnection(aiohttp_client_session=shared_client)
64
+ return connection
65
+
66
+ async def _get_shared_client(self, **kwargs) -> aiohttp.ClientSession:
67
+ """Get or create a shared aiohttp client session.
68
+
69
+ Args:
70
+ **kwargs: Additional arguments to pass to ClientSession constructor.
71
+
72
+ Returns:
73
+ aiohttp.ClientSession: The shared client session.
74
+ """
75
+ self._shared_client = self._shared_client or aiohttp.ClientSession(**kwargs)
76
+ return self._shared_client
77
+
78
+ async def update_cookies(self, cookies):
79
+ """Update the cookies in the shared client session.
80
+
81
+ Args:
82
+ cookies: Cookie data to update in the session.
83
+ """
84
+ shared_client = await self._get_shared_client()
85
+ shared_client.cookie_jar.update_cookies(cookies)
86
+
87
+ async def close(self):
88
+ """Close the shared client session and clean up resources."""
89
+ if self._shared_client:
90
+ await self._shared_client.close()
91
+ self._shared_client = None
92
+
93
+
94
+ class ConnectionManagersFactory:
95
+ """Factory class for creating and managing high-level connection managers.
96
+
97
+ This class creates connection managers that handle authentication, rate limiting,
98
+ request/response processing, and time synchronization for both REST and WebSocket
99
+ connections.
100
+
101
+ Attributes:
102
+ _connections_factory (ConnectionsFactory): Factory for creating base connections.
103
+ _rest_pre_processors (list[RESTPreProcessor]): Processors to run before REST requests.
104
+ _rest_post_processors (list[RESTPostProcessor]): Processors to run after REST responses.
105
+ _ws_pre_processors (list[WebSocketPreProcessor]): Processors to run before WS messages.
106
+ _ws_post_processors (list[WebSocketPostProcessor]): Processors to run after WS messages.
107
+ _auth (Auth | None): Authentication handler.
108
+ _throttler (AsyncThrottler): Rate limiting handler.
109
+ _time_synchronizer (TimeSynchronizer | None): Time synchronization handler.
110
+ """
111
+
112
+ def __init__(
113
+ self,
114
+ throttler: AsyncThrottler,
115
+ auth: Auth | None = None,
116
+ rest_pre_processors: list[RESTPreProcessor] | None = None,
117
+ rest_post_processors: list[RESTPostProcessor] | None = None,
118
+ ws_pre_processors: list[WebSocketPreProcessor] | None = None,
119
+ ws_post_processors: list[WebSocketPostProcessor] | None = None,
120
+ time_synchronizer: TimeSynchronizer | None = None,
121
+ ):
122
+ """Initialize the ConnectionManagersFactory with the specified components.
123
+
124
+ Args:
125
+ throttler (AsyncThrottler): Rate limiting component for API requests.
126
+ auth (Auth | None): Authentication handler for requests. Defaults to None.
127
+ rest_pre_processors (list[RESTPreProcessor] | None): List of processors to run before REST requests.
128
+ Defaults to None.
129
+ rest_post_processors (list[RESTPostProcessor] | None): List of processors to run after REST responses.
130
+ Defaults to None.
131
+ ws_pre_processors (list[WebSocketPreProcessor] | None): List of processors to run before WebSocket messages.
132
+ Defaults to None.
133
+ ws_post_processors (list[WebSocketPostProcessor] | None): List of processors to run after WebSocket messages.
134
+ Defaults to None.
135
+ time_synchronizer (TimeSynchronizer | None): Component for handling time synchronization.
136
+ Defaults to None.
137
+ """
138
+ self._connections_factory = ConnectionsFactory()
139
+ self._rest_pre_processors = rest_pre_processors or []
140
+ self._rest_post_processors = rest_post_processors or []
141
+ self._ws_pre_processors = ws_pre_processors or []
142
+ self._ws_post_processors = ws_post_processors or []
143
+ self._auth = auth
144
+ self._throttler = throttler
145
+ self._time_synchronizer = time_synchronizer
146
+
147
+ @property
148
+ def throttler(self) -> AsyncThrottler:
149
+ """Get the rate limiting throttler.
150
+
151
+ Returns:
152
+ AsyncThrottler: The throttler instance used for rate limiting.
153
+ """
154
+ return self._throttler
155
+
156
+ @property
157
+ def time_synchronizer(self) -> TimeSynchronizer | None:
158
+ """Get the time synchronization component.
159
+
160
+ Returns:
161
+ TimeSynchronizer | None: The time synchronizer instance if configured, None otherwise.
162
+ """
163
+ return self._time_synchronizer
164
+
165
+ @property
166
+ def auth(self) -> Auth | None:
167
+ """Get the authentication handler.
168
+
169
+ Returns:
170
+ Auth | None: The authentication instance if configured, None otherwise.
171
+ """
172
+ return self._auth
173
+
174
+ async def get_rest_manager(self) -> RESTManager:
175
+ """Create a new REST connection manager with all configured components.
176
+
177
+ Returns:
178
+ RESTManager: A fully configured REST connection manager with authentication,
179
+ rate limiting, and request/response processing capabilities.
180
+ """
181
+ connection = await self._connections_factory.get_rest_connection()
182
+ assistant = RESTManager(
183
+ connection=connection,
184
+ throttler=self._throttler,
185
+ rest_pre_processors=self._rest_pre_processors,
186
+ rest_post_processors=self._rest_post_processors,
187
+ auth=self._auth,
188
+ )
189
+ return assistant
190
+
191
+ async def get_ws_manager(self, **kwargs) -> WebSocketManager:
192
+ """Create a new WebSocket connection manager with all configured components.
193
+
194
+ Args:
195
+ **kwargs: Additional arguments to pass to the WebSocket connection.
196
+
197
+ Returns:
198
+ WebSocketManager: A fully configured WebSocket connection manager with
199
+ authentication and message processing capabilities.
200
+ """
201
+ connection = await self._connections_factory.get_ws_connection(**kwargs)
202
+ assistant = WebSocketManager(
203
+ connection, self._ws_pre_processors, self._ws_post_processors, self._auth
204
+ )
205
+ return assistant
206
+
207
+ async def update_cookies(self, cookies):
208
+ """Update the cookies in the shared client session.
209
+
210
+ Args:
211
+ cookies: Cookie data to update in the session.
212
+ """
213
+ await self._connections_factory.update_cookies(cookies)
214
+
215
+ async def close(self):
216
+ """Close all connections and clean up resources."""
217
+ await self._connections_factory.close()
@@ -0,0 +1,40 @@
1
+ """REST API client implementation for NetworkPype.
2
+
3
+ This module provides a complete solution for making HTTP requests with features
4
+ like rate limiting, request/response processing, and connection management. It
5
+ uses aiohttp for making asynchronous HTTP requests and supports customization
6
+ through processors.
7
+
8
+ Key Components:
9
+ RESTManager: High-level interface for making HTTP requests.
10
+ RESTConnection: Low-level HTTP connection handler.
11
+ RESTRequest: Request data container with validation.
12
+ RESTResponse: Response data container with validation.
13
+ RESTPreProcessor: Base class for request pre-processors.
14
+ RESTPostProcessor: Base class for response post-processors.
15
+
16
+ Example:
17
+ ```python
18
+ from networkpype.rest import RESTManager, RESTConnection
19
+ from networkpype.rest.processor import JSONProcessor
20
+
21
+ # Create a REST client with JSON processing
22
+ connection = RESTConnection()
23
+ manager = RESTManager(
24
+ connection=connection,
25
+ post_processors=[JSONProcessor()]
26
+ )
27
+
28
+ # Make HTTP requests
29
+ async with manager.session():
30
+ # GET request with automatic JSON parsing
31
+ response = await manager.get("https://api.example.com/data")
32
+ data = response.data # Parsed JSON data
33
+
34
+ # POST request with automatic JSON serialization
35
+ response = await manager.post(
36
+ "https://api.example.com/items",
37
+ data={"name": "test"}
38
+ )
39
+ ```
40
+ """
@@ -0,0 +1,105 @@
1
+ """REST connection module for low-level HTTP communication.
2
+
3
+ This module provides a low-level interface for making HTTP requests using the aiohttp
4
+ library. It handles the direct communication with HTTP servers while providing a clean
5
+ abstraction over the underlying HTTP client library.
6
+
7
+ The module is designed to work with the RESTRequest and RESTResponse classes to provide
8
+ a consistent interface for HTTP communication, regardless of the underlying HTTP client
9
+ implementation.
10
+
11
+ Classes:
12
+ RESTConnection: Low-level HTTP connection handler.
13
+ """
14
+
15
+ import aiohttp
16
+ from yarl import URL
17
+
18
+ from networkpype.rest.request import RESTRequest
19
+ from networkpype.rest.response import RESTResponse
20
+
21
+
22
+ class RESTConnection:
23
+ """Low-level HTTP connection handler.
24
+
25
+ This class provides direct access to HTTP communication functionality, wrapping
26
+ an aiohttp client session. It handles the conversion between the networkpype
27
+ request/response types and the underlying aiohttp types.
28
+
29
+ The connection is designed to be reused across multiple requests to take advantage
30
+ of connection pooling and other HTTP/1.1 and HTTP/2 optimizations.
31
+
32
+ Attributes:
33
+ _client_session (aiohttp.ClientSession): The underlying aiohttp client session.
34
+
35
+ Example:
36
+ ```python
37
+ async with aiohttp.ClientSession() as session:
38
+ connection = RESTConnection(session)
39
+ request = RESTRequest(
40
+ method=RESTMethod.GET,
41
+ url="https://api.example.com/data"
42
+ )
43
+ response = await connection.call(request)
44
+ data = await response.json()
45
+ ```
46
+ """
47
+
48
+ def __init__(self, aiohttp_client_session: aiohttp.ClientSession):
49
+ """Initialize the RESTConnection with an aiohttp client session.
50
+
51
+ Args:
52
+ aiohttp_client_session (aiohttp.ClientSession): The aiohttp client session
53
+ to use for making HTTP requests.
54
+ """
55
+ self._client_session = aiohttp_client_session
56
+
57
+ async def call(
58
+ self, request: RESTRequest, encoded: bool = False, **kwargs
59
+ ) -> RESTResponse:
60
+ """Execute an HTTP request.
61
+
62
+ This method converts the networkpype request into an aiohttp request,
63
+ executes it, and wraps the response in a networkpype response object.
64
+
65
+ Args:
66
+ request (RESTRequest): The request to execute.
67
+ encoded (bool): Whether the URL is already percent-encoded. If True,
68
+ no additional encoding will be performed. Defaults to False.
69
+ **kwargs: Additional arguments to pass to aiohttp.ClientSession.request().
70
+
71
+ Returns:
72
+ RESTResponse: The response from the server.
73
+
74
+ Raises:
75
+ aiohttp.ClientError: If there is an error making the request.
76
+ asyncio.TimeoutError: If the request times out.
77
+ ValueError: If the request URL is None.
78
+ """
79
+ if request.url is None:
80
+ raise ValueError("Request URL cannot be None")
81
+
82
+ aiohttp_resp = await self._client_session.request(
83
+ method=request.method.value,
84
+ url=URL(request.url, encoded=encoded),
85
+ params=request.params,
86
+ data=request.data,
87
+ headers=request.headers,
88
+ **kwargs,
89
+ )
90
+
91
+ resp = await self._build_resp(aiohttp_resp)
92
+ return resp
93
+
94
+ @staticmethod
95
+ async def _build_resp(aiohttp_resp: aiohttp.ClientResponse) -> RESTResponse:
96
+ """Build a networkpype response from an aiohttp response.
97
+
98
+ Args:
99
+ aiohttp_resp (aiohttp.ClientResponse): The aiohttp response to wrap.
100
+
101
+ Returns:
102
+ RESTResponse: The wrapped response.
103
+ """
104
+ resp = RESTResponse(aiohttp_resp)
105
+ return resp