WEBVTT

00:00:00.001 --> 00:00:02.940
Can you write me a Python app for all the major platforms out there?

00:00:02.940 --> 00:00:07.060
Oh wait, I also want them to be native GUI applications.

00:00:07.060 --> 00:00:13.840
And I want them to work on mobile, so Android, iOS, tvOS, and watchOS, as well as the major desktops.

00:00:13.840 --> 00:00:19.580
Also, I need them to appear indistinguishable from the native apps in terms of the way you deploy them.

00:00:19.580 --> 00:00:24.400
So a .app on macOS and a .exe on Windows and so on.

00:00:24.400 --> 00:00:27.940
What technology would you use for this if you were going to build it in Python?

00:00:28.300 --> 00:00:35.220
This week, I'll introduce you to a wide set of small, focused, and powerful tools that make all of this and more possible.

00:00:35.220 --> 00:00:39.540
We're speaking with Russell Keith McGee, the founder of the Beware Project.

00:00:39.540 --> 00:00:45.200
This is Talk Python To Me, episode 76, recorded October 4th, 2016.

00:00:56.600 --> 00:01:17.920
Welcome to Talk Python To Me, a weekly podcast on Python, the language, the libraries, the ecosystem, and the personalities.

00:01:18.320 --> 00:01:20.060
This is your host, Michael Kennedy.

00:01:20.060 --> 00:01:22.060
Follow me on Twitter, where I'm @mkennedy.

00:01:22.060 --> 00:01:25.940
Keep up with the show and listen to past episodes at talkpython.fm.

00:01:25.940 --> 00:01:28.460
And follow the show on Twitter via at Talk Python.

00:01:29.580 --> 00:01:32.900
This episode is brought to you by Rollbar and Hired.

00:01:32.900 --> 00:01:34.920
Thank them both for supporting the show.

00:01:34.920 --> 00:01:42.240
Check them out at Rollbar and at Hired underscore HQ on Twitter and tell them thank you.

00:01:42.240 --> 00:01:43.680
Hi, everyone.

00:01:43.680 --> 00:01:46.700
I want to take a moment and give you a quick update about my online courses.

00:01:46.700 --> 00:01:51.780
I just opened Access for my Python for Entrepreneurs course for pre-order.

00:01:52.180 --> 00:01:54.680
If you're thinking about taking this course, you should act soon.

00:01:54.680 --> 00:01:58.660
Right now, while we're still finishing the content, you can buy it for just $59.

00:01:58.660 --> 00:02:00.760
That's $30 off the retail price.

00:02:00.760 --> 00:02:04.220
And you'll get early access to the content while it's being developed.

00:02:04.220 --> 00:02:08.860
Currently, there's about 3.5 hours of content, and there's more coming every day.

00:02:08.860 --> 00:02:11.900
Check it out at talkpython.fm/launch.

00:02:11.900 --> 00:02:15.280
The early reviews have been great, so I'm sure you'll love it too.

00:02:16.080 --> 00:02:18.460
Now, let's hear about the Beware Project with Russell.

00:02:18.460 --> 00:02:20.680
Russell, welcome to the show.

00:02:20.680 --> 00:02:21.560
Thanks for having me.

00:02:21.560 --> 00:02:22.460
It's my honor.

00:02:22.460 --> 00:02:25.840
We're going to talk about so many things in the Beware Project.

00:02:25.840 --> 00:02:29.720
Several of my guests have actually recommended the Beware Project as something that's really

00:02:29.720 --> 00:02:33.940
standing out in the Python space, and I kind of have to agree with them.

00:02:33.940 --> 00:02:36.980
You guys are doing some cool stuff, and so I'm looking forward to talking about it.

00:02:36.980 --> 00:02:38.360
Oh, fantastic.

00:02:38.360 --> 00:02:43.280
It's been a fantastic ride the last couple of years, and it's over the last sort of 12 months

00:02:43.280 --> 00:02:47.660
who sort of just started to get a lot more momentum and starting to – partially because

00:02:47.660 --> 00:02:50.680
we're actually getting to the point where we've got something we can really show that's

00:02:50.680 --> 00:02:52.080
interesting, not just sort of theoretical.

00:02:52.080 --> 00:02:55.160
So, yeah, really enthused to talk about it.

00:02:55.160 --> 00:02:55.880
Yeah, great.

00:02:55.880 --> 00:02:59.360
Now, before we get to it, let's start with you.

00:02:59.360 --> 00:03:00.160
What's your story?

00:03:00.160 --> 00:03:01.400
How did you get into Python and programming?

00:03:01.400 --> 00:03:05.440
The programming story for me started a long, long time ago.

00:03:05.980 --> 00:03:12.220
My father is a mechanical engineer who kind of saw these computer things at the point when

00:03:12.220 --> 00:03:17.480
home computing was just starting to become a thing, and he got one of the first Commodore

00:03:17.480 --> 00:03:20.420
64s that was available for sale in Australia.

00:03:20.420 --> 00:03:25.360
Not with any specific plan of what he was going to do with it, just could see that these computers

00:03:25.360 --> 00:03:29.040
were going to be a thing and kind of maybe we should play with them a little bit, which

00:03:29.040 --> 00:03:30.700
is something he's always done with technology.

00:03:30.700 --> 00:03:36.000
He bought a hideously expensive 3D printer when they were still hideously expensive, just

00:03:36.000 --> 00:03:36.920
so he could play with it.

00:03:36.920 --> 00:03:42.820
So, yeah, I got introduced to the Commodore 64 when I was 8 or 10, somewhere around that

00:03:42.820 --> 00:03:47.000
sort of territory, and I've kind of been just tinkering with them ever since.

00:03:47.000 --> 00:03:52.320
It's kind of gone from, hey, I can write this really, really dumb, my sister is ugly, my sister

00:03:52.320 --> 00:03:59.320
is ugly, my sister is ugly, go to 10 loop, through to doing a PhD in computer science over

00:03:59.320 --> 00:03:59.580
time.

00:03:59.580 --> 00:04:04.040
So, my undergrad degree actually wasn't in computer science, it's in physics, but I picked

00:04:04.040 --> 00:04:07.860
up all the computing degrees and computing courses I could along the way, and they kind

00:04:07.860 --> 00:04:12.080
of encouraged me to come over to the computer science department for my postgrad studies.

00:04:12.080 --> 00:04:16.620
So, I did my honours in computer science and a PhD in computer science, and then progressed

00:04:16.620 --> 00:04:18.340
from there into working in industry.

00:04:18.340 --> 00:04:24.020
My PhD supervisor and I had a very, very frank conversation at one point about halfway through

00:04:24.020 --> 00:04:27.480
my PhD, even when we decided mutually that my future did not lie in academia.

00:04:28.200 --> 00:04:32.660
And so, yes, from that point, she was happy to try and get me out of academia and into industry,

00:04:32.660 --> 00:04:36.820
and I started working professionally as a computer scientist since then.

00:04:36.820 --> 00:04:41.960
I was in a PhD program, and I know you feel like you're on the path to just keep going

00:04:41.960 --> 00:04:42.680
into academics.

00:04:42.680 --> 00:04:49.660
But I feel personally very lucky that I had a broader exposure around that time to see what

00:04:49.660 --> 00:04:54.780
was possible in industry, because for every opportunity in academics, I feel like there's

00:04:54.780 --> 00:04:59.680
100 opportunities that are just so amazing out there, you know, outside of the confines of

00:04:59.680 --> 00:05:01.380
a university and a grant.

00:05:01.860 --> 00:05:02.840
I think it's great.

00:05:02.840 --> 00:05:03.280
Yeah.

00:05:03.280 --> 00:05:07.860
I mean, for me, it was, I don't know, a slightly more practical thing is that I actually like

00:05:07.860 --> 00:05:10.900
doing things, not just kind of the theoretical aspects of it.

00:05:10.900 --> 00:05:16.400
And I was getting, during my PhD, I was getting very, very tied up in playing around with interesting

00:05:16.400 --> 00:05:19.800
pieces of technology with a view to actually doing something, but wasn't actually furthering

00:05:19.800 --> 00:05:20.500
my research at all.

00:05:20.500 --> 00:05:24.820
So, and it's kind of a precursor to a lot of the stuff that I'm now doing in Bware in some

00:05:24.820 --> 00:05:25.120
regards.

00:05:25.480 --> 00:05:25.760
Excellent.

00:05:25.760 --> 00:05:26.640
Okay.

00:05:26.640 --> 00:05:28.860
So where along the path did you come across Python?

00:05:28.860 --> 00:05:31.620
I first used Python back in the 1.5 days.

00:05:31.620 --> 00:05:38.040
So a long time ago, I was talking like early, late 90s, at which point it was mostly a system

00:05:38.040 --> 00:05:43.420
config language, mostly because Red Hat was using it in their setup tools and what have you.

00:05:43.420 --> 00:05:47.100
At that point, it was kind of, well, this is an odd language with odd syntax.

00:05:47.100 --> 00:05:50.100
I don't want to use odd syntax, so let's not use it.

00:05:50.100 --> 00:05:52.400
What's up with this white space thing, huh?

00:05:52.640 --> 00:05:53.820
Yeah, well, and that's the thing.

00:05:53.820 --> 00:05:56.560
It was, it's the thing that everybody gets caught on.

00:05:56.560 --> 00:06:03.760
But as I sort of grew as a software developer, that interesting property became more and more

00:06:03.760 --> 00:06:05.740
the thing that I actually value in Python.

00:06:05.740 --> 00:06:11.540
So it's one of these things where once you've read enough incredibly badly formatted Java

00:06:11.540 --> 00:06:15.800
code, you realize how valuable it is having a language that literally cannot run unless

00:06:15.800 --> 00:06:17.400
you get the white space indentation, right?

00:06:17.400 --> 00:06:18.000
Yeah.

00:06:18.320 --> 00:06:22.640
And so, yeah, it's sort of, over time, it grew from being just the systems language I

00:06:22.640 --> 00:06:25.500
kind of have to use to something that I vaguely tinkered around with.

00:06:25.500 --> 00:06:32.360
Over that whole period of the sort of mid-90s through to about 2005, when I got involved with

00:06:32.360 --> 00:06:38.040
Django, I've had this series of little background projects that I've tinkered around with.

00:06:38.040 --> 00:06:41.660
And whenever I wanted to learn a new language or a new framework or a new whatever, it's sort

00:06:41.660 --> 00:06:44.440
of the first project is, let's render that in this new language.

00:06:44.700 --> 00:06:48.120
And at some point, I got to the point where, yeah, well, hang on, I can do this in Python,

00:06:48.120 --> 00:06:48.460
can't I?

00:06:48.460 --> 00:06:49.460
Let's build this in Python.

00:06:49.460 --> 00:06:50.980
And yeah, this is actually working really.

00:06:50.980 --> 00:06:52.880
I like the way this is coming out.

00:06:52.880 --> 00:06:57.640
I then got kind of distracted by, hang on, maybe this web thing is actually a thing too.

00:06:57.640 --> 00:06:59.640
Oh, I can use this Python for the web.

00:06:59.640 --> 00:07:01.960
Oh, look, here's this Django thing, which is brand new.

00:07:01.960 --> 00:07:06.560
And 10 years later, I'm still working on the Django project.

00:07:06.560 --> 00:07:10.900
So you actually became and have been for a while a core developer on the Django project.

00:07:11.180 --> 00:07:11.660
That's correct.

00:07:11.660 --> 00:07:11.860
Yeah.

00:07:11.860 --> 00:07:18.580
So I was introduced, like I discovered Django because I was poking around.

00:07:18.580 --> 00:07:22.920
I had this vague idea that the web was a thing that maybe I should know more about, and maybe

00:07:22.920 --> 00:07:25.420
I could use it to solve some of these technical problems that I had.

00:07:25.420 --> 00:07:32.620
And I found Django just before they did like the 0.91 release or around that sort of timeframe.

00:07:32.620 --> 00:07:36.260
So very, very early days, November of 2005, effectively.

00:07:36.260 --> 00:07:40.100
And it was sort of two things really happened.

00:07:40.100 --> 00:07:46.040
One, because it was a really early stage project, the sort of the barrier to getting involved was a lot lower than it is today

00:07:46.040 --> 00:07:49.840
because there's not as much sort of momentum and inertia around what's going on.

00:07:50.240 --> 00:07:54.060
But also because it was written in Python, I come from a physics background.

00:07:54.060 --> 00:07:56.400
I have done theoretical computer science.

00:07:56.400 --> 00:07:59.440
But like all theory, it's utterly useless for actually doing things.

00:07:59.440 --> 00:08:02.960
I never actually formally studied networking or anything like that.

00:08:03.020 --> 00:08:10.320
So when I tried to work out how to build a web page with PHP, the PHP website didn't actually help me at all.

00:08:10.320 --> 00:08:12.820
I didn't understand what it was trying to do.

00:08:12.820 --> 00:08:22.300
But the Django tutorial got me from I don't know how the web really works to, oh, yeah, okay, I can build a website.

00:08:22.300 --> 00:08:24.820
And this makes sense now relatively quickly.

00:08:25.620 --> 00:08:33.660
And when I hit the limits of what Django could do, because it was written in Python, I could dive into it and I could modify it relatively easily.

00:08:33.660 --> 00:08:35.720
I understood what was going on pretty quickly.

00:08:35.720 --> 00:08:47.540
So within a month or two of picking up Django for the first time, I was submitting patches that would – if you've got a many-to-many relationship between two tables,

00:08:47.540 --> 00:08:51.740
back in the day, you could only go from the model that defined it to the model that it was pointing to.

00:08:51.740 --> 00:08:53.800
I needed to be able to go the other way.

00:08:53.800 --> 00:08:56.660
So I added that modification into the query language.

00:08:56.660 --> 00:09:01.960
And when you start making changes like that, the core team, Adrian and Jacob, offered me the commit bit.

00:09:01.960 --> 00:09:04.440
And sort of the rest is history from there.

00:09:04.440 --> 00:09:05.760
Yeah, that's really great.

00:09:05.760 --> 00:09:15.880
Do you feel like getting started and contributing to Django was easier 10 years ago because it was a newer, less mature, less sort of solidified project?

00:09:15.880 --> 00:09:16.800
Absolutely.

00:09:16.800 --> 00:09:22.360
I mean, when things are – like 10 years ago, Django didn't have a backwards compatibility guarantee.

00:09:22.360 --> 00:09:30.760
There was certainly a preference to not just move things around because, but changing backwards compatible things was at least an option.

00:09:30.760 --> 00:09:36.220
There wasn't as much – the community was smaller, so it was easier to get consensus with a bunch of people.

00:09:36.220 --> 00:09:44.720
There wasn't the consideration of a million – if we deploy this change, Instagram is going to break because we all of a sudden have changed this API.

00:09:45.520 --> 00:09:48.800
So, yeah, 10 years ago, it was absolutely easier to get involved.

00:09:48.800 --> 00:09:50.340
There's no doubt about that at all.

00:09:50.340 --> 00:09:52.080
Yeah, that's really interesting.

00:09:52.080 --> 00:09:53.960
I think that's a big tradeoff, right?

00:09:53.960 --> 00:09:56.880
I mean, the value of Django is probably higher now.

00:09:56.880 --> 00:10:00.900
But it's just – it's all sorts of projects that have been around for so long.

00:10:01.020 --> 00:10:05.900
So, let's talk about a project that's not been around for quite that long, and that's your project, Beware.

00:10:05.900 --> 00:10:07.000
Yes.

