Linter python (#299)

* Added pyflakes and Pylint for python

* Actually run linter in CI

* some simple pyflakes changes

* Add flake8 to panda reqs for linter test

* flake8 errors are fixed

* run flake8 in regression tests

* meant to run flake8

* hack to ignore unused import

* bug

* fix bugs in tucan_loopback

* Another fix by using set_safety_mode

* added pylintrc file

* more fixes and enabled pylint as well

* Fix pylint in circleci

* added linter to readme
master
rbiasini 2019-10-15 14:03:31 -07:00 committed by GitHub
parent 62e2f5caac
commit fce38a91d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 757 additions and 145 deletions

View File

@ -92,6 +92,20 @@ jobs:
command: |
docker run language_check /bin/bash -c "cd /panda/tests/language; ./test_language.py"
linter_python:
machine:
docker_layer_caching: true
steps:
- checkout
- run:
name: Build image
command: "docker build -t linter_python -f tests/linter_python/Dockerfile ."
- run:
name: Run linter python test
command: |
docker run linter_python /bin/bash -c "cd /panda/tests/linter_python; PYTHONPATH=/ ./flake8_panda.sh"
docker run linter_python /bin/bash -c "cd /panda/tests/linter_python; PYTHONPATH=/ ./pylint_panda.sh"
workflows:
version: 2
main:
@ -101,3 +115,4 @@ workflows:
- build
- safety_replay
- language_check
- linter_python

View File

@ -108,6 +108,8 @@ to ensure that the behavior remains unchanged.
* compiling the code in various configuration and flashing it both through USB and WiFi.
* Receiving, sending and forwarding CAN messages on all buses, over USB and WiFi.
In addition, we run [Pylint](https://www.pylint.org/) and [Flake8](https://github.com/PyCQA/flake8) linters on all python files within the panda repo.
Hardware
------

View File

@ -1 +1 @@
from .python import Panda, PandaWifiStreaming, PandaDFU, ESPROM, CesantaFlasher, flash_release, BASEDIR, ensure_st_up_to_date, build_st, PandaSerial
from .python import Panda, PandaWifiStreaming, PandaDFU, ESPROM, CesantaFlasher, flash_release, BASEDIR, ensure_st_up_to_date, build_st, PandaSerial # noqa: F401

View File

@ -11,7 +11,7 @@ def enter_download_mode(device):
try:
handle.controlWrite(usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, 0xd1, 0, 0, b'')
except (usb1.USBErrorIO, usb1.USBErrorPipe) as e:
except (usb1.USBErrorIO, usb1.USBErrorPipe):
print("Device download mode enabled.")
time.sleep(1)
else:

View File

@ -1,6 +1,5 @@
#!/usr/bin/env python3
import sys
import struct
from Crypto.PublicKey import RSA
def egcd(a, b):

View File

@ -1,6 +1,4 @@
#!/usr/bin/env python3
import binascii
import csv
import sys

View File

@ -13,10 +13,8 @@
# 0,344,c000c00000000000
import binascii
import csv
import sys
from panda import Panda
class Message():
"""Details about a specific message ID."""

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python3
import sys
from panda import Panda
def get_panda_password():

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python3
import time
import struct
import binascii
from panda import Panda
from hexdump import hexdump
from panda.python.isotp import isotp_send, isotp_recv

View File

@ -10,10 +10,10 @@ import time
import traceback
import subprocess
from .dfu import PandaDFU
from .esptool import ESPROM, CesantaFlasher
from .flash_release import flash_release
from .update import ensure_st_up_to_date
from .serial import PandaSerial
from .esptool import ESPROM, CesantaFlasher # noqa: F401
from .flash_release import flash_release # noqa: F401
from .update import ensure_st_up_to_date # noqa: F401
from .serial import PandaSerial # noqa: F401
from .isotp import isotp_send, isotp_recv
__version__ = '0.0.9'
@ -27,10 +27,10 @@ def build_st(target, mkfile="Makefile"):
from panda import BASEDIR
cmd = 'cd %s && make -f %s clean && make -f %s %s >/dev/null' % (os.path.join(BASEDIR, "board"), mkfile, mkfile, target)
try:
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError as exception:
output = exception.output
returncode = exception.returncode
_ = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError:
#output = exception.output
#returncode = exception.returncode
raise
def parse_can_buffer(dat):
@ -558,7 +558,7 @@ class Panda(object):
def kline_ll_recv(self, cnt, bus=2):
echo = bytearray()
while len(echo) != cnt:
ret = str(self._handle.controlRead(Panda.REQUEST_OUT, 0xe0, bus, 0, cnt-len(echo)))
ret = self._handle.controlRead(Panda.REQUEST_OUT, 0xe0, bus, 0, cnt-len(echo))
if DEBUG and len(ret) > 0:
print("kline recv: " + binascii.hexlify(ret))
echo += ret

View File

@ -1,8 +1,6 @@
import os
import usb1
import struct
import time
import binascii
# *** DFU mode ***
@ -116,6 +114,6 @@ class PandaDFU(object):
self.status()
try:
self._handle.controlWrite(0x21, DFU_DNLOAD, 2, 0, b"")
stat = str(self._handle.controlRead(0x21, DFU_GETSTATUS, 0, 0, 6))
_ = str(self._handle.controlRead(0x21, DFU_GETSTATUS, 0, 0, 6))
except Exception:
pass

View File

@ -29,7 +29,7 @@ import subprocess
import sys
import tempfile
import time
import traceback
#import traceback
import usb1
__version__ = "1.2"
@ -44,7 +44,7 @@ class FakePort(object):
@property
def baudrate(self):
return self._baudrate
return self.baudrate
@baudrate.setter
def baudrate(self, x):
@ -434,7 +434,7 @@ class BaseFirmwareImage(object):
def write_v1_header(self, f, segments):
f.write(struct.pack('<BBBBI', ESPROM.ESP_IMAGE_MAGIC, len(segments),
self.flash_mode, self.flash_size_freq, self.entrypoint))
self.flash_mode, self.flash_size_freq, self.entrypoint)) # pylint: disable=no-member
class ESPFirmwareImage(BaseFirmwareImage):
@ -864,7 +864,7 @@ def write_mem(esp, args):
def dump_mem(esp, args):
f = file(args.filename, 'wb')
f = open(args.filename, 'wb')
for i in range(args.size / 4):
d = esp.read_reg(args.address + (i * 4))
f.write(struct.pack('<I', d))
@ -944,7 +944,7 @@ def make_image(args):
if len(args.segfile) != len(args.segaddr):
raise FatalError('Number of specified files does not match number of specified addresses')
for (seg, addr) in zip(args.segfile, args.segaddr):
data = file(seg, 'rb').read()
data = open(seg, 'rb').read()
image.add_segment(addr, data)
image.entrypoint = args.entrypoint
image.save(args.output)
@ -1026,7 +1026,7 @@ def read_flash(esp, args):
t = time.time() - t
print('\rRead %d bytes at 0x%x in %.1f seconds (%.1f kbit/s)...'
% (len(data), args.address, t, len(data) / t * 8 / 1000))
file(args.filename, 'wb').write(data)
open(args.filename, 'wb').write(data)
def _verify_flash(flasher, args, flash_params=None):
@ -1235,7 +1235,7 @@ class AddrFilenamePairAction(argparse.Action):
for i in range(0,len(values),2):
try:
address = int(values[i],0)
except ValueError as e:
except ValueError:
raise argparse.ArgumentError(self,'Address "%s" must be a number' % values[i])
try:
argfile = open(values[i + 1], 'rb')

