WEBVTT

00:00.000 --> 00:14.520
Okay, so thank you very much for joining us for this talk where going to be hearing from John Evans

00:14.520 --> 00:21.120
John is a member of the KeyCAD core development team and he is the author of the new KeyCAD

00:21.120 --> 00:25.080
IPC interface that provides a scripting back end.

00:25.080 --> 00:30.960
So he is going to give us an overview of what this IPC is and how to use it.

00:30.960 --> 00:34.240
So without further ado, please welcome John Evans.

00:34.240 --> 00:40.040
All right, thanks everyone.

00:40.040 --> 00:43.160
So yeah, like Seth said, I've been working on KeyCAD for a long time.

00:43.160 --> 00:48.360
If you're new to the world of open hardware and haven't heard of KeyCAD yet, welcome.

00:48.360 --> 00:52.640
It's a CAD tool, mostly for designing electronics for printed circuit board design, but

00:52.640 --> 00:55.040
it also has a few other applications.

00:55.040 --> 00:59.480
So I'm going to be talking about one of the new features, which is coming in KeyCAD 9.

00:59.480 --> 01:03.520
If you want to hear about the other 500 features, stick around for Wayne's talk a little

01:03.520 --> 01:07.200
bit later, and KeyCAD 9 will be out shortly.

01:07.200 --> 01:11.200
It was going to be out the end of this week, but it's going to be next week because

01:11.200 --> 01:14.960
fuzz them and things so stick around.

01:14.960 --> 01:20.520
So to talk about what I did here, I have to start by talking about why I did it.

01:20.520 --> 01:25.600
If you're familiar with KeyCAD, you probably know that it already has a plug-in system.

01:25.600 --> 01:29.840
KeyCAD has had the ability to add Python plug-ins for quite a long time.

01:29.840 --> 01:34.720
And if you're really into KeyCAD, maybe you've even tried to write some of your own plug-ins.

01:34.720 --> 01:39.640
So why did I make an API if we already have an API?

01:39.640 --> 01:45.280
So the current Python plug-in system is mostly around a tool called Swig, which is a

01:45.280 --> 01:48.560
clever tool that can analyze mostly C++ code.

01:48.560 --> 01:53.480
Now they also support C, and it automatically generates wrappers in a variety of different

01:53.480 --> 02:00.240
languages, and allows you to, for example, call C++ functions directly from Python.

02:00.240 --> 02:07.040
So in the case of KeyCAD, a subset of our C++ application is wrapped using Swig into a Python

02:07.040 --> 02:13.800
module, and plug-ins can then just import that Python module and call into KeyCAD code.

02:13.800 --> 02:14.720
So this is pretty cool.

02:14.800 --> 02:17.480
We don't have to do that much work.

02:17.480 --> 02:19.680
Code is mostly generated for us.

02:19.680 --> 02:23.400
We have some extra code that we had to write, but not that much.

02:23.400 --> 02:28.200
And now Python-based tools can do a lot of different things with KeyCAD, which has been

02:28.200 --> 02:34.040
really great for the ecosystem, because there is now a whole range of tooling that adds

02:34.040 --> 02:41.120
on to KeyCAD does specific things or things that we hadn't yet supported in the main C++ code

02:41.120 --> 02:43.960
base, which is pretty good, right?

02:44.200 --> 02:51.000
Well, maybe this is a bit obvious in hindsight, but this really wasn't the best choice to deliver

02:51.000 --> 02:57.720
an API that works the way that people expect when they hear the phrase API, like not having

02:57.720 --> 03:03.320
the functions you call change every version, or not being able to crash KeyCAD, if you call

03:03.320 --> 03:06.280
functions in the wrong order.

03:06.280 --> 03:12.520
So the main challenge is with Swig, our cover, like a couple of different places.

03:12.520 --> 03:18.400
So first of all, from the point of view of us, the KeyCAD development team, like I said,

03:18.400 --> 03:20.360
the interface is really fragile.

03:20.360 --> 03:24.160
There's no API layer within the KeyCAD code base.

03:24.160 --> 03:28.760
It was just directly, let's take the existing things that KeyCAD is doing, let's make

03:28.760 --> 03:31.280
it so that you can call them from Python.