00:10:07.000 --> 00:10:15.020
So, Beware is interesting because it's kind of many things that work together sort of synergetically.

00:10:15.020 --> 00:10:19.400
And you said that your project follows the Unix philosophy for tools.

00:10:19.400 --> 00:10:20.020
Yes.

00:10:20.220 --> 00:10:24.400
Give us a quick overview of what Beware is and then maybe touch on that.

00:10:24.400 --> 00:10:24.900
Sure.

00:10:24.900 --> 00:10:25.160
Okay.

00:10:25.160 --> 00:10:29.900
So, the place where I started with that sort of Unix philosophy is a talk that I gave at PyCon Australia.

00:10:29.900 --> 00:10:32.560
I think it was four years ago, but I have to check the exact date.

00:10:32.560 --> 00:10:38.980
But essentially, the theory that I was positing at that point was that the Unix philosophy as a process is quite strong.

00:10:38.980 --> 00:10:42.740
Now, the Unix philosophy is the idea that you don't build one tool that does everything.

00:10:42.740 --> 00:10:47.100
You build a large number of small tools, each of which has a well-defined interface.

00:10:47.760 --> 00:10:55.180
So, that – and then the power comes from the small tools being able to plug together really easily or having a natural way of plugging together.

00:10:55.180 --> 00:11:03.560
Now, the unfortunate corollary of the Unix philosophy has become that in order for something to be Unix, it must be text-based.

00:11:03.560 --> 00:11:09.280
So, yes, you can run LS, and LS you can pipe into sort, and sort you can pipe into unique.

00:11:09.280 --> 00:11:12.280
And these are really, really powerful things to do.

00:11:12.280 --> 00:11:15.480
But at the end of the day, it's all text.

00:11:16.100 --> 00:11:20.720
And there are many, many areas where text is not the natural interface.

00:11:20.720 --> 00:11:22.840
And the example that I gave at the time was testing.

00:11:22.840 --> 00:11:33.060
If you run a unit test suite or a pytest suite or whatever, what you get coming up on the screen as the user interface is dot, dot, dot, dot, dot, dot, F, dot, dot, dot, dot, dot, dot, dot, dot, dot.

00:11:33.060 --> 00:11:40.140
Which is completely correct and completely accurate, but not helpful from a user interface perspective.

00:11:40.140 --> 00:11:42.700
What you want to know is which dot is running?

00:11:42.700 --> 00:11:44.500
Why did it turn up an F?

00:11:44.500 --> 00:11:49.480
When something writes to standard output at the wrong time, which test did that?

00:11:49.480 --> 00:11:52.100
How long has my test suite got left to run?

00:11:52.100 --> 00:11:57.980
Now, these are all questions that you're entirely in a position to answer or at least provide good guesses for in the case of something like runtime.

00:11:57.980 --> 00:12:09.040
But when your only user interface is writing something to console, you have – you are deliberate or you have – you have just hobbled yourself in terms of what it is you can actually display.

00:12:09.980 --> 00:12:15.940
So what I was originally positing with the Beware project was that what we can do is build tools that are still Unix related.

00:12:15.940 --> 00:12:17.000
Now, they do one thing.

00:12:17.000 --> 00:12:18.120
They do one thing well.

00:12:18.120 --> 00:12:24.880
But one of those one things can be let's display a GUI that enables me to see all these useful things.

00:12:24.880 --> 00:12:27.320
So here is – where we started was with Cricut.

00:12:27.320 --> 00:12:30.520
Cricut is a user interface for running test suites.

00:12:30.520 --> 00:12:32.940
It shows a tree, which is your test suite.

00:12:32.940 --> 00:12:39.180
You press go and it works through your test suite, highlighting the lines of the tree that are currently running as individual tests.

00:12:39.180 --> 00:12:47.780
As the test suite is running, you can click on other pieces of the tree and see what tests have run and how long they took to run and what output they generated and whether they passed and failed.

00:12:47.780 --> 00:12:53.320
And because you know, well, this is how long the test suite is, this is how many tests there are.

00:12:53.320 --> 00:12:56.280
Each test takes an average of X milliseconds or seconds.

00:12:56.280 --> 00:13:00.060
Therefore, we can estimate this entire suite is going to take 20 seconds to run.

00:13:00.060 --> 00:13:01.100
That's really nice.

00:13:01.100 --> 00:13:04.980
I think the visual component of it is just – I am with you.

00:13:04.980 --> 00:13:07.060
I don't mind working the command line.

00:13:07.060 --> 00:13:12.260
But we have such powerful and beautiful OSs these days.

00:13:12.260 --> 00:13:18.180
Like, I feel like we're using one-tenth of what we can in terms of interactability, right?

00:13:18.180 --> 00:13:18.620
Yeah.

00:13:18.620 --> 00:13:25.800
I've bought a $4,000 laptop with a retina display that's able to render things at a resolution that my eye can't discern.

00:13:25.800 --> 00:13:27.600
And I'm using it to show 80 by 25.

00:13:27.600 --> 00:13:29.580
It just doesn't make any sense.

00:13:29.580 --> 00:13:31.080
Yeah, it totally doesn't make any sense.

00:13:31.080 --> 00:13:40.540
But I think that taking this idea of the Unix philosophy applied to like a modern GUI-based set of tooling, that's really powerful.

00:13:40.540 --> 00:13:43.780
And that's one of the things that I find really appealing about your project.

00:13:44.040 --> 00:13:52.660
Yeah, and that's sort of – like I said, we started – I started initially with Cricket as a proof of concept because, you know, unit testing is a thing that I do a lot of and I enjoy.

00:13:52.660 --> 00:13:57.540
And the unit test suite is difficult to get into when all you've got is dot, dot, dot, dot, dot.

00:13:57.600 --> 00:14:02.900
So here is a user interface that lets you use, interrogate, manipulate a test suite as it runs.

00:14:02.900 --> 00:14:06.940
The other – like I also have – there's another tool called Duvet, which is a coverage tool.

00:14:06.940 --> 00:14:18.260
It takes the code results partially from a test suite but also from anywhere else that it's running and shows you graphically which lines of code have been operated rather than giving you, you know, line 17 to 25 were not covered.

00:14:18.520 --> 00:14:19.800
Well, what's line 17 to 25?

00:14:19.800 --> 00:14:21.180
Oh, it's that for loop.

00:14:21.180 --> 00:14:22.140
Yeah, exactly.

00:14:22.140 --> 00:14:28.500
Yeah, 94% coverage is not the same as scrolling through your code and seeing, oh, there's a red spot.

00:14:28.500 --> 00:14:29.440
Hmm, why is that red?

00:14:29.440 --> 00:14:30.320
Yeah, exactly.

00:14:30.320 --> 00:14:36.080
But in order to get that capability, you don't have to swallow the whole of an IDE.

00:14:36.080 --> 00:14:42.120
You just have to have a mechanism for displaying that isn't 80 by 25 console.

00:14:43.480 --> 00:14:54.180
And so one of the things when I was poking around your projects that seemed to be a theme was they seem to be supported on all the major OSs, at least the desktop ones for the most part.

00:14:54.180 --> 00:14:55.860
Yeah, so that's the intention anyway.

00:14:55.860 --> 00:15:00.500
So originally I use a Mac as my daily developer box.

00:15:00.500 --> 00:15:04.040
I do also do work on Linux mostly as a server capacity.

00:15:04.040 --> 00:15:08.080
I know I have many, many friends who are using Linux as a desktop.

00:15:08.080 --> 00:15:11.700
And, you know, if I write a tool that is useful, I don't want to lock them out.

00:15:11.880 --> 00:15:16.120
You know, I don't – my passion for Mac is not because I particularly like Macs.

00:15:16.120 --> 00:15:17.500
It's because I like the hardware.

00:15:17.500 --> 00:15:20.500
I think it is a usable operating system.

00:15:20.500 --> 00:15:23.280
It is a usable platform where I don't have to mess around.

00:15:23.280 --> 00:15:26.260
If someone wants to use a different platform, they should be able to.

00:15:26.260 --> 00:15:29.900
And my choice of tools shouldn't be affecting their productivity.

00:15:29.900 --> 00:15:34.200
I've been from the beginning very actively trying to do this as a cross-platform thing.

00:15:34.200 --> 00:15:40.020
Plus also from my perspective, you know, one of these days I'm anticipating that I probably will end up leaving Mac and going somewhere else.

00:15:40.180 --> 00:15:41.920
And I want all my tools to keep working, please.

00:15:41.920 --> 00:15:42.780
Yeah.

00:15:42.780 --> 00:15:47.080
That would definitely lock you in if you spent five years building an amazing set of tools.

00:15:47.080 --> 00:15:50.580
But you had to stay on your – whatever OS you happen to have been on at the time, right?

00:15:50.580 --> 00:15:51.200
Yeah.

00:15:51.200 --> 00:15:52.260
You couldn't possibly leave.

00:15:52.260 --> 00:15:56.840
And the thing is, you know, at the end of the day, so much of what these platforms are doing is not platform-specific.

00:15:57.060 --> 00:16:00.260
You know, it's show me a menu, show me a button, show me a pull-down.

00:16:00.260 --> 00:16:02.040
You know, these are generic concepts.

00:16:02.040 --> 00:16:10.720
Originally, it started – like, Cricket is still and was originally built using TK Inter, mostly because it is available cross-platform.

00:16:10.720 --> 00:16:15.040
And you can install it saying pip install, you know, pip install whatever, and it just works.

00:16:15.660 --> 00:16:20.900
And a lot of where Beware has been sort of hunting for the last sort of three and a half years has been TK Inter.

00:16:20.900 --> 00:16:24.660
The major limitation I hit is that TK doesn't have a web widget.

00:16:24.660 --> 00:16:27.100
You can't display a web page in TK.

00:16:27.900 --> 00:16:35.100
And over time, TK's theming on OS X has gotten worse and worse, but that's kind of secondary to just you can't display a web page.

00:16:35.100 --> 00:16:39.420
And trying to write a new widget in TK is just pathologically bad.

00:16:39.420 --> 00:16:43.880
So it turned out for me the easy solution was to write a new widget toolkit, ironically.

00:16:43.880 --> 00:16:54.360
Yeah, I think there's a lot of cross-platform tool or tool chains, but not too many of them seem to really focus on the truly native component.

00:16:54.360 --> 00:16:56.640
And that makes a big difference to me.

00:16:56.640 --> 00:17:00.360
I remember running some Java apps and just looking at, like, the file open dialog.

00:17:00.360 --> 00:17:02.600
Oh, this just so does not belong here.

00:17:02.600 --> 00:17:03.540
What is this thing?

00:17:03.540 --> 00:17:07.000
It kind of resembles a file open dialog, but I know it's not.

00:17:07.000 --> 00:17:08.260
Like, the hotkeys don't work.

00:17:08.260 --> 00:17:10.900
All the various things that you would expect, right?

00:17:10.900 --> 00:17:12.360
Yeah, exactly.

00:17:12.360 --> 00:17:17.120
And so there are cross-platform widget toolkits that work to various degrees of work.

00:17:17.120 --> 00:17:22.300
There are things like Swing in Java, which sometimes looks like native and sometimes doesn't quite.

00:17:22.300 --> 00:17:25.960
And then you've got things like GTK, which, yeah, sure, works on Mac,

00:17:26.020 --> 00:17:27.120
as long as you're running an X server.

00:17:27.120 --> 00:17:31.780
And then you get the loving user interface of an X server running on your Mac.

00:17:31.780 --> 00:17:38.420
And then there are things like QT and WX, which are relatively mature and been used for a while and have Python bindings.

00:17:38.420 --> 00:17:41.180
But the Python bindings are kind of a secondary thought.

00:17:41.180 --> 00:17:45.520
In the case of QT, there's a whole licensing thing that's going on that's just a complete mess.

00:17:46.060 --> 00:17:52.400
And they're not as simple as pip install widget set because there's compiled components and libraries.

00:17:52.400 --> 00:17:54.640
And you've got to install this 150 meg library.

00:17:54.640 --> 00:17:56.320
And you've got to know which one you've got to have.

00:17:56.420 --> 00:18:03.440
And it just becomes such a nightmare that the basic thing of, I just want this damn thing to run, gets in the way of getting stuff done.

00:18:03.440 --> 00:18:04.040
Absolutely.

00:18:04.040 --> 00:18:06.640
The UIs in your apps look really nice.

00:18:06.640 --> 00:18:07.520
And they're cross-platform.

00:18:07.520 --> 00:18:08.300
What did you do?

00:18:08.880 --> 00:18:13.840
I accidentally stumbled upon a couple of things that I didn't realize were actually possible.

00:18:13.840 --> 00:18:25.660
So I was looking a long time ago at Pygame and realized that Pygame actually manages to do this native thing without actually having a compiled component.

00:18:25.880 --> 00:18:35.040
And the way it does it is because Objective-C, whether you know it or not, is actually a raw C API with some pretty syntax around the outside of it.

00:18:35.040 --> 00:18:42.400
And Python gives you this thing called C types, which lets you call any C API without having to compile something.

00:18:42.660 --> 00:19:00.200
So with a little bit of Python class magic and Meta class and descriptors and what have you, you can write a class in Python that is a pure Python class that looks and feels and behaves in the Objective-C environment like an Objective-C class.

00:19:00.200 --> 00:19:03.500
And then when you go, you look at the next option, you look at GTK.

00:19:03.500 --> 00:19:06.760
GTK provides native Python bindings that are actually native Python bindings.

00:19:06.760 --> 00:19:18.620
So there you've got two major platforms where you can write native applications using the native APIs with pure Python without having a binary component involved.

00:19:18.620 --> 00:19:27.580
And then so from there, it was kind of a, well, okay, that means I've got Coco and GTK, which are the two that I'm sort of covering my bets on.

00:19:27.580 --> 00:19:28.380
Can I do this on Windows?

00:19:28.380 --> 00:19:31.100
Well, yeah, because there's a Win32 and that's a C API.

00:19:31.100 --> 00:19:31.980
Okay, so that works.

00:19:31.980 --> 00:19:36.380
What about, well, but why is anyone going to use this new platform?

00:19:36.380 --> 00:19:40.220
You know, it's nice that it doesn't have this extra compiled component, but that's not sort of compelling.

00:19:40.220 --> 00:19:42.080
What's going to be compelling?

00:19:42.080 --> 00:19:44.680
And this is, again, sort of three years ago.

00:19:44.680 --> 00:19:48.360
It was like, well, what if I could use these widget sets on mobile as well?

00:19:48.360 --> 00:20:02.280
A lot of what I've been doing for the last couple of years is trying to get Python to run on mobile, both on Android and on iOS, so that you can actually then say, well, okay, yeah, I can run this, this similar API or identical API on macOS.

00:20:02.280 --> 00:20:04.080
I can run it on GTK on Linux.

00:20:04.080 --> 00:20:07.740
I can run it on iOS and I can run it on an Android.

00:20:07.740 --> 00:20:11.960
And that's sort of, you know, that's what's been keeping me busy for the last couple of years at this point.

00:20:11.960 --> 00:20:12.620
Yeah.

00:20:12.620 --> 00:20:15.920
And that's quite the achievement, especially the mobile part.

00:20:16.560 --> 00:20:26.660
But I think even, you kind of went through it quick, but I feel like native on the three major desktops is actually a bigger deal than, you know, maybe it sounds at first.

00:20:26.740 --> 00:20:37.580
I think if you're going to build an app and if it can look and behave literally like a macOS app or a Windows app or a Linux app, that is a really big deal.