View File

@ -12,7 +12,6 @@ def ensure_st_up_to_date():
panda = None
panda_dfu = None
should_flash_recover = False
while 1:
# break on normal mode Panda

View File

@ -13,7 +13,7 @@
import codecs
import os
import re
from setuptools import setup, Extension
from setuptools import setup
here = os.path.abspath(os.path.dirname(__file__))

View File

@ -1,4 +1,3 @@
import os
from panda import build_st
def test_build_panda():

View File

@ -1,6 +1,4 @@
import os
from panda import Panda
from .helpers import panda_type_to_serial, test_white_and_grey, test_all_pandas, panda_connect_and_init
from .helpers import test_all_pandas, panda_connect_and_init
@test_all_pandas
@panda_connect_and_init

View File

@ -1,5 +1,3 @@
import os
import sys
import time
from panda import Panda
@ -180,6 +178,6 @@ def test_gmlan_bad_toggle(p):
@test_all_pandas
@panda_connect_and_init
def test_serial_debug(p):
junk = p.serial_read(Panda.SERIAL_DEBUG)
_ = p.serial_read(Panda.SERIAL_DEBUG) # junk
p.call_control_api(0xc0)
assert(p.serial_read(Panda.SERIAL_DEBUG).startswith(b"can "))

View File

@ -1,5 +1,3 @@
import os
import time
from panda import Panda
from .helpers import connect_wifi, test_white, test_all_pandas, panda_type_to_serial, panda_connect_and_init

View File

@ -1,8 +1,6 @@
import time
from panda import Panda
from .helpers import time_many_sends, connect_wifi, test_white, panda_type_to_serial
from nose.tools import timed, assert_equal, assert_less, assert_greater
@test_white
@panda_type_to_serial

View File

