I’m developing a plugin which adds MicroPython support to PyCharm and all other IDEs with the python plugin.
One of the plugin’s features is a built-in MicroPython stub package manager, which will allow users to browse available stub packages, install them and easily activate them in the IDE.
I’m struggling to figure out how sets of .pyi files should properly be attached and detached programatically. I’m currently relying on a very fragile approach of modifying the projectLibraryTable. This doesn’t always work and I’m aware that it isn’t best practice.
I have tried using the AdditionalLibraryRootsProvider:
class MpyAdditionalLibraryRootsProvider : AdditionalLibraryRootsProvider() {
override fun getAdditionalProjectLibraries(project: Project): Collection<SyntheticLibrary> {
val settings = project.service<MpySettingsService>()
val pythonService = project.service<MpyPythonService>()
if (!settings.state.areStubsEnabled || settings.state.activeStubsPackage.isNullOrBlank()) {
println("return 1")
return emptyList()
}
val availableStubs = pythonService.getAvailableStubs()
val activeStubPackage = settings.state.activeStubsPackage
if (!availableStubs.contains(activeStubPackage) || activeStubPackage == null) {
println("return 2")
return emptyList()
}
val rootPath = "${MpyPythonService.stubsPath}/$activeStubPackage"
val virtualFile = LocalFileSystem.getInstance().findFileByPath(rootPath)
if (virtualFile == null) {
println("return 3")
return emptyList()
}
println("Attaching stub package: $virtualFile")
return listOf(
SyntheticLibrary.newImmutableLibrary(
listOf(virtualFile),
emptyList(),
emptySet(),
null
)
)
}
}
fun notifyStubsChanged(project: Project, oldStubPackage: String, newStubPackage: String) {
val settings = project.service<MpySettingsService>()
val pythonService = project.service<MpyPythonService>()
val oldRoots = if (pythonService.getAvailableStubs().contains(oldStubPackage)) {
println("got into old condition")
val oldVirtualFile = LocalFileSystem.getInstance().findFileByPath("${MpyPythonService.stubsPath}/$oldStubPackage")
println(oldVirtualFile)
if (oldVirtualFile != null) listOf(oldVirtualFile) else emptyList()
} else emptyList()
val stubsEnabled = settings.state.areStubsEnabled
val newRoots = if (stubsEnabled && pythonService.getAvailableStubs().contains(newStubPackage)) {
println("got into new condition")
val newVirtualFile = LocalFileSystem.getInstance().findFileByPath("${MpyPythonService.stubsPath}/$newStubPackage")
println(newVirtualFile)
if (newVirtualFile != null) listOf(newVirtualFile) else emptyList()
} else emptyList()
println("Removing old roots: $oldRoots")
println("Adding new roots: $newRoots")
ApplicationManager.getApplication().runWriteAction {
AdditionalLibraryRootsListener.fireAdditionalLibraryChanged(
project,
"MicroPython Stubs",
oldRoots,
newRoots,
"MicroPythonLibraryProvider"
)
}
}
I can see the debug prints activating the correct folders, however, the interpreter still doesn’t recognize the MicroPython specific modules when imported. The same stub packages that I’m attempting to attach here work when I attach them by modifying the projectLibraryTable.
Could someone please help me figure out what the correct way to programatically attach/detach .pyi stub packages is?