Skip to content

Commit b71fc21

Browse files
refactor: wip
1 parent 3090db1 commit b71fc21

2 files changed

Lines changed: 205 additions & 17 deletions

File tree

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# coding: utf-8
2+
3+
from __future__ import absolute_import
4+
5+
import io
6+
import multiprocessing
7+
import ssl
8+
from urllib.parse import urlencode
9+
10+
from influxdb_client_3.write_client.rest import ApiException
11+
12+
try:
13+
import urllib3
14+
except ImportError:
15+
raise ImportError('OpenAPI Python client requires urllib3.')
16+
17+
18+
class RESTResponse(io.IOBase):
19+
20+
def __init__(self, resp):
21+
"""Initialize with HTTP response."""
22+
self.urllib3_response = resp
23+
self.status = resp.status
24+
self.reason = resp.reason
25+
self.data = resp.data
26+
27+
def getheaders(self):
28+
"""Return a dictionary of the response headers."""
29+
return self.urllib3_response.headers
30+
31+
def getheader(self, name, default=None):
32+
"""Return a given response header."""
33+
return self.urllib3_response.headers.get(name, default)
34+
35+
def get_string_body(self):
36+
return self.urllib3_response.data.decode('utf-8')
37+
38+
class RestClient(object):
39+
40+
def __init__(self,
41+
base_url,
42+
default_header=None,
43+
verify_ssl=True,
44+
ssl_ca_cert=None,
45+
cert_file=None,
46+
cert_key_file=None,
47+
cert_key_password=None,
48+
ssl_context=None,
49+
proxy=None,
50+
proxy_headers=None,
51+
enable_gzip=False,
52+
gzip_threshold=None,
53+
pools_size=4,
54+
maxsize=None,
55+
timeout=None,
56+
retries=False,
57+
connection_pool_maxsize=multiprocessing.cpu_count() * 5,
58+
):
59+
"""Initialize REST client."""
60+
# urllib3.PoolManager will pass all kw parameters to connectionpool
61+
# https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75 # noqa: E501
62+
# https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680 # noqa: E501
63+
# maxsize is the number of requests to host that are allowed in parallel # noqa: E501
64+
# Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html # noqa: E501
65+
66+
self.pools_size = pools_size
67+
self.maxsize = maxsize
68+
self.timeout = timeout
69+
self.retries = retries
70+
self.default_header = default_header
71+
72+
# cert_reqs
73+
if verify_ssl:
74+
cert_reqs = ssl.CERT_REQUIRED
75+
else:
76+
cert_reqs = ssl.CERT_NONE
77+
78+
# ca_certs
79+
if ssl_ca_cert:
80+
ca_certs = ssl_ca_cert
81+
else:
82+
ca_certs = None
83+
84+
addition_pool_args = {'retries': self.retries}
85+
86+
if maxsize is None:
87+
if connection_pool_maxsize is not None:
88+
maxsize = connection_pool_maxsize
89+
else:
90+
maxsize = 4
91+
92+
# https pool manager
93+
if proxy:
94+
self.pool_manager = urllib3.ProxyManager(
95+
host='localhost',
96+
port=8181,
97+
num_pools=pools_size,
98+
maxsize=maxsize,
99+
cert_reqs=cert_reqs,
100+
ca_certs=ca_certs,
101+
cert_file=cert_file,
102+
key_file=cert_key_file,
103+
key_password=cert_key_password,
104+
proxy_url=proxy,
105+
proxy_headers=proxy_headers,
106+
ssl_context=ssl_context,
107+
**addition_pool_args
108+
).connection_from_url(url=base_url)
109+
else:
110+
self.pool_manager = urllib3.PoolManager(
111+
host='localhost',
112+
port=8181,
113+
num_pools=pools_size,
114+
maxsize=maxsize,
115+
cert_reqs=cert_reqs,
116+
ca_certs=ca_certs,
117+
cert_file=cert_file,
118+
key_file=cert_key_file,
119+
key_password=cert_key_password,
120+
ssl_context=ssl_context,
121+
**addition_pool_args
122+
).connection_from_url(url=base_url)
123+
124+
def request(self, method, url, query_params=None, headers=None,
125+
body=None, timeout=None, **urlopen_kw):
126+
"""Perform requests.
127+
128+
:param method: http request method
129+
:param url: http request url
130+
:param query_params: query parameters in the url
131+
:param headers: http request headers
132+
:param body: request json body, for `application/json`
133+
:param timeout: timeout setting for this request. If one
134+
number provided, it will be total request
135+
timeout. It can also be a pair (tuple) of
136+
(connection, read) timeouts.
137+
:param urlopen_kw: Additional parameters are passed to
138+
:meth:`urllib3.request.RequestMethods.request`
139+
"""
140+
# timeout = None
141+
# _configured_timeout = _request_timeout or self.timeout
142+
# if _configured_timeout:
143+
# if isinstance(_configured_timeout, (int, float,)): # noqa: E501,F821
144+
# timeout = urllib3.Timeout(total=_configured_timeout / 1_000)
145+
# elif (isinstance(_configured_timeout, tuple) and
146+
# len(_configured_timeout) == 2):
147+
# timeout = urllib3.Timeout(
148+
# connect=_configured_timeout[0] / 1_000, read=_configured_timeout[1] / 1_000)
149+
150+
if headers is None or len(headers) == 0:
151+
headers = self.default_header
152+
153+
# TODO: debug logics ?
154+
# if self.configuration.debug:
155+
# _BaseRESTClient.log_request(method, f"{url}?{urlencode(query_params)}")
156+
# _BaseRESTClient.log_headers(headers, '>>>')
157+
# _BaseRESTClient.log_body(body, '>>>')
158+
159+
# TODO: body string or json ???
160+
161+
if query_params is not None and query_params != {}:
162+
url += '?' + urlencode(query_params)
163+
164+
r = self.pool_manager.request(method, url,
165+
body=body,
166+
headers=headers,
167+
timeout=timeout,
168+
**urlopen_kw)
169+
170+
r = RESTResponse(r)
171+
172+
# TODO: debug logics ?
173+
# if self.configuration.debug:
174+
# _BaseRESTClient.log_response(r.status)
175+
# if hasattr(r, 'headers'):
176+
# _BaseRESTClient.log_headers(r.headers, '<<<')
177+
# if hasattr(r, 'urllib3_response'):
178+
# _BaseRESTClient.log_headers(r.urllib3_response.headers, '<<<')
179+
# _BaseRESTClient.log_body(r.data, '<<<')
180+
181+
if not 200 <= r.status <= 299:
182+
raise ApiException(http_resp=r)
183+
184+
return r
185+
186+
def __getstate__(self):
187+
"""Return a dict of attributes that you want to pickle."""
188+
state = self.__dict__.copy()
189+
# Remove Pool managaer
190+
del state['pool_manager']
191+
return state
192+
193+
def __setstate__(self, state):
194+
"""Set your object with the provided dict."""
195+
self.__dict__.update(state)
196+
# Init Pool manager
197+
self.__init__(self.pools_size, self.maxsize, self.retries)

