Skip to content

Commit 9995c45

Browse files
authored
Merge pull request #57 from tekktrik/feature/add-typing
Add Type Hints
2 parents 28062a7 + c917de9 commit 9995c45

File tree

6 files changed

+82
-25
lines changed

6 files changed

+82
-25
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ repos:
2424
name: pylint (library code)
2525
types: [python]
2626
args:
27-
- --disable=consider-using-f-string
27+
- --disable=consider-using-f-string,duplicate-code
2828
exclude: "^(docs/|examples/|tests/|setup.py$)"
2929
- id: pylint
3030
name: pylint (example code)

adafruit_motor/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# SPDX-FileCopyrightText: 2021 Scott Shawcroft for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT

adafruit_motor/motor.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
* Author(s): Scott Shawcroft
2121
"""
2222

23+
try:
24+
from typing import Optional, Type
25+
from types import TracebackType
26+
from pwmio import PWMOut
27+
except ImportError:
28+
pass
29+
2330
__version__ = "0.0.0-auto.0"
2431
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Motor.git"
2532

@@ -48,22 +55,22 @@ class DCMotor:
4855
:param ~pwmio.PWMOut negative_pwm: The motor input that causes the motor to spin backwards
4956
when high and the other is low."""
5057

51-
def __init__(self, positive_pwm, negative_pwm):
58+
def __init__(self, positive_pwm: PWMOut, negative_pwm: PWMOut) -> None:
5259
self._positive = positive_pwm
5360
self._negative = negative_pwm
5461
self._throttle = None
5562
self._decay_mode = FAST_DECAY
5663

5764
@property
58-
def throttle(self):
65+
def throttle(self) -> Optional[float]:
5966
"""Motor speed, ranging from -1.0 (full speed reverse) to 1.0 (full speed forward),
6067
or ``None`` (controller off).
6168
If ``None``, both PWMs are turned full off. If ``0.0``, both PWMs are turned full on.
6269
"""
6370
return self._throttle
6471

6572
@throttle.setter
66-
def throttle(self, value):
73+
def throttle(self, value: Optional[float]) -> None:
6774
if value is not None and (value > 1.0 or value < -1.0):
6875
raise ValueError("Throttle must be None or between -1.0 and +1.0")
6976
self._throttle = value
@@ -91,23 +98,28 @@ def throttle(self, value):
9198
self._negative.duty_cycle = 0
9299

93100
@property
94-
def decay_mode(self):
101+
def decay_mode(self) -> int:
95102
"""Motor controller recirculation current decay mode. A value of ``motor.FAST_DECAY``
96103
sets the motor controller to the default fast recirculation current decay mode
97104
(coasting); ``motor.SLOW_DECAY`` sets slow decay (braking) mode."""
98105
return self._decay_mode
99106

100107
@decay_mode.setter
101-
def decay_mode(self, mode=FAST_DECAY):
108+
def decay_mode(self, mode: int = FAST_DECAY) -> None:
102109
if mode in (FAST_DECAY, SLOW_DECAY):
103110
self._decay_mode = mode
104111
else:
105112
raise ValueError(
106113
"Decay mode value must be either motor.FAST_DECAY or motor.SLOW_DECAY"
107114
)
108115

109-
def __enter__(self):
116+
def __enter__(self) -> "DCMotor":
110117
return self
111118

112-
def __exit__(self, exception_type, exception_value, traceback):
119+
def __exit__(
120+
self,
121+
exception_type: Optional[Type[type]],
122+
exception_value: Optional[BaseException],
123+
traceback: Optional[TracebackType],
124+
) -> None:
113125
self.throttle = None

adafruit_motor/servo.py

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212
* Author(s): Scott Shawcroft
1313
"""
1414

15+
try:
16+
from typing import Optional, Type
17+
from types import TracebackType
18+
from pwmio import PWMOut
19+
except ImportError:
20+
pass
21+
22+
1523
__version__ = "0.0.0-auto.0"
1624
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Motor.git"
1725

@@ -24,18 +32,22 @@ class _BaseServo: # pylint: disable-msg=too-few-public-methods
2432
:param int min_pulse: The minimum pulse length of the servo in microseconds.
2533
:param int max_pulse: The maximum pulse length of the servo in microseconds."""
2634

27-
def __init__(self, pwm_out, *, min_pulse=750, max_pulse=2250):
35+
def __init__(
36+
self, pwm_out: PWMOut, *, min_pulse: int = 750, max_pulse: int = 2250
37+
) -> None:
2838
self._pwm_out = pwm_out
2939
self.set_pulse_width_range(min_pulse, max_pulse)
3040

31-
def set_pulse_width_range(self, min_pulse=750, max_pulse=2250):
41+
def set_pulse_width_range(
42+
self, min_pulse: int = 750, max_pulse: int = 2250
43+
) -> None:
3244
"""Change min and max pulse widths."""
3345
self._min_duty = int((min_pulse * self._pwm_out.frequency) / 1000000 * 0xFFFF)
3446
max_duty = (max_pulse * self._pwm_out.frequency) / 1000000 * 0xFFFF
3547
self._duty_range = int(max_duty - self._min_duty)
3648

3749
@property
38-
def fraction(self):
50+
def fraction(self) -> Optional[float]:
3951
"""Pulse width expressed as fraction between 0.0 (`min_pulse`) and 1.0 (`max_pulse`).
4052
For conventional servos, corresponds to the servo position as a fraction
4153
of the actuation range. Is None when servo is diabled (pulsewidth of 0ms).
@@ -45,7 +57,7 @@ def fraction(self):
4557
return (self._pwm_out.duty_cycle - self._min_duty) / self._duty_range
4658

4759
@fraction.setter
48-
def fraction(self, value):
60+
def fraction(self, value: Optional[float]) -> None:
4961
if value is None:
5062
self._pwm_out.duty_cycle = 0 # disable the motor
5163
return
@@ -85,22 +97,29 @@ class Servo(_BaseServo):
8597
Test carefully to find the safe minimum and maximum.
8698
"""
8799

