WEBVTT 00:00:00.001 --> 00:00:05.260 Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds. 00:00:05.260 --> 00:00:10.460 This is episode 175, recorded March 26, 2020. 00:00:10.460 --> 00:00:11.440 I'm Michael Kennedy. 00:00:11.440 --> 00:00:12.460 And I'm Brian Okken. 00:00:12.460 --> 00:00:13.640 Brian, we have a special guest. 00:00:13.640 --> 00:00:16.880 Welcome, Matt Harrison. How are you doing, man? Glad to have you here. 00:00:16.880 --> 00:00:19.540 Good. Good. Thanks for coming. Come on. 00:00:19.540 --> 00:00:22.140 Yeah. It's always nice to have you on the show. 00:00:22.140 --> 00:00:25.840 Before we get into it, let me just tell you this episode is sponsored by Datadog. 00:00:25.840 --> 00:00:27.800 Check them out at pythonbytes.fm. 00:00:28.460 --> 00:00:30.480 Datadog. I'll tell you more stuff about them later. 00:00:30.480 --> 00:00:33.200 First, I want to just throw this out to both of you guys. 00:00:33.200 --> 00:00:39.380 The world is, I don't know, is it turned upside down or is it locked down or what has gone on with the world? It's crazy. 00:00:39.380 --> 00:00:43.500 We're kind of software people, and I know we're all kind of in different boats. 00:00:43.500 --> 00:00:46.520 I am definitely grateful that I'm a software person. 00:00:46.520 --> 00:00:56.600 I have a lot of friends that are not, that are in the retail industry or the selling stuff to people sort of industry or self-employed. 00:00:56.740 --> 00:00:58.680 And those people, they're really hurting. 00:00:58.680 --> 00:01:05.820 I've got a lot of people I know that if they're self-employed, you don't qualify for unemployment insurance and stuff. 00:01:05.820 --> 00:01:07.180 So there's a lot of people hurting. 00:01:07.180 --> 00:01:08.500 How are you guys? 00:01:08.500 --> 00:01:09.000 It's crazy. 00:01:09.000 --> 00:01:09.600 Yeah. 00:01:09.600 --> 00:01:10.300 Matt, how about you? 00:01:10.480 --> 00:01:15.980 I just found out this morning that my largest client just dropped all my trainings for the rest of the year. 00:01:15.980 --> 00:01:19.520 That's not your favorite phone call or email to receive, is it? 00:01:19.520 --> 00:01:26.720 Not the best news, but the thought that I have on that is like past couple of years have been very good, right? 00:01:26.800 --> 00:01:29.760 And people have said like the bubble will burst. 00:01:29.760 --> 00:01:36.600 And I don't know that we thought that a virus would do this, but I mean, it looks like winter came for better, for worse. 00:01:36.600 --> 00:01:38.860 And so people are going to have to adapt. 00:01:39.480 --> 00:01:43.440 And now if you can weather the storm, it's going to be tough though. 00:01:43.440 --> 00:01:50.100 I mean, I was even talking with some friends who are in the medical industry and they're like, we're worried about our jobs, right? 00:01:50.100 --> 00:01:53.260 And these are like doctors and people who work at the hospital. 00:01:53.260 --> 00:01:56.880 So it's interesting to see what's going on. 00:01:57.100 --> 00:02:01.240 And I've worked from home for the good portion of the last 15 years. 00:02:01.240 --> 00:02:07.500 And right now it's scary to see that there's a lot of upheaval and we'll see what happens. 00:02:07.500 --> 00:02:08.960 How are things going for you, Michael? 00:02:08.960 --> 00:02:10.320 Well, you know what? 00:02:10.320 --> 00:02:12.020 It's really interesting. 00:02:12.020 --> 00:02:23.040 If you'd asked me this question like six years ago when I was doing mostly in-person training, it would have been like somebody just cut the light switch off and said, you know, we're all leaving. 00:02:23.040 --> 00:02:23.600 Yeah. 00:02:23.600 --> 00:02:24.960 Lock the door on your way out, right? 00:02:25.000 --> 00:02:27.840 It would have been purely traumatic. 00:02:27.840 --> 00:02:31.760 Luckily now, like online courses are great still. 00:02:31.760 --> 00:02:33.540 Podcasting is great. 00:02:33.540 --> 00:02:39.680 Like what's ironic is my work life is literally unchanged, but the rest of my life is scrambled, right? 00:02:39.680 --> 00:02:42.540 Like my daughter is home from school because they closed school. 00:02:42.540 --> 00:02:44.240 Like Oregon's now on full lockdown. 00:02:44.240 --> 00:02:46.280 Like it's hard to go out to dinner. 00:02:46.280 --> 00:02:50.720 So everything is changed in some ways, but ironically, not my work life really. 00:02:50.720 --> 00:02:53.280 I'm sure it'll have some effect eventually, but nothing immediate. 00:02:53.800 --> 00:02:55.520 I guess one more thing before we move off. 00:02:55.520 --> 00:02:56.100 I'm just curious. 00:02:56.100 --> 00:02:57.660 Like what are your plans around training? 00:02:57.660 --> 00:03:01.980 Like are you going to be teaching over Zoom or is it just focus on other stuff until it comes back? 00:03:01.980 --> 00:03:03.720 Yeah, I think both of that. 00:03:03.720 --> 00:03:09.760 I do have some clients who are moving to virtual training and I already do a bunch of virtual training anyway. 00:03:09.760 --> 00:03:23.840 So, I mean, it's sad that some of them aren't able to or can't due to circumstances or whatnot, but try and see if other people want virtual training and just work on other products that people are interested in as well. 00:03:23.840 --> 00:03:24.940 Yeah, absolutely. 00:03:24.940 --> 00:03:26.640 Well, hang tough. 00:03:26.640 --> 00:03:33.960 You guys and everyone out there, it's going to be a wild ride and hopefully the software side of the world is a little bit less bumpy, but it's still, it's crazy. 00:03:34.600 --> 00:03:38.360 All right, well, let's talk a little bit about the future, Brian. 00:03:38.360 --> 00:03:44.020 Like we can't predict when the COVID stuff is going to be better, but you could probably predict some stuff about the Python in the future. 00:03:44.260 --> 00:03:48.920 I'm just still getting excited, used to being able to have Python 3.8 everywhere. 00:03:48.920 --> 00:03:55.160 And, but we've got Python 3.9 right around the corner and in October is the scheduled release. 00:03:55.160 --> 00:04:00.480 I don't know if that'll change due to the virus or not, but that's where it is. 00:04:00.480 --> 00:04:09.080 And one of the cool things that I noticed from a blog article is that there's union operators coming for dictionaries in Python 3.9. 00:04:09.080 --> 00:04:11.740 And this is a PEP 584. 00:04:11.740 --> 00:04:19.520 And there's a article called a dictionary merging and updating in Python 3.9 by not, I think young qui. 00:04:20.140 --> 00:04:22.560 And there's a couple new operators. 00:04:22.560 --> 00:04:28.540 One of them, it's just the bar or the bar equals or the pipe operator, whatever. 00:04:28.540 --> 00:04:32.680 It looks normal for if you're used to, I guess that's the math or operator. 00:04:32.680 --> 00:04:36.200 It's like a bitwise or, yeah. 00:04:36.200 --> 00:04:37.680 I'm kind of excited about it. 00:04:37.680 --> 00:04:45.460 So you can combine two dictionaries by just doing like a dictionary one or dictionary two or something like that. 00:04:45.660 --> 00:04:51.860 And then the equivalent assignment operator as well, which is really an update operator and a merge. 00:04:51.860 --> 00:04:59.160 The article spent a little bit of time talking about the other older methods that you can use to combine dictionaries now. 00:04:59.160 --> 00:05:02.320 And I know people have covered those in a lot of places. 00:05:02.320 --> 00:05:05.360 The one thing, the article actually spent a lot of time on it. 00:05:05.360 --> 00:05:10.940 And I just think it's something to watch out for and be aware of is when you're combining dictionaries, usually the, 00:05:11.500 --> 00:05:17.840 if there's overlapping values, like if there's a value with the same key in both dictionaries, 00:05:17.840 --> 00:05:20.380 you'll get the second one will take precedence. 00:05:20.380 --> 00:05:22.420 It's just something to be aware of. 00:05:22.420 --> 00:05:22.740 Yeah. 00:05:22.740 --> 00:05:22.980 Yeah. 00:05:22.980 --> 00:05:26.160 And that's the way it works in the, like the current operators as well, right? 00:05:26.160 --> 00:05:29.180 The star star sort of combine stuff and whatnot. 00:05:29.180 --> 00:05:29.600 Yeah. 00:05:29.600 --> 00:05:32.460 As long as you're aware of it, it's good to know, but this is clean. 00:05:32.460 --> 00:05:36.760 It's actually something that now that I see it, I'm surprised that we don't already have a, 00:05:36.760 --> 00:05:41.820 an operator already in to combine dictionaries because it's something I kind of do a lot of. 00:05:41.820 --> 00:05:42.100 So. 00:05:42.100 --> 00:05:42.400 Yeah. 00:05:42.400 --> 00:05:47.120 And if you look at the syntax there for the pipe, I mean, the pipe is already in the set operator. 00:05:47.120 --> 00:05:53.960 And prior to sets existing, when people used to use dictionaries to emulate sets, I mean, 00:05:53.960 --> 00:05:57.780 they wouldn't do the or operator, but, but it's, it's interesting that it's sort of coming around 00:05:57.780 --> 00:05:59.960 circle now that we originally had dictionaries. 00:05:59.960 --> 00:06:04.080 People started using dictionaries as a simple replacement for sets. 00:06:04.180 --> 00:06:08.540 And we got sets, which had the pipe operator and now the pipe is coming back to the dictionary. 00:06:08.540 --> 00:06:09.340 Interesting. 00:06:09.340 --> 00:06:11.660 So why do you guys think they didn't use plus? 00:06:11.660 --> 00:06:15.660 Like you want to combine two things like two lists. 00:06:15.660 --> 00:06:17.440 You don't use a pipe to put them together. 00:06:17.440 --> 00:06:18.780 You use a plus for strings. 00:06:18.780 --> 00:06:19.640 Use a plus. 00:06:19.640 --> 00:06:20.940 Plus already existed. 00:06:20.940 --> 00:06:25.060 I think it's because of the union operator already being used for sets. 00:06:25.060 --> 00:06:25.440 Yeah. 00:06:25.440 --> 00:06:26.000 You think so? 00:06:26.000 --> 00:06:26.680 Yeah. 00:06:26.680 --> 00:06:26.940 All right. 00:06:26.940 --> 00:06:27.140 Cool. 00:06:27.140 --> 00:06:32.780 Well, yeah, it's good to see some nice shorthands coming there, but if we can have a pipe equals 00:06:32.780 --> 00:06:35.000 operator, give me the plus plus. 00:06:35.000 --> 00:06:35.360 Come on. 00:06:35.360 --> 00:06:36.320 I just want the plus plus. 00:06:36.320 --> 00:06:39.180 I want the double pipe. 00:06:39.180 --> 00:06:40.660 Yeah. 00:06:40.660 --> 00:06:41.280 Double pipe. 00:06:41.280 --> 00:06:42.360 What does that mean? 00:06:42.360 --> 00:06:44.360 All right, Matt, you got the next one. 00:06:44.360 --> 00:06:48.620 This one is short and sweet, but it looks pretty cool if you got the use case for it. 00:06:48.620 --> 00:06:49.220 Yeah. 00:06:49.220 --> 00:06:49.620 Yeah. 00:06:49.620 --> 00:06:59.280 So there is this super string library, which is a new library that's a replacement of, well, 00:06:59.280 --> 00:07:02.560 not a replacement, but it's a new string library for holding sequences of characters. 00:07:02.560 --> 00:07:07.700 It's built on this rope data structure, and apparently it's pretty optimized. 00:07:07.960 --> 00:07:15.740 It uses a 20th the amount of memory and a fifth the speed, so operates five times faster for 00:07:15.740 --> 00:07:16.740 a lot of operations. 00:07:16.740 --> 00:07:23.160 I think this could be super useful for people who are manipulating data. 00:07:23.520 --> 00:07:28.860 So it'd be interesting to look at if the people who are doing NLP could take advantage of this. 00:07:28.860 --> 00:07:36.440 Definitely the memory constraints, using a 20th the amount of memory would be awesome, even 00:07:36.440 --> 00:07:41.100 in places like Pandas, NLP as well, natural language processing. 00:07:41.600 --> 00:07:44.280 The API is pretty basic right now. 00:07:44.280 --> 00:07:49.560 It's got concatenation, getting to the length, doing some indexing and slicing and stripping 00:07:49.560 --> 00:07:50.920 and uppercasing and lowercasing. 00:07:50.920 --> 00:07:56.320 So that could be a good, with the speed and memory performance they're showing, that could 00:07:56.320 --> 00:08:00.040 be a good enough limited set of capabilities. 00:08:00.040 --> 00:08:04.020 Sort of for me, the elephant in the room is the F string. 00:08:04.020 --> 00:08:06.840 For me, that's the best feature of Python 3. 00:08:06.840 --> 00:08:08.100 I know. 00:08:09.140 --> 00:08:11.960 Implement that, and let's use it. 00:08:11.960 --> 00:08:17.240 Yeah, the other thing that's missing is negative indexes, but that can't be hard to add, honestly. 00:08:17.240 --> 00:08:21.120 Maybe it's hard to add quickly, but it can't be hard to add negative indexing. 00:08:21.120 --> 00:08:22.500 That's a good point. 00:08:22.500 --> 00:08:25.720 I mean, they don't make any reference to whether they support Unicode. 00:08:25.720 --> 00:08:28.420 So that's, I guess, another question, right? 00:08:28.420 --> 00:08:34.300 If they do support the Unicode capabilities, the Python supporting, I mean, Unicode can make 00:08:34.300 --> 00:08:38.920 indexing a little bit more complicated, but that might be what's going on there. 00:08:38.920 --> 00:08:43.360 But this will be interesting to watch, interesting library to watch. 00:08:43.360 --> 00:08:44.080 What do you think, Brian? 00:08:44.080 --> 00:08:50.660 I'm just not in a place where the strings are the memory or the bottleneck in any of my applications. 00:08:50.660 --> 00:08:52.280 Yeah. 00:08:52.280 --> 00:08:55.780 Yeah, but to give you an example, like a real world example, like I've been playing with 00:08:55.780 --> 00:09:00.720 some Markdown stuff for like the sort of CMS side of things that I'm writing in Markdown. 00:09:00.720 --> 00:09:07.020 And if you've got something that's maybe 10, 20 pages of Markdown, it takes half a second 00:09:07.020 --> 00:09:10.340 to convert that from Markdown to HTML. 00:09:10.340 --> 00:09:15.080 I don't know how much of that is like the actual string juggling and how much of that is just 00:09:15.080 --> 00:09:16.840 converting it to Markdown is slow. 00:09:16.980 --> 00:09:22.080 But that's a non-trivial amount of processing that's like sort of around the corner. 00:09:22.080 --> 00:09:23.380 I mean, you would never do it manually. 00:09:23.380 --> 00:09:24.620 You would use a library, right? 00:09:24.620 --> 00:09:26.940 But still, you can benefit from that. 00:09:26.940 --> 00:09:30.520 On that, you can think of all the people who are using static libraries, right? 00:09:30.520 --> 00:09:35.080 For web pages who, you know, once you get, they all complain about once you get X number 00:09:35.080 --> 00:09:37.000 of pages in there, they start getting slow. 00:09:37.000 --> 00:09:41.520 And the rebuild takes five seconds instead of a half a second or whatever, right? 00:09:41.620 --> 00:09:44.680 And so something like this could help there as well. 00:09:44.680 --> 00:09:45.180 Right. 00:09:45.180 --> 00:09:45.700 Theoretically. 00:09:45.700 --> 00:09:49.980 So this is not a super popular library, but I'm glad you put it on here because I think 00:09:49.980 --> 00:09:50.520 it's pretty cool. 00:09:50.520 --> 00:09:51.880 I guess two thoughts. 00:09:51.880 --> 00:09:58.480 One, it'd be interesting to look at what they're doing and if there's any easy low-hanging fruit 00:09:58.480 --> 00:10:02.000 to bring back to CPython because it would be better if just Python strings were faster. 00:10:02.000 --> 00:10:03.140 And they're like, why would you make this? 00:10:03.140 --> 00:10:03.900 It's the same speed. 00:10:03.900 --> 00:10:04.740 You know what I mean? 00:10:04.740 --> 00:10:08.180 Then the other, Brian, you may have noticed, there's no tests. 00:10:08.180 --> 00:10:10.640 Yeah, it looks like it's recent. 00:10:10.980 --> 00:10:14.520 It's like, I don't know if it's even been around for more than a week. 00:10:14.520 --> 00:10:16.200 Yeah, I think it's pretty new. 00:10:16.200 --> 00:10:18.540 So if somebody's like, oh, this is cool, let me try it out. 00:10:18.540 --> 00:10:22.660 Like maybe a way you could participate is like write some tests just to verify things, right? 00:10:22.660 --> 00:10:23.840 But yeah, pretty cool. 00:10:23.840 --> 00:10:24.820 It's just imaginary. 00:10:24.820 --> 00:10:27.860 If there's no test, it's like no picture, no proof, man. 00:10:27.860 --> 00:10:33.680 If it continuously deployed in the woods and there were no tests to hear it, did it actually 00:10:33.680 --> 00:10:33.940 happen? 00:10:33.940 --> 00:10:34.400 Something like that? 00:10:34.400 --> 00:10:35.720 Yeah, yeah, exactly. 00:10:35.720 --> 00:10:36.480 Sure. 00:10:36.480 --> 00:10:39.000 That's the saying, I think, the historical version. 00:10:39.740 --> 00:10:45.760 I thought your new testing strategy is if it doesn't have tests and you don't commit 00:10:45.760 --> 00:10:46.000 it. 00:10:46.000 --> 00:10:47.620 Didn't you say you're using something like that? 00:10:47.620 --> 00:10:50.400 Yeah, that's good. 00:10:50.400 --> 00:10:52.060 Yeah, that's a good way for sure. 00:10:52.060 --> 00:10:52.760 All right. 00:10:52.760 --> 00:10:56.260 So this next one is going to affect everybody who works with Python. 00:10:56.260 --> 00:10:57.500 This is a big deal. 00:10:58.200 --> 00:11:00.840 Hopefully it's not a bumpy deal, but it's a big deal. 00:11:00.840 --> 00:11:08.480 So the Python Packaging Authority folks, the PSF subgroup, they recently got funding to 00:11:08.480 --> 00:11:10.980 hire some developers to make pip better. 00:11:10.980 --> 00:11:12.840 So pip is awesome. 00:11:12.840 --> 00:11:14.020 We all pip things. 00:11:14.020 --> 00:11:18.680 And even if you don't pip things, if you pip them or you poetry them, you really pip them 00:11:18.680 --> 00:11:19.480 down below, right? 00:11:19.480 --> 00:11:22.520 So they got a bunch of funding to make that better. 00:11:22.520 --> 00:11:27.340 And one of the challenges, one of the first challenges that they're tackling is that pip 00:11:27.340 --> 00:11:32.140 will, it's not, it doesn't take into account all the stuff you're trying to do. 00:11:32.140 --> 00:11:34.840 It just says, I see a requirements file. 00:11:34.840 --> 00:11:37.520 Let me just go from top to bottom, just start hitting it, right? 00:11:37.520 --> 00:11:38.880 Install the first one. 00:11:38.880 --> 00:11:39.560 Install the second one. 00:11:39.660 --> 00:11:43.900 So they're rolling out a new pip resolver at the end of the year. 00:11:43.900 --> 00:11:45.080 That's pretty cool, huh? 00:11:45.080 --> 00:11:45.420 Yeah. 00:11:45.420 --> 00:11:46.460 This is neat. 00:11:46.460 --> 00:11:46.700 Yeah. 00:11:46.700 --> 00:11:51.680 So the idea is basically, it's going to go and it's going to look at the dependencies of 00:11:51.680 --> 00:11:56.480 the various packages and try to install something that is consistent across all of them. 00:11:56.480 --> 00:12:02.380 Like maybe the first package in your requirements files requires, I don't know, docutils 16. 00:12:02.380 --> 00:12:05.680 And the second one requires docutils 15. 00:12:05.680 --> 00:12:09.020 Or maybe the first one doesn't even specify and 16 is just the latest. 00:12:09.020 --> 00:12:13.200 If you pip install -r that you're going to get 16 and then it's going to complain that 00:12:13.200 --> 00:12:14.580 you have 16 and not 15. 00:12:14.580 --> 00:12:15.180 You know what I mean? 00:12:15.180 --> 00:12:20.180 It's like, it just doesn't even factor in the larger system that these two things have 00:12:20.180 --> 00:12:20.620 to coexist. 00:12:20.620 --> 00:12:22.540 So that's one of the things they're working on. 00:12:22.540 --> 00:12:27.840 So to reduce inconsistency, it'll no longer install a combination of packages that's mutually 00:12:27.840 --> 00:12:30.720 inconsistent and it will be no pushover. 00:12:30.720 --> 00:12:31.920 It can be strict. 00:12:31.920 --> 00:12:38.820 If you ask it to install two packages with incompatible requirements, it will say no. 00:12:38.820 --> 00:12:39.900 It will not do it. 00:12:39.900 --> 00:12:40.120 Yeah. 00:12:40.120 --> 00:12:41.900 And then it just doesn't install anything, I think. 00:12:41.900 --> 00:12:42.240 Yeah. 00:12:42.240 --> 00:12:42.580 Yeah. 00:12:42.580 --> 00:12:43.940 It just says, no, I can't install it. 00:12:43.940 --> 00:12:46.540 That might cause some problems, right? 00:12:46.540 --> 00:12:47.600 Yeah, it might. 00:12:47.600 --> 00:12:52.420 Or make people's processes work differently. 00:12:53.000 --> 00:13:00.500 Because I mean, right now I know there's a bunch of library top of each other and I can sort 00:13:00.500 --> 00:13:02.680 of just install them over on top of it. 00:13:02.680 --> 00:13:07.860 I have my libraries and some of them sort of work and some of it doesn't refuse to install 00:13:07.860 --> 00:13:08.080 them. 00:13:08.080 --> 00:13:12.460 So this might be a speed bump in the road for a lot of people. 00:13:12.940 --> 00:13:18.940 And maybe in the end it works out better, but might cause some consternation in the short 00:13:18.940 --> 00:13:19.240 term. 00:13:19.240 --> 00:13:21.300 Yeah, that was my first thought exactly. 00:13:21.300 --> 00:13:24.580 It's like, oh, there's going to be a bunch of stuff that just won't install anymore. 00:13:24.580 --> 00:13:25.340 Yeah. 00:13:25.340 --> 00:13:29.960 Maybe a library itself can't install because two of its base libraries dependencies like 00:13:29.960 --> 00:13:31.160 themselves are inconsistent. 00:13:31.160 --> 00:13:32.620 Well, how are they working now then? 00:13:32.620 --> 00:13:34.300 You just get a warning and it just still works. 00:13:34.300 --> 00:13:37.700 It's not that they're necessarily truly inconsistent. 00:13:38.020 --> 00:13:41.480 One says, I require library less than equal to this version. 00:13:41.480 --> 00:13:44.340 Another one says, I require library greater than equal to that version. 00:13:44.340 --> 00:13:49.600 That doesn't necessarily mean the one that requires the lower one wouldn't work with the 00:13:49.600 --> 00:13:50.040 newer one. 00:13:50.040 --> 00:13:52.060 It's just that's what the requirements state. 00:13:52.060 --> 00:13:52.840 You know what I mean? 00:13:52.840 --> 00:13:59.300 Like, for example, Boto3, which is the Python 3 library if we're talking to AWS and its underlying 00:13:59.300 --> 00:14:06.340 library, BotoCore, at one point we're having different dependency, like inconsistent dependency 00:14:06.340 --> 00:14:10.580 statements or something weird like that that I was running into. 00:14:10.580 --> 00:14:11.980 But it didn't matter. 00:14:11.980 --> 00:14:12.520 It still ran. 00:14:12.520 --> 00:14:14.300 I'm just like, oh, I better run the unit test. 00:14:14.300 --> 00:14:15.620 It says these aren't going to work together. 00:14:15.620 --> 00:14:19.500 Let's see if they, you know, like maybe there's some corner of that thing that doesn't work, 00:14:19.500 --> 00:14:20.440 but I don't use that corner. 00:14:20.440 --> 00:14:21.500 So like, I don't care. 00:14:21.500 --> 00:14:22.140 Yeah. 00:14:22.140 --> 00:14:27.320 Or you have like in the machine learning side, you have like this library depends on some 00:14:27.320 --> 00:14:29.980 old version of TensorFlow, but it doesn't. 00:14:29.980 --> 00:14:31.340 You're not using TensorFlow. 00:14:31.580 --> 00:14:36.700 You're using some utility library in it, but it also has support for TensorFlow, but you're 00:14:36.700 --> 00:14:37.320 not using it. 00:14:37.320 --> 00:14:42.060 So if you had a different version of TensorFlow on it, it wouldn't really affect you because 00:14:42.060 --> 00:14:43.720 you weren't using that portion of it. 00:14:43.720 --> 00:14:44.640 Right. 00:14:44.640 --> 00:14:47.140 But it sounds like pip will say, no, I can't install these things. 00:14:47.140 --> 00:14:50.980 They make statements about two things that they can't coexist. 00:14:50.980 --> 00:14:52.980 But you're like, I don't really care that they're working. 00:14:52.980 --> 00:14:53.620 You know what I mean? 00:14:53.620 --> 00:14:55.340 So I think this is good. 00:14:55.340 --> 00:14:56.720 I think it makes things more predictable. 00:14:56.720 --> 00:14:58.220 But you're right, Matt. 00:14:58.220 --> 00:15:01.040 It's definitely going to cause some challenges. 00:15:01.040 --> 00:15:06.340 And maybe it'll get people to update things like the base library statements that they 00:15:06.340 --> 00:15:08.120 depend upon more carefully. 00:15:08.120 --> 00:15:09.100 Yeah. 00:15:09.100 --> 00:15:14.500 One of the things I'd like to see for talking about pip is that I'd really like to see Python 00:15:14.500 --> 00:15:22.500 come out with dot releases that if there's a new version of pip that all the latest versions 00:15:22.500 --> 00:15:24.940 of Python have the latest version of Pip. 00:15:24.940 --> 00:15:30.140 I'm just really tired of installing Python places and immediately having pip out of date. 00:15:30.140 --> 00:15:30.380 Yeah. 00:15:30.380 --> 00:15:35.140 I actually have an alias that when I create a virtual environment, then immediately does 00:15:35.140 --> 00:15:39.040 a pip dash install --upgrade pip and set up tools. 00:15:39.040 --> 00:15:40.940 Because why doesn't it just do that for me? 00:15:40.940 --> 00:15:41.160 Yeah. 00:15:41.160 --> 00:15:41.680 Anyway. 00:15:41.680 --> 00:15:46.280 Can I just update the top level one so that all my new virtual environments get the newest 00:15:46.280 --> 00:15:46.580 one? 00:15:46.580 --> 00:15:46.960 Yeah. 00:15:46.960 --> 00:15:47.440 Anyway. 00:15:47.440 --> 00:15:48.080 This is coming. 00:15:48.080 --> 00:15:49.000 They blogged about it. 00:15:49.000 --> 00:15:50.860 I linked to the blog post from the PSF. 00:15:50.860 --> 00:15:55.860 They said there's a couple of things you can do to help first and most fundamentally help 00:15:55.860 --> 00:15:58.020 them understand how you're using Pip. 00:15:58.160 --> 00:16:00.360 They have some user experience research going on. 00:16:00.360 --> 00:16:01.920 There's a link to go do part of that. 00:16:01.920 --> 00:16:05.420 You can check right now if this is going to be a problem for you. 00:16:05.420 --> 00:16:09.040 Go to your project, your virtual environment, activate it and type pip check. 00:16:09.040 --> 00:16:11.940 And it will tell you if you are in this inconsistent state. 00:16:11.940 --> 00:16:14.840 I had one website that was, a couple that weren't. 00:16:14.840 --> 00:16:17.960 I hacked around until I fixed them up and everything was good. 00:16:17.960 --> 00:16:19.900 Make sure you test the new version of Pip. 00:16:19.900 --> 00:16:21.260 It'll probably be out in May. 00:16:21.260 --> 00:16:22.220 Help spread the word. 00:16:22.220 --> 00:16:23.680 All three of us are doing that. 00:16:23.680 --> 00:16:23.980 Ta-da. 00:16:24.460 --> 00:16:24.760 Awesome. 00:16:24.760 --> 00:16:29.960 And if you develop a tool like Poetry or something that lives on top of this, make 00:16:29.960 --> 00:16:33.620 sure that you test integration with the thing coming out in beta in May. 00:16:33.620 --> 00:16:34.680 All right. 00:16:34.680 --> 00:16:38.700 Really quickly before we move on, let me tell you all about Datadog. 00:16:38.700 --> 00:16:41.880 This episode is brought to them, brought to you by them. 00:16:41.880 --> 00:16:43.480 So let me ask you a question. 00:16:43.480 --> 00:16:46.120 Do you have an app in production that's slower than you'd like? 00:16:46.360 --> 00:16:47.920 Is its performance all over the place? 00:16:47.920 --> 00:16:49.660 Maybe fast, sometimes slow, others? 00:16:49.660 --> 00:16:51.340 Here's the important question. 00:16:51.340 --> 00:16:54.220 Do you know why it's slow or inconsistent? 00:16:54.220 --> 00:16:55.860 With Datadog, you will. 00:16:55.860 --> 00:16:59.220 You can troubleshoot your app's performance with Datadog's end-to-end tracing. 00:16:59.220 --> 00:17:04.240 Use the detailed frame graphs to identify bottlenecks and latency in that finicky app of yours. 00:17:04.240 --> 00:17:07.480 Be the hero that got the app back on track at your company. 00:17:07.480 --> 00:17:11.140 Get started with a free trial today at pythonbytes.fm/Datadog. 00:17:11.140 --> 00:17:12.520 Use a cool product. 00:17:12.520 --> 00:17:13.680 Help support the show. 00:17:14.180 --> 00:17:19.940 Matt, I think this next topic you got here, this pretty much is on everyone's mind right now. 00:17:19.940 --> 00:17:23.120 And maybe you're trying to not think about it, but there's some useful stuff going on here. 00:17:23.120 --> 00:17:24.080 Yeah. 00:17:24.080 --> 00:17:31.460 Just with the whole coronavirus, COVID-19, I've been thinking, you know, what can I do as an 00:17:31.460 --> 00:17:32.520 individual to help? 00:17:32.520 --> 00:17:37.080 And I think a lot of people are trying to flatten the curve or limit the growth. 00:17:37.080 --> 00:17:41.760 And I think a lot of people, at least in our community, understand the importance of that, 00:17:41.860 --> 00:17:45.000 but maybe not the general populace as well. 00:17:45.000 --> 00:17:50.480 So one of the things that I thought that I could do is just, you know, spread among my local community 00:17:50.480 --> 00:17:52.480 through my local social media. 00:17:52.480 --> 00:17:54.900 Like, what is the growth locally here where I'm based? 00:17:54.900 --> 00:17:57.140 I'm based out of Salt Lake in Utah. 00:17:57.720 --> 00:18:01.400 And so I had a problem actually getting the data. 00:18:01.400 --> 00:18:06.000 I mean, there aren't any repositories that have local Utah data. 00:18:06.000 --> 00:18:13.380 The local Department of Health is reporting on it, but their data, there's not a source of data that you can cleanly pull. 00:18:13.380 --> 00:18:17.020 So I've been pulling, making my own data source. 00:18:17.020 --> 00:18:27.060 And then I've been just posting those on Twitter and LinkedIn just with my local data to sort of track what that growth looks like and sort of put that in people's minds to sort of, 00:18:27.060 --> 00:18:31.020 hey, think about what's going on locally and see what changes you can make. 00:18:31.420 --> 00:18:37.960 And I did some basic modeling to sort of predict what's going on because I've been reading other people's models about, you know, 00:18:37.960 --> 00:18:42.180 this is an exponential growth weight, blah, blah, blah, what that looks like. 00:18:42.240 --> 00:18:45.040 And so I did some basic models using machine learning. 00:18:45.040 --> 00:18:53.780 But it's also in the Twittersphere and elsewhere, people are saying all these data scientists are coming and just throwing machine learning at this, 00:18:53.780 --> 00:18:54.960 and that's not the right thing to do. 00:18:54.960 --> 00:19:00.280 The right thing to do is read the literature and see, you know, what epidemiologists and others have done. 00:19:00.280 --> 00:19:05.380 And so I just want to point to some things that might be interesting. 00:19:05.380 --> 00:19:10.520 I've got a link to a Kaggle project that shows making some basic machine learning models, 00:19:10.620 --> 00:19:17.140 but it also points to a library that's found in SciPy that probably a lot of people don't know about. 00:19:17.140 --> 00:19:18.780 I know about it because I teach about it. 00:19:18.780 --> 00:19:26.020 And that's in SciPy, there's an ODEINT function, which is a solver for what's called ordinary differential equations. 00:19:26.020 --> 00:19:30.720 And so this is probably a math class that you may have taken in college. 00:19:30.720 --> 00:19:36.940 I took one in college, and it was purely theoretical, and I've basically forgot everything since then. 00:19:37.140 --> 00:19:40.220 But there's what's called an SIR model. 00:19:40.220 --> 00:19:50.100 And that stands for you have people who are susceptible to being sick, you have people who are infected, and you have people who are recovered. 00:19:50.100 --> 00:19:56.160 And so typically, these flatten the curves are looking at the infected part, the infected growth of that. 00:19:56.160 --> 00:20:00.540 But there's a relationship between all these three different groups, and they're more complex models. 00:20:00.540 --> 00:20:11.860 But if you use ordinary differential equations, that is the tool that epidemiologists and statisticians use to plot these and determine what's going on here, 00:20:11.860 --> 00:20:18.380 rather than just throwing it at linear regression or trying to do a machine learning model that way. 00:20:18.380 --> 00:20:24.440 So I just want to point people at this Kaggle project has got an example of doing this SIR model. 00:20:24.440 --> 00:20:27.620 It's also got some basic machine learning models as well. 00:20:27.620 --> 00:20:35.120 But be aware that, you know, a lot of these things that we learn about, that in theory, you think, oh, that doesn't make sense. 00:20:35.120 --> 00:20:44.260 This is actually a case where ordinary differential equations are the right or one of the right tools to look at this data and understand what's going on there. 00:20:44.780 --> 00:20:45.680 Yeah, this is a cool project. 00:20:45.680 --> 00:20:47.260 Yeah, definitely a cool project. 00:20:47.260 --> 00:20:51.980 I'm sure there's a ton of data science going on around all of this. 00:20:51.980 --> 00:20:53.920 There's a lot of data. 00:20:53.920 --> 00:20:57.180 It's coming from different places, like live dashboards and stuff. 00:20:57.180 --> 00:20:59.160 And I think this is really cool. 00:20:59.160 --> 00:21:00.560 I didn't know about the SIR model. 00:21:00.560 --> 00:21:01.080 That's cool. 00:21:01.080 --> 00:21:08.580 There are a bunch of other Python libraries as well that epidemiologists have created and whatnot that implement these SIR models. 00:21:08.580 --> 00:21:10.660 And there's another one, S-I-E-R. 00:21:11.300 --> 00:21:14.800 And so check those out if you're interested in sort of digging with the data. 00:21:14.800 --> 00:21:18.540 But a plea to people to think about what you can do for your local community. 00:21:18.540 --> 00:21:24.180 You know, if you've got skills to help out, what can you do locally to help out and help others? 00:21:24.180 --> 00:21:25.600 Yeah, absolutely. 00:21:26.180 --> 00:21:34.920 Also, random side point here, looking through this code on Kaggle, I'd never realized that you could unpack a tuple in a nested way. 00:21:34.920 --> 00:21:39.480 Like thing, comma, tuple unpacking thing, right? 00:21:39.480 --> 00:21:41.900 So where you can layer these in deeper and deeper. 00:21:41.900 --> 00:21:43.080 That's pretty awesome, actually. 00:21:43.080 --> 00:21:43.740 Yeah. 00:21:43.740 --> 00:21:45.560 Your data structure is nested, right? 00:21:45.960 --> 00:21:50.060 Not necessarily going to make your code easy to read, but you can have fun there. 00:21:50.060 --> 00:21:52.720 It can definitely make it shorter. 00:21:52.720 --> 00:21:54.000 All right, cool. 00:21:54.000 --> 00:21:54.920 That's a nice one. 00:21:54.920 --> 00:21:58.020 Brian, you're getting all philosophical on this with this next one. 00:21:58.020 --> 00:21:58.360 What's up? 00:21:58.360 --> 00:22:03.500 Okay, so this is totally, we're going from serious to definitely not serious. 00:22:04.160 --> 00:22:05.980 So I noticed this also. 00:22:05.980 --> 00:22:14.020 So there's a Reddit thread that's now, or I don't know if it was Reddit or Stack Overflow, but it got taken down. 00:22:14.020 --> 00:22:19.920 But essentially the question was, why does all return true if the iterable is empty? 00:22:19.920 --> 00:22:25.160 So there's an all keyword in Python that I guess actually a lot of people don't know about. 00:22:25.160 --> 00:22:32.320 That takes an iterable and it returns true if all of the elements of the iterable are true. 00:22:32.880 --> 00:22:35.080 Or evaluate to true in a Boolean context. 00:22:35.080 --> 00:22:37.640 That's really helpful for a lot of things. 00:22:37.640 --> 00:22:43.480 The interesting aspect is, what should it do if the iterable is empty? 00:22:43.480 --> 00:22:50.800 And because, you know, actually the person asking the question said, shouldn't it be false? 00:22:50.800 --> 00:22:55.620 Just like, you know, you can say if list, and if it's an empty list, it's false. 00:22:55.620 --> 00:22:58.420 Why would all be true if it's empty? 00:22:58.420 --> 00:23:00.960 And I enjoyed the conversation. 00:23:00.960 --> 00:23:05.460 And somebody wrote an article called, about this, why is, why does all return true? 00:23:05.460 --> 00:23:11.440 The end lesson is, it doesn't matter why, because the core team decided it, and you just need to know it. 00:23:11.440 --> 00:23:12.380 And work around it. 00:23:12.380 --> 00:23:15.500 It's been thusly decreed to be true, so therefore it is true. 00:23:15.660 --> 00:23:21.320 Yeah, and then one of the things I wanted to point out from this discussion is the statement, all unicorns are blue. 00:23:21.320 --> 00:23:22.720 I just love that. 00:23:22.720 --> 00:23:27.180 You can't tell me, it is definitely true, because there are no unicorns. 00:23:27.180 --> 00:23:30.440 So therefore it's true for me to say all unicorns are blue. 00:23:30.440 --> 00:23:30.740 Yeah. 00:23:30.740 --> 00:23:33.040 And so I like that. 00:23:33.040 --> 00:23:38.440 And I guess I'm glad that my daughter doesn't listen to this to hear me say that there are no unicorns. 00:23:38.440 --> 00:23:39.720 Sorry, honey. 00:23:39.720 --> 00:23:40.720 Don't break her heart. 00:23:40.720 --> 00:23:43.740 Next, you can talk about no Santa or what's going on here. 00:23:43.740 --> 00:23:46.000 Like the tooth fairy is not real? 00:23:46.000 --> 00:23:46.500 Come on. 00:23:46.700 --> 00:23:51.600 But the person writing this article, Carl Johnson, is actually also a philosopher and a programmer. 00:23:51.600 --> 00:24:00.380 So he talks about this 2,500-year-old debate in philosophy about whether or not all unicorns are blue, should be true or false. 00:24:00.380 --> 00:24:08.820 And also we get talk about predicate logic and Socrates and Aristotle and syllogisms and things like that. 00:24:08.820 --> 00:24:14.980 Actually, we never, at the end, I still don't know why the core team chose that that is true. 00:24:15.100 --> 00:24:16.840 But it's a fun thing to look into. 00:24:16.840 --> 00:24:17.960 That's fun. 00:24:17.960 --> 00:24:22.440 So looking at it from the outside, I envision it working like this. 00:24:22.440 --> 00:24:30.060 The way all works to be efficient is it says for thing in collection, if not thing, return false. 00:24:30.060 --> 00:24:32.220 Go all the way in, return true. 00:24:32.220 --> 00:24:34.840 And it just never goes into that loop, so return true. 00:24:34.840 --> 00:24:35.760 Probably, yeah. 00:24:35.760 --> 00:24:40.020 But I probably got to go and open up the CPython source code to find out. 00:24:40.020 --> 00:24:41.520 Matt, what do you think? 00:24:41.520 --> 00:24:42.460 I don't know. 00:24:42.540 --> 00:24:49.460 I'm looking at the Unicode symbol, the Unicode emoji in my Python REPL right now. 00:24:49.460 --> 00:24:53.760 And that's hex code point 1F984. 00:24:53.760 --> 00:24:55.000 And it doesn't look blue. 00:24:55.000 --> 00:24:55.740 It looks pink. 00:24:55.740 --> 00:24:57.540 So something's got a pile of... 00:24:57.540 --> 00:25:02.680 We definitely got to put... 00:25:02.680 --> 00:25:04.980 Somebody's going to have to put a comment on that blog post. 00:25:04.980 --> 00:25:05.640 Yeah. 00:25:05.640 --> 00:25:06.840 Yeah, that's not true. 00:25:06.840 --> 00:25:07.860 All unicorns are pink. 00:25:07.860 --> 00:25:12.000 It's interesting that they did make it true to your point, like in a Boolean context, right? 00:25:12.000 --> 00:25:14.400 Anything empty in Python is false. 00:25:14.400 --> 00:25:15.160 So... 00:25:15.160 --> 00:25:15.520 Yeah, yeah. 00:25:15.520 --> 00:25:20.260 I mean, another option would have been to raise an exception so you can't ask for the truthiness of nothing. 00:25:20.260 --> 00:25:29.140 The main reason why I wanted to bring it up and the main reason I enjoy reading this article is now I will never forget that all of nothing is true. 00:25:30.860 --> 00:25:35.180 I'm also thinking, have I ever used all in an if statement? 00:25:35.180 --> 00:25:38.140 I don't know that I have used all in an if statement. 00:25:38.140 --> 00:25:39.560 Where do you use it? 00:25:39.560 --> 00:25:41.500 Hey, yeah, I guess I have. 00:25:41.500 --> 00:25:42.780 Yeah, I've used it. 00:25:42.780 --> 00:25:44.620 Usually I'll put like a set... 00:25:44.620 --> 00:25:45.300 Not a set... 00:25:45.300 --> 00:25:47.780 Some kind of generator expression in there. 00:25:47.780 --> 00:25:51.180 Because I don't usually want to test all the things are actually true. 00:25:51.180 --> 00:25:55.640 I want to test like the dates are greater than today for all of them or something, right? 00:25:55.640 --> 00:25:58.720 So put a little comprehension in there and then ask all of that. 00:25:58.720 --> 00:26:02.900 Yeah, I guess it returns a Boolean, so you would put it in an if statement. 00:26:02.900 --> 00:26:04.880 I guess so. 00:26:04.880 --> 00:26:08.200 I don't use it a ton either, but every now and then I'm happy with it. 00:26:08.200 --> 00:26:13.000 If I put it in an if statement, am I going to loop over the contents of all, right? 00:26:13.000 --> 00:26:16.020 I don't know that I have it in an if statement. 00:26:16.020 --> 00:26:17.240 I loop over... 00:26:17.240 --> 00:26:17.460 No, no. 00:26:17.460 --> 00:26:19.240 It would be to avoid a loop, right? 00:26:19.240 --> 00:26:21.060 It would be like one line of loop, basically. 00:26:21.060 --> 00:26:21.820 Yeah. 00:26:21.820 --> 00:26:22.140 Cool. 00:26:22.140 --> 00:26:23.660 Yeah, I won't forget either now. 00:26:23.660 --> 00:26:26.720 I didn't realize it was so philosophical, but apparently here it is. 00:26:26.720 --> 00:26:28.980 All right, last one. 00:26:28.980 --> 00:26:29.820 This was really quick. 00:26:29.820 --> 00:26:33.420 This is a project written by Jean-Sebastien Douai. 00:26:33.420 --> 00:26:34.860 Did I close it right? 00:26:34.860 --> 00:26:36.840 Called pytest Monitor. 00:26:36.840 --> 00:26:38.880 And the idea of pytest Monitor... 00:26:38.880 --> 00:26:40.020 Brian, are you familiar with this one already? 00:26:40.020 --> 00:26:41.520 I looked it up quickly, yeah. 00:26:41.520 --> 00:26:42.960 But I haven't used it before. 00:26:42.960 --> 00:26:43.800 Yeah, but okay, cool. 00:26:43.800 --> 00:26:49.320 Basically, you pip install this and then anytime you run a pytest test, 00:26:49.320 --> 00:26:52.720 it's going to automatically collect some data for you. 00:26:52.720 --> 00:26:57.800 It'll analyze memory consumption, timing, CPU usage, stuff like that. 00:26:57.800 --> 00:27:00.760 And it'll put it into a little local SQLite database file, 00:27:00.760 --> 00:27:03.300 and you can look at it over time and whatnot. 00:27:03.300 --> 00:27:05.020 So it's pretty cool, right? 00:27:05.020 --> 00:27:10.300 If you want to say, well, how long does this code take to run on the production machine 00:27:10.300 --> 00:27:12.920 versus on our laptops, right? 00:27:12.920 --> 00:27:15.720 You actually get tracking and whatnot from that. 00:27:15.840 --> 00:27:18.820 So not a huge addition, but it's kind of cool. 00:27:18.820 --> 00:27:20.500 It's built on a couple of libraries. 00:27:20.500 --> 00:27:28.320 PSutil and memory profiler, which let it basically go and ask all these questions on a per test basis. 00:27:28.320 --> 00:27:29.060 It's cool. 00:27:29.240 --> 00:27:31.080 And then obviously it just runs in pytest. 00:27:31.080 --> 00:27:31.520 That's cool. 00:27:31.520 --> 00:27:36.440 I could see where you might want to have a report where you just want to run, 00:27:36.440 --> 00:27:38.960 limit what that's running on. 00:27:38.960 --> 00:27:41.240 I don't know that I would want that necessarily on everything, 00:27:41.240 --> 00:27:47.340 but you might have some hotspots or whatever where you want to monitor that and report on that. 00:27:47.340 --> 00:27:49.440 Having it on everything seems like... 00:27:50.440 --> 00:27:55.380 I don't know what the performance implications are of all that monitoring. 00:27:55.380 --> 00:27:58.140 I think it'd be cool to see... 00:27:58.140 --> 00:28:01.940 This is one of the parts where I'd like to actually see the reporting of this project 00:28:01.940 --> 00:28:05.400 have some reporting that's nicer around it, 00:28:05.400 --> 00:28:07.340 because that's some really cool information, 00:28:07.340 --> 00:28:09.560 but I think some reporting would help it. 00:28:09.560 --> 00:28:10.380 Yeah, it doesn't look... 00:28:10.380 --> 00:28:11.480 It's not beautiful, is it? 00:28:11.480 --> 00:28:13.040 It is in the SQLite database. 00:28:13.040 --> 00:28:14.380 You could grab it and do what you want, 00:28:14.380 --> 00:28:15.780 but then you've got to write that. 00:28:15.780 --> 00:28:17.000 It's like coverage. 00:28:17.000 --> 00:28:20.700 One of the wonderful things about coverage is the reporting part of it. 00:28:20.700 --> 00:28:21.600 Yeah, absolutely. 00:28:21.600 --> 00:28:22.420 All right. 00:28:22.420 --> 00:28:24.480 Well, if that's something you guys care about, 00:28:24.480 --> 00:28:27.260 go install that and check it out. 00:28:27.260 --> 00:28:27.680 All right. 00:28:27.680 --> 00:28:29.260 Well, that's it for all of our major items. 00:28:29.260 --> 00:28:33.520 Brian, Matt, you guys got anything you want to throw out there extra before we get to our joke? 00:28:33.520 --> 00:28:34.500 Stay safe. 00:28:34.500 --> 00:28:35.740 Yeah, absolutely. 00:28:35.740 --> 00:28:36.840 I've got nothing extra. 00:28:36.840 --> 00:28:37.480 How about you, Michael? 00:28:37.480 --> 00:28:40.780 Well, I took two of my projects that I've been kind of fiddling with for 00:28:40.780 --> 00:28:42.920 either a short time or a long time, 00:28:42.920 --> 00:28:43.780 depending on which one, 00:28:43.880 --> 00:28:47.940 and put them both up on PyPI as things you can now pip install. 00:28:47.940 --> 00:28:49.020 So that's kind of cool. 00:28:49.020 --> 00:28:50.900 So the switch laying, 00:28:50.900 --> 00:28:53.020 my little extension to add switch to the Python language, 00:28:53.020 --> 00:28:54.580 you can pip install that now. 00:28:54.580 --> 00:28:55.520 I still love that thing. 00:28:55.520 --> 00:28:56.240 I use it all the time. 00:28:56.240 --> 00:28:58.820 And then my markdown subtemplates. 00:28:58.820 --> 00:28:59.500 Oh, what's that, Matt? 00:28:59.500 --> 00:29:00.960 You use that in production. 00:29:00.960 --> 00:29:02.220 Oh, yeah. 00:29:02.220 --> 00:29:02.840 All the time. 00:29:02.840 --> 00:29:03.940 Awesome. 00:29:04.740 --> 00:29:09.740 Yeah, there's like a couple of places where it would be like this huge if statement or some other weird lookup. 00:29:09.740 --> 00:29:11.340 And it does cool stuff to say like, 00:29:11.340 --> 00:29:12.900 oh, you already tested for this case. 00:29:12.900 --> 00:29:13.580 Or you're like, 00:29:13.580 --> 00:29:15.840 have the same case in two places. 00:29:15.840 --> 00:29:16.680 And you would miss one, 00:29:16.680 --> 00:29:17.380 the second one, 00:29:17.380 --> 00:29:19.100 because it'd be caught by the first and so on. 00:29:19.100 --> 00:29:19.640 Cool. 00:29:19.640 --> 00:29:20.320 Yep. 00:29:20.320 --> 00:29:21.240 And then the second one, 00:29:21.240 --> 00:29:22.520 the markdown subtemplate thing, 00:29:22.520 --> 00:29:23.680 which we talked about before, 00:29:23.680 --> 00:29:26.140 but it was not then pip installable. 00:29:26.140 --> 00:29:27.180 So now it is. 00:29:27.180 --> 00:29:28.120 People can check those out. 00:29:28.120 --> 00:29:29.320 Do you have tests on these, man? 00:29:29.320 --> 00:29:30.700 Of course we got tests on those. 00:29:30.700 --> 00:29:31.060 Okay. 00:29:31.220 --> 00:29:33.360 I don't have pytest monitor on it, 00:29:33.360 --> 00:29:34.080 but we got tests going. 00:29:34.080 --> 00:29:36.140 I have tests in there. 00:29:36.140 --> 00:29:37.200 So they do exist. 00:29:37.200 --> 00:29:38.560 The code does exist as tests. 00:29:38.560 --> 00:29:38.820 It does. 00:29:38.820 --> 00:29:41.360 Yes, we can speak of it. 00:29:41.360 --> 00:29:41.720 Yes. 00:29:41.720 --> 00:29:43.280 Are you all ready for a joke? 00:29:43.280 --> 00:29:43.740 Yes. 00:29:43.740 --> 00:29:44.520 This one is, 00:29:44.520 --> 00:29:45.880 it's not really that funny. 00:29:45.880 --> 00:29:47.600 It's more like... 00:29:47.600 --> 00:29:49.040 As opposed to the rest of our jokes. 00:29:49.040 --> 00:29:50.340 Dude, I think I've done that. 00:29:50.340 --> 00:29:54.580 Well, some of them are like meant to be straight out funny. 00:29:54.580 --> 00:29:56.160 This one's like funny, 00:29:56.160 --> 00:29:56.820 ironic, 00:29:56.820 --> 00:29:57.480 because yeah, 00:29:57.480 --> 00:29:59.640 I did that too at one point or something like that, 00:29:59.640 --> 00:29:59.820 right? 00:30:00.140 --> 00:30:02.800 So this guy on Twitter sent a message, 00:30:02.800 --> 00:30:05.040 sarcastic pharmacist, 00:30:05.040 --> 00:30:06.260 sent it over and said, 00:30:06.260 --> 00:30:09.160 I was listening to a discussion on TalkByThon 00:30:09.160 --> 00:30:11.600 about rebooting a server instead of chasing bugs 00:30:11.600 --> 00:30:16.120 and thought you should check out xkcd.com 1495. 00:30:16.120 --> 00:30:19.920 And there's just a picture 00:30:19.920 --> 00:30:21.880 and it has like a trade office. 00:30:21.880 --> 00:30:22.060 It says, 00:30:22.060 --> 00:30:22.380 okay, 00:30:22.380 --> 00:30:24.320 why is everything broken in my life? 00:30:24.320 --> 00:30:25.180 Here's the deal. 00:30:25.180 --> 00:30:32.400 like I could spend one to 10 hours figuring out why my server keeps running out of swap space and crashing. 00:30:32.400 --> 00:30:37.740 Or I could spend five minutes plugging it into a light timer that reboots it every 24 hours. 00:30:37.740 --> 00:30:38.880 That takes five minutes. 00:30:38.880 --> 00:30:39.460 Let's do that. 00:30:39.460 --> 00:30:40.240 Yeah. 00:30:40.240 --> 00:30:41.820 So true. 00:30:41.820 --> 00:30:43.000 Yeah. 00:30:43.000 --> 00:30:45.960 That's actually an interesting thing. 00:30:45.960 --> 00:30:50.440 We just ordered a bunch of web programmable power strips. 00:30:51.440 --> 00:30:51.920 Yeah. 00:30:51.920 --> 00:30:57.380 Because one of the things you do when working with electronics is sometimes power cycle the things. 00:30:57.380 --> 00:31:00.560 Ain't no way to go and do that when I'm working from home. 00:31:00.560 --> 00:31:00.840 So. 00:31:00.840 --> 00:31:01.600 How interesting. 00:31:01.760 --> 00:31:04.500 So you built that into like the CI, CD, 00:31:04.500 --> 00:31:05.320 hey, 00:31:05.320 --> 00:31:06.620 with the tests, 00:31:06.620 --> 00:31:08.300 like let's do that. 00:31:08.300 --> 00:31:08.600 Sleep. 00:31:08.600 --> 00:31:09.320 Most of the time, 00:31:09.320 --> 00:31:10.460 these aren't problematic, 00:31:10.460 --> 00:31:14.240 but there is the occasional in development instrument where, 00:31:14.240 --> 00:31:18.260 or in development operating system portions or something like that, 00:31:18.260 --> 00:31:21.820 where it gets into flaky situations and rebooting is a good, 00:31:21.820 --> 00:31:23.600 is a good thing to do from the start. 00:31:23.600 --> 00:31:25.400 Because as a software developer, 00:31:25.400 --> 00:31:27.440 I can get things into really wacky states. 00:31:27.440 --> 00:31:28.920 It doesn't happen a lot, 00:31:29.100 --> 00:31:32.640 but it happens enough to where it's good to know that, 00:31:32.640 --> 00:31:32.960 yeah, 00:31:32.960 --> 00:31:34.480 that you can buy these web power switches. 00:31:34.480 --> 00:31:36.560 We're getting industrial ones, 00:31:36.560 --> 00:31:40.000 which are kind of expensive because you can stick them in instrument racks, 00:31:40.000 --> 00:31:42.180 but they're just a normal power strip, 00:31:42.180 --> 00:31:42.740 but you've, 00:31:42.740 --> 00:31:47.900 they've got a web address and a rest or on a rest like API that you can put them in strips. 00:31:47.900 --> 00:31:48.260 And if you, 00:31:48.260 --> 00:31:48.440 yeah, 00:31:48.440 --> 00:31:50.360 if you want to use them in a CI, 00:31:50.360 --> 00:31:51.080 CD pipeline, 00:31:51.080 --> 00:31:52.720 you can call them that way too, 00:31:52.720 --> 00:31:53.180 if you want. 00:31:53.180 --> 00:31:56.100 But normally we just have them as a backup so that we, 00:31:56.200 --> 00:31:59.380 we can log in and reboot them if we need to. 00:31:59.380 --> 00:32:00.980 You don't have them connected to Alexa. 00:32:00.980 --> 00:32:02.980 Alexa, 00:32:02.980 --> 00:32:04.220 reboot my computer. 00:32:04.220 --> 00:32:05.040 No. 00:32:05.040 --> 00:32:05.580 Yeah. 00:32:05.580 --> 00:32:07.700 My test won't pass. 00:32:07.700 --> 00:32:08.000 Help. 00:32:08.000 --> 00:32:09.740 Shall I reboot again? 00:32:09.740 --> 00:32:10.160 Yes, 00:32:10.160 --> 00:32:10.480 please. 00:32:10.480 --> 00:32:13.180 Awesome. 00:32:13.180 --> 00:32:13.500 All right. 00:32:13.500 --> 00:32:13.800 Well, 00:32:13.800 --> 00:32:15.040 Brian, 00:32:15.040 --> 00:32:15.740 thank you as always. 00:32:15.740 --> 00:32:16.140 And Matt, 00:32:16.140 --> 00:32:16.960 thanks for being here today. 00:32:16.960 --> 00:32:17.740 It's fun to chat with you. 00:32:17.740 --> 00:32:17.960 Yeah. 00:32:17.960 --> 00:32:18.340 Thank you. 00:32:18.340 --> 00:32:18.580 Yeah. 00:32:18.580 --> 00:32:20.880 Thank you for listening to Python Bytes. 00:32:20.880 --> 00:32:23.420 Follow the show on Twitter via at Python Bytes. 00:32:23.420 --> 00:32:26.280 That's Python Bytes as in B-Y-T-E-S. 00:32:26.280 --> 00:32:29.500 And get the full show notes at pythonbytes.fm. 00:32:29.500 --> 00:32:31.180 If you have a news item you want featured, 00:32:31.180 --> 00:32:33.720 just visit pythonbytes.fm and send it our way. 00:32:33.720 --> 00:32:36.420 We're always on the lookout for sharing something cool. 00:32:36.420 --> 00:32:38.320 On behalf of myself and Brian Okken, 00:32:38.320 --> 00:32:39.520 this is Michael Kennedy. 00:32:39.520 --> 00:32:42.960 Thank you for listening and sharing this podcast with your friends and colleagues.