@ -3,7 +3,7 @@ import sys
import time
from .helpers import time_many_sends, connect_wifi, test_white, panda_type_to_serial
from panda import Panda, PandaWifiStreaming
from nose.tools import timed, assert_equal, assert_less, assert_greater
from nose.tools import assert_less, assert_greater
@test_white
@panda_type_to_serial

View File

@ -171,7 +171,7 @@ def test_black_loopback(panda0, panda1):
time.sleep(0.1)
# check for receive
cans_echo = send_panda.can_recv()
_ = send_panda.can_recv() # cans echo
cans_loop = recv_panda.can_recv()
loop_buses = []

View File

@ -2,13 +2,12 @@ import os
import sys
import time
import random
import binascii
import subprocess
import requests
import _thread
from functools import wraps
from panda import Panda
from nose.tools import timed, assert_equal, assert_less, assert_greater
from nose.tools import assert_equal
from parameterized import parameterized, param
SPEED_NORMAL = 500

View File

@ -11,9 +11,6 @@ import time
import random
import argparse
from hexdump import hexdump
from itertools import permutations
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
from panda import Panda
@ -33,7 +30,7 @@ def run_test(sleep_duration):
pandas[0] = Panda(pandas[0])
pandas[1] = Panda(pandas[1])
# find out the hardware types
# find out the hardware types
if not pandas[0].is_black() or not pandas[1].is_black():
print("Connect two black pandas to run this test!")
assert False
@ -66,14 +63,14 @@ def run_test(sleep_duration):
test_buses(pandas[0], pandas[1], test_array, sleep_duration)
print("***************** TESTING (1 --> 0) *****************")
test_buses(pandas[1], pandas[0], test_array, sleep_duration)
def test_buses(send_panda, recv_panda, test_array, sleep_duration):
for send_bus, send_obd, recv_obd, recv_buses in test_array:
send_panda.send_heartbeat()
recv_panda.send_heartbeat()
print("\nSend bus:", send_bus, " Send OBD:", send_obd, " Recv OBD:", recv_obd)
# set OBD on pandas
send_panda.set_gmlan(True if send_obd else None)
recv_panda.set_gmlan(True if recv_obd else None)
@ -92,7 +89,7 @@ def test_buses(send_panda, recv_panda, test_array, sleep_duration):
time.sleep(0.1)
# check for receive
cans_echo = send_panda.can_recv()
_ = send_panda.can_recv() # cans echo
cans_loop = recv_panda.can_recv()
loop_buses = []
@ -101,7 +98,7 @@ def test_buses(send_panda, recv_panda, test_array, sleep_duration):
loop_buses.append(loop[3])
if len(cans_loop) == 0:
print(" No loop")
# test loop buses
recv_buses.sort()
loop_buses.sort()

View File

@ -11,9 +11,6 @@ import time
import random
import argparse
from hexdump import hexdump
from itertools import permutations
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
from panda import Panda
@ -118,10 +115,10 @@ def test_buses(black_panda, other_panda, direction, test_array, sleep_duration):
# check for receive
if direction:
cans_echo = black_panda.can_recv()
_ = black_panda.can_recv() # can echo
cans_loop = other_panda.can_recv()
else:
cans_echo = other_panda.can_recv()
_ = other_panda.can_recv() # can echo
cans_loop = black_panda.can_recv()
loop_buses = []

View File

@ -11,9 +11,6 @@ import time
import random
import argparse
from hexdump import hexdump
from itertools import permutations
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
from panda import Panda
@ -42,7 +39,7 @@ def run_test(sleep_duration):
black_panda = None
other_panda = None
# find out which one is black
if pandas[0].is_black() and not pandas[1].is_black():
black_panda = pandas[0]
@ -69,7 +66,7 @@ def run_test(sleep_duration):
test_buses(black_panda, other_panda, True, [(0, False, [0]), (1, False, [1]), (2, False, [2]), (1, True, [0])], sleep_duration)
test_buses(black_panda, other_panda, False, [(0, False, [0]), (1, False, [1]), (2, False, [2]), (0, True, [0, 1])], sleep_duration)
counter += 1
runtime = time.time() - start_time
print("Number of cycles:", counter, "Non-zero bus errors:", nonzero_bus_errors, "Zero bus errors:", zero_bus_errors, "Content errors:", content_errors, "Runtime: ", runtime)
@ -80,7 +77,7 @@ def run_test(sleep_duration):
black_panda.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
time.sleep(1)
temp_start_time = time.time()
def test_buses(black_panda, other_panda, direction, test_array, sleep_duration):
global nonzero_bus_errors, zero_bus_errors, content_errors
@ -94,7 +91,7 @@ def test_buses(black_panda, other_panda, direction, test_array, sleep_duration):
black_panda.send_heartbeat()
other_panda.send_heartbeat()
print("\ntest can: ", send_bus, " OBD: ", obd)
# set OBD on black panda
black_panda.set_gmlan(True if obd else None)
@ -109,7 +106,7 @@ def test_buses(black_panda, other_panda, direction, test_array, sleep_duration):
other_panda.can_clear(recv_bus)
else:
black_panda.can_clear(recv_bus)
black_panda.can_recv()
other_panda.can_recv()
@ -124,10 +121,10 @@ def test_buses(black_panda, other_panda, direction, test_array, sleep_duration):
# check for receive
if direction:
cans_echo = black_panda.can_recv()
_ = black_panda.can_recv() # cans echo
cans_loop = other_panda.can_recv()
else:
cans_echo = other_panda.can_recv()
_ = other_panda.can_recv() # cans echo
cans_loop = black_panda.can_recv()
loop_buses = []
@ -141,7 +138,7 @@ def test_buses(black_panda, other_panda, direction, test_array, sleep_duration):
print(" No loop")
if not os.getenv("NOASSERT"):
assert False
# test loop buses
recv_buses.sort()
loop_buses.sort()

