Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace asserts with ValueError or TypeError #709

Open
wants to merge 3 commits into
base: ev3dev-stretch
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ python-ev3dev2 (2.1.0) UNRELEASED; urgency=medium
[Daniel Walton]
* RPyC update docs and make it easier to use
* use double backticks consistently in docstrings
* replace asserts with ValueError or TypeError

[Matěj Volf]
* LED animation fix duration None
Expand Down
3 changes: 3 additions & 0 deletions ev3dev2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ def library_load_warning_message(library_name, dependent_class):
class DeviceNotFound(Exception):
pass

class ThreadNotRunning(Exception):
pass

# -----------------------------------------------------------------------------
# Define the base class from which all other ev3dev classes are defined.

Expand Down
15 changes: 8 additions & 7 deletions ev3dev2/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,8 @@ def text_pixels(self, text, clear_screen=True, x=0, y=0, text_color='black', fon

if font is not None:
if isinstance(font, str):
assert font in fonts.available(), "%s is an invalid font" % font
if font not in fonts.available():
raise ValueError("%s is an invalid font" % font)
font = fonts.load(font)
return self.draw.text((x, y), text, fill=text_color, font=font)
else:
Expand Down Expand Up @@ -423,13 +424,13 @@ def text_grid(self, text, clear_screen=True, x=0, y=0, text_color='black', font=

"""

assert 0 <= x < Display.GRID_COLUMNS,\
"grid columns must be between 0 and %d, %d was requested" %\
((Display.GRID_COLUMNS - 1, x))
if not 0 <= x < Display.GRID_COLUMNS:
raise ValueError("grid columns must be between 0 and %d, %d was requested" %\
(Display.GRID_COLUMNS - 1, x))

assert 0 <= y < Display.GRID_ROWS,\
"grid rows must be between 0 and %d, %d was requested" %\
((Display.GRID_ROWS - 1), y)
if not 0 <= y < Display.GRID_ROWS:
raise ValueError("grid rows must be between 0 and %d, %d was requested" %\
(Display.GRID_ROWS - 1, y))

return self.text_pixels(text, clear_screen,
x * Display.GRID_COLUMN_PIXELS,
Expand Down
18 changes: 9 additions & 9 deletions ev3dev2/led.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,14 +313,14 @@ def set_color(self, group, color, pct=1):

color_tuple = color
if isinstance(color, str):
assert color in self.led_colors, \
"%s is an invalid LED color, valid choices are %s" % \
(color, ', '.join(self.led_colors.keys()))
if color not in self.led_colors:
raise ValueError("%s is an invalid LED color, valid choices are %s" % \
(color, ', '.join(self.led_colors.keys())))
color_tuple = self.led_colors[color]

assert group in self.led_groups, \
"%s is an invalid LED group, valid choices are %s" % \
(group, ', '.join(self.led_groups.keys()))
if group not in self.led_groups:
raise ValueError("%s is an invalid LED group, valid choices are %s" % \
(group, ', '.join(self.led_groups.keys())))

for led, value in zip(self.led_groups[group], color_tuple):
led.brightness_pct = value * pct
Expand All @@ -339,9 +339,9 @@ def set(self, group, **kwargs):
if not self.leds:
return

assert group in self.led_groups, \
"%s is an invalid LED group, valid choices are %s" % \
(group, ', '.join(self.led_groups.keys()))
if group not in self.led_groups:
raise ValueError("%s is an invalid LED group, valid choices are %s" % \
(group, ', '.join(self.led_groups.keys())))

for led in self.led_groups[group]:
for k in kwargs:
Expand Down
70 changes: 40 additions & 30 deletions ev3dev2/motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

from logging import getLogger
from os.path import abspath
from ev3dev2 import get_current_platform, Device, list_device_names
from ev3dev2 import get_current_platform, Device, list_device_names, ThreadNotRunning
from ev3dev2.stopwatch import StopWatch

log = getLogger(__name__)
Expand Down Expand Up @@ -112,16 +112,17 @@ class SpeedPercent(SpeedValue):
"""

def __init__(self, percent):
assert -100 <= percent <= 100,\
"{} is an invalid percentage, must be between -100 and 100 (inclusive)".format(percent)
if not -100 <= percent <= 100:
raise ValueError("{} is an invalid percentage, must be between -100 and 100 (inclusive)".format(percent))

self.percent = percent

def __str__(self):
return str(self.percent) + "%"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return SpeedPercent(self.percent * other)

def to_native_units(self, motor):
Expand All @@ -143,7 +144,8 @@ def __str__(self):
return "{:.2f}".format(self.native_counts) + " counts/sec"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return SpeedNativeUnits(self.native_counts * other)

def to_native_units(self, motor=None):
Expand All @@ -165,16 +167,17 @@ def __str__(self):
return str(self.rotations_per_second) + " rot/sec"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return SpeedRPS(self.rotations_per_second * other)

def to_native_units(self, motor):
"""
Return the native speed measurement required to achieve desired rotations-per-second
"""
assert abs(self.rotations_per_second) <= motor.max_rps,\
"invalid rotations-per-second: {} max RPS is {}, {} was requested".format(
motor, motor.max_rps, self.rotations_per_second)
if abs(self.rotations_per_second) > motor.max_rps:
raise ValueError("invalid rotations-per-second: {} max RPS is {}, {} was requested".format(
motor, motor.max_rps, self.rotations_per_second))
return self.rotations_per_second/motor.max_rps * motor.max_speed


Expand All @@ -190,16 +193,17 @@ def __str__(self):
return str(self.rotations_per_minute) + " rot/min"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return SpeedRPM(self.rotations_per_minute * other)

def to_native_units(self, motor):
"""
Return the native speed measurement required to achieve desired rotations-per-minute
"""
assert abs(self.rotations_per_minute) <= motor.max_rpm,\
"invalid rotations-per-minute: {} max RPM is {}, {} was requested".format(
motor, motor.max_rpm, self.rotations_per_minute)
if abs(self.rotations_per_minute) > motor.max_rpm:
raise ValueError("invalid rotations-per-minute: {} max RPM is {}, {} was requested".format(
motor, motor.max_rpm, self.rotations_per_minute))
return self.rotations_per_minute/motor.max_rpm * motor.max_speed


Expand All @@ -215,16 +219,17 @@ def __str__(self):
return str(self.degrees_per_second) + " deg/sec"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return SpeedDPS(self.degrees_per_second * other)

def to_native_units(self, motor):
"""
Return the native speed measurement required to achieve desired degrees-per-second
"""
assert abs(self.degrees_per_second) <= motor.max_dps,\
"invalid degrees-per-second: {} max DPS is {}, {} was requested".format(
motor, motor.max_dps, self.degrees_per_second)
if abs(self.degrees_per_second) > motor.max_dps:
raise ValueError("invalid degrees-per-second: {} max DPS is {}, {} was requested".format(
motor, motor.max_dps, self.degrees_per_second))
return self.degrees_per_second/motor.max_dps * motor.max_speed


Expand All @@ -240,16 +245,17 @@ def __str__(self):
return str(self.degrees_per_minute) + " deg/min"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return SpeedDPM(self.degrees_per_minute * other)

def to_native_units(self, motor):
"""
Return the native speed measurement required to achieve desired degrees-per-minute
"""
assert abs(self.degrees_per_minute) <= motor.max_dpm,\
"invalid degrees-per-minute: {} max DPM is {}, {} was requested".format(
motor, motor.max_dpm, self.degrees_per_minute)
if abs(self.degrees_per_minute) > motor.max_dpm:
raise ValueError("invalid degrees-per-minute: {} max DPM is {}, {} was requested".format(
motor, motor.max_dpm, self.degrees_per_minute))
return self.degrees_per_minute/motor.max_dpm * motor.max_speed


Expand Down Expand Up @@ -949,8 +955,9 @@ def _speed_native_units(self, speed, label=None):

# If speed is not a SpeedValue object we treat it as a percentage
if not isinstance(speed, SpeedValue):
assert -100 <= speed <= 100,\
"{}{} is an invalid speed percentage, must be between -100 and 100 (inclusive)".format("" if label is None else (label + ": ") , speed)
if not -100 <= speed <= 100:
raise ValueError("{}{} is an invalid speed percentage, must be between -100 and 100 (inclusive)".format(
"" if label is None else (label + ": ") , speed))
speed = SpeedPercent(speed)

return speed.to_native_units(self)
Expand Down Expand Up @@ -1666,8 +1673,8 @@ def set_args(self, **kwargs):
def set_polarity(self, polarity, motors=None):
valid_choices = (LargeMotor.POLARITY_NORMAL, LargeMotor.POLARITY_INVERSED)

assert polarity in valid_choices,\
"%s is an invalid polarity choice, must be %s" % (polarity, ', '.join(valid_choices))
if polarity not in valid_choices:
raise ValueError("%s is an invalid polarity choice, must be %s" % (polarity, ', '.join(valid_choices)))
motors = motors if motors is not None else self.motors.values()

for motor in motors:
Expand Down Expand Up @@ -2203,7 +2210,8 @@ def follow_gyro_angle(self,
speed_native_units = speed.to_native_units(self.left_motor)
MAX_SPEED = SpeedNativeUnits(self.max_speed)

assert speed_native_units <= MAX_SPEED, "Speed exceeds the max speed of the motors"
if speed_native_units > MAX_SPEED:
raise ValueError("Speed exceeds the max speed of the motors")

while follow_for(self, **kwargs):
current_angle = self._gyro.angle
Expand Down Expand Up @@ -2371,8 +2379,8 @@ def get_speed_steering(self, steering, speed):
automatically.
"""

assert steering >= -100 and steering <= 100,\
"{} is an invalid steering, must be between -100 and 100 (inclusive)".format(steering)
if steering < -100 or steering > 100:
raise ValueError("{} is an invalid steering, must be between -100 and 100 (inclusive)".format(steering))

# We don't have a good way to make this generic for the pair... so we
# assume that the left motor's speed stats are the same as the right
Expand Down Expand Up @@ -2690,7 +2698,8 @@ def turn_to_angle(self, speed, angle_target_degrees, brake=True, block=True):
"""
Rotate in place to ``angle_target_degrees`` at ``speed``
"""
assert self.odometry_thread_id, "odometry_start() must be called to track robot coordinates"
if not self.odometry_thread_id:
raise ThreadNotRunning("odometry_start() must be called to track robot coordinates")

# Make both target and current angles positive numbers between 0 and 360
if angle_target_degrees < 0:
Expand Down Expand Up @@ -2729,7 +2738,8 @@ def on_to_coordinates(self, speed, x_target_mm, y_target_mm, brake=True, block=T
"""
Drive to (``x_target_mm``, ``y_target_mm``) coordinates at ``speed``
"""
assert self.odometry_thread_id, "odometry_start() must be called to track robot coordinates"
if not self.odometry_thread_id:
raise ThreadNotRunning("odometry_start() must be called to track robot coordinates")

# stop moving
self.off(brake='hold')
Expand Down
8 changes: 4 additions & 4 deletions ev3dev2/sensor/lego.py
Original file line number Diff line number Diff line change
Expand Up @@ -643,9 +643,8 @@ def wait_until_angle_changed_by(self, delta, direction_sensitive=False):
If ``direction_sensitive`` is False (default) we will wait until angle has changed
by ``delta`` in either direction.
"""
assert self.mode in (self.MODE_GYRO_G_A, self.MODE_GYRO_ANG,
self.MODE_TILT_ANG),\
'Gyro mode should be MODE_GYRO_ANG, MODE_GYRO_G_A or MODE_TILT_ANG'
if self.mode not in (self.MODE_GYRO_G_A, self.MODE_GYRO_ANG, self.MODE_TILT_ANG):
raise ValueError("{} mode is {}, it should be MODE_GYRO_ANG, MODE_GYRO_G_A or MODE_TILT_ANG".format(self, self.mode))
start_angle = self.value(0)

if direction_sensitive:
Expand Down Expand Up @@ -775,7 +774,8 @@ def __init__(self, address=None, name_pattern=SYSTEM_DEVICE_NAME_CONVENTION, nam
super(InfraredSensor, self).__init__(address, name_pattern, name_exact, driver_name='lego-ev3-ir', **kwargs)

def _normalize_channel(self, channel):
assert channel >= 1 and channel <= 4, "channel is %s, it must be 1, 2, 3, or 4" % channel
if channel < 1 or channel > 4:
raise ValueError("channel is %s, it must be 1, 2, 3, or 4" % channel)
channel = max(1, min(4, channel)) - 1
return channel

Expand Down
4 changes: 2 additions & 2 deletions ev3dev2/sound.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ class Sound(object):
)

def _validate_play_type(self, play_type):
assert play_type in self.PLAY_TYPES, \
"Invalid play_type %s, must be one of %s" % (play_type, ','.join(str(t) for t in self.PLAY_TYPES))
if play_type not in self.PLAY_TYPES:
raise ValueError("Invalid play_type %s, must be one of %s" % (play_type, ','.join(str(t) for t in self.PLAY_TYPES)))

def _audio_command(self, command, play_type):
if is_micropython():
Expand Down
24 changes: 16 additions & 8 deletions ev3dev2/unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ def __str__(self):
return str(self.millimeters) + "mm"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return DistanceMillimeters(self.millimeters * other)

@property
Expand All @@ -82,7 +83,8 @@ def __str__(self):
return str(self.centimeters) + "cm"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return DistanceCentimeters(self.centimeters * other)

@property
Expand All @@ -102,7 +104,8 @@ def __str__(self):
return str(self.decimeters) + "dm"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return DistanceDecimeters(self.decimeters * other)

@property
Expand All @@ -122,7 +125,8 @@ def __str__(self):
return str(self.meters) + "m"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return DistanceMeters(self.meters * other)

@property
Expand All @@ -142,7 +146,8 @@ def __str__(self):
return str(self.inches) + "in"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return DistanceInches(self.inches * other)

@property
Expand All @@ -162,7 +167,8 @@ def __str__(self):
return str(self.feet) + "ft"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return DistanceFeet(self.feet * other)

@property
Expand All @@ -182,7 +188,8 @@ def __str__(self):
return str(self.yards) + "yd"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return DistanceYards(self.yards * other)

@property
Expand All @@ -202,7 +209,8 @@ def __str__(self):
return str(self.studs) + "stud"

def __mul__(self, other):
assert isinstance(other, (float, int)), "{} can only be multiplied by an int or float".format(self)
if not isinstance(other, (float, int)):
raise TypeError("{} can only be multiplied by an int or float, not {}".format(self, type(other)))
return DistanceStuds(self.studs * other)

@property
Expand Down