Skip to content

Commit e8d978b

Browse files
authored
Linting with flake8 (#111)
1 parent da547e4 commit e8d978b

File tree

12 files changed

+270
-170
lines changed

12 files changed

+270
-170
lines changed

.flake8

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[flake8]
2+
application-import-names = pydruid
3+
exclude =
4+
docs
5+
env
6+
tests
7+
.eggs
8+
build
9+
import-order-style = google
10+
max-line-length = 90

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ __pycache__
1111
\#*#
1212
.#*
1313
*~
14+
.tox
15+
env

.travis.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
language: python
22
python:
3-
- "2.6"
43
- "2.7"
5-
- "3.2"
6-
- "3.3"
74
- "3.4"
8-
install: "python setup.py install"
5+
- "3.6"
6+
install:
7+
- pip install flake8
8+
- python setup.py install
9+
before_script: flake8
910
script: py.test

pydruid/async_client.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@
2929

3030
class AsyncPyDruid(BaseDruidClient):
3131
"""
32-
Asynchronous PyDruid client which mirrors functionality of the synchronous PyDruid, but it executes queries
32+
Asynchronous PyDruid client which mirrors functionality of the synchronous
33+
PyDruid, but it executes queries
3334
asynchronously (using an asynchronous http client from Tornado framework).
3435
35-
Returns Query objects that can be used for exporting query results into TSV files or pandas.DataFrame objects
36+
Returns Query objects that can be used for exporting query results into
37+
TSV files or pandas.DataFrame objects
3638
for subsequent analysis.
3739
3840
:param str url: URL of Broker node in the Druid cluster
@@ -83,7 +85,8 @@ class AsyncPyDruid(BaseDruidClient):
8385
8486
>>> print top.result
8587
>>> [{'timestamp': '2013-10-04T00:00:00.000Z',
86-
'result': [{'count': 7.0, 'user_name': 'user_1'}, {'count': 6.0, 'user_name': 'user_2'}]}]
88+
'result': [{'count': 7.0, 'user_name': 'user_1'},
89+
{'count': 6.0, 'user_name': 'user_2'}]}]
8790
8891
>>> df = top.export_pandas()
8992
>>> print df
@@ -100,7 +103,8 @@ def _post(self, query):
100103
http_client = AsyncHTTPClient()
101104
try:
102105
headers, querystr, url = self._prepare_url_headers_and_body(query)
103-
response = yield http_client.fetch(url, method='POST', headers=headers, body=querystr)
106+
response = yield http_client.fetch(
107+
url, method='POST', headers=headers, body=querystr)
104108
except HTTPError as e:
105109
self.__handle_http_error(e, query)
106110
else:

pydruid/client.py

Lines changed: 163 additions & 35 deletions
Large diffs are not rendered by default.

pydruid/query.py

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@
2727

2828
class Query(collections.MutableSequence):
2929
"""
30-
Query objects are produced by PyDruid clients and can be used for exporting query results into TSV files or
31-
pandas.DataFrame objects for subsequent analysis. They also hold information about the issued query.
30+
Query objects are produced by PyDruid clients and can be used for
31+
exporting query results into TSV files or
32+
pandas.DataFrame objects for subsequent analysis. They also hold
33+
information about the issued query.
3234
3335
Query acts as a wrapper over raw result list of dictionaries.
3436
@@ -100,7 +102,8 @@ def export_tsv(self, dest_path):
100102
header.append('timestamp')
101103
header.append('version')
102104
else:
103-
raise NotImplementedError('TSV export not implemented for query type: {0}'.format(self.query_type))
105+
raise NotImplementedError(
106+
'TSV export not implemented for query type: {0}'.format(self.query_type))
104107

105108
w.writerow(header)
106109

@@ -177,7 +180,9 @@ def export_pandas(self):
177180
for item in self.result:
178181
nres += [e.get('event') for e in item['result'].get('events')]
179182
else:
180-
raise NotImplementedError('Pandas export not implemented for query type: {0}'.format(self.query_type))
183+
raise NotImplementedError(
184+
'Pandas export not implemented for query '
185+
'type: {0}'.format(self.query_type))
181186

182187
df = pandas.DataFrame(nres)
183188
return df
@@ -210,18 +215,22 @@ def parse_datasource(datasource, query_type):
210215
"""
211216
Parse an input datasource object into valid dictionary
212217
213-
Input can be a string, in which case it is simply returned, or a list, when it is turned into
214-
a UNION datasource.
218+
Input can be a string, in which case it is simply returned, or a
219+
list, when it is turned into a UNION datasource.
215220
216221
:param datasource: datasource parameter
217222
:param string query_type: query type
218223
:raise ValueError: if input is not string or list of strings
219224
"""
220225
if not (
221226
isinstance(datasource, six.string_types) or
222-
(isinstance(datasource, list) and all([isinstance(x, six.string_types) for x in datasource]))
227+
(
228+
isinstance(datasource, list) and
229+
all([isinstance(x, six.string_types) for x in datasource])
230+
)
223231
):
224-
raise ValueError('Datasource definition not valid. Must be string or list of strings')
232+
raise ValueError(
233+
'Datasource definition not valid. Must be string or list of strings')
225234
if isinstance(datasource, six.string_types):
226235
return datasource
227236
else:
@@ -232,8 +241,9 @@ def validate_query(query_type, valid_parts, args):
232241
"""
233242
Validate the query parts so only allowed objects are sent.
234243
235-
Each query type can have an optional 'context' object attached which is used to set certain
236-
query context settings, etc. timeout or priority. As each query can have this object, there's
244+
Each query type can have an optional 'context' object attached which
245+
is used to set certain query context settings, etc. timeout or
246+
priority. As each query can have this object, there's
237247
no need for it to be sent - it might as well be added here.
238248
239249
:param string query_type: a type of query
@@ -265,7 +275,8 @@ def build_query(self, query_type, args):
265275
if key == 'aggregations':
266276
query_dict[key] = build_aggregators(val)
267277
elif key == 'post_aggregations':
268-
query_dict['postAggregations'] = Postaggregator.build_post_aggregators(val)
278+
query_dict['postAggregations'] = \
279+
Postaggregator.build_post_aggregators(val)
269280
elif key == 'context':
270281
query_dict['context'] = val
271282
elif key == 'datasource':
@@ -290,8 +301,10 @@ def build_query(self, query_type, args):
290301

291302
def topn(self, args):
292303
"""
293-
A TopN query returns a set of the values in a given dimension, sorted by a specified metric. Conceptually, a
294-
topN can be thought of as an approximate GroupByQuery over a single dimension with an Ordering spec. TopNs are
304+
A TopN query returns a set of the values in a given dimension,
305+
sorted by a specified metric. Conceptually, a
306+
topN can be thought of as an approximate GroupByQuery over a
307+
single dimension with an Ordering spec. TopNs are
295308
faster and more resource efficient than GroupBy for this use case.
296309
297310
:param dict args: dict of arguments
@@ -310,7 +323,8 @@ def topn(self, args):
310323

311324
def timeseries(self, args):
312325
"""
313-
A timeseries query returns the values of the requested metrics (in aggregate) for each timestamp.
326+
A timeseries query returns the values of the requested metrics
327+
(in aggregate) for each timestamp.
314328
315329
:param dict args: dict of args
316330
@@ -327,7 +341,8 @@ def timeseries(self, args):
327341

328342
def groupby(self, args):
329343
"""
330-
A group-by query groups a results set (the requested aggregate metrics) by the specified dimension(s).
344+
A group-by query groups a results set (the requested aggregate
345+
metrics) by the specified dimension(s).
331346
332347
:param dict args: dict of args
333348

pydruid/utils/aggregators.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,13 @@
1818
from .filters import Filter
1919

2020

21-
def thetasketch(raw_column, isinputthetasketch = False, size = 16384):
22-
return {"type": "thetaSketch", "fieldName": raw_column, "isInputThetaSketch": isinputthetasketch, "size": size}
21+
def thetasketch(raw_column, isinputthetasketch=False, size=16384):
22+
return {
23+
"type": "thetaSketch",
24+
"fieldName": raw_column,
25+
"isInputThetaSketch": isinputthetasketch,
26+
"size": size,
27+
}
2328

2429

2530
def min(raw_metric):
@@ -79,12 +84,16 @@ def filtered(filter, agg):
7984
"filter": Filter.build_filter(filter),
8085
"aggregator": agg}
8186