00:20:37.580 --> 00:20:40.520
And if you can use Python for that, that's even better.

00:20:40.520 --> 00:20:48.560
Now, one of the projects, and I'm sorry, I don't remember the name of the project, but one of the projects you're working on is bundling that up so you can distribute.

00:20:48.680 --> 00:20:54.500
You can actually ship sort of a bundled up version of Python with everything it needs to run your app, right?

00:20:54.500 --> 00:20:55.180
Correct.

00:20:55.180 --> 00:20:56.040
Yeah, that's briefcase.

00:20:56.040 --> 00:21:05.620
So, yeah, the idea of briefcase, yeah, is to say, well, okay, a macOS application is basically a directory with some metadata in very specific places.

00:21:05.620 --> 00:21:15.840
And historically, giving someone a tool that is written in Python is kind of a, well, you need to install Python, but you need to install it from here and you need to give it your system password.

00:21:16.160 --> 00:21:22.000
And then you've got to hope that someone hasn't buggered up the site packages directory and, and, and, and, and, and.

00:21:22.000 --> 00:21:23.080
Here's the dependencies.

00:21:23.080 --> 00:21:24.420
Install those too.

00:21:24.420 --> 00:21:29.480
Yeah, and then you sacrifice the chicken and wave the blood this way and hopefully it works.

00:21:29.480 --> 00:21:32.840
Unless you're on Windows, then you better find out where VCVAR is about.

00:21:32.840 --> 00:21:34.340
Oh, exactly.

00:21:34.340 --> 00:21:37.480
And, you know, because every Windows user knows how to set their path variable.

00:21:37.480 --> 00:21:42.400
But at the end of the day, we're now at the point where a 100 megabyte application is absolutely nothing.

00:21:42.560 --> 00:21:46.580
You know, okay, 10 years ago, that was a major drama, but now that's just getting up in the morning.

00:21:46.580 --> 00:21:51.720
So why not ship the version of Python you actually need with the dependencies you actually need?

00:21:51.720 --> 00:21:53.780
And when you run it, it runs it locally.

00:21:53.780 --> 00:21:57.000
And so, okay, with macOS, well, yeah, I can do that.

00:21:57.000 --> 00:21:57.520
I can template.

00:21:57.520 --> 00:22:06.320
I can use cookie cutter, which is a fantastic project from Audrey Roy Greenfield and Danny Greenfield Roy, to like template out what this application needs to look like.

00:22:06.320 --> 00:22:15.640
And then your Python script goes here and your dependencies go there and we can pip install into that directory, zip it up, ship it to someone, and it just runs because it's pure Python.

00:22:15.640 --> 00:22:20.740
You're giving them the Python interpreter it has to use with the dependencies that they need and it's running natively.

00:22:20.740 --> 00:22:22.760
And then from there, you can do similar sorts of things.

00:22:23.120 --> 00:22:28.040
I haven't done as much work with Linux because installing apps on Linux doesn't quite work as well.

00:22:28.040 --> 00:22:38.860
I've done some exploratory work with Windows and it should absolutely be possible on Windows, possibly to the point of like actually generating an MSI installer that looks like it's a completely native installer.

00:22:38.860 --> 00:22:42.660
It just happens to spit out something that starts a Python interpreter, but you never know that.

00:22:42.660 --> 00:22:55.120
I think the irony is we in the Python community will be successful on these desktop systems and mobile systems if people don't know that they're running a Python application.

00:22:55.120 --> 00:22:56.580
Oh, absolutely.

00:22:56.580 --> 00:22:57.660
I completely agree.

00:22:57.660 --> 00:23:04.680
So as soon as you know or you can tell what tool someone used to build something, I think you've lost the game.

00:23:04.840 --> 00:23:14.940
Like you need to be able to run a piece of software and just be able to give it to anybody and it will just start, it will just run, it will behave the way they expect it to and they don't get any surprises.

00:23:14.940 --> 00:23:29.420
Anything less than that and yeah, okay, yeah, it may be very useful in various areas or demographics or whatever, but you're not going to get the mass market adoption if you've got to hold your breath and lift your leg in a funny way on a Tuesday when the moon's full in order for it to work.

00:23:29.420 --> 00:23:36.340
Yep, it might work for developers, it might work inside your company, but it's not going to be something you can broadly distribute if that's the story, right?

00:23:36.340 --> 00:23:37.240
Yeah, exactly.

00:23:37.240 --> 00:23:44.400
But even beyond that, I mean, looking at the developers themselves, this is part of the great lamentation about why I got involved with Beware in the first place.

00:23:44.400 --> 00:23:49.740
You shouldn't be in a situation where you have to be this tall to get onto this development project.

00:23:49.740 --> 00:23:58.160
If you can't just pick up a tool and use it and pick up a tool and develop it, then you've just set a barrier to entry to anybody helping to make your project better.

00:23:58.380 --> 00:24:04.580
So the dream of open source is that anyone can get involved, anyone can make their project better, anyone can contribute a patch.

00:24:04.580 --> 00:24:15.980
But if I can't even get a development environment going without 10 years of a computer science experience, then what the hell chance has the random person who has no computer science background got of fixing the tool?

00:24:15.980 --> 00:24:16.720
They don't.

00:24:16.720 --> 00:24:21.620
It's the being able to contribute open source dream is at best a dream.

00:24:21.940 --> 00:24:22.540
Yeah, yeah.

00:24:22.540 --> 00:24:29.060
And then you end up with people running to things like JavaScript because, hey, we can all start a browser or something like that, right?

00:24:29.060 --> 00:24:30.300
Yeah, exactly.

00:24:42.480 --> 00:24:47.240
This portion of TalkPyPundemy has been brought to you by Rollbar.

00:24:47.240 --> 00:24:58.960
One of the frustrating things about being a developer is dealing with errors, relying on users to report errors, digging through log files, trying to debug issues, or a million alerts just flooding your inbox and ruining your day.

00:24:59.080 --> 00:25:06.180
With Rollbar's full stack error monitoring, you'll get the context, insights, and control that you need to find and fix bugs faster.

00:25:06.680 --> 00:25:07.880
It's easy to install.

00:25:07.880 --> 00:25:12.140
You can start tracking production errors and deployments in eight minutes or even less.

00:25:12.140 --> 00:25:21.500
Rollbar works with all the major languages and frameworks, including the Python ones such as Django, Flask, Pyramid, as well as Ruby, JavaScript, Node, iOS, and Android.

00:25:21.500 --> 00:25:30.700
You can integrate Rollbar into your existing workflow, send error alerts to Slack or HipChat, or even automatically create issues in Jira, Pivotal Tracker, and a whole bunch more.

00:25:30.700 --> 00:25:34.080
Rollbar has put together a special offer for Talk Python To Me listeners.

00:25:34.080 --> 00:25:39.760
Visit Rollbar.com slash Talk Python To Me, sign up, and get the bootstrap plan free for 90 days.

00:25:39.760 --> 00:25:42.800
That's 300,000 errors tracked all for free.

00:25:42.800 --> 00:25:46.520
But hey, just between you and me, I really hope you don't encounter that many errors.

00:25:46.520 --> 00:25:52.540
Loved by developers at awesome companies like Heroku, Twilio, Kayak, Instacart, Zendesk, Twitch, and more.

00:25:52.540 --> 00:25:54.140
Give Rollbar a try today.

00:25:54.140 --> 00:25:56.740
Go to Rollbar.com slash Talk Python To Me.

00:25:56.740 --> 00:26:10.260
Yeah, so you said, well, your website, which I'm presuming you had a say in what it said,

00:26:10.260 --> 00:26:18.680
says that the end goal of the Beware project is to be able to do for mobile and desktop facing software the same thing that Django has done for web software.

00:26:18.680 --> 00:26:33.980
I think that touches on the point you just made that like Django, the Django community, Django girls, all these different groups seem to have found a way to make it really easy to onboard into dynamic server-based web development,

00:26:33.980 --> 00:26:36.060
which is not really a simple thing to do, to be honest.

00:26:36.060 --> 00:26:38.100
There's a lot of moving parts and things you've got to know.

00:26:38.580 --> 00:26:46.360
Yeah, and I suppose that's the Django girls analogy is really the one that's really is my yardstick for when this is successful,

00:26:46.360 --> 00:26:53.880
because what the Ola Sotaska, Ola Sendecker have done and the rest of the team with Django girls as it's grown has been absolutely amazing,

00:26:53.880 --> 00:27:03.760
because it proves that you don't need to have a computer science degree to be able to do things on the web and to do really meaningful things on the web too.

00:27:04.340 --> 00:27:11.920
You can take people who are intelligent and engaged with no computer science background and in a day's training course,

00:27:11.920 --> 00:27:18.320
get them to the point where they have a database-backed website that is under their control, publicly visible somewhere on the internet.

00:27:18.320 --> 00:27:26.060
Now, there's that, yeah, at some level, that's an absolutely huge achievement, you know, because this is incredibly empowering for those people.

00:27:26.280 --> 00:27:31.540
But it also, having APIs, part of the reason it's possible is because we've got an API, we've got Django,

00:27:31.540 --> 00:27:38.540
we've got a language like Python that is readable and gives reasonably good error messages and enforces reasonably good practices.

00:27:38.540 --> 00:27:43.240
But we haven't done it by taking something and dumbing it down.

00:27:43.240 --> 00:27:48.340
We've taken the live tool and just pointed them in the direction of things they have to do.

00:27:48.340 --> 00:27:49.320
That's powerful.

00:27:49.320 --> 00:27:50.320
That's super powerful.

00:27:50.320 --> 00:27:58.540
I think that's also one of the powers of Python is there are simple languages out there, Visual Basic, for example,

00:27:58.540 --> 00:28:01.580
that is super easy to get started with, but they don't go very far.

00:28:01.580 --> 00:28:07.200
And then there's really powerful languages like C++, Java, C#, whatever.

00:28:07.200 --> 00:28:11.080
But there's, you know, that first step is like a really big jump.

00:28:11.080 --> 00:28:16.900
And Python, I think, is just really well designed in that it actually spans both of those.

00:28:17.060 --> 00:28:20.440
And so we're kind of lucky to be in this space as well.

00:28:20.440 --> 00:28:21.660
Yeah, no, I agree.

00:28:21.660 --> 00:28:29.320
I mean, it's Python is a language that is easy enough to teach to beginners and simple enough and conceivable enough that you can –

00:28:29.320 --> 00:28:30.600
hello world is one line of code.

00:28:30.600 --> 00:28:34.320
You don't have to teach a whole lot of computer science concepts to get going.

00:28:34.320 --> 00:28:37.060
But that doesn't mean the computer science concepts aren't there.

00:28:37.060 --> 00:28:44.700
You can do asynchronous decorators and, you know, all this kind of really, really hardcore computer science stuff without –

00:28:44.700 --> 00:28:47.640
but you can opt into it as you need to over time.

00:28:47.640 --> 00:28:49.860
And you can get basic stuff done.

00:28:49.860 --> 00:28:56.260
And Django, you know, something like Django, you can provide an API that lets you get stuff done with most of the important –

00:28:56.260 --> 00:29:02.120
sort of the difficult questions answered for you, but with an option in the future that if it ever starts to become a problem,

00:29:02.120 --> 00:29:09.460
you can dig in and replace that decision with something that's going to scale better or perform better or whatever the problem happens to be.

00:29:09.460 --> 00:29:10.220
Yeah, absolutely.

00:29:10.220 --> 00:29:14.860
And we have a lot of good examples like, hey, you can build Dropbox or Instagram or whatever.

00:29:14.860 --> 00:29:15.100
Yeah, exactly.

00:29:15.100 --> 00:29:18.380
I mean like, okay, well, whatever you're trying to do is probably not that complicated.

00:29:18.380 --> 00:29:19.520
So perfect.

00:29:19.520 --> 00:29:20.240
This will work for you.

00:29:20.240 --> 00:29:27.820
You can scale from Django Girls to Dropbox without – or to Instagram without – you know, okay, yes, you've got to level up along the way.

00:29:27.920 --> 00:29:35.340
And there's – you know, the Django that's being used in Instagram is not the same Django that's being used in Django Girls in some regards because so many parts have been swapped out.

00:29:35.340 --> 00:29:45.280
There was a quote from Cal Henderson at the very, very first DjangoCon where he sort of points out that the frameworks – the companies that are at the top of that performance tree,

00:29:45.280 --> 00:29:53.880
the top 1% of websites have very, very unique requirements because they've got very specific traffic patterns and very specific queries that need to be issued.

00:29:53.880 --> 00:29:57.460
And there are some things they have to do a lot of that other people don't have to do a lot of.

00:29:57.460 --> 00:30:01.360
The good news is that 99% of websites are not in the top 1% of websites.

00:30:02.120 --> 00:30:09.440
So for most of those websites, you can just take a common entry point, give them something generic, and as long as they've got the power to move over time,

00:30:09.440 --> 00:30:12.240
then it doesn't matter that you're hiding the detail from them initially.

00:30:12.240 --> 00:30:12.700
Yeah.

00:30:12.700 --> 00:30:13.920
Yeah, that's really great.

00:30:13.920 --> 00:30:20.280
One of the things that I thought would be fun to do for the audience would be to look at all the different projects that you have going on

00:30:20.280 --> 00:30:27.740
because I looked at it here and I was just blown away at how many different things, you know, following the Unix philosophy that you pointed out,

00:30:27.740 --> 00:30:31.080
cool little tools that fit together that you guys have here.

00:30:31.080 --> 00:30:33.920
So maybe we could do like a quick survey of those.

00:30:33.920 --> 00:30:34.520
Sure.

00:30:34.520 --> 00:30:34.760
Okay.

00:30:34.760 --> 00:30:39.980
And it's interesting that this is actually, no, reactions are probably the wrong way to putting it.

00:30:39.980 --> 00:30:43.260
It's sort of, it's lessons learned from being involved in Django.

00:30:43.260 --> 00:30:50.840
The Unix philosophy here is not just about a single tool that does something well and therefore makes it easy to use and powerful to plug into something else.

00:30:50.840 --> 00:30:57.540
It's also a contribution aid because if you've got a tool that you know only does one thing and only does one thing well,

00:30:57.540 --> 00:30:59.700
the code base is inherently smaller.

00:30:59.980 --> 00:31:06.380
Now, overall, the amount of lines of code that are ultimately going to end up in everything that's Bware is probably going to be as big, if not bigger than Django, I imagine.

00:31:06.380 --> 00:31:13.760
But if you want to just contribute to the coverage tool, you can look at just the code for the coverage tool.

00:31:13.760 --> 00:31:18.400
You don't have to carry the entire baggage of all of Bware to be able to understand that one piece.

00:31:18.400 --> 00:31:19.540
Yeah, that's a great point.

00:31:19.540 --> 00:31:23.940
It makes it easier to consume piece and which makes it easier to get involved.

00:31:23.940 --> 00:31:26.640
But yes, so a survey of what we have.

00:31:26.880 --> 00:31:27.080
Sure.

00:31:27.080 --> 00:31:32.600
Well, also, I think that also is helpful from a project management and scope perspective.

00:31:32.600 --> 00:31:36.120
Like somebody proposes a feature for Cricket, the test runner.

00:31:36.120 --> 00:31:39.560
Well, like it really had better be about running tests, right?

00:31:39.560 --> 00:31:41.700
And not like an editor feature or something, right?