View File

@ -10,9 +10,6 @@ import time
import random
import argparse
from hexdump import hexdump
from itertools import permutations
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
from panda import Panda
@ -46,7 +43,7 @@ def run_test(sleep_duration):
black_panda = None
other_panda = None
if type0 == "\x03" and type1 != "\x03":
black_panda = pandas[0]
other_panda = pandas[1]
@ -86,15 +83,15 @@ def run_test(sleep_duration):
assert False
counter += 1
print("Number of cycles:", counter, "Open errors:", open_errors, "Closed errors:", closed_errors, "Content errors:", content_errors)
print("Number of cycles:", counter, "Open errors:", open_errors, "Closed errors:", closed_errors, "Content errors:", content_errors)
def test_buses(black_panda, other_panda, test_obj):
global content_errors
send_bus, obd, recv_buses = test_obj
black_panda.send_heartbeat()
other_panda.send_heartbeat()
# Set OBD on send panda
other_panda.set_gmlan(True if obd else None)
@ -103,7 +100,7 @@ def test_buses(black_panda, other_panda, test_obj):
for recv_bus in recv_buses:
black_panda.can_clear(recv_bus)
black_panda.can_recv()
other_panda.can_recv()
@ -114,7 +111,7 @@ def test_buses(black_panda, other_panda, test_obj):
time.sleep(0.05)
# check for receive
cans_echo = other_panda.can_recv()
_ = other_panda.can_recv() # can echo
cans_loop = black_panda.can_recv()
loop_buses = []
@ -122,7 +119,7 @@ def test_buses(black_panda, other_panda, test_obj):
if (loop[0] != at) or (loop[2] != st):
content_errors += 1
loop_buses.append(loop[3])
# test loop buses
recv_buses.sort()
loop_buses.sort()

View File