influxdb_client_3/write_client/client/write_api.py

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44
# TODO Remove after this program no longer supports Python 3.8.*
55
from __future__ import annotations
66

7-
import logging
87
import datetime
8+
import logging
99
import os
1010
import warnings
1111
from collections import defaultdict
12-
1312
from enum import Enum
1413
from http import HTTPStatus
1514
from multiprocessing.pool import ThreadPool
1615
from random import random
1716
from time import sleep
1817
from typing import Union, Any, Iterable, NamedTuple
18+
1919
import reactivex as rx
2020
import urllib3
2121
from reactivex import operators as ops, Observable
@@ -24,7 +24,7 @@
2424

2525
from influxdb_client_3.exceptions import InfluxDBPartialWriteError
2626
from influxdb_client_3.version import USER_AGENT
27-
from influxdb_client_3.write_client._sync import rest_client
27+
from influxdb_client_3.write_client._sync.rest_client import RestClient
2828
from influxdb_client_3.write_client.client._base import _HAS_DATACLASS
2929
from influxdb_client_3.write_client.client.write.dataframe_serializer import DataframeSerializer
3030
from influxdb_client_3.write_client.client.write.point import Point, DEFAULT_WRITE_PRECISION, sanitize_tag_order
@@ -292,7 +292,6 @@ class WriteApi:
292292
"""
293293

294294
def __init__(self,
295-
base_url: str,
296295
token: str,
297296
bucket: str,
298297
org: str,
@@ -301,6 +300,7 @@ def __init__(self,
301300
auth_scheme=None,
302301
timeout=None,
303302
pool_threads = None,
303+
rest_client: RestClient = None,
304304
write_options: WriteOptions = WriteOptions(),
305305
point_settings: PointSettings = PointSettings(),
306306
**kwargs) -> None:
@@ -336,11 +336,8 @@ def __init__(self,
336336
"""
337337
# TODO should allow passing auth schema???
338338

339-
# TODO fix retries
340-
retries = None
341-
self.rest_client = rest_client.RestClient(retries=retries)
339+
self.rest_client = rest_client
342340

343-
self.base_url = base_url
344341
self.token = token
345342
self.bucket = bucket
346343
self.org = org
@@ -883,9 +880,6 @@ def __call_api(
883880
if query_params:
884881
query_params = self.sanitize_for_serialization(query_params)
885882

886-
# request url
887-
url = self.base_url + resource_path
888-
889883
urlopen_kw = urlopen_kw or {}
890884

891885
timeout = None
@@ -901,7 +895,7 @@ def __call_api(
901895
# perform request and return response
902896
response_data = self.rest_client.request(
903897
method=method,
904-
url=url,
898+
url=resource_path,
905899
query_params=query_params,
906900
headers=header_params,
907901
body=body,
@@ -1233,11 +1227,8 @@ def _post_write_prepare(self, org, bucket, body, **kwargs): # noqa: E501,D401,D
12331227
if accept_partial is False:
12341228
query_params.append(('accept_partial', 'false'))
12351229

1236-
auth_schema = 'Token' if self.auth_scheme is None else self.auth_scheme
1237-
header_params = {
1238-
'Authorization': f'{auth_schema} {self.token}',
1239-
'User-Agent': USER_AGENT
1240-
}
1230+
1231+
header_params = {}
12411232

12421233
if 'content_encoding' in local_var_params:
12431234
header_params['Content-Encoding'] = local_var_params['content_encoding'] # noqa: E501

0 commit comments

Comments
 (0)