00:31:41.700 --> 00:31:49.920
Like if this was some giant project that did all these things, well, maybe it makes sense to add this funky drag and drop editor thing that somebody's proposing or whatever their idea was, right?

00:31:50.040 --> 00:31:51.200
Yeah, yeah, exactly.

00:31:51.200 --> 00:31:54.180
And, you know, you can say, well, okay, yes, this should absolutely be a tool.

00:31:54.180 --> 00:31:56.860
It's just not Cricket because Cricket is a test runner.

00:31:56.860 --> 00:31:57.100
Yeah.

00:31:57.100 --> 00:31:57.720
Excellent.

00:31:57.720 --> 00:31:58.400
Perfect.

00:31:58.400 --> 00:32:02.620
So just for people listening, you can find all this stuff at pybee.org.

00:32:02.620 --> 00:32:04.760
So P-Y-B-E-E dot O-R-G.

00:32:04.760 --> 00:32:07.440
And so let's talk about some of the tools.

00:32:07.440 --> 00:32:12.880
Like you had built some tools for actually performing checks when people do pull requests.

00:32:12.880 --> 00:32:14.800
And you call that B4 with two E's.

00:32:14.800 --> 00:32:15.540
Nice.

00:32:15.540 --> 00:32:15.940
Yes.

00:32:15.940 --> 00:32:17.340
We're big on puns as well.

00:32:17.540 --> 00:32:23.360
So there's almost always an inside story or a background gag.

00:32:23.360 --> 00:32:34.180
The person who suggested B4 to me suggested at the same time a different name that I really am kicking myself I didn't pick, which was Apis Praiore, which, yeah, sort of is the Latin for B.

00:32:34.180 --> 00:32:36.700
But, you know, Apriori, Apis Praiore.

00:32:36.700 --> 00:32:39.340
But, yeah, so B4 is – we haven't actually got that one live yet.

00:32:39.340 --> 00:32:43.520
It's basically we're looking for a way to actually run that and integrate.

00:32:43.640 --> 00:32:49.940
But it's essentially – all it does is listens for a pull request trigger, runs in the same way that you don't – you know, pysetup.py –

00:32:49.940 --> 00:32:52.240
pysetup.py test runs your test suite.

00:32:52.240 --> 00:32:56.020
Pythonsetup.py B4 will go through and run linters.

00:32:56.020 --> 00:32:57.480
It'll go through and run spell checkers.

00:32:57.480 --> 00:33:03.660
It'll go through and run any of the pre-commit checks that you might have, which is also not something that's particularly uncommon.

00:33:03.820 --> 00:33:18.360
But the thing that's different is that it integrates with GitHub so that when you – if you look at, like, your GitHub pull request, if anyone's integrated with something like Travis, it will run your pull requests – sorry, run your pull requests through Travis, run the test suite, and then if it passes the tests, give it a little green tick.

00:33:18.360 --> 00:33:24.940
B4 will also put a little green tick to say, and the linting is fine, and the spell checking is fine, and this, and this, and this.

00:33:25.380 --> 00:33:38.020
So just as a sanity checker, before anyone even reviews a pull request, we can go through 15 different checks if we need to about what this code needs to look like and provide the automated feedback to say, oh, yeah, no, hang on.

00:33:38.020 --> 00:33:45.820
You've got an indentation problem here on line 17 and a spell check – a spelling problem in your documentation over here and so on and so on.

00:33:46.180 --> 00:34:01.440
That's actually taking a suggestion from the Rust community that they've sort of discovered – I don't know if it was accidentally or intentional or if there's something behind it – but that if you've got feedback that needs to be given, it's – that is sort of mechanical in nature.

00:34:01.440 --> 00:34:09.540
It is better for that feedback to come from a robot because people understand that robots don't have emotions and aren't being – they're not picking on this because you're a human.

00:34:09.540 --> 00:34:13.980
They're picking on this because it's not fitting a rule, and so they will work with it.

00:34:13.980 --> 00:34:21.240
It also means it can be automated, which is one more thing that you don't have to do as a developer who is reviewing this code.

00:34:21.240 --> 00:34:29.380
If I look at a B4 approved patch, I know that it passes all the tests, and it has been linted, and it doesn't have any spelling mistakes, and so on and so on.

00:34:29.760 --> 00:34:36.340
Yeah, it's great, and so you save your energy for reviewing things like algorithms and the checks that should be there and whatnot, right?

00:34:36.340 --> 00:34:37.040
Yeah.

00:34:37.040 --> 00:34:37.780
Cool.

00:34:37.780 --> 00:34:42.780
So the next one that's on the list is Duvet, which is your coverage visualization tool.

00:34:42.780 --> 00:34:43.600
We talked about that.

00:34:43.600 --> 00:34:45.380
And then there's Briefcase.

00:34:45.380 --> 00:34:53.540
That's the one that lets you package your Python app into a standalone application, and I just can't get over the possibility of how cool that is.

00:34:53.540 --> 00:35:02.420
I know there's been like Py2exe and CX Freeze and Py2app, and they all seem to like almost work, and they just drive me crazy.

00:35:02.420 --> 00:35:10.880
Yeah, and that was kind of my – like I'm aware these projects exist, and a lot of them work really well for Windows but don't work on any other platform.

00:35:11.120 --> 00:35:18.640
So in some cases, I will admit I haven't actually done a whole lot of packaging work here on Windows, and I haven't done any on Linux at this point.

00:35:18.640 --> 00:35:28.560
But the approach that I'm sort of taking there with the way Briefcase is working is basically, well, here is a template for what an app needs to look like if only I knew the one script I need to run.

00:35:28.880 --> 00:35:30.640
Put my one script here, and the rest goes.

00:35:30.640 --> 00:35:39.140
It's also a helper sort of thing for iOS and Android because in order to get an iOS project running, you can't just drop a Python script somewhere.

00:35:39.140 --> 00:35:45.540
You actually need to have this great big iOS Xcode project, and most of that can be automated.

00:35:45.540 --> 00:35:48.900
Yeah, and it actually creates an Xcode project file, right?

00:35:49.040 --> 00:35:59.900
Yes, exactly, and the intention is in the not-too-distant future, hopefully, that it will create the Xcode project, compile the Xcode project, push the Xcode project to the device, and start it.

00:35:59.900 --> 00:36:01.120
Yeah, that's fantastic.

00:36:01.120 --> 00:36:01.780
Yeah.

00:36:01.780 --> 00:36:07.440
Like I said, I'm very thrilled about this, and this is going to require lots of attention because that looks cool.

00:36:07.440 --> 00:36:12.320
The other one that we talked about that's next in the list is Cricket, so that's your GUI test runner.

00:36:12.320 --> 00:36:16.560
That was your first foyer in this whole beware plan, right?

00:36:16.560 --> 00:36:17.020
Correct, yeah.

00:36:17.220 --> 00:36:29.320
Yeah, that's where I started as a proof of concept that, yes, you could build a cross-platform GUI tool that was useful for development purposes that you could pip install into your development environment and just use.

00:36:29.320 --> 00:36:39.120
I mean, the thing that's interesting there, that sort of pip install thing, if you've got – like test runners aren't unusual in IDEs, but in order to get them to work, like you need to know where PyCharm puts its path setting.

00:36:39.120 --> 00:36:45.040
You need to know where the environment variables go for the test environment to start up.

00:36:45.360 --> 00:36:48.880
So like in Django's context, it's, you know, you need to set Django settings.

00:36:48.880 --> 00:36:53.580
You need to know where the Django settings file is so that the application can start.

00:36:53.580 --> 00:36:57.020
Working out where to put that in your IDE is a complex thing.

00:36:57.460 --> 00:37:05.860
Whereas with – one of the interesting side effects of Cricket is because you pip install it into your environment, when it starts, it forks from inside your running Python environment.

00:37:05.860 --> 00:37:09.380
So you inherit all the environment that it needs to run in.

00:37:09.760 --> 00:37:18.240
So as long as you can run a test suite, as long as your environment is set up the way that, you know, your command line environment should be set up, Cricket just works.

00:37:18.240 --> 00:37:20.900
You don't have to – there is no configuration dialogue for Cricket.

00:37:20.900 --> 00:37:21.960
Yeah, that's awesome.

00:37:21.960 --> 00:37:23.460
I really like it.

00:37:23.460 --> 00:37:30.480
And, you know, the playful icons and the fun names really make it, like, enticing to go explore these.

00:37:30.480 --> 00:37:33.480
So the next one, speaking of that, is called Bug Jar.

00:37:33.480 --> 00:37:39.900
Yeah, and I'm actually mildly surprised that that name hadn't been taken anywhere because it seems like an absolute gimme for a debugger.

00:37:39.900 --> 00:37:50.740
That's actually, like, if you dig back into the archives behind – before Cricket, Bug Jar is actually where I really started because what I really wanted – PDB is an incredibly powerful tool.

00:37:50.740 --> 00:37:54.660
PDB is – the API, the way it all works is fantastic.

00:37:54.660 --> 00:37:58.080
The PDB interface, to my mind, is toxic.

00:37:58.600 --> 00:38:04.700
And I know that there is IPDB and there's PDB++ and there's a bunch of other tools out there, but they're all console-driven.

00:38:04.700 --> 00:38:09.460
And I know there is WinPDB, but I've never been able to get it to actually, you know, work.

00:38:09.460 --> 00:38:19.000
What I really, really wanted was the debugger that was like the one that I had in 1988 when I first got my copy of Ball and C, but for Python.

00:38:19.000 --> 00:38:22.040
And I got a little distracted along the way.

00:38:22.040 --> 00:38:23.440
Eventually, I'm going to get back there, I swear.

00:38:23.640 --> 00:38:29.480
That's a great idea, and I really appreciate a visual interactive debugger myself as well.

00:38:29.480 --> 00:38:36.880
I know you can do it with – in the command line, but it's not the same when you're working on a large project, in my opinion.

00:38:36.880 --> 00:38:50.120
Yeah, I mean, the visual scope and context you get by having an arrow pointing at a line of code with a window on the side that says the value of X is 3 versus a command line interface where you have to type 15 commands to get the same amount of information.

00:38:50.120 --> 00:38:52.480
It just – it seems like a no-brainer to me.

00:38:52.860 --> 00:38:53.220
Yeah, absolutely.

00:38:53.220 --> 00:38:57.840
So the last one is kind of a quick documentation one called Galley.

00:38:57.840 --> 00:39:02.200
Yeah, the name on that may actually need to change because we've lost the namespace on PyPI.

00:39:02.200 --> 00:39:08.720
That's the one that finally pushed me over the edge with TK because TK doesn't have a web widget.

00:39:08.720 --> 00:39:10.200
I write documentation.

00:39:10.200 --> 00:39:15.400
I like – I don't like writing documentation, but I appreciate the documentation is important and I need to write it.

00:39:15.400 --> 00:39:24.680
But Sphinx, as much as markdown and restructured text try to look like markup, they don't.

00:39:25.340 --> 00:39:28.560
So you end up writing a bunch of code, compiling it.

00:39:28.560 --> 00:39:36.680
Oh, I missed – I didn't put – there's one less underscore that I needed on that particular thing or I forgot the colon after this bit.

00:39:37.320 --> 00:39:45.840
So the idea behind Galley was to provide you a text window on one side where you edit your text and then actually render it so you can see what it looks like as you modify it.

00:39:45.840 --> 00:39:53.420
But in order to do that, you need to have a web browser to actually display the content of the code or the content of what has been generated and you can't do that in TK.

00:39:54.480 --> 00:40:02.560
Actually, the other interesting thing about Galley is that it actually takes me a little bit closer to the thing that got me involved in Django in the first place, which is an editing tool.

00:40:02.560 --> 00:40:08.000
There's a whole other podcast in the tool that in my dream of dreams I'm eventually one day going to write.

00:40:08.000 --> 00:40:12.080
That's sort of an editor that is context-sensitive or syntax-sensitive.

00:40:12.080 --> 00:40:14.980
But, yeah, that's a talk for another time.

00:40:14.980 --> 00:40:15.540
All right.

00:40:15.540 --> 00:40:15.880
Awesome.

00:40:15.880 --> 00:40:17.200
Sounds great.

00:40:17.200 --> 00:40:18.640
All right.

00:40:18.640 --> 00:40:21.320
So that wraps it up for the tools.

00:40:21.320 --> 00:40:22.720
Let's talk about some of the libraries.

00:40:22.720 --> 00:40:25.980
And these libraries are – each one of them is really ambitious.

00:40:25.980 --> 00:40:27.760
And it's just one more library.

00:40:27.760 --> 00:40:28.660
So that's pretty cool.

00:40:28.660 --> 00:40:31.880
So the first one is Coliseum.

00:40:31.880 --> 00:40:36.120
This has to do with the layout and putting stuff basically on a screen.

00:40:36.120 --> 00:40:40.620
Is this for the web or is this for your Python desktop app?

00:40:40.620 --> 00:40:41.240
No.

00:40:41.240 --> 00:40:45.160
So this is actually targeting – like the reason I started that project is specifically because of Toga.

00:40:45.160 --> 00:40:52.320
When I started Toga, the original plan was to use something called Cassowary, which is if you've ever programmed for iOS,

00:40:52.320 --> 00:40:56.140
it's the constraints algorithm that underpins Cassowary.

00:40:56.140 --> 00:40:57.600
So that underpins iOS.

00:40:57.600 --> 00:41:03.480
So effectively, it's a linear algebra approach to describing how widgets appear on a page.

00:41:03.480 --> 00:41:09.480
If you've ever written any GUI code for a native application, you effectively have to say,

00:41:09.480 --> 00:41:14.440
I've got a button and a button, and there's a split pane, and the split pane is this, and so on and so on.

00:41:14.980 --> 00:41:18.800
And there's usually some box model that's involved, which here is a stack of vertical boxes,

00:41:18.800 --> 00:41:20.480
or here is a grid of some description.

00:41:20.480 --> 00:41:30.740
The Cassowary is trying to do an algorithmic approach, which says, I'm going to specify how my desktop lays out as a series of linear programming constraints.

00:41:30.860 --> 00:41:35.800
So the left side of this button must be 10 pixels from the left side of the screen,

00:41:35.800 --> 00:41:41.600
but the right side of the button must be no more than 10 pixels from the right side of the screen, and so on.

00:41:41.600 --> 00:41:47.740
And then you run Cassowary to solve the linear programming constraints, and then your widgets appear on the screen.

00:41:47.740 --> 00:41:54.080
Now, that's incredibly powerful, but it's also an absolute pain in the butt if when it goes wrong,

00:41:54.280 --> 00:41:55.640
because all of a sudden you're trying to solve-

00:41:55.640 --> 00:41:59.040
Yeah, it's super hard to debug that iOS stuff, and you're just like, what is going wrong with this?

00:41:59.040 --> 00:41:59.900
Why does this not work?

00:41:59.900 --> 00:42:01.520
When it works, it's great.

00:42:01.520 --> 00:42:03.540
When it doesn't, you are screwed.

00:42:03.540 --> 00:42:11.280
So prompted mostly by React, they sort of, or React Native rather, they sort of pointed out that you could lay out,

00:42:11.280 --> 00:42:18.040
like the CSS box model, yes, it's intended for the web, but there's actually nothing web-specific about it per se.

00:42:18.040 --> 00:42:25.240
It's basically just a set of algorithms for how you put boxes of content and relate boxes of content in a tree-like structure.

00:42:25.240 --> 00:42:31.980
So what I said originally ported just the version of Flexbox that React has developed,

