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.