Skip to content

Annotation fixes in circuitplayground_base and bluefruit.py #118

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

Merged
merged 13 commits into from
Aug 8, 2022
Merged
Show file tree
Hide file tree
Changes from 5 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
14 changes: 9 additions & 5 deletions adafruit_circuitplayground/bluefruit.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
* `Circuit Playground Bluefruit <https://www.adafruit.com/product/4333>`_

"""
try:
import typing # pylint: disable=unused-import
except ImportError:
pass

import array
import math
Expand All @@ -38,7 +42,7 @@ class Bluefruit(CircuitPlaygroundBase):

_audio_out = audiopwmio.PWMAudioOut

def __init__(self):
def __init__(self) -> None:
# Only create the cpb module member when we aren't being imported by Sphinx
if (
"__module__" in dir(digitalio.DigitalInOut)
Expand All @@ -60,7 +64,7 @@ def __init__(self):
self._samples = None

@staticmethod
def _normalized_rms(values):
def _normalized_rms(values) -> float:
mean_values = int(sum(values) / len(values))
return math.sqrt(
sum(
Expand All @@ -71,7 +75,7 @@ def _normalized_rms(values):
)

@property
def sound_level(self):
def sound_level(self) -> float:
"""Obtain the sound level from the microphone (sound sensor).

.. image :: ../docs/_static/microphone.jpg
Expand All @@ -92,7 +96,7 @@ def sound_level(self):
self._mic.record(self._samples, len(self._samples))
return self._normalized_rms(self._samples)

def loud_sound(self, sound_threshold=200):
def loud_sound(self, sound_threshold: int = 200) -> bool:
"""Utilise a loud sound as an input.

:param int sound_threshold: Threshold sound level must exceed to return true (Default: 200)
Expand Down Expand Up @@ -134,7 +138,7 @@ def loud_sound(self, sound_threshold=200):

return self.sound_level > sound_threshold

def play_mp3(self, file_name):
def play_mp3(self, file_name: str) -> None:
"""Play a .mp3 file using the onboard speaker.

:param file_name: The name of your .mp3 file in quotation marks including .mp3
Expand Down
92 changes: 50 additions & 42 deletions adafruit_circuitplayground/circuit_playground_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# pylint: disable=too-many-instance-attributes, too-many-lines

"""
`adafruit_circuitplayground.circuit_playground_base`
'adafruit_circuitplayground.circuit_playground_base'
Copy link
Member

@tekktrik tekktrik Jul 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These uses of ticks (`) are used intentionally for formatting, you should change this and the other ones below back to that so the formatting and links will show appropriately.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like these should be reverted back to ticks (`)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I did? tick to the left of #1 ?

Copy link
Member

@tekktrik tekktrik Jul 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it should be reverted back to:

Suggested change
'adafruit_circuitplayground.circuit_playground_base'
`adafruit_circuitplayground.circuit_playground_base`

====================================================

CircuitPython base class for Circuit Playground.
Expand All @@ -33,6 +33,12 @@
import neopixel
import touchio

try:
from typing import Literal, Optional, Iterator
Copy link
Member

@tekktrik tekktrik Jul 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always forget that Literal wasn't added to typing until Python 3.8. Since we support Python 3.7 as the minimum version, which means for development as well, let's import it Literal from typing_extensions instead. You can remove the Literal import here and add this as a line below:

    from typing_extensions import Literal

Make sure you add typing-extensions~=4.0 as a dependency in setup.py and requirements.txt to ensure it gets downloaded as well. Let me know if you need help doing that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clue about setup.py would be nice. All I see is setup.py.disabled. Is that because of Pycharm?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll need to update this branch to the latest main branch, that file has been deleted and since replaced with setup.py in a recent pull request.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, got that update now. is it added as just a simple import in setup.py? or some other way?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You add it to the list of install_requires in setup()

    install_requires=[
        "adafruit-circuitpython-lis3dh",
        "adafruit-circuitpython-thermistor",
        "adafruit-circuitpython-neopixel",
        "typing-extensions~=4.0",
    ],

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it threw a number error after adding this line, and went back to just dying when I removed "~=4.0". All pylint is showing me locally is that it does not like the uname function of os, in addition to the line ending errors.

Not sure if you can see what specifically is choking it here.....

from microcontroller import Pin
except ImportError:
pass

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground.git"

Expand All @@ -41,12 +47,12 @@ class Photocell:
"""Simple driver for analog photocell on the Circuit Playground Express and Bluefruit."""

# pylint: disable=too-few-public-methods
def __init__(self, pin):
def __init__(self, pin: Pin) -> None:
self._photocell = analogio.AnalogIn(pin)

# TODO(tannewt): Calibrate this against another calibrated sensor.
@property
def light(self):
def light(self) -> int:
"""Light level."""
return self._photocell.value * 330 // (2**16)

Expand All @@ -58,7 +64,7 @@ class CircuitPlaygroundBase: # pylint: disable=too-many-public-methods
SINE_WAVE = 0
SQUARE_WAVE = 1

def __init__(self):
def __init__(self) -> None:
# Define switch:
self._switch = digitalio.DigitalInOut(board.SLIDE_SWITCH)
self._switch.switch_to_input(pull=digitalio.Pull.UP)
Expand Down Expand Up @@ -117,7 +123,7 @@ def __init__(self):
self._b = None

@property
def detect_taps(self):
def detect_taps(self) -> Literal[1, 2]:
"""Configure what type of tap is detected by ``cp.tapped``. Use ``1`` for single-tap
detection and ``2`` for double-tap detection. This does nothing without ``cp.tapped``.