00:42:31.980 --> 00:42:40.040
and the intention is to connect that into a full CSS2 plus Flexbox plus any of the other interesting pieces of the CSS spec

00:42:40.040 --> 00:42:42.040
that you can use for any boxes.

00:42:42.040 --> 00:42:46.440
Now, obviously, that immediately translates to buttons, widgets on a page,

00:42:46.820 --> 00:42:52.560
but you could also do things like, okay, I need a HTML to PDF translator.

00:42:52.560 --> 00:42:57.560
Well, okay, I can take the DOM tree that I've got and use that to turn out a set of drawing instructions.

00:42:57.560 --> 00:43:03.560
So the intention is that ultimately Colosseum is going to be powerful, or it will be powerful enough

00:43:03.560 --> 00:43:10.040
that you can throw an arbitrary piece of CSS and some tree of content and be able to render it.

00:43:10.040 --> 00:43:15.760
The interesting side effect of that, of course, is that when you actually want to take Toga and deploy it to the web,

00:43:15.820 --> 00:43:21.180
which is something I've spoken about at DjangoCon Europe this year, it means that you've actually got CSS.

00:43:21.180 --> 00:43:27.060
So you've got the same layout mechanism on the web that you're using in your native GUI toolkits.

00:43:27.060 --> 00:43:30.840
So you don't actually have to have a separate layout scheme working out there.

00:43:30.840 --> 00:43:31.940
Yeah, that's cool.

00:43:31.940 --> 00:43:32.860
I really like it.

00:43:32.860 --> 00:43:33.820
That's quite ambitious.

00:43:34.280 --> 00:43:39.120
I definitely think CSS is a fabulous way to layout things.

00:43:39.120 --> 00:43:48.080
I've used a lot of Windows, rich GUI type of layouts, and I've always gone, gee, if I just had CSS, this thing would be maintainable, you know?

00:43:48.340 --> 00:43:56.260
I will admit I do have a bit of a love-hate relationship with CSS more generally, but it's sort of – in terms of a general – it is something that is well-known.

00:43:56.260 --> 00:43:57.580
It is something that is well-understood.

00:43:57.580 --> 00:43:58.800
It is something that is well-documented.

00:43:58.800 --> 00:43:59.940
It is something that is open.

00:44:00.780 --> 00:44:09.680
And that sort of combination of stuff, but the only – it makes it really powerful, but the only thing we don't have is an open implementation that isn't tied to a browser.

00:44:09.680 --> 00:44:10.340
Yeah.

00:44:10.340 --> 00:44:15.040
So, yeah, at some point I'd need to sit down and spend a whole lot of time just working on Coliseum.

00:44:15.040 --> 00:44:17.320
At the moment it's fairly limited in what it can do.

00:44:17.320 --> 00:44:20.680
It's useful enough but not completely CSS or the complete CSS.

00:44:20.680 --> 00:44:21.640
Sure, sure.

00:44:21.640 --> 00:44:22.200
Yeah.

00:44:22.200 --> 00:44:22.800
Cool.

00:44:22.800 --> 00:44:30.320
And, you know, I think part of that frustration, at least projected my own frustrations I've had with CSS and things like that and the design is,

00:44:30.600 --> 00:44:33.600
more about when the implementation varies.

00:44:33.600 --> 00:44:41.860
It's like, why does IE have a line here, a border, and why does Firefox have a space and Chrome has neither of these, like – that's not really a frustration with CSS.

00:44:41.860 --> 00:44:43.760
That's just, like, with the browsers.

00:44:43.760 --> 00:44:44.560
Yeah.

00:44:44.560 --> 00:44:45.240
Yeah, for sure.

00:45:00.420 --> 00:45:02.400
IE platform for top Python developer jobs.

00:45:02.400 --> 00:45:07.200
Create your profile and instantly get access to 3,500 companies who will work to compete with you.

00:45:07.200 --> 00:45:10.060
Take it from one of Hired's users who recently got a job and said,

00:45:10.060 --> 00:45:15.360
I had my first offer on Thursday after going live on Monday and I ended up getting eight offers in total.

00:45:15.360 --> 00:45:18.820
I've worked with recruiters in the past, but they've always been pretty hit and miss.

00:45:18.820 --> 00:45:21.660
I tried LinkedIn, but I found Hired to be the best.

00:45:21.660 --> 00:45:23.760
I really like knowing the salary up front.

00:45:23.760 --> 00:45:26.120
Privacy was also a huge seller for me.

00:45:26.120 --> 00:45:27.800
Sounds awesome, doesn't it?

00:45:28.100 --> 00:45:29.800
Well, wait until you hear about the sign-in bonus.

00:45:29.800 --> 00:45:33.220
Everyone who accepts a job from Hired gets $1,000 sign-in bonus.

00:45:33.220 --> 00:45:35.880
And as Talk Python listeners, it gets way sweeter.

00:45:35.880 --> 00:45:41.140
Use the link Hired.com slash Talk Python To Me and Hired will double the sign-in bonus to $2,000.

00:45:41.140 --> 00:45:42.920
Opportunity's knocking.

00:45:42.920 --> 00:45:46.700
Visit Hired.com slash Talk Python To Me and answer the door.

00:45:48.920 --> 00:45:59.660
Yeah, so you mentioned Toga a couple times and Toga is a Python native, OS native GUI toolkit.

00:45:59.660 --> 00:46:00.520
Yes.

00:46:00.520 --> 00:46:02.100
Tell us about that.

00:46:02.100 --> 00:46:02.820
Okay.

00:46:02.820 --> 00:46:06.300
So this is essentially the bit that comes before the actual application.

00:46:06.300 --> 00:46:10.580
So the philosophy we've kind of taken is that native is good.

00:46:10.580 --> 00:46:11.700
Native is what you're looking for.

00:46:11.700 --> 00:46:13.480
You want something that looks native, feels native.

00:46:13.480 --> 00:46:16.320
It's not pretending to be agnostic.

00:46:16.320 --> 00:46:18.900
It's not pretending to be the platform that it's not.

00:46:18.900 --> 00:46:22.880
It gives you – if you want a button, it's a button the way that a button looks on that platform.

00:46:23.580 --> 00:46:32.140
And it sort of does that by being Python first, Python native, which means that you're not looking at an API that is very obviously C wrapped in Python.

00:46:32.140 --> 00:46:43.760
It enables you to do things like – the classic example is whenever you've got a long-running task in most widget toolkits, they are C or some variant thereof.

00:46:43.760 --> 00:46:56.600
And so you come up with some small quantum of work that can be evaluated and you push that quantum of work into some form of timer in a separate thread that gets evaluated at some regular interval.

00:46:56.600 --> 00:47:01.920
In Toga, you use the same – just a function that's a callback except you make it a generator.

00:47:01.920 --> 00:47:03.160
You make it yield regularly.

00:47:03.160 --> 00:47:08.600
And when it yields, what it does is it yields to the event loop and then it resumes inside where it was previously.

00:47:09.140 --> 00:47:24.800
So you can exploit the fact that Toga gives you – or so Python gives you this mechanism to resume where you were inside a method, which isn't a capability you have inside Java and C and C++ and so on, to produce an API that is rich and flexible.

00:47:24.800 --> 00:47:28.440
You know, when you want to specify a list of something, you just give it a list of something.

00:47:28.440 --> 00:47:30.220
When you want it in a string, you just give it a string.

00:47:30.220 --> 00:47:35.820
And it works out how to make that render in a native fashion, in a native appropriate fashion.

00:47:35.820 --> 00:47:36.840
Yeah, that's really amazing.

00:47:37.020 --> 00:47:44.200
And if you want to try it out, anyone listening can just pip it, soltoga, T-O-G-A, and then toga-demo, right?

00:47:44.200 --> 00:47:47.860
And then boom, you have a running GUI right there.

00:47:47.860 --> 00:47:49.100
It looks totally native to me.

00:47:49.100 --> 00:47:49.440
Yeah.

00:47:49.440 --> 00:47:54.240
And it is completely native because it is – you know, when Toga demo runs, it is firing up on Mac.

00:47:54.240 --> 00:48:01.560
It's an NS window with an NS split pane with an NS list or NS table and so on and so on.

00:48:01.560 --> 00:48:05.680
And when you click on the button that's a dialog, it's an NS alert box or whatever it happens to be.

00:48:05.680 --> 00:48:12.880
And then if you do exactly the same on the GTK, it's a GTK window with a GTK split pane with a GTK button in it and so on and so on.

00:48:12.980 --> 00:48:20.880
So if you look behind this, it sounds like it's incredibly complicated, but the actual code behind Toga is relatively simple once you've got the bridging to the native layer done.

00:48:20.880 --> 00:48:24.200
On GTK, you get that for free because there is a native Python API.

00:48:24.920 --> 00:48:35.700
And Rubicon, which is the library that lets us get to Objective-C, is complex but almost completely transparent because you just sort of name the classes and name the methods in a slightly funny way and you can access them.

00:48:35.700 --> 00:48:46.200
So the native Toga implementation of a button on macOS, for example, is about 30 lines of code and it's 30 fairly straightforward lines of code at that.

00:48:46.200 --> 00:48:48.840
So adding new widgets is relatively simple.

00:48:48.900 --> 00:48:54.800
And at the end of the day, if you do actually want to get into a widget that is very macOS specific, you can just drop into that level.

00:48:54.800 --> 00:48:55.280
Okay.

00:48:55.280 --> 00:48:56.680
Yeah, that's really great.

00:48:56.680 --> 00:48:58.560
Toga looks really amazing.

00:48:58.560 --> 00:49:06.600
And like I said, I think building out these truly OS native things in Python, mix that with a briefcase.

00:49:06.600 --> 00:49:07.740
Very lovely, right?

00:49:07.740 --> 00:49:10.600
So the next one, I'm sure I'm going to mispronounce.

00:49:10.600 --> 00:49:12.020
So can you hit it for me?

00:49:12.020 --> 00:49:12.700
Okay.

00:49:12.700 --> 00:49:13.500
So that's Oroboros.

00:49:13.500 --> 00:49:14.320
Oroboros.

00:49:14.320 --> 00:49:14.620
Okay.

00:49:14.620 --> 00:49:15.360
Yeah.

00:49:15.360 --> 00:49:15.860
Yeah.

00:49:15.860 --> 00:49:24.120
So Oroboros, for those who don't know the Greek mythology or the old Latin mythology, it's the image of a snake eating its own tail.

00:49:24.120 --> 00:49:30.540
So the idea here is that if we're going to – part of being – of Toga is trying to be cross-platform.

00:49:30.540 --> 00:49:31.580
So we've got it on macOS.

00:49:31.580 --> 00:49:32.680
We've got it on GTK.

00:49:32.680 --> 00:49:35.360
We've got it on – we've got some parts of it on Windows.

00:49:35.360 --> 00:49:39.140
But they're all just sort of standard Python running in standard Python-y kind of ways.

00:49:39.540 --> 00:49:48.600
We've got Python running on iOS, and that's actually just CPython compiled for iOS because iOS is, as much as they try to hide it, C under the hood and Clang under the hood.

00:49:49.260 --> 00:49:53.420
But on Android, they really, really, really want you to be using Java.

00:49:53.420 --> 00:49:56.660
So I've kind of had to do a bit of an interesting shim to get there, which I'm sure we'll come to.

00:49:56.660 --> 00:50:03.260
And for deploying to the web, if you want Python on the web, well, you've got to have it written in JavaScript.

00:50:03.260 --> 00:50:09.940
In order to do that, you need an implementation of the Python standard library written in – written so it works on that platform.

00:50:10.440 --> 00:50:13.760
Now, a lot of the Python standard library is written in Python, but there are some parts that aren't.

00:50:13.760 --> 00:50:21.200
So things like the underlying core of date time, mk time, and time structure T and things like that are native concepts.

00:50:21.200 --> 00:50:26.520
So you've got to have a native implementation of those concepts that the rest of the standard library can then build on.

00:50:26.520 --> 00:50:48.840
And so Oroboros is attempting to build as much of the standard library in Python as we can possibly build, cribbing from CPython when we can, and then filling out the rest with the interface, the API that you need to implement in order to have date time working inside a web browser or working on an Android phone.

00:50:48.840 --> 00:50:49.840
That's really amazing.

00:50:49.840 --> 00:50:52.160
Have you combined that with PyPy?

00:50:52.260 --> 00:51:07.320
I think we have actually taken some pieces with PyPy, and I think there probably is some crossover there in terms of what we're doing and what they're doing in that PyPy benefits from having a pure Python version of any module because they can then optimize the entire VM rather than just optimizing parts of it.

00:51:07.320 --> 00:51:16.400
So at some point, I don't know if we'll merge with PyPy, PyPy merges with Oroboros or whatever, but there is a piece there that I think that can be shared at the very least.

00:51:16.400 --> 00:51:17.200
Yeah, absolutely.

00:51:17.200 --> 00:51:23.060
That definitely seems like that would be great because if you have it in pure Python and you feed it to PyPy, it should go nice and fast.

00:51:23.060 --> 00:51:24.280
Theoretically.

00:51:24.280 --> 00:51:25.460
That's the intention, yeah.

00:51:25.460 --> 00:51:28.300
And that is ultimately what PyPy is doing a lot of the time.

00:51:28.300 --> 00:51:40.980
It is just they have re-implemented parts of what is written in C in Python so that it will run fast because they can pass the full bytecode optimizer over everything it's doing rather than just parts of what it's doing.

00:51:40.980 --> 00:51:41.660
Right, absolutely.

00:51:41.660 --> 00:51:46.660
So that brings us pretty naturally to the next major category, which you call bridges.

00:51:46.660 --> 00:51:48.040
Yes.

00:51:48.040 --> 00:51:51.420
I love the subtitle, boldly going where new Python has gone before.

00:51:51.420 --> 00:51:55.760
Sorry, the question from before might be like, well, all right, great.

00:51:55.760 --> 00:51:57.700
It's a pure Python standard library.

00:51:57.700 --> 00:51:58.820
Like, what can you do that?

00:51:58.820 --> 00:52:03.460
But then you have Batavia, which would work really well with that, right?

00:52:03.980 --> 00:52:10.080
Yeah, so the idea here is that Batavia specifically started as a bit of a joke at PyCon Australia Sprints last year.

00:52:10.080 --> 00:52:12.020
I don't particularly like JavaScript.

00:52:12.020 --> 00:52:16.400
I accept it that it exists and it is the lingua franca that is on the web and it's not going anywhere.

00:52:16.400 --> 00:52:19.160
And I don't want to language shame anybody for having knowing JavaScript.

00:52:19.160 --> 00:52:23.440
It is an important language to learn, to know, and there are some very valuable things in there.

00:52:23.660 --> 00:52:27.320
But I would be a very happy man if I never had to write another line of JavaScript in my life.

00:52:27.320 --> 00:52:36.080
So part of that is that if I'm going to write web software and I want responsive front-end web software, I need to have Python running in the browser.

00:52:36.080 --> 00:52:44.300
Or alternatively, I need to rewrite everything I'm doing on the server in JavaScript, which given that I don't want to do that, I need to get Python into the browser somehow.

00:52:45.100 --> 00:52:59.200
So what Batavia does is take a look at the fact that when you compile CPython, now Python as a whole is a, you know, if you wanted to have a complete Python compiler and interpreter and everything, yeah, that's a big thing to build.

00:52:59.200 --> 00:53:01.220
And there are people who are doing that.