@ -109,9 +109,9 @@ class ELMCarSimulator():
print(" LIN Reply (%x)" % to_addr, binascii.hexlify(msg))
PHYS_ADDR = 0x80
FUNC_ADDR = 0xC0
#FUNC_ADDR = 0xC0
RECV = 0xF1
SEND = 0x33 # Car OBD Functional Address
#SEND = 0x33 # Car OBD Functional Address
headers = struct.pack("BBB", PHYS_ADDR | len(msg), RECV, to_addr)
if not self.__silent:
print(" Sending LIN", binascii.hexlify(headers+msg),
@ -172,7 +172,7 @@ class ELMCarSimulator():
while not self.__stop:
for address, ts, data, src in self.panda.can_recv():
if self.__on and src is 0 and len(data) == 8 and data[0] >= 2:
if self.__on and src == 0 and len(data) == 8 and data[0] >= 2:
if not self.__silent:
print("Processing CAN message", src, hex(address), binascii.hexlify(data))
self.__can_process_msg(data[1], data[2], address, ts, data, src)

View File

@ -1,16 +1,14 @@
import os
import sys
import time
import socket
import select
import pytest
import struct
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
from . import elm_car_simulator
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", ".."))
from panda import Panda
from panda.tests import elm_car_simulator
def elm_connect():
s = socket.create_connection(("192.168.0.10", 35000))
@ -234,35 +232,35 @@ def test_elm_send_lin_multiline_msg():
send_compare(s, b'0902\r', # headers OFF, Spaces ON
b"BUS INIT: OK\r"
"49 02 01 00 00 00 31 \r"
"49 02 02 44 34 47 50 \r"
"49 02 03 30 30 52 35 \r"
"49 02 04 35 42 31 32 \r"
"49 02 05 33 34 35 36 \r\r>")
b"49 02 01 00 00 00 31 \r"
b"49 02 02 44 34 47 50 \r"
b"49 02 03 30 30 52 35 \r"
b"49 02 04 35 42 31 32 \r"
b"49 02 05 33 34 35 36 \r\r>")
send_compare(s, b'ATS0\r', b'OK\r\r>') # Spaces OFF
send_compare(s, b'0902\r', # Headers OFF, Spaces OFF
b"49020100000031\r"
"49020244344750\r"
"49020330305235\r"
"49020435423132\r"
"49020533343536\r\r>")
b"49020244344750\r"
b"49020330305235\r"
b"49020435423132\r"
b"49020533343536\r\r>")
send_compare(s, b'ATH1\r', b'OK\r\r>') # Headers ON
send_compare(s, b'0902\r', # Headers ON, Spaces OFF
b"87F1104902010000003105\r"
"87F11049020244344750E4\r"
"87F11049020330305235BD\r"
"87F11049020435423132B1\r"
"87F11049020533343536AA\r\r>")
b"87F11049020244344750E4\r"
b"87F11049020330305235BD\r"
b"87F11049020435423132B1\r"
b"87F11049020533343536AA\r\r>")
send_compare(s, b'ATS1\r', b'OK\r\r>') # Spaces ON
send_compare(s, b'0902\r', # Headers ON, Spaces ON
b"87 F1 10 49 02 01 00 00 00 31 05 \r"
"87 F1 10 49 02 02 44 34 47 50 E4 \r"
"87 F1 10 49 02 03 30 30 52 35 BD \r"
"87 F1 10 49 02 04 35 42 31 32 B1 \r"
"87 F1 10 49 02 05 33 34 35 36 AA \r\r>")
b"87 F1 10 49 02 02 44 34 47 50 E4 \r"
b"87 F1 10 49 02 03 30 30 52 35 BD \r"
b"87 F1 10 49 02 04 35 42 31 32 B1 \r"
b"87 F1 10 49 02 05 33 34 35 36 AA \r\r>")
finally:
sim.stop()
sim.join()
@ -461,7 +459,7 @@ def test_elm_send_can_multimsg():
sim.can_add_extra_noise(b'\x03\x41\x0D\xFA', addr=0x7E9)# Inject message into the stream
send_compare(s, b'010D\r',
b"7E8 03 41 0D 53 \r"
"7E9 03 41 0D FA \r\r>") # Check it was ignored.
b"7E9 03 41 0D FA \r\r>") # Check it was ignored.
finally:
sim.stop()
sim.join()
@ -503,28 +501,28 @@ def test_elm_send_can_multiline_msg():
send_compare(s, b'0902\r', # headers OFF, Spaces ON
b"014 \r"
"0: 49 02 01 31 44 34 \r"
"1: 47 50 30 30 52 35 35 \r"
"2: 42 31 32 33 34 35 36 \r\r>")
b"0: 49 02 01 31 44 34 \r"
b"1: 47 50 30 30 52 35 35 \r"
b"2: 42 31 32 33 34 35 36 \r\r>")
send_compare(s, b'ATS0\r', b'OK\r\r>') # Spaces OFF
send_compare(s, b'0902\r', # Headers OFF, Spaces OFF
b"014\r"
"0:490201314434\r"
"1:47503030523535\r"
"2:42313233343536\r\r>")
b"0:490201314434\r"
b"1:47503030523535\r"
b"2:42313233343536\r\r>")
send_compare(s, b'ATH1\r', b'OK\r\r>') # Headers ON
send_compare(s, b'0902\r', # Headers ON, Spaces OFF
b"7E81014490201314434\r"
"7E82147503030523535\r"
"7E82242313233343536\r\r>")
b"7E82147503030523535\r"
b"7E82242313233343536\r\r>")
send_compare(s, b'ATS1\r', b'OK\r\r>') # Spaces ON
send_compare(s, b'0902\r', # Headers ON, Spaces ON
b"7E8 10 14 49 02 01 31 44 34 \r"
"7E8 21 47 50 30 30 52 35 35 \r"
"7E8 22 42 31 32 33 34 35 36 \r\r>")
b"7E8 21 47 50 30 30 52 35 35 \r"
b"7E8 22 42 31 32 33 34 35 36 \r\r>")
finally:
sim.stop()
sim.join()

View File