87+
8288
def javascript(columns_list, fn_aggregate, fn_combine, fn_reset):
83-
return {"type": "javascript",
84-
"fieldNames": columns_list,
85-
"fnAggregate":fn_aggregate,
86-
"fnCombine":fn_combine,
87-
"fnReset":fn_reset}
89+
return {
90+
"type": "javascript",
91+
"fieldNames": columns_list,
92+
"fnAggregate": fn_aggregate,
93+
"fnCombine": fn_combine,
94+
"fnReset": fn_reset,
95+
}
96+
8897

8998
def build_aggregators(agg_input):
9099
return [_build_aggregator(name, kwargs)

pydruid/utils/filters.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ def __eq__(self, func):
128128

129129
class Bound(Filter):
130130
"""
131-
Bound filter can be used to filter by comparing dimension values to an upper value or/and a lower value.
131+
Bound filter can be used to filter by comparing dimension values to an
132+
upper value or/and a lower value.
132133
133134
:ivar str dimension: Dimension to filter on.
134135
:ivar str lower: Lower bound.
@@ -137,9 +138,11 @@ class Bound(Filter):
137138
:ivar bool upperStrict: Strict upper inclusion. Initial value: False
138139
:ivar bool alphaNumeric: Numeric comparison. Initial value: False
139140
"""
140-
def __init__(self, dimension, lower, upper, lowerStrict=False, upperStrict=False, alphaNumeric=False):
141-
142-
Filter.__init__(self,
141+
def __init__(
142+
self, dimension, lower, upper, lowerStrict=False,
143+
upperStrict=False, alphaNumeric=False):
144+
Filter.__init__(
145+
self,
143146
type='bound', dimension=dimension,
144147
lower=lower, upper=upper,
145148
lowerStrict=lowerStrict, upperStrict=upperStrict,
@@ -148,14 +151,15 @@ def __init__(self, dimension, lower, upper, lowerStrict=False, upperStrict=False
148151

149152
class Interval(Filter):
150153
"""
151-
Interval filter can be used to filter by comparing dimension(__time) values to a list of intervals.
154+
Interval filter can be used to filter by comparing dimension(__time)
155+
values to a list of intervals.
152156
153157
:ivar str dimension: Dimension to filter on.
154158
:ivar list intervals: List of ISO-8601 intervals of data to filter out.
155159
"""
156160
def __init__(self, dimension, intervals):
157161

158-
Filter.__init__(self,
162+
Filter.__init__(
163+
self,
159164
type='interval', dimension=dimension,
160165
intervals=intervals)
161-

pydruid/utils/having.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
class Having:
2323
def __init__(self, **args):
2424

25-
if args['type'] in ('equalTo', 'lessThan','greaterThan'):
25+
if args['type'] in ('equalTo', 'lessThan', 'greaterThan'):
2626
self.having = {'having': {'type': args['type'],
2727
'aggregation': args['aggregation'],
2828
'value': args['value']}}
@@ -50,12 +50,12 @@ def _combine(self, typ, x):
5050
if self.having['having']['type'] == typ:
5151
havingSpecs = self.having['having']['havingSpecs'] + [x.having['having']]
5252
return Having(type=typ, havingSpecs=havingSpecs)
53-
elif x.having['having']['type']==typ:
53+
elif x.having['having']['type'] == typ:
5454
havingSpecs = [self.having['having']] + x.having['having']['havingSpecs']
5555
return Having(type=typ, havingSpecs=havingSpecs)
5656
else:
5757
return Having(type=typ,
58-
havingSpecs=[self.having['having'], x.having['having']])
58+
havingSpecs=[self.having['having'], x.having['having']])
5959

6060
def __and__(self, x):
6161
return self._combine('and', x)

pydruid/utils/postaggregator.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ def __init__(self, fields, output_name=None):
110110

111111
Postaggregator.__init__(self, None, None, name)
112112
self.post_aggregator = {
113-
'type': 'doubleGreatest', 'name': name, 'fields': [f.post_aggregator for f in fields]}
113+
'type': 'doubleGreatest',
114+
'name': name,
115+
'fields': [f.post_aggregator for f in fields]}
114116

115117

116118
class DoubleLeast(Postaggregator):
@@ -123,7 +125,9 @@ def __init__(self, fields, output_name=None):
123125

124126
Postaggregator.__init__(self, None, None, name)
125127
self.post_aggregator = {
126-
'type': 'doubleLeast', 'name': name, 'fields': [f.post_aggregator for f in fields]}
128+
'type': 'doubleLeast',
129+
'name': name,
130+
'fields': [f.post_aggregator for f in fields]}
127131

128132

129133
class LongGreatest(Postaggregator):
@@ -136,7 +140,9 @@ def __init__(self, fields, output_name=None):
136140

137141
Postaggregator.__init__(self, None, None, name)
138142
self.post_aggregator = {
139-
'type': 'longGreatest', 'name': name, 'fields': [f.post_aggregator for f in fields]}
143+
'type': 'longGreatest',
144+
'name': name,
145+
'fields': [f.post_aggregator for f in fields]}
140146

141147

142148
class LongLeast(Postaggregator):
@@ -149,7 +155,9 @@ def __init__(self, fields, output_name=None):
149155

150156
Postaggregator.__init__(self, None, None, name)
151157
self.post_aggregator = {
152-
'type': 'longLeast', 'name': name, 'fields': [f.post_aggregator for f in fields]}
158+
'type': 'longLeast',
159+
'name': name,
160+
'fields': [f.post_aggregator for f in fields]}
153161