00:53:01.220 --> 00:53:03.020
You know, Brython and Sculpt both do that.

00:53:03.020 --> 00:53:05.280
PyPy.js takes a slightly different approach.

00:53:05.280 --> 00:53:09.120
I had Ryan from PyPy.js on and there's a bunch of cool stuff that's happening to him.

00:53:09.120 --> 00:53:13.760
But a lot of those projects are really large or they make big trade-offs in terms of support.

00:53:13.760 --> 00:53:17.680
Yeah, so like, you know, PyPy.js, I don't know exactly where it's at in terms of size now.

00:53:17.680 --> 00:53:21.600
But like the first time I looked at it, it was like 20 megabytes as a compressed download.

00:53:21.600 --> 00:53:24.420
And that's fine if you've got that already cached.

00:53:24.420 --> 00:53:30.380
But if you want to build your next Instagram, downloading a 20 meg bootstrap is just not a candidate.

00:53:30.380 --> 00:53:33.260
So Batavia treats it at a slightly different angle.

00:53:33.260 --> 00:53:40.740
So in saying instead of we don't actually need the full Python interpreter or the full Python compiling tool chain with a REPL and everything else,

00:53:40.740 --> 00:53:43.160
what we need is the ability to run Python code.

00:53:43.160 --> 00:53:46.340
CPython compiles to bytecode.

00:53:46.340 --> 00:53:54.640
Bytecode is a simple virtual machine with 150 odd instructions, most of which are push, pop, add value, subtract value, this kind of thing.

00:53:54.640 --> 00:54:00.380
Can we implement that virtual machine in JavaScript and then just give it Python bytecode?

00:54:00.380 --> 00:54:01.860
And the answer is yes.

00:54:01.860 --> 00:54:04.660
And it turns out to be a relatively small amount of bytecode as well.

00:54:04.660 --> 00:54:11.740
You can get Batavia, like a fully functioning Batavia instance running in something like 10 kilobyte of compressed JavaScript.

00:54:11.740 --> 00:54:15.460
And I'm sure there's all sorts of opportunities to optimize there as well.

00:54:15.460 --> 00:54:16.260
That's amazing.

00:54:16.260 --> 00:54:19.980
And that's totally acceptable for downloading 10, 15K in JavaScript.

00:54:19.980 --> 00:54:20.260
Yeah, yeah, yeah.

00:54:20.260 --> 00:54:23.080
So that's less than your logo image in most cases.

00:54:23.080 --> 00:54:25.900
You know, it's easily an achievable goal.

00:54:25.900 --> 00:54:32.280
And all you're really losing is really performance at that point because it is CPython that is running.

00:54:32.280 --> 00:54:38.420
It's just running in the browser using JavaScript to emulate the pieces that can't be done natively.

00:54:38.600 --> 00:55:04.460
Now, the other thing I have to shout out here is part of the reason that I know this or I thought this joke actually might be plausible is a blog article slash book chapter written by Ned Batchelder and Alison Captur called Architecture Open Source Volume 4, which looks at sort of a bunch of complex problems and says, okay, let's solve this problem in 500 lines or 500 lines of Python.

00:55:04.460 --> 00:55:07.220
And Alison's chapter in that book.

00:55:07.220 --> 00:55:08.340
Yeah, that's a cool book.

00:55:08.480 --> 00:55:09.240
Yeah, it's a very cool book.

00:55:09.240 --> 00:55:10.620
Yeah, it's an amazing book.

00:55:10.620 --> 00:55:14.780
And one of the chapters in there is here is a Python interpreter written in 500 lines of Python.

00:55:14.780 --> 00:55:18.820
And that blew my mind when I read it.

00:55:18.820 --> 00:55:19.960
It's amazing stuff.

00:55:19.960 --> 00:55:25.580
But it also means, hang on, 500 lines of Python, that means I should be able to do it in about 500 lines of JavaScript as well.

00:55:25.580 --> 00:55:26.700
And that's about dead on.

00:55:26.700 --> 00:55:27.880
It's not that far from it.

00:55:27.880 --> 00:55:31.500
You need a little bit more bootstrapping to say like JavaScript's only got numbers.

00:55:31.500 --> 00:55:34.320
You need a concept of integers and floats and they need to behave the right way.

00:55:34.320 --> 00:55:36.840
There's a little bit of bootstrapping you need to do around the outside.

00:55:37.360 --> 00:55:39.500
But it's achievable is the point.

00:55:39.500 --> 00:55:53.840
And you can do it in sub 100k of code or some 100k of deliverable artifacts, which means that when you – if you've got like a – say you've got a Django server that has a form and the form has a validation function at some point.

00:55:53.840 --> 00:55:56.640
That validation function is Python code.

00:55:56.640 --> 00:55:58.740
It can be compiled as a code object.

00:55:58.740 --> 00:56:00.480
That code object has bytecode.

00:56:00.480 --> 00:56:02.160
That bytecode can be turned into a string.

00:56:02.160 --> 00:56:03.620
The string can be sent to the browser.

00:56:03.620 --> 00:56:09.780
The browser can then run that JavaScript – or say run that bytecode in the JavaScript version of the virtual machine.

00:56:10.200 --> 00:56:17.940
And then you've got not just similar or transpiled or whatever, exactly the same code running on the client and the server.

00:56:17.940 --> 00:56:19.660
And you've written it all in Python.

00:56:19.660 --> 00:56:21.500
Yeah, that's great.

00:56:21.500 --> 00:56:25.500
So it takes the load off your server because most of the stuff would happen client-side.

00:56:26.040 --> 00:56:27.120
And it means you write it once.

00:56:27.120 --> 00:56:28.420
Yeah, it's not just the load.

00:56:28.420 --> 00:56:29.540
I mean the load is obviously a benefit.

00:56:29.540 --> 00:56:35.320
But it's also – if you want a rich user interface, you want to say you want to validate credit card numbers as they're being typed in.

00:56:35.320 --> 00:56:39.600
You can't do that server-side because this is something I get acutely aware of because I'm in Australia.

00:56:39.600 --> 00:56:41.800
You can't change the laws of physics.

00:56:41.800 --> 00:56:45.840
Ping time from me to the east coast of the U.S. is 300 milliseconds.

00:56:45.840 --> 00:56:54.160
You cannot change that unless you are willing to accept a 300 millisecond or longer delay in every user interface action.

00:56:54.160 --> 00:56:55.520
It has to be running locally.

00:56:55.520 --> 00:56:58.800
And if you can run it in Python, then all the better.

00:56:58.800 --> 00:57:00.220
Yeah, very cool.

00:57:00.220 --> 00:57:01.560
Those two go together.

00:57:01.560 --> 00:57:01.820
Great.

00:57:01.820 --> 00:57:02.520
That's awesome.

00:57:02.520 --> 00:57:06.540
So that's Python in JavaScript.

00:57:06.540 --> 00:57:07.740
Yes.

00:57:07.740 --> 00:57:11.480
What if I want to run Python bytecode on, say, the JPM?

00:57:11.480 --> 00:57:13.580
Well, I'm glad you asked.

00:57:13.580 --> 00:57:17.740
So, yeah, the next project on the list is VOC, VOC.

00:57:17.740 --> 00:57:21.940
That is a – takes a very similar approach to what Batavia has done.

00:57:21.940 --> 00:57:32.880
But instead of saying let's target JavaScript, let's rewrite a CPython interpreter in JavaScript, it says, okay, CPython, when it runs, is a stack-based virtual machine.

00:57:32.880 --> 00:57:36.960
Java, when it runs, is a stack-based virtual machine.

00:57:37.600 --> 00:57:40.220
Now, okay, to be sure, they are different stack-based virtual machines.

00:57:40.220 --> 00:57:41.300
They have different requirements.

00:57:41.300 --> 00:57:42.160
They have different needs.

00:57:42.160 --> 00:57:44.660
They have different operational characteristics.

00:57:44.660 --> 00:57:49.840
But they're close enough that if you squint, you can turn one into the other.

00:57:49.840 --> 00:57:51.540
And so that's what VOC does.

00:57:51.540 --> 00:58:00.920
VOC says, okay, let's take this Python code, CPython code, and compile it into directly the equivalent Java class files.

00:58:00.920 --> 00:58:03.540
Not turning it into Java code that gets compiled.

00:58:03.540 --> 00:58:05.200
Turning it into the class file directly.

00:58:05.200 --> 00:58:07.380
So the output isn't a PYC file.

00:58:07.380 --> 00:58:09.560
The output is a .class file.

00:58:09.560 --> 00:58:13.460
That then runs as if it was Java because it is Java.

00:58:14.340 --> 00:58:26.100
So, and the sort of interesting little side effects of things like that is that when, you know, you write your Python code and it throws an exception, for example, the exception can point at the line of Python code that generated it.

00:58:26.100 --> 00:58:28.820
Now, this sort of general approach isn't that unusual.

00:58:28.900 --> 00:58:33.420
If you look at something like Scala, Scala is just a compiler that produces Java class files.

00:58:33.420 --> 00:58:35.460
It happens to be a different functional language.

00:58:35.460 --> 00:58:41.400
So all we're doing here is effectively a compiler that takes Python input and spits out Java class files.

00:58:41.400 --> 00:58:50.260
Now, that's critically different to something like Jython, which is a full implementation of a Java virtual machine and Java compiler and all the rest.

00:58:50.260 --> 00:58:58.260
So when you run your Python code through Jython, it is Python code being interpreted in Java at runtime.

00:58:58.260 --> 00:58:58.780
Right.

00:58:58.780 --> 00:59:01.480
Which is also not to be, not to dis Jython.

00:59:01.480 --> 00:59:04.200
Jython is a great project as well, but it's a different approach.

00:59:04.200 --> 00:59:04.600
Right.

00:59:04.600 --> 00:59:13.760
It's almost like instead of using C to implement the virtual machine, they're using Java versus actually compiling, compiling the steps.

00:59:13.760 --> 00:59:14.240
Yeah.

00:59:14.240 --> 00:59:23.900
And ultimately, the reason that I've kind of started VOC is that you say it's written in Java rather than written in C star, except for the parts that aren't.

00:59:23.900 --> 00:59:33.920
Because there are parts of the compiler tool chain, Xerces and what have you, that are written using the Java native interface.

00:59:33.920 --> 00:59:42.780
And so you can't actually, at least not at the moment anyway, you can't compile Jython for Android because there are parts that will not run on Android.

00:59:43.280 --> 00:59:45.440
So I needed a different approach to get things working on Android.

00:59:45.440 --> 00:59:47.160
And so, you know, VOC was born.

00:59:47.160 --> 00:59:47.560
Cool.

00:59:47.560 --> 00:59:48.800
And VOC works on Android.

00:59:48.800 --> 00:59:51.380
And yeah, the intention was originally to target it for Android.

00:59:51.380 --> 00:59:58.840
But by a side effect, because Java is actually a cross-platform runtime environment, I've, you know, I knocked out a demo swing application.

00:59:58.840 --> 01:00:05.080
You can write a native swing application that gets native swing APIs in Python and it will run through Java.

01:00:05.080 --> 01:00:06.780
And you can't tell that it's not Java.

01:00:06.780 --> 01:00:07.620
That's really cool.

01:00:07.620 --> 01:00:12.200
It turns out a Java API, a Java user interface that looks awful because it's not native.

01:00:12.380 --> 01:00:14.660
But, you know, it is using Swing's native components.

01:00:14.660 --> 01:00:31.360
You could entirely plausibly write a, you can't do it yet, but conceptually, you could take Django, compile it to Java class files, run it in a J2EE container, and satisfy your, you know, your enterprise deployment requirement that everything's written in Java.

01:00:31.440 --> 01:00:32.240
Because it is.

01:00:32.240 --> 01:00:34.140
It's just written in Python in Java.

01:00:34.140 --> 01:00:34.540
Yeah.

01:00:34.540 --> 01:00:36.100
They just care how it executes, right?

01:00:36.100 --> 01:00:37.060
Interesting.

01:00:37.060 --> 01:00:37.820
Yeah, exactly.

01:00:37.820 --> 01:00:44.240
So I'm always, you know, I've done a lot of, like, scientific parallel computation type stuff previously.

01:00:44.240 --> 01:00:48.540
And I'm always on the lookout for things that let me dodge the GIL.

01:00:48.540 --> 01:00:50.580
Does this let you dodge the gill?

01:00:51.220 --> 01:00:56.180
Well, effectively, yeah, because, you know, it is on, when it's compiling, it's compiling for the Java virtual machine.

01:00:56.180 --> 01:01:02.300
So it is producing thing, you know, the variables are all locked the same way they would be in a piece of Java code.

01:01:02.380 --> 01:01:05.020
So it is a gill-less version of Python.

01:01:05.020 --> 01:01:08.600
With all the language, well, not all yet, because I'm still working on bits of it.

01:01:08.600 --> 01:01:13.120
But, you know, you can do anything you can do in Python, you can do in Vox.

01:01:13.120 --> 01:01:16.740
You know, you can, for example, you can do yield statements in Vox.

01:01:16.740 --> 01:01:19.680
There is no equivalent of a yield statement in Java.

01:01:19.680 --> 01:01:26.780
But I can, you can generate the Java bytecode that does the functionality of yield, because it's essentially just assembly language at that point.

01:01:26.780 --> 01:01:28.580
It's just Java assembly language.

01:01:28.580 --> 01:01:29.760
Okay, very interesting.

01:01:29.760 --> 01:01:31.920
All right, final one on your bridge.

01:01:32.220 --> 01:01:32.900
Is Rubicon.

01:01:32.900 --> 01:01:41.340
Yeah, so Rubicon was, there was originally a Rubicon Java as well, which I was looking at using for Android, but turned out to not be quite plausible for various reasons.

01:01:41.340 --> 01:01:43.660
But it's mostly there for the Objective-C portion.

01:01:43.660 --> 01:01:51.080
So I touched on this earlier, that Objective-C, for all of the funny syntax, is ultimately just a series of C APIs.

01:01:51.080 --> 01:01:57.620
And C types, which is part of the Python standard library, lets you call any native C function as long as you know it's prototype.

01:01:58.180 --> 01:02:03.800
So you can invoke any Objective-C API directly from Python without having to compile anything.

01:02:03.800 --> 01:02:15.100
And then Rubicon then sort of wraps that up in a bunch of meta classes and whatnot, using the Python 3 type annotation syntax to say, well, this argument is an integer and this one is a Boolean and it returns an object.

01:02:15.100 --> 01:02:19.120
Map that to the underlying call in Objective-C.

01:02:19.360 --> 01:02:25.640
You end up with, you know, you can instantiate an NS button the same way that you would in Python normally.

01:02:25.640 --> 01:02:31.880
The only difference is that the message passing syntax replace colons with underscores and the method names get really long.

01:02:31.880 --> 01:02:39.120
But that's kind of, you know, you don't have to pre-compile, pre-declare, pre-anything about what is in your Objective-C environment.

01:02:39.120 --> 01:02:41.120
You've just got to call the things you need.

01:02:41.400 --> 01:02:42.060
Wow, that's fantastic.

01:02:42.060 --> 01:02:45.100
So you brought up Python 3.

01:02:45.100 --> 01:02:48.220
What's the story with Python 3 across Beware in general?

01:02:48.220 --> 01:02:48.860
Okay.

01:02:48.860 --> 01:02:53.760
So I have taken the wonderfully controversial stance of saying Python 2 is dead.

01:02:53.760 --> 01:02:56.180
I am developing a set of tools.

