Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

update pep8 contrib, and fix all the last warning from "make style".

  • Loading branch information...
commit 5d50999c6739a5b528acd9b68fb93c6e34aeec97 1 parent 8aeab85
@tito tito authored
Showing with 1,730 additions and 719 deletions.
  1. +2 −4 kivy/__init__.py
  2. +2 −2 kivy/atlas.py
  3. +1 −1  kivy/config.py
  4. +4 −2 kivy/core/audio/audio_gstreamer.py
  5. +5 −5 kivy/core/image/__init__.py
  6. +18 −18 kivy/core/image/img_gif.py
  7. +3 −3 kivy/core/spelling/__init__.py
  8. +2 −3 kivy/core/text/__init__.py
  9. +1 −2  kivy/core/text/markup.py
  10. +1 −1  kivy/core/text/text_pygame.py
  11. +3 −3 kivy/core/video/video_gstreamer.py
  12. +2 −2 kivy/core/video/video_pyglet.py
  13. +1 −1  kivy/core/window/window_pygame.py
  14. +3 −3 kivy/ext/__init__.py
  15. +14 −13 kivy/geometry.py
  16. +1 −1  kivy/graphics/__init__.py
  17. +1 −1  kivy/input/postproc/dejitter.py
  18. +1 −1  kivy/input/postproc/ignorelist.py
  19. +14 −15 kivy/input/providers/hidinput.py
  20. +13 −14 kivy/input/providers/linuxwacom.py
  21. +1 −1  kivy/input/providers/mouse.py
  22. +0 −1  kivy/input/providers/mtdev.py
  23. +3 −4 kivy/input/providers/probesysfs.py
  24. +6 −6 kivy/input/providers/wm_pen.py
  25. +4 −4 kivy/input/providers/wm_touch.py
  26. +1 −1  kivy/interactive.py
  27. +8 −8 kivy/lang.py
  28. +1 −1  kivy/loader.py
  29. +1 −1  kivy/logger.py
  30. +2 −2 kivy/modules/keybinding.py
  31. +2 −2 kivy/modules/recorder.py
  32. +11 −7 kivy/parser.py
  33. +1 −1  kivy/support.py
  34. +1 −1  kivy/tests/test_image.py
  35. +1 −1  kivy/tests/test_issue_609.py
  36. +1 −2  kivy/tools/benchmark.py
  37. +2 −4 kivy/tools/gles_compat/subset_gles.py
  38. +1 −4 kivy/tools/packaging/factory.py
  39. +1,445 −430 kivy/tools/pep8checker/pep8.py
  40. +9 −3 kivy/tools/pep8checker/pep8kivy.py
  41. +1 −2  kivy/tools/report.py
  42. +5 −4 kivy/uix/accordion.py
  43. +9 −9 kivy/uix/anchorlayout.py
  44. +7 −7 kivy/uix/boxlayout.py
  45. +20 −20 kivy/uix/bubble.py
  46. +2 −2 kivy/uix/button.py
  47. +18 −18 kivy/uix/gridlayout.py
  48. +2 −2 kivy/uix/image.py
  49. +14 −12 kivy/uix/label.py
  50. +5 −3 kivy/uix/popup.py
  51. +1 −2  kivy/uix/rst.py
  52. +10 −9 kivy/uix/scatter.py
  53. +1 −1  kivy/uix/screenmanager.py
  54. +2 −3 kivy/uix/scrollview.py
  55. +4 −4 kivy/uix/slider.py
  56. +6 −6 kivy/uix/stacklayout.py
  57. +17 −17 kivy/uix/tabbedpanel.py
  58. +3 −5 kivy/uix/textinput.py
  59. +0 −1  kivy/uix/videoplayer.py
  60. +0 −3  kivy/uix/widget.py
  61. +9 −9 kivy/utils.py
  62. +1 −1  kivy/vector.py