03:31.280 --> 03:35.640
And this means that we are constantly dealing with challenges when we want to refactor

03:35.640 --> 03:41.640
that code, when we want to deprecate something, or add a new way of doing things, or just

03:41.640 --> 03:45.640
change how we do things internally in order to improve KeyCAD itself.

03:45.640 --> 03:50.460
We have to decide are we going to just break these plugins that are expecting this

03:50.460 --> 03:56.160
old interface, which we sometimes have to do, unfortunately, or are we going to add some

03:56.160 --> 04:00.720
way of preserving backwards compatibility, which sometimes is pretty easy and sometimes

04:00.720 --> 04:06.880
is impossible, and often is forgotten about until later, which is annoying for all of the

04:06.880 --> 04:08.800
Python developers.

04:08.800 --> 04:13.800
In addition to that, which is a big pain for a lot of people, Swig is also a little

04:13.800 --> 04:18.160
bit annoying for us on the development team, because we've been moving to use more and

04:18.160 --> 04:25.840
more modern C++ APIs and types, and Swig is slowly getting better at this, but it's still

04:25.840 --> 04:30.720
not, you know, it's not keeping pace with how we adopt C++ features.

04:30.720 --> 04:34.200
And it also slows down the build process for us, which limits how fast we can iterate

04:34.200 --> 04:36.200
on things.

04:36.200 --> 04:41.200
And like I said, Python plugins are directly reaching into KeyCAD as it is running.

04:41.200 --> 04:45.520
They're running in the same process, they have access to all that memory.

04:45.520 --> 04:50.000
If they do things that don't match the expected contract, that we were thinking about

04:50.000 --> 04:55.280
when we wrote the code, they can just completely break things in very weird ways and cause

04:55.280 --> 04:58.640
an interesting bug reports.

04:58.640 --> 05:00.720
But it doesn't stop there.

05:00.720 --> 05:05.280
The current Python plugin system basically lets plugins assume that the Python bindings

05:05.280 --> 05:09.720
to our core framework library, WSWJits, are available.

05:09.720 --> 05:15.920
And sometimes this has been interesting for packaging, because that binding WX Python

05:15.920 --> 05:21.680
is sometimes out of sync with WX widgets in different platforms, and we've had to patch

05:21.680 --> 05:27.080
around that, and basically spend a bunch of energy maintaining things on the windows and

05:27.080 --> 05:29.440
macOS side, especially.

05:29.440 --> 05:34.960
We also have to bundle our own Python interpreter on those platforms, because we need to ensure

05:35.040 --> 05:40.040
for these plugins that they have, all of these Python modules available with appropriate

05:40.040 --> 05:45.480
versions, and we can't rely on that being installable externally.

05:45.480 --> 05:51.120
So we have to now ship a Python environment, and plugins have to use that environment,

05:51.120 --> 05:57.120
which is challenging for them if they want to then add external Python dependencies, and

05:57.120 --> 06:01.400
sometimes it's just not possible for them to use certain Python dependencies.

06:01.400 --> 06:05.600
There's one Python environment shared by everything, which if you're a Python developer,

06:05.600 --> 06:09.800
you know, is just not a great idea.

06:09.800 --> 06:15.840
If that wasn't enough, it's also not great as a developer if you're trying to build plugins,

06:15.840 --> 06:23.720
because using keycads to run your Python code, the way that it runs is a little bit different

06:23.720 --> 06:28.480
than the way that you would typically run a Python program, and so if you're trying

06:28.520 --> 06:34.200
to test your code, if you're trying to debug in an IDE or anything like that, it's sometimes

06:34.200 --> 06:38.880
possible, but it's very hard to get exactly the same environment and run it in an exactly

06:38.880 --> 06:40.080
the same way.

06:40.080 --> 06:44.040
So sometimes you just have to test things the brute force way.

06:44.040 --> 06:48.680
We have a built-in Python console that lets you have a Python repel and just test things

06:48.680 --> 06:49.680
out.

06:49.680 --> 06:54.280
But if you're used to developing Python, maybe you're used to a little bit nicer tooling,

06:54.280 --> 07:00.920
and this built-in console is something that the keycad team now has to maintain, and

07:00.920 --> 07:06.840
it's another challenge and another thing that makes developing for keycad a little bit bespoke

07:06.840 --> 07:11.120
compared to other kinds of Python development.

07:11.120 --> 07:15.800
So that's where we are, and it's taken a long time to develop something better along the

07:15.800 --> 07:20.360
way we considered a few options that we then didn't do, which I think are an interesting

07:20.360 --> 07:21.840
dimension.

07:21.840 --> 07:25.840
So first of all, we could have just made a real API layer in C++, and then pointed

07:25.840 --> 07:28.640
to Swiget that instead of at the internals.

07:28.640 --> 07:32.320
This would have been relatively straightforward, and it would have probably totally solved

07:32.320 --> 07:37.080
those fragility problems where you know, function names are changing every keycad version.

07:37.080 --> 07:40.600
The issue is that most of those other problems would have remained.

07:40.600 --> 07:45.040
So we have known for a while that we wanted to move away from Swig.

07:45.040 --> 07:50.040
And we also spend a little while looking at a library called Pi by 11, which is kind of serving

07:50.040 --> 07:55.520
the same kind of function as Swig, but in a more manual way where you have more control

07:55.520 --> 07:57.120
over how it works.

07:57.120 --> 08:02.120
And this might have solved a few more of the problems, but definitely not all of them.

08:02.120 --> 08:07.200
So about two years ago, I wrote an RFC for the team that basically said, what if we

08:07.200 --> 08:08.840
went in a different direction here?

08:08.840 --> 08:13.000
What if we could completely remove Python from the core of keycad and build a different

08:13.000 --> 08:14.640
kind of API?

08:14.640 --> 08:19.240
So over that window, I built a proof of concept, and it seemed to be working pretty well,

08:19.240 --> 08:23.760
time passed, and here we are now about to ship the first real version of this with keycad

08:23.760 --> 08:24.760
9.

08:24.760 --> 08:27.880
So let's talk about the IPC API.

08:27.880 --> 08:30.920
What I wanted in this API can basically be summed up like this.

08:30.920 --> 08:35.800
First of all, we wanted to be able to change any internals in keycad and hide that change

08:35.800 --> 08:37.600
from all the API users.

08:37.600 --> 08:43.120
We should be able to do normal things that people expect, like have a sane deprecation policy

08:43.120 --> 08:47.000
and have forwards and backwards compatibility wherever possible.

08:47.000 --> 08:51.400
In the end of all, API users should no longer have direct access to keycad internal

08:51.400 --> 08:52.400
state.

08:52.400 --> 08:57.520
We want to run them in external processes and keep them from doing, let's say, accidental

08:57.520 --> 08:59.080
evil.

08:59.080 --> 09:03.560
And third, the developer experiences important, both for us the keycad team and for all

09:03.560 --> 09:08.600
of the API users, if we want this thing to be adopted and useful, it has to be better

09:08.600 --> 09:13.360
than what exists out there right now, not just different.

09:13.360 --> 09:15.120
So here's how it works at a high level.

09:15.120 --> 09:20.080
The API is using protocol buffers to define messages, messages that are passed back and

09:20.080 --> 09:25.800
forth between keycad and an external application over unic sockets or Windows name pipes.

09:25.800 --> 09:29.800
And we use a library called nanomessage next generation, which I'll just call NNG from

09:29.800 --> 09:36.520
now on because it's shorter as an abstraction layer over those sockets and pipes.

09:36.520 --> 09:37.720
So let's start at the bottom.

09:37.720 --> 09:38.720
Why NNG?

09:38.720 --> 09:40.320
It's a question I get sometimes.

09:40.320 --> 09:44.200
I looked at a number of different options that could solve the problem I had where I want

09:44.200 --> 09:49.280
to send bytes back and forth between keycad and other things on the same machine.

09:49.280 --> 09:54.440
And basically, NNG came out on top because it's pretty simple to use and very few lines

09:54.440 --> 09:55.440
of code.

09:55.440 --> 10:00.840
And those very few lines of code are using the native platform IPC mechanisms.

10:00.840 --> 10:05.120
The same code does the right thing on Windows or on non-Windows and you don't have to

10:05.120 --> 10:08.280
care that much about the differences there.

10:08.280 --> 10:13.480
And it has all the availability we needed it to be in terms of what platforms it supported

10:13.480 --> 10:16.000
and what languages it supported.

10:16.000 --> 10:18.960
And basically, I didn't find a good reason not to use it.

10:18.960 --> 10:23.240
And I also looked at a lot of other options so you can see some of them down here.

10:23.240 --> 10:29.040
And all of these other options came out as either more complicated or they had some drawback

10:29.040 --> 10:34.440
or in some way they were trying to solve a different set of problems than my problems.

10:34.440 --> 10:41.480
So I think there are great solutions for different problems but they weren't the one for me.

10:41.480 --> 10:44.240
So then one layer up, yProtobuff.

10:44.240 --> 10:49.160
So if you're not familiar with Protobuff, basically, is a project from Google where you define

10:49.160 --> 10:51.960
messages using a domain-specific language.

10:51.960 --> 10:58.480
And then use a tool that compiles that DSL into various different wrappers essentially

10:58.480 --> 11:02.920
in a bunch of different target languages that implement those messages.

11:02.920 --> 11:08.680
And we use this because we can then define most of the keycad API in terms of those DSL

11:08.680 --> 11:12.400
messages which are pretty easy to parse but look at some in a bit.

11:12.400 --> 11:17.520
And it means it's really easy to keep keycad synced up with the third party language bindings.

11:17.520 --> 11:23.000
So Protobuff is not perfect and in fact it has some downsides that are important to be aware

11:23.000 --> 11:25.800
of if you want to use it for your project.

11:25.800 --> 11:30.440
But ultimately I did look at a number of alternatives to Protobuff and they either didn't

11:30.440 --> 11:34.360
have all the features we need or they weren't nearly as popular.

11:34.360 --> 11:40.320
And I decided after looking at what was available and all of the resources I could find,

11:40.320 --> 11:44.920
people posting about challenges they had had and how they had overcome those challenges.

11:44.920 --> 11:50.000
I wanted to go with the thing that was the most widely used because I could see how these

11:50.000 --> 11:53.320
people were doing similar things and how they had solved these problems.

11:53.320 --> 11:57.000
And some of the alternatives I looked at, there just wasn't that much information about people

11:57.000 --> 11:58.800
solving similar problems.

11:58.800 --> 12:01.640
And I think that kind of thing is important.

12:01.640 --> 12:05.120
So here are some example Protobuff messages from the Kika API.

12:05.120 --> 12:10.360
You can think of them kind of like structures if you know a language like CRC++.

12:10.360 --> 12:16.160
You can see some of these have primitive types like these in 64s and then a lot of them

12:16.160 --> 12:20.760
are composed out of other messages internally.

12:20.760 --> 12:27.320
So here's an example of a command that an API client might want to send to get the bounding

12:27.320 --> 12:29.880
box or extends from a text object.

12:29.880 --> 12:34.760
So we're going to have this certain other message that specifies what the text is and

12:34.760 --> 12:39.560
we're going to get back that box 2 we just saw with the bounding box.

12:39.560 --> 12:43.280
So to actually send and receive these messages, we have these what are called envelope

12:43.280 --> 12:49.280
messages that have a request and response inside as an any type which is a Protobuff feature

12:49.280 --> 12:54.880
that basically lets you do runtime type introspection so that we can dynamically dispatch a handler

12:54.880 --> 12:58.440
depending on what kind of message we receive coming in.

12:58.440 --> 13:03.960
Protobuff defines a binary format that these messages get serialized into and that serialized

13:03.960 --> 13:07.160
format is what we send back and forth over the wire.

13:07.160 --> 13:12.960
And one note is that Protobuff can also be serialized as text that is basically JSON.

13:12.960 --> 13:17.000
So we have a debugging feature where you can actually dump every message going back and

13:17.000 --> 13:21.640
forth to a text log and see what's going on which is really handy.

13:21.640 --> 13:25.680
So we have these messages, how do we actually hook them up to Kikaad?

13:25.680 --> 13:28.560
At a super high level, Kikaad is an event driven application.

13:28.560 --> 13:32.080
One of our other devs, Ian, who's up there, did a deep dive into this on our developer

13:32.080 --> 13:36.880
meetup on Friday and you can watch that on our YouTube channel if you want the full details.

13:36.880 --> 13:40.960
But at a really high level, events are coming in from various sources, maybe from an input

13:40.960 --> 13:45.360
device, maybe from the operating system and they get routed to various event handlers

13:45.360 --> 13:46.840
by it at Stasher.

13:46.840 --> 13:49.120
This is all happening in a single thread.

13:49.120 --> 13:53.360
So all these handlers are designed to be non-blocking and sometimes they have their own

13:53.360 --> 13:57.760
internal event loops and all of this is going on with various core routine magic that

13:57.760 --> 14:02.920
lets us have somewhat sane code, but I'm going to skip over that today.

14:02.920 --> 14:08.120
So to hook into this, I basically added a new type of event and this is called whenever

14:08.120 --> 14:12.480
any kind of API message comes in and that is routed to a new kind of handler which is

14:12.480 --> 14:15.360
handling the API messages.

14:15.360 --> 14:19.840
And this handler is unpacking that envelope message and figuring out, okay, what should I

14:19.840 --> 14:21.240
do with this?

14:21.240 --> 14:27.520
It has its own set of handlers that are all supporting the actual API functions.

14:27.520 --> 14:32.200
Some of those functions might be able to return some calculation immediately.

14:32.200 --> 14:37.240
Some may be able to create their own other events and post those to the event loop that

14:37.240 --> 14:39.720
will then get handle that some later time.

14:39.720 --> 14:44.120
So all of these have to be non-blocking and essentially return to the client immediately.

14:44.120 --> 14:49.560
So if you want to call an API command that is going to take some time to do, you are

14:49.560 --> 14:53.360
just going to immediately get a reply that, hey, this command started and you are going

14:53.360 --> 14:56.880
to need to check back to see when it finished.

14:56.880 --> 15:00.520
Some of the details of this by the way can be kind of hidden from the actual users of the

15:00.520 --> 15:05.880
API through the client libraries to make it a little bit less complicated.

15:05.880 --> 15:10.240
And one other thing I should mention is that these API handlers are dynamically registered.

15:10.240 --> 15:15.360
So for example, if you open a keypad project manager, you might only have a few handlers,

15:15.360 --> 15:19.800
but then when you open up the PCB editor, it will register a PCB handler because now you

15:19.800 --> 15:24.520
can work with a board and now you can call get board and refill zones and things like that.

15:24.520 --> 15:29.520
And if you close that PCB editor, it will get the registered and then if you say refill zones,

15:29.520 --> 15:35.120
you will instead get back a message saying, hey, there's not a handler for that right now.

15:35.120 --> 15:39.600
So because of this design, the API events are synchronous and are getting sequenced in with

15:39.600 --> 15:43.480
all of the user input, so that's something you have to keep in mind as a plug-in developer

15:43.480 --> 15:48.600
is that you're not kind of operating in parallel with the user, but with the user.

15:48.600 --> 15:54.040
So you have to keep in mind how you want your plug-in actions to get sequenced in as under

15:54.040 --> 15:55.400
steps.

15:55.400 --> 15:59.800
And sometimes the user will be doing something that we don't want to allow interruption,

15:59.800 --> 16:03.920
like if you're in the middle of routing tracks, you're API plug-in to be able to just delete

16:03.920 --> 16:05.440
the board.

16:05.440 --> 16:10.200
So sometimes the API will say, hey, I'm busy, you need to try that again later.

16:10.200 --> 16:14.200
So that's an overview of how it's implemented, but what about using it?

16:14.200 --> 16:18.760
Well, we're releasing Python bindings for the API along with HIKI 9, and you can actually

16:18.760 --> 16:22.600
install it right now if you have a nightly and want to try it out.

16:22.600 --> 16:27.200
So it's there in the Python package index, and that's the source code for it.

16:27.200 --> 16:31.200
Just make sure that you go into your KIKI preferences and turn on the API because it's not

16:31.200 --> 16:34.320
on by default right now.

16:34.320 --> 16:37.720
So here's a simple example of creating a zone on whatever board is open.

16:37.720 --> 16:42.360
We start by importing some things, and then getting a handle to the open KIKI instance,

16:42.360 --> 16:46.440
and then the board, and then we construct a zone object that has certain properties, which

16:46.440 --> 16:50.360
is most of the code you see there, and finally, we put it on the board.

16:50.360 --> 16:55.680
By the way, we could be developing this from any IDE or from a REPL outside of KIKI,

16:55.680 --> 16:59.280
and it would work the same way as if it was running as a plug-in from KIKI.

16:59.280 --> 17:01.200
So there's no longer any difference there.

17:01.200 --> 17:05.960
You can use whatever kind of Python environment is most comfortable for you.

17:05.960 --> 17:10.600
One thing I want to point out is that these two lines are the only lines that are communicating

17:10.600 --> 17:12.760
with KIKI using the API.

17:12.760 --> 17:18.360
So the rest of it is building up objects and Python that are representing protobuff messages

17:18.360 --> 17:21.640
that will then be sent.

17:21.640 --> 17:23.040
You could also take away that hunt.

17:23.040 --> 17:25.920
It's a lot of steps to define an outline for a zone.

17:25.920 --> 17:26.920
And this is true.

17:26.920 --> 17:32.960
And I guess my point here is that even if we make the API really easy to use and Python

17:33.040 --> 17:38.640
and all that good stuff, you're still going to need to kind of understand KIKI some places

17:38.640 --> 17:43.760
to understand, okay, the zone is complicated because it can actually have a arcs in its border

17:43.760 --> 17:45.880
and it can have internal cutouts and things like this.

17:45.880 --> 17:48.760
And so the API describes all of that.

17:48.760 --> 17:52.840
So that just is on us to make sure that all of these things are documented well

17:52.840 --> 17:56.320
and have good examples for you to work from.

17:56.320 --> 18:00.160
One thing that I'm not going to have time for too much detail on is that there is a new

18:00.160 --> 18:04.920
Python plugin launching system coming with KIKI 9, which is using virtual environments

18:04.920 --> 18:09.680
per plugin and automatic dependency installation that mostly works.

18:09.680 --> 18:14.800
And this, you know, I'm sure there's a few edge cases because that's Python where it

18:14.800 --> 18:18.520
doesn't work, but for a few people who've been testing it, it seems to work, which is

18:18.520 --> 18:22.880
really awesome because now plugins can use whatever UI to locate they want.

18:22.880 --> 18:28.040
And as a bonus, it can launch any executable file so you don't necessarily need to use

18:28.040 --> 18:31.120
Python if you don't want to.

18:31.120 --> 18:36.040
So KIKI 9 is coming from with the first public version of this API, but I'm definitely

18:36.040 --> 18:37.040
not done.

18:37.040 --> 18:41.160
There are a lot of features that are important to add that will be coming in future versions.

18:41.160 --> 18:43.200
And probably some things I don't even know I should add.

18:43.200 --> 18:48.040
So I'm definitely looking for feedback from early users of this, you know, up next I'm

18:48.040 --> 18:52.240
going to be working on integration with the footprint editor and replacing the footprint

18:52.240 --> 18:57.200
wizard systems so that we can have a shared code base between our library team and KIKI

18:57.200 --> 19:03.400
had itself, you know, called back to the CAD query talk, which just happened.

19:03.400 --> 19:05.520
We also want to support headless operations.

19:05.520 --> 19:10.040
And since I know a lot of people are wondering, yes, we are bringing this to schematic

19:10.040 --> 19:11.040
and symbols.

19:11.040 --> 19:12.640
No, it's not in nine.

19:12.640 --> 19:16.960
Basically, we just ran out of time to do the necessary internal changes to the schematic

19:16.960 --> 19:19.920
editor to make that possible.

19:19.920 --> 19:23.560
So if you want to learn more, you can find a little bit more detail than I was able to cover

19:23.560 --> 19:31.400
today in the DevDox link here as well as more information about creating new API plugins.

19:31.400 --> 19:36.040
KIKI Python is up on Python package index so you can check that out and there are some

19:36.040 --> 19:42.840
examples, basic plugins and also just some quick scripts in that repo.

19:42.840 --> 19:46.440
So with that, any questions?

19:46.440 --> 20:09.720
Hi, I was just wondering, how does that work when you have multiple KIKI at instance running,

20:09.720 --> 20:13.280
like, how do you select one or something like that?

20:13.280 --> 20:14.280
Great question.

20:14.320 --> 20:18.760
Question was, if you have multiple different instances, how do you know which one to talk to?

20:18.760 --> 20:23.880
So there will be a default path that the first instance will grab.

20:23.880 --> 20:28.880
And then after that, if it's already taken, you will have a different way to communicate

20:28.880 --> 20:34.000
that will have different process ID in the path essentially.

20:34.000 --> 20:39.000
When you launch a plugin from KIKI, it passes the information through environment variables

20:39.000 --> 20:43.080
as to where you should communicate with this KIKI that just launched it.

20:43.080 --> 20:48.120
And if you are running from a debugger, you would have to manually override that if you didn't

20:48.120 --> 20:49.600
want to use the default path.

20:49.600 --> 20:56.280
So if you're developing a Python plugin, I recommend using just one instance at a time.

20:56.280 --> 21:03.720
Can you go a bit into, sorry, can you go a bit into how the virtual environment installation

21:03.720 --> 21:08.000
works on, like, how much Python installation?

21:08.080 --> 21:15.480
Yes, so the virtual environment is today pretty basic and assumes one particular workflow,

21:15.480 --> 21:20.200
which has so far been working in my tests, but I know it won't cover all cases.

21:20.200 --> 21:26.080
So basically, if you're plugin in your plugin definition file, says it's a Python plugin,

21:26.080 --> 21:32.040
then we will look for a requirements text file, and we will attempt to install.

21:32.040 --> 21:36.560
So we will use Python, basically you can configure which Python interpreter to use,

21:36.560 --> 21:40.800
and then we will assume that we have access to the virtual environment module.

21:40.800 --> 21:44.200
So if you somehow don't have that, it won't work.

21:44.200 --> 21:49.480
And then we will attempt to install PIP, and then we will attempt to use PIP to install your dependencies.

21:49.480 --> 21:55.160
And if you can't install PIP, or if your dependencies don't have binary wheels, it won't work,

21:55.160 --> 21:57.240
and you'll have to do something manual.

21:57.240 --> 21:59.720
But that's something that I'm sure could be improved in the future.

21:59.720 --> 22:10.720
Well, we have more questions if our pod, if you could start getting set up.

22:10.720 --> 22:17.480
One question if my plugin is doing something both with schematics and PCB editors,

22:17.480 --> 22:21.200
are a way that I can launch any application.

22:21.200 --> 22:26.760
You mentioned that it has to be running in order to understand the command.

22:26.760 --> 22:31.400
So if you want to have a plugin that launches kick-out?

22:31.400 --> 22:37.640
No, if my plugin is like printing schematics and generating Gorbors, for example,

22:37.640 --> 22:46.680
it has to deal with schematics and PCB new.

22:46.680 --> 22:49.080
And if one of them is not running, one will happen.

22:49.120 --> 22:57.320
You mentioned that schematics has to be running in order to understand commands for schematics.

22:57.320 --> 23:02.200
Yeah, so today you can only with the current plugin system.

23:02.200 --> 23:07.880
It's intended for the use case of the user launches it from the editor.

23:07.880 --> 23:10.880
So your plugin cannot open the editor.

23:10.880 --> 23:13.880
The user has to open the editor and then launch the plugin.

23:13.880 --> 23:16.600
In the future, we won't have that restriction.

23:16.600 --> 23:19.400
One of the things I put on the roadmap was a headless mode.

23:19.400 --> 23:23.000
So right now you actually can't do plotting and exporting with this.

23:23.000 --> 23:27.960
That's well supported by keycud CLI, so that's our recommendation right now.

23:27.960 --> 23:32.520
But in the future, you will be able to do things like that through a special mode of keycud CLI,

23:32.520 --> 23:42.280
where you can have your plugin say, now I want to open this schematic file and work with it.

23:42.280 --> 23:46.520
Any further questions?

23:46.520 --> 23:48.680
Okay, thank you, John.