01:02:56.180 --> 01:02:58.820
I started developing a set of tools four years ago.

01:02:58.820 --> 01:03:02.260
Four years ago, I was developing stuff in Python 2 primarily.

01:03:02.940 --> 01:03:06.140
I am now at the point where I'm developing new runtimes.

01:03:06.140 --> 01:03:12.480
I'm developing new languages or new runtime environments, new language interpreters, new libraries for cross-platform.

01:03:12.480 --> 01:03:17.240
I have made the decision that I am Python 3 and for the most part, I don't care about Python 2.

01:03:17.240 --> 01:03:20.420
Now, if someone else wants to come in and care about Python 2, power to them.

01:03:20.420 --> 01:03:21.960
I won't turn down the patch.

01:03:22.140 --> 01:03:27.040
But I am aggressively targeting Python 3 and hoping that that will be enough of an incentive.

01:03:27.040 --> 01:03:35.400
Like by the time that Toga is mature enough that you can seriously do stuff with it, that that will be enough of a reason for people to consider building new code in Python.

01:03:35.400 --> 01:03:38.900
And part of that is also that it is also new projects.

01:03:38.900 --> 01:03:39.860
And this is a new library.

01:03:39.860 --> 01:03:42.600
No one is coming to this with existing code base.

01:03:42.600 --> 01:03:44.380
So I can start with the new APIs.

01:03:44.380 --> 01:03:45.840
And so I am.

01:03:45.840 --> 01:03:46.840
Yeah, that's brilliant.

01:03:46.840 --> 01:03:50.680
And on behalf of everyone, thank you for moving us all one step closer.

01:03:50.680 --> 01:03:51.260
That's great.

01:03:51.580 --> 01:03:52.920
Or how many projects do you have?

01:03:52.920 --> 01:03:53.240
15?

01:03:53.240 --> 01:03:54.880
Maybe move just 15 steps closer.

01:03:54.880 --> 01:03:55.320
I don't know.

01:03:55.320 --> 01:03:56.380
But you definitely move just closer.

01:03:56.380 --> 01:03:56.860
So thanks.

01:03:56.860 --> 01:03:58.080
All right.

01:03:58.080 --> 01:04:00.000
So that kind of more or less rounds up beware.

01:04:00.000 --> 01:04:01.880
There's a few more things on here.

01:04:01.880 --> 01:04:08.640
One of them is Python Apple support, which let me just read the description because I think it really brings home some of the power of what you have here.

01:04:08.640 --> 01:04:16.760
A meta package for building a version of Python that can be embedded into macOS, iOS, tvOS, or a watchOS project.

01:04:16.760 --> 01:04:19.760
Of course, for Python, written in Python, right?

01:04:19.760 --> 01:04:23.520
That's just so cool that all those OSes are involved in this, right?

01:04:23.520 --> 01:04:24.240
Yeah.

01:04:24.240 --> 01:04:31.240
So I mean this is kind of one of these accidents that happens because Apple is trying to make a consistent development environment for themselves.

01:04:31.240 --> 01:04:35.180
We just happen to be able to, you know, horseshoe, crowbar into place.

01:04:35.720 --> 01:04:39.780
As Apple tries to put or is pushing Swift, they have historically pushed Objective-C.

01:04:39.780 --> 01:04:41.800
Both of those are built on top of Clang.

01:04:41.800 --> 01:04:46.040
Clang is a GCC advanced in various ways.

01:04:46.040 --> 01:04:48.820
So it is, under the hood, a C compiler.

01:04:48.820 --> 01:04:51.600
The good news is that CPython is written in C.

01:04:51.600 --> 01:05:02.640
And so with the application of a few patches, you can compile the default CPython sources for any of those platforms.

01:05:02.640 --> 01:05:07.860
Now, the catch is that, and this is sort of a process of long negotiation with the CPython team,

01:05:07.980 --> 01:05:12.540
is that it's not just a matter of a patch that says, hey, look, you can build for macOS.

01:05:12.540 --> 01:05:15.960
MacOS these days only compiles for one platform.

01:05:15.960 --> 01:05:16.960
It compiles for x86.

01:05:16.960 --> 01:05:23.420
When you compile for iOS, you actually need to compile for, depending upon where exactly you're targeting,

01:05:23.960 --> 01:05:27.140
possibly as many as five or six different platforms.

01:05:27.140 --> 01:05:33.900
You need ARMv6, ARMv7, ARMv7S, i386, x86-64, ARM64.

01:05:33.900 --> 01:05:39.420
And you need to have all of those compiled and turned into what's called a fat binary.

01:05:39.420 --> 01:05:42.640
So it's like one library file that has all of those pieces.

01:05:42.640 --> 01:05:46.960
And there's a whole bunch of tooling that you need to, like, you need to build all the libraries separately

01:05:46.960 --> 01:05:52.240
and then mash them together with this thing, this tool called LiPo, to make them into one library.

01:05:52.500 --> 01:05:56.860
Now, that doesn't fit well into the CPython build chain at the moment.

01:05:56.860 --> 01:06:01.220
I've submitted a proposal for a patch that would enable you to manage that,

01:06:01.220 --> 01:06:04.200
but I don't know if that's likely to ever get merged.

01:06:04.200 --> 01:06:06.920
There's a whole bunch of sort of technical and political things that go on there.

01:06:06.920 --> 01:06:10.160
So Python Apple support is essentially just an external project that says, okay,

01:06:10.160 --> 01:06:15.020
take the CPython source code, download it for you, apply the patch that I know needs to be applied,

01:06:15.020 --> 01:06:22.120
build it, build all the dependencies, build OpenSSL, and build libbz2 and all the other pieces that need to be built.

01:06:22.120 --> 01:06:26.780
And spit out a Python.framework that works on iOS.

01:06:26.780 --> 01:06:27.400
That's great.

01:06:27.400 --> 01:06:32.240
And then the interesting thing is then, okay, well, doing that for iOS, well, you can do it for macOS as well,

01:06:32.240 --> 01:06:34.940
because that's basically just, you know, you only have to compile it for x86.

01:06:34.940 --> 01:06:39.020
tvOS is exactly the same thing, except you've only got to compile it for ARM64.

01:06:39.020 --> 01:06:43.060
And watchOS is exactly the same thing, except you've got to compile it for ARM7K.

01:06:43.540 --> 01:06:45.260
So it's the same basic infrastructure.

01:06:45.260 --> 01:06:47.860
You've just got to change the key that you're calling into.

01:06:47.860 --> 01:06:48.400
I see.

01:06:48.400 --> 01:06:50.640
Just make it a little more Apple-friendly, bundle that all together.

01:06:50.640 --> 01:06:50.880
Yeah.

01:06:50.880 --> 01:06:51.140
Yeah.

01:06:51.140 --> 01:06:52.020
Yeah, exactly.

01:06:52.020 --> 01:06:52.500
Awesome.

01:06:52.500 --> 01:07:00.400
And so one of your main goals was to build a Python toolchain that lets you write these UI apps in Android

01:07:00.400 --> 01:07:03.580
and the various Apple OSes as well as Windows.

01:07:03.580 --> 01:07:07.080
And so you have a bunch of templates as well to help people get started, right?

01:07:07.080 --> 01:07:11.700
These are cookie-cutter templates, which I haven't talked a lot about cookie-cutter, but it's a really great project.

01:07:11.700 --> 01:07:14.620
And I'm sure we'll have Audrey on the show sometime to talk about it.

01:07:14.620 --> 01:07:15.060
Yeah.

01:07:15.060 --> 01:07:18.520
Yeah, so tell us really quickly about your templates before we're out of time.

01:07:18.520 --> 01:07:19.020
Sure.

01:07:19.020 --> 01:07:24.180
So the templates are effectively saying, well, you know, okay, a Python project is, at the end of the day,

01:07:24.180 --> 01:07:27.260
a entry.py that contains print hello world.

01:07:27.260 --> 01:07:30.160
You know, it can be more than that, but that's all you have to have.

01:07:30.160 --> 01:07:34.000
But in order for them to run on iOS, you have to have a whole lot more.

01:07:35.060 --> 01:07:39.900
You have to have your Xcode project and your dependencies and your icons and your configurations and all this other stuff.

01:07:39.900 --> 01:07:43.640
But most of that information is relatively constrained.

01:07:43.640 --> 01:07:47.780
Like we know we need the name of the package, and the name of the package needs to appear here, here, here, here, and here.

01:07:47.780 --> 01:07:52.240
So the templates are basically just saying, okay, well, I know what format it needs to come out as.

01:07:52.240 --> 01:07:55.320
All I don't know is the name of the package I want to generate.

01:07:55.320 --> 01:08:00.900
So let's just leave that as a blank, generate it from template, and then you've got something you can use.

01:08:00.900 --> 01:08:08.360
And then Briefcase takes those templates and takes the support libraries and things like that, pre-compiled versions of the support libraries, and spits them out.

01:08:08.360 --> 01:08:10.400
You run Briefcase over your project.

01:08:10.400 --> 01:08:19.500
If you've got a project that has your hello world.py file, and it has a setup.py that says that's where the file is and these are the dependencies,

01:08:19.500 --> 01:08:27.240
it takes all that information, uses that to generate the template so that you can then just say, run this Xcode project, and off goes your iOS project.

01:08:27.240 --> 01:08:31.920
Or run this, generate the GTK application or generate the watchOS application.

01:08:31.920 --> 01:08:32.320
Yeah.

01:08:32.320 --> 01:08:33.340
That's excellent.

01:08:33.340 --> 01:08:34.640
Yeah.

01:08:34.640 --> 01:08:36.400
So I think your project is great.

01:08:36.400 --> 01:08:38.240
I definitely want to encourage people to check it out.

01:08:38.240 --> 01:08:41.180
We'll probably have to kind of leave it there for that one.

01:08:41.300 --> 01:08:46.020
So one thing I did notice is that you have a couple of upcoming events that you're going to be at.

01:08:46.020 --> 01:08:46.920
Were you just in Portland?

01:08:46.920 --> 01:08:49.100
I was not in Portland for PyDX, no.

01:08:49.100 --> 01:08:54.280
I was in Portland for PyCon this year, and I'll probably be back there next year at this point.

01:08:54.280 --> 01:08:54.640
All right.

01:08:54.640 --> 01:08:54.880
Yeah.

01:08:54.880 --> 01:08:57.680
I was thinking, maybe I just missed you like three days ago in PyDX.

01:08:57.680 --> 01:08:57.960
Anyway.

01:08:57.960 --> 01:08:58.860
No, no.

01:08:58.860 --> 01:08:59.580
Unfortunately not.

01:08:59.580 --> 01:08:59.900
Yeah.

01:08:59.900 --> 01:09:00.120
Okay.

01:09:00.120 --> 01:09:07.360
But so, yeah, maybe tell people about some of the upcoming events that you have that you're going to be at in case they want to meet you or some of the team members or something like that.

01:09:07.360 --> 01:09:07.880
Sure.

01:09:07.920 --> 01:09:08.180
Absolutely.

01:09:08.180 --> 01:09:16.500
So I myself will be – I'm keynoting Python Brazil on the 15th of October this year, and I'll be around for the sprints there as well.

01:09:16.500 --> 01:09:19.600
So if you're in Florianopolis, please come and see me.

01:09:19.600 --> 01:09:21.560
We're very keen to have new people involved.

01:09:21.560 --> 01:09:25.660
About two weeks after that, I'll be in Amsterdam for Django Under the Hood.

01:09:25.660 --> 01:09:32.960
So that's the Django deep dive conference that happens once a year in Amsterdam, and I'll be there for the full sprints of that as well.

01:09:33.100 --> 01:09:38.780
Probably working on Batavia and some of the more webby parts of the framework at that point.

01:09:38.780 --> 01:09:45.000
I'm also speaking at LinuxConf Australia 2016 in January next year down in Hobart.

01:09:45.000 --> 01:09:52.000
If you haven't ever been to Australia, I can highly recommend Hobart as a venue to go to and LCA as a conference.

01:09:52.000 --> 01:09:53.420
It's a great little community.

01:09:54.120 --> 01:09:56.240
It's sort of the Australian equivalent.

01:09:56.240 --> 01:09:58.560
It's like the peak open source conference.

01:09:58.560 --> 01:10:03.100
Despite the name LinuxConf AU, it is a multi-language – there are people there talking about FreeBSD.

01:10:03.100 --> 01:10:08.700
It's kind of an odd name that's kind of stuck around for historical reasons rather than being actually just about Linux.

01:10:08.700 --> 01:10:10.520
So they're the ones immediately.

01:10:10.520 --> 01:10:15.900
There are a couple of other conferences that I'm speaking at in the future, some of which I can't talk about.

01:10:15.900 --> 01:10:18.380
But what's your directories?

01:10:18.380 --> 01:10:20.880
I'm coming to a city near you.

01:10:21.080 --> 01:10:21.520
Awesome.

01:10:21.520 --> 01:10:23.240
Yeah, spreading the good word.

01:10:23.240 --> 01:10:24.060
Excellent.

01:10:24.060 --> 01:10:24.560
Indeed.

01:10:25.360 --> 01:10:32.120
I also noticed that if people need help, they want to set this up and they've got a big team and they really want to get going, that you also offer training.

01:10:32.120 --> 01:10:35.220
So people want to get a jump start, they can contact you, right?

01:10:35.220 --> 01:10:35.640
Yes.

01:10:35.640 --> 01:10:39.240
Then just maybe give a quick shout out to all the people on it if you want to just pull up the list.

01:10:39.240 --> 01:10:40.080
Yeah.

01:10:40.080 --> 01:10:45.500
So I haven't specifically got – it's not like you can come to me and say, here's my rate card for Python training or Choga training.

01:10:45.560 --> 01:10:55.260
It's more an aspirational thing about being able to fund the development of Beware and Python development on a more sustainable basis.

01:10:55.260 --> 01:10:59.660
I have been working on this as sort of a part-time volunteer capacity for the last couple of years.

01:11:00.100 --> 01:11:07.440
I've had some amazing help from Katie McLaughlin and Philip James and Chris Swenson who have done amazing work as well.

01:11:07.440 --> 01:11:09.560
But they definitely have volunteer capacity.

01:11:09.560 --> 01:11:18.440
I have recently been – started to be paid on a part-time capacity from a company called Jambon Software to do bits of Beware development.

01:11:18.440 --> 01:11:25.440
But I would like to ultimately turn this into a full-time gig for myself and a small team of crack Python developers.

01:11:25.440 --> 01:11:38.920
And also to use that as an opportunity to reach out, to get new people involved, to reach out, do diversity, to do diversity and outreach, to bring interns in, pay them for their time and actually introduce them to open source development.

01:11:39.040 --> 01:11:48.840
And once you get to give them an internship with a crack team of people at the top of their open source contribution game, let them loose on the world and see what else they can do.

01:11:48.840 --> 01:11:56.360
So, yes, training is one axis where I'm definitely – I am notionally available for hire if someone wants to do that.

01:11:56.360 --> 01:12:08.480
But I'm also open to all sorts of other options, including if you go to pyb.org, there are some options there for corporate sponsorship if you want to become a member of the project and drop some money in the tin regularly so that we can continue to do what we're doing.

01:12:08.480 --> 01:12:12.180
Because ultimately, the reason I'm doing this is because I like Python.

01:12:12.180 --> 01:12:13.360
I want to keep using Python.

01:12:13.360 --> 01:12:24.460
But I don't think we can continue to sustain large-scale Python development the way that it sort of has been on a wish and a prayer for the last 10, 15 years.