@ -1,17 +1,16 @@
#!/usr/bin/env python3
import time
from panda import Panda
p = Panda()
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
p.set_gmlan(bus=2)
#p.can_send(0xaaa, "\x00\x00", bus=3)
#p.can_send(0xaaa, b"\x00\x00", bus=3)
last_add = None
while 1:
ret = p.can_recv()
if len(ret) > 0:
add = ret[0][0]
if last_add is not None and add != last_add+1:
print("MISS %d %d" % (last_add, add))
if last_add is not None and add != last_add + 1:
print("MISS: ", last_add, add)
last_add = add
print(ret)

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python3
# pylint: skip-file
import numpy as np
import visa
import matplotlib.pyplot as plt

View File

@ -20,7 +20,7 @@ if __name__ == "__main__":
res = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
print(res)
found_bad_language = True
except subprocess.CalledProcessError as e:
except subprocess.CalledProcessError:
pass
if found_bad_language:
sys.exit("Failed: found bad language")

View File

@ -0,0 +1,585 @@
[MASTER]
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code
extension-pkg-whitelist=scipy
# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS
# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
ignore-patterns=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Use multiple processes to speed up Pylint.
jobs=4
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
# Pickle collected data for later comparisons.
persistent=yes
# Specify a configuration file.
#rcfile=
# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages
suggestion-mode=yes
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
confidence=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once).You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=print-statement,
parameter-unpacking,
unpacking-in-except,
old-raise-syntax,
backtick,
long-suffix,
old-ne-operator,
old-octal-literal,
import-star-module-level,
non-ascii-bytes-literal,
raw-checker-failed,
bad-inline-option,
locally-disabled,
locally-enabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
apply-builtin,
basestring-builtin,
buffer-builtin,
cmp-builtin,
coerce-builtin,
execfile-builtin,
file-builtin,
long-builtin,
raw_input-builtin,
reduce-builtin,
standarderror-builtin,
unicode-builtin,
xrange-builtin,
coerce-method,
delslice-method,
getslice-method,
setslice-method,
no-absolute-import,
old-division,
dict-iter-method,
dict-view-method,
next-method-called,
metaclass-assignment,
indexing-exception,
raising-string,
reload-builtin,
oct-method,
hex-method,
nonzero-method,
cmp-method,
input-builtin,
round-builtin,
intern-builtin,
unichr-builtin,
map-builtin-not-iterating,
zip-builtin-not-iterating,
range-builtin-not-iterating,
filter-builtin-not-iterating,
using-cmp-argument,
eq-without-hash,
div-method,
idiv-method,
rdiv-method,
exception-message-attribute,
invalid-str-codec,
sys-max-int,
bad-python3-import,
deprecated-string-function,
deprecated-str-translate-call,
deprecated-itertools-function,
deprecated-types-field,
next-method-defined,
dict-items-not-iterating,
dict-keys-not-iterating,
dict-values-not-iterating,
bad-indentation,
line-too-long,
missing-docstring,
multiple-statements,
bad-continuation,
invalid-name,
too-many-arguments,
too-many-locals,
superfluous-parens,
bad-whitespace,
too-many-instance-attributes,
wrong-import-position,
ungrouped-imports,
wrong-import-order,
protected-access,
trailing-whitespace,
too-many-branches,
too-few-public-methods,
too-many-statements,
trailing-newlines,
attribute-defined-outside-init,
too-many-return-statements,
too-many-public-methods,
unused-argument,
old-style-class,
no-init,
len-as-condition,
unneeded-not,
no-self-use,
multiple-imports,
no-else-return,
logging-not-lazy,
fixme,
redefined-outer-name,
unused-variable,
unsubscriptable-object,
expression-not-assigned,
too-many-boolean-expressions,
consider-using-ternary,
invalid-unary-operand-type,
relative-import,
deprecated-lambda
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=c-extension-no-member
[REPORTS]
# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details
#msg-template=
# Set the output format. Available formats are text, parseable, colorized, json
# and msvs (visual studio).You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=text
# Tells whether to display a full report or only the messages
reports=no
# Activate the evaluation score.
score=yes
[REFACTORING]
# Maximum number of nested blocks for function / method body
max-nested-blocks=5
# Complete name of functions that never returns. When checking for
# inconsistent-return-statements if a never returning function is called then
# it will be considered as an explicit return statement and no message will be
# printed.
never-returning-functions=optparse.Values,sys.exit
[LOGGING]
# Logging modules to check that the string format arguments are in logging
# function parameter format
logging-modules=logging
[SPELLING]
# Limits count of emitted suggestions for spelling mistakes
max-spelling-suggestions=4
# Spelling dictionary name. Available dictionaries: none. To make it working
# install python-enchant package.
spelling-dict=
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,
XXX,
TODO
[SIMILARITIES]
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=no
# Minimum lines number of a similarity.
min-similarity-lines=4
[TYPECHECK]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=capnp.* cereal.* pygame.* zmq.* setproctitle.* smbus2.* usb1.* serial.* cv2.*
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=flask setproctitle usb1 flask.ext.socketio smbus2 usb1.*
# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes
# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1
# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=
# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,
_cb
# A regular expression matching the name of dummy variables (i.e. expectedly
# not used).
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
# Argument names that match this expression will be ignored. Default to name
# with leading underscore
ignored-argument-names=_.*|^ignored_|^unused_
# Tells whether we should check for unused import in __init__ files.
init-import=no
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,past.builtins,future.builtins
[FORMAT]
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Maximum number of characters on a single line.
max-line-length=100
# Maximum number of lines in a module
max-module-lines=1000
# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,
dict-separator
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
[BASIC]
# Naming style matching correct argument names
argument-naming-style=snake_case
# Regular expression matching correct argument names. Overrides argument-
# naming-style
#argument-rgx=
# Naming style matching correct attribute names
attr-naming-style=snake_case
# Regular expression matching correct attribute names. Overrides attr-naming-
# style
#attr-rgx=
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,
bar,
baz,
toto,
tutu,
tata
# Naming style matching correct class attribute names
class-attribute-naming-style=any
# Regular expression matching correct class attribute names. Overrides class-
# attribute-naming-style
#class-attribute-rgx=
# Naming style matching correct class names
class-naming-style=PascalCase
# Regular expression matching correct class names. Overrides class-naming-style
#class-rgx=
# Naming style matching correct constant names
const-naming-style=UPPER_CASE
# Regular expression matching correct constant names. Overrides const-naming-
# style
#const-rgx=
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
# Naming style matching correct function names
function-naming-style=snake_case
# Regular expression matching correct function names. Overrides function-
# naming-style
#function-rgx=
# Good variable names which should always be accepted, separated by a comma
good-names=i,
j,
k,
ex,
Run,
_
# Include a hint for the correct naming format with invalid-name
include-naming-hint=no
# Naming style matching correct inline iteration names
inlinevar-naming-style=any
# Regular expression matching correct inline iteration names. Overrides
# inlinevar-naming-style
#inlinevar-rgx=
# Naming style matching correct method names
method-naming-style=snake_case
# Regular expression matching correct method names. Overrides method-naming-
# style
#method-rgx=
# Naming style matching correct module names
module-naming-style=snake_case
# Regular expression matching correct module names. Overrides module-naming-
# style
#module-rgx=
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_
# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties.
property-classes=abc.abstractproperty
# Naming style matching correct variable names
variable-naming-style=snake_case
# Regular expression matching correct variable names. Overrides variable-
# naming-style
#variable-rgx=
[DESIGN]
# Maximum number of arguments for function / method
max-args=5
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Maximum number of boolean expressions in a if statement
max-bool-expr=5
# Maximum number of branch for function / method body
max-branches=12
# Maximum number of locals for function / method body
max-locals=15
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of return / yield for function / method body
max-returns=6
# Maximum number of statements in function / method body
max-statements=50
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
[CLASSES]
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,
__new__,
setUp
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,
_fields,
_replace,
_source,
_make
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
[IMPORTS]
# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no
# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,
TERMIOS,
Bastion,
rexec
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=
# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=
# Force import order to recognize a module as part of a third party library.
known-third-party=enchant
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception

View File

@ -0,0 +1,19 @@
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y make python python-pip locales curl git zlib1g-dev libffi-dev bzip2 libssl-dev
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash
ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}"
RUN pyenv install 3.7.3
RUN pyenv global 3.7.3
RUN pyenv rehash
COPY tests/linter_python/requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . /panda

View File

@ -0,0 +1,8 @@
#!/usr/bin/env bash
RESULT=$(python3 -m flake8 --select=F $(find ../../ -type f | grep -v "/boardesp/" | grep -v "/cppcheck/" | grep "\.py$"))
if [[ $RESULT ]]; then
echo "Pyflakes found errors in the code. Please fix and try again"
echo "$RESULT"
exit 1
fi

View File

@ -0,0 +1,11 @@
#!/usr/bin/env bash
python3 -m pylint --disable=R,C,W $(find ../../ -type f | grep -v "/boardesp/" | grep -v "/cppcheck/" | grep "\.py$")
exit_status=$?
(( res = exit_status & 3 ))
if [[ $res != 0 ]]; then
echo "Pylint found errors in the code. Please fix and try again"
exit 1
fi

View File

@ -0,0 +1,12 @@
cffi==1.11.4
numpy==1.14.5
libusb1==1.6.6
requests
flake8==3.7.8
pylint==2.4.2
coverage
pycrypto==2.6.1
hexdump>=3.3
nose
tqdm>=4.14.0
parameterized

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3
import sys
import time
import struct
import argparse

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import unittest
import numpy as np
import libpandasafety_py
import libpandasafety_py # pylint: disable=import-error
from panda import Panda
MAX_RATE_UP = 2

