Skip to content

Commit d7c0d6f

Browse files
authored
Consolidate entry points (#49)
* Consolidate entry points * Add release notes for version 0.13.0 - CLI consolidation * Refactor CLI and add test coverage * lint * add cli
1 parent c6934c7 commit d7c0d6f

File tree

6 files changed

+244
-41
lines changed

6 files changed

+244
-41
lines changed

HISTORY.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# History
22

3+
## 0.13.0 (2025-08-22)
4+
5+
* Consolidate multiple entry points into a single `teensytoany` command with subcommands:
6+
- `teensytoany programmer` (replaces `teensytoany_programmer`)
7+
- `teensytoany i2c-scan` (replaces `teensytoany_i2c_scan`)
8+
- `teensytoany list` (replaces `teensytoany_list`)
9+
* Maintain backward compatibility with deprecation warnings for old entry points
10+
311
## 0.12.1 (2025-08-22)
412

513
* Add `fastled_set_max_refresh_rate` method to control FastLED refresh rate.

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ def get_version_and_cmdclass(pkg_path):
5151
name='teensytoany',
5252
entry_points={
5353
'console_scripts': [
54-
'teensytoany_programmer=teensytoany.programmer:teensytoany_programmer',
54+
'teensytoany=teensytoany.cli:teensytoany_cli',
55+
'teensytoany_programmer=teensytoany.programmer:main',
5556
'teensytoany_i2c_scan=teensytoany.i2c_scan:main',
5657
'teensytoany_list=teensytoany.list:main',
5758
],

teensytoany/cli.py

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import click
2+
3+
import teensytoany
4+
from teensytoany.i2c_scan import i2c_scan
5+
from teensytoany.list import teensytoany_list
6+
from teensytoany.programmer import teensytoany_programmer
7+
8+
9+
@click.group(epilog=f"Version {teensytoany.__version__}")
10+
@click.version_option(teensytoany.__version__)
11+
def teensytoany_cli():
12+
"""TeensyToAny command line interface"""
13+
14+
15+
@teensytoany_cli.command()
16+
@click.option(
17+
'--serial-number',
18+
default=None,
19+
help=(
20+
'Serial number of the Teensy device to program. '
21+
'If not provided and only one Teensy device found, '
22+
'it will be programmed.'
23+
)
24+
)
25+
@click.option(
26+
'--mcu',
27+
type=click.Choice(['TEENSY40', 'TEENSY32']),
28+
default='TEENSY40',
29+
help='Microcontroller to program.'
30+
)
31+
@click.option(
32+
'--firmware-version',
33+
default=None,
34+
type=str,
35+
help='Firmware version to program. If not provided, the latest version will be programmed.'
36+
)
37+
@click.option(
38+
'--firmware-variant',
39+
default=None,
40+
type=str,
41+
help='Firmware variant to program. If not provided, the standard variant will be programmed.'
42+
)
43+
@click.option(
44+
'--download-only',
45+
is_flag=True,
46+
default=False,
47+
help='Download the firmware only, do not program the device.'
48+
)
49+
def programmer(
50+
serial_number=None,
51+
mcu='TEENSY40',
52+
firmware_version=None,
53+
firmware_variant=None,
54+
download_only=False
55+
):
56+
"""Program a Teensy device with a given firmware version"""
57+
# pylint: disable=duplicate-code
58+
teensytoany_programmer(
59+
serial_number=serial_number,
60+
mcu=mcu,
61+
firmware_version=firmware_version,
62+
firmware_variant=firmware_variant,
63+
download_only=download_only
64+
)
65+
66+
67+
@teensytoany_cli.command()
68+
@click.option(
69+
'--serial-number', '-s',
70+
type=str,
71+
default=None,
72+
show_default=False,
73+
help='Serial number of the Teensy device.'
74+
)
75+
@click.option(
76+
'--interface',
77+
'-i',
78+
type=int,
79+
default=0,
80+
show_default=True,
81+
help='I2C interface to use (0 for I2C, 1 for I2C1).'
82+
)
83+
@click.option(
84+
'--seven-bit-mode',
85+
'-7',
86+
is_flag=True,
87+
default=False,
88+
help=(
89+
'Report addresses in 7-bit mode instead of 8-bit mode. '
90+
'By default, addresses are reported in 8-bit mode.'
91+
),
92+
)
93+
@click.option(
94+
'--baud-rate',
95+
type=int,
96+
default=100_100,
97+
show_default=True,
98+
help='Baud rate for the I2C bus.',
99+
)
100+
@click.option(
101+
'--verbose',
102+
is_flag=True,
103+
default=False,
104+
help='Report in verbose mode, print out all pinged addresses.',
105+
)
106+
def i2c_scan_command(
107+
serial_number=None,
108+
interface=0,
109+
seven_bit_mode=False,
110+
baud_rate=100_100,
111+
verbose=False,
112+
):
113+
"""Scan I2C devices connected to TeensyToAny"""
114+
# pylint: disable=duplicate-code
115+
i2c_scan(
116+
serial_number=serial_number,
117+
interface=interface,
118+
baud_rate=baud_rate,
119+
seven_bit_mode=seven_bit_mode,
120+
verbose=verbose,
121+
)
122+
123+
124+
@teensytoany_cli.command()
125+
@click.option(
126+
'--manufacturer',
127+
type=str,
128+
default="TeensyToAny",
129+
show_default=True,
130+
help="Manufacturer of the device to list.",
131+
)
132+
@click.option(
133+
'--teensyduino',
134+
is_flag=True,
135+
default=False,
136+
help=(
137+
"List devices with manufacturer 'TeensyToAny'. "
138+
"This is a shortcut for --manufacturer=TeensyToAny"
139+
),
140+
)
141+
def list_command(
142+
manufacturer="TeensyToAny",
143+
teensyduino=False,
144+
):
145+
"""List available TeensyToAny devices"""
146+
teensytoany_list(
147+
manufacturer=manufacturer,
148+
teensyduino=teensyduino,
149+
)
150+
151+
152+
if __name__ == '__main__':
153+
teensytoany_cli()

teensytoany/i2c_scan.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ def main(
5252
baud_rate=100_100,
5353
verbose=False,
5454
):
55+
click.echo(
56+
"WARNING: teensytoany_i2c_scan is deprecated. Use 'teensytoany i2c_scan' instead.",
57+
err=True
58+
)
59+
# pylint: disable=duplicate-code
5560
return i2c_scan(
5661
serial_number=serial_number,
5762
interface=interface,

teensytoany/list.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,26 @@
66
from teensytoany import TeensyToAny
77

88

9+
def teensytoany_list(
10+
manufacturer="TeensyToAny",
11+
teensyduino=False,
12+
):
13+
"""
14+
List available TeensyToAny devices.
15+
"""
16+
if teensyduino:
17+
manufacturer = "Teensyduino"
18+
19+
try:
20+
device_serial_numbers = TeensyToAny.device_serial_number_pairs(manufacturer=manufacturer)
21+
except RuntimeError:
22+
click.echo(f"Error: Could not find any devices with manufacturer '{manufacturer}'.")
23+
sys.exit(1)
24+
25+
for device, serial_number in device_serial_numbers:
26+
click.echo(f"Port: {device} -- Serial Number: {serial_number}")
27+
28+
929
@click.command(epilog=f"Version {teensytoany.__version__}")
1030
@click.option(
1131
'--manufacturer',
@@ -31,14 +51,8 @@ def main(
3151
"""
3252
List available TeensyToAny devices.
3353
"""
34-
if teensyduino:
35-
manufacturer = "Teensyduino"
36-
37-
try:
38-
device_serial_numbers = TeensyToAny.device_serial_number_pairs(manufacturer=manufacturer)
39-
except RuntimeError:
40-
click.echo(f"Error: Could not find any devices with manufacturer '{manufacturer}'.")
41-
sys.exit(1)
42-
43-
for device, serial_number in device_serial_numbers:
44-
click.echo(f"Port: {device} -- Serial Number: {serial_number}")
54+
click.echo("WARNING: teensytoany_list is deprecated. Use 'teensytoany list' instead.", err=True)
55+
teensytoany_list(
56+
manufacturer=manufacturer,
57+
teensyduino=teensyduino,
58+
)

teensytoany/programmer.py

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,45 @@
33
import teensytoany
44

55

6+
def teensytoany_programmer(
7+
serial_number=None,
8+
mcu='TEENSY40',
9+
firmware_version=None,
10+
firmware_variant=None,
11+
download_only=False
12+
):
13+
"""Program a Teensy device with a given firmware version"""
14+
variant_str = f"variant {firmware_variant} of " if firmware_variant else ""
15+
if download_only:
16+
for mcu_to_download in ['TEENSY40', 'TEENSY32']:
17+
if firmware_version is None:
18+
firmware_version = teensytoany.TeensyToAny.get_latest_available_firmware_version(
19+
mcu=mcu_to_download, online=True, local=False
20+
)
21+
print(
22+
f"Downloading {variant_str} firmware version {firmware_version} "
23+
f"for {mcu_to_download}."
24+
)
25+
teensytoany.TeensyToAny.download_firmware(
26+
mcu=mcu_to_download,
27+
version=firmware_version,
28+
variant=firmware_variant
29+
)
30+
return
31+
32+
print('Programming please wait...')
33+
teensytoany.TeensyToAny.program_firmware(
34+
serial_number,
35+
mcu=mcu,
36+
version=firmware_version,
37+
variant=firmware_variant
38+
)
39+
with teensytoany.TeensyToAny(serial_number) as teensy:
40+
print(f"TeensyToAny version: {teensy.version}")
41+
print(f"TeensyToAny variant: {firmware_variant}")
42+
print(f"TeensyToAny serial_number: {teensy.serial_number}")
43+
44+
645
@click.command(epilog=f"Version {teensytoany.__version__}")
746
@click.option(
847
'--serial-number',
@@ -40,44 +79,27 @@
4079
)
4180
# Make the epligue print the version
4281
@click.version_option(teensytoany.__version__)
43-
def teensytoany_programmer(
82+
def main(
4483
serial_number=None,
4584
mcu='TEENSY40',
4685
firmware_version=None,
4786
firmware_variant=None,
4887
download_only=False
4988
):
5089
"""Program a Teensy device with a given firmware version"""
51-
variant_str = f"variant {firmware_variant} of " if firmware_variant else ""
52-
if download_only:
53-
for mcu_to_download in ['TEENSY40', 'TEENSY32']:
54-
if firmware_version is None:
55-
firmware_version = teensytoany.TeensyToAny.get_latest_available_firmware_version(
56-
mcu=mcu_to_download, online=True, local=False
57-
)
58-
print(
59-
f"Downloading {variant_str} firmware version {firmware_version} "
60-
f"for {mcu_to_download}."
61-
)
62-
teensytoany.TeensyToAny.download_firmware(
63-
mcu=mcu_to_download,
64-
version=firmware_version,
65-
variant=firmware_variant
66-
)
67-
return
68-
69-
print('Programming please wait...')
70-
teensytoany.TeensyToAny.program_firmware(
71-
serial_number,
90+
click.echo(
91+
"WARNING: teensytoany_programmer is deprecated. Use 'teensytoany programmer' instead.",
92+
err=True
93+
)
94+
# pylint: disable=duplicate-code
95+
teensytoany_programmer(
96+
serial_number=serial_number,
7297
mcu=mcu,
73-
version=firmware_version,
74-
variant=firmware_variant
98+
firmware_version=firmware_version,
99+
firmware_variant=firmware_variant,
100+
download_only=download_only
75101
)
76-
with teensytoany.TeensyToAny(serial_number) as teensy:
77-
print(f"TeensyToAny version: {teensy.version}")
78-
print(f"TeensyToAny variant: {firmware_variant}")
79-
print(f"TeensyToAny serial_number: {teensy.serial_number}")
80102

81103

82104
if __name__ == '__main__':
83-
teensytoany_programmer()
105+
main()

0 commit comments

Comments
 (0)