01:12:24.460 --> 01:12:34.540
Django development has not been anywhere near as fast or as motivated as it could have been if we only had a little bit more money or if the Django project had a little bit more money.

01:12:35.100 --> 01:12:45.980
And given the amount of money that is available in the Django community, the number of people who are making millions of dollars with Django, I think it's telling that we haven't been able to find a way to pay the bills a little bit more effectively.

01:12:45.980 --> 01:12:46.520
Yeah.

01:12:46.520 --> 01:12:57.520
I just want to sort of second that thought and say there are so many companies that are many, many million dollars of revenue or billions of dollars that take open source and just go, okay, great.

01:12:57.520 --> 01:12:57.940
This is free.

01:12:57.940 --> 01:12:58.740
This saves us money.

01:12:58.740 --> 01:13:01.420
There's not a lot of giving back, right?

01:13:01.480 --> 01:13:06.560
Like if they just put a small portion, a very small portion back into these projects, it would make such a difference.

01:13:06.560 --> 01:13:07.280
So, yeah.

01:13:07.280 --> 01:13:07.840
Yeah.

01:13:07.840 --> 01:13:13.580
I mean, it's like I've made the gag on Twitter a couple of times where, you know, I'm offering corporate sponsorships in Beware.

01:13:13.580 --> 01:13:18.940
And, you know, $1,000 a month, it sounds like it's a lot of money to you and me as individual developers.

01:13:18.940 --> 01:13:23.120
To a company, it's like not even – it's a rounding error on their soda budget.

01:13:23.680 --> 01:13:26.720
But that's effectively a Desi Russell.

01:13:26.720 --> 01:13:28.660
$1,000 is a Desi Russell.

01:13:28.660 --> 01:13:30.940
You can get one-tenth of me for $1,000.

01:13:30.940 --> 01:13:31.760
Yeah.

01:13:31.760 --> 01:13:35.800
The problem is I need 10 of you to agree to buy a Teddy Desi Russell and then I'm working full time.

01:13:35.800 --> 01:13:40.760
Now, there are more than 10 companies in the world who have a very vested interest in Python.

01:13:40.760 --> 01:13:42.460
I just need to work out who they are.

01:13:42.460 --> 01:13:43.200
Yeah, absolutely.

01:13:44.200 --> 01:13:49.780
Before we move on, before we sort of round up the show, there's always two questions I ask at the end.

01:13:49.780 --> 01:13:51.320
So, I'll send them to you now.

01:13:51.320 --> 01:13:56.320
So, first of all, I think you may be able to pull a few from your own project.

01:13:56.320 --> 01:13:57.840
And that's totally legit if you want to do that.

01:13:57.840 --> 01:14:01.740
But there's over 80,000 packages in PyPI.

01:14:01.740 --> 01:14:07.080
What one do you think maybe people don't know about, you want to recommend, you say, this thing's amazing, you should check it out?

01:14:07.080 --> 01:14:09.160
If I may indulge, I actually have two.

01:14:09.160 --> 01:14:09.580
Oh, you may.

01:14:09.580 --> 01:14:14.380
They are both at the – they're not my project, so I will completely be above board there.

01:14:14.380 --> 01:14:15.940
There's no nepotism at all going on here.

01:14:15.940 --> 01:14:29.400
They're both in the sort of the developer space and they're tools that I have found incredibly useful, particularly since one of the downsides to Beware being lots of little projects is that you have – the process of releasing Toga is not trivial.

01:14:29.400 --> 01:14:33.100
There's a lot of things that need to happen because there are a lot of pieces that need to be released.

01:14:33.100 --> 01:14:36.600
And each one of them has a release process, each one of which needs to be tested and all the rest.

01:14:36.600 --> 01:14:41.860
So the two tools – one is called – a tool called Check Manifest, Check-Manifest.

01:14:41.860 --> 01:14:44.140
It is a really, really boring thing.

01:14:44.140 --> 01:15:01.600
All it does is you pip install it into your project, you run Check Manifest, and it checks that your manifest.in file matches what is checked into your version control so that you don't accidentally release a package that doesn't have three files that have to be there for the source code to actually run and compile.

01:15:01.600 --> 01:15:01.940
Okay.

01:15:01.940 --> 01:15:02.520
Excellent.

01:15:02.520 --> 01:15:13.120
It is mind-numbingly simple, but the number of times I have made that mistake, it is paid for itself – it's paid for its free cost on PyPI many, many times over.

01:15:13.120 --> 01:15:13.900
Nice.

01:15:13.900 --> 01:15:15.000
All right.

01:15:15.000 --> 01:15:15.920
So that's number one.

01:15:15.920 --> 01:15:16.440
Cool.

01:15:16.440 --> 01:15:16.980
That's number one.

01:15:16.980 --> 01:15:24.060
The second one is DevPI, which is a version of the Python package index that you can run locally.

01:15:24.260 --> 01:15:30.120
So it is a fully – it follows the full PyPI protocol and all that sort of stuff.

01:15:30.120 --> 01:15:34.680
And effectively, it just lets you run a local PyPI server that you can talk to.

01:15:34.680 --> 01:15:42.460
So you can upload a package to PyPI and see if it works without actually loading it up to PyPI to see what you've broken.

01:15:42.460 --> 01:15:50.420
So you can sit there and upload the half a dozen packages that are part of Beware, realize that, oh, crap, I've forgotten the dependency here between this one and this one.

01:15:50.420 --> 01:16:01.500
And as a result, repackage Toga version 0.2.1 so that it gets the dependency right or misses the file that you forgot to run check manifest this time.

01:16:02.500 --> 01:16:11.260
And test it out in a sandbox environment rather than pushing it to PyPI where once you have uploaded Toga 0.2.1, you can't upload it again.

01:16:11.260 --> 01:16:13.780
You have to release Toga 0.2.2.

01:16:13.780 --> 01:16:17.740
So, yeah, that one has also saved my bacon on more times than I care to count.

01:16:17.740 --> 01:16:19.220
Yeah, that's a great recommendation.

01:16:19.220 --> 01:16:20.300
All right.

01:16:20.300 --> 01:16:21.120
And favorite editor?

01:16:21.120 --> 01:16:23.060
So I am a sublime text person.

01:16:23.060 --> 01:16:24.940
I like it, but I don't love it.

01:16:24.940 --> 01:16:29.040
And this is one of these areas where one of these days, Toga is going to solve this problem for me.

01:16:29.160 --> 01:16:34.640
I have an intellectual love of Emacs, but I can't bring myself to actually use it.

01:16:34.640 --> 01:16:37.900
Partially because the Lisp syntax does my head in.

01:16:37.900 --> 01:16:46.820
And secondly, because the people who developed Emacs seem to be scientifically opposed to user interfaces that make any damn sense whatsoever.

01:16:46.820 --> 01:16:53.840
Every application on the planet has decided that command save saves on a Mac box, but not on Emacs.

01:16:53.840 --> 01:16:56.780
Now, OK, yes, before the Emacs people come out of the woodwork.

01:16:56.840 --> 01:17:01.740
Yes, I know you can configure it, but it does not come out of the box usable for development.

01:17:01.740 --> 01:17:09.900
And that for me is if your tool ships in a form where it is unusable, then you have a problem.

01:17:09.900 --> 01:17:14.160
My classic one that I absolutely hate about Emacs is that, yes, you can.

01:17:14.160 --> 01:17:15.480
Emacs ships with a tutorial.

01:17:15.480 --> 01:17:16.120
That's fantastic.

01:17:16.120 --> 01:17:17.060
Let's do the tutorial.

01:17:17.060 --> 01:17:18.820
If there's something I need to know, let's do the tutorial.

01:17:18.820 --> 01:17:23.900
The first couple of pages of the tutorial teach you about the key combinations for page up and page down.

01:17:24.080 --> 01:17:26.280
I have a button on my keyboard to do that.

01:17:26.280 --> 01:17:28.420
It says page up and page down right on it, doesn't it?

01:17:28.420 --> 01:17:29.480
It says page up and page down.

01:17:29.480 --> 01:17:30.580
And they work really well.

01:17:30.580 --> 01:17:32.900
So stop trying to teach me how to use my keyboard.

01:17:32.900 --> 01:17:35.900
Actually teach me how to do the things in Emacs that are interesting.

01:17:35.900 --> 01:17:41.700
And I know there are many things in Emacs that are interesting, but I can't get there because the onboarding process is toxic.

01:17:41.700 --> 01:17:42.280
Oh, boy.

01:17:42.280 --> 01:17:45.180
You also might have a home and an end button as well.

01:17:45.780 --> 01:17:46.800
Yes, yes, exactly.

01:17:46.800 --> 01:17:52.500
And one of these days, the end goal for me, I'll be a very happy person when I've been able to build a Toga.

01:17:52.500 --> 01:17:54.860
Sublime Text is great because it's cross-platform.

01:17:54.860 --> 01:17:57.300
It's bad because there's no source code.

01:17:57.300 --> 01:17:58.220
It's not open sourced.

01:17:58.520 --> 01:18:08.360
So I want to write an open sourced programmable editor that is the analog of Emacs but programmed in Python but open source and native user interface everywhere.

01:18:08.360 --> 01:18:13.280
That also just happens to plug into all the other really useful Bware tools because I just need it to be an editor.

01:18:13.280 --> 01:18:14.780
I don't need it to be a debugger.

01:18:14.780 --> 01:18:16.440
I don't need it to be a coverage tool.

01:18:16.780 --> 01:18:21.920
I need it to edit things really well and talk out to APIs of other tools when it needs to talk to other tools.

01:18:21.920 --> 01:18:25.800
I think that's a great vision and probably a great place to leave it.

01:18:25.800 --> 01:18:28.140
So it's been really great.

01:18:28.140 --> 01:18:29.300
Is there any final call to action?

01:18:29.300 --> 01:18:32.540
Are you guys accepting contributors or anything like that?

01:18:32.540 --> 01:18:35.140
We are always actively seeking out contributors.

01:18:35.140 --> 01:18:39.680
So this is one of the things I'm moderately proud of in the way that Bware is operated.

01:18:39.680 --> 01:18:46.720
We've got an open offer to anyone of any level of experience to contribute, to be mentored through the process of contributing to Bware.

01:18:47.280 --> 01:18:49.160
And that's not just sort of idle words either.

01:18:49.160 --> 01:18:52.000
This is something that has actually been fleshed out in reality.

01:18:52.000 --> 01:19:01.220
So at PyCon US this year, we ended up filling, I think at the peak, there was something like six or seven tables full of people who were contributing to Bware.

01:19:01.220 --> 01:19:05.740
When anyone contributes to Bware, there's actually a little coin.

01:19:05.740 --> 01:19:13.080
There's a challenge coin that we've had struck thanks to originally from MaxCDN for funding but now RevSys have funded the second pressing of these coins.

01:19:14.060 --> 01:19:17.720
And essentially, as soon as you get a contribution into Bware, you get one of these coins.

01:19:17.720 --> 01:19:19.540
And you can only get it if you contribute to Bware.

01:19:19.540 --> 01:19:26.120
But we had people who literally learned to use GitHub two hours earlier who have now got commits in Bware.

01:19:26.120 --> 01:19:26.840
That's great.

01:19:26.840 --> 01:19:33.740
We have been able to mentor people with very, very little programming experience to be contributors of non-trivial features in Bware.

01:19:33.740 --> 01:19:38.340
So if you go to the Bware website, there is a link in there for how to get involved with contributing.

01:19:38.340 --> 01:19:43.220
One of the big things it shakes off is, yes, okay, this whole imposter syndrome thing, it's real.

01:19:43.220 --> 01:19:46.560
And by the way, the members of the core team have imposter syndrome as well.

01:19:47.140 --> 01:19:49.460
So, yeah, don't worry about the imposter syndrome.

01:19:49.460 --> 01:19:50.520
We will walk you through this.

01:19:50.520 --> 01:19:53.680
We want to help you become the best developer you can.

01:19:53.680 --> 01:19:55.980
And we'll mentor you through that whole process.

01:19:55.980 --> 01:19:57.060
So get in touch.

01:19:57.060 --> 01:20:00.360
And we'll be more than happy to help you get involved.

01:20:00.360 --> 01:20:01.020
All right.

01:20:01.020 --> 01:20:01.520
That's great.

01:20:01.520 --> 01:20:03.160
Russell, thanks so much for being on the show.

01:20:03.160 --> 01:20:04.840
It's been fun to talk about your project.

01:20:04.840 --> 01:20:05.940
Yeah, it's been an absolute pleasure.

01:20:05.940 --> 01:20:06.860
Thank you very much for your time.

01:20:06.860 --> 01:20:07.320
You bet.

01:20:07.320 --> 01:20:07.800
Talk to you later.

01:20:09.080 --> 01:20:11.900
This has been another episode of Talk Python To Me.

01:20:11.900 --> 01:20:15.120
Today's guest has been Russell Keith McGee.

01:20:15.120 --> 01:20:18.180
And this episode has been sponsored by Rollbar and Hired.

01:20:18.180 --> 01:20:20.000
Thank you both for supporting the show.

01:20:20.000 --> 01:20:22.840
Rollbar takes the pain out of errors.

01:20:22.840 --> 01:20:30.540
They give you the context and insight you need to quickly locate and fix errors that might have gone unnoticed until your users complain, of course.

01:20:30.540 --> 01:20:37.700
As Talk Python To Me listeners, track a ridiculous number of errors for free at rollbar.com slash Talk Python To Me.

01:20:38.580 --> 01:20:40.440
Hired wants to help you find your next big thing.

01:20:40.440 --> 01:20:48.940
Visit Hired.com slash Talk Python To Me to get five or more offers with salary and equity presented right up front and a special listener signing bonus of $2,000.

01:20:48.940 --> 01:20:51.760
Are you or a colleague trying to learn Python?

01:20:51.760 --> 01:20:56.440
Have you tried books and videos that just left you bored by covering topics point by point?

01:20:56.440 --> 01:21:05.060
Well, check out my online course, Python Jumpstart, by building 10 apps at talkpython.fm/course to experience a more engaging way to learn Python.

01:21:05.460 --> 01:21:12.380
And if you're looking for something a little more advanced, try my WritePythonic code course at talkpython.fm/Pythonic.

01:21:12.380 --> 01:21:14.860
Be sure to subscribe to the show.

01:21:14.860 --> 01:21:17.060
Open your favorite podcatcher and search for Python.

01:21:17.060 --> 01:21:18.300
We should be right at the top.

01:21:18.680 --> 01:21:27.600
You can also find the iTunes feed at /itunes, Google Play feed at /play, and direct RSS feed at /rss on talkpython.fm.

01:21:27.600 --> 01:21:32.700
Our theme music is Developers, Developers, Developers by Corey Smith, who goes by Smix.

01:21:32.700 --> 01:21:39.380
Corey just recently started selling his tracks on iTunes, so I recommend you check it out at talkpython.fm/music.

01:21:39.600 --> 01:21:44.760
You can browse his tracks he has for sale on iTunes and listen to the full-length version of the theme song.

01:21:44.760 --> 01:21:46.820
This is your host, Michael Kennedy.

01:21:46.820 --> 01:21:48.100
Thanks so much for listening.

01:21:48.100 --> 01:21:49.280
I really appreciate it.

01:21:49.280 --> 01:21:51.440
Smix, let's get out of here.

01:21:51.440 --> 01:22:12.960
Outro Music.