Expand All @@ -138,7 +144,7 @@ def detect_taps(self):
return self._detect_taps

@staticmethod
def _default_tap_threshold(tap):
def _default_tap_threshold(tap: Literal[1, 2]) -> int:
if (
"nRF52840" in os.uname().machine
): # If we're on a CPB, use a higher tap threshold
Expand All @@ -148,7 +154,7 @@ def _default_tap_threshold(tap):
return 90 if tap == 1 else 60

@detect_taps.setter
def detect_taps(self, value):
def detect_taps(self, value: Literal[1, 2]) -> None:
self._detect_taps = value
if value == 1:
self._lis3dh.set_tap(
Expand All @@ -169,13 +175,13 @@ def detect_taps(self, value):

def configure_tap( # pylint: disable-msg=too-many-arguments
self,
tap,
accel_range=adafruit_lis3dh.RANGE_8_G,
threshold=None,
time_limit=None,
time_latency=50,
time_window=255,
):
tap: Literal[0, 1, 2],
accel_range: Literal[0, 1, 2, 3] = adafruit_lis3dh.RANGE_8_G,
threshold: Optional[int] = None,
time_limit: Optional[int] = None,
time_latency: int = 50,
time_window: int = 255,
) -> None:
"""Granular configuration of tap parameters. Expose the power of the
adafruit_lis3dh module.

Expand Down Expand Up @@ -245,7 +251,7 @@ def configure_tap( # pylint: disable-msg=too-many-arguments
)

@property
def tapped(self):
def tapped(self) -> bool:
"""True once after a detecting a tap. Requires ``cp.detect_taps``.

.. image :: ../docs/_static/accelerometer.jpg
Expand Down Expand Up @@ -297,7 +303,7 @@ def tapped(self):
return self._lis3dh.tapped

@property
def acceleration(self):
def acceleration(self) -> adafruit_lis3dh.AccelerationTuple:
"""Obtain data from the x, y and z axes.

.. image :: ../docs/_static/accelerometer.jpg
Expand All @@ -318,7 +324,7 @@ def acceleration(self):
"""
return self._lis3dh.acceleration

def shake(self, shake_threshold=30):
def shake(self, shake_threshold: int = 30) -> bool:
"""Detect when device is shaken.

:param int shake_threshold: The threshold shake must exceed to return true (Default: 30)
Expand Down Expand Up @@ -352,7 +358,7 @@ def shake(self, shake_threshold=30):
"""
return self._lis3dh.shake(shake_threshold=shake_threshold)

