#PyCharm CircuitPython stubs
1 messages · Page 1 of 1 (latest)
@haughty solar I have installed PyCharm. Going to use it over VSCode for this. It works now, even with stuff I installed from GitHub and manually mpy compiled. Since the library is at least in the correct search path for PyCharm.
However, what I am trying to figure out is how to get the stubs for the board? The CircuitPython extension for VSCode has some kind of repo of the board stubs, for each board.
I don't know about that, I don't know if it's a thing ?
I would maybe expect an IDE to have some notion of a "project" to which you add the board drive and its lib directory, giving it knowledge of what is in it, but only py files
VSCode extension for Adafruit's CircuitPython. Contribute to joedevivo/vscode-circuitpython development by creating an account on GitHub.
like, he's building some kind of something with this
maybe I can simply do a from board import ...?
I mean, it looks like they're in there, somehow
just wondering how do I target a specific one?
oh the board module ?
yeah
in this case an RP2040 feather
thank you for your time and help, by the way
there's a list of everything supported, but how do I find the stubs?
there's that?
but it doesn't list the rp2040
the built-in modules should be part of circuitpython-stubs, but the board module there contains all pins of all boards, I don't know that there are ways through those stubs to do that
yeah, I saw it had all of them
blinka is the compatiblity layer for Linux boards like the Raspberry pi 4, Beaglebone, and such
aaah, yeah, true
just trying to trace down where it gets those board definitions from in the Python files
then submodule link to https://github.com/raspberrypi/pico-sdk/tree/bfcbefafc5d2a210551a4d9d80b4303d4ae0adf7 which has the https://github.com/raspberrypi/pico-sdk/tree/bfcbefafc5d2a210551a4d9d80b4303d4ae0adf7/src/rp2040 rp2040 stuff... for the pico, but it's all in C, so I dunno where the Python comes from. Are those dynamically generated?
Here's the info file with all the stuff:
https://github.com/adafruit/circuitpython/blob/main/ports/raspberrypi/boards/adafruit_feather_rp2040/mpconfigboard.mk
vendor, product, name, manu, and such
from reading some sources some of this is stored in S3, or something?
I don't know, I think @autumn citrus might be able to help you
the question is about generating/getting the stubs for a specific board's board module, right ?
@dry robin I'm not aware of any way to get a "correct" board module stubs for any particular board. I haven't looked into it in a while, but last I knew the board module in the stubs does not contain anything (no pins or I2C / SPI etc) At one point I had the idea to try to make one for stubs that would contain every possible pin for every device, but to my knowledge that wasn't ever done.
correct
board.c in the core repo for each device is one place to look to find valid pins for any given board, but I'm aware of any way to get that information into pycharm (beyond I guess manually copying the relavent bits into a board.pyi file in the stubs, but that would be impractical at scale for many different device)
there's that from the vscode extension that does build individual stubs
Interesting. Thanks for the link, that does look promising
Yeah, I was wondering if there's something we can do for PyCharm that is similar?
I've tried the VSCode extension, and while it's pretty decent, it's got a few bugs that are pretty irritating. For instance, if you place a non-bundled .mpy file in your CIRCUITPY dir, it will crash any library operations from that VSCode extension.
whoops, board.c that I mentioned above was the wrong file name. pins.c is the actual name of that file. i.e. https://github.com/adafruit/circuitpython/blob/main/ports/atmel-samd/boards/cp_sapling_m0/pins.c
good catch
it is likely possible. But we would need to figure out the best strategy to publish / distribute it. Currently we don't have a plug-in or anything similar for PyCharm. The core stubs exist and can be installed from PyPi, but I don't know if there is a mechanism that would allow pip / pypi to generate the correct board stubs for a given device when the user requests an install.
Maybe the core stubs could include a little bit of actual python code that allows the user to select a device and builds the pyi for them based on the selected device. Or possibly that could get distributed seperately from the stubs if there is a desire to keep that pypi listing to stubs only and no functional code.
I would be willing to contribute to this if anybody is game? I'd probably need some help, though.
For instance, where would we place it? My guess is that we should probably make this somewhat agnostic and then create a plugin or similar for PyCharm to handle the board selection.
I'd definitely be interested in having this functionality and also willing to help out. I will poke around with this script that you linked later this week and ponder some possible ways we could encorporate that or something similar.
If you're available on Monday's we do a weekly meeting, this might make a good topic for "in the weeds" section to see if other folks have any ideas or input regarding what would be the best way to distribute these individualized board stubs.
Wonderful. I am available on Mondays. What time?
And is this something we do separately from the vscode plugin, or should we plan to contribute back to that project? Maybe make the stubs agnostic for any editor?
I don't have any experience making plugins for PyCharm (or any IDEs) so I've not really looked into that at all yet. Ideally I'd love to come up with a way that it won't require a plugin. I.e. download the core stubs, then run some command passing an argument and something generates and replaces the stock board.pyi file in the stubs.
The meeting is at 2pm eastern time. The "in the weeds" section is the last thing we do typically so it's usually 30-45 minutes or so after the start.
How do I join the meeting?
I am definitely fine with just having a command as well.
Join the #circuitpython-dev channel at the time of the meeting, there is a voice channel here in discord as well and that is where we hold the meeting. You need a specific role in the discord here to be able to speak at the meeting as well. I can give you that role if you'd like, and you'll also get mentioned from it on mondays a bit before the metting.
I might should use my proper Discord account for this. Let me figure that out, right fast. This is more of a "gamer/whatever/account."
Sure thing. You can always ask any time in #circuitpython-dev to have the circuitpythonista role assigned to you. Me or another mod will take care of it when the time comes.
here's a dump of the boards that have been generated by the vscode plugin... It's MIT licensed, https://github.com/joedevivo/vscode-circuitpython/blob/master/LICENSE so I figured it was safe enough to share here
@autumn citrus @haughty solar to circle back here, I just successfully used a board.pyi from that tar ball in PyCharm and it works
the combo of finding the correct one requires parsing the vendor and product ID, and checking the correct folder
then including that in the interpreter config's directories
Which were a bit difficult to add: https://www.jetbrains.com/help/pycharm/stubs.html
I wonder if that [adding path] can be scripted?
this was the process that I used for getting the circuitpython stubs before we figured out how to get the stubs listed on PyPi. Now that they are I can install the stubs with pip and pycharm is able to find and use them for helper hints. I think it may be possible to paste your board.pyi file in the right spot inside of the stubs installed via pip to have it get recognized without needing to do the whole add an interpreter path thing.
well, maybe
you'd have to overwrite a board.pyi file somewhere, no?
What I was thinking was, look at these files: https://raw.githubusercontent.com/adafruit/circuitpython/main/ports/raspberrypi/boards/adafruit_feather_rp2040/mpconfigboard.mk basically parse them for the vendor and product IDs and names (so you can list them) and then let user pick, and from there, just copy that specific board.pyi to a place where it can be included? I mean, it could be in the current project, I think?
but from what I can tell, creating local stubs need to completely reproduce the directory structure, basically the same as a mock or whatever
I think you'd overwrite the one in site-packages where the stubs gets installed to from pip.
to think this through, then we'd need to back it up, in case the user wants to switch board, right?
Need to do a bit of research tbh. I think the board.pyi that is included in the stubs is essentially empty (but I haven't verified this yet). If that is the case then there is really nothing important to switch back to. They could want to switch to another board, in which case I envision running the command again with a different argument for the board that they want to change to.
Maybe it would be good to have a way to do multiple boards, or maybe do away with the idea of it conforming to a specific devices altogether and instead include all possible values in the single board.pyi that gets distributed with the stubs. Then there would be no "second step" of running the command. But as a trade-off the board module would also include things that may not be present / accurate for whatever specific device the user is actually working on. So the IDEs code completion / hints might be a little misleading for any given specific device.
The high level choice between those approaches will be good to get input from the group on during the call next week if we can.
okay, I have confirmed that the existing board.pyi file that is distributed today does not contain any pin property names:
"""Board specific pin names
Common container for board base pin names. These will vary from board to
board so don't expect portability when using this module.
.. warning:: The board module varies by board. The APIs documented here may or may not be
available on a specific board."""
from __future__ import annotations
import busio
def I2C() -> busio.I2C:
"""Returns the `busio.I2C` object for the board designated SDA and SCL pins. It is a singleton."""
...
def SPI() -> busio.SPI:
"""Returns the `busio.SPI` object for the board designated SCK, MOSI and MISO pins. It is a
singleton."""
...
def UART() -> busio.UART:
"""Returns the `busio.UART` object for the board designated TX and RX pins. It is a singleton.
The object created uses the default parameter values for `busio.UART`. If you need to set
parameters that are not changeable after creation, such as ``receiver_buffer_size``,
do not use `board.UART()`; instead create a `busio.UART` object explicitly with the
desired parameters."""
...
And does already contain a warning that the values represented in it do not necessarily apply to all devices.
Based on that I am inclined to lean toward just including all possible pins in this device. The more I think about the "run a command" approach I think it may not be something that a lot of people actually end up doing. If we include everything at least the file is helpful to everyone and we just have to be clear about it not applying to all devices, which it does mention already.
oh I was surprised because in BBEdit board. completes to what looks like all the pin names, but they actually come from Blinka (it uses the jedi language server)
is there any meaningful comparison that could happen against, say board.D10 that wouldn't evaluate correctly based on a generic stub with all properties as opposed to a board specific stub?
I think any given pin such as board.D10 would evaluate correctly. The only consequence of containing all possible pins that I can think of is that the IDE would not flag any sort of error if the code in question uses a pin that the users board does not actually have. i.e. it would happily allow you to use board.IO11 without warning since that does exist on some boards, but unless the user is working one of the ones specifically that does have it the code would not actually work as expected on their device.
I would want that warning, for sure.
Maybe some kind of hybrid approach could work. By default board.pyi could contain every pin from every device. But we also provide an optional utility with command that can be run to select a specific single device. Running the command overrides the default pyi fill with one generated for the chosen board. The same utility can have a command that reverts back to the default that contains everything.
That could work. I'm curious to see what people would prefer here. I am more along the lines of I'd rather see a ton of warnings until I have selected a board, than see perfectly happy code that in essence is broken as soon as I upload it to my device.
Are there any instances where using the wrong pin could lead to any mechanical or electrical failures? Is that even a concern? Just trying to make sure some kid (probably me) doesn't burn their house down.
full disclosure, I come at this from a programming background, not an electrical one. I've learned lots, but my knowledge alone is not up to a point where I would stake safety on it. That being said. It could be possible depending on the circuit and what things are hooked up to the micro-controller. But I think this risk exists regardless of the stubs information. As far as I understand it the stubs for board can only tell you whether a given pin exists. (even in the best case where it's catered to a specific board). It can't tell you much more about the pin i.e. where it's located physically on the hardware, or operating voltages or anything else like that. With that in mind I cannot really think of a scenario where the stubs telling you that a pin does or does not exist (whether or not it's actually correct for the device they are using) could itself increase that risk.
That's kind of where I was leaning as well, so we should be good with having all the possible values in the stub, then.