Skip to content

Commit 54a11aa

Browse files
authored
Merge pull request #647 from JulienPalard/avoid_inspect
Avoid relying on inspect to list functions.
2 parents d5cc5f6 + 7b98ff3 commit 54a11aa

File tree

1 file changed

+64
-45
lines changed

1 file changed

+64
-45
lines changed

pycodestyle.py

Lines changed: 64 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,43 @@
141141
COMMENT_WITH_NL = tokenize.generate_tokens(['#\n'].pop).send(None)[1] == '#\n'
142142

143143

144+
_checks = {'physical_line': {}, 'logical_line': {}, 'tree': {}}
145+
146+
147+
def _get_parameters(function):
148+
if sys.version_info >= (3, 3):
149+
return [parameter.name
150+
for parameter
151+
in inspect.signature(function).parameters.values()
152+
if parameter.kind == parameter.POSITIONAL_OR_KEYWORD]
153+
else:
154+
return inspect.getargspec(function)[0]
155+
156+
157+
def register_check(check, codes=None):
158+
"""Register a new check object."""
159+
def _add_check(check, kind, codes, args):
160+
if check in _checks[kind]:
161+
_checks[kind][check][0].extend(codes or [])
162+
else:
163+
_checks[kind][check] = (codes or [''], args)
164+
if inspect.isfunction(check):
165+
args = _get_parameters(check)
166+
if args and args[0] in ('physical_line', 'logical_line'):
167+
if codes is None:
168+
codes = ERRORCODE_REGEX.findall(check.__doc__ or '')
169+
_add_check(check, args[0], codes, args)
170+
elif inspect.isclass(check):
171+
if _get_parameters(check.__init__)[:2] == ['self', 'tree']:
172+
_add_check(check, 'tree', codes, None)
173+
return check
174+
175+
144176
##############################################################################
145177
# Plugins (check functions) for physical lines
146178
##############################################################################
147179

148-
180+
@register_check
149181
def tabs_or_spaces(physical_line, indent_char):
150182
r"""Never mix tabs and spaces.
151183
@@ -165,6 +197,7 @@ def tabs_or_spaces(physical_line, indent_char):
165197
return offset, "E101 indentation contains mixed spaces and tabs"
166198

167199

200+
@register_check
168201
def tabs_obsolete(physical_line):
169202
r"""For new projects, spaces-only are strongly recommended over tabs.
170203
@@ -176,6 +209,7 @@ def tabs_obsolete(physical_line):
176209
return indent.index('\t'), "W191 indentation contains tabs"
177210

178211

212+
@register_check
179213
def trailing_whitespace(physical_line):
180214
r"""Trailing whitespace is superfluous.
181215
@@ -197,6 +231,7 @@ def trailing_whitespace(physical_line):
197231
return 0, "W293 blank line contains whitespace"
198232

199233

234+
@register_check
200235
def trailing_blank_lines(physical_line, lines, line_number, total_lines):
201236
r"""Trailing blank lines are superfluous.
202237
@@ -213,6 +248,7 @@ def trailing_blank_lines(physical_line, lines, line_number, total_lines):
213248
return len(physical_line), "W292 no newline at end of file"
214249

215250

251+
@register_check
216252
def maximum_line_length(physical_line, max_line_length, multiline, noqa):
217253
r"""Limit all lines to a maximum of 79 characters.
218254
@@ -251,6 +287,7 @@ def maximum_line_length(physical_line, max_line_length, multiline, noqa):
251287
##############################################################################
252288

253289

290+
@register_check
254291
def blank_lines(logical_line, blank_lines, indent_level, line_number,
255292
blank_before, previous_logical,
256293
previous_unindented_logical_line, previous_indent_level,
@@ -313,6 +350,7 @@ def blank_lines(logical_line, blank_lines, indent_level, line_number,
313350
"class or function definition, found %d" % blank_before
314351

315352

353+
@register_check
316354
def extraneous_whitespace(logical_line):
317355
r"""Avoid extraneous whitespace.
318356
@@ -345,6 +383,7 @@ def extraneous_whitespace(logical_line):
345383
yield found, "%s whitespace before '%s'" % (code, char)
346384

347385

386+
@register_check
348387
def whitespace_around_keywords(logical_line):
349388
r"""Avoid extraneous whitespace around keywords.
350389
@@ -368,6 +407,7 @@ def whitespace_around_keywords(logical_line):
368407
yield match.start(2), "E271 multiple spaces after keyword"
369408

370409

410+
@register_check
371411
def missing_whitespace_after_import_keyword(logical_line):
372412
r"""Multiple imports in form from x import (a, b, c) should have space
373413
between import statement and parenthesised name list.
@@ -385,6 +425,7 @@ def missing_whitespace_after_import_keyword(logical_line):
385425
yield pos, "E275 missing whitespace after keyword"
386426