View File

@ -1,9 +1,7 @@
#!/usr/bin/env python3
import csv
import glob
import unittest
import numpy as np
import libpandasafety_py
import libpandasafety_py # pylint: disable=import-error
from panda import Panda
MAX_RATE_UP = 3

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import unittest
import numpy as np
import libpandasafety_py
import libpandasafety_py # pylint: disable=import-error
from panda import Panda
MAX_RATE_UP = 7

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import unittest
import numpy as np
import libpandasafety_py
import libpandasafety_py # pylint: disable=import-error
from panda import Panda
MAX_BRAKE = 255

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python3
import unittest
import numpy as np
import libpandasafety_py
import libpandasafety_py # pylint: disable=import-error
from panda import Panda
MAX_BRAKE = 255

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import unittest
import numpy as np
import libpandasafety_py
import libpandasafety_py # pylint: disable=import-error
from panda import Panda
MAX_RATE_UP = 3

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import unittest
import numpy as np
import libpandasafety_py
import libpandasafety_py # pylint: disable=import-error
from panda import Panda
MAX_RATE_UP = 50

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import unittest
import numpy as np
import libpandasafety_py
import libpandasafety_py # pylint: disable=import-error
from panda import Panda
MAX_RATE_UP = 10

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import unittest
import numpy as np
import libpandasafety_py
import libpandasafety_py # pylint: disable=import-error
from panda import Panda
IPAS_OVERRIDE_THRESHOLD = 200
@ -233,8 +233,8 @@ class TestToyotaSafety(unittest.TestCase):
self.safety.safety_tx_hook(self._ipas_control_msg(a, 1))
self.safety.set_controls_allowed(1)
self.safety.safety_rx_hook(self._speed_msg(s))
max_delta_up = int(np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_V) * 2 / 3. + 1.)
max_delta_down = int(np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_VU) * 2 / 3. + 1.)
#max_delta_up = int(np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_V) * 2 / 3. + 1.)
#max_delta_down = int(np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_VU) * 2 / 3. + 1.)
self.safety.safety_rx_hook(self._angle_meas_msg(a))
self.assertTrue(self.safety.get_controls_allowed())
self.safety.safety_rx_hook(self._angle_meas_msg(a + 150))

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import unittest
import numpy as np
import libpandasafety_py
import libpandasafety_py # pylint: disable=import-error
from panda import Panda
MAX_RATE_UP = 10

View File

@ -2,12 +2,9 @@
import os
import sys
from panda import Panda
import panda.tests.safety.libpandasafety_py as libpandasafety_py
from panda.tests.safety_replay.helpers import is_steering_msg, get_steer_torque, \
set_desired_torque_last, package_can_msg, \
init_segment
from tools.lib.logreader import LogReader
from panda.tests.safety_replay.helpers import package_can_msg, init_segment
from tools.lib.logreader import LogReader # pylint: disable=import-error
# replay a drive to check for safety violations
def replay_drive(lr, safety_mode, param):

View File

@ -5,7 +5,7 @@ import requests
from panda import Panda
from replay_drive import replay_drive
from tools.lib.logreader import LogReader
from tools.lib.logreader import LogReader # pylint: disable=import-error
BASE_URL = "https://commadataci.blob.core.windows.net/openpilotci/"

View File

@ -2,7 +2,6 @@
import os
import sys
import time
import random
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
@ -21,4 +20,4 @@ if __name__ == "__main__":
st = get_test_string()[0:8]
bus = random.randint(0, 2)
p.can_send(at, st, bus)
#print("Sent message on bus: ", bus)
#print("Sent message on bus: ", bus)

View File

@ -25,7 +25,7 @@ if __name__ == "__main__":
# p_in.can_recv()
#sys.exit(0)
p_out.set_controls_allowed(True)
p_out.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
set_out, set_in = set(), set()

View File

@ -33,7 +33,7 @@ def run_test_w_pandas(pandas, sleep_duration):
print("H", h)
for hh in h:
hh.set_controls_allowed(True)
hh.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
# test both directions
for ho in permutations(list(range(len(h))), r=2):
@ -70,8 +70,8 @@ def run_test_w_pandas(pandas, sleep_duration):
time.sleep(sleep_duration)
# **** test can line loopback ****
# for bus, gmlan in [(0, None), (1, False), (2, False), (1, True), (2, True)]:
for bus, gmlan in [(0, None), (1, None)]:
# for bus, gmlan in [(0, None), (1, False), (2, False), (1, True), (2, True)]:
for bus, gmlan in [(0, None), (1, None)]:
print("\ntest can", bus)
# flush
cans_echo = panda0.can_recv()