Skip to content

Commit 410ad37

Browse files
mroeschkejreback
authored andcommitted
CLN: Lint for lists instead of generators in built-in Python functions (#18335)
1 parent f1b1158 commit 410ad37

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+169
-159
lines changed

asv_bench/benchmarks/frame_ctor.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def setup(self, offset, n_steps):
132132
offset = getattr(offsets, offset)
133133
self.idx = get_index_for_offset(offset(n_steps, **kwargs))
134134
self.df = DataFrame(np.random.randn(len(self.idx), 10), index=self.idx)
135-
self.d = dict([(col, self.df[col]) for col in self.df.columns])
135+
self.d = dict(self.df.items())
136136

137137
def time_frame_ctor(self, offset, n_steps):
138138
DataFrame(self.d)

asv_bench/benchmarks/io_bench.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ class read_json_lines(object):
202202
def setup(self):
203203
self.N = 100000
204204
self.C = 5
205-
self.df = DataFrame(dict([('float{0}'.format(i), randn(self.N)) for i in range(self.C)]))
205+
self.df = DataFrame({('float{0}'.format(i), randn(self.N)) for i in range(self.C)})
206206
self.df.to_json(self.fname,orient="records",lines=True)
207207

208208
def teardown(self):

asv_bench/benchmarks/packers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def _setup(self):
1717
self.N = 100000
1818
self.C = 5
1919
self.index = date_range('20000101', periods=self.N, freq='H')
20-
self.df = DataFrame(dict([('float{0}'.format(i), randn(self.N)) for i in range(self.C)]), index=self.index)
20+
self.df = DataFrame(dict(('float{0}'.format(i), randn(self.N)) for i in range(self.C)), index=self.index)
2121
self.df2 = self.df.copy()
2222
self.df2['object'] = [('%08x' % randrange((16 ** 8))) for _ in range(self.N)]
2323
self.remove(self.f)

asv_bench/vbench_to_asv.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def visit_ClassDef(self, node):
6969
return node
7070

7171
def visit_TryExcept(self, node):
72-
if any([isinstance(x, (ast.Import, ast.ImportFrom)) for x in node.body]):
72+
if any(isinstance(x, (ast.Import, ast.ImportFrom)) for x in node.body):
7373
self.imports.append(node)
7474
else:
7575
self.generic_visit(node)

ci/lint.sh

+13
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ if [ "$LINT" ]; then
8484
fi
8585
echo "Check for invalid testing DONE"
8686

87+
echo "Check for use of lists instead of generators in built-in Python functions"
88+
89+
# Example: Avoid `any([i for i in some_iterator])` in favor of `any(i for i in some_iterator)`
90+
#
91+
# Check the following functions:
92+
# any(), all(), sum(), max(), min(), list(), dict(), set(), frozenset(), tuple(), str.join()
93+
grep -R --include="*.py*" -E "[^_](any|all|sum|max|min|list|dict|set|frozenset|tuple|join)\(\[.* for .* in .*\]\)"
94+
95+
if [ $? = "0" ]; then
96+
RET=1
97+
fi
98+
echo "Check for use of lists instead of generators in built-in Python functions DONE"
99+
87100
else
88101
echo "NOT Linting"
89102
fi

doc/source/conf.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
# JP: added from sphinxdocs
7979
autosummary_generate = False
8080

81-
if any([re.match("\s*api\s*", l) for l in index_rst_lines]):
81+
if any(re.match("\s*api\s*", l) for l in index_rst_lines):
8282
autosummary_generate = True
8383

8484
files_to_delete = []
@@ -89,7 +89,7 @@
8989

9090
_file_basename = os.path.splitext(f)[0]
9191
_regex_to_match = "\s*{}\s*$".format(_file_basename)
92-
if not any([re.match(_regex_to_match, line) for line in index_rst_lines]):
92+
if not any(re.match(_regex_to_match, line) for line in index_rst_lines):
9393
files_to_delete.append(f)
9494

9595
if files_to_delete:

doc/sphinxext/ipython_sphinxext/ipython_directive.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ def process_output(self, data, output_prompt,
522522
source = self.directive.state.document.current_source
523523
content = self.directive.content
524524
# Add tabs and join into a single string.
525-
content = '\n'.join([TAB + line for line in content])
525+
content = '\n'.join(TAB + line for line in content)
526526

527527
# Make sure the output contains the output prompt.
528528
ind = found.find(output_prompt)

doc/sphinxext/numpydoc/compiler_unparse.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ def _Return(self, t):
399399
self._fill("return ")
400400
if t.value:
401401
if isinstance(t.value, Tuple):
402-
text = ', '.join([ name.name for name in t.value.asList() ])
402+
text = ', '.join(name.name for name in t.value.asList())
403403
self._write(text)
404404
else:
405405
self._dispatch(t.value)

doc/sphinxext/numpydoc/docscrape.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ def _parse_summary(self):
270270
# If several signatures present, take the last one
271271
while True:
272272
summary = self._doc.read_to_next_empty_line()
273-
summary_str = " ".join([s.strip() for s in summary]).strip()
273+
summary_str = " ".join(s.strip() for s in summary).strip()
274274
if re.compile('^([\w., ]+=)?\s*[\w\.]+\(.*\)$').match(summary_str):
275275
self['Signature'] = summary_str
276276
if not self._is_at_section():
@@ -289,7 +289,7 @@ def _parse(self):
289289

290290
for (section,content) in self._read_sections():
291291
if not section.startswith('..'):
292-
section = ' '.join([s.capitalize() for s in section.split(' ')])
292+
section = ' '.join(s.capitalize() for s in section.split(' '))
293293
if section in ('Parameters', 'Returns', 'Raises', 'Warns',
294294
'Other Parameters', 'Attributes', 'Methods'):
295295
self[section] = self._parse_param_list(content)

doc/sphinxext/numpydoc/docscrape_sphinx.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def _str_member_list(self, name):
130130
out += [''] + autosum
131131

132132
if others:
133-
maxlen_0 = max(3, max([len(x[0]) for x in others]))
133+
maxlen_0 = max(3, max(len(x[0]) for x in others))
134134
hdr = sixu("=")*maxlen_0 + sixu(" ") + sixu("=")*10
135135
fmt = sixu('%%%ds %%s ') % (maxlen_0,)
136136
out += ['', hdr]
@@ -203,7 +203,7 @@ def _str_references(self):
203203
m = re.match(r'.. \[([a-z0-9._-]+)\]', line, re.I)
204204
if m:
205205
items.append(m.group(1))
206-
out += [' ' + ", ".join(["[%s]_" % item for item in items]), '']
206+
out += [' ' + ", ".join("[%s]_" % item for item in items), '']
207207
return out
208208

209209
def _str_examples(self):

doc/sphinxext/numpydoc/phantom_import.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def import_phantom_module(xml_file):
6060
# Sort items so that
6161
# - Base classes come before classes inherited from them
6262
# - Modules come before their contents
63-
all_nodes = dict([(n.attrib['id'], n) for n in root])
63+
all_nodes = dict((n.attrib['id'], n) for n in root)
6464

6565
def _get_bases(node, recurse=False):
6666
bases = [x.attrib['ref'] for x in node.findall('base')]

pandas/_libs/parsers.pyx

+2-2
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,7 @@ cdef class TextReader:
770770
msg = self.orig_header
771771
if isinstance(msg, list):
772772
msg = "[%s], len of %d," % (
773-
','.join([ str(m) for m in msg ]), len(msg))
773+
','.join(str(m) for m in msg), len(msg))
774774
raise ParserError(
775775
'Passed header=%s but only %d lines in file'
776776
% (msg, self.parser.lines))
@@ -2227,7 +2227,7 @@ def _concatenate_chunks(list chunks):
22272227
for name in names:
22282228
arrs = [chunk.pop(name) for chunk in chunks]
22292229
# Check each arr for consistent types.
2230-
dtypes = set([a.dtype for a in arrs])
2230+
dtypes = set(a.dtype for a in arrs)
22312231
if len(dtypes) > 1:
22322232
common_type = np.find_common_type(dtypes, [])
22332233
if common_type == np.object:

pandas/_libs/src/inference.pyx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1309,7 +1309,7 @@ def maybe_convert_objects(ndarray[object] objects, bint try_float=0,
13091309

13101310
# we try to coerce datetime w/tz but must all have the same tz
13111311
if seen.datetimetz_:
1312-
if len(set([getattr(val, 'tzinfo', None) for val in objects])) == 1:
1312+
if len({getattr(val, 'tzinfo', None) for val in objects}) == 1:
13131313
from pandas import DatetimeIndex
13141314
return DatetimeIndex(objects)
13151315
seen.object_ = 1

pandas/_libs/tslibs/resolution.pyx

+2-3
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ class Resolution(object):
218218
'U': 'N',
219219
'N': None}
220220

221-
_str_reso_map = dict([(v, k) for k, v in _reso_str_map.items()])
221+
_str_reso_map = {v: k for k, v in _reso_str_map.items()}
222222

223223
_reso_freq_map = {
224224
'year': 'A',
@@ -232,8 +232,7 @@ class Resolution(object):
232232
'microsecond': 'U',
233233
'nanosecond': 'N'}
234234

235-
_freq_reso_map = dict([(v, k)
236-
for k, v in _reso_freq_map.items()])
235+
_freq_reso_map = {v: k for k, v in _reso_freq_map.items()}
237236

238237
@classmethod
239238
def get_str(cls, reso):

pandas/_libs/tslibs/strptime.pyx

+1-1
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ class TimeRE(dict):
568568
break
569569
else:
570570
return ''
571-
regex = '|'.join([re.escape(stuff) for stuff in to_convert])
571+
regex = '|'.join(re.escape(stuff) for stuff in to_convert)
572572
regex = '(?P<%s>%s' % (directive, regex)
573573
return '%s)' % regex
574574

pandas/_version.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,11 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
141141
if verbose:
142142
print("keywords are unexpanded, not using")
143143
raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
144-
refs = set([r.strip() for r in refnames.strip("()").split(",")])
144+
refs = set(r.strip() for r in refnames.strip("()").split(","))
145145
# starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
146146
# just "foo-1.0". If we see a "tag: " prefix, prefer those.
147147
TAG = "tag: "
148-
tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
148+
tags = set(r[len(TAG):] for r in refs if r.startswith(TAG))
149149
if not tags:
150150
# Either we're using git < 1.8.3, or there really are no tags. We use
151151
# a heuristic: assume all version tags have a digit. The old git %d
@@ -154,7 +154,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
154154
# between branches and tags. By ignoring refnames without digits, we
155155
# filter out many common branch names like "release" and
156156
# "stabilization", as well as "HEAD" and "master".
157-
tags = set([r for r in refs if re.search(r'\d', r)])
157+
tags = set(r for r in refs if re.search(r'\d', r))
158158
if verbose:
159159
print("discarding '{}', no digits".format(",".join(refs - tags)))
160160
if verbose:

pandas/core/common.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ def map_indices_py(arr):
347347
Returns a dictionary with (element, index) pairs for each element in the
348348
given array/list
349349
"""
350-
return dict([(x, i) for i, x in enumerate(arr)])
350+
return dict((x, i) for i, x in enumerate(arr))
351351

352352

353353
def union(*seqs):

pandas/core/dtypes/concat.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ def _concat_datetimetz(to_concat, name=None):
459459
it is used in DatetimeIndex.append also
460460
"""
461461
# do not pass tz to set because tzlocal cannot be hashed
462-
if len(set([str(x.dtype) for x in to_concat])) != 1:
462+
if len(set(str(x.dtype) for x in to_concat)) != 1:
463463
raise ValueError('to_concat must have the same tz')
464464
tz = to_concat[0].tz
465465
# no need to localize because internal repr will not be changed

pandas/core/frame.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -3895,7 +3895,7 @@ def f(col):
38953895
return self._constructor_sliced(r, index=new_index,
38963896
dtype=r.dtype)
38973897

3898-
result = dict([(col, f(col)) for col in this])
3898+
result = dict((col, f(col)) for col in this)
38993899

39003900
# non-unique
39013901
else:
@@ -3906,9 +3906,7 @@ def f(i):
39063906
return self._constructor_sliced(r, index=new_index,
39073907
dtype=r.dtype)
39083908

3909-
result = dict([
3910-
(i, f(i)) for i, col in enumerate(this.columns)
3911-
])
3909+
result = dict((i, f(i)) for i, col in enumerate(this.columns))
39123910
result = self._constructor(result, index=new_index, copy=False)
39133911
result.columns = new_columns
39143912
return result
@@ -3986,7 +3984,7 @@ def _compare_frame_evaluate(self, other, func, str_rep, try_cast=True):
39863984
if self.columns.is_unique:
39873985

39883986
def _compare(a, b):
3989-
return dict([(col, func(a[col], b[col])) for col in a.columns])
3987+
return dict((col, func(a[col], b[col])) for col in a.columns)
39903988

39913989
new_data = expressions.evaluate(_compare, str_rep, self, other)
39923990
return self._constructor(data=new_data, index=self.index,
@@ -3995,8 +3993,8 @@ def _compare(a, b):
39953993
else:
39963994

39973995
def _compare(a, b):
3998-
return dict([(i, func(a.iloc[:, i], b.iloc[:, i]))
3999-
for i, col in enumerate(a.columns)])
3996+
return dict((i, func(a.iloc[:, i], b.iloc[:, i]))
3997+
for i, col in enumerate(a.columns))
40003998

40013999
new_data = expressions.evaluate(_compare, str_rep, self, other)
40024000
result = self._constructor(data=new_data, index=self.index,

pandas/core/generic.py

+13-13
Original file line numberDiff line numberDiff line change
@@ -279,21 +279,21 @@ def set_axis(a, i):
279279

280280
def _construct_axes_dict(self, axes=None, **kwargs):
281281
"""Return an axes dictionary for myself."""
282-
d = dict([(a, self._get_axis(a)) for a in (axes or self._AXIS_ORDERS)])
282+
d = dict((a, self._get_axis(a)) for a in (axes or self._AXIS_ORDERS))
283283
d.update(kwargs)
284284
return d
285285

286286
@staticmethod
287287
def _construct_axes_dict_from(self, axes, **kwargs):
288288
"""Return an axes dictionary for the passed axes."""
289-
d = dict([(a, ax) for a, ax in zip(self._AXIS_ORDERS, axes)])
289+
d = dict((a, ax) for a, ax in zip(self._AXIS_ORDERS, axes))
290290
d.update(kwargs)
291291
return d
292292

293293
def _construct_axes_dict_for_slice(self, axes=None, **kwargs):
294294
"""Return an axes dictionary for myself."""
295-
d = dict([(self._AXIS_SLICEMAP[a], self._get_axis(a))
296-
for a in (axes or self._AXIS_ORDERS)])
295+
d = dict((self._AXIS_SLICEMAP[a], self._get_axis(a))
296+
for a in (axes or self._AXIS_ORDERS))
297297
d.update(kwargs)
298298
return d
299299

@@ -329,7 +329,7 @@ def _construct_axes_from_arguments(self, args, kwargs, require_all=False):
329329
raise TypeError("not enough/duplicate arguments "
330330
"specified!")
331331

332-
axes = dict([(a, kwargs.pop(a, None)) for a in self._AXIS_ORDERS])
332+
axes = dict((a, kwargs.pop(a, None)) for a in self._AXIS_ORDERS)
333333
return axes, kwargs
334334

335335
@classmethod
@@ -586,10 +586,10 @@ def transpose(self, *args, **kwargs):
586586
# construct the args
587587
axes, kwargs = self._construct_axes_from_arguments(args, kwargs,
588588
require_all=True)
589-
axes_names = tuple([self._get_axis_name(axes[a])
590-
for a in self._AXIS_ORDERS])
591-
axes_numbers = tuple([self._get_axis_number(axes[a])
592-
for a in self._AXIS_ORDERS])
589+
axes_names = tuple(self._get_axis_name(axes[a])
590+
for a in self._AXIS_ORDERS)
591+
axes_numbers = tuple(self._get_axis_number(axes[a])
592+
for a in self._AXIS_ORDERS)
593593

594594
# we must have unique axes
595595
if len(axes) != len(set(axes)):
@@ -699,8 +699,8 @@ def squeeze(self, axis=None):
699699
(self._get_axis_number(axis),))
700700
try:
701701
return self.iloc[
702-
tuple([0 if i in axis and len(a) == 1 else slice(None)
703-
for i, a in enumerate(self.axes)])]
702+
tuple(0 if i in axis and len(a) == 1 else slice(None)
703+
for i, a in enumerate(self.axes))]
704704
except Exception:
705705
return self
706706

@@ -4277,8 +4277,8 @@ def fillna(self, value=None, method=None, axis=None, inplace=False,
42774277
elif self.ndim == 3:
42784278

42794279
# fill in 2d chunks
4280-
result = dict([(col, s.fillna(method=method, value=value))
4281-
for col, s in self.iteritems()])
4280+
result = dict((col, s.fillna(method=method, value=value))
4281+
for col, s in self.iteritems())
42824282
new_obj = self._constructor.\
42834283
from_dict(result).__finalize__(self)
42844284
new_data = new_obj._data

pandas/core/groupby.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ def get_converter(s):
471471
raise ValueError(msg)
472472

473473
converters = [get_converter(s) for s in index_sample]
474-
names = [tuple([f(n) for f, n in zip(converters, name)])
474+
names = [tuple(f(n) for f, n in zip(converters, name))
475475
for name in names]
476476

477477
else:

pandas/core/indexes/api.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def conv(i):
101101

102102

103103
def _sanitize_and_check(indexes):
104-
kinds = list(set([type(index) for index in indexes]))
104+
kinds = list({type(index) for index in indexes})
105105

106106
if list in kinds:
107107
if len(kinds) > 1:
@@ -122,8 +122,8 @@ def _get_consensus_names(indexes):
122122

123123
# find the non-none names, need to tupleify to make
124124
# the set hashable, then reverse on return
125-
consensus_names = set([tuple(i.names) for i in indexes
126-
if com._any_not_none(*i.names)])
125+
consensus_names = set(tuple(i.names) for i in indexes
126+
if com._any_not_none(*i.names))
127127
if len(consensus_names) == 1:
128128
return list(list(consensus_names)[0])
129129
return [None] * indexes[0].nlevels

0 commit comments

Comments
 (0)