influxparser 0.0.5
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.
- checksums.yaml +7 -0
- data/lib/influxparser.rb +93 -0
- data/test/test_parse_point_from_docs.rb +293 -0
- metadata +45 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 79b8236a2441da883a688e7d4284a1c191358db2
|
4
|
+
data.tar.gz: b2d6bc730f78faad33e35429c5e68e9c19c292ed
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: db897eaf4b325a0ed1c0bffde1162ed1e23d6ff1800c6762b90749117af45a782e33795cd117a9a44e74754af7725980c5d8fc384537216178c0c74bfb061596
|
7
|
+
data.tar.gz: 83a972e25f5e5259230c2bb9cb6e3a46b3faadb46694d4a11e76a25deb3b5cb3eff27e06ef0be1f3da0664653f96950bbc6c5b43b338cbacaf7cbd3fa9eda982
|
data/lib/influxparser.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# TODO: the tags hash should be absent when there are no tags
|
2
|
+
# TODO: time key shouldn't exist if there is no time
|
3
|
+
# TODO: deal with improper line protocol
|
4
|
+
class InfluxParser
|
5
|
+
class << self
|
6
|
+
def parse_point(s, options = {})
|
7
|
+
default_options = {:parse_types => true, :time_format => nil}
|
8
|
+
options = default_options.merge(options)
|
9
|
+
|
10
|
+
point = {}
|
11
|
+
point['_raw'] = s
|
12
|
+
s = s.strip # trim whitespace
|
13
|
+
|
14
|
+
measurement_end = s.index /(?<!\\) /
|
15
|
+
|
16
|
+
|
17
|
+
mparts = s[0..measurement_end-1].split(/(?<!\\),/) # split on unescaped commas for the measurement name and tags
|
18
|
+
point['series'] = unescape_measurement mparts[0]
|
19
|
+
|
20
|
+
# if any tags were attached to the measurement iterate over them now
|
21
|
+
point['tags'] = {}
|
22
|
+
mparts.drop(1).each do |t|
|
23
|
+
tag = t.split(/(?<!\\)=/)
|
24
|
+
point['tags'][unescape_tag tag[0]] = unescape_tag tag[1]
|
25
|
+
end
|
26
|
+
|
27
|
+
# now iterate over the values
|
28
|
+
last_value_raw = ''
|
29
|
+
last_key = ''
|
30
|
+
point['values'] = {}
|
31
|
+
vparts = s[measurement_end+1..-1].split(/(?<!\\),/)
|
32
|
+
# puts "vparts:#{vparts}"
|
33
|
+
vparts.each do |v|
|
34
|
+
value = v.split(/(?<!\\)=/)
|
35
|
+
last_value_raw = value[1]
|
36
|
+
last_key = unescape_tag value[0]
|
37
|
+
# puts "last k/v #{last_key}==#{last_value_raw}"
|
38
|
+
point['values'][last_key] = unescape_point(value[1],options)
|
39
|
+
end
|
40
|
+
# puts "-----\n#{point['values'].to_yaml}\n"
|
41
|
+
|
42
|
+
# check for a timestamp in the last value
|
43
|
+
# TODO: I hate this, but it's late and I just want to move past it for now
|
44
|
+
# TODO: this level of nesting would fill rubocop with rage
|
45
|
+
has_space = last_value_raw.rindex(/ /)
|
46
|
+
if has_space
|
47
|
+
time_stamp = last_value_raw[has_space+1..-1] # take everything from the space to the end
|
48
|
+
if time_stamp.index(/"/)
|
49
|
+
point['timestamp'] = nil
|
50
|
+
else
|
51
|
+
# it was a timestamp, strip it from the last value and set the timestamp
|
52
|
+
point['values'][last_key] = unescape_point(last_value_raw[0..has_space-1],options)
|
53
|
+
point['timestamp'] = time_stamp
|
54
|
+
if options[:time_format]
|
55
|
+
n_time = time_stamp.to_f / 1000000000
|
56
|
+
t = Time.at(n_time).utc
|
57
|
+
point['timestamp'] = t.strftime(options[:time_format])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
else
|
61
|
+
point['timestamp'] = nil
|
62
|
+
end
|
63
|
+
|
64
|
+
point
|
65
|
+
end
|
66
|
+
def unescape_measurement(s)
|
67
|
+
s.gsub(/\\ /,' ').gsub(/\\,/,',')
|
68
|
+
end
|
69
|
+
def unescape_tag(s)
|
70
|
+
t = unescape_measurement s
|
71
|
+
t.gsub(/\\=/,'=')
|
72
|
+
end
|
73
|
+
def unescape_point(s,options)
|
74
|
+
# puts "unescape:#{s}"
|
75
|
+
# s = s.gsub(/\\\\/,'\\').gsub(/\\"/,'""') # handle escaped characters if present
|
76
|
+
|
77
|
+
# it is a string, return it
|
78
|
+
return s[1..-2].gsub(/\\\\/,'\\').gsub(/\\"/,'""') if s[0,1] == '"'
|
79
|
+
|
80
|
+
return s.sub(/(?<=\d)i/,'') if (!options[:parse_types]) # the customer doesn't care about types so just return it, but strip the trailing i from an integer because we care
|
81
|
+
|
82
|
+
# handle the booleans
|
83
|
+
return true if ['t','T','true','True','TRUE'].include?(s)
|
84
|
+
return false if ['f','F','false','False','FALSE'].include?(s)
|
85
|
+
|
86
|
+
# by here we have either an unquoted string or some numeric
|
87
|
+
|
88
|
+
return s.to_f if s =~ /^(\d|\.)+$/ # floats are only digits and dots
|
89
|
+
return s.chomp('i').to_i if s[0..-2] =~ /^(\d)+$/ # trailing i is an integer remove it
|
90
|
+
return s.gsub(/\\\\/,'\\').gsub(/\\"/,'"')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,293 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
4
|
+
require 'test/unit'
|
5
|
+
require 'influxparser'
|
6
|
+
class TestParsePointFromDocs < Test::Unit::TestCase # def setup
|
7
|
+
# end
|
8
|
+
|
9
|
+
|
10
|
+
# def teardown
|
11
|
+
# end
|
12
|
+
|
13
|
+
def test_two_tags
|
14
|
+
point = InfluxParser.parse_point('weather,location=us-midwest,season=summer temperature=82 1465839830100400200')
|
15
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
16
|
+
|
17
|
+
# measurement
|
18
|
+
assert_equal('weather',point['series'])
|
19
|
+
|
20
|
+
# tags
|
21
|
+
assert_equal(2,point['tags'].length)
|
22
|
+
|
23
|
+
# check location
|
24
|
+
assert_equal(true,point['tags'].key?('location'))
|
25
|
+
assert_equal('us-midwest',point['tags']['location'])
|
26
|
+
|
27
|
+
# check season
|
28
|
+
assert_equal(true,point['tags'].key?('season'))
|
29
|
+
assert_equal('summer',point['tags']['season'])
|
30
|
+
|
31
|
+
# value
|
32
|
+
assert_equal(true,point['values'].key?('temperature'))
|
33
|
+
assert_equal(82,point['values']['temperature'])
|
34
|
+
|
35
|
+
# time
|
36
|
+
assert_equal('1465839830100400200',point['timestamp'])
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_no_tags
|
41
|
+
point = InfluxParser.parse_point('weather temperature=82 1465839830100400200')
|
42
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
43
|
+
|
44
|
+
# measurement
|
45
|
+
assert_equal('weather',point['series'])
|
46
|
+
|
47
|
+
# no tags
|
48
|
+
assert_equal(true,point.key?('tags'))
|
49
|
+
assert_equal(0,point['tags'].length)
|
50
|
+
|
51
|
+
# value
|
52
|
+
assert_equal(true,point['values'].key?('temperature'))
|
53
|
+
assert_equal(82,point['values']['temperature'])
|
54
|
+
|
55
|
+
# time
|
56
|
+
assert_equal('1465839830100400200',point['timestamp'])
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_two_values
|
61
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature=82,humidity=71 1465839830100400200')
|
62
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
63
|
+
|
64
|
+
# measurement
|
65
|
+
assert_equal('weather',point['series'])
|
66
|
+
|
67
|
+
# check location
|
68
|
+
assert_equal(true,point['tags'].key?('location'))
|
69
|
+
assert_equal('us-midwest',point['tags']['location'])
|
70
|
+
|
71
|
+
# values
|
72
|
+
assert_equal(2,point['values'].length)
|
73
|
+
|
74
|
+
assert_equal(true,point['values'].key?('temperature'))
|
75
|
+
assert_equal(82,point['values']['temperature'])
|
76
|
+
|
77
|
+
assert_equal(true,point['values'].key?('humidity'))
|
78
|
+
assert_equal(71,point['values']['humidity'])
|
79
|
+
|
80
|
+
# time
|
81
|
+
assert_equal('1465839830100400200',point['timestamp'])
|
82
|
+
|
83
|
+
end
|
84
|
+
def test_timestamp
|
85
|
+
# no timestamp
|
86
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature=82')
|
87
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
88
|
+
assert_nil(point['timestamp'])
|
89
|
+
|
90
|
+
# unformatted time
|
91
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature=82 1465839830100400200')
|
92
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
93
|
+
assert_equal('1465839830100400200',point['timestamp'])
|
94
|
+
|
95
|
+
# time
|
96
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature=82 1465839830100400200',{:time_format => "%Y-%d-%mT%H:%M:%S.%NZ"})
|
97
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
98
|
+
assert_equal('2016-13-06T17:43:50.100400209Z',point['timestamp'])
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_float
|
103
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature=82 1465839830100400200')
|
104
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
105
|
+
assert_equal(82.0,point['values']['temperature'])
|
106
|
+
end
|
107
|
+
def test_integer
|
108
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature=82i 1465839830100400200')
|
109
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
110
|
+
assert_equal(82,point['values']['temperature'])
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_string
|
114
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature="too warm" 1465839830100400200')
|
115
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
116
|
+
assert_equal('too warm',point['values']['temperature'])
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_invalid_time
|
120
|
+
# TODO: this should be throwing a parse error
|
121
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature=82 "1465839830100400200"')
|
122
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_invalid_string
|
127
|
+
# TODO: this should be throwing a parse error
|
128
|
+
point = InfluxParser.parse_point("weather,location=us-midwest temperature='too warm' 1465839830100400200")
|
129
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_boolean
|
133
|
+
point = InfluxParser.parse_point("weather,location=us-midwest temperature=t 1465839830100400200")
|
134
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
135
|
+
assert_equal(true,point['values']['temperature'])
|
136
|
+
|
137
|
+
point = InfluxParser.parse_point("weather,location=us-midwest temperature=T 1465839830100400200")
|
138
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
139
|
+
assert_equal(true,point['values']['temperature'])
|
140
|
+
|
141
|
+
point = InfluxParser.parse_point("weather,location=us-midwest temperature=true 1465839830100400200")
|
142
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
143
|
+
assert_equal(true,point['values']['temperature'])
|
144
|
+
|
145
|
+
point = InfluxParser.parse_point("weather,location=us-midwest temperature=True 1465839830100400200")
|
146
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
147
|
+
assert_equal(true,point['values']['temperature'])
|
148
|
+
|
149
|
+
point = InfluxParser.parse_point("weather,location=us-midwest temperature=TRUE 1465839830100400200")
|
150
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
151
|
+
assert_equal(true,point['values']['temperature'])
|
152
|
+
|
153
|
+
point = InfluxParser.parse_point("weather,location=us-midwest temperature=f 1465839830100400200")
|
154
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
155
|
+
assert_equal(false,point['values']['temperature'])
|
156
|
+
|
157
|
+
point = InfluxParser.parse_point("weather,location=us-midwest temperature=F 1465839830100400200")
|
158
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
159
|
+
assert_equal(false,point['values']['temperature'])
|
160
|
+
|
161
|
+
point = InfluxParser.parse_point("weather,location=us-midwest temperature=false 1465839830100400200")
|
162
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
163
|
+
assert_equal(false,point['values']['temperature'])
|
164
|
+
|
165
|
+
point = InfluxParser.parse_point("weather,location=us-midwest temperature=False 1465839830100400200")
|
166
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
167
|
+
assert_equal(false,point['values']['temperature'])
|
168
|
+
|
169
|
+
point = InfluxParser.parse_point("weather,location=us-midwest temperature=FALSE 1465839830100400200")
|
170
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
171
|
+
assert_equal(false,point['values']['temperature'])
|
172
|
+
|
173
|
+
end
|
174
|
+
def test_ridiculous_quotes
|
175
|
+
# from the influx docs: Do not double or single quote measurement names, tag keys, tag values, and field keys. It is valid line protocol but InfluxDB assumes that the quotes are part of the name.
|
176
|
+
point = InfluxParser.parse_point('"weather","location"="us-midwest" "temperature"=82 1465839830100400200')
|
177
|
+
|
178
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
179
|
+
# measurement
|
180
|
+
assert_equal('"weather"',point['series'])
|
181
|
+
|
182
|
+
# check tag
|
183
|
+
assert_equal(true,point['tags'].key?('"location"'))
|
184
|
+
assert_equal('"us-midwest"',point['tags']['"location"'])
|
185
|
+
|
186
|
+
# check values
|
187
|
+
|
188
|
+
assert_equal(true,point['values'].key?('"temperature"'))
|
189
|
+
assert_equal(82,point['values']['"temperature"'])
|
190
|
+
|
191
|
+
# time
|
192
|
+
assert_equal('1465839830100400200',point['timestamp'])
|
193
|
+
|
194
|
+
|
195
|
+
|
196
|
+
# Do the same thing for ridiculous single quotes
|
197
|
+
point = InfluxParser.parse_point("'weather','location'='us-midwest' 'temperature'=82 1465839830100400200")
|
198
|
+
|
199
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
200
|
+
# measurement
|
201
|
+
assert_equal("'weather'",point['series'])
|
202
|
+
|
203
|
+
# check tag
|
204
|
+
assert_equal(true,point['tags'].key?("'location'"))
|
205
|
+
assert_equal("'us-midwest'",point['tags']["'location'"])
|
206
|
+
|
207
|
+
# check values
|
208
|
+
|
209
|
+
assert_equal(true,point['values'].key?("'temperature'"))
|
210
|
+
assert_equal(82,point['values']["'temperature'"])
|
211
|
+
|
212
|
+
# time
|
213
|
+
assert_equal('1465839830100400200',point['timestamp'])
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_escaping
|
218
|
+
point = InfluxParser.parse_point('weather,location=us\,midwest temperature=82 1465839830100400200')
|
219
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
220
|
+
assert_equal('us,midwest',point['tags']['location'])
|
221
|
+
|
222
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temp\=rature=82 1465839830100400200')
|
223
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
224
|
+
assert_equal(82,point['values']['temp=rature'])
|
225
|
+
|
226
|
+
point = InfluxParser.parse_point('weather,location\ place=us-midwest temperature=82 1465839830100400200')
|
227
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
228
|
+
assert_equal(true,point['tags'].key?('location place'))
|
229
|
+
|
230
|
+
point = InfluxParser.parse_point('wea\,ther,location=us-midwest temperature=82 1465839830100400200')
|
231
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
232
|
+
assert_equal('wea,ther',point['series'])
|
233
|
+
|
234
|
+
point = InfluxParser.parse_point('wea\ ther,location=us-midwest temperature=82 1465839830100400200')
|
235
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
236
|
+
assert_equal('wea ther',point['series'])
|
237
|
+
|
238
|
+
point = InfluxParser.parse_point('weather temperature=toohot\"')
|
239
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
240
|
+
assert_equal('toohot"',point['values']['temperature'])
|
241
|
+
|
242
|
+
|
243
|
+
# so many slashes -- note they're extra terrible because I need to escape ruby slashes in the test strings
|
244
|
+
|
245
|
+
# forward slash
|
246
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature_str="too hot/cold" 1465839830100400201')
|
247
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
248
|
+
assert_equal('too hot/cold',point['values']['temperature_str'])
|
249
|
+
|
250
|
+
# one slash
|
251
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature_str="too hot\cold" 1465839830100400201')
|
252
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
253
|
+
assert_equal('too hot\cold',point['values']['temperature_str'])
|
254
|
+
|
255
|
+
# two slashes
|
256
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature_str="too hot\\\cold" 1465839830100400201')
|
257
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
258
|
+
assert_equal('too hot\cold',point['values']['temperature_str'])
|
259
|
+
|
260
|
+
# three slashes
|
261
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature_str="too hot\\\\\cold" 1465839830100400201')
|
262
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
263
|
+
assert_equal("too hot\\\\cold",point['values']['temperature_str'])
|
264
|
+
|
265
|
+
# four slashes
|
266
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature_str="too hot\\\\\\\cold" 1465839830100400201')
|
267
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
268
|
+
assert_equal("too hot\\\\cold",point['values']['temperature_str'])
|
269
|
+
|
270
|
+
# five slashes
|
271
|
+
point = InfluxParser.parse_point('weather,location=us-midwest temperature_str="too hot\\\\\\\\\cold" 1465839830100400201')
|
272
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
273
|
+
assert_equal("too hot\\\\\\cold",point['values']['temperature_str'])
|
274
|
+
|
275
|
+
end
|
276
|
+
def test_types
|
277
|
+
point = InfluxParser.parse_point('weather float=82,integer=82i,impliedstring=helloworld,explicitstring="hello world" 1465839830100400200')
|
278
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
279
|
+
assert_equal(82.0,point['values']['float'])
|
280
|
+
assert_equal(82,point['values']['integer'])
|
281
|
+
assert_equal('helloworld',point['values']['impliedstring'])
|
282
|
+
assert_equal('hello world',point['values']['explicitstring'])
|
283
|
+
|
284
|
+
# do it again but this time without type parsing
|
285
|
+
point = InfluxParser.parse_point('weather float=82,integer=82i,impliedstring=helloworld,explicitstring="hello world" 1465839830100400200',{:parse_types => false})
|
286
|
+
assert_not_equal(false,point) # a straight up parse error will false
|
287
|
+
assert_equal('82',point['values']['float'])
|
288
|
+
assert_equal('82',point['values']['integer'])
|
289
|
+
assert_equal('helloworld',point['values']['impliedstring'])
|
290
|
+
assert_equal('hello world',point['values']['explicitstring'])
|
291
|
+
|
292
|
+
end
|
293
|
+
end
|
metadata
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: influxparser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Robert Labrie
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-02-03 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Unofficial influx line protocol parser
|
14
|
+
email: robert.labrie@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/influxparser.rb
|
20
|
+
- test/test_parse_point_from_docs.rb
|
21
|
+
homepage:
|
22
|
+
licenses: []
|
23
|
+
metadata: {}
|
24
|
+
post_install_message:
|
25
|
+
rdoc_options: []
|
26
|
+
require_paths:
|
27
|
+
- lib
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
34
|
+
requirements:
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
requirements: []
|
39
|
+
rubyforge_project:
|
40
|
+
rubygems_version: 2.5.2.1
|
41
|
+
signing_key:
|
42
|
+
specification_version: 3
|
43
|
+
summary: InfluxDB line protocol parser
|
44
|
+
test_files:
|
45
|
+
- test/test_parse_point_from_docs.rb
|