def _touch(self, i):
def _touch(self, i) -> bool:
if not isinstance(self._touches[i], touchio.TouchIn):
# First time referenced. Get the pin from the slot for this touch
# and replace it with a TouchIn object for the pin.
Expand All @@ -364,7 +370,7 @@ def _touch(self, i):
# lists and the capital A to match the pin name. The capitalization is not strictly Python
# style, so everywhere we use these names, we whitelist the errors using:
@property
def touch_A1(self): # pylint: disable=invalid-name
def touch_A1(self) -> bool: # pylint: disable=invalid-name
"""Detect touch on capacitive touch pad A1.

.. image :: ../docs/_static/capacitive_touch_pad_A1.jpg
Expand All @@ -383,7 +389,7 @@ def touch_A1(self): # pylint: disable=invalid-name
return self._touch(1)

@property
def touch_A2(self): # pylint: disable=invalid-name
def touch_A2(self) -> bool: # pylint: disable=invalid-name
"""Detect touch on capacitive touch pad A2.

.. image :: ../docs/_static/capacitive_touch_pad_A2.jpg
Expand All @@ -402,7 +408,7 @@ def touch_A2(self): # pylint: disable=invalid-name
return self._touch(2)

@property
def touch_A3(self): # pylint: disable=invalid-name
def touch_A3(self) -> bool: # pylint: disable=invalid-name
"""Detect touch on capacitive touch pad A3.

.. image :: ../docs/_static/capacitive_touch_pad_A3.jpg
Expand All @@ -421,7 +427,7 @@ def touch_A3(self): # pylint: disable=invalid-name
return self._touch(3)

@property
def touch_A4(self): # pylint: disable=invalid-name
def touch_A4(self) -> bool: # pylint: disable=invalid-name
"""Detect touch on capacitive touch pad A4.

.. image :: ../docs/_static/capacitive_touch_pad_A4.jpg
Expand All @@ -440,7 +446,7 @@ def touch_A4(self): # pylint: disable=invalid-name
return self._touch(4)

@property
def touch_A5(self): # pylint: disable=invalid-name
def touch_A5(self) -> bool: # pylint: disable=invalid-name
"""Detect touch on capacitive touch pad A5.

.. image :: ../docs/_static/capacitive_touch_pad_A5.jpg
Expand All @@ -459,7 +465,7 @@ def touch_A5(self): # pylint: disable=invalid-name
return self._touch(5)

@property
def touch_A6(self): # pylint: disable=invalid-name
def touch_A6(self) -> bool: # pylint: disable=invalid-name
"""Detect touch on capacitive touch pad A6.

.. image :: ../docs/_static/capacitive_touch_pad_A6.jpg
Expand All @@ -478,7 +484,7 @@ def touch_A6(self): # pylint: disable=invalid-name
return self._touch(6)

@property
def touch_TX(self): # pylint: disable=invalid-name
def touch_TX(self) -> bool: # pylint: disable=invalid-name
"""Detect touch on capacitive touch pad TX (also known as A7 on the Circuit Playground
Express) Note: can be called as ``touch_A7`` on Circuit Playground Express.

Expand All @@ -497,7 +503,7 @@ def touch_TX(self): # pylint: disable=invalid-name
"""
return self._touch(7)

def adjust_touch_threshold(self, adjustment):
def adjust_touch_threshold(self, adjustment: int) -> None:
"""Adjust the threshold needed to activate the capacitive touch pads.
Higher numbers make the touch pads less sensitive.

Expand All @@ -524,7 +530,7 @@ def adjust_touch_threshold(self, adjustment):
self._touch_threshold_adjustment += adjustment

@property
def pixels(self):
def pixels(self) -> neopixel.NeoPixel:
"""Sequence-like object representing the ten NeoPixels around the outside
of the Circuit Playground. Each pixel is at a certain index in the sequence
as labeled below. Colors can be RGB hex like 0x110000 for red where each
Expand Down Expand Up @@ -552,7 +558,7 @@ def pixels(self):
return self._pixels

@property
def button_a(self):
def button_a(self) -> bool:
"""``True`` when Button A is pressed. ``False`` if not.

.. image :: ../docs/_static/button_a.jpg
Expand All @@ -574,7 +580,7 @@ def button_a(self):
return self._a.value

@property
def button_b(self):
def button_b(self) -> bool:
"""``True`` when Button B is pressed. ``False`` if not.