View
6 kivy/__init__.py
@@ -43,7 +43,7 @@
if platform() == 'macosx' and sys.maxint < 9223372036854775807:
- r ='''Unsupported Python version detected!:
+ r = '''Unsupported Python version detected!:
Kivy requires a 64 bit version of Python to run on OS X. We strongly advise
you to use the version of Python that is provided by Apple (don't use ports,
fink or homebrew unless you know what you're doing).
@@ -112,7 +112,7 @@ def parse_version(version):
if tag == 'dev' and systag != 'dev':
Logger.warning('Application requested a -dev version of Kivy. '
'(You have %s, but the application requires %s)' % (
- __version__, version))
+ __version__, version))
# not tag rev (-alpha-1, -beta-x) allowed.
if tagrev is not None:
raise Exception('Revision format must not contain any tagrevision')
@@ -273,7 +273,6 @@ def kivy_usage():
Logger.setLevel(level=level)
Logger.setLevel(level=LOG_LEVELS.get('debug'))
-
# Can be overrided in command line
if 'KIVY_UNITTEST' not in environ:
@@ -298,7 +297,6 @@ def kivy_usage():
opts = []
args = []
-
need_save = False
for opt, arg in opts:
if opt in ('-h', '--help'):
View
4 kivy/atlas.py
@@ -246,7 +246,7 @@ def create(outname, filenames, size, padding=1):
imw += padding
imh += padding
if imw > size or imh > size:
- Logger.error('Atlas: image %s is larger than the atlas size!'%\
+ Logger.error('Atlas: image %s is larger than the atlas size!' %
imageinfo[0])
return
@@ -310,7 +310,7 @@ def create(outname, filenames, size, padding=1):
# as the uniq id.
uid = splitext(basename(fb[6]))[0]
x, y, w, h = fb[2:6]
- d[uid] = x, size-y-h, w, h
+ d[uid] = x, size - y - h, w, h
outfn = '%s.atlas' % outname
with open(outfn, 'w') as fd:
View
2  kivy/config.py
@@ -290,7 +290,7 @@ def write(self):
if version != KIVY_CONFIG_VERSION and 'KIVY_NO_CONFIG' not in environ:
Logger.warning('Config: Older configuration version detected'
' (%d instead of %d)' % (
- version, KIVY_CONFIG_VERSION))
+ version, KIVY_CONFIG_VERSION))
Logger.warning('Config: Upgrading configuration in progress.')
need_save = True
View
6 kivy/core/audio/audio_gstreamer.py
@@ -112,12 +112,14 @@ def _get_length(self):
self._data.set_state(gst.STATE_PLAYING)
try:
self._data.get_state()
- return self._data.query_duration(gst.Format(gst.FORMAT_TIME))[0] / 1000000000.
+ return self._data.query_duration(gst.Format(
+ gst.FORMAT_TIME))[0] / 1000000000.
finally:
self._data.set_state(gst.STATE_NULL)
self._data.set_property('volume', volume_before)
else:
- return self._data.query_duration(gst.Format(gst.FORMAT_TIME))[0] / 1000000000.
+ return self._data.query_duration(gst.Format
+ (gst.FORMAT_TIME))[0] / 1000000000.
return super(SoundGstreamer, self)._get_length()
SoundLoader.register(SoundGstreamer)
View
10 kivy/core/image/__init__.py
@@ -97,10 +97,10 @@ def have_mipmap(self):
return len(self.mipmaps) > 1
def __repr__(self):
- return '<ImageData width=%d height=%d fmt=%s ' \
- 'source=%r with %d images>' % (
- self.width, self.height, self.fmt,
- self.source, len(self.mipmaps))
+ return ('<ImageData width=%d height=%d fmt=%s '
+ 'source=%r with %d images>' % (
+ self.width, self.height, self.fmt,
+ self.source, len(self.mipmaps)))
def add_mipmap(self, level, width, height, data):
'''Add a image for a specific mipmap level.
@@ -662,7 +662,7 @@ def read_pixel(self, x, y):
assert data.fmt in ImageData._supported_fmts
size = 3 if data.fmt in ('rgb', 'bgr') else 4
index = y * data.width * size + x * size
- raw = data.data[index:index+size]
+ raw = data.data[index:index + size]
color = map(lambda c: ord(c) / 255.0, raw)
# conversion for BGR->RGB, BGR->RGBA format
View
36 kivy/core/image/img_gif.py
@@ -65,7 +65,7 @@ def load(self, filename):
ls_height = im.ls_height
im_images = im.images
im_palette = im.palette
- pixel_map = array('B', [0]*(ls_width*ls_height*4))
+ pixel_map = array('B', [0] * (ls_width * ls_height * 4))
for img in im_images:
palette = img.palette if img.local_color_table_flag\
else im_palette
@@ -74,7 +74,7 @@ def load(self, filename):
#draw_method_restore_previous = 1 \
# if img.draw_method == 'restore previous' else 0
draw_method_replace = 1 \
- if ((img.draw_method == 'replace') or\
+ if ((img.draw_method == 'replace') or
(img.draw_method == 'restore background')) else 0
pixels = img.pixels
img_height = img.height
@@ -125,17 +125,17 @@ def load(self, filename):
continue
# this pixel isn't transparent
#doesn't have transparent color
- (pixel_map[rgba_pos], pixel_map[rgba_pos + 1],\
- pixel_map[rgba_pos + 2]) = (r, g, b)
+ (pixel_map[rgba_pos], pixel_map[rgba_pos + 1],
+ pixel_map[rgba_pos + 2]) = (r, g, b)
pixel_map[rgba_pos + 3] = 255
# if magic pink move to next pixel
rgba_pos += 4
i += 1
- img_data_append(ImageData(ls_width, ls_height, \
+ img_data_append(ImageData(ls_width, ls_height,
'rgba', pixel_map.tostring()))
if draw_method_replace:
- pixel_map = array('B', [0]*(ls_width*ls_height*4))
+ pixel_map = array('B', [0] * (ls_width * ls_height * 4))
self.filename = filename
@@ -160,7 +160,7 @@ class Gif(object):
LABEL_COMMENT = 0xFE
LABEL_PLAINTEXT = 0x01
- FMT_EXT_GRAPHIC_CONTROL = '<BBHB' #89a
+ FMT_EXT_GRAPHIC_CONTROL = '<BBHB' # 89a
def __init__(self, data, debug):
self.data = data
@@ -319,7 +319,7 @@ def fill(self):
self.color_table_flag = self.flags[7]
self.sort_flag = self.flags[3]
#3 bit
- self.color_resolution = pack_bits(self.flags[4:7]) # 7 not included
+ self.color_resolution = pack_bits(self.flags[4:7]) # 7 not included
#3 bit
self.global_color_table_size = 2 ** (pack_bits(self.flags[:3]) + 1)
@@ -351,7 +351,7 @@ def fill(self):
try:
nextbyte = self_pops('<B', self_data)[0]
except:
- nextbyte = 0x3b # force end
+ nextbyte = 0x3b # force end
#20. Image Descriptor
if nextbyte == Gif_IMAGE_SEPARATOR:
@@ -383,8 +383,8 @@ def fill(self):
print 'LZW length:', len(image_lzwcode)
image.lzwcode = image_lzwcode
- image.pixels = self_lzw_decode(image.lzwcode, image.codesize, \
- table_size)
+ image.pixels = self_lzw_decode(image.lzwcode, image.codesize,
+ table_size)
# Extensions
elif nextbyte == Gif_EXTENSION_INTRODUCER:
@@ -439,8 +439,8 @@ def bits_to_int(self, bits):
i = 0
for bit in bits:
if bit:
- i+= 2**(c-1)
- c +=1
+ i += 2 ** (c - 1)
+ c += 1
return i
def get_color_table(self, size):
@@ -451,10 +451,10 @@ def get_color_table(self, size):
palette = []
palette_append = palette.append
- while pos + 3 < (size+1):
+ while pos + 3 < (size + 1):
red = raw_color_table[pos]
- green = raw_color_table[pos+1]
- blue = raw_color_table[pos+2]
+ green = raw_color_table[pos + 1]
+ blue = raw_color_table[pos + 2]
palette_append((red, green, blue))
pos += 3
return palette
@@ -476,7 +476,7 @@ def lzw_decode(self, input, initial_codesize, color_table_size):
clearcode, end_of_info = color_table_size, color_table_size + 1
if Debug:
- print 'codesize: %d' %codesize
+ print 'codesize: %d' % codesize
print 'clearcode %d, end_of_info: %d' % (clearcode, end_of_info)
def pop(size, _bits):
@@ -559,7 +559,7 @@ def get_bits(flags, reverse=False, bits=8):
mybits = (1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048)[:bits]
- rev_num=1
+ rev_num = 1
if reverse:
rev_num = -1
ret = array('B')
View
6 kivy/core/spelling/__init__.py
@@ -95,7 +95,7 @@ def list_languages(self):
Return a list of all languages supported by the registered languages.
E.g.: ['en', 'en_GB', 'en_US', 'de', ...]
'''
- raise NotImplementedError('list_languages() is not implemented ' + \
+ raise NotImplementedError('list_languages() is not implemented '
'by abstract spelling base class!')
def check(self, word):
@@ -109,7 +109,7 @@ def check(self, word):
If the word shouldn't be checked, return None (e.g. for '').
'''
- raise NotImplementedError('check() not implemented by abstract ' + \
+ raise NotImplementedError('check() not implemented by abstract ' +
'spelling base class!')
def suggest(self, fragment):
@@ -124,7 +124,7 @@ def suggest(self, fragment):
E.g.: 'foo' might become 'of', 'food' or 'foot'.
'''
- raise NotImplementedError('suggest() not implemented by abstract ' + \
+ raise NotImplementedError('suggest() not implemented by abstract ' +
'spelling base class!')
View
5 kivy/core/text/__init__.py
@@ -147,7 +147,7 @@ def register(name, fn_regular, fn_italic=None, fn_bold=None,
else:
fonts.append(font)
else:
- fonts.append(fonts[-1]) # add regular font to list again
+ fonts.append(fonts[-1]) # add regular font to list again
LabelBase._fonts[name] = tuple(fonts)
@@ -211,7 +211,7 @@ def shorten(self, text, margin=2):
return u'{0}...{1}'.format(text[:segment].strip(),
text[-segment:].strip())
else:
- segment = max_letters - 3 # length of '...'
+ segment = max_letters - 3 # length of '...'
return u'{0}...'.format(text[:segment].strip())
def render(self, real=False):
@@ -273,7 +273,6 @@ def render(self, real=False):
if not glyph in cache:
cache[glyph] = get_extents(glyph)
-
# Shorten the text that we actually display
text = self.text
if options['shorten'] and get_extents(text)[0] > uw:
View
3  kivy/core/text/markup.py
@@ -284,11 +284,10 @@ def _real_render(self):
# vertical alignement
if y == 0:
if av == 1:
- y = int((h - txt_height)/2)
+ y = int((h - txt_height) / 2)
elif av == 2:
y = h - (txt_height)
-
for pw, ph, part, options in line[2]:
self.options = options
r(part, x, y + (lh - ph) / 1.25)
View
2  kivy/core/text/text_pygame.py
@@ -22,7 +22,7 @@
class LabelPygame(LabelBase):
def _get_font_id(self):
- return '|'.join([unicode(self.options[x]) for x \
+ return '|'.join([unicode(self.options[x]) for x
in ('font_size', 'font_name_r', 'bold', 'italic')])
def _get_font(self):
View
6 kivy/core/video/video_gstreamer.py
@@ -52,8 +52,8 @@ def _on_gst_message(bus, message):
# log all error messages
if message.type == gst.MESSAGE_ERROR:
error, debug = map(str, message.parse_error())
- Logger.error('gstreamer_video: %s'%error)
- Logger.debug('gstreamer_video: %s'%debug)
+ Logger.error('gstreamer_video: %s' % error)
+ Logger.debug('gstreamer_video: %s' % debug)
def _on_gst_eos(obj, *largs):
@@ -119,7 +119,7 @@ def unload(self):
self._texture = None
def load(self):
- Logger.debug('gstreamer_video: Load <%s>'% self._filename)
+ Logger.debug('gstreamer_video: Load <%s>' % self._filename)
self._playbin.set_state(gst.STATE_NULL)
self._playbin.set_property('uri', self._get_uri())
self._playbin.set_state(gst.STATE_READY)
View
4 kivy/core/video/video_pyglet.py
@@ -40,7 +40,7 @@ def unload(self):
self._fbo = None
def load(self):
- self.unload() #make sure we unload an resources
+ self.unload() # make sure we unload an resources
#load media file and set size of video
self._source = source = pyglet.media.load(self._filename)
@@ -61,7 +61,7 @@ def load(self):
self.time = self._player.time
def _update(self, dt):
- if self._source.duration - self.time < 0.1: #we are at the end
+ if self._source.duration - self.time < 0.1: # we are at the end
self.seek(0)
if self.state == 'playing':
# keep track of time into video
View
2  kivy/core/window/window_pygame.py
@@ -193,7 +193,7 @@ def on_keyboard(self, key,
is_osx = platform() == 'darwin'
if key == 27 or (is_osx and key in (113, 119) and modifier == 1024):
stopTouchApp()
- self.close() #not sure what to do here
+ self.close() # not sure what to do here
return True
super(WindowPygame, self).on_keyboard(key, scancode,
codepoint=codepoint, modifier=modifier)
View
6 kivy/ext/__init__.py
@@ -238,13 +238,13 @@ def unzip_extensions():
already_unzipped = False
if extdir in files:
- Logger.trace(("Extension '%s' has already been " % extname) + \
+ Logger.trace(("Extension '%s' has already been " % extname) +
"extracted manually, just moving the zip.")
already_unzipped = True
# Filter the namelist of zipfile to take only the members that start
# with the extension name (MyExt/...)
- members = [x for x in zipf.namelist() \
+ members = [x for x in zipf.namelist()
if x.startswith(extname + '/')]
if not already_unzipped:
@@ -270,7 +270,7 @@ def unzip_extensions():
fd.write(zipf.read(member))
except Exception, e:
# Catch any error, e.g. non-writable directory, etc.
- Logger.error("Failed installing extension " + \
+ Logger.error("Failed installing extension " +
"'%s' %s." % (extname, e))
return
finally:
View
27 kivy/geometry.py
@@ -31,12 +31,13 @@ def circumcircle(a, b, c):
Q = Vector(b[0], b[1])
R = Vector(c[0], c[1])
- mPQ = (P+Q)*.5
- mQR = (Q+R)*.5
+ mPQ = (P + Q) * .5
+ mQR = (Q + R) * .5
- numer = -(-mPQ.y*R.y + mPQ.y*Q.y + mQR.y*R.y - mQR.y*Q.y \
- -mPQ.x*R.x + mPQ.x*Q.x + mQR.x*R.x - mQR.x*Q.x)
- denom = (-Q.x*R.y + P.x*R.y - P.x*Q.y + Q.y*R.x - P.y*R.x + P.y*Q.x)
+ numer = -(- mPQ.y * R.y + mPQ.y * Q.y + mQR.y * R.y - mQR.y * Q.y
+ - mPQ.x * R.x + mPQ.x * Q.x + mQR.x * R.x - mQR.x * Q.x)
+ denom = (-Q.x * R.y + P.x * R.y - P.x * Q.y +
+ Q.y * R.x - P.y * R.x + P.y * Q.x)
t = numer / denom
@@ -76,13 +77,13 @@ def minimum_bounding_circle(points):
return (p1 + p2) * .5, ((p1 - p2) * .5).length()
# determine a point P with the smallest y value
- P = min(points, key = lambda p: p.y)
+ P = min(points, key=lambda p: p.y)
# find a point Q such that the angle of the line segment
# PQ with the x axis is minimal
def x_axis_angle(q):
if q == P:
- return 1e10 # max val if teh same, to skip
+ return 1e10 # max val if the same, to skip
return abs((q - P).angle((1, 0)))
Q = min(points, key=x_axis_angle)
@@ -90,29 +91,29 @@ def x_axis_angle(q):
# find R such that angle PRQ is minimal
def angle_pq(r):
if r in (P, Q):
- return 1e10 # max val if teh same, to skip
+ return 1e10 # max val if the same, to skip
return abs((r - P).angle(r - Q))
R = min(points, key=angle_pq)
# check for case 1 (angle PRQ is obtuse), the circle is determined
# by two points, P and Q. radius = |(P-Q)/2|, center = (P+Q)/2
if angle_pq(R) > 90.0:
- return (P+Q)*.5, ((P-Q)*.5).length()
+ return (P + Q) * .5, ((P - Q) * .5).length()
# if angle RPQ is obtuse, make P = R, and try again
- if abs((R-P).angle(Q-P)) > 90:
+ if abs((R - P).angle(Q - P)) > 90:
P = R
continue
# if angle PQR is obtuse, make Q = R, and try again
- if abs((P-Q).angle(R-Q)) > 90:
+ if abs((P - Q).angle(R - Q)) > 90:
Q = R
continue
- # all angles were acute..we just need teh circle through the
+ # all angles were acute..we just need the circle through the
# two points furthest apart!
break
- # find teh circumcenter for triangle given by P,Q,R
+ # find the circumcenter for triangle given by P,Q,R
return circumcircle(P, Q, R)
View
2  kivy/graphics/__init__.py
@@ -75,7 +75,7 @@
from kivy.graphics.instructions import Callback, Canvas, CanvasBase, \
ContextInstruction, Instruction, InstructionGroup, RenderContext, \
- VertexInstruction # pyflakes.ignore
+ VertexInstruction
from kivy.graphics.context_instructions import BindTexture, Color, \
MatrixInstruction, PopMatrix, PushMatrix, Rotate, Scale, \
Translate, gl_init_resources
View
2  kivy/input/postproc/dejitter.py
@@ -43,7 +43,7 @@ def __init__(self):
def taxicab_distance(self, p, q):
# Get the taxicab/manhattan/citiblock distance for efficiency reasons
- return abs(p[0]-q[0]) + abs(p[1]-q[1])
+ return abs(p[0] - q[0]) + abs(p[1] - q[1])
def process(self, events):
if not self.jitterdist:
View
2  kivy/input/postproc/ignorelist.py
@@ -43,5 +43,5 @@ def process(self, events):
continue
if self.collide_ignore(touch):
touch.ud.__pp_ignore__ = True
- return [(etype, touch) for etype, touch in events \
+ return [(etype, touch) for etype, touch in events
if not '__pp_ignore__' in touch.ud]
View
29 kivy/input/providers/hidinput.py
@@ -95,7 +95,7 @@ def __str__(self):
EV_PWR = 0x16
EV_FF_STATUS = 0x17
EV_MAX = 0x1f
- EV_CNT = (EV_MAX+1)
+ EV_CNT = (EV_MAX + 1)
KEY_MAX = 0x2ff
@@ -111,19 +111,19 @@ def __str__(self):
MSC_RAW = 0x03
MSC_SCAN = 0x04
MSC_MAX = 0x07
- MSC_CNT = (MSC_MAX+1)
-
- ABS_MT_TOUCH_MAJOR = 0x30 # Major axis of touching ellipse
- ABS_MT_TOUCH_MINOR = 0x31 # Minor axis (omit if circular)
- ABS_MT_WIDTH_MAJOR = 0x32 # Major axis of approaching ellipse
- ABS_MT_WIDTH_MINOR = 0x33 # Minor axis (omit if circular)
- ABS_MT_ORIENTATION = 0x34 # Ellipse orientation
- ABS_MT_POSITION_X = 0x35 # Center X ellipse position
- ABS_MT_POSITION_Y = 0x36 # Center Y ellipse position
- ABS_MT_TOOL_TYPE = 0x37 # Type of touching device
- ABS_MT_BLOB_ID = 0x38 # Group a set of packets as a blob
- ABS_MT_TRACKING_ID = 0x39 # Unique ID of initiated contact
- ABS_MT_PRESSURE = 0x3a # Pressure on contact area
+ MSC_CNT = (MSC_MAX + 1)
+
+ ABS_MT_TOUCH_MAJOR = 0x30 # Major axis of touching ellipse
+ ABS_MT_TOUCH_MINOR = 0x31 # Minor axis (omit if circular)
+ ABS_MT_WIDTH_MAJOR = 0x32 # Major axis of approaching ellipse
+ ABS_MT_WIDTH_MINOR = 0x33 # Minor axis (omit if circular)
+ ABS_MT_ORIENTATION = 0x34 # Ellipse orientation
+ ABS_MT_POSITION_X = 0x35 # Center X ellipse position
+ ABS_MT_POSITION_Y = 0x36 # Center Y ellipse position
+ ABS_MT_TOOL_TYPE = 0x37 # Type of touching device
+ ABS_MT_BLOB_ID = 0x38 # Group a set of packets as a blob
+ ABS_MT_TRACKING_ID = 0x39 # Unique ID of initiated contact
+ ABS_MT_PRESSURE = 0x3a # Pressure on contact area
# some ioctl base (with 0 value)
EVIOCGNAME = 2147501318
@@ -366,5 +366,4 @@ def update(self, dispatch_fn):
except:
pass
-
MotionEventFactory.register('hidinput', HIDInputMotionEventProvider)
View
27 kivy/input/providers/linuxwacom.py
@@ -84,7 +84,7 @@ def __str__(self):
EV_PWR = 0x16
EV_FF_STATUS = 0x17
EV_MAX = 0x1f
- EV_CNT = (EV_MAX+1)
+ EV_CNT = (EV_MAX + 1)
KEY_MAX = 0x2ff
@@ -100,23 +100,23 @@ def __str__(self):
MSC_RAW = 0x03
MSC_SCAN = 0x04
MSC_MAX = 0x07
- MSC_CNT = (MSC_MAX+1)
+ MSC_CNT = (MSC_MAX + 1)
ABS_X = 0x00
ABS_Y = 0x01
ABS_PRESSURE = 0x18
ABS_MISC = 0x28 # if 0, it's touch up
- ABS_MT_TOUCH_MAJOR = 0x30 # Major axis of touching ellipse
- ABS_MT_TOUCH_MINOR = 0x31 # Minor axis (omit if circular)
- ABS_MT_WIDTH_MAJOR = 0x32 # Major axis of approaching ellipse
- ABS_MT_WIDTH_MINOR = 0x33 # Minor axis (omit if circular)
- ABS_MT_ORIENTATION = 0x34 # Ellipse orientation
- ABS_MT_POSITION_X = 0x35 # Center X ellipse position
- ABS_MT_POSITION_Y = 0x36 # Center Y ellipse position
- ABS_MT_TOOL_TYPE = 0x37 # Type of touching device
- ABS_MT_BLOB_ID = 0x38 # Group a set of packets as a blob
- ABS_MT_TRACKING_ID = 0x39 # Unique ID of initiated contact
- ABS_MT_PRESSURE = 0x3a # Pressure on contact area
+ ABS_MT_TOUCH_MAJOR = 0x30 # Major axis of touching ellipse
+ ABS_MT_TOUCH_MINOR = 0x31 # Minor axis (omit if circular)
+ ABS_MT_WIDTH_MAJOR = 0x32 # Major axis of approaching ellipse
+ ABS_MT_WIDTH_MINOR = 0x33 # Minor axis (omit if circular)
+ ABS_MT_ORIENTATION = 0x34 # Ellipse orientation
+ ABS_MT_POSITION_X = 0x35 # Center X ellipse position
+ ABS_MT_POSITION_Y = 0x36 # Center Y ellipse position
+ ABS_MT_TOOL_TYPE = 0x37 # Type of touching device
+ ABS_MT_BLOB_ID = 0x38 # Group a set of packets as a blob
+ ABS_MT_TRACKING_ID = 0x39 # Unique ID of initiated contact
+ ABS_MT_PRESSURE = 0x3a # Pressure on contact area
# some ioctl base (with 0 value)
EVIOCGNAME = 2147501318
@@ -385,5 +385,4 @@ def update(self, dispatch_fn):
except:
pass
-
MotionEventFactory.register('linuxwacom', LinuxWacomMotionEventProvider)
View
2  kivy/input/providers/mouse.py
@@ -141,7 +141,7 @@ def test_activity(self):
def find_touch(self, x, y):
factor = 10. / EventLoop.window.system_size[0]
for t in self.touches.itervalues():
- if abs(x-t.sx) < factor and abs(y-t.sy) < factor:
+ if abs(x - t.sx) < factor and abs(y - t.sy) < factor:
return t
return False
View
1  kivy/input/providers/mtdev.py
@@ -295,5 +295,4 @@ def update(self, dispatch_fn):
except:
pass
-
MotionEventFactory.register('mtdev', MTDMotionEventProvider)
View
7 kivy/input/providers/probesysfs.py
@@ -80,7 +80,7 @@ def get_capabilities(self):
long_bit = getconf("LONG_BIT")
for i, word in enumerate(line.split(" ")):
word = int(word, 16)
- subcapabilities = [bool(word & 1<<i) for i in range(long_bit)]
+ subcapabilities = [bool(word & 1 << i) for i in range(long_bit)]
capabilities[:0] = subcapabilities
return capabilities
@@ -155,11 +155,11 @@ def __init__(self, device, args):
def probe(self):
inputs = get_inputs(self.input_path)
if not self.select_all:
- inputs = [x for x in inputs if \
+ inputs = [x for x in inputs if
x.has_capability(ABS_MT_POSITION_X)]
for device in inputs:
Logger.debug('ProbeSysfs: found device: %s at %s' % (
- device.name, device.device))
+ device.name, device.device))
# must ignore ?
if self.match:
@@ -194,5 +194,4 @@ def probe(self):
from kivy.base import EventLoop
EventLoop.add_input_provider(instance)
-
MotionEventFactory.register('probesysfs', ProbeSysfsHardwareProbe)
View
12 kivy/input/providers/wm_pen.py
@@ -42,15 +42,15 @@ def __str__(self):
class RECT(Structure):
_fields_ = [
- ('left', ULONG),
- ('top', ULONG),
- ('right', ULONG),
- ('bottom', ULONG)]
+ ('left', ULONG),
+ ('top', ULONG),
+ ('right', ULONG),
+ ('bottom', ULONG)]
x = property(lambda self: self.left)
y = property(lambda self: self.top)
- w = property(lambda self: self.right-self.left)
- h = property(lambda self: self.bottom-self.top)
+ w = property(lambda self: self.right - self.left)
+ h = property(lambda self: self.bottom - self.top)
win_rect = RECT()
windll.user32.SetWindowLongPtrW.restype = WNDPROC
View
8 kivy/input/providers/wm_touch.py
@@ -96,8 +96,8 @@ class RECT(Structure):
x = property(lambda self: self.left)
y = property(lambda self: self.top)
- w = property(lambda self: self.right-self.left)
- h = property(lambda self: self.bottom-self.top)
+ w = property(lambda self: self.right - self.left)
+ h = property(lambda self: self.bottom - self.top)
windll.user32.SetWindowLongPtrW.restype = WNDPROC
windll.user32.SetWindowLongPtrW.argtypes = [HANDLE, c_int, WNDPROC]
@@ -150,8 +150,8 @@ def update(self, dispatch_fn):
break
# adjust x,y to window coordinates (0.0 to 1.0)
- x = (t.screen_x()-win_rect.x)/float(win_rect.w)
- y = 1.0 - (t.screen_y()-win_rect.y)/float(win_rect.h)
+ x = (t.screen_x() - win_rect.x) / float(win_rect.w)
+ y = 1.0 - (t.screen_y() - win_rect.y) / float(win_rect.h)
# actually dispatch input
if t.event_type == 'begin':
View
2  kivy/interactive.py
@@ -210,7 +210,7 @@ def __call__(self, *args, **kw):
return SafeMembrane(r)
def __getattribute__(self, attr, oga=object.__getattribute__):
- if attr.startswith('__') or attr =='_ref':
+ if attr.startswith('__') or attr == '_ref':
subject = oga(self, '_ref')
if attr == '_ref':
return subject
View
16 kivy/lang.py
@@ -488,12 +488,12 @@ def __init__(self, context, line, message):
sc = ['...']
sc += [' %4d:%s' % x for x in sourcecode[sc_start:line]]
sc += ['>> %4d:%s' % (line, sourcecode[line][1])]
- sc += [' %4d:%s' % x for x in sourcecode[line+1:sc_stop]]
+ sc += [' %4d:%s' % x for x in sourcecode[line + 1:sc_stop]]
sc += ['...']
sc = '\n'.join(sc)
message = 'Parser: File "%s", line %d:\n%s\n%s' % (
- self.filename, self.line+1, sc, message)
+ self.filename, self.line + 1, sc, message)
super(ParserException, self).__init__(message)
@@ -507,7 +507,7 @@ class ParserRuleProperty(object):
'''Represent a property inside a rule
'''
- __slots__ = ('ctx', 'line', 'name', 'value', 'co_value', \
+ __slots__ = ('ctx', 'line', 'name', 'value', 'co_value',
'watched_keys', 'mode')
def __init__(self, ctx, line, name, value):
@@ -559,8 +559,8 @@ def precompile(self):
def __repr__(self):
return '<ParserRuleProperty name=%r filename=%s:%d' \
'value=%r watched_keys=%r>' % (
- self.name, self.ctx.filename, self.line + 1,
- self.value, self.watched_keys)
+ self.name, self.ctx.filename, self.line + 1,
+ self.value, self.watched_keys)
class ParserRule(object):
@@ -825,7 +825,7 @@ def parse_level(self, level, lines):
tmp = content.lstrip(' \t')
# Replace any tab with 4 spaces
- tmp = content[:len(content)-len(tmp)]
+ tmp = content[:len(content) - len(tmp)]
tmp = tmp.replace('\t', ' ')
count = len(tmp)
@@ -838,7 +838,7 @@ def parse_level(self, level, lines):
# Level finished
if count < indent:
- return objects, lines[i-1:]
+ return objects, lines[i - 1:]
# Current level, create an object
elif count == indent:
@@ -1029,7 +1029,7 @@ def match(self, widget):
parents = ParserSelectorName.parents
cls = widget.__class__
if not cls in parents:
- classes = [x.__name__.lower() for x in \
+ classes = [x.__name__.lower() for x in
[cls] + list(self.get_bases(cls))]
parents[cls] = classes
return self.key in parents[cls]
View
2  kivy/loader.py
@@ -192,7 +192,7 @@ def _update(self, *largs):
return
# create the image
- image = data#ProxyImage(data)
+ image = data # ProxyImage(data)
Cache.append('kivy.loader', filename, image)
# update client
View
2  kivy/logger.py
@@ -162,7 +162,7 @@ def _configure(self):
if not os.path.exists(filename):
break
n += 1
- if n > 10000: # prevent maybe flooding ?
+ if n > 10000: # prevent maybe flooding ?
raise Exception('Too many logfile, remove them')
FileHandler.filename = filename
View
4 kivy/modules/keybinding.py
@@ -13,9 +13,9 @@
def _on_keyboard_handler(instance, key, scancode, codepoint, modifier):
- if key == 293: # F12
+ if key == 293: # F12
instance.screenshot()
- elif key == 292: # F11
+ elif key == 292: # F11
instance.rotation += 90
View
4 kivy/modules/recorder.py
@@ -37,12 +37,12 @@
def on_recorder_key(recorder, window, key, *largs):
- if key == 289: # F8
+ if key == 289: # F8
if recorder.play:
Logger.error('Recorder: Cannot start recording while playing.')
return
recorder.record = not recorder.record
- elif key == 288: # F7
+ elif key == 288: # F7
if recorder.record:
Logger.error('Recorder: Cannot start playing while recording.')
return
View
18 kivy/parser.py
@@ -30,7 +30,7 @@ def parse_filename(filename):
def color_error(text):
- #show warning and return a sane value
+ # show warning and return a sane value
Logger.warning(text)
return (0, 0, 0, 1)
@@ -55,10 +55,12 @@ def parse_color(text):
if len(value) < 3:
#in case of invalid input like rgb()/rgb(r)/rgb(r, g)
raise ValueError
- except ValueError, AttributeError:
- return color_error('Color Parser:Invalid color for %r' % text)
+ except ValueError:
+ return color_error('ColorParser: Invalid color for %r' % text)
+ except AttributeError:
+ return color_error('ColorParser: Invalid color for %r' % text)
else:
- return color_error('Color Parser:Invalid color for %r' % text)
+ return color_error('ColorParser: Invalid color for %r' % text)
if len(value) == 3:
value.append(1.)
elif len(text):
@@ -70,11 +72,13 @@ def parse_color(text):
res = ''.join([x + x for x in res])
elif lres != 6 and lres != 8:
#raise ColorException('Invalid color format for %r' % text)
- return color_error('Color Parser:Invalid color format for %r' %text)
+ return color_error(
+ 'ColorParser: Invalid color format for %r' % text)
try:
- value = [int(res[i:i+2], 16) / 255. for i in xrange(0, len(res), 2)]
+ value = [int(res[i:i + 2], 16) / 255.
+ for i in xrange(0, len(res), 2)]
except ValueError:
- return color_error('Color Parser:Invalid color for %r' % text)
+ return color_error('ColorParser: Invalid color for %r' % text)
if lres == 6:
value.append(1.)
return value
View
2  kivy/support.py
@@ -117,7 +117,7 @@ def android_check_pause(*largs):
Logger.info('Android: Android resumed, resume the app')
app.dispatch('on_resume')
Window.canvas.ask_update()
- g_android_redraw_count = 25 # 5 frames/seconds, during 5 seconds
+ g_android_redraw_count = 25 # 5 frames/seconds during 5 seconds
Clock.unschedule(_android_ask_redraw)
Clock.schedule_interval(_android_ask_redraw, 1 / 5)
Logger.info('Android: App resume completed.')
View
2  kivy/tests/test_image.py
@@ -14,6 +14,6 @@ def setUp(self):
def test_keep_data(self):
root = self.root
self.assertEqual(root._image._data[0].data, None)
- i1 = self.cls(self.image, keep_data = True)
+ i1 = self.cls(self.image, keep_data=True)
if not i1._image._data[0].data:
self.fail('Image has no data even with keep_data = True')
View
2  kivy/tests/test_issue_609.py
@@ -9,7 +9,7 @@ def test_markup_pos(self):
lbl = Label(text="TextToTest")
lbl.bind(text_size=lbl.setter('size'))
- mrkp = Label(text="TextToTest", markup = True)
+ mrkp = Label(text="TextToTest", markup=True)
mrkp.bind(text_size=mrkp.setter('size'))
grid = GridLayout(rows=1, size_hint=(1, 1))
View
3  kivy/tools/benchmark.py
@@ -176,7 +176,7 @@ def log(s, newline=True):
# force gc before next test
gc.collect()
- log('%2d/%-2d %-60s' % (benchs.index(x)+1,
+ log('%2d/%-2d %-60s' % (benchs.index(x) + 1,
len(benchs), x.__doc__), False)
try:
sys.stderr.write('.')
@@ -226,7 +226,6 @@ def log(s, newline=True):
r = requests.post('https://api.github.com/gists', data=json.dumps(payload))
-
print
print
print 'REPORT posted at {0}'.format(r.json['html_url'])
View
6 kivy/tools/gles_compat/subset_gles.py
@@ -24,9 +24,9 @@
'''
-gl = open("/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/" + \
+gl = open("/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/" +
"OpenGL.framework/Versions/A/Headers/gl.h", 'r')
-glext = open("/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/" + \
+glext = open("/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/" +
"OpenGL.framework/Versions/A/Headers/glext.h", 'r')
gles = open("gl2.h", 'r')
@@ -85,8 +85,6 @@ def extract_common_symbols(symbols1, symbols2, already_extracted):
print line2
print "#define %s %s" % (symbol1, symbol2)
-
-
# Generate ------------------------------------------------
# pipe to kivy/kivy/graphics/common_subset.h
View
5 kivy/tools/packaging/factory.py
@@ -78,10 +78,7 @@ def run(self):
if symbol.startswith('_'):
continue
attr = getattr(m, symbol)
- if type(attr) not in (
- types.TypeType,
- types.ClassType,
- ):
+ if type(attr) not in (types.TypeType, types.ClassType):
continue
symbols.append((symbol, module))
print symbol,
View
1,875 kivy/tools/pep8checker/pep8.py
@@ -1,6 +1,6 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# pep8.py - Check Python source code formatting, according to PEP 8
-# Copyright (C) 2006 Johann C. Rocholl <johann@browsershots.org>
+# Copyright (C) 2006 Johann C. Rocholl <johann@rocholl.net>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -22,7 +22,7 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-"""
+r"""
Check Python source code formatting, according to PEP 8:
http://www.python.org/dev/peps/pep-0008/
@@ -30,8 +30,7 @@
$ python pep8.py -h
This program and its regression test suite live here:
-http://svn.browsershots.org/trunk/devtools/pep8/
-http://trac.browsershots.org/browser/trunk/devtools/pep8/
+http://github.com/jcrocholl/pep8
Groups of errors and warnings:
E errors
@@ -43,6 +42,7 @@
500 line length
600 deprecation
700 statements
+900 syntax error
You can add checks to this program by writing plugins. Each plugin is
a simple function that is called for each line of source code, either
@@ -79,40 +79,84 @@ def blank_lines(logical_line, blank_lines, indent_level, line_number)
The docstring of each check function shall be the relevant part of
text from PEP 8. It is printed if the user enables --show-pep8.
+Several docstrings contain examples directly from the PEP 8 document.
+
+Okay: spam(ham[1], {eggs: 2})
+E201: spam( ham[1], {eggs: 2})
+
+These examples are verified automatically when pep8.py is run with the
+--doctest option. You can add examples for your own check functions.
+The format is simple: "Okay" or error/warning code followed by colon
+and space, the rest of the line is example source code. If you put 'r'
+before the docstring, you can use \n for newline, \t for tab and \s
+for space.
"""
+__version__ = '1.3.3'
+
import os
import sys
import re
import time
import inspect
+import keyword
import tokenize
from optparse import OptionParser
-from keyword import iskeyword
from fnmatch import fnmatch
-
-__version__ = '0.2.0'
-__revision__ = '$Rev$'
-
-default_exclude = '.svn,CVS,*.pyc,*.pyo'
-
-indent_match = re.compile(r'([ \t]*)').match
-raise_comma_match = re.compile(r'raise\s+\w+\s*(,)').match
-equals_boolean_search = re.compile(r'([!=]=\s*(True|False))|((True|False)\s*[!=]=)').search
-equals_None_search = re.compile(r'([!=]=\s*None)|(None\s*[!=]=)').search
-
-not_one_ws_around_operators_match = re.compile(r'^[^\(\[]+[^\s](\+|\-|\*|/|%|\^|&|\||=|<|>|>>|<<|\+=|\-=|\*=|/=|%=|\^=|&=|\|=|==|<=|>=|>>=|<<=|!=|<>)[^\s][^\)\]]+$').match
-
-operators = """
-+ - * / % ^ & | = < > >> <<
-+= -= *= /= %= ^= &= |= == <= >= >>= <<=
-!= <> :
-in is or not and
-""".split()
-
-options = None
-args = None
+try:
+ from configparser import RawConfigParser
+ from io import TextIOWrapper
+except ImportError:
+ from ConfigParser import RawConfigParser
+
+DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git'
+DEFAULT_IGNORE = 'E24'
+if sys.platform == 'win32':
+ DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8')
+else:
+ DEFAULT_CONFIG = os.path.join(os.getenv('XDG_CONFIG_HOME') or
+ os.path.expanduser('~/.config'), 'pep8')
+MAX_LINE_LENGTH = 80
+REPORT_FORMAT = {
+ 'default': '%(path)s:%(row)d:%(col)d: %(code)s %(text)s',
+ 'pylint': '%(path)s:%(row)d: [%(code)s] %(text)s',
+}
+
+
+SINGLETONS = frozenset(['False', 'None', 'True'])
+KEYWORDS = frozenset(keyword.kwlist + ['print']) - SINGLETONS
+BINARY_OPERATORS = frozenset([
+ '**=', '*=', '+=', '-=', '!=', '<>',
+ '%=', '^=', '&=', '|=', '==', '/=', '//=', '<=', '>=', '<<=', '>>=',
+ '%', '^', '&', '|', '=', '/', '//', '<', '>', '<<'])
+UNARY_OPERATORS = frozenset(['>>', '**', '*', '+', '-'])
+OPERATORS = BINARY_OPERATORS | UNARY_OPERATORS
+WHITESPACE = frozenset(' \t')
+SKIP_TOKENS = frozenset([tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE,
+ tokenize.INDENT, tokenize.DEDENT])
+BENCHMARK_KEYS = ['directories', 'files', 'logical lines', 'physical lines']
+
+INDENT_REGEX = re.compile(r'([ \t]*)')
+RAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*(,)')
+RERAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*,\s*\w+\s*,\s*\w+')
+SELFTEST_REGEX = re.compile(r'(Okay|[EW]\d{3}):\s(.*)')
+ERRORCODE_REGEX = re.compile(r'[EW]\d{3}')
+DOCSTRING_REGEX = re.compile(r'u?r?["\']')
+EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[[({] | []}),;:]')
+WHITESPACE_AFTER_COMMA_REGEX = re.compile(r'[,;:]\s*(?: |\t)')
+COMPARE_SINGLETON_REGEX = re.compile(r'([=!]=)\s*(None|False|True)')
+COMPARE_TYPE_REGEX = re.compile(r'([=!]=|is|is\s+not)\s*type(?:s\.(\w+)Type'
+ r'|\(\s*(\(\s*\)|[^)]*[^ )])\s*\))')
+KEYWORD_REGEX = re.compile(r'(?:[^\s])(\s*)\b(?:%s)\b(\s*)' %
+ r'|'.join(KEYWORDS))
+OPERATOR_REGEX = re.compile(r'(?:[^\s])(\s*)(?:[-+*/|!<=>%&^]+)(\s*)')
+LAMBDA_REGEX = re.compile(r'\blambda\b')
+HUNK_REGEX = re.compile(r'^@@ -\d+,\d+ \+(\d+),(\d+) @@.*$')
+
+# Work around Python < 2.6 behaviour, which does not generate NL after
+# a comment which is on a line by itself.
+COMMENT_WITH_NL = tokenize.generate_tokens(['#\n'].pop).send(None)[1] == '#\n'
##############################################################################
@@ -121,7 +165,7 @@ def blank_lines(logical_line, blank_lines, indent_level, line_number)
def tabs_or_spaces(physical_line, indent_char):
- """
+ r"""
Never mix tabs and spaces.
The most popular way of indenting Python is with spaces only. The
@@ -130,52 +174,81 @@ def tabs_or_spaces(physical_line, indent_char):
invoking the Python command line interpreter with the -t option, it issues
warnings about code that illegally mixes tabs and spaces. When using -tt
these warnings become errors. These options are highly recommended!
+
+ Okay: if a == 0:\n a = 1\n b = 1
+ E101: if a == 0:\n a = 1\n\tb = 1
"""
- indent = indent_match(physical_line).group(1)
+ indent = INDENT_REGEX.match(physical_line).group(1)
for offset, char in enumerate(indent):
if char != indent_char:
return offset, "E101 indentation contains mixed spaces and tabs"
def tabs_obsolete(physical_line):
- """
+ r"""
For new projects, spaces-only are strongly recommended over tabs. Most
editors have features that make this easy to do.
+
+ Okay: if True:\n return
+ W191: if True:\n\treturn
"""
- indent = indent_match(physical_line).group(1)
- if indent.count('\t'):
+ indent = INDENT_REGEX.match(physical_line).group(1)
+ if '\t' in indent:
return indent.index('\t'), "W191 indentation contains tabs"
def trailing_whitespace(physical_line):
- """
+ r"""
JCR: Trailing whitespace is superfluous.
- """
- physical_line = physical_line.rstrip('\n') # chr(10), newline
- physical_line = physical_line.rstrip('\r') # chr(13), carriage return
- physical_line = physical_line.rstrip('\x0c') # chr(12), form feed, ^L
- stripped = physical_line.rstrip()
+ FBM: Except when it occurs as part of a blank line (i.e. the line is
+ nothing but whitespace). According to Python docs[1] a line with only
+ whitespace is considered a blank line, and is to be ignored. However,
+ matching a blank line to its indentation level avoids mistakenly
+ terminating a multi-line statement (e.g. class declaration) when
+ pasting code into the standard Python interpreter.
+
+ [1] http://docs.python.org/reference/lexical_analysis.html#blank-lines
+
+ The warning returned varies on whether the line itself is blank, for easier
+ filtering for those who want to indent their blank lines.
+
+ Okay: spam(1)
+ W291: spam(1)\s
+ W293: class Foo(object):\n \n bang = 12
+ """
+ physical_line = physical_line.rstrip('\n') # chr(10), newline
+ physical_line = physical_line.rstrip('\r') # chr(13), carriage return
+ physical_line = physical_line.rstrip('\x0c') # chr(12), form feed, ^L
+ stripped = physical_line.rstrip(' \t\v')
if physical_line != stripped:
- return len(stripped), "W291 trailing whitespace"
+ if stripped:
+ return len(stripped), "W291 trailing whitespace"
+ else:
+ return 0, "W293 blank line contains whitespace"
#def trailing_blank_lines(physical_line, lines, line_number):
-# """
+# r"""
# JCR: Trailing blank lines are superfluous.
+#
+# Okay: spam(1)
+# W391: spam(1)\n
# """
-# if physical_line.strip() == '' and line_number == len(lines):
+# if not physical_line.rstrip() and line_number == len(lines):
# return 0, "W391 blank line at end of file"
def missing_newline(physical_line):
"""
JCR: The last line should have a newline.
+
+ Reports warning W292.
"""
if physical_line.rstrip() == physical_line:
return len(physical_line), "W292 no newline at end of file"
-def maximum_line_length(physical_line):
+def maximum_line_length(physical_line, max_line_length):
"""
Limit all lines to a maximum of 79 characters.
@@ -185,25 +258,21 @@ def maximum_line_length(physical_line):
ugly. Therefore, please limit all lines to a maximum of 79 characters.
For flowing long blocks of text (docstrings or comments), limiting the
length to 72 characters is recommended.
- """
- length = len(physical_line.rstrip())
- if length > 80:
- return 80, "E501 line too long (%d characters)" % length
-
-
-def crlf_lines(physical_line):
- """
- Line contains CR (e.g. as a CRLF line ending).
- Many free software projects have a strong focus on POSIX platforms (like
- Linux, *BSD, Unix, Mac OS X, etc.) and they all use LF-only line endings.
- Only Win32 platform uses CRLF line endings.
- So if you have a Win32-only source code using CRLF line endings, you might
- want to exclude this test.
+ Reports error E501.
"""
- pos = physical_line.find('\r')
- if pos >= 0:
- return pos, "W293 line contains CR char(s)"
+ line = physical_line.rstrip()
+ length = len(line)
+ if length > max_line_length:
+ if hasattr(line, 'decode'): # Python 2
+ # The line could contain multi-byte characters
+ try:
+ length = len(line.decode('utf-8'))
+ except UnicodeError:
+ pass
+ if length > max_line_length:
+ return (max_line_length, "E501 line too long "
+ "(%d > %d characters)" % (length, max_line_length))
##############################################################################
@@ -212,8 +281,8 @@ def crlf_lines(physical_line):
def blank_lines(logical_line, blank_lines, indent_level, line_number,
- previous_logical):
- """
+ previous_logical, previous_indent_level):
+ r"""
Separate top-level function and class definitions with two blank lines.
Method definitions inside a class are separated by a single blank line.
@@ -223,20 +292,30 @@ def blank_lines(logical_line, blank_lines, indent_level, line_number,
one-liners (e.g. a set of dummy implementations).
Use blank lines in functions, sparingly, to indicate logical sections.
+
+ Okay: def a():\n pass\n\n\ndef b():\n pass
+ Okay: def a():\n pass\n\n\n# Foo\n# Bar\n\ndef b():\n pass
+
+ E301: class Foo:\n b = 0\n def bar():\n pass
+ E302: def a():\n pass\n\ndef b(n):\n pass
+ E303: def a():\n pass\n\n\n\ndef b(n):\n pass
+ E303: def a():\n\n\n\n pass
+ E304: @decorator\n\ndef a():\n pass
"""
if line_number == 1:
- return # Don't expect blank lines before the first line
+ return # Don't expect blank lines before the first line
if previous_logical.startswith('@'):
- return # Don't expect blank lines after function decorator
- if (logical_line.startswith('def ') or
- logical_line.startswith('class ') or
- logical_line.startswith('@')):
- if indent_level > 0 and blank_lines != 1:
- return 0, "E301 expected 1 blank line, found %d" % blank_lines
- if indent_level == 0 and blank_lines != 2:
- return 0, "E302 expected 2 blank lines, found %d" % blank_lines
- if blank_lines > 2:
- return 0, "E303 too many blank lines (%d)" % blank_lines
+ if blank_lines:
+ yield 0, "E304 blank lines found after function decorator"
+ elif blank_lines > 2 or (indent_level and blank_lines == 2):
+ yield 0, "E303 too many blank lines (%d)" % blank_lines
+ elif logical_line.startswith(('def ', 'class ', '@')):
+ if indent_level:
+ if not (blank_lines or previous_indent_level < indent_level or
+ DOCSTRING_REGEX.match(previous_logical)):
+ yield 0, "E301 expected 1 blank line, found 0"
+ elif blank_lines != 2:
+ yield 0, "E302 expected 2 blank lines, found %d" % blank_lines
def extraneous_whitespace(logical_line):
@@ -246,51 +325,265 @@ def extraneous_whitespace(logical_line):
- Immediately inside parentheses, brackets or braces.
- Immediately before a comma, semicolon, or colon.
+
+ Okay: spam(ham[1], {eggs: 2})
+ E201: spam( ham[1], {eggs: 2})
+ E201: spam(ham[ 1], {eggs: 2})
+ E201: spam(ham[1], { eggs: 2})
+ E202: spam(ham[1], {eggs: 2} )
+ E202: spam(ham[1 ], {eggs: 2})
+ E202: spam(ham[1], {eggs: 2 })
+
+ E203: if x == 4: print x, y; x, y = y , x
+ E203: if x == 4: print x, y ; x, y = y, x
+ E203: if x == 4 : print x, y; x, y = y, x
"""
line = logical_line
- for char in '([{':
- found = line.find(char + ' ')
- if found > -1:
- return found + 1, "E201 whitespace after '%s'" % char
- for char in '}])':
- found = line.find(' ' + char)
- if found > -1 and line[found - 1] != ',':
- return found, "E202 whitespace before '%s'" % char
- for char in ',;:':
- found = line.find(' ' + char)
- if found > -1:
- return found, "E203 whitespace before '%s'" % char
+ for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line):
+ text = match.group()
+ char = text.strip()
+ found = match.start()
+ if text == char + ' ':
+ # assert char in '([{'
+ yield found + 1, "E201 whitespace after '%s'" % char
+ elif line[found - 1] != ',':
+ code = ('E202' if char in '}])' else 'E203') # if char in ',;:'
+ yield found, "%s whitespace before '%s'" % (code, char)
+
+
+def whitespace_around_keywords(logical_line):
+ r"""
+ Avoid extraneous whitespace around keywords.
+
+ Okay: True and False
+ E271: True and False
+ E272: True and False
+ E273: True and\tFalse
+ E274: True\tand False
+ """
+ for match in KEYWORD_REGEX.finditer(logical_line):
+ before, after = match.groups()
+
+ if '\t' in before:
+ yield match.start(1), "E274 tab before keyword"
+ elif len(before) > 1:
+ yield match.start(1), "E272 multiple spaces before keyword"
+
+ if '\t' in after:
+ yield match.start(2), "E273 tab after keyword"
+ elif len(after) > 1:
+ yield match.start(2), "E271 multiple spaces after keyword"
def missing_whitespace(logical_line):
"""
JCR: Each comma, semicolon or colon should be followed by whitespace.
+
+ Okay: [a, b]
+ Okay: (3,)
+ Okay: a[1:4]
+ Okay: a[:4]
+ Okay: a[1:]
+ Okay: a[1:4:2]
+ E231: ['a','b']
+ E231: foo(bar,baz)
"""
line = logical_line
for index in range(len(line) - 1):
char = line[index]
- if char in ',;:' and line[index + 1] != ' ':
+ if char in ',;:' and line[index + 1] not in WHITESPACE:
before = line[:index]
if char == ':' and before.count('[') > before.count(']'):
- continue # Slice syntax, no space required
- return index, "E231 missing whitespace after '%s'" % char
+ continue # Slice syntax, no space required
+ if char == ',' and line[index + 1] == ')':
+ continue # Allow tuple with only one element: (3,)
+ yield index, "E231 missing whitespace after '%s'" % char
def indentation(logical_line, previous_logical, indent_char,
indent_level, previous_indent_level):
- """
+ r"""
Use 4 spaces per indentation level.
For really old code that you don't want to mess up, you can continue to
use 8-space tabs.
+
+ Okay: a = 1
+ Okay: if a == 0:\n a = 1
+ E111: a = 1
+
+ Okay: for item in items:\n pass
+ E112: for item in items:\npass
+
+ Okay: a = 1\nb = 2
+ E113: a = 1\n b = 2
"""
if indent_char == ' ' and indent_level % 4:
- return 0, "E111 indentation is not a multiple of four"
+ yield 0, "E111 indentation is not a multiple of four"
indent_expect = previous_logical.endswith(':')
if indent_expect and indent_level <= previous_indent_level:
- return 0, "E112 expected an indented block"
+ yield 0, "E112 expected an indented block"
if indent_level > previous_indent_level and not indent_expect:
- return 0, "E113 unexpected indentation"
+ yield 0, "E113 unexpected indentation"
+
+
+def continuation_line_indentation(logical_line, tokens, indent_level, verbose):
+ r"""
+ Continuation lines should align wrapped elements either vertically using
+ Python's implicit line joining inside parentheses, brackets and braces, or
+ using a hanging indent.
+
+ When using a hanging indent the following considerations should be applied:
+
+ - there should be no arguments on the first line, and
+
+ - further indentation should be used to clearly distinguish itself as a
+ continuation line.
+
+ Okay: a = (\n)
+ E123: a = (\n )
+
+ Okay: a = (\n 42)
+ E121: a = (\n 42)
+ E122: a = (\n42)
+ E123: a = (\n 42\n )
+ E124: a = (24,\n 42\n)
+ E125: if (a or\n b):\n pass
+ E126: a = (\n 42)
+ E127: a = (24,\n 42)
+ E128: a = (24,\n 42)
+ """
+ first_row = tokens[0][2][0]
+ nrows = 1 + tokens[-1][2][0] - first_row
+ if nrows == 1:
+ return
+
+ # indent_next tells us whether the next block is indented; assuming
+ # that it is indented by 4 spaces, then we should not allow 4-space
+ # indents on the final continuation line; in turn, some other
+ # indents are allowed to have an extra 4 spaces.
+ indent_next = logical_line.endswith(':')
+
+ row = depth = 0
+ # remember how many brackets were opened on each line
+ parens = [0] * nrows
+ # relative indents of physical lines
+ rel_indent = [0] * nrows
+ # visual indents
+ indent = [indent_level]
+ indent_chances = {}
+ last_indent = (0, 0)
+ if verbose >= 3:
+ print(">>> " + tokens[0][4].rstrip())
+
+ for token_type, text, start, end, line in tokens:
+ newline = row < start[0] - first_row
+ if newline:
+ row = start[0] - first_row
+ newline = (not last_token_multiline and
+ token_type not in (tokenize.NL, tokenize.NEWLINE))
+
+ if newline:
+ # this is the beginning of a continuation line.
+ last_indent = start
+ if verbose >= 3:
+ print("... " + line.rstrip())
+
+ # record the initial indent.
+ rel_indent[row] = start[1] - indent_level
+
+ if depth:
+ # a bracket expression in a continuation line.
+ # find the line that it was opened on
+ for open_row in range(row - 1, -1, -1):
+ if parens[open_row]:
+ break
+ else:
+ # an unbracketed continuation line (ie, backslash)
+ open_row = 0
+ hang = rel_indent[row] - rel_indent[open_row]
+ visual_indent = indent_chances.get(start[1])
+
+ if token_type == tokenize.OP and text in ']})':
+ # this line starts with a closing bracket
+ if indent[depth]:
+ if start[1] != indent[depth]:
+ yield (start, 'E124 closing bracket does not match '
+ 'visual indentation')
+ elif hang:
+ yield (start, 'E123 closing bracket does not match '
+ 'indentation of opening bracket\'s line')
+ elif visual_indent is True:
+ # visual indent is verified
+ if not indent[depth]:
+ indent[depth] = start[1]
+ elif visual_indent in (text, str):
+ # ignore token lined up with matching one from a previous line
+ pass
+ elif indent[depth] and start[1] < indent[depth]:
+ # visual indent is broken
+ yield (start, 'E128 continuation line '
+ 'under-indented for visual indent')
+ elif hang == 4 or (indent_next and rel_indent[row] == 8):
+ # hanging indent is verified
+ pass
+ else:
+ # indent is broken
+ if hang <= 0:
+ error = 'E122', 'missing indentation or outdented'
+ elif indent[depth]:
+ error = 'E127', 'over-indented for visual indent'
+ elif hang % 4:
+ error = 'E121', 'indentation is not a multiple of four'
+ else:
+ error = 'E126', 'over-indented for hanging indent'
+ yield start, "%s continuation line %s" % error
+
+ # look for visual indenting
+ if parens[row] and token_type != tokenize.NL and not indent[depth]:
+ indent[depth] = start[1]
+ indent_chances[start[1]] = True
+ if verbose >= 4:
+ print("bracket depth %s indent to %s" % (depth, start[1]))
+ # deal with implicit string concatenation
+ elif token_type == tokenize.STRING or text in ('u', 'ur', 'b', 'br'):
+ indent_chances[start[1]] = str
+
+ # keep track of bracket depth
+ if token_type == tokenize.OP:
+ if text in '([{':
+ depth += 1
+ indent.append(0)
+ parens[row] += 1
+ if verbose >= 4:
+ print("bracket depth %s seen, col %s, visual min = %s" %
+ (depth, start[1], indent[depth]))
+ elif text in ')]}' and depth > 0:
+ # parent indents should not be more than this one
+ prev_indent = indent.pop() or last_indent[1]
+ for d in range(depth):
+ if indent[d] > prev_indent:
+ indent[d] = 0
+ for ind in list(indent_chances):
+ if ind >= prev_indent:
+ del indent_chances[ind]
+ depth -= 1
+ if depth:
+ indent_chances[indent[depth]] = True
+ for idx in range(row, -1, -1):
+ if parens[idx]:
+ parens[idx] -= 1
+ break
+ assert len(indent) == depth + 1
+ if start[1] not in indent_chances:
+ # allow to line up tokens
+ indent_chances[start[1]] = text
+
+ last_token_multiline = (start[0] != end[0])
+
+ if indent_next and rel_indent[-1] == 4:
+ yield (last_indent, "E125 continuation line does not distinguish "
+ "itself from next logical line")
def whitespace_before_parameters(logical_line, tokens):
@@ -302,6 +595,13 @@ def whitespace_before_parameters(logical_line, tokens):
- Immediately before the open parenthesis that starts an indexing or
slicing.
+
+ Okay: spam(1)
+ E211: spam (1)
+
+ Okay: dict['key'] = list[index]
+ E211: dict ['key'] = list[index]
+ E211: dict['key'] = list [index]
"""
prev_type = tokens[0][0]
prev_text = tokens[0][1]
@@ -311,106 +611,366 @@ def whitespace_before_parameters(logical_line, tokens):
if (token_type == tokenize.OP and
text in '([' and
start != prev_end and
- prev_type == tokenize.NAME and
+ (prev_type == tokenize.NAME or prev_text in '}])') and
+ # Syntax "class A (B):" is allowed, but avoid it
(index < 2 or tokens[index - 2][1] != 'class') and
- (not iskeyword(prev_text))):
- return prev_end, "E211 whitespace before '%s'" % text
+ # Allow "return (a.foo for a in range(5))"
+ not keyword.iskeyword(prev_text)):
+ yield prev_end, "E211 whitespace before '%s'" % text
prev_type = token_type
prev_text = text
prev_end = end
-def extra_whitespace_around_operator(logical_line):
- """
+def whitespace_around_operator(logical_line):
+ r"""
Avoid extraneous whitespace in the following situations:
- More than one space around an assignment (or other) operator to
align it with another.
- """
- line = logical_line
- for operator in operators:
- found = line.find(' ' + operator)
- if found > -1:
- return found, "E221 multiple spaces before operator"
- found = line.find(operator + ' ')
- if found > -1:
- return found, "E222 multiple spaces after operator"
- found = line.find('\t' + operator)
- if found > -1:
- return found, "E223 tab before operator"
- found = line.find(operator + '\t')
- if found > -1:
- return found, "E224 tab after operator"
-
-def whitespace_around_operator(logical_line):
- """
- Have exactly 1 space left and right of the operator.
- """
- match = not_one_ws_around_operators_match(logical_line)
- if match and not 'lambda' in logical_line:
- return match.start(1), "E225 operators shall be surrounded by a single space on each side %s" % logical_line
+ Okay: a = 12 + 3
+ E221: a = 4 + 5
+ E222: a = 4 + 5
+ E223: a = 4\t+ 5
+ E224: a = 4 +\t5
+ """
+ for match in OPERATOR_REGEX.finditer(logical_line):
+ before, after = match.groups()
+
+ if '\t' in before:
+ yield match.start(1), "E223 tab before operator"
+ elif len(before) > 1:
+ yield match.start(1), "E221 multiple spaces before operator"
+
+ if '\t' in after:
+ yield match.start(2), "E224 tab after operator"
+ elif len(after) > 1:
+ yield match.start(2), "E222 multiple spaces after operator"
+
+
+def missing_whitespace_around_operator(logical_line, tokens):
+ r"""
+ - Always surround these binary operators with a single space on
+ either side: assignment (=), augmented assignment (+=, -= etc.),
+ comparisons (==, <, >, !=, <>, <=, >=, in, not in, is, is not),
+ Booleans (and, or, not).
+
+ - Use spaces around arithmetic operators.
+
+ Okay: i = i + 1
+ Okay: submitted += 1
+ Okay: x = x * 2 - 1
+ Okay: hypot2 = x * x + y * y
+ Okay: c = (a + b) * (a - b)
+ Okay: foo(bar, key='word', *args, **kwargs)
+ Okay: baz(**kwargs)
+ Okay: negative = -1
+ Okay: spam(-1)
+ Okay: alpha[:-i]
+ Okay: if not -5 < x < +5:\n pass
+ Okay: lambda *args, **kw: (args, kw)
+
+ E225: i=i+1
+ E225: submitted +=1
+ E225: x = x*2 - 1
+ E225: hypot2 = x*x + y*y
+ E225: c = (a+b) * (a-b)
+ E225: c = alpha -4
+ E225: z = x **y
+ """
+ parens = 0
+ need_space = False
+ prev_type = tokenize.OP
+ prev_text = prev_end = None
+ for token_type, text, start, end, line in tokens:
+ if token_type in (tokenize.NL, tokenize.NEWLINE, tokenize.ERRORTOKEN):
+ # ERRORTOKEN is triggered by backticks in Python 3000
+ continue
+ if text in ('(', 'lambda'):
+ parens += 1
+ elif text == ')':
+ parens -= 1
+ if need_space:
+ if start != prev_end:
+ need_space = False
+ elif text == '>' and prev_text in ('<', '-'):
+ # Tolerate the "<>" operator, even if running Python 3
+ # Deal with Python 3's annotated return value "->"
+ pass
+ else:
+ yield prev_end, "E225 missing whitespace around operator"
+ need_space = False
+ elif token_type == tokenize.OP and prev_end is not None:
+ if text == '=' and parens:
+ # Allow keyword args or defaults: foo(bar=None).
+ pass
+ elif text in BINARY_OPERATORS:
+ need_space = True
+ elif text in UNARY_OPERATORS:
+ # Allow unary operators: -123, -x, +1.
+ # Allow argument unpacking: foo(*args, **kwargs).
+ if prev_type == tokenize.OP:
+ if prev_text in '}])':
+ need_space = True
+ elif prev_type == tokenize.NAME:
+ if prev_text not in KEYWORDS:
+ need_space = True
+ elif prev_type not in SKIP_TOKENS:
+ need_space = True
+ if need_space and start == prev_end:
+ yield prev_end, "E225 missing whitespace around operator"
+ need_space = False
+ prev_type = token_type
+ prev_text = text
+ prev_end = end
def whitespace_around_comma(logical_line):
- """
+ r"""
Avoid extraneous whitespace in the following situations:
- More than one space around an assignment (or other) operator to
align it with another.
- JCR: This should also be applied around comma etc.
+ Note: these checks are disabled by default
+
+ Okay: a = (1, 2)
+ E241: a = (1, 2)
+ E242: a = (1,\t2)
"""
line = logical_line
- for separator in ',;:':
- found = line.find(separator + ' ')
- if found > -1:
- return found + 1, "E241 multiple spaces after '%s'" % separator
- found = line.find(separator + '\t')
- if found > -1:
- return found + 1, "E242 tab after '%s'" % separator
+ for m in WHITESPACE_AFTER_COMMA_REGEX.finditer(line):
+ found = m.start() + 1
+ if '\t' in m.group():
+ yield found, "E242 tab after '%s'" % m.group()[0]
+ else:
+ yield found, "E241 multiple spaces after '%s'" % m.group()[0]
+
+
+def whitespace_around_named_parameter_equals(logical_line, tokens):
+ """
+ Don't use spaces around the '=' sign when used to indicate a
+ keyword argument or a default parameter value.
+
+ Okay: def complex(real, imag=0.0):
+ Okay: return magic(r=real, i=imag)
+ Okay: boolean(a == b)
+ Okay: boolean(a != b)
+ Okay: boolean(a <= b)
+ Okay: boolean(a >= b)
+
+ E251: def complex(real, imag = 0.0):
+ E251: return magic(r = real, i = imag)
+ """
+ parens = 0
+ no_space = False
+ prev_end = None
+ for token_type, text, start, end, line in tokens:
+ if no_space:
+ no_space = False
+ if start != prev_end:
+ yield (prev_end,
+ "E251 no spaces around keyword / parameter equals")
+ elif token_type == tokenize.OP:
+ if text == '(':
+ parens += 1
+ elif text == ')':
+ parens -= 1
+ elif parens and text == '=':
+ no_space = True
+ if start != prev_end:
+ yield (prev_end,
+ "E251 no spaces around keyword / parameter equals")
+ prev_end = end
-def imports_on_separate_lines(logical_line):
+def whitespace_before_inline_comment(logical_line, tokens):
"""
+ Separate inline comments by at least two spaces.
+
+ An inline comment is a comment on the same line as a statement. Inline
+ comments should be separated by at least two spaces from the statement.
+ They should start with a # and a single space.
+
+ Okay: x = x + 1 # Increment x
+ Okay: x = x + 1 # Increment x
+ E261: x = x + 1 # Increment x
+ E262: x = x + 1 #Increment x
+ E262: x = x + 1 # Increment x
+ """
+ prev_end = (0, 0)
+ for token_type, text, start, end, line in tokens:
+ if token_type == tokenize.COMMENT:
+ if not line[:start[1]].strip():
+ continue
+ if prev_end[0] == start[0] and start[1] < prev_end[1] + 2:
+ yield (prev_end,
+ "E261 at least two spaces before inline comment")
+ if text.startswith('# ') or not text.startswith('# '):
+ yield start, "E262 inline comment should start with '# '"
+ elif token_type != tokenize.NL:
+ prev_end = end
+
+
+def imports_on_separate_lines(logical_line):
+ r"""
Imports should usually be on separate lines.
+
+ Okay: import os\nimport sys
+ E401: import sys, os
+
+ Okay: from subprocess import Popen, PIPE
+ Okay: from myclas import MyClass
+ Okay: from foo.bar.yourclass import YourClass
+ Okay: import myclass
+ Okay: import foo.bar.yourclass
"""
line = logical_line
if line.startswith('import '):
found = line.find(',')
- if found > -1:
- return found, "E401 multiple imports on one line"
+ if -1 < found:
+ yield found, "E401 multiple imports on one line"
def compound_statements(logical_line):
- """
+ r"""
Compound statements (multiple statements on the same line) are
generally discouraged.
+
+ While sometimes it's okay to put an if/for/while with a small body
+ on the same line, never do this for multi-clause statements. Also
+ avoid folding such long lines!
+
+ Okay: if foo == 'blah':\n do_blah_thing()
+ Okay: do_one()
+ Okay: do_two()
+ Okay: do_three()
+
+ E701: if foo == 'blah': do_blah_thing()
+ E701: for x in lst: total += x
+ E701: while t < 10: t = delay()
+ E701: if foo == 'blah': do_blah_thing()
+ E701: else: do_non_blah_thing()
+ E701: try: something()
+ E701: finally: cleanup()
+ E701: if foo == 'blah': one(); two(); three()
+
+ E702: do_one(); do_two(); do_three()
"""
line = logical_line
found = line.find(':')
if -1 < found < len(line) - 1:
before = line[:found]
- if (before.count('{') <= before.count('}') and # {'a': 1} (dict)
- before.count('[') <= before.count(']') and # [1:2] (slice)
- not re.search(r'\blambda\b', before)): # lambda x: x
- return found, "E701 multiple statements on one line (colon)"
+ if (before.count('{') <= before.count('}') and # {'a': 1} (dict)
+ before.count('[') <= before.count(']') and # [1:2] (slice)
+ before.count('(') <= before.count(')') and # (Python 3 annotation)
+ not LAMBDA_REGEX.search(before)): # lambda x: x
+ yield found, "E701 multiple statements on one line (colon)"
found = line.find(';')
if -1 < found:
- return found, "E702 multiple statements on one line (semicolon)"
+ yield found, "E702 multiple statements on one line (semicolon)"
+
+
+def explicit_line_join(logical_line, tokens):
+ r"""
+ Avoid explicit line join between brackets.
+
+ The preferred way of wrapping long lines is by using Python's implied line
+ continuation inside parentheses, brackets and braces. Long lines can be
+ broken over multiple lines by wrapping expressions in parentheses. These
+ should be used in preference to using a backslash for line continuation.
+
+ E502: aaa = [123, \\n 123]
+ E502: aaa = ("bbb " \\n "ccc")
+
+ Okay: aaa = [123,\n 123]
+ Okay: aaa = ("bbb "\n "ccc")
+ Okay: aaa = "bbb " \\n "ccc"
+ """
+ prev_start = prev_end = parens = 0
+ for token_type, text, start, end, line in tokens:
+ if start[0] != prev_start and parens and backslash:
+ yield backslash, "E502 the backslash is redundant between brackets"
+ if end[0] != prev_end:
+ if line.rstrip('\r\n').endswith('\\'):
+ backslash = (end[0], len(line.splitlines()[-1]) - 1)
+ else:
+ backslash = None
+ prev_start = prev_end = end[0]
+ else:
+ prev_start = start[0]
+ if token_type == tokenize.OP:
+ if text in '([{':
+ parens += 1
+ elif text in ')]}':
+ parens -= 1
-def python_3000_has_key(logical_line):
+def comparison_to_singleton(logical_line):
+ """
+ Comparisons to singletons like None should always be done
+ with "is" or "is not", never the equality operators.
+
+ Okay: if arg is not None:
+ E711: if arg != None:
+ E712: if arg == True:
+
+ Also, beware of writing if x when you really mean if x is not None --
+ e.g. when testing whether a variable or argument that defaults to None was
+ set to some other value. The other value might have a type (such as a
+ container) that could be false in a boolean context!
+ """
+ match = COMPARE_SINGLETON_REGEX.search(logical_line)
+ if match:
+ same = (match.group(1) == '==')
+ singleton = match.group(2)
+ msg = "'if cond is %s:'" % (('' if same else 'not ') + singleton)
+ if singleton in ('None',):
+ code = 'E711'
+ else:
+ code = 'E712'
+ nonzero = ((singleton == 'True' and same) or
+ (singleton == 'False' and not same))
+ msg += " or 'if %scond:'" % ('' if nonzero else 'not ')
+ yield match.start(1), ("%s comparison to %s should be %s" %
+ (code, singleton, msg))
+
+
+def comparison_type(logical_line):
"""
+ Object type comparisons should always use isinstance() instead of
+ comparing types directly.
+
+ Okay: if isinstance(obj, int):
+ E721: if type(obj) is type(1):
+
+ When checking if an object is a string, keep in mind that it might be a
+ unicode string too! In Python 2.3, str and unicode have a common base
+ class, basestring, so you can do:
+
+ Okay: if isinstance(obj, basestring):
+ Okay: if type(a1) is type(b1):
+ <