88-
def __init__(self, pwm_out, *, actuation_range=180, min_pulse=750, max_pulse=2250):
100+
def __init__(
101+
self,
102+
pwm_out: PWMOut,
103+
*,
104+
actuation_range: int = 180,
105+
min_pulse: int = 750,
106+
max_pulse: int = 2250
107+
) -> None:
89108
super().__init__(pwm_out, min_pulse=min_pulse, max_pulse=max_pulse)
90109
self.actuation_range = actuation_range
91110
"""The physical range of motion of the servo in degrees."""
92111
self._pwm = pwm_out
93112

94113
@property
95-
def angle(self):
114+
def angle(self) -> Optional[float]:
96115
"""The servo angle in degrees. Must be in the range ``0`` to ``actuation_range``.
97116
Is None when servo is disabled."""
98117
if self.fraction is None: # special case for disabled servos
99118
return None
100119
return self.actuation_range * self.fraction
101120

102121
@angle.setter
103-
def angle(self, new_angle):
122+
def angle(self, new_angle: Optional[int]) -> None:
104123
if new_angle is None: # disable the servo by sending 0 signal
105124
self.fraction = None
106125
return
@@ -116,22 +135,27 @@ class ContinuousServo(_BaseServo):
116135
:param int max_pulse: The maximum pulse width of the servo in microseconds."""
117136

118137
@property
119-
def throttle(self):
138+
def throttle(self) -> float:
120139
"""How much power is being delivered to the motor. Values range from ``-1.0`` (full
121140
throttle reverse) to ``1.0`` (full throttle forwards.) ``0`` will stop the motor from
122141
spinning."""
123142
return self.fraction * 2 - 1
124143

125144
@throttle.setter
126-
def throttle(self, value):
145+
def throttle(self, value: float) -> None:
127146
if value > 1.0 or value < -1.0:
128147
raise ValueError("Throttle must be between -1.0 and 1.0")
129148
if value is None:
130149
raise ValueError("Continuous servos cannot spin freely")
131150
self.fraction = (value + 1) / 2
132151

133-
def __enter__(self):
152+
def __enter__(self) -> "ContinuousServo":
134153
return self
135154

136-
def __exit__(self, exception_type, exception_value, traceback):
155+
def __exit__(
156+
self,
157+
exception_type: Optional[Type[type]],
158+
exception_value: Optional[BaseException],
159+
traceback: Optional[TracebackType],
160+
) -> None:
137161
self.throttle = 0

adafruit_motor/stepper.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818

1919
from micropython import const
2020

21+
try:
22+
from typing import Union, Optional
23+
from pwmio import PWMOut
24+
from digitalio import DigitalInOut
25+
except ImportError:
26+
pass
27+
2128
__version__ = "0.0.0-auto.0"
2229
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Motor.git"
2330

@@ -79,7 +86,15 @@ class StepperMotor:
7986
:param microsteps: set to `None`
8087
"""
8188

82-
def __init__(self, ain1, ain2, bin1, bin2, *, microsteps=16):
89+
def __init__(
90+
self,
91+
ain1: Union[PWMOut, DigitalInOut],
92+
ain2: Union[PWMOut, DigitalInOut],
93+
bin1: Union[PWMOut, DigitalInOut],
94+
bin2: Union[PWMOut, DigitalInOut],
95+
*,
96+
microsteps: Optional[int] = 16
97+
) -> None:
8398
if microsteps is None:
8499
#
85100
# Digital IO Pins
@@ -107,7 +122,7 @@ def __init__(self, ain1, ain2, bin1, bin2, *, microsteps=16):
107122
self._microsteps = microsteps
108123
self._update_coils()
109124

110-
def _update_coils(self, *, microstepping=False):
125+
def _update_coils(self, *, microstepping: bool = False) -> None:
111126
if self._microsteps is None:
112127
#
113128
# Digital IO Pins
@@ -144,7 +159,7 @@ def _update_coils(self, *, microstepping=False):
144159
for i in range(4):
145160
self._coil[i].duty_cycle = duty_cycles[i]
146161

147-
def release(self):
162+
def release(self) -> None:
148163
"""Releases all the coils so the motor can free spin, also won't use any power"""
149164
# De-energize coils:
150165
for coil in self._coil:
@@ -153,9 +168,9 @@ def release(self):
153168
else:
154169
coil.duty_cycle = 0
155170

156-
def onestep(
157-
self, *, direction=FORWARD, style=SINGLE
158-
): # pylint: disable=too-many-branches
171+
def onestep( # pylint: disable=too-many-branches
172+
self, *, direction: int = FORWARD, style: int = SINGLE
173+
) -> None:
159174
"""Performs one step of a particular style. The actual rotation amount will vary by style.
160175
`SINGLE` and `DOUBLE` will normal cause a full step rotation. `INTERLEAVE` will normally
161176
do a half step rotation. `MICROSTEP` will perform the smallest configured step.

docs/conf.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
copyright = "2017 Scott Shawcroft"
4444
author = "Scott Shawcroft"
4545

46+
# Ignore imports of these modules, which sphinx will not know about.
47+
autodoc_mock_imports = ["pwmio"]
48+
4649
# The version info for the project you're documenting, acts as replacement for
4750
# |version| and |release|, also used in various other places throughout the
4851
# built documents.

0 commit comments

Comments
 (0)