Barmaja-PyArduino 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. Barmaja_PyArduino/BARMAJA_PyArduino.ico +0 -0
  2. Barmaja_PyArduino/__init__.py +528 -0
  3. Barmaja_PyArduino/__init__.pyi +331 -0
  4. Barmaja_PyArduino/__main__.py +2 -0
  5. Barmaja_PyArduino/adapters/__init__.py +35 -0
  6. Barmaja_PyArduino/api_registry.py +459 -0
  7. Barmaja_PyArduino/backend/__init__.py +3 -0
  8. Barmaja_PyArduino/backend/uno_cpp.py +1680 -0
  9. Barmaja_PyArduino/board.py +80 -0
  10. Barmaja_PyArduino/cli.py +223 -0
  11. Barmaja_PyArduino/compiler.py +1721 -0
  12. Barmaja_PyArduino/console.py +217 -0
  13. Barmaja_PyArduino/device_packs.py +367 -0
  14. Barmaja_PyArduino/device_packs_builtin/Button/arduino/Barmaja_Button/library.properties +9 -0
  15. Barmaja_PyArduino/device_packs_builtin/Button/arduino/Barmaja_Button/src/Barmaja_Button.h +18 -0
  16. Barmaja_PyArduino/device_packs_builtin/Button/example.py +10 -0
  17. Barmaja_PyArduino/device_packs_builtin/Button/pack.json +40 -0
  18. Barmaja_PyArduino/device_packs_builtin/ClockDS3231/arduino/Barmaja_ClockDS3231/library.properties +9 -0
  19. Barmaja_PyArduino/device_packs_builtin/ClockDS3231/arduino/Barmaja_ClockDS3231/src/Barmaja_ClockDS3231.h +20 -0
  20. Barmaja_PyArduino/device_packs_builtin/ClockDS3231/example.py +8 -0
  21. Barmaja_PyArduino/device_packs_builtin/ClockDS3231/pack.json +136 -0
  22. Barmaja_PyArduino/device_packs_builtin/DistanceVL53L0X/arduino/Barmaja_DistanceVL53L0X/library.properties +9 -0
  23. Barmaja_PyArduino/device_packs_builtin/DistanceVL53L0X/arduino/Barmaja_DistanceVL53L0X/src/Barmaja_DistanceVL53L0X.h +12 -0
  24. Barmaja_PyArduino/device_packs_builtin/DistanceVL53L0X/example.py +8 -0
  25. Barmaja_PyArduino/device_packs_builtin/DistanceVL53L0X/pack.json +48 -0
  26. Barmaja_PyArduino/device_packs_builtin/LCDParallel/arduino/Barmaja_LCDParallel/library.properties +9 -0
  27. Barmaja_PyArduino/device_packs_builtin/LCDParallel/arduino/Barmaja_LCDParallel/src/Barmaja_LCDParallel.h +17 -0
  28. Barmaja_PyArduino/device_packs_builtin/LCDParallel/example.py +10 -0
  29. Barmaja_PyArduino/device_packs_builtin/LCDParallel/pack.json +137 -0
  30. Barmaja_PyArduino/device_packs_builtin/LoadCellHX711/arduino/Barmaja_LoadCellHX711/library.properties +9 -0
  31. Barmaja_PyArduino/device_packs_builtin/LoadCellHX711/arduino/Barmaja_LoadCellHX711/src/Barmaja_LoadCellHX711.h +16 -0
  32. Barmaja_PyArduino/device_packs_builtin/LoadCellHX711/example.py +11 -0
  33. Barmaja_PyArduino/device_packs_builtin/LoadCellHX711/pack.json +74 -0
  34. Barmaja_PyArduino/device_packs_builtin/NeoPixelStrip/arduino/Barmaja_NeoPixelStrip/library.properties +9 -0
  35. Barmaja_PyArduino/device_packs_builtin/NeoPixelStrip/arduino/Barmaja_NeoPixelStrip/src/Barmaja_NeoPixelStrip.h +15 -0
  36. Barmaja_PyArduino/device_packs_builtin/NeoPixelStrip/example.py +13 -0
  37. Barmaja_PyArduino/device_packs_builtin/NeoPixelStrip/pack.json +114 -0
  38. Barmaja_PyArduino/device_packs_builtin/OLEDText/arduino/Barmaja_OLEDText/library.properties +9 -0
  39. Barmaja_PyArduino/device_packs_builtin/OLEDText/arduino/Barmaja_OLEDText/src/Barmaja_OLEDText.h +21 -0
  40. Barmaja_PyArduino/device_packs_builtin/OLEDText/example.py +9 -0
  41. Barmaja_PyArduino/device_packs_builtin/OLEDText/pack.json +103 -0
  42. Barmaja_PyArduino/device_packs_builtin/PressureBMP280/arduino/Barmaja_PressureBMP280/library.properties +9 -0
  43. Barmaja_PyArduino/device_packs_builtin/PressureBMP280/arduino/Barmaja_PressureBMP280/src/Barmaja_PressureBMP280.h +16 -0
  44. Barmaja_PyArduino/device_packs_builtin/PressureBMP280/example.py +8 -0
  45. Barmaja_PyArduino/device_packs_builtin/PressureBMP280/pack.json +92 -0
  46. Barmaja_PyArduino/device_packs_builtin/RotaryEncoder/arduino/Barmaja_RotaryEncoder/library.properties +9 -0
  47. Barmaja_PyArduino/device_packs_builtin/RotaryEncoder/arduino/Barmaja_RotaryEncoder/src/Barmaja_RotaryEncoder.h +18 -0
  48. Barmaja_PyArduino/device_packs_builtin/RotaryEncoder/example.py +10 -0
  49. Barmaja_PyArduino/device_packs_builtin/RotaryEncoder/pack.json +44 -0
  50. Barmaja_PyArduino/device_packs_builtin/ServoDriverPCA9685/arduino/Barmaja_ServoDriverPCA9685/library.properties +9 -0
  51. Barmaja_PyArduino/device_packs_builtin/ServoDriverPCA9685/arduino/Barmaja_ServoDriverPCA9685/src/Barmaja_ServoDriverPCA9685.h +15 -0
  52. Barmaja_PyArduino/device_packs_builtin/ServoDriverPCA9685/example.py +10 -0
  53. Barmaja_PyArduino/device_packs_builtin/ServoDriverPCA9685/pack.json +117 -0
  54. Barmaja_PyArduino/device_packs_builtin/ShiftRegister595/arduino/Barmaja_ShiftRegister595/library.properties +9 -0
  55. Barmaja_PyArduino/device_packs_builtin/ShiftRegister595/arduino/Barmaja_ShiftRegister595/src/Barmaja_ShiftRegister595.h +14 -0
  56. Barmaja_PyArduino/device_packs_builtin/ShiftRegister595/example.py +9 -0
  57. Barmaja_PyArduino/device_packs_builtin/ShiftRegister595/pack.json +83 -0
  58. Barmaja_PyArduino/device_packs_builtin/TemperatureDS18B20/arduino/Barmaja_TemperatureDS18B20/library.properties +9 -0
  59. Barmaja_PyArduino/device_packs_builtin/TemperatureDS18B20/arduino/Barmaja_TemperatureDS18B20/src/Barmaja_TemperatureDS18B20.h +16 -0
  60. Barmaja_PyArduino/device_packs_builtin/TemperatureDS18B20/example.py +8 -0
  61. Barmaja_PyArduino/device_packs_builtin/TemperatureDS18B20/pack.json +63 -0
  62. Barmaja_PyArduino/doctor.py +406 -0
  63. Barmaja_PyArduino/environment.py +595 -0
  64. Barmaja_PyArduino/errors.py +166 -0
  65. Barmaja_PyArduino/flow.py +754 -0
  66. Barmaja_PyArduino/frontend.py +611 -0
  67. Barmaja_PyArduino/installer.py +151 -0
  68. Barmaja_PyArduino/ir.py +660 -0
  69. Barmaja_PyArduino/library_adder.py +440 -0
  70. Barmaja_PyArduino/live.py +859 -0
  71. Barmaja_PyArduino/lowering.py +596 -0
  72. Barmaja_PyArduino/numeric.py +748 -0
  73. Barmaja_PyArduino/pack_builder.py +544 -0
  74. Barmaja_PyArduino/py.typed +0 -0
  75. Barmaja_PyArduino/serial_monitor.py +172 -0
  76. Barmaja_PyArduino/source.py +184 -0
  77. Barmaja_PyArduino/stubgen.py +148 -0
  78. Barmaja_PyArduino/symbols.py +646 -0
  79. Barmaja_PyArduino/target.py +1631 -0
  80. Barmaja_PyArduino/toolchain.py +506 -0
  81. Barmaja_PyArduino/typesys.py +917 -0
  82. Barmaja_PyArduino/workflow.py +213 -0
  83. barmaja_pyarduino-2.0.0.dist-info/METADATA +39 -0
  84. barmaja_pyarduino-2.0.0.dist-info/RECORD +87 -0
  85. barmaja_pyarduino-2.0.0.dist-info/WHEEL +5 -0
  86. barmaja_pyarduino-2.0.0.dist-info/licenses/LICENSE.txt +7 -0
  87. barmaja_pyarduino-2.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,80 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+