387427

428+
@register_check
388429
def missing_whitespace(logical_line):
389430
r"""Each comma, semicolon or colon should be followed by whitespace.
390431
@@ -411,6 +452,7 @@ def missing_whitespace(logical_line):
411452
yield index, "E231 missing whitespace after '%s'" % char
412453

413454

455+
@register_check
414456
def indentation(logical_line, previous_logical, indent_char,
415457
indent_level, previous_indent_level):
416458
r"""Use 4 spaces per indentation level.
@@ -442,6 +484,7 @@ def indentation(logical_line, previous_logical, indent_char,
442484
yield 0, tmpl % (3 + c, "unexpected indentation")
443485

444486

487+
@register_check
445488
def continued_indentation(logical_line, tokens, indent_level, hang_closing,
446489
indent_char, noqa, verbose):
447490
r"""Continuation lines indentation.
@@ -641,6 +684,7 @@ def continued_indentation(logical_line, tokens, indent_level, hang_closing,
641684
yield pos, "%s with same indent as next logical line" % code
642685

643686

687+
@register_check
644688
def whitespace_before_parameters(logical_line, tokens):
645689
r"""Avoid extraneous whitespace.
646690
@@ -673,6 +717,7 @@ def whitespace_before_parameters(logical_line, tokens):
673717
prev_end = end
674718

675719

720+
@register_check
676721
def whitespace_around_operator(logical_line):
677722
r"""Avoid extraneous whitespace around an operator.
678723
@@ -696,6 +741,7 @@ def whitespace_around_operator(logical_line):
696741
yield match.start(2), "E222 multiple spaces after operator"
697742

698743

744+
@register_check
699745
def missing_whitespace_around_operator(logical_line, tokens):
700746
r"""Surround operators with a single space on either side.
701747
@@ -788,6 +834,7 @@ def missing_whitespace_around_operator(logical_line, tokens):
788834
prev_end = end
789835

790836

837+
@register_check
791838
def whitespace_around_comma(logical_line):
792839
r"""Avoid extraneous whitespace after a comma or a colon.
793840
@@ -806,6 +853,7 @@ def whitespace_around_comma(logical_line):
806853
yield found, "E241 multiple spaces after '%s'" % m.group()[0]
807854

808855

856+
@register_check
809857
def whitespace_around_named_parameter_equals(logical_line, tokens):
810858
r"""Don't use spaces around the '=' sign in function arguments.
811859
@@ -856,6 +904,7 @@ def whitespace_around_named_parameter_equals(logical_line, tokens):
856904
prev_end = end
857905

858906

907+
@register_check
859908
def whitespace_before_comment(logical_line, tokens):
860909
r"""Separate inline comments by at least two spaces.
861910
@@ -897,6 +946,7 @@ def whitespace_before_comment(logical_line, tokens):
897946
prev_end = end
898947

899948

949+
@register_check
900950
def imports_on_separate_lines(logical_line):
901951
r"""Place imports on separate lines.
902952
@@ -916,6 +966,7 @@ def imports_on_separate_lines(logical_line):
916966
yield found, "E401 multiple imports on one line"
917967

918968

969+
@register_check
919970
def module_imports_on_top_of_file(
920971
logical_line, indent_level, checker_state, noqa):
921972
r"""Place imports at the top of the file.
@@ -972,6 +1023,7 @@ def is_string_literal(line):
9721023
checker_state['seen_non_imports'] = True
9731024

9741025

1026+
@register_check
9751027
def compound_statements(logical_line):
9761028
r"""Compound statements (on the same line) are generally discouraged.
9771029
@@ -1032,6 +1084,7 @@ def compound_statements(logical_line):
10321084
found = line.find(';', found + 1)
10331085

10341086

1087+
@register_check
10351088
def explicit_line_join(logical_line, tokens):
10361089
r"""Avoid explicit line join between brackets.
10371090
@@ -1071,6 +1124,7 @@ def explicit_line_join(logical_line, tokens):
10711124
parens -= 1
10721125

10731126

1127+
@register_check
10741128
def break_around_binary_operator(logical_line, tokens):
10751129
r"""
10761130
Avoid breaks before binary operators.
@@ -1120,6 +1174,7 @@ def is_binary_operator(token_type, text):
11201174
previous_text = text
11211175

11221176

1177+
@register_check
11231178
def comparison_to_singleton(logical_line, noqa):
11241179
r"""Comparison to singletons should use "is" or "is not".
11251180
@@ -1154,6 +1209,7 @@ def comparison_to_singleton(logical_line, noqa):
11541209
(code, singleton, msg))
11551210

11561211

1212+
@register_check
11571213
def comparison_negative(logical_line):
11581214
r"""Negative comparison should be done using "not in" and "is not".
11591215
@@ -1175,6 +1231,7 @@ def comparison_negative(logical_line):
11751231
yield pos, "E714 test for object identity should be 'is not'"
11761232

11771233

1234+
@register_check
11781235
def comparison_type(logical_line, noqa):
11791236
r"""Object type comparisons should always use isinstance().
11801237
@@ -1198,6 +1255,7 @@ def comparison_type(logical_line, noqa):
11981255
yield match.start(), "E721 do not compare types, use 'isinstance()'"
11991256

12001257

1258+
@register_check
12011259
def bare_except(logical_line, noqa):
12021260
r"""When catching exceptions, mention specific exceptions when possible.
12031261
@@ -1214,6 +1272,7 @@ def bare_except(logical_line, noqa):
12141272
yield match.start(), "E722 do not use bare except'"
12151273

12161274

1275+
@register_check
12171276
def ambiguous_identifier(logical_line, tokens):
12181277
r"""Never use the characters 'l', 'O', or 'I' as variable names.
12191278
@@ -1266,6 +1325,7 @@ def ambiguous_identifier(logical_line, tokens):
12661325
prev_start = start
12671326

12681327

1328+
@register_check
12691329
def python_3000_has_key(logical_line, noqa):
12701330
r"""The {}.has_key() method is removed in Python 3: use the 'in' operator.
12711331
@@ -1277,6 +1337,7 @@ def python_3000_has_key(logical_line, noqa):
12771337
yield pos, "W601 .has_key() is deprecated, use 'in'"
12781338

12791339

1340+
@register_check
12801341
def python_3000_raise_comma(logical_line):
12811342
r"""When raising an exception, use "raise ValueError('message')".
12821343
@@ -1290,6 +1351,7 @@ def python_3000_raise_comma(logical_line):
12901351
yield match.end() - 1, "W602 deprecated form of raising exception"
12911352

12921353

1354+
@register_check
12931355
def python_3000_not_equal(logical_line):
12941356
r"""New code should always use != instead of <>.
12951357
@@ -1303,6 +1365,7 @@ def python_3000_not_equal(logical_line):
13031365
yield pos, "W603 '<>' is deprecated, use '!='"
13041366

13051367

1368+
@register_check
13061369
def python_3000_backticks(logical_line):
13071370
r"""Use repr() instead of backticks in Python 3.
13081371
@@ -1471,50 +1534,6 @@ def _is_eol_token(token, _eol_token=_is_eol_token):
14711534
##############################################################################
14721535

14731536

1474-
_checks = {'physical_line': {}, 'logical_line': {}, 'tree': {}}
1475-
1476-
1477-
def _get_parameters(function):
1478-
if sys.version_info >= (3, 3):
1479-
return [parameter.name
1480-
for parameter
1481-
in inspect.signature(function).parameters.values()
1482-
if parameter.kind == parameter.POSITIONAL_OR_KEYWORD]
1483-
else:
1484-
return inspect.getargspec(function)[0]
1485-
1486-
1487-
def register_check(check, codes=None):
1488-
"""Register a new check object."""
1489-
def _add_check(check, kind, codes, args):
1490-
if check in _checks[kind]:
1491-
_checks[kind][check][0].extend(codes or [])
1492-
else:
1493-
_checks[kind][check] = (codes or [''], args)
1494-
if inspect.isfunction(check):
1495-
args = _get_parameters(check)
1496-
if args and args[0] in ('physical_line', 'logical_line'):
1497-
if codes is None:
1498-
codes = ERRORCODE_REGEX.findall(check.__doc__ or '')
1499-
_add_check(check, args[0], codes, args)
1500-
elif inspect.isclass(check):
1501-
if _get_parameters(check.__init__)[:2] == ['self', 'tree']:
1502-
_add_check(check, 'tree', codes, None)
1503-
1504-
1505-
def init_checks_registry():
1506-
"""Register all globally visible functions.
1507-
1508-
The first argument name is either 'physical_line' or 'logical_line'.
1509-
"""
1510-
mod = inspect.getmodule(register_check)
1511-
for (name, function) in inspect.getmembers(mod, inspect.isfunction):
1512-
register_check(function)
1513-
1514-
1515-
init_checks_registry()
1516-
1517-
15181537
class Checker(object):
15191538
"""Load a Python source file, tokenize it, check coding style."""
15201539

0 commit comments

Comments
 (0)