Skip to content

Commit fe46aa0

Browse files
authored
Merge branch 'master' into master
2 parents 4e576a5 + c300105 commit fe46aa0

File tree

6 files changed

+66
-14
lines changed

6 files changed

+66
-14
lines changed

examples/tutorial_pandas.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ def main(host='localhost', port=8086):
1212
user = 'root'
1313
password = 'root'
1414
dbname = 'demo'
15-
# Temporarily avoid line protocol time conversion issues #412, #426, #431.
1615
protocol = 'json'
1716

1817
client = DataFrameClient(host, port, user, password, dbname)

influxdb/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@
1818
]
1919

2020

21-
__version__ = '5.0.0'
21+
__version__ = '5.1.0'

influxdb/_dataframe_client.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ def _convert_dataframe_to_json(dataframe,
236236
field_columns = list(
237237
set(dataframe.columns).difference(set(tag_columns)))
238238

239-
dataframe.index = dataframe.index.to_datetime()
239+
dataframe.index = pd.to_datetime(dataframe.index)
240240
if dataframe.index.tzinfo is None:
241241
dataframe.index = dataframe.index.tz_localize('UTC')
242242

@@ -288,6 +288,8 @@ def _convert_dataframe_to_lines(self,
288288
raise TypeError('Must be DataFrame with DatetimeIndex or '
289289
'PeriodIndex.')
290290

291+
dataframe = dataframe.rename(
292+
columns={item: _escape_tag(item) for item in dataframe.columns})
291293
# Create a Series of columns for easier indexing
292294
column_series = pd.Series(dataframe.columns)
293295

@@ -363,16 +365,18 @@ def _convert_dataframe_to_lines(self,
363365

364366
# Make an array of formatted field keys and values
365367
field_df = dataframe[field_columns]
368+
# Keep the positions where Null values are found
369+
mask_null = field_df.isnull().values
366370

367371
field_df = self._stringify_dataframe(field_df,
368372
numeric_precision,
369373
datatype='field')
370374

371-
def format_line(line):
372-
line = line[~line.isnull()] # drop None entries
373-
return ",".join((line.index + '=' + line.values))
374-
375-
fields = field_df.apply(format_line, axis=1)
375+
field_df = (field_df.columns.values + '=').tolist() + field_df
376+
field_df[field_df.columns[1:]] = ',' + field_df[
377+
field_df.columns[1:]]
378+
field_df = field_df.where(~mask_null, '') # drop Null entries
379+
fields = field_df.sum(axis=1)
376380
del field_df
377381

378382
# Generate line protocol string
@@ -386,9 +390,6 @@ def _stringify_dataframe(dframe, numeric_precision, datatype='field'):
386390
# Prevent modification of input dataframe
387391
dframe = dframe.copy()
388392

389-
# Keep the positions where Null values are found
390-
mask_null = dframe.isnull().values
391-
392393
# Find int and string columns for field-type data
393394
int_columns = dframe.select_dtypes(include=['integer']).columns
394395
string_columns = dframe.select_dtypes(include=['object']).columns
@@ -433,7 +434,6 @@ def _stringify_dataframe(dframe, numeric_precision, datatype='field'):
433434

434435
dframe.columns = dframe.columns.astype(str)
435436

436-
dframe = dframe.where(~mask_null, None)
437437
return dframe
438438

439439
def _datetime_to_epoch(self, datetime, time_precision='s'):

influxdb/client.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ class InfluxDBClient(object):
5959
:type udp_port: int
6060
:param proxies: HTTP(S) proxy to use for Requests, defaults to {}
6161
:type proxies: dict
62+
:param path: path of InfluxDB on the server to connect, defaults to ''
63+
:type path: str
6264
"""
6365

6466
def __init__(self,
@@ -75,6 +77,7 @@ def __init__(self,
7577
udp_port=4444,
7678
proxies=None,
7779
pool_size=10,
80+
path='',
7881
):
7982
"""Construct a new InfluxDBClient object."""
8083
self.__host = host
@@ -98,6 +101,13 @@ def __init__(self,
98101
if use_udp:
99102
self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
100103

104+
if not path:
105+
self.__path = ''
106+
elif path[0] == '/':
107+
self.__path = path
108+
else:
109+
self.__path = '/' + path
110+
101111
self._scheme = "http"
102112

103113
if ssl is True:
@@ -110,10 +120,11 @@ def __init__(self,
110120
else:
111121
self._proxies = proxies
112122

113-
self.__baseurl = "{0}://{1}:{2}".format(
123+
self.__baseurl = "{0}://{1}:{2}{3}".format(
114124
self._scheme,
115125
self._host,
116-
self._port)
126+
self._port,
127+
self._path)
117128

118129
self._headers = {
119130
'Content-Type': 'application/json',
@@ -132,6 +143,10 @@ def _host(self):
132143
def _port(self):
133144
return self.__port
134145

146+
@property
147+
def _path(self):
148+
return self.__path
149+
135150
@property
136151
def _udp_port(self):
137152
return self.__udp_port

influxdb/tests/client_test.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,24 @@ def test_scheme(self):
109109
)
110110
self.assertEqual('https://host:8086', cli._baseurl)
111111

112+
cli = InfluxDBClient(
113+
'host', 8086, 'username', 'password', 'database', ssl=True,
114+
path="somepath"
115+
)
116+
self.assertEqual('https://host:8086/somepath', cli._baseurl)
117+
118+
cli = InfluxDBClient(
119+
'host', 8086, 'username', 'password', 'database', ssl=True,
120+
path=None
121+
)
122+
self.assertEqual('https://host:8086', cli._baseurl)
123+
124+
cli = InfluxDBClient(
125+
'host', 8086, 'username', 'password', 'database', ssl=True,
126+
path="/somepath"
127+
)
128+
self.assertEqual('https://host:8086/somepath', cli._baseurl)
129+
112130
def test_dsn(self):
113131
"""Set up the test datasource name for TestInfluxDBClient object."""
114132
cli = InfluxDBClient.from_dsn('influxdb://192.168.0.1:1886')

influxdb/tests/dataframe_client_test.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,26 @@ def test_dataframe_write_points_with_whitespace_measurement(self):
8181
cli.write_points(dataframe, 'meas with space')
8282
self.assertEqual(m.last_request.body, expected)
8383

84+
def test_dataframe_write_points_with_whitespace_in_column_names(self):
85+
"""write_points should escape white space in column names."""
86+
now = pd.Timestamp('1970-01-01 00:00+00:00')
87+
dataframe = pd.DataFrame(data=[["1", 1, 1.0], ["2", 2, 2.0]],
88+
index=[now, now + timedelta(hours=1)],
89+
columns=["column one", "column two",
90+
"column three"])
91+
expected = (
92+
b"foo column\\ one=\"1\",column\\ two=1i,column\\ three=1.0 0\n"
93+
b"foo column\\ one=\"2\",column\\ two=2i,column\\ three=2.0 "
94+
b"3600000000000\n"
95+
)
96+
with requests_mock.Mocker() as m:
97+
m.register_uri(requests_mock.POST,
98+
"http://localhost:8086/write",
99+
status_code=204)
100+
cli = DataFrameClient(database='db')
101+
cli.write_points(dataframe, 'foo')
102+
self.assertEqual(m.last_request.body, expected)
103+
84104
def test_write_points_from_dataframe_with_none(self):
85105
"""Test write points from df in TestDataFrameClient object."""
86106
now = pd.Timestamp('1970-01-01 00:00+00:00')

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy