WEBVTT

00:00:00.020 --> 00:00:07.940
This episode is all about Beware, the project that is working towards true native apps built on Python, especially for iOS and Android.

00:00:08.740 --> 00:00:13.040
Russell's been at this for more than a decade, and the progress is now hitting critical mass.

00:00:13.820 --> 00:00:18.440
We'll cover the Toga GUI toolkit, building and shipping your apps with Briefcase,

00:00:18.840 --> 00:00:23.900
and the newly official support for iOS and Android in CPython, and much more.

00:00:24.700 --> 00:00:29.260
I can't wait to explore how Beware opens up the entire mobile ecosystem for Python developers,

00:00:29.620 --> 00:00:30.380
So let's jump right in.

00:00:31.100 --> 00:00:35.800
This is Talk Python To Me, episode 499, recorded February 18th, 2025.

00:00:37.239 --> 00:00:39.240
Are you ready for your host, please?

00:00:40.100 --> 00:00:42.940
You're listening to Michael Kennedy on Talk Python To Me.

00:00:43.480 --> 00:00:46.560
Live from Portland, Oregon, and this segment was made with Python.

00:00:49.820 --> 00:00:52.680
Welcome to Talk Python To Me, a weekly podcast on Python.

00:00:53.280 --> 00:00:54.940
This is your host, Michael Kennedy.

00:00:55.270 --> 00:00:57.840
Follow me on Mastodon, where I'm @mkennedy,

00:00:58.000 --> 00:01:03.280
and follow the podcast using @talkpython, both accounts over at fosstodon.org,

00:01:03.680 --> 00:01:08.180
and keep up with the show and listen to over nine years of episodes at talkpython.fm.

00:01:08.780 --> 00:01:12.640
If you want to be part of our live episodes, you can find the live streams over on YouTube.

00:01:13.220 --> 00:01:18.920
Subscribe to our YouTube channel over at talkpython.fm/youtube and get notified about upcoming shows.

00:01:19.780 --> 00:01:22.660
This episode is sponsored by Posit and Posit Workbench.

00:01:23.500 --> 00:01:28.180
Posit Workbench allows data scientists to code in Python within their preferred environment

00:01:28.650 --> 00:01:30.680
without any additional strain on IT.

00:01:31.440 --> 00:01:34.640
It gives data scientists access to all the development environments they love,

00:01:34.820 --> 00:01:37.720
including Jupyter Notebooks, JupyterLab, Positron, and VS Code,

00:01:38.200 --> 00:01:40.960
and helps ensure reproducibility and consistency.

00:01:41.360 --> 00:01:43.620
If you work on a data science team where consistency matters,

00:01:44.180 --> 00:01:45.540
check out Posit Workbench.

00:01:46.180 --> 00:01:48.620
Visit talkpython.fm/workbench for details.

00:01:50.280 --> 00:01:52.160
Russell, welcome to Talk Python To Me.

00:01:52.430 --> 00:01:53.120
Great to have you back.

00:01:53.340 --> 00:01:54.780
Hey, thank you for having me again.

00:01:55.160 --> 00:01:56.540
Yeah, it's good to have you back.

00:01:56.810 --> 00:02:00.040
You've been diligently working away on Beware,

00:02:00.400 --> 00:02:04.080
and I am very excited to see what you all are up to these days

00:02:04.230 --> 00:02:06.060
because I have very high hopes for the project.

00:02:06.620 --> 00:02:08.179
I'm multiple angles.

00:02:08.860 --> 00:02:09.240
I'm a fan.

00:02:09.539 --> 00:02:10.200
Thank you very much.

00:02:10.800 --> 00:02:14.240
Yeah, I have been very busy, particularly busy over the last couple of years,

00:02:14.740 --> 00:02:16.080
but, yeah, we've made some good progress,

00:02:16.380 --> 00:02:21.500
and, yeah, we started to see the fruits of what is now at this point almost a 10-year –

00:02:21.500 --> 00:02:22.920
well, it is over a 10-year project.

00:02:23.020 --> 00:02:23.320
So

00:02:23.320 --> 00:02:26.160
you've been at it for a long time and it's been quite a while since I had you on the show

00:02:26.520 --> 00:02:30.160
and Talk Python has been around for almost 10 years. And so I know you've been at it for

00:02:30.580 --> 00:02:34.860
quite a while. That's awesome. And it seems like you're starting to get some real traction,

00:02:35.120 --> 00:02:36.560
which it couldn't come soon enough.

00:02:36.800 --> 00:02:40.000
Yes. And the good, the sort of the reason why that has

00:02:40.220 --> 00:02:46.199
happened is basically about three years ago, I was hired by Anaconda to work on their open source

00:02:46.220 --> 00:02:53.360
team um so i am employed full-time just to work on beware uh with another guy malcolm smith who

00:02:53.680 --> 00:02:59.140
works with me based in based in london um and yeah just like the short version is it is amazing how

00:02:59.220 --> 00:03:02.780
much progress you can make when you have two people working full-time on an open source project and

00:03:02.850 --> 00:03:03.480
like just a lot

00:03:03.480 --> 00:03:07.880
of stuff all the yeah yeah i've always thought that about things it's like there's

00:03:08.260 --> 00:03:12.519
the main product or the main project of the main library and then there's all these little

00:03:13.000 --> 00:03:18.480
not fun, annoying details that somebody just has to grind through. And when it's two hours in on a

00:03:18.580 --> 00:03:21.180
weekend where you're excited about it, it's not the final

00:03:21.180 --> 00:03:21.920
push over the

00:03:21.920 --> 00:03:23.300
finish line, grindy details

00:03:23.460 --> 00:03:28.480
that people want to do. And so when it's, I wake up today and we're pushing it forward every day,

00:03:28.920 --> 00:03:29.140
it's

00:03:29.140 --> 00:03:30.020
awesome. Yeah. And

00:03:30.020 --> 00:03:34.180
a lot of it is also just like CPython is an awesome project, but it's a

00:03:34.280 --> 00:03:39.459
big project and getting anything to happen. Like it's a, you've got to move a big project in the

00:03:39.420 --> 00:03:43.580
direction of something, that takes a lot of political effort. It takes a lot of time. It

00:03:43.680 --> 00:03:46.740
takes a lot of hanging around our mailing lists. And at some point, if you're just trying to do it

00:03:46.800 --> 00:03:49.860
on like two hours on a weekend, that just doesn't happen. But

00:03:49.860 --> 00:03:50.460
if you can actually

00:03:50.460 --> 00:03:50.960
say, okay,

00:03:51.420 --> 00:03:55.440
every morning I'm going to spend an hour responding to all the email that I've received about this

00:03:55.580 --> 00:03:59.260
project, well, then you can do it. And then you can actually have a meaningful progress.

00:03:59.880 --> 00:04:05.159
And then there's also things like, I don't use, I have no disrespect whatsoever for anybody who

00:04:05.180 --> 00:04:10.320
uses Windows. I don't use Windows on a day-to-day basis. It is, as a weekend project, very hard to

00:04:10.320 --> 00:04:16.739
get me excited about working on Windows app signing as a personal side project. And I am going to see

00:04:17.040 --> 00:04:21.400
no benefit out of that whatsoever. But when I've got time for it, a lot of other stuff

00:04:22.420 --> 00:04:26.420
becomes more plausible and more palatable as a thing to look at.

00:04:26.740 --> 00:04:31.280
Yeah. I want to let you do an introduction for yourself real quick before we dive into it. But I

00:04:31.260 --> 00:04:35.480
want to tie this back to PyScript a little bit as well. I think there might be some times that

00:04:35.620 --> 00:04:35.960
align there.

00:04:36.300 --> 00:04:37.860
There absolutely are. Yeah,

00:04:37.960 --> 00:04:40.200
I can imagine. So for folks who haven't listened

00:04:41.220 --> 00:04:46.220
over all of the years and have a really great memory, tell us, who are you? What are you up

00:04:46.300 --> 00:04:48.120
to these days? Give us a bit of a hint already.

00:04:48.460 --> 00:04:53.100
So hi, I'm Russell. I am in days of yore,

00:04:53.120 --> 00:04:57.419
I was possibly better known for my contributions to the Django project. I was a very early contributor

00:04:57.440 --> 00:04:59.140
or a member of the Django core team.

00:04:59.960 --> 00:05:01.040
I don't do anywhere,

00:05:01.500 --> 00:05:03.260
well, I basically don't do any Django work at this point.

00:05:03.380 --> 00:05:05.700
My interests have moved away from web stuff generally.

00:05:06.760 --> 00:05:08.300
For about the last 10 years,

00:05:08.390 --> 00:05:10.400
I have been working on the Beware project,

00:05:10.700 --> 00:05:14.540
which is a collection of tools and libraries

00:05:14.940 --> 00:05:17.620
to support building graphical user interfaces,

00:05:18.220 --> 00:05:19.440
native graphical user interfaces

00:05:19.440 --> 00:05:20.420
in Python

00:05:21.020 --> 00:05:23.640
and targeting that at desktop platforms,

00:05:23.650 --> 00:05:25.300
so Windows, Linux, macOS,

00:05:25.560 --> 00:05:27.960
but also mobile platforms, iOS and Android,

00:05:28.510 --> 00:05:31.120
the web as a GUI user interface,

00:05:32.050 --> 00:05:33.680
and more recently also TextUID,

00:05:33.680 --> 00:05:34.880
the console-based applications.

00:05:35.680 --> 00:05:38.100
Working on the premise that every platform

00:05:38.600 --> 00:05:41.920
has a concept of a native interface.

00:05:41.990 --> 00:05:43.700
Now, there is a concept of a button

00:05:44.240 --> 00:05:45.200
on all of those platforms.

00:05:45.740 --> 00:05:48.100
How you access that button is different on every platform.

00:05:48.720 --> 00:05:51.340
And Beware's goal is to, one,

00:05:51.800 --> 00:05:54.180
put a clean interface around the outside of that

00:05:54.100 --> 00:05:55.760
so you can have a common API for,

00:05:55.800 --> 00:05:57.160
I just want a button on the screen

00:05:57.240 --> 00:05:59.260
so when I push the button, the light goes Bing.

00:06:00.100 --> 00:06:02.220
One, provide a common cross-platform API for that.

00:06:02.680 --> 00:06:05.300
And then two, provide the mechanisms to say,

00:06:05.460 --> 00:06:07.300
okay, I have written my machine

00:06:07.460 --> 00:06:08.340
that goes Bing with a button.

00:06:08.980 --> 00:06:09.920
I want to give it to someone

00:06:10.600 --> 00:06:11.900
and I want to give it to them

00:06:12.520 --> 00:06:16.060
using the platform's app infrastructure.

00:06:16.280 --> 00:06:18.960
I just want to have it on this person's iPhone

00:06:19.340 --> 00:06:21.260
or give it to a Windows user

00:06:21.400 --> 00:06:23.280
and have them just run it

00:06:23.520 --> 00:06:26.000
without having to go through, okay, well, first you've got to set up

00:06:26.000 --> 00:06:28.800
a Python virtual environment, and then you've got to pip install it.

00:06:29.780 --> 00:06:31.440
Are you familiar with the terminal?

00:06:32.010 --> 00:06:32.940
Why don't you become

00:06:32.940 --> 00:06:33.880
familiar with the terminal?

00:06:33.970 --> 00:06:34.080
We'll

00:06:34.080 --> 00:06:34.740
start there, yeah.

00:06:35.220 --> 00:06:39.480
From my perspective, there are absolutely, as a developer,

00:06:39.650 --> 00:06:40.400
I need to know that.

00:06:40.440 --> 00:06:43.200
As a Python user, I need to know how that stuff works.

00:06:43.520 --> 00:06:44.060
If I have

00:06:44.060 --> 00:06:44.980
written a program

00:06:44.980 --> 00:06:46.560
and I want to give it to someone,

00:06:47.020 --> 00:06:50.899
if they need to know what Python is, I have failed as a developer

00:06:50.920 --> 00:06:53.560
because as an end user, they don't care.

00:06:53.920 --> 00:06:54.000
They

00:06:54.000 --> 00:06:55.220
just want to spool the app

00:06:55.220 --> 00:06:56.200
the same way as everything.

00:06:56.320 --> 00:06:58.680
They want to double click on an icon and make the thing work.

00:06:59.420 --> 00:07:00.880
And that's the other part of

00:07:00.880 --> 00:07:01.220
doing it.

00:07:01.340 --> 00:07:01.700
That's awesome.

00:07:01.820 --> 00:07:06.120
And I would say if it's not possible to have a little colorful,

00:07:06.760 --> 00:07:09.720
native-looking icon, either in your dock, in your taskbar,

00:07:10.040 --> 00:07:12.460
in your app launcher on your phone that you touch,

00:07:12.740 --> 00:07:13.660
and the thing comes to life,

00:07:14.140 --> 00:07:16.140
that's not a real app delivery platform.

00:07:16.660 --> 00:07:19.259
Yeah, it is a very powerful language

00:07:19.280 --> 00:07:21.060
with which you can do all sorts of incredible things.

00:07:21.300 --> 00:07:22.020
But at the end of the day,

00:07:22.200 --> 00:07:24.460
you've got to give that thing to someone to do it

00:07:24.820 --> 00:07:27.540
without giving them a three-year degree in computer science

00:07:27.720 --> 00:07:29.160
before they can actually do the damn thing.

00:07:29.340 --> 00:07:29.580
Sure.

00:07:29.660 --> 00:07:32.100
And even if they can, they might not want to, right?

00:07:32.440 --> 00:07:32.660
Yeah, exactly.

00:07:32.720 --> 00:07:33.440
I don't want to do that.

00:07:33.620 --> 00:07:33.980
It's a barrier.

00:07:34.480 --> 00:07:35.020
Yeah, yeah.

00:07:35.360 --> 00:07:36.180
I love my web browser.

00:07:36.320 --> 00:07:37.320
I don't want to start it that way.

00:07:37.540 --> 00:07:37.720
Yeah.

00:07:39.160 --> 00:07:43.760
Yeah, so the extension of that then is that particularly for the web,

00:07:44.900 --> 00:07:46.280
for iOS and for Android,

00:07:47.080 --> 00:07:50.720
there's kind of the foundational question then of, well, okay,

00:07:50.760 --> 00:07:53.940
but how do I run Python on that device at all? You

00:07:53.940 --> 00:07:54.000
know,

00:07:54.040 --> 00:07:54.680
how do I

00:07:54.680 --> 00:07:56.240
get Python on my iPhone?

00:07:57.420 --> 00:08:01.240
And I don't just want to have like a Python interpreter on my iPhone because

00:08:01.280 --> 00:08:04.000
you don't like the, an iPhone, everything is inside an app.

00:08:04.020 --> 00:08:06.840
So I need to have it inside my app. How do I get it inside the app?

00:08:06.840 --> 00:08:07.940
And then when it's inside the app,

00:08:08.240 --> 00:08:11.480
how do I invoke the code that's there and so on and so on.

00:08:12.000 --> 00:08:16.499
So a lot of the work that's kind of been leading up to this point is like

00:08:16.520 --> 00:08:22.620
literally how to make cpython work on ios how do i make cpython work on android how do i make cpython

00:08:22.740 --> 00:08:23.900
work in the browser um

00:08:23.900 --> 00:08:29.220
right so yeah that's awesome a very very interesting and powerful goal i think

00:08:29.520 --> 00:08:35.320
let's not talk about it just yet but i think it's gonna it's it's really it leaves python open to

00:08:35.560 --> 00:08:40.360
being not the default choice even though it's a really great programming default choice language

00:08:40.880 --> 00:08:44.639
somebody says i want to i want to get started programming awesome you should check out python

00:08:44.920 --> 00:08:48.600
yeah i want to build an app you shouldn't check out python right like you don't want that to be the

00:08:48.820 --> 00:08:53.100
the answer right and this path that you're you're making you're hacking away

00:08:53.100 --> 00:08:53.940
in the forest forest

00:08:54.760 --> 00:08:56.180
yeah exactly one

00:08:56.180 --> 00:09:00.120
of the one of the stimulus for me working on this there was a couple

00:09:00.260 --> 00:09:04.700
but one of them is that my son who is now first year university but at the time when i was sort

00:09:04.700 --> 00:09:11.919
of starting it was you know late primary school um was starting to look at how to program and the

00:09:11.940 --> 00:09:16.980
device that he had at school was an iPad. And he says, okay, well, I'm learning to program. Great.

00:09:17.300 --> 00:09:22.980
How do I build an iPad app? Well, you don't. Like, it's complicated. Like, maybe.

00:09:23.860 --> 00:09:24.880
Have you heard the story for

00:09:24.880 --> 00:09:25.880
it? It's kind of complicated.

00:09:26.740 --> 00:09:32.020
It's learning. Then you say, okay, well, but I'm learning Python because Python is a good

00:09:32.140 --> 00:09:38.760
language for teaching people how to program. Okay, well, now I want to write that iPad app.

00:09:39.120 --> 00:09:40.140
Yeah, but you can't.

00:09:40.320 --> 00:09:42.840
So maybe you've got to learn a different language for that.

00:09:42.850 --> 00:09:43.900
But I don't want to learn a different language.

00:09:44.020 --> 00:09:45.800
I've only barely got my hands around Python.

00:09:45.980 --> 00:09:48.840
Why do I have to learn another language just to be able to have an app there?

00:09:49.280 --> 00:09:55.180
So there's a running sort of semi-joke that goes around that Python is the second best language for everything.

00:09:55.860 --> 00:10:00.620
And part of it being the second best language for everything is that it needs to be able to do all these things,

00:10:01.260 --> 00:10:07.600
maybe not as well as Swift on an iPhone or Coughlin on an Android machine or whatever,

00:10:08.040 --> 00:10:10.520
but well enough that you can get something going.

00:10:11.280 --> 00:10:13.560
Yeah, I would be well happy to say

00:10:13.700 --> 00:10:15.440
it takes an extra 5% of my battery

00:10:15.920 --> 00:10:16.740
compared to a regular app.

00:10:16.920 --> 00:10:17.780
They use a Python app.

00:10:17.840 --> 00:10:18.260
I don't care.

00:10:18.580 --> 00:10:18.880
It's fine.

00:10:19.160 --> 00:10:20.440
But it's not that.

00:10:20.560 --> 00:10:21.860
It's possible, impossible.

00:10:22.660 --> 00:10:22.880
Right?

00:10:23.020 --> 00:10:23.800
That's not a great divide.

00:10:24.440 --> 00:10:25.740
All right, before we dive into this though,

00:10:26.080 --> 00:10:28.040
you mentioned that you work

00:10:28.280 --> 00:10:30.280
on the open source team at Anaconda.

00:10:30.600 --> 00:10:30.960
So I want to

00:10:30.960 --> 00:10:31.240
give you

00:10:31.240 --> 00:10:31.500
a

00:10:31.500 --> 00:10:31.800
moment

00:10:31.920 --> 00:10:33.280
to talk a little bit about what that is.

00:10:33.420 --> 00:10:35.799
I had Peter Wang on the show not too long ago

00:10:36.220 --> 00:10:37.960
and he's always super fun to talk to.

00:10:38.380 --> 00:10:41.400
And I know that they're putting a lot of support

00:10:42.120 --> 00:10:42.900
behind PyScript.

00:10:43.460 --> 00:10:46.380
And it sounds like the timing of releasing PyScript

00:10:46.420 --> 00:10:48.940
and all that is a little bit aligned with when you joined.

00:10:49.380 --> 00:10:50.780
Yeah, so maybe talk to us a bit about all this.

00:10:51.340 --> 00:10:55.240
Yeah, so Anaconda took a round of funding

00:10:56.040 --> 00:10:57.880
a little over three, almost four years ago,

00:10:57.980 --> 00:10:58.520
I think at this point.

00:10:58.940 --> 00:11:01.880
And part of that was to sort of really start doubling down

00:11:02.399 --> 00:11:05.000
on the contribution of open source.

00:11:05.280 --> 00:11:14.900
Anaconda is a company who is built upon tools that are open source, most notably Conda, but that's not the only piece of it.

00:11:15.740 --> 00:11:16.900
Conda is an open source project.

00:11:17.620 --> 00:11:18.760
Someone needs to maintain it.

00:11:19.100 --> 00:11:33.620
Anaconda is able to make money selling this open source product, this whole Python ecosystem, into Fortune 500 companies who need all sorts of legal compliance and standards compliance and security reporting and all that kind of stuff.

00:11:33.700 --> 00:11:38.900
that your student doing a high school computer programming degree doesn't care about, but

00:11:38.920 --> 00:11:39.980
the big end of town does.

00:11:40.779 --> 00:11:45.380
Anaconda is able to make money out of that, but recognizes that the only reason they're

00:11:45.520 --> 00:11:49.120
able to make money doing that is that there is this open source foundation, that Python

00:11:49.320 --> 00:11:51.120
is an open source ecosystem.

00:11:51.980 --> 00:11:57.120
And unless people are maintaining that stuff, Anaconda is not going to have a company in

00:11:57.120 --> 00:11:59.820
a couple of years because everyone's going to move away from Python or do other things

00:11:59.880 --> 00:12:01.320
or find other ways of solving problems.

00:12:02.120 --> 00:12:04.440
And, you know, that ultimately is bad news for Anaconda.

00:12:05.240 --> 00:12:10.180
The other side of it, and sort of the reason why PyScript is interesting, why Anaconda

00:12:10.220 --> 00:12:14.900
is supporting iOS and Android work, is that there is an opportunity here to just literally

00:12:15.100 --> 00:12:15.820
make the pie bigger.

00:12:16.400 --> 00:12:19.860
That if Anaconda, you know, if someone can come in and say, oh yeah, I want to write

00:12:20.000 --> 00:12:24.120
my, you're at a Fortune 500 company, I want to write my app, I want to write it in Python.

00:12:24.580 --> 00:12:26.740
Okay, well now I can do it at iOS and Android.

00:12:27.100 --> 00:12:32.060
There's now more users for Anaconda's products as a result of this investment that's been

00:12:32.080 --> 00:12:34.440
in iOS and Android to make it possible at all.

00:12:35.260 --> 00:12:36.840
It is very much a long-term project.

00:12:37.000 --> 00:12:38.960
But like this is iOS and Android stuff.

00:12:39.340 --> 00:12:42.420
Conda as a project does not have particularly good support

00:12:42.490 --> 00:12:43.340
for iOS and Android.

00:12:43.880 --> 00:12:46.520
Eventually, hopefully not that far off, it will.

00:12:47.320 --> 00:12:49.280
But you don't get to Conda supporting it

00:12:49.620 --> 00:12:50.680
until Python supports it.

00:12:51.220 --> 00:12:52.540
And you don't get Python supports it

00:12:52.550 --> 00:12:55.120
unless someone sits down and actually does the hard work

00:12:55.300 --> 00:12:58.200
to make that happen, which is essentially what I was hired to,

00:12:58.380 --> 00:12:59.760
myself and Malcolm, who had to do.

00:13:00.940 --> 00:13:02.300
And PyScript fits in a very similar boat.

00:13:02.460 --> 00:13:05.720
The web is undeniably a platform that is everywhere

00:13:06.320 --> 00:13:08.820
that you can't run Python in, or you couldn't run Python,

00:13:08.910 --> 00:13:10.420
or it was very hard to run Python in.

00:13:10.860 --> 00:13:13.740
And PyScript as an effort is essentially saying,

00:13:14.230 --> 00:13:16.600
okay, let's make it as straightforward as possible

00:13:16.710 --> 00:13:19.380
for me to just drop some Python into a browser

00:13:19.640 --> 00:13:22.200
and do web user interface stuff

00:13:22.800 --> 00:13:24.460
where instead of having to learn JavaScript

00:13:24.610 --> 00:13:25.800
and learn a whole new ecosystem

00:13:25.830 --> 00:13:27.120
and learn a whole bunch of new set of tools,

00:13:27.240 --> 00:13:30.580
I can just use Python and open up.

00:13:30.920 --> 00:13:36.720
that whole other ecosystem of places where you can run Python code as another place where you

00:13:36.730 --> 00:13:37.360
might want to do things.

00:13:37.670 --> 00:13:40.140
Yeah. And to give people a sense of what's possible with PyScript,

00:13:40.940 --> 00:13:46.920
it's very, very interesting. On iOS and also on Android, I'm sure I just haven't tried it,

00:13:47.200 --> 00:13:51.920
you can create progressive web apps and then say, save this to my home screen. And when it launches,

00:13:52.200 --> 00:13:55.720
it looks like a native app, but you can't really tell that it's not a native app.

00:13:56.040 --> 00:14:04.720
I put together a sample when PyScript first came out that had an offline or offline capable PyScript, all Python written app.

00:14:04.800 --> 00:14:07.340
And it was talking to some APIs out on the Internet.

00:14:07.520 --> 00:14:12.440
And even just those early stages, it was like, wow, this really makes things possible.

00:14:12.740 --> 00:14:21.520
The challenge is, I mean, this is the big challenge, is people don't discover apps on their mobile devices through progressive web apps, right?

00:14:21.920 --> 00:14:23.440
Hence your project, right?

00:14:23.660 --> 00:14:27.180
They go to the app store and they click get or buy,

00:14:27.570 --> 00:14:29.040
and then it shows up on their device, right?

00:14:29.160 --> 00:14:31.040
It's kind of like back to like,

00:14:31.160 --> 00:14:32.460
well, if you could create a virtual environment,

00:14:32.840 --> 00:14:33.640
you could run this thing.

00:14:33.760 --> 00:14:35.180
If you can create a progressive web app,

00:14:35.400 --> 00:14:36.200
I'm a huge fan of them,

00:14:36.540 --> 00:14:36.700
but

00:14:36.700 --> 00:14:39.480
my fandom doesn't change people's

00:14:39.480 --> 00:14:40.120
behavior, right?

00:14:40.880 --> 00:14:41.120
Sure.

00:14:41.450 --> 00:14:43.840
But there is also like to defend my own project here,

00:14:44.200 --> 00:14:45.880
like I'm a big fan of PyScript.

00:14:46.030 --> 00:14:46.760
I love what they're doing.

00:14:47.280 --> 00:14:49.780
There are limits to what you can do in a progressive web app.

00:14:49.880 --> 00:14:52.440
Those limits are getting extended further and further out,

00:14:52.620 --> 00:14:52.640
But

00:14:52.640 --> 00:14:53.800
there are things that

00:14:53.800 --> 00:15:02.460
if you want to have access to the entire capabilities of your device directly at the hardware layer, you can't do that in a progressive web app.

00:15:02.460 --> 00:15:07.420
You can only do it if you're actually writing to the native APIs and you've got direct hardware access.

00:15:09.220 --> 00:15:14.600
The web browser sandbox does place some limits on what you can do.

00:15:15.000 --> 00:15:15.940
Do those limits matter?

00:15:16.540 --> 00:15:17.860
That's an open question.

00:15:17.920 --> 00:15:21.520
there are a lot of things that probably should be progressive web apps that are, you know,

00:15:21.959 --> 00:15:23.560
or that could be progressive web apps.

00:15:24.480 --> 00:15:28.780
But that doesn't mean that there's no market for native apps or that PyScript is like,

00:15:29.020 --> 00:15:33.000
PyScript is eventually going to make, you know, Beware or native apps completely irrelevant.

00:15:33.180 --> 00:15:33.300
Because

00:15:33.300 --> 00:15:33.460
there is...

00:15:33.460 --> 00:15:34.420
No, it absolutely won't.

00:15:34.720 --> 00:15:34.820
Yeah.

00:15:35.140 --> 00:15:38.040
And the other thing is that they actually do complement each other really well.

00:15:38.200 --> 00:15:44.720
Like, Beware does have a PyScript web backend or PyScript-based web backend specifically

00:15:44.900 --> 00:15:45.180
so you

00:15:45.180 --> 00:15:47.340
can say, okay, I want to build an app.

00:15:47.400 --> 00:15:49.660
it has a button and when I press it, the dialog button,

00:15:49.800 --> 00:15:50.700
my dialog box pops up.

00:15:51.140 --> 00:15:54.800
Nothing about what I just said dictated whether it was a web browser

00:15:55.140 --> 00:15:57.020
or an iOS app or a desktop app.

00:15:57.400 --> 00:16:00.400
I can render that on all of them and then say, okay,

00:16:00.540 --> 00:16:02.960
well, it starts as a progressive web app because that's how I want to do it

00:16:02.980 --> 00:16:04.380
and then I'm going to spend a little bit more effort

00:16:04.420 --> 00:16:07.420
and actually make it into a native app and get it into the iOS app store.

00:16:07.940 --> 00:16:12.900
You can progress along that chain without cutting off any options.

00:16:13.320 --> 00:16:13.500
Yeah.

00:16:13.720 --> 00:16:17.040
Oh, I think your project, the native app side is critical.

00:16:17.300 --> 00:16:24.760
I just think there's also a bunch of people out there that say, well, I'm going to build a front end, interactive front end and have a bunch of Django REST framework or something on the back end.

00:16:25.220 --> 00:16:25.640
So I'll use

00:16:25.640 --> 00:16:27.280
React or I'll use Vue.

00:16:27.320 --> 00:16:29.240
And why isn't the answer Python, right?

00:16:29.320 --> 00:16:29.660
It

00:16:29.660 --> 00:16:30.780
really, really could

00:16:30.780 --> 00:16:31.200
be Python.

00:16:31.480 --> 00:16:33.840
That's kind of, I think, where PyScript has a lot of possibilities.

00:16:35.740 --> 00:16:38.920
This portion of Talk Python To Me is brought to you by the folks at Posit.

00:16:39.660 --> 00:16:42.280
Posit has made a huge investment in the Python community lately.

00:16:42.740 --> 00:16:46.680
known originally for RStudio, they've been building down a suite of tools and services

00:16:46.950 --> 00:16:52.480
for Team Python. Have you ever thought of all the things that go into a Python data science project?

00:16:53.200 --> 00:16:57.800
You need your notebook or IDE, sure. Also a server or cloud environment to run it,

00:16:58.240 --> 00:17:03.860
a version of Python, packages, access to your databases, and internal APIs. That's a lot of

00:17:03.950 --> 00:17:08.579
setup. And if you change any of these things, when you return to your projects a month down the road,

00:17:08.819 --> 00:17:13.400
you might get different results. Wouldn't it be nice to have all of this set up for you in one

00:17:13.920 --> 00:17:19.000
easy to access place whenever you want to get work done? That's the goal of Posit Workbench.

00:17:19.699 --> 00:17:23.959
Posit Workbench allows data scientists to code in Python within their preferred environment

00:17:24.439 --> 00:17:29.580
without an additional strain on IT. It gives data scientists access to all the development

00:17:29.820 --> 00:17:34.540
environments they love, including Jupyter Notebooks, JupyterLab, Positron, and VS Code.

00:17:34.860 --> 00:17:37.320
and yet it helps ensure reproducibility.

00:17:37.740 --> 00:17:38.360
Here's how it works.

00:17:38.740 --> 00:17:41.040
You or your IT team set up Posit Workbench

00:17:41.040 --> 00:17:43.660
on a powerful, dedicated server within your organization

00:17:44.360 --> 00:17:45.940
or on the same cloud service

00:17:46.200 --> 00:17:48.260
that is hosting your most important data sources,

00:17:48.800 --> 00:17:52.440
such as AWS, SageMaker, Azure, GCP, Kubernetes,

00:17:53.020 --> 00:17:54.160
or pretty much anywhere.

00:17:54.740 --> 00:17:57.180
There, you create dedicated, pre-configured environments

00:17:57.440 --> 00:17:58.660
to run your code and notebooks.

00:17:59.220 --> 00:18:01.480
And importantly, you also configure access

00:18:01.820 --> 00:18:04.300
to proprietary databases and internal APIs.

00:18:05.100 --> 00:18:13.900
When it's time to onboard a new data scientist or start a new project, you just fire it up in Workbench and it's fully configured and ready to go, including on the infrastructure side of things.

00:18:14.460 --> 00:18:17.300
All of this is securely administered by your organization.

00:18:18.100 --> 00:18:23.740
If you work on a data science team where consistency matters, you owe it to you and your org to check out Posit Workbench.

00:18:24.060 --> 00:18:29.300
Visit talkpython.fm/workbench today and get a three-month free trial to see if it's a good fit.

00:18:29.680 --> 00:18:34.280
That's talkpython.fm/workbench. The link is in your podcast player's show notes.

00:18:34.940 --> 00:18:36.940
Thank you to Posit for supporting Talk Python To Me.

00:18:38.220 --> 00:18:42.540
I think that brings us a little bit to one of your keynotes from 2019, where you talked

00:18:42.740 --> 00:18:44.480
about Black Swan events, right?

00:18:44.920 --> 00:18:45.160
Yes.

00:18:46.240 --> 00:18:49.480
It's a little bit of the same story, but maybe give people a sense of this and we can link

00:18:49.560 --> 00:18:52.160
to this keynote if they want to explore that side of things more.

00:18:52.440 --> 00:18:52.700
Sure.

00:18:52.990 --> 00:18:53.080
Yeah.

00:18:53.200 --> 00:18:58.400
So the idea behind a Black Swan event was Nicholas...

00:18:58.740 --> 00:19:00.020
Nassim Talib, I believe it

00:19:00.020 --> 00:19:00.240
was.

00:19:00.460 --> 00:19:01.260
Nassim Talib, that's the one.

00:19:01.290 --> 00:19:01.420
Yep.

00:19:01.550 --> 00:19:02.160
I forget his name.

00:19:02.860 --> 00:19:06.440
but he identified this idea of what's called a black swan event.

00:19:07.600 --> 00:19:10.000
The reason I use this is I'm from Perth and black swans come from Perth.

00:19:10.140 --> 00:19:11.480
So it was an interesting

00:19:11.480 --> 00:19:12.820
little tie-in for an international

00:19:12.820 --> 00:19:13.180
keynote.

00:19:13.860 --> 00:19:15.440
You guys actually have black swans all over?

00:19:15.580 --> 00:19:15.980
We have

00:19:15.980 --> 00:19:16.120
them.

00:19:16.220 --> 00:19:19.160
The state emblem of Western Australia is a black swan.

00:19:19.220 --> 00:19:20.340
Like that is literally

00:19:20.340 --> 00:19:22.440
on our flag.

00:19:23.000 --> 00:19:23.600
So the

00:19:23.600 --> 00:19:27.000
theory was that the Dutch bumped into Western Australia

00:19:27.300 --> 00:19:30.820
accidentally looking for the Spice Islands in the 1600s.

00:19:31.220 --> 00:19:36.420
And at the time they did that, they knew with absolute certainty that all swans were white.

00:19:37.000 --> 00:19:41.000
And then they bumped into Western Australia and they discovered that all the swans here are black.

00:19:42.520 --> 00:19:49.880
The idea behind a black swan event is a thing you don't see coming that completely changes your view of the world.

00:19:50.380 --> 00:19:53.800
And black swan events are the sorts of things that completely change markets.

00:19:53.900 --> 00:20:04.120
We don't know what, if you're not looking, if you're not ready for a cataclysmic change in your ecosystem, then the change happens and you are left behind.

00:20:05.179 --> 00:20:05.700
I

00:20:05.700 --> 00:20:06.340
would say

00:20:06.340 --> 00:20:09.500
COVID is a good example of what hit people.

00:20:10.360 --> 00:20:10.940
Another one's AI.

00:20:11.960 --> 00:20:14.820
Yeah, AI is still, how is that going to impact?

00:20:14.960 --> 00:20:16.560
It's just a little bit less clear.

00:20:16.750 --> 00:20:21.640
And COVID, we're kind of seeing the impacts of that, whether that's going to have long-term impacts.

00:20:21.880 --> 00:20:22.380
like it's some

00:20:22.380 --> 00:20:23.000
of those things seem

00:20:23.000 --> 00:20:23.720
to be kind of fading away.

00:20:24.580 --> 00:20:25.360
But the one that I,

00:20:25.900 --> 00:20:26.000
yeah,

00:20:26.280 --> 00:20:26.360
well,

00:20:27.100 --> 00:20:27.180
yeah,

00:20:27.600 --> 00:20:27.780
mostly.

00:20:28.000 --> 00:20:28.120
I mean,

00:20:28.620 --> 00:20:28.820
people,

00:20:28.820 --> 00:20:28.960
I mean,

00:20:29.080 --> 00:20:29.600
people still get to say,

00:20:29.760 --> 00:20:30.260
but like the,

00:20:30.620 --> 00:20:33.320
the world has shut down and

00:20:33.320 --> 00:20:34.060
will we,

00:20:34.360 --> 00:20:35.760
will economies just disappear?

00:20:36.320 --> 00:20:36.820
Level of,

00:20:36.960 --> 00:20:37.480
Oh my gosh.

00:20:37.580 --> 00:20:37.920
It's kind of,

00:20:37.980 --> 00:20:39.360
that's the history I was thinking of.

00:20:39.460 --> 00:20:39.660
Yeah.

00:20:39.880 --> 00:20:39.940
I,

00:20:40.260 --> 00:20:41.820
the one that I was highlighting for,

00:20:41.960 --> 00:20:42.160
for,

00:20:43.160 --> 00:20:45.440
for Python is that Python is a programming language,

00:20:46.220 --> 00:20:48.600
but it's a programming language that has historically assumed,

00:20:48.720 --> 00:20:48.820
well,

00:20:48.880 --> 00:20:49.640
you're running on a laptop,

00:20:49.860 --> 00:20:50.000
right?

00:20:50.380 --> 00:20:51.580
Like that's where you run computer code.

00:20:51.680 --> 00:20:56.740
you always run computer code in a laptop. And then iPhones turned up. And now we've got computing in

00:20:56.880 --> 00:21:01.620
our pocket that is as powerful, if not more powerful than the laptops that we had on our desk

00:21:01.880 --> 00:21:07.020
10 years ago. And Python can't run there, or at least at the time, couldn't really run there.

00:21:07.540 --> 00:21:13.520
So what does that mean for Python? Why am I going to learn Python? If the computing ecosystem moves

00:21:13.640 --> 00:21:18.840
to a world where everybody's using phones and tablets, and I can't run Python on a phone or a

00:21:18.840 --> 00:21:23.740
tablet, why am I going to learn Python? Python as an ecosystem has an existential risk there

00:21:23.850 --> 00:21:28.480
because of this black swan of a change in the way people do computing.

00:21:29.140 --> 00:21:30.360
And at

00:21:30.360 --> 00:21:31.040
the time I gave that

00:21:31.180 --> 00:21:35.460
keynote, what I was essentially saying is, okay, as an ecosystem, we need to take a long, hard look

00:21:35.470 --> 00:21:40.680
at ourselves. It's impossible to know what the black swan events are going to be, but we can look

00:21:40.780 --> 00:21:44.739
at where the ecosystem is now. We can look at the trends of things that are happening and we can work

00:21:44.760 --> 00:21:52.520
out institutionally what are our risks, like what would need to change to make Python a

00:21:52.720 --> 00:21:53.440
dead ecosystem.

00:21:54.320 --> 00:21:59.900
And the obvious one, the one that I was really pushing at that time, one of which is platforms

00:22:00.000 --> 00:22:00.700
that we need to support.

00:22:00.820 --> 00:22:04.280
And the second is how do we support this software going forward?

00:22:04.420 --> 00:22:09.740
How do we actually guarantee that this community-driven project continues to be maintained?

00:22:10.080 --> 00:22:13.320
Because if we don't have maintainers, then the code doesn't get written.

00:22:14.500 --> 00:22:14.800
So, yeah.

00:22:15.000 --> 00:22:15.660
Yeah, excellent.

00:22:15.900 --> 00:22:17.060
I recommend people check it out.

00:22:17.280 --> 00:22:17.720
It's on YouTube.

00:22:17.920 --> 00:22:19.040
I will link to it.

00:22:19.580 --> 00:22:20.740
It's scary the last five years ago.

00:22:21.540 --> 00:22:21.940
I know.

00:22:22.140 --> 00:22:24.520
I feel like that was pretty recent, but no.

00:22:25.500 --> 00:22:28.740
No, that was the last one before COVID, by the way, bringing it full circle.

00:22:29.500 --> 00:22:35.300
Tommy out there asked in the audience, is in the iOS Pythonistas app, I had some really good simple use cases in the past.

00:22:35.600 --> 00:22:42.380
The GUI layer, a bit of a hassle, but like the library modules, also could not call some not yet exposed APIs.

00:22:42.460 --> 00:22:47.360
I guess as we get into this, maybe think, just people probably know about the Pythonista app.

00:22:47.680 --> 00:22:48.720
I don't know.

00:22:49.560 --> 00:22:50.520
Yeah, it was around.

00:22:51.460 --> 00:22:52.560
And it's not the same idea.

00:22:52.920 --> 00:22:54.120
It's not what you guys are trying to do.

00:22:54.500 --> 00:22:57.300
Yes and no, because I actually worked on Pythonista.

00:22:57.660 --> 00:23:02.200
The reason that Pythonista supports Python 3, I was contracted to do the Python 3 port.

00:23:02.380 --> 00:23:02.600
So the

00:23:02.600 --> 00:23:03.780
core of that library

00:23:03.780 --> 00:23:05.900
is essentially the thing that Beware was doing.

00:23:05.960 --> 00:23:09.000
And the reason it was able to move to Python 3 was because of the work that I was doing.

00:23:10.220 --> 00:23:17.940
It is, yeah, it is very much sort of the Pythonista as an idea is kind of what if idle, but on a phone?

00:23:18.200 --> 00:23:22.640
Like here is a development environment where you can write Python code.

00:23:22.680 --> 00:23:26.720
You have some access to some libraries and some GUI libraries.

00:23:27.540 --> 00:23:33.520
So you can put a button up, but you're not writing, you're not using Pythonista to write an app.

00:23:33.780 --> 00:23:40.380
You're using it to put an interface into a running Pythonista sheet, you know, working

00:23:40.660 --> 00:23:40.880
environment.

00:23:41.940 --> 00:23:44.120
It is absolutely a way to write Python.

00:23:44.190 --> 00:23:45.940
It is a way to have

00:23:45.940 --> 00:23:47.100
Python running

00:23:47.100 --> 00:23:47.900
on your phone.

00:23:48.450 --> 00:23:52.820
But it is not something that's going to push something to the iOS app store so that random

00:23:52.930 --> 00:23:54.660
other person can buy your app.

00:23:55.040 --> 00:23:59.620
You know, to me, it feels a little bit like shortcuts on iOS in that you could kind of

00:23:59.620 --> 00:24:02.560
put together some behaviors, but you would never try to make an app.

00:24:02.660 --> 00:24:07.100
yeah that's it's not that's not too far from it and it except that it's all inside the sound

00:24:07.690 --> 00:24:12.320
yeah and you could do real python which is way better than shortcut but the kind of the type

00:24:12.320 --> 00:24:16.440
of thing you accomplish it feels a little bit like i can go find this thing and run it and it'll do

00:24:16.560 --> 00:24:17.580
something for me which is cool

00:24:17.580 --> 00:24:17.780
but

00:24:17.780 --> 00:24:18.440
yeah it's

00:24:18.440 --> 00:24:22.400
not going to be the new airbnb implementation no

00:24:22.400 --> 00:24:22.720
exactly

00:24:23.020 --> 00:24:29.959
and like even like i guess beware as a project isn't it the intention is not that it would be

00:24:29.980 --> 00:24:33.080
the next Airbnb as a final product.

00:24:33.270 --> 00:24:36.940
It might, however, be the mock-up of the demo app

00:24:37.080 --> 00:24:40.020
that you take to your initial seed funding round

00:24:40.350 --> 00:24:43.080
to prove, here is the idea we've got.

00:24:43.380 --> 00:24:44.580
We've proved it out with some people,

00:24:44.670 --> 00:24:46.480
just like a small little sample trial, whatever.

00:24:47.180 --> 00:24:49.060
Now give us the money to go and actually hire

00:24:49.420 --> 00:24:51.720
a team of iOS developers and a team of Android developers

00:24:51.770 --> 00:24:53.480
to build an absolutely kick-ass,

00:24:54.500 --> 00:24:56.540
optimized native application of every platform.

00:24:57.240 --> 00:24:59.940
Yeah, maybe a little bit like Playgrounds

00:24:59.960 --> 00:25:01.380
Well, perhaps in that regard.

00:25:02.060 --> 00:25:03.440
Yeah, a little bit, I guess, like Playgrounds, yeah.

00:25:04.320 --> 00:25:05.600
Yeah, also a different focus.

00:25:05.840 --> 00:25:09.500
But another comment maybe as we dive into this, Joe out there asks us,

00:25:09.530 --> 00:25:10.260
hey, great project.

00:25:10.470 --> 00:25:12.020
How would you sell this to us?

00:25:12.400 --> 00:25:14.880
And that there's a few other frameworks like WXPython, Kivy.

00:25:15.720 --> 00:25:17.260
WXPython also renders data of GUIs.

00:25:18.960 --> 00:25:19.880
How would I sell it?

00:25:20.010 --> 00:25:22.480
Okay, says he, pulling out the sales sheet.

00:25:23.480 --> 00:25:24.600
Let me get my pitch deck.

00:25:24.710 --> 00:25:25.020
Hold on.

00:25:25.960 --> 00:25:27.640
So there's essentially two questions there.

00:25:27.740 --> 00:25:30.500
One is WX Python and one is KIVI.

00:25:31.780 --> 00:25:35.380
The KIVI is a sort of the two different reasons.

00:25:35.740 --> 00:25:38.980
KIVI does work on iOS and Android and also on the desktop platforms.

00:25:39.580 --> 00:25:43.540
KIVI is taking a very, very distinctly different approach to user interface design.

00:25:44.030 --> 00:25:49.560
So KIVI can run on all those platforms, but the user interface that it puts up is a KIVI

00:25:49.630 --> 00:25:50.060
user interface.

00:25:50.390 --> 00:25:51.580
It always looks like KIVI.

00:25:51.580 --> 00:25:55.840
And it's like if you build a macOS app, it will look the same on Windows.

00:25:56.100 --> 00:25:58.420
It'll look the same on GDK, and it will look the same, you know,

00:25:58.700 --> 00:25:59.720
size of window notwithstanding.

00:26:00.040 --> 00:26:01.600
It will look the same on iOS and Android.

00:26:02.400 --> 00:26:05.480
That is a completely viable way to build apps.

00:26:06.020 --> 00:26:08.600
It is not a native user interface.

00:26:10.400 --> 00:26:14.620
And one of the major reasons that I dislike that as an approach,

00:26:14.980 --> 00:26:17.300
I'm not in any way saying that Kibbe is a bad project.

00:26:17.480 --> 00:26:19.100
It is a different way to build user interfaces,

00:26:19.480 --> 00:26:23.420
and I prefer a different approach, which is to say an actual native button.

00:26:23.620 --> 00:26:26.260
So on macOS, it looks like a macOS app.

00:26:26.480 --> 00:26:28.540
On iOS, it looks like an iOS app.

00:26:28.620 --> 00:26:30.520
On Windows, it looks like a Windows app.

00:26:32.020 --> 00:26:34.800
The downside is that if you need to take screenshots,

00:26:35.080 --> 00:26:36.120
you've got to have an iOS screenshot

00:26:36.280 --> 00:26:38.180
and a macOS screenshot and a Windows screenshot.

00:26:39.340 --> 00:26:42.660
The benefit is consistency with the rest of the platform.

00:26:43.460 --> 00:26:46.180
And that might seem like a totally cosmetic thing,

00:26:46.800 --> 00:26:49.660
but one, consistency between applications

00:26:50.180 --> 00:26:52.179
is a mode of user interface discovery

00:26:52.200 --> 00:26:55.860
because if people know this is how a button works on MacOS,

00:26:56.180 --> 00:26:58.100
they know how your platform does it as well,

00:26:58.100 --> 00:26:59.000
how your app does it as well,

00:26:59.300 --> 00:26:59.780
rather than

00:26:59.780 --> 00:27:01.820
having to discover how you have decided

00:27:01.820 --> 00:27:04.600
to implement menus or buttons or anything else.

00:27:05.140 --> 00:27:06.960
Yeah, one of the really things that stands out,

00:27:06.960 --> 00:27:10.620
I think, super stark a lot of times is the file open save dialogs.

00:27:10.640 --> 00:27:10.900
Yes,

00:27:11.410 --> 00:27:11.540
yes.

00:27:11.600 --> 00:27:11.940
It's like,

00:27:12.000 --> 00:27:15.460
whoa, this is clearly just alien versus...

00:27:15.480 --> 00:27:15.740
Yeah, and

00:27:15.740 --> 00:27:16.700
a lot of cases,

00:27:17.160 --> 00:27:19.799
they are missing the one thing on my platform

00:27:19.820 --> 00:27:22.120
that makes file dialogues actually useful

00:27:22.600 --> 00:27:22.720
because

00:27:22.720 --> 00:27:23.340
I can do

00:27:23.340 --> 00:27:25.680
this thing that I can't do in your dialogue

00:27:26.100 --> 00:27:27.120
because you've had to build it from scratch.

00:27:27.260 --> 00:27:28.520
And speaking of building from scratch,

00:27:28.620 --> 00:27:30.700
the other big benefit of a native GUI

00:27:31.140 --> 00:27:33.940
is that you get all of the platform's native affordances.

00:27:34.660 --> 00:27:36.320
One of the most surprising things,

00:27:36.460 --> 00:27:37.720
it wasn't necessarily surprising

00:27:37.860 --> 00:27:39.460
because I understood why I was doing it,

00:27:39.560 --> 00:27:41.000
but things that might be surprising to people

00:27:41.040 --> 00:27:42.520
who haven't followed along GUI development,

00:27:43.400 --> 00:27:45.740
we have received an inordinate number

00:27:46.240 --> 00:27:48.379
of very, very enthusiastic comments

00:27:48.380 --> 00:27:51.600
from blind people writing iOS apps.

00:27:52.410 --> 00:27:54.540
Because an iOS app built with Beware

00:27:55.140 --> 00:27:57.880
fits in directly with screen readers

00:27:58.380 --> 00:28:01.200
because it is using the platform's native accessibility.

00:28:02.000 --> 00:28:04.440
Kivy has not built explicitly

00:28:05.090 --> 00:28:06.720
native screen reader support into their widgets.

00:28:06.930 --> 00:28:08.100
To the best of my knowledge,

00:28:08.150 --> 00:28:09.760
or at least all the reports that I'm getting

00:28:09.760 --> 00:28:10.920
are saying that it's not there

00:28:11.280 --> 00:28:13.260
because you have to build it from scratch

00:28:13.900 --> 00:28:16.120
on every platform and they haven't done that.

00:28:16.360 --> 00:28:17.160
It's a lot of work.

00:28:17.220 --> 00:28:19.360
I'm not underselling how big of a project it is,

00:28:19.520 --> 00:28:23.720
but Beware got it for free because we are using native widgets,

00:28:24.300 --> 00:28:26.000
and that's not an insignificant consideration.

00:28:28.020 --> 00:28:28.420
That's

00:28:28.420 --> 00:28:28.720
Kivy.

00:28:28.780 --> 00:28:29.020
Oh, sorry.

00:28:29.560 --> 00:28:29.960
No, no, please

00:28:29.960 --> 00:28:30.220
go ahead.

00:28:30.460 --> 00:28:31.980
No, I was going to say, that's the Kivy.

00:28:32.280 --> 00:28:35.320
So that's the not native user interface but looks the same everywhere

00:28:35.660 --> 00:28:38.240
versus Beware's using native widgets everywhere.

00:28:38.600 --> 00:28:40.880
The other argument is, okay, but why don't you use WX Windows?

00:28:41.320 --> 00:28:44.579
The reason we don't use WX Windows is WX Windows doesn't run on iOS

00:28:44.600 --> 00:28:47.460
or Android and trying to make it run on iOS and Android.

00:28:47.710 --> 00:28:49.540
Like I did look into it and it was a little bit crunchy.

00:28:50.740 --> 00:28:53.480
Qt apparently works on iOS now.

00:28:53.550 --> 00:28:54.900
It didn't when I started the project,

00:28:56.240 --> 00:28:58.280
but they very much don't want you to write Python.

00:28:58.350 --> 00:29:00.040
And one of the things that Beware is trying to push

00:29:00.080 --> 00:29:01.900
and Toga as a GUI platform is trying to push

00:29:01.950 --> 00:29:03.740
is you're writing Python code.

00:29:03.810 --> 00:29:04.580
It looks like Python.

00:29:04.770 --> 00:29:05.840
It tastes like Python.

00:29:06.320 --> 00:29:07.960
If you don't want to write Python, that's fine.

00:29:08.160 --> 00:29:09.580
There are plenty of GUI toolkits out there

00:29:09.590 --> 00:29:11.200
that don't require you to write Python.

00:29:11.590 --> 00:29:14.180
But Toga is a Python first GUI toolkit.

00:29:14.280 --> 00:29:24.900
And it looks like, tastes like Python, we support, we use, actively use in APIs, iterators and generators and asyncio syntax and context managers.

00:29:25.520 --> 00:29:37.220
Things that WX Windows as a light wrapper around a C++ framework doesn't really expose because they are limited by what C++ looks like when you program it.

00:29:37.620 --> 00:29:41.279
And you also get that to a certain extent in QT as well or PyQT.

00:29:42.120 --> 00:29:42.920
Yeah, they're both wrappers.

00:29:43.420 --> 00:29:43.580
Interesting.

00:29:44.200 --> 00:29:48.380
So let's talk about some of the peps that make this possible, right?

00:29:48.740 --> 00:29:48.840
Yeah.

00:29:49.020 --> 00:29:55.860
There's the foundational, basically adding platforms as a intentionally supported platform

00:29:56.460 --> 00:29:58.920
to the CPython whole process, right?

00:29:59.020 --> 00:29:59.340
The core

00:29:59.340 --> 00:30:00.140
developers working

00:30:00.140 --> 00:30:03.340
on it from the builds and the deployments and all those kinds

00:30:03.380 --> 00:30:03.680
of things.

00:30:03.740 --> 00:30:08.200
And so you've got a couple of peps where you're the author of them, which is awesome.

00:30:08.400 --> 00:30:10.180
I'm strictly the author of one.

00:30:10.280 --> 00:30:11.720
Malcolm Smith was the author of the Android one.

00:30:11.920 --> 00:30:12.240
Oh, okay.

00:30:12.660 --> 00:30:12.800
Got it.

00:30:13.060 --> 00:30:16.280
One Android with Malcolm and one iOS with you.

00:30:16.390 --> 00:30:16.480
Okay.

00:30:16.670 --> 00:30:18.220
I see which side fence you come down on.

00:30:18.230 --> 00:30:18.620
I got it.

00:30:18.820 --> 00:30:18.960
Yep.

00:30:19.180 --> 00:30:19.560
No, no, no, no.

00:30:20.160 --> 00:30:20.580
That's all good.

00:30:20.700 --> 00:30:21.200
I'm with you.

00:30:21.240 --> 00:30:21.560
I'm with you.

00:30:22.100 --> 00:30:22.240
All right.

00:30:22.570 --> 00:30:23.500
Tell us about these peps.

00:30:23.960 --> 00:30:24.980
What role do they have?

00:30:25.640 --> 00:30:27.140
And their status is final.

00:30:27.380 --> 00:30:28.200
That's good.

00:30:29.100 --> 00:30:29.460
So, yeah.

00:30:29.910 --> 00:30:36.400
So, the PEP was essentially formalizing the things that Malcolm and I have been maintaining

00:30:36.700 --> 00:30:40.040
independently, both of us, at the time for like about eight, nine years.

00:30:41.280 --> 00:30:41.900
We had patches.

00:30:42.340 --> 00:30:46.200
like I was maintaining a set of patches to make CPython run on iOS,

00:30:46.360 --> 00:30:48.060
and I was manually maintaining all those patches.

00:30:48.160 --> 00:30:50.280
And every time a new Python release would come out,

00:30:50.440 --> 00:30:52.980
I'd have to go and sit down and spend, you know,

00:30:53.100 --> 00:30:54.420
a couple of months trying to work out, okay,

00:30:54.620 --> 00:30:55.620
what have they changed this time?

00:30:56.300 --> 00:30:59.840
And, you know, getting all of those, updating all of the PR,

00:31:00.000 --> 00:31:03.920
all of the code to make it work on a new version of Python.

00:31:04.960 --> 00:31:11.260
In the 3.13 timeframe, so it's, what, September of 2023,

00:31:12.080 --> 00:31:17.860
I went along to the CPython core team summit in the US.

00:31:18.460 --> 00:31:20.700
Sorry, it was in Bono.

00:31:22.580 --> 00:31:24.180
And basically with the intention of,

00:31:24.520 --> 00:31:26.060
I want to upstream all these patches.

00:31:26.240 --> 00:31:26.840
We've got these patches.

00:31:27.000 --> 00:31:27.580
They're not huge.

00:31:27.680 --> 00:31:28.960
They're big, but they're not huge.

00:31:29.300 --> 00:31:30.300
I'd like to formalize that.

00:31:30.460 --> 00:31:32.320
And so the outcome of that was what we need is a PEP.

00:31:32.420 --> 00:31:35.520
We need a formal description of what it is you're going to do,

00:31:35.800 --> 00:31:36.620
why it's going to change,

00:31:37.220 --> 00:31:40.600
what impact that has on the rest of the ecosystem for you to do that,

00:31:40.980 --> 00:31:44.480
and to formalize a couple of the little details

00:31:45.159 --> 00:31:47.660
that need to be formally specified

00:31:47.840 --> 00:31:49.120
in order for the rest of the ecosystem

00:31:49.160 --> 00:31:49.960
to play nice with this.

00:31:50.240 --> 00:31:50.920
Little details like,

00:31:51.200 --> 00:31:54.300
what does sys.platform return on an iOS machine?

00:31:54.580 --> 00:31:56.240
Like it's a really minor detail,

00:31:56.600 --> 00:31:56.740
but

00:31:56.740 --> 00:31:57.460
it's a question you've

00:31:57.460 --> 00:31:57.880
got to answer.

00:31:58.400 --> 00:31:59.520
And it's like, it's an answer that even Apple Darwin

00:31:59.520 --> 00:31:59.780
is probably

00:31:59.780 --> 00:32:00.200
wrong.

00:32:01.060 --> 00:32:01.160
Well,

00:32:01.160 --> 00:32:02.440
yeah, that's the thing. Like it's

00:32:02.440 --> 00:32:05.420
Darwin on macOS for some historical reasons, but like even

00:32:05.420 --> 00:32:07.400
on iOS, should it be iOS? Should it be

00:32:07.400 --> 00:32:09.740
iOS capitalized? Should it be

00:32:09.740 --> 00:32:10.460
iPhone?

00:32:10.840 --> 00:32:11.800
Should it be iPhone OS?

00:32:12.140 --> 00:32:14.080
Should it be iPhone OS or iPhone simulator?

00:32:14.440 --> 00:32:18.020
All of these are answers that Apple itself uses at various points in their API.

00:32:18.600 --> 00:32:19.360
And what about iPad?

00:32:20.600 --> 00:32:21.820
Well, an iPad is iPad iOS.

00:32:22.080 --> 00:32:22.680
Is that a different answer?

00:32:23.160 --> 00:32:23.980
And so on.

00:32:24.900 --> 00:32:32.780
And then the one that really matters for that is nailing down what is the platform tag that will be used for packaging purposes?

00:32:32.960 --> 00:32:38.340
So when a wheel, a binary wheel, eventually lands on PyPI, what's the tag?

00:32:38.400 --> 00:32:39.780
Like what is it?

00:32:40.480 --> 00:32:44.320
For macOS, it's a macOS X underscore 11 underscore ARM64.

00:32:44.900 --> 00:32:44.980
Okay.

00:32:45.400 --> 00:32:46.120
What is it for iPhone?

00:32:46.520 --> 00:32:47.320
Yeah, maybe we could elaborate.

00:32:47.520 --> 00:32:50.460
Maybe you could elaborate just a little bit on like what that even means, right?

00:32:50.640 --> 00:32:52.880
Because before Wheels, things were different.

00:32:52.960 --> 00:32:53.600
You would download it.

00:32:53.600 --> 00:32:54.160
You would build it.

00:32:54.200 --> 00:32:56.080
You'd have to have Fortran or some random thing.

00:32:56.500 --> 00:33:00.500
Wheels solved that, but that then created a combinatorial explosion of binary assets,

00:33:00.740 --> 00:33:00.880
right?

00:33:01.200 --> 00:33:01.740
Why does that matter?

00:33:02.040 --> 00:33:02.640
Why does that matter?

00:33:02.660 --> 00:33:14.240
So the major change with wheels is that it moved from a world where installing a Python package required you to execute code at time of installation.

00:33:15.840 --> 00:33:25.660
And that's not a good idea from a security perspective because you then need to audit all of the code that's going to execute when you install the package.

00:33:26.220 --> 00:33:33.160
And you can't find anything out about the package without running that code or at least auditing the code that's going to run.

00:33:34.000 --> 00:33:43.540
Wheels provides you to say, okay, this is a wheel is basically just a zip file with a bunch of known metadata that describes exactly what is in here.

00:33:44.000 --> 00:33:49.780
But part of that specification is also a binary specification that says, what version of CPython is it compatible with?

00:33:50.040 --> 00:33:52.300
What version of the operating system is it compatible with?

00:33:52.700 --> 00:33:54.880
What CPU architecture is it compatible with?

00:33:55.240 --> 00:34:06.820
So that if I look at a wheel that is labeled, for example, macOS 11.0 ARM64, I know that this will run on macOS 11 with an ARM64 CPU.

00:34:07.500 --> 00:34:09.659
There are any number of these tags available.

00:34:09.780 --> 00:34:15.300
And there's differences like the Universal 2, which will support both x86 and ARM.

00:34:15.740 --> 00:34:33.980
And on Linux, there's a thing called a mini Linux wheel, which is a specification for specifically what API guarantees does this Linux platform guarantee in terms of what is available in the CPython, in terms of the C library, the GNU C library, et cetera, et cetera.

00:34:34.240 --> 00:34:39.780
You have to be able to specify that so that I know when I get this wheel, I know where it will work and how it will work.

00:34:39.840 --> 00:34:43.740
And for the point of view of pip, pip knowing which version should I download?

00:34:44.379 --> 00:34:46.980
I've got an app here that I'm running on my macOS machine.

00:34:47.520 --> 00:34:48.720
Which wheel should I download?

00:34:49.179 --> 00:34:52.120
Go and grab one and resolve it and find out and solve that question.

00:34:52.399 --> 00:34:52.600
Yeah.

00:34:52.860 --> 00:34:56.760
So without knowing that answer, you don't know how to install wheels, basically.

00:34:57.220 --> 00:34:57.360
Correct.

00:34:57.460 --> 00:35:12.260
Part of the wheel specification is which – if the wheel contains all the pre-compiled components, in order for it to have pre-compiled components, there's an API or an ABI specification there of exactly what symbols am I going to be able to link against?

00:35:12.290 --> 00:35:13.600
What can I assume exists?

00:35:14.420 --> 00:35:15.960
Will this run on my machine?

00:35:16.980 --> 00:35:17.240
Yeah.

00:35:17.840 --> 00:35:18.920
What's going to happen, right?

00:35:19.170 --> 00:35:20.520
Is it even compiled from architecture?

00:35:21.040 --> 00:35:26.260
And we have a similar thing with Python standalone builds that is now part of Astral, which is really great.

00:35:26.320 --> 00:35:30.360
we can just grab the Python we need because we know the platform tags and all that kind of stuff.

00:35:30.680 --> 00:35:33.220
Any difference about the Android one?

00:35:33.420 --> 00:35:36.240
I mean, you obviously need one for each platform, I suppose.

00:35:36.760 --> 00:35:37.640
We do, yeah, basically.

00:35:38.040 --> 00:35:40.940
And there will be at some point in the hopefully not too distant future,

00:35:40.960 --> 00:35:44.760
there will be one for Inscripten as well, just formalizing Inscripten support,

00:35:45.200 --> 00:35:49.100
which is the Pyodide slash PyScript in the browser version.

00:35:50.480 --> 00:35:52.780
Yeah, you need to have one for every platform.

00:35:53.120 --> 00:35:59.880
I guess the one notable difference between iOS and Android as a PEP is that in theory,

00:36:00.960 --> 00:36:04.020
CPython 12 could compile on Android.

00:36:04.100 --> 00:36:08.320
There were some patches which had been applied without going through the formal PEP process

00:36:08.800 --> 00:36:13.500
on the basis of, well, it doesn't cost us anything to add this code in.

00:36:13.500 --> 00:36:16.120
We're not guaranteeing it's going to work, but it's not breaking anything.

00:36:16.160 --> 00:36:17.240
So we might as well have it there.

00:36:17.840 --> 00:36:24.760
And so there's one, like the process of formalizing it did change one notable thing,

00:36:25.300 --> 00:36:29.800
which is that previously, if you were able to get Sys.platform to compile on Android,

00:36:29.840 --> 00:36:33.120
and it was possible and realistically it needed some patches, but it could be done,

00:36:33.960 --> 00:36:36.180
Sys.platform would return Linux.

00:36:37.180 --> 00:36:42.740
Because technically it is, but not in a way that's even remotely helpful to anyone.

00:36:43.760 --> 00:36:44.020
And so

00:36:44.020 --> 00:36:46.120
one of the things that the PEP specified,

00:36:46.270 --> 00:36:47.820
like, yes, it is a Linux kernel,

00:36:48.260 --> 00:36:49.700
but Linux doesn't help you there

00:36:49.960 --> 00:36:51.920
because nothing about an Android machine

00:36:52.520 --> 00:36:53.720
actually behaves like Linux

00:36:54.500 --> 00:36:56.780
once you're past like the kernel level.

00:36:57.520 --> 00:36:59.380
The rest of the thing is what you actually care about.

00:36:59.850 --> 00:37:01.400
And the rest of the libraries you can guarantee

00:37:01.600 --> 00:37:02.260
is what you care about.

00:37:02.680 --> 00:37:05.880
And so one of the things that the PEP had to specify

00:37:06.640 --> 00:37:10.560
was, okay, we are changing what sys.platform means on Android

00:37:10.980 --> 00:37:13.720
because you need to be able to differentiate

00:37:13.740 --> 00:37:17.060
I am on an Android machine, not just a desktop Linux box.

00:37:18.180 --> 00:37:18.340
And

00:37:18.340 --> 00:37:18.580
so, yeah,

00:37:18.680 --> 00:37:20.360
so that was one notable change.

00:37:20.640 --> 00:37:22.880
It was in that PEP that wasn't in the iOS one.

00:37:23.220 --> 00:37:23.420
Interesting.

00:37:23.700 --> 00:37:25.400
You mentioned mScripten.

00:37:25.820 --> 00:37:25.920
What

00:37:25.920 --> 00:37:26.900
an interesting project.

00:37:27.320 --> 00:37:28.820
Yeah, it almost

00:37:28.820 --> 00:37:29.500
looks like it's

00:37:29.500 --> 00:37:31.580
not AI because it's LLVM,

00:37:32.000 --> 00:37:32.980
but it has nothing to do with it.

00:37:33.060 --> 00:37:33.300
Yeah, yes.

00:37:33.700 --> 00:37:36.040
It's a different set of LLs altogether.

00:37:37.060 --> 00:37:37.160
Yeah.

00:37:37.920 --> 00:37:47.180
So inscription is kind of the tail end, the current manifestation of a long series of

00:37:47.280 --> 00:37:49.760
developments that started like 15 years ago.

00:37:50.300 --> 00:37:58.980
Someone worked out that modern web browsers have spent so much time optimizing the JavaScript

00:37:59.260 --> 00:38:06.060
compilers that there are certain JavaScript constructs that map almost one-to-one to machine

00:38:06.300 --> 00:38:06.480
code.

00:38:06.780 --> 00:38:21.180
Like you can say, okay, add these two integers in JavaScript or to these two numbers in JavaScript that if you know the numbers are integers, will map through the JavaScript jits that are running.

00:38:21.250 --> 00:38:24.580
It will map to a literal, you know, add instruction

00:38:24.580 --> 00:38:25.260
on your CPU.

00:38:25.540 --> 00:38:26.840
Like two registers coming together.

00:38:27.010 --> 00:38:27.760
Yeah, two registers

00:38:27.760 --> 00:38:28.200
coming together.

00:38:28.900 --> 00:38:40.120
And so if you restrict yourself to handwriting just that subset of JavaScript, you can essentially write assembler in JavaScript.

00:38:40.880 --> 00:38:51.640
Now, in practice, nobody can actually do that because it's just way too constraining to know that you actually have to put the brackets around the outside of here or else the jit won't optimize it in just the right way.

00:38:52.140 --> 00:38:53.380
But that's what compilers are for.

00:38:53.760 --> 00:38:59.340
Compilers are really good at taking a set of arbitrary input and following a set of arbitrary rules to produce a consistent set of output.

00:38:59.640 --> 00:39:10.140
And so this thing called ASM.js was born, which is essentially an input format that could be compiled to a JIT-able version of JavaScript that would run as a native platform.

00:39:10.740 --> 00:39:18.340
And then from that, you can then get to WASM, which is WebAssembly, which is a formal text specification of the sort of things that ASM.js was working on.

00:39:18.760 --> 00:39:23.740
And then Inscripten is a compiler tool chain that plugs into LLVM.

00:39:23.740 --> 00:39:33.640
So if you've used a compiler like Clang, it is essentially a wrapper around a set of compiler building tools that produces output.

00:39:34.000 --> 00:39:39.040
So you are used to calling GCC or Clang on a C program.

00:39:39.900 --> 00:39:48.600
Clang calls into your C program, compiles it into an LLVM format, and LLVM converts it into actual runnable executables.

00:39:49.140 --> 00:39:59.800
And so it's an LLVM plugin that instead of spitting out macOS-compatible binary executable assembly, it spits out WASM.

00:39:59.940 --> 00:40:03.420
It spits out JavaScript-optimized code that can run in the browser.

00:40:03.860 --> 00:40:05.620
That's all very much high level.

00:40:05.760 --> 00:40:07.960
There's a lot of very, very complicated details that go on in the internals.

00:40:08.140 --> 00:40:14.120
But the end point is that Enscripten lets you take any arbitrary C code and compile it to

00:40:14.720 --> 00:40:18.800
JavaScript that will run in a browser at nearish native speed.

00:40:19.920 --> 00:40:22.060
Good news is that CPython is written in C.

00:40:22.390 --> 00:40:27.720
And so you can compile CPython into a JavaScript version or into this JavaScript subset, and

00:40:27.770 --> 00:40:28.880
it will run in the browser.

00:40:29.260 --> 00:40:31.060
There's a bunch of other stuff you need to do as well.

00:40:31.110 --> 00:40:35.100
And Enscripten is providing a bunch of other things like guaranteeing a bunch of Unix system

00:40:35.300 --> 00:40:35.840
calls are available.

00:40:36.440 --> 00:40:38.000
But broadly, that's the idea here.

00:40:38.000 --> 00:40:40.860
So you can take any C code and have it run in the browser.

00:40:41.400 --> 00:40:43.880
And at that point, Python is just C code.

00:40:44.320 --> 00:40:44.420
So

00:40:44.420 --> 00:40:45.100
all of

00:40:45.100 --> 00:40:45.400
a sudden,

00:40:45.750 --> 00:40:49.060
yeah, but the best news is because the browser is everywhere, because

00:40:49.300 --> 00:40:53.480
JavaScript interpreters are everywhere, you've now got cross-platform binaries.

00:40:53.880 --> 00:40:58.640
You've got a format that you can compile to once, and it will run pretty much everywhere

00:40:59.120 --> 00:41:03.640
because existentially, every platform that matters has a web browser now, which means

00:41:03.800 --> 00:41:04.920
it's got the ability to run JavaScript.

00:41:05.600 --> 00:41:09.460
And so JavaScript becomes this cross-platform format

00:41:09.810 --> 00:41:11.940
without ever actually being JavaScript the language.

00:41:12.160 --> 00:41:14.200
It's just kind of exploiting some weird quirks

00:41:14.300 --> 00:41:14.400
of the

00:41:14.400 --> 00:41:14.880
way JavaScript

00:41:14.880 --> 00:41:15.600
works as a language.

00:41:16.080 --> 00:41:17.820
It's like saying you never write assembly,

00:41:18.080 --> 00:41:19.980
but kind of still do machine instructions.

00:41:20.200 --> 00:41:21.320
But you're always writing

00:41:21.320 --> 00:41:21.660
assembly.

00:41:21.880 --> 00:41:22.340
Yeah, exactly.

00:41:22.880 --> 00:41:27.200
There's a really, if you go back, oh gosh, 12, 13 years,

00:41:27.440 --> 00:41:29.240
Gary Bernhardt gave a talk at PyCon

00:41:29.980 --> 00:41:31.540
called The Birth and Death of JavaScript.

00:41:32.440 --> 00:41:33.040
So good.

00:41:33.390 --> 00:41:34.180
It was so good.

00:41:34.660 --> 00:41:35.500
It is hilarious.

00:41:36.180 --> 00:41:39.260
At the time, it was just straight up, oh, this is a funny gag,

00:41:39.860 --> 00:41:43.280
except that he has accurately predicted the next 15 years

00:41:43.480 --> 00:41:46.540
of software development in terms of the way everything has gone.

00:41:46.850 --> 00:41:48.780
And I've never spoken to Gary about it,

00:41:48.840 --> 00:41:52.400
so I don't know how much of this was just for the giggles

00:41:53.030 --> 00:41:56.620
and how much of it was accurately like this is where things are going.

00:41:57.740 --> 00:41:58.720
But as it

00:41:58.720 --> 00:41:58.860
turns out It

00:41:58.860 --> 00:41:59.160
was

00:41:59.160 --> 00:42:00.900
both really, really entertaining

00:42:00.900 --> 00:42:04.080
and really technically well-presented

00:42:04.340 --> 00:42:05.780
and predicted, like you said.

00:42:05.900 --> 00:42:06.080
Yes.

00:42:06.460 --> 00:42:06.800
It's something.

00:42:07.240 --> 00:42:08.940
And for people who are not familiar with this stuff,

00:42:09.040 --> 00:42:10.280
like one of the examples he showed,

00:42:10.360 --> 00:42:11.300
I don't know if he came up with it

00:42:11.340 --> 00:42:13.140
or he was just quoting and showing it off,

00:42:13.460 --> 00:42:16.380
but somebody took Mozilla Firefox, I think,

00:42:16.480 --> 00:42:18.280
and compiled that into Scriptum,

00:42:18.320 --> 00:42:19.420
was running inside of Chrome,

00:42:19.940 --> 00:42:21.200
but then inside the embedded,

00:42:21.620 --> 00:42:23.820
Firefox was running like Doom compiled,

00:42:23.880 --> 00:42:26.280
Doom Scriptum or some crazy 3D.

00:42:26.500 --> 00:42:27.200
I mean, it was wild.

00:42:27.500 --> 00:42:27.660
Yeah.

00:42:27.820 --> 00:42:34.660
The list of things you can do once you've got the ability to compile C is truly phenomenal,

00:42:35.320 --> 00:42:35.580
purely

00:42:35.580 --> 00:42:36.120
because

00:42:36.120 --> 00:42:43.220
the C compiler toolchain for all of the flaws of C as a language, C is

00:42:43.320 --> 00:42:43.780
lingua franca.

00:42:44.160 --> 00:42:44.280
C

00:42:44.280 --> 00:42:45.180
is where everything

00:42:45.180 --> 00:42:45.620
is done.

00:42:46.420 --> 00:42:47.380
And we're

00:42:47.380 --> 00:42:50.640
now kind of removing, like the whole thing with LRVM is essentially we're removing

00:42:50.920 --> 00:42:53.880
C from the front end, letting you put any language you want on the front.

00:42:54.420 --> 00:42:57.200
But now we can use the same toolchain to target any platform we want.

00:42:57.320 --> 00:43:05.060
And so you divorce the specific language from the tool chain that is producing platform-specific binaries.

00:43:05.340 --> 00:43:05.560
Nice.

00:43:05.920 --> 00:43:08.340
All right, let's talk about some of the projects and get some updates on them.

00:43:08.580 --> 00:43:09.300
I know it's been a while.

00:43:09.960 --> 00:43:10.360
And,

00:43:10.880 --> 00:43:14.280
you know, you've got a lot of support from Anaconda, which, you know, thank you again.

00:43:15.060 --> 00:43:15.300
Yes,

00:43:15.440 --> 00:43:15.760
absolutely.

00:43:16.020 --> 00:43:16.460
That's

00:43:16.460 --> 00:43:16.640
awesome.

00:43:17.080 --> 00:43:20.580
So we'll maybe touch on some of the high-level or most important ones.

00:43:20.960 --> 00:43:21.100
Toga?

00:43:21.780 --> 00:43:22.180
So

00:43:22.180 --> 00:43:24.300
Toga, the cross-platform GUI toolkit.

00:43:24.520 --> 00:43:29.420
So this is the analog of a Kibbe or a QT or a WX Windows.

00:43:30.040 --> 00:43:33.080
It's the API that lets you say, I want a window that has a button.

00:43:33.360 --> 00:43:36.620
And when I press the button, the light goes off, whatever

00:43:36.620 --> 00:43:37.500
you want it to do.

00:43:37.660 --> 00:43:39.500
Put this text in the label or whatever.

00:43:39.780 --> 00:43:40.000
Exactly,

00:43:40.280 --> 00:43:40.520
exactly.

00:43:41.600 --> 00:43:46.020
So it is cross-platform, pure Python, runs cross-platform.

00:43:47.040 --> 00:43:49.440
And by cross-platform, I mean all the desktop platforms,

00:43:49.490 --> 00:43:52.760
so Windows, macOS, Linux with GTK.

00:43:53.280 --> 00:43:54.700
It runs as a web.

00:43:55.220 --> 00:43:56.640
There's a web backend and a textual backend.

00:43:56.760 --> 00:43:58.180
Both of those are very early prototypes,

00:43:58.340 --> 00:44:00.100
but I can't, like there are demos I can do

00:44:00.240 --> 00:44:01.220
that I demonstrate that it works.

00:44:02.220 --> 00:44:03.400
And also iOS and Android.

00:44:04.380 --> 00:44:06.800
So essentially anywhere that you might want plausibly

00:44:06.940 --> 00:44:07.820
to have a user interface,

00:44:08.420 --> 00:44:10.700
I can give you a user interface purely written in Python.

00:44:11.460 --> 00:44:14.820
We also cover a bunch of hardware services as well.

00:44:15.000 --> 00:44:18.040
So for example, you can, using a pure Python interface,

00:44:18.580 --> 00:44:19.720
get a GPS read.

00:44:19.780 --> 00:44:21.080
You can work out where you are at a GPS

00:44:21.580 --> 00:44:22.540
and we have a native WAP widget.

00:44:22.620 --> 00:44:26.480
So you can say, get a GPS read and put it by center of the map of where I am currently standing.

00:44:26.920 --> 00:44:29.720
And that works on iOS, on Android, on macOS.

00:44:30.400 --> 00:44:35.000
We've got it working on GTK and we've got a PR in flight to make it work on Windows as well, I think.

00:44:35.900 --> 00:44:39.780
That, you know, it just, same code just runs everywhere and just, where am I?

00:44:39.850 --> 00:44:40.400
Give me an answer.

00:44:40.710 --> 00:44:41.020
Give me a

00:44:41.020 --> 00:44:41.420
ping every

00:44:41.420 --> 00:44:42.840
time I move a significant distance.

00:44:43.700 --> 00:44:45.380
And also for cameras, similar, similar thing for cameras.

00:44:46.540 --> 00:44:49.940
There is a question out of the audience, which I don't know the answer, but I'll throw that for you.

00:44:50.020 --> 00:44:53.440
Is there any more love coming for the Beware WebView widget?

00:44:55.680 --> 00:44:58.960
Having a case, not what they're referring to with Ceph,

00:44:59.060 --> 00:44:59.160
but

00:44:59.160 --> 00:45:01.680
is there

00:45:01.680 --> 00:45:02.860
more love coming?

00:45:03.480 --> 00:45:05.820
I mean, sure, as soon as somebody wants to pay attention to it.

00:45:05.880 --> 00:45:08.860
Am I actively intending in the very near future to do anything with it?

00:45:09.420 --> 00:45:10.140
Probably not.

00:45:10.170 --> 00:45:15.760
The most likely change that's on the horizon is to close the loop on callbacks.

00:45:15.840 --> 00:45:18.080
So at the moment, you can, from Python,

00:45:18.620 --> 00:45:20.720
inject arbitrary JavaScript into a web view,

00:45:21.660 --> 00:45:24.480
but you can't have something happen in the JavaScript

00:45:24.700 --> 00:45:26.740
to trigger an action outside in the Python,

00:45:26.840 --> 00:45:29.660
which is essentially kind of the last piece of the puzzle you need

00:45:29.690 --> 00:45:33.140
to have a full kind of electron clone.

00:45:33.270 --> 00:45:34.800
Yeah, I was going to say, that's very electron.

00:45:35.700 --> 00:45:36.580
Yeah, we

00:45:36.580 --> 00:45:39.280
actually have a bunch of tooling in place.

00:45:39.500 --> 00:45:41.280
We call it positron because it's like electron,

00:45:41.460 --> 00:45:42.400
but positive because it's Python.

00:45:42.510 --> 00:45:42.960
I love it.

00:45:43.490 --> 00:45:43.820
I love it.

00:45:43.960 --> 00:45:47.860
Yeah, so we can take a website and turn it into a native app.

00:45:48.240 --> 00:45:50.720
The only thing you can't do is then close the loop back out

00:45:50.780 --> 00:45:55.860
and call native hardware type stuff back into the Python API.

00:45:56.320 --> 00:45:57.220
Not impossible to do.

00:45:57.520 --> 00:45:59.680
I know exactly how to do it on iOS and macOS.

00:45:59.820 --> 00:46:01.400
I think I know how to do it on GTK.

00:46:01.420 --> 00:46:02.580
I don't know how to do it on Windows.

00:46:03.980 --> 00:46:07.000
So that might happen at some point in the not too distant future.

00:46:08.360 --> 00:46:11.860
Beyond that, oh, Seth, are they referring to the Chromium framework?

00:46:12.440 --> 00:46:15.180
No intention to, but if someone wants to write that up,

00:46:15.680 --> 00:46:17.760
there's no reason you couldn't be a standalone widget.

00:46:17.920 --> 00:46:23.760
This is very much from the Django days of if there is no,

00:46:24.040 --> 00:46:27.780
just because something exists doesn't mean it needs to be in the core.

00:46:27.860 --> 00:46:30.040
So if someone wants to write a third-party widget

00:46:30.240 --> 00:46:32.620
that wraps the Chromium embedded framework

00:46:33.340 --> 00:46:36.480
and turn it into a Toga widget, Toga will support that.

00:46:36.660 --> 00:46:39.280
And to the extent that if there's something that makes it a little bit crusty,

00:46:39.320 --> 00:46:41.180
there's probably a couple of areas where it could be a little bit smoother.

00:46:41.720 --> 00:46:44.340
If there's a way we can make it smoother, I'm totally on board with that.

00:46:44.840 --> 00:46:47.100
Doesn't mean it needs to be in Toga core itself.

00:46:47.760 --> 00:46:51.360
Django has a huge ecosystem of Django compatible plugins.

00:46:52.060 --> 00:46:53.620
Toga very much can be in that same space.

00:46:54.640 --> 00:46:57.880
Everything doesn't have to be in Toga for it to be useful in Toga.

00:46:58.200 --> 00:46:58.580
That's awesome.

00:46:58.720 --> 00:46:59.120
That's good to know.

00:46:59.480 --> 00:47:04.580
So I guess maybe the big updates here are the textual and the web targets for Toga.

00:47:04.610 --> 00:47:04.960
Is that right?

00:47:05.660 --> 00:47:09.440
They've been the biggest changes in the last eight years, I guess, is that those two now

00:47:10.210 --> 00:47:10.320
exist.

00:47:11.480 --> 00:47:15.140
And obviously you still need a lot of work, but like proof of concept, you can do it.

00:47:15.840 --> 00:47:16.280
And it's really

00:47:16.280 --> 00:47:18.720
just kind of turn the handle and make more widgets come out.

00:47:19.620 --> 00:47:22.380
The biggest sort of impediment to that at the moment is actually testing.

00:47:22.860 --> 00:47:28.700
One of the changes that has come on since I've been working at Anaconda full time is we've

00:47:28.840 --> 00:47:29.620
gone and got test coverage.

00:47:29.720 --> 00:47:34.300
We've got 100% test coverage of all of the core and all of the desktop and mobile platforms.

00:47:34.580 --> 00:47:39.440
So we have a very, very solid regression test suite to know that things aren't going to

00:47:39.460 --> 00:47:42.600
break as a result of this weird little tweak over here that we make.

00:47:42.680 --> 00:47:44.120
We've actually got validation of all that.

00:47:44.540 --> 00:47:47.260
We don't have that yet on web and textual,

00:47:47.820 --> 00:47:50.240
mostly because of quirks of how those platforms actually run.

00:47:50.380 --> 00:47:53.840
There's a kind of a foundational question we need to answer on the web one

00:47:53.840 --> 00:47:54.320
in particular.

00:47:55.120 --> 00:47:56.940
Yeah, I can imagine how the textual one works.

00:47:57.480 --> 00:48:00.720
What's the runtime look for part of the web?

00:48:00.820 --> 00:48:02.680
Is that PyScript or is that PyOxid?

00:48:03.700 --> 00:48:04.940
It is PyScript,

00:48:04.990 --> 00:48:05.100
yeah.

00:48:05.130 --> 00:48:08.400
So it's a briefcase, which I guess we'll get to in a moment,

00:48:08.560 --> 00:48:10.420
But Briefcase has the ability to target a web deployment.

00:48:10.540 --> 00:48:17.140
It generates a HTML page that injects a load this wheel.

00:48:17.600 --> 00:48:18.960
And this wheel is your app.

00:48:19.420 --> 00:48:24.720
But it's a Python wheel that just contains your code for your running app.

00:48:25.340 --> 00:48:25.540
And, yeah,

00:48:25.600 --> 00:48:26.400
but it's PyScript

00:48:26.400 --> 00:48:27.160
that's making that work.

00:48:27.500 --> 00:48:28.560
Yeah, PyScript is neat.

00:48:28.800 --> 00:48:29.280
Definitely neat.

00:48:29.600 --> 00:48:30.040
Just

00:48:30.040 --> 00:48:31.640
the fact that it's opening up these types of things.

00:48:31.820 --> 00:48:34.500
So Briefcase, yeah, let's dive a little more into that one.

00:48:34.840 --> 00:48:37.880
Yeah, so Briefcase is then sort of the other part of the story.

00:48:38.100 --> 00:48:39.500
you know, I've written this out.

00:48:39.500 --> 00:48:39.760
It gives you the runtime,

00:48:40.210 --> 00:48:41.800
but you're still in the terminal to launch it

00:48:41.820 --> 00:48:43.840
with virtual environments and all that kind of business, right?

00:48:44.080 --> 00:48:44.360
Yeah, okay.

00:48:44.760 --> 00:48:45.800
Yeah, so briefcase is,

00:48:46.220 --> 00:48:47.760
the scary thing is at the end of the day,

00:48:47.860 --> 00:48:50.440
briefcase is really just kind of three templates

00:48:50.590 --> 00:48:51.260
in a trench coat.

00:48:51.660 --> 00:48:52.560
There's not a lot of,

00:48:52.830 --> 00:48:55.380
like, there's not a lot that it's doing beyond that

00:48:55.560 --> 00:48:58.440
and also encoding all of the annoying details

00:48:58.820 --> 00:49:01.940
that are embedded 15 pages deep in Microsoft's

00:49:02.120 --> 00:49:05.140
how to write an app, you know, documentation

00:49:06.500 --> 00:49:10.240
around code signing and packaging and building an installer

00:49:10.560 --> 00:49:12.000
and all of that kind of stuff.

00:49:12.680 --> 00:49:17.200
So on the theory that 99% of Python users have code

00:49:17.300 --> 00:49:21.620
that runs as Python minus M, my app, make that be a macOS app.

00:49:21.870 --> 00:49:22.780
And that's what Briefcase does.

00:49:22.980 --> 00:49:25.800
It says, okay, how do I turn this into an icon on my desktop

00:49:26.000 --> 00:49:28.420
that I can double click and the app will just start.

00:49:28.760 --> 00:49:29.540
And it will include

00:49:29.540 --> 00:49:30.640
an embedded

00:49:30.640 --> 00:49:31.500
version of Python.

00:49:32.290 --> 00:49:34.960
So I don't need to tell my end user how to install Python.

00:49:35.060 --> 00:49:41.060
it will be signed and notarized in accordance with Apple's latest specifications it might come

00:49:41.180 --> 00:49:44.500
inside a DMG because I need to be able to distribute it along with a readme or it might

00:49:44.500 --> 00:49:49.760
come as a.pkg file because I actually need like in the case of non-GUI apps you actually like you

00:49:49.800 --> 00:49:53.420
want to be able to put something on your path and you have to have like a post install script and

00:49:53.620 --> 00:49:59.420
pkgs how you do that on macOS similarly on Windows it produces an MSI and it drops a Python

00:49:59.660 --> 00:50:04.240
embedded and all that kind of stuff make sure your dependencies are there on macOS it makes sure that

00:50:04.220 --> 00:50:09.020
of you install. If I'm building it on ARM machine, the app will still run on x86 because it'll install

00:50:09.500 --> 00:50:13.820
both versions of both the x86 and the ARM binaries and merge them where they're necessary and do all

00:50:13.820 --> 00:50:18.560
that kind of stuff. So it's all the little fiddly details. It is essentially just running a bunch

00:50:18.580 --> 00:50:24.100
of command line, like everything Briefcase does is just a command line tool or rolling out a template.

00:50:25.180 --> 00:50:34.180
If you turn up the verbosity, it will tell you in the prompt, like this is what I'm running. I'm

00:50:34.200 --> 00:50:35.780
notary tool and so on and so on.

00:50:36.460 --> 00:50:37.520
But you don't have to worry about that.

00:50:37.640 --> 00:50:39.580
Like it's just going to, this is what will encode.

00:50:39.580 --> 00:50:45.760
It'll do it all for you and just spit out either a DMG, a.zip, an MSI,

00:50:47.140 --> 00:50:51.640
IPA files on iOS, APK files or AAB files on Android,

00:50:51.960 --> 00:50:52.900
whatever the native platform is.

00:50:53.140 --> 00:50:56.480
And then on Linux, one of the things we've added more recently,

00:50:56.820 --> 00:51:02.620
we can do flat packs, we can do Debian, RPM, PKG zip,

00:51:03.160 --> 00:51:05.340
PKG files for Arch and Manjuro,

00:51:05.840 --> 00:51:08.680
like all of the common packaging formats we try to cover.

00:51:08.840 --> 00:51:10.440
The only one that I can think of that's notable

00:51:10.560 --> 00:51:11.660
that we don't cover at the moment.

00:51:12.480 --> 00:51:14.520
We don't do NCS installers on Windows

00:51:15.280 --> 00:51:19.360
and we don't do Snap packages on Linux.

00:51:19.840 --> 00:51:22.800
Not because we can't, just because I've only got two arms

00:51:23.080 --> 00:51:25.460
and there's a limit to how much I can practically do.

00:51:25.700 --> 00:51:28.200
If someone wants those, I can point you at the code

00:51:28.200 --> 00:51:29.140
and show you what you're going to do.

00:51:29.300 --> 00:51:31.720
And it's a moderately...

00:51:31.740 --> 00:51:35.760
If you know the commands you need to run to make a thing happen, I can show you how to

00:51:35.920 --> 00:51:36.640
plug that into Briefcase.

00:51:36.720 --> 00:51:39.740
And like Briefcase's infrastructure is designed to be pluggable.

00:51:39.780 --> 00:51:41.780
So it doesn't even need to be in Briefcase.

00:51:41.780 --> 00:51:44.800
You can, again, do it as an external plugin and have it plug into Briefcase.

00:51:45.080 --> 00:51:46.380
There are two things I want to ask you about here.

00:51:46.760 --> 00:51:47.000
One,

00:51:47.160 --> 00:51:48.520
notarization and signing.

00:51:48.960 --> 00:51:50.080
I remember how

00:51:50.080 --> 00:51:54.920
long ago I built C++ desktop apps and.NET desktop apps.

00:51:55.100 --> 00:51:58.760
And you could just compile them and give them to somebody and let them run it.

00:51:59.120 --> 00:52:01.240
And those sweet days are long gone.

00:52:01.680 --> 00:52:01.720
You

00:52:01.720 --> 00:52:03.600
know, it'll get flagged with big warnings.

00:52:03.830 --> 00:52:07.940
Like this looks like a virus because it didn't go through our digital signature system.

00:52:08.620 --> 00:52:08.720
Yep.

00:52:09.120 --> 00:52:10.360
What a frustrating thing.

00:52:10.640 --> 00:52:11.860
So this has support for that.

00:52:12.160 --> 00:52:12.540
It does.

00:52:12.840 --> 00:52:12.900
Yeah.

00:52:14.200 --> 00:52:14.380
Yeah.

00:52:14.780 --> 00:52:18.160
It turns out there are bad people on the internet and they're willing

00:52:18.160 --> 00:52:18.620
to do bad

00:52:18.620 --> 00:52:18.900
things.

00:52:19.590 --> 00:52:19.840
Who knew?

00:52:20.780 --> 00:52:25.460
So yeah, macOS has a bunch of processes for signing all of the binaries in an application

00:52:26.020 --> 00:52:30.420
and then stamping what's called a notarization certificate to the installer to say,

00:52:30.600 --> 00:52:33.760
This is a package in a format that hasn't been modified

00:52:34.040 --> 00:52:36.440
that I am willing to verify as me as a person.

00:52:37.040 --> 00:52:39.160
This is what the version of the package looks like

00:52:39.580 --> 00:52:40.440
when it's correctly installed.

00:52:41.440 --> 00:52:43.000
And then Sorry,

00:52:43.160 --> 00:52:44.160
probably in practice, if you

00:52:44.160 --> 00:52:47.260
want to distribute stuff to Mac and Windows, you probably

00:52:47.260 --> 00:52:49.400
need to create a developer account and sign

00:52:49.400 --> 00:52:50.940
these things, unless your

00:52:50.940 --> 00:52:53.740
users are willing to run with the big scary, this looks

00:52:53.740 --> 00:52:55.240
unsigned and untrusted. We've

00:52:55.240 --> 00:52:56.680
moved it to the trash, or you

00:52:56.680 --> 00:52:57.740
can go in there and run it. You know

00:52:57.740 --> 00:52:58.220
what I mean? Yeah,

00:52:58.460 --> 00:52:59.340
like on macOS,

00:52:59.460 --> 00:53:01.160
It like literally has to be at this point.

00:53:01.200 --> 00:53:02.480
You actually can't get away

00:53:02.780 --> 00:53:04.740
with not getting a developer certificate

00:53:04.920 --> 00:53:07.580
because the secure stuff on the M1 ship

00:53:08.100 --> 00:53:09.160
literally will not run.

00:53:09.440 --> 00:53:11.620
You can do cheap and nasty ad hoc signing,

00:53:11.740 --> 00:53:13.100
which means it will run on my machine.

00:53:14.080 --> 00:53:15.520
But if you want to give it to anybody else,

00:53:16.160 --> 00:53:17.240
it is now at the point

00:53:17.400 --> 00:53:18.880
where you've got to go into the settings,

00:53:19.420 --> 00:53:20.000
explicitly say,

00:53:20.240 --> 00:53:21.300
I'm willing to trust content

00:53:21.480 --> 00:53:22.640
that comes from an unknown provider.

00:53:23.180 --> 00:53:26.360
Start the app by pressing option and double click,

00:53:26.880 --> 00:53:28.960
selecting the option of I'm willing to accept this.

00:53:29.260 --> 00:53:32.960
Like it can be done, but it's like nobody is actually ever going to do that.

00:53:33.960 --> 00:53:34.900
So you basically, yeah,

00:53:34.960 --> 00:53:35.320
you've got to

00:53:35.320 --> 00:53:38.380
sign up for a $99 a year developer account

00:53:38.780 --> 00:53:39.820
and then go through the signing process.

00:53:40.060 --> 00:53:40.460
And signing

00:53:40.460 --> 00:53:41.160
is

00:53:41.160 --> 00:53:42.380
a non-trivial activity.

00:53:42.560 --> 00:53:43.340
It is difficult.

00:53:43.860 --> 00:53:45.780
There are like you've got to do things in the right order.

00:53:46.280 --> 00:53:50.060
And there is like even you have to submit the app in a zip format.

00:53:50.800 --> 00:53:53.980
But you can't just use PK zip or your standard command line zip.

00:53:54.140 --> 00:53:57.460
You've got to use Ditto, which is Mac's version of zip,

00:53:57.840 --> 00:54:04.880
Because otherwise, file system properties can end up being corrupted because the UTF-18 coding won't go quite reversible in the way.

00:54:04.980 --> 00:54:07.060
Like, it is a nightmare.

00:54:07.420 --> 00:54:09.080
Briefcase solves all those problems for you.

00:54:09.220 --> 00:54:14.500
It should be as straightforward as just package this thing and sign and it works.

00:54:15.780 --> 00:54:16.180
Similarly,

00:54:16.180 --> 00:54:17.800
it's not quite as bad on Windows.

00:54:18.060 --> 00:54:21.640
Like, Windows will let you install an unsigned binary.

00:54:21.720 --> 00:54:24.600
It just comes up with sort of the, this comes from an unknown developer.

00:54:24.740 --> 00:54:25.920
Are you sure you want to do this?

00:54:26.060 --> 00:54:26.620
And you say, okay.

00:54:27.540 --> 00:54:34.800
But realistically, like people's willingness to click the this looks like it might be insecure is low and decreasing.

00:54:35.400 --> 00:54:39.060
And so, yeah, you've just got to go get a certificate, sign the app, validate that it's you.

00:54:39.780 --> 00:54:42.240
It's kind of it's the price of doing app business at this point.

00:54:42.560 --> 00:54:46.140
Yeah, I guess it's sort of the equivalent of you have to have SSL to run a website.

00:54:46.620 --> 00:54:46.760
However,

00:54:47.010 --> 00:54:47.140
exactly.

00:54:47.370 --> 00:54:48.540
It is exactly that.

00:54:48.920 --> 00:54:50.420
Yes, but we're missing Let's Encrypt.

00:54:50.650 --> 00:54:51.360
We're missing Let's Encrypt.

00:54:51.400 --> 00:54:51.560
Yes.

00:54:51.650 --> 00:54:52.220
That's that part.

00:54:52.240 --> 00:54:52.300
Yeah.

00:54:52.860 --> 00:55:04.400
From the Windows point of view, there is absolutely a window of opportunity to do a Let's Encrypt because Windows doesn't specify who you've got to get your certificate from.

00:55:04.710 --> 00:55:06.880
It just has to be signed by a root certificate that they honor.

00:55:07.580 --> 00:55:10.780
So, like, essentially the instructions in briefcase kind of go get a certificate.

00:55:10.960 --> 00:55:11.460
Where do you get it from?

00:55:12.340 --> 00:55:12.600
You know,

00:55:12.880 --> 00:55:13.280
here

00:55:13.280 --> 00:55:13.880
are some options.

00:55:14.030 --> 00:55:14.520
Go have fun.

00:55:15.300 --> 00:55:19.540
So there is absolutely an opportunity for someone to do a Let's Encrypt here for app signing.

00:55:19.900 --> 00:55:27.420
Unfortunately for Apple, that doesn't apply because Apple does insist that the certificate needs to be issued by them, signed by them, so that they can revoke it.

00:55:28.010 --> 00:55:34.980
And maybe the EU changes around app distribution will relax that somewhat, but at least for the moment, you've got to go through Apple.

00:55:35.440 --> 00:55:35.500
Yeah.

00:55:35.890 --> 00:55:38.540
As salty as I am at the EU about the cookie warnings.

00:55:39.660 --> 00:55:39.880
Yeah.

00:55:40.210 --> 00:55:40.360
Yeah.

00:55:40.620 --> 00:55:41.660
But I do have

00:55:41.660 --> 00:55:45.540
hope that they can bring some reason to some of the other App Store type behaviors.

00:55:45.750 --> 00:55:46.700
It would certainly be.

00:55:46.940 --> 00:55:47.660
I would not.

00:55:47.740 --> 00:55:48.740
I welcome that development.

00:55:49.180 --> 00:55:50.800
I am waiting to see what happens.

00:55:51.680 --> 00:55:53.100
I had a lot of hope that the App Store stuff,

00:55:53.660 --> 00:55:55.620
I had a lot of hope opening the App Store thing

00:55:55.800 --> 00:55:58.140
would provide a way to make it easier

00:55:58.340 --> 00:55:59.520
for Beware to distribute apps.

00:56:00.540 --> 00:56:01.920
But in practice, it doesn't look like

00:56:02.020 --> 00:56:02.800
that's actually going to happen.

00:56:03.140 --> 00:56:03.920
So yeah.

00:56:04.500 --> 00:56:05.440
It's, yeah.

00:56:05.760 --> 00:56:08.520
Nice try, but they squeeze through another

00:56:08.520 --> 00:56:09.820
track,

00:56:10.240 --> 00:56:10.360
basically.

00:56:11.180 --> 00:56:11.760
It is what it is.

00:56:12.180 --> 00:56:12.820
It is what it is.

00:56:14.180 --> 00:56:15.620
The gatekeeper stuff drives me crazy.

00:56:15.820 --> 00:56:18.179
I've had so much trouble getting my mobile apps

00:56:18.200 --> 00:56:20.260
in the app store, not for reasons technical,

00:56:20.540 --> 00:56:21.460
just for reasons of...

00:56:21.890 --> 00:56:24.360
Yeah, and I guess that's the

00:56:24.360 --> 00:56:24.540
thing.

00:56:24.540 --> 00:56:27.040
It's like, I will, to a limited extent,

00:56:28.360 --> 00:56:33.400
defend the, not so much the gatekeeping aspect of it,

00:56:33.480 --> 00:56:35.660
but the fact that there is a process involved

00:56:36.000 --> 00:56:39.340
to protect against completely arbitrary content.

00:56:40.320 --> 00:56:41.660
That side of it is useful.

00:56:42.300 --> 00:56:45.280
But the fact that there's, like, it is that locked down

00:56:45.460 --> 00:56:46.959
and only from Apple is the part

00:56:46.980 --> 00:56:48.360
where it becomes a little bit onerous

00:56:48.500 --> 00:56:48.640
and that

00:56:48.640 --> 00:56:49.460
there's no competition

00:56:49.640 --> 00:56:50.680
to make Apple work better,

00:56:50.900 --> 00:56:51.740
I guess is the real thing.

00:56:51.780 --> 00:56:51.900
Yeah, yeah.

00:56:52.160 --> 00:56:53.140
You can't go into a

00:56:53.140 --> 00:56:53.700
competition.

00:56:54.140 --> 00:56:54.580
Yeah, and

00:56:54.580 --> 00:56:54.920
the rent

00:56:54.920 --> 00:56:55.540
is a, yeah.

00:56:55.840 --> 00:56:56.400
Yeah, yeah, yeah.

00:56:56.540 --> 00:56:57.180
From my app there.

00:56:57.480 --> 00:56:59.220
You don't have in-app purchasing.

00:56:59.440 --> 00:57:00.900
Well, I don't want to sell anything in my app.

00:57:00.900 --> 00:57:02.200
I just want to let people view the stuff

00:57:02.380 --> 00:57:03.060
that we already got online.

00:57:03.440 --> 00:57:04.540
Well, you're going to have to add it.

00:57:04.800 --> 00:57:08.260
So weeks and weeks of paying developers

00:57:08.680 --> 00:57:09.520
and stuff to build it

00:57:09.840 --> 00:57:11.680
just so they can have their few bucks,

00:57:11.840 --> 00:57:12.260
you know what I mean?

00:57:12.300 --> 00:57:12.780
And it's just like,

00:57:12.900 --> 00:57:14.060
you have no idea how

00:57:14.060 --> 00:57:15.080
much pain this is.

00:57:15.420 --> 00:57:16.380
Yeah, and like, I guess,

00:57:16.640 --> 00:57:21.500
I could almost, I don't like it, but I could almost grant them that, you know, the golden rule of

00:57:22.140 --> 00:57:26.120
has the gold makes the rules, but it's their store. They get to decide what's in there,

00:57:26.180 --> 00:57:27.720
but I don't have the option of another store.

00:57:28.400 --> 00:57:30.260
And in

00:57:30.260 --> 00:57:32.880
particular, the review process is so

00:57:33.320 --> 00:57:37.100
inscrutable. Like Google is no better in this regard. If something

00:57:37.100 --> 00:57:37.720
goes wrong

00:57:37.720 --> 00:57:38.340
with your Google

00:57:38.540 --> 00:57:46.600
application, good luck with that. For all the money they're taking, they're not providing good

00:57:46.600 --> 00:57:49.220
customer service. They're providing no as a customer service.

00:57:50.300 --> 00:57:51.520
Exactly. Yeah. They're both

00:57:51.640 --> 00:57:57.220
bad. I'm not saying Google's good. They're both bad. Okay. But for a briefcase here, we have,

00:57:57.520 --> 00:58:03.220
we have the targets that I would expect Linux, Mac, Windows. Yes. But iPad, iPhone, Android,

00:58:03.460 --> 00:58:05.600
tell us about that. Even watch.

00:58:06.500 --> 00:58:09.320
So we, yeah, so we don't, we don't actually have it working for

00:58:09.440 --> 00:58:09.700
watchOS.

00:58:09.880 --> 00:58:10.160
I have

00:58:10.160 --> 00:58:10.860
a proof of,

00:58:11.180 --> 00:58:14.960
yeah, I have a proof of concept that it can work on Apple TV. I have

00:58:14.980 --> 00:58:16.800
written a Python application for Apple TV.

00:58:17.730 --> 00:58:19.740
Web deployment, actually, that's that website's out of date.

00:58:19.810 --> 00:58:20.560
I should need to update that.

00:58:20.630 --> 00:58:21.620
We do have web deployments.

00:58:21.840 --> 00:58:23.900
Put that in the proper bullet list, right?

00:58:23.940 --> 00:58:24.140
Yes.

00:58:24.500 --> 00:58:25.500
Yes, it should be on the proper bullet list.

00:58:26.620 --> 00:58:31.060
So, yeah, but submitting to an app store, there are iOS apps,

00:58:31.110 --> 00:58:33.880
there are Android apps in the Apple and Google app stores

00:58:34.900 --> 00:58:36.540
that are written with BWare.

00:58:37.480 --> 00:58:39.020
So you are producing a binary.

00:58:39.110 --> 00:58:41.200
It is signed and validated and then sent to Apple,

00:58:41.310 --> 00:58:43.880
and Apple says, yes, that's fine, and Google says, yes, that's fine,

00:58:44.020 --> 00:58:45.280
and it's available for purchase.

00:58:45.540 --> 00:58:46.100
So, yeah.

00:58:46.240 --> 00:58:46.420
Awesome.

00:58:46.560 --> 00:58:49.140
So what do you get, like an APK for Android?

00:58:49.440 --> 00:58:50.640
And what is the AP?

00:58:50.820 --> 00:58:51.540
It's an IPA.

00:58:51.720 --> 00:58:53.340
Yeah, it's an IPA, but you don't ever

00:58:53.340 --> 00:58:53.960
see it.

00:58:54.120 --> 00:58:56.520
Like you basically have to, for all practical purposes,

00:58:56.660 --> 00:58:57.920
you have to submit it through Xcode.

00:58:58.340 --> 00:59:00.740
That might be something we can resolve, but I haven't.

00:59:00.980 --> 00:59:01.240
They don't

00:59:01.240 --> 00:59:02.200
make it easy to find out

00:59:02.200 --> 00:59:02.740
how to not

00:59:02.740 --> 00:59:03.300
use Xcode

00:59:03.300 --> 00:59:03.700
to do it.

00:59:04.420 --> 00:59:06.500
No, I think you're probably committed.

00:59:06.680 --> 00:59:09.660
Even for my Flutter-based app, I've got to go do a build

00:59:09.900 --> 00:59:11.860
and an app store submission through Xcode.

00:59:12.020 --> 00:59:12.180
Yeah, yeah.

00:59:12.380 --> 00:59:13.120
The tools are

00:59:13.120 --> 00:59:14.700
there, but yeah.

00:59:15.860 --> 00:59:17.700
But yeah, you get an AAB for Android.

00:59:17.800 --> 00:59:22.880
You get effectively an IPA, but an Xcode project you can submit for iPhone.

00:59:23.640 --> 00:59:29.320
For web, you get a tarball that is basically upload to your web provider of choice,

00:59:29.400 --> 00:59:34.120
and it would work, and it would end up being similar for Apple TV

00:59:34.240 --> 00:59:36.480
or WatchOS or WearOS eventually.

00:59:36.620 --> 00:59:36.740
Awesome.

00:59:37.380 --> 00:59:40.540
Well, that's really great that you've been making so much progress on this,

00:59:40.960 --> 00:59:43.860
And is it Steven, the other guy you're working with?

00:59:44.920 --> 00:59:45.280
Malcolm.

00:59:45.800 --> 00:59:46.340
I'm sorry,

00:59:46.460 --> 00:59:46.580
Malcolm.

00:59:47.040 --> 00:59:48.660
You and Malcolm have been making so much progress.

00:59:48.860 --> 00:59:49.720
That's really, really great.

00:59:50.000 --> 00:59:53.660
And I think only good things are going to come from having the backing of Anaconda.

00:59:54.239 --> 00:59:55.860
So we've got just a couple of minutes left.

00:59:55.980 --> 00:59:58.600
What do you want to tell people about this project, these projects,

00:59:58.750 --> 01:00:00.220
how they should adopt them, where

01:00:00.220 --> 01:00:00.940
they're ready for use,

01:00:01.450 --> 01:00:02.360
and so on, things like that?

01:00:02.620 --> 01:00:05.620
I guess the quick thing I'd say is that we're not done yet.

01:00:05.820 --> 01:00:06.600
There's still more to come.

01:00:07.939 --> 01:00:10.380
Just a week and change ago, pip.

01:00:10.760 --> 01:00:15.480
sorry, PyPI officially started accepting iOS and Android wheels.

01:00:15.640 --> 01:00:17.700
So you can upload an iOS and Android wheel.

01:00:18.040 --> 01:00:20.680
There aren't any on there yet that I'm aware of,

01:00:20.740 --> 01:00:22.060
but I'm actively working on that.

01:00:22.120 --> 01:00:24.060
So just so I can prove, hey, look, yes, there's one over there.

01:00:24.100 --> 01:00:24.500
Look at it.

01:00:25.880 --> 01:00:27.420
But part of the reason there's not one there yet

01:00:27.600 --> 01:00:31.220
is that the tooling to build iOS and Android wheels is not quite there.

01:00:31.620 --> 01:00:33.160
And that's what I'm actively working on right now.

01:00:33.280 --> 01:00:36.760
I would be deeply surprised if by the end of this year,

01:00:36.860 --> 01:00:39.180
there aren't multiple high profile projects that have.

01:00:39.300 --> 01:00:45.900
I have the patches for Pillow to literally produce iOS wheels as part of their normal release process.

01:00:46.380 --> 01:00:49.480
They haven't even seen the PRs yet, but I'm

01:00:49.480 --> 01:00:50.440
certainly hoping to

01:00:50.440 --> 01:00:50.960
work with them.

01:00:51.280 --> 01:00:52.300
Yeah, I mean, they know it's coming.

01:00:52.500 --> 01:00:53.160
Hugo knows it's coming.

01:00:53.380 --> 01:01:00.500
So there is a lot of work still to do in terms of getting that patch accepted, but at least I know it can be done.

01:01:00.640 --> 01:01:15.560
And more importantly, things like CI build wheels, like the infrastructure for putting a build all these wheels as part of CI is something where I have the patch and I'm like this close to being able to submit a pull request to CI build wheel to say, here's the back end to let you generate iOS wheels.

01:01:16.300 --> 01:01:18.300
Similarly, we've got to do all that work for Android as well.

01:01:18.460 --> 01:01:20.100
So there is still a lot of work to come.

01:01:20.440 --> 01:01:32.360
My hope is that sort of by the end of this year, says he, being very hopeful, we'll be in a position where like anything you can do on a desktop platform, you can basically do on iOS and Android as well.

01:01:33.140 --> 01:01:40.600
With the caveat that there might be, if there's C code involved, you might need to actually like work out how to compile this thing for iOS and Android.

01:01:41.200 --> 01:01:43.860
For a lot of simple projects, literally there's nothing you've got to do.

01:01:43.920 --> 01:01:46.200
You've just cranked the handle and make the compiler do its thing.

01:01:46.480 --> 01:01:47.880
Yeah, especially if you have Python.

01:01:48.380 --> 01:01:48.940
Yeah, exactly.

01:01:49.620 --> 01:01:51.540
The other part that I'm sort of playing around with this year

01:01:51.860 --> 01:01:54.840
as a sort of a background project is doing for Enscripten

01:01:55.320 --> 01:01:58.980
what I did last year or I'm up and I did last year for iOS and Android,

01:01:59.120 --> 01:02:01.400
which is get Enscripten up to tier three support.

01:02:01.550 --> 01:02:05.580
So there will be a PEP and official supported platform.

01:02:05.750 --> 01:02:09.900
Like Enscripten will be an officially supported platform in CPython

01:02:10.360 --> 01:02:12.160
in the same way that iOS and Android are.

01:02:13.000 --> 01:02:16.520
I'm mostly shepherding that as sort of a member of the CPython core team

01:02:17.839 --> 01:02:21.040
and Hood Chatham is actually doing most of the heavy lifting on that.

01:02:21.580 --> 01:02:24.780
He's a PyDyde maintainer and is involved with PyScript as well

01:02:24.900 --> 01:02:25.980
to a lesser extent.

01:02:27.380 --> 01:02:29.520
And, yeah, so he is working on the patches for that

01:02:29.550 --> 01:02:31.920
and I'm kind of shepherding those patches into core.

01:02:32.620 --> 01:02:35.500
We are about to stand up and build bot to actually make the kind of the –

01:02:35.880 --> 01:02:39.060
make sure every pull request is validated to make sure it still works

01:02:39.180 --> 01:02:41.640
on Inscripten essentially, which is one of the big sort of milestones

01:02:42.020 --> 01:02:43.480
for official platform support.

01:02:43.740 --> 01:02:44.900
Yeah, that's super neat.

01:02:45.640 --> 01:02:46.240
What about CI?

01:02:46.260 --> 01:02:46.980
for people.

01:02:47.590 --> 01:02:48.260
Yeah, what about CI

01:02:48.330 --> 01:02:49.200
for people who want to build

01:02:49.720 --> 01:02:51.700
wheels for iOS and Android?

01:02:52.300 --> 01:02:53.000
That's essentially

01:02:53.050 --> 01:02:53.760
where CI build rule

01:02:53.760 --> 01:02:54.100
comes in.

01:02:54.280 --> 01:02:55.240
So you can do it right now.

01:02:55.320 --> 01:02:56.500
So every time we

01:02:56.500 --> 01:02:56.720
make

01:02:56.720 --> 01:02:57.420
a change to Toga,

01:02:57.880 --> 01:02:59.400
we run a full test suite

01:02:59.820 --> 01:03:00.980
on iOS, on Android,

01:03:01.720 --> 01:03:02.520
on macOS

01:03:02.660 --> 01:03:03.220
and all the other

01:03:03.380 --> 01:03:03.880
desktop platforms.

01:03:04.220 --> 01:03:06.120
You can use like GitHub Action CI

01:03:06.340 --> 01:03:07.280
will let you start

01:03:07.430 --> 01:03:08.500
an iPhone simulator

01:03:08.940 --> 01:03:09.600
and run the tests

01:03:09.780 --> 01:03:10.560
on that iPhone simulator.

01:03:10.610 --> 01:03:12.300
You can start an Android simulator

01:03:12.680 --> 01:03:13.540
and it will run a simulator

01:03:13.550 --> 01:03:14.020
on those platforms.

01:03:14.400 --> 01:03:15.440
It's like it takes three minutes

01:03:15.460 --> 01:03:21.240
to start the simulator, but that's just the price of doing business for iPhone, basically.

01:03:21.700 --> 01:03:25.620
Yeah, I guess they probably already have CI for iOS and Android because there's probably

01:03:25.620 --> 01:03:27.340
a ton of mobile projects on there.

01:03:27.440 --> 01:03:30.240
It's kind of unusual to complain it with Python, right?

01:03:30.540 --> 01:03:31.240
Yes, absolutely.

01:03:31.420 --> 01:03:33.460
And so you can do it.

01:03:33.880 --> 01:03:34.940
You can run those tests.

01:03:35.200 --> 01:03:38.440
There are probably some things that could be done at an institutional level at GitHub

01:03:38.780 --> 01:03:40.460
to make those tests run faster.

01:03:41.800 --> 01:03:48.420
But that's a, you know, now I've just got to convince Microsoft to implement an entirely new backend for GitHub Actions.

01:03:48.860 --> 01:03:51.020
And they don't support like Windows on ARM yet.

01:03:51.080 --> 01:03:52.700
So I'm not holding their breath thinking I support iOS.

01:03:53.640 --> 01:03:54.860
Yeah, yeah, I hear

01:03:54.860 --> 01:03:55.040
that.

01:03:55.420 --> 01:03:57.080
One final forward-looking question, I suppose.

01:03:57.440 --> 01:04:01.340
What do you see support for MScript in giving us?

01:04:01.640 --> 01:04:06.440
You know, for example, like having the JavaScript stuff, you'd see like, okay, well, great, I can run it in a browser.

01:04:06.600 --> 01:04:10.940
But well, then Node comes along and now I can run servers on it or I can distribute it or there's tool.

01:04:11.240 --> 01:04:14.060
Like there's these sort of ways in which these environments

01:04:14.460 --> 01:04:17.080
grow unexpectedly, at least for most people, I think.

01:04:17.130 --> 01:04:19.080
And how do you think InScript in my...

01:04:19.280 --> 01:04:19.740
So

01:04:19.740 --> 01:04:23.200
my hope is that what we'll end up seeing

01:04:23.680 --> 01:04:28.160
is the analog of React and Vue, but for Python.

01:04:29.500 --> 01:04:31.720
So you can right now, or you have been able to write

01:04:31.890 --> 01:04:33.860
a Django server-side website,

01:04:34.080 --> 01:04:36.240
pick any other GUI, any other web framework you want.

01:04:36.980 --> 01:04:38.560
You can write your server-side code, excuse me,

01:04:38.570 --> 01:04:40.280
you write your server-side code completely in Python.

01:04:40.490 --> 01:04:40.820
It's great.

01:04:41.840 --> 01:04:43.940
but then you've got to push your code to the front end

01:04:44.340 --> 01:04:47.620
and you have to write JavaScript on the front end.

01:04:48.020 --> 01:04:49.760
And so that's kind of essentially where Node came from

01:04:49.900 --> 01:04:51.380
is realizing that we've got to write this code,

01:04:51.430 --> 01:04:52.420
like we've got validation code,

01:04:52.540 --> 01:04:53.380
you've got to run it around the client

01:04:53.520 --> 01:04:54.200
and run it around the server.

01:04:54.520 --> 01:04:57.000
So I can't put Python in the client,

01:04:57.420 --> 01:04:59.000
so I might as well bring JavaScript back to the server.

01:04:59.320 --> 01:05:01.400
And so having that same language everywhere

01:05:01.550 --> 01:05:02.420
is a real advantage.

01:05:03.260 --> 01:05:05.120
InScripten lets us get Python into the browser,

01:05:05.560 --> 01:05:06.940
but the part that we don't have yet

01:05:07.160 --> 01:05:11.780
is the rich Python-first GUI framework in the browser.

01:05:13.260 --> 01:05:15.000
My hope is that with...

01:05:15.170 --> 01:05:16.640
Oh, you lost me there? I'm not sure.

01:05:18.260 --> 01:05:24.120
My hope is that with inscription in the browser,

01:05:24.740 --> 01:05:29.620
what we'll get is the ability to build that toolkit.

01:05:30.120 --> 01:05:31.080
I don't know what it is.

01:05:31.110 --> 01:05:33.360
I don't know what will stimulate its development,

01:05:33.530 --> 01:05:36.080
but it should hopefully make it, or at least makes it possible.

01:05:36.680 --> 01:05:43.000
And once it's possible, then a bunch of people, you know, project people can start playing around with it and actually making things.

01:05:46.140 --> 01:05:47.300
Oh, we lost Russell.

01:05:49.779 --> 01:05:52.020
Well, that's probably a good place to call it, folks.

01:05:52.720 --> 01:05:53.940
Thanks to Russell for being on the show.

01:05:54.360 --> 01:05:55.060
And thank you all for listening.

01:05:55.600 --> 01:05:56.040
Talk to you all later.

01:05:56.450 --> 01:05:56.540
Bye.

01:05:58.180 --> 01:06:00.560
This has been another episode of Talk Python To Me.

01:06:01.360 --> 01:06:02.380
Thank you to our sponsors.

01:06:02.770 --> 01:06:04.000
Be sure to check out what they're offering.

01:06:04.130 --> 01:06:05.420
It really helps support the show.

01:06:06.300 --> 01:06:09.620
This episode is sponsored by Posit and Posit Workbench.

01:06:10.380 --> 01:06:15.100
Posit Workbench allows data scientists to code in Python within their preferred environment

01:06:15.570 --> 01:06:17.580
without any additional strain on IT.

01:06:18.340 --> 01:06:21.540
It gives data scientists access to all the development environments they love,

01:06:21.720 --> 01:06:24.640
including Jupyter Notebooks, JupyterLab, Positron, and VS Code,

01:06:25.100 --> 01:06:27.740
and helps ensure reproducibility and consistency.

01:06:28.260 --> 01:06:30.540
If you work on a data science team where consistency matters,

01:06:31.080 --> 01:06:32.540
check out Posit Workbench.

01:06:33.100 --> 01:06:35.540
Visit talkpython.fm/workbench for details.

01:06:36.640 --> 01:06:37.560
Want to level up your Python?

01:06:38.020 --> 01:06:41.660
We have one of the largest catalogs of Python video courses over at Talk Python.

01:06:42.140 --> 01:06:46.820
Our content ranges from true beginners to deeply advanced topics like memory and async.

01:06:47.260 --> 01:06:49.440
And best of all, there's not a subscription in sight.

01:06:49.840 --> 01:06:52.360
Check it out for yourself at training.talkpython.fm.

01:06:53.080 --> 01:06:57.240
Be sure to subscribe to the show, open your favorite podcast app, and search for Python.

01:06:57.700 --> 01:06:58.560
We should be right at the top.

01:06:58.680 --> 01:07:07.920
You can also find the iTunes feed at /itunes, the Google Play feed at /play, and the direct RSS feed at /rss on talkpython.fm.

01:07:08.600 --> 01:07:10.840
We're live streaming most of our recordings these days.

01:07:11.180 --> 01:07:18.680
If you want to be part of the show and have your comments featured on the air, be sure to subscribe to our YouTube channel at talkpython.fm/youtube.

01:07:19.700 --> 01:07:20.820
This is your host, Michael Kennedy.

01:07:21.240 --> 01:07:22.080
Thanks so much for listening.

01:07:22.240 --> 01:07:23.240
I really appreciate it.

01:07:23.580 --> 01:07:25.180
Now get out there and write some Python code.