154162

155163
class ThetaSketchOp:
@@ -162,15 +170,15 @@ def __init__(self, fn, fields, name):
162170

163171
def __or__(self, other):
164172
return ThetaSketchOp('UNION', self.fields(other),
165-
self.name + '_OR_' + other.name)
173+
self.name + '_OR_' + other.name)
166174

167175
def __and__(self, other):
168176
return ThetaSketchOp('INTERSECT', self.fields(other),
169-
self.name + '_AND_' + other.name)
177+
self.name + '_AND_' + other.name)
170178

171179
def __ne__(self, other):
172180
return ThetaSketchOp('NOT', self.fields(other),
173-
self.name + '_NOT_' + other.name)
181+
self.name + '_NOT_' + other.name)
174182

175183
def fields(self, other):
176184
return [self.post_aggregator, other.post_aggregator]
@@ -194,10 +202,11 @@ def __init__(self, name):
194202

195203
class ThetaSketchEstimate(Postaggregator):
196204
def __init__(self, fields):
205+
field = fields.post_aggregator \
206+
if type(fields) in [ThetaSketch, ThetaSketchOp] else fields
197207
self.post_aggregator = {
198208
'type': 'thetaSketchEstimate',
199209
'name': 'thetasketchestimate',
200-
'field': fields.post_aggregator if type(fields) in [ThetaSketch, ThetaSketchOp] else fields}
210+
'field': field,
211+
}
201212
self.name = 'thetasketchestimate'
202-
203-

0 commit comments

Comments
 (0)