6
+ @dataclass(frozen=True)
7
+ class BoardProfile:
8
+ id: str
9
+ name: str
10
+ fqbn: str
11
+ mcu: str
12
+ flash_bytes: int
13
+ sram_bytes: int
14
+ digital_pins: tuple[int, ...]
15
+ analog_aliases: dict[str, int]
16
+ analog_channels: tuple[int, ...]
17
+ pwm_pins: tuple[int, ...]
18
+ pwm_timer_map: dict[int, str]
19
+ uart_rx_pin: int
20
+ uart_tx_pin: int
21
+ i2c_sda_pin: int
22
+ i2c_scl_pin: int
23
+ servo_timer: str
24
+ servo_pwm_conflict_pins: tuple[int, ...]
25
+ servo_max_channels: int
26
+ millis_bits: int
27
+ cpp_int_bits: int
28
+ float_bits: int
29
+ sram_warning_ratio: float = 0.75
30
+ sram_error_ratio: float = 0.90
31
+
32
+ @property
33
+ def analog_pins(self) -> tuple[int, ...]:
34
+ return tuple(self.analog_aliases.values())
35
+
36
+ @property
37
+ def digital_capable_pins(self) -> tuple[int, ...]:
38
+ # Arduino AVR core permits A0..A5 aliases to be used as digital pins.
39
+ return tuple(sorted(set(self.digital_pins) | set(self.analog_pins)))
40
+
41
+ @property
42
+ def uart_pins(self) -> tuple[int, int]:
43
+ return (self.uart_rx_pin, self.uart_tx_pin)
44
+
45
+ @property
46
+ def i2c_pins(self) -> tuple[int, int]:
47
+ return (self.i2c_sda_pin, self.i2c_scl_pin)
48
+
49
+ def alias_for_pin(self, pin: int) -> str | None:
50
+ for alias, number in self.analog_aliases.items():
51
+ if number == pin:
52
+ return alias
53
+ return None
54
+
55
+
56
+ UNO = BoardProfile(
57
+ id="uno",
58
+ name="Arduino Uno",
59
+ fqbn="arduino:avr:uno",
60
+ mcu="ATmega328P",
61
+ flash_bytes=32256, # usable program space (32 KiB minus the 512-byte Optiboot bootloader)
62
+ sram_bytes=2048,
63
+ digital_pins=tuple(range(14)),
64
+ analog_aliases={f"A{i}": 14 + i for i in range(6)},
65
+ analog_channels=tuple(range(6)),
66
+ pwm_pins=(3, 5, 6, 9, 10, 11),
67
+ pwm_timer_map={3: "Timer2", 5: "Timer0", 6: "Timer0", 9: "Timer1", 10: "Timer1", 11: "Timer2"},
68
+ uart_rx_pin=0,
69
+ uart_tx_pin=1,
70
+ i2c_sda_pin=18, # A4
71
+ i2c_scl_pin=19, # A5
72
+ servo_timer="Timer1",
73
+ servo_pwm_conflict_pins=(9, 10),
74
+ servo_max_channels=12,
75
+ millis_bits=32,
76
+ cpp_int_bits=16,
77
+ float_bits=32,
78
+ )
79
+
80
+ BOARDS = {UNO.id: UNO, UNO.fqbn: UNO}
@@ -0,0 +1,223 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import os
5
+ import sys
6
+ from pathlib import Path
7
+
8
+ from .compiler import Transpiler
9
+ from .errors import BarmajaError, BoardDetectionError, InternalCompilerError, format_error
10
+ from .toolchain import board_for_port, compile_sketch, detect_board, upload_compiled
11
+ from .doctor import run_doctor
12
+
13
+
14
+ def _compile(path: str):
15
+ return Transpiler().compile_file(path)
16
+
17
+
18
+ def _write_line(stream, text: str, *, style: str | None = None) -> None:
19
+ from .console import write_styled
20
+
21
+ write_styled(stream, text, style=style)
22
+
23
+
24
+ def _write_warnings(result) -> None:
25
+ for warning in getattr(result, "warnings", ()) or ():
26
+ where = ""
27
+ span = getattr(warning, "span", None)
28
+ line = getattr(span, "start_line", None) or getattr(span, "line", None)
29
+ if line:
30
+ where = f"Line {line}: "
31
+ text = f"Warning: {where}{warning.message}"
32
+ if getattr(warning, "hint", None):
33
+ text += f" ({warning.hint})"
34
+ _write_line(sys.stderr, text)
35
+
36
+
37
+ def _list_packs(*, details: bool) -> int:
38
+ from . import device_packs as dp
39
+ from . import api_registry # noqa: F401 (loads packs)
40
+ from .toolchain import pinned_library_dirs
41
+ installed = {p.name.lower() for p in pinned_library_dirs()}
42
+ dev = os.environ.get("BARMAJA_DEV_LIBRARIES")
43
+ if dev and Path(dev).is_dir():
44
+ installed |= {p.name.lower() for p in Path(dev).iterdir() if p.is_dir()}
45
+ missing_any = False
46
+ _write_line(sys.stdout, f"{len(dp.LOADED)} device pack(s):")
47
+ for name, pack in dp.LOADED.items():
48
+ missing = [d["name"] for d in pack.dependencies
49
+ if d.get("library_folder", d["name"]).lower() not in installed]
50
+ missing_any |= bool(missing)
51
+ state = "libraries OK" if not missing else "MISSING: " + ", ".join(missing)
52
+ _write_line(sys.stdout, f" {name:22s} {pack.status:18s} [{pack.source}] {state}")
53
+ if details:
54
+ args = ", ".join(p.name for p in pack.constructor)
55
+ _write_line(sys.stdout, f" {pack.title}\n {name}({args})")
56
+ for m in pack.methods.values():
57
+ _write_line(sys.stdout, f" .{m.name}({', '.join(p.name for p in m.params)}) -> {m.returns}")
58
+ for err in dp.LOAD_ERRORS:
59
+ _write_line(sys.stderr, " SKIPPED " + err)
60
+ return 2 if (missing_any or dp.LOAD_ERRORS) else 0
61
+
62
+
63
+ def main(argv: list[str] | None = None) -> int:
64
+ parser = argparse.ArgumentParser(prog="pyarduino", description="Barmaja PyArduino CLI")
65
+ sub = parser.add_subparsers(dest="command", required=True)
66
+
67
+ for cmd, help_text in [
68
+ ("check", "Parse and validate Python without requiring Arduino CLI"),
69
+ ("generate", "Generate Arduino C++"),
70
+ ("verify", "Generate and compile for Arduino Uno"),
71
+ ("upload", "Generate, auto-detect Uno, compile, and upload"),
72
+ ]:
73
+ p = sub.add_parser(cmd, help=help_text)
74
+ p.add_argument("source")
75
+ if cmd == "generate":
76
+ p.add_argument("-o", "--output")
77
+ if cmd == "upload":
78
+ p.add_argument("--port", help="Serial port to use when automatic detection is ambiguous (e.g. COM5)")
79
+ p.add_argument("--details", action="store_true", help="Show technical details for errors")
80
+
81
+ sub.add_parser("detect", help="Auto-detect connected Arduino Uno")
82
+ doctor = sub.add_parser("doctor", help="Check the Barmaja PyArduino environment")
83
+ doctor.add_argument("--details", action="store_true", help="Show complete technical details")
84
+ doctor.add_argument("--pictoblox", action="store_true", help="Check the PictoBlox installation")
85
+
86
+ adder = sub.add_parser("add-library", help="Add an Arduino library (ZIP or folder). No path = open the Library Adder window")
87
+ adder.add_argument("path", nargs="?")
88
+ adder.add_argument("--auto", action="store_true", help="No window: convert, check and install automatically")
89
+ adder.add_argument("--class", dest="cls", help="Library C++ class to use (default: best guess)")
90
+ adder.add_argument("--name", help="Class name students will use (default: derived from the library class)")
91
+ adder.add_argument("--no-compile", action="store_true", help="Skip the Arduino Uno compile test")
92
+ adder.add_argument("--check-only", action="store_true", help="Check but do not install")
93
+ rm = sub.add_parser("remove-pack", help="Remove a library added with add-library (moved to backups)")
94
+ rm.add_argument("name")
95
+ packs_cmd = sub.add_parser("packs", help="List device packs (extra Arduino libraries/sensors) and check their libraries")
96
+ packs_cmd.add_argument("--details", action="store_true", help="Show methods and dependencies")
97
+
98
+ args = parser.parse_args(argv)
99
+ try:
100
+ if args.command == "packs":
101
+ return _list_packs(details=args.details)
102
+ if args.command == "add-library":
103
+ from .library_adder import add_library_auto, run_gui
104
+ if args.auto and args.path:
105
+ return add_library_auto(args.path, cls=args.cls, student=args.name, compile=not args.no_compile,
106
+ do_install=not args.check_only)
107
+ return run_gui(args.path)
108
+ if args.command == "remove-pack":
109
+ from .library_adder import remove
110
+ for line in remove(args.name):
111
+ _write_line(sys.stdout, line)
112
+ return 0
113
+ if args.command == "doctor":
114
+ report = run_doctor(details=args.details, pictoblox=args.pictoblox, use_cache=not args.details)
115
+ text = report.detailed() if args.details else report.concise()
116
+ _write_line(
117
+ sys.stdout if report.ok else sys.stderr,
118
+ text,
119
+ style=None if report.ok else "error",
120
+ )
121
+ return 0 if report.ok else 2
122
+
123
+ if args.command == "detect":
124
+ b = detect_board()
125
+ _write_line(sys.stdout, f"{b.name} detected on {b.port} ({b.fqbn}).")
126
+ return 0
127
+
128
+ result = _compile(args.source)
129
+ if not (args.command == "generate" and not args.output):
130
+ _write_warnings(result)
131
+
132
+ if args.command == "check":
133
+ from . import __version__
134
+ _write_line(sys.stdout, f"Barmaja PyArduino code is valid for {__version__}.")
135
+ return 0
136
+
137
+ if args.command == "generate":
138
+ if args.output:
139
+ out = Path(args.output)
140
+ out.write_text(result.cpp, encoding="utf-8")
141
+ _write_line(sys.stdout, f"Generated Arduino code: {out}")
142
+ else:
143
+ _write_line(sys.stdout, result.cpp)
144
+ return 0
145
+
146
+ if args.command == "verify":
147
+ from .console import compilation_summary_lines
148
+ _write_line(sys.stdout, "Compiling sketch...")
149
+ artifact = compile_sketch(result.cpp)
150
+ _write_line(sys.stdout, "")
151
+ for index, line in enumerate(compilation_summary_lines(artifact.memory)):
152
+ _write_line(sys.stdout, line, style="success" if index == 0 else None)
153
+ return 0
154
+
155
+ if args.command == "upload":
156
+ from .console import compilation_summary_lines
157
+ _write_line(sys.stdout, "Compiling sketch...")
158
+ artifact = compile_sketch(result.cpp)
159
+ _write_line(sys.stdout, "")
160
+ for index, line in enumerate(compilation_summary_lines(artifact.memory)):
161
+ _write_line(sys.stdout, line, style="success" if index == 0 else None)
162
+ _write_line(sys.stdout, "")
163
+ _write_line(sys.stdout, "Searching for Arduino Uno...")
164
+
165
+ port = args.port or os.environ.get("BARMAJA_PORT")
166
+ try:
167
+ board = board_for_port(port) if port else detect_board()
168
+ except BoardDetectionError as exc:
169
+ if getattr(exc, "reason", None) != "not-found":
170
+ raise
171
+ ports = ", ".join(getattr(exc, "ports", ()) or ()) or "none"
172
+ _write_line(sys.stderr, "")
173
+ _write_line(sys.stderr, "Arduino Uno not detected.", style="error")
174
+ _write_line(sys.stderr, f"Ports found: {ports}", style="error")
175
+ _write_line(sys.stderr, "")
176
+ _write_line(sys.stderr, "Connect the Arduino Uno by USB, wait a few seconds,", style="error")
177
+ _write_line(sys.stderr, "then run the program again.", style="error")
178
+ _write_line(sys.stderr, "")
179
+ _write_line(sys.stderr, "Compilation completed successfully.", style="error")
180
+ _write_line(sys.stderr, "Upload was not attempted.", style="error")
181
+ return 2
182
+
183
+ if port:
184
+ _write_line(sys.stdout, f"Arduino Uno selected on {board.port}.")
185
+ else:
186
+ _write_line(sys.stdout, f"Arduino Uno detected on {board.port}.")
187
+ _write_line(sys.stdout, "")
188
+ _write_line(sys.stdout, "Uploading...")
189
+ upload_compiled(artifact, board)
190
+ _write_line(sys.stdout, "Upload completed successfully.", style="success")
191
+ _write_line(sys.stdout, "")
192
+ _write_line(sys.stdout, "The Arduino program is now running standalone.", style="success")
193
+ return 0
194
+
195
+ except BarmajaError as exc:
196
+ show = bool(getattr(args, "details", False)) or os.environ.get("BARMAJA_DEBUG") == "1"
197
+ text = format_error(exc, details=show)
198
+ if isinstance(exc, InternalCompilerError) and not show:
199
+ text += "\nRun the same command again with --details and share the output with your teacher."
200
+ _write_line(sys.stderr, text, style="error")
201
+ return 3 if isinstance(exc, InternalCompilerError) else 2
202
+ except OSError as exc:
203
+ # File/OS failures are still concise and traceback-free at the student CLI.
204
+ _write_line(sys.stderr, f"Barmaja PyArduino: {exc}", style="error")
205
+ return 2
206
+ except Exception as exc:
207
+ # Last-resort boundary: never leak a Python traceback to students.
208
+ wrapped = InternalCompilerError(
209
+ "An internal Barmaja PyArduino error occurred.",
210
+ details=f"{type(exc).__name__}: {exc}",
211
+ )
212
+ show = bool(getattr(args, "details", False)) or os.environ.get("BARMAJA_DEBUG") == "1"
213
+ text = format_error(wrapped, details=show)
214
+ if not show:
215
+ text += "\nRun the same command again with --details and share the output with your teacher."
216
+ _write_line(sys.stderr, text, style="error")
217
+ return 3
218
+
219
+ return 1
220
+
221
+
222
+ if __name__ == "__main__":
223
+ raise SystemExit(main())