.. image :: ../docs/_static/button_b.jpg
Expand All @@ -596,7 +602,7 @@ def button_b(self):
return self._b.value

@property
def switch(self):
def switch(self) -> bool:
"""``True`` when the switch is to the left next to the music notes.
``False`` when it is to the right towards the ear.

Expand All @@ -617,7 +623,7 @@ def switch(self):
return self._switch.value

@property
def temperature(self):
def temperature(self) -> float:
"""The temperature in Celsius.

.. image :: ../docs/_static/thermistor.jpg
Expand All @@ -642,7 +648,7 @@ def temperature(self):
return self._temp.temperature

@property
def light(self):
def light(self) -> int:
"""The light level.

.. image :: ../docs/_static/light_sensor.jpg
Expand All @@ -664,7 +670,7 @@ def light(self):
return self._light.light

@property
def red_led(self):
def red_led(self) -> bool:
"""The red led next to the USB plug marked D13.

.. image :: ../docs/_static/red_led.jpg
Expand All @@ -686,19 +692,19 @@ def red_led(self):
return self._led.value

@red_led.setter
def red_led(self, value):
def red_led(self, value: bool) -> None:
self._led.value = value

@staticmethod
def _sine_sample(length):
def _sine_sample(length: int) -> Iterator[int]:
tone_volume = (2**15) - 1
# Amplitude shift up in order to not have negative numbers
shift = 2**15
for i in range(length):
yield int(tone_volume * math.sin(2 * math.pi * (i / length)) + shift)

@staticmethod
def _square_sample(length):
def _square_sample(length: int) -> Iterator[int]:
# Square waves are MUCH louder than then sine
tone_volume = (2**16) - 1
half_length = length // 2
Expand All @@ -707,7 +713,7 @@ def _square_sample(length):
for _ in range(half_length):
yield 0

def _generate_sample(self, length=100, waveform=SINE_WAVE):
def _generate_sample(self, length: int = 100, waveform: int = SINE_WAVE) -> None:
if self._sample is not None:
return
if waveform == self.SQUARE_WAVE:
Expand All @@ -717,13 +723,15 @@ def _generate_sample(self, length=100, waveform=SINE_WAVE):
self._sample = self._audio_out(board.SPEAKER) # pylint: disable=not-callable
self._wave_sample = audiocore.RawSample(self._wave)

def play_tone(self, frequency, duration, waveform=SINE_WAVE):
def play_tone(
self, frequency: int, duration: float, waveform: int = SINE_WAVE
) -> None:
"""Produce a tone using the speaker. Try changing frequency to change
the pitch of the tone.

:param int frequency: The frequency of the tone in Hz
:param float duration: The duration of the tone in seconds
:param str waveform: Type of waveform to be generated [SINE_WAVE, SQUARE_WAVE].
:param int waveform: Type of waveform to be generated [SINE_WAVE, SQUARE_WAVE].

Default is SINE_WAVE.

Expand All @@ -743,7 +751,7 @@ def play_tone(self, frequency, duration, waveform=SINE_WAVE):
time.sleep(duration)
self.stop_tone()

def start_tone(self, frequency, waveform=SINE_WAVE):
def start_tone(self, frequency: int, waveform: int = SINE_WAVE) -> None:
"""Produce a tone using the speaker. Try changing frequency to change
the pitch of the tone.

Expand Down Expand Up @@ -779,7 +787,7 @@ def start_tone(self, frequency, waveform=SINE_WAVE):
if not self._sample.playing:
self._sample.play(self._wave_sample, loop=True)

def stop_tone(self):
def stop_tone(self) -> None:
"""Use with start_tone to stop the tone produced.

.. image :: ../docs/_static/speaker.jpg
Expand All @@ -806,7 +814,7 @@ def stop_tone(self):
self._sample = None
self._speaker_enable.value = False

def play_file(self, file_name):
def play_file(self, file_name: str) -> None:
"""Play a .wav file using the onboard speaker.

:param file_name: The name of your .wav file in quotation marks including .wav
Expand Down