Brought to you by Michael and Brian - take a Talk Python course or get Brian's pytest book


Transcript #173: Your test deserves a fluent flavor

Return to episode page view on github
Recorded on Thursday, Mar 12, 2020.

00:00 Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to

00:04 your earbuds. This is episode 173, recorded March 12th, 2020. I'm Michael Kennedy.

00:11 And I am Brian Okken.

00:12 And we have one of our favorite sponsors, Datadog, sponsoring the show. Check them out

00:16 at pythonbytes.fm.datadog. Get a cool t-shirt, get some cool software. Tell you more about that

00:21 later. You know, I think people who, when they're getting started, Brian, they write basic code,

00:25 but they realize that Python is so easy to use because you can just do something like

00:30 request.get. And hey, you have a website already. Like you've already downloaded like something from

00:35 an API or you downloaded something, some HTML or a file. And then it's easy to forget that

00:41 maybe there's more to it. Yeah, I actually totally forgot there was more to it. And

00:45 we know of requests as being both powerful and really easy to use. And there's just about a

00:51 million tutorials on how to put something together quickly with requests. So I was really thrilled to

00:56 come across this article by, I think it's Danny Hadovic, titled Advanced Usage of Python Requests.

01:04 He covers timeouts, retries, hooks, and more. And kind of that comment is it's easy to be immediately

01:11 productive with requests. But there's some really cool things that you can do that I had no idea you

01:16 could do this stuff. So some of the cool tricks that he runs down, actually all the tricks he runs

01:21 down, there's a hooks thing, you can attach a hooks to a session. And so you can use hooks to call

01:29 raise for status on every call. So raise for status is a way you can say, well, if when I request for

01:36 something, if a certain status comes back, then call this other function. But like a 404, there's certain

01:43 wildcard ones that you might want to like all the error ones you might want to always call

01:47 something. So there's a way to hook that up. That's pretty cool.

01:50 Oh, yeah. Nice.

01:52 Base URLs. I had no idea you could do this. This is so neat. Instead of doing like the full path to a URL

01:58 for every if you're doing a whole bunch of them, you can use a set up a base URL that essentially gets

02:06 prepended to everything else later.

02:08 Yeah. And this comes from request tool belt, which we covered before. So it like wraps and adds on to

02:14 requests, which is pretty awesome.

02:15 Oh, does it? Okay.

02:16 Yeah. Yeah. Yeah.

02:16 That's cool.

02:16 Yeah. And this is something I do all the time when I'm writing code that talks to consumes APIs or talks

02:23 to APIs or whatever is it's like, here's the base URL we set. And there's usually an if statement,

02:28 like, are you in development mode? Do this. Are you in production? Use this other URL as the base.

02:33 And then, you know, just do a slash, whatever it gets. But for me, it's always been.

02:37 Oh, that's a great use of base.

02:38 Yeah. For me, it's I've always been like, well, okay, get base URL plus whatever that I'm like.

02:44 Oh, yeah. Does it have the slash on the end or does it not have the slash on the end? Do I need

02:49 to put the slash on that? You know what I mean? And it's super clear here how that works. So I really

02:53 like this. Like I could totally have made use of this and I haven't been so I should.

02:57 And then he covers things like retries on failure, timeouts, timeouts with retries, a little bit of

03:04 testing and mocking of requests. But there's, you know, there's a lot about that.

03:07 Yeah. I'm looking at the section here on timeouts. I feel like, do you think people could get frustrated

03:13 about this or something? What's up with this guy in this card game, man?

03:17 I'm not sure.

03:17 There's like this, like under setting default timeouts. There's like a giphy of a guy just

03:21 beating a card table to death, right? Because he lost. It's playing Settlers of Catan and I'm

03:27 guessing he lost. Anyway, it's a great, great giphy to go along with it.

03:31 I'm not sure why that is relevant to here, but it's funny. It's a funny little video.

03:37 Why is it relevant? This is irrelevant to the podcast, but how is this relevant?

03:43 Well, it says it's great that stuff will just wait, but it can really frustrate you when someone's

03:48 forgot to set a timeout and it halts a program in production. So I'm guessing this

03:51 is an expression of being frustrated because production's lagged. Yeah. Yeah. Yeah. Anyway,

03:58 the one that I also thought was interesting, the base URL is cool, is the retry on failure is pretty

04:03 neat actually.

04:03 Yeah. And then you can even customize it to say, well, not, don't retry everything, but certain

04:08 things you want to make sure you retry.

04:10 Yeah, for sure. And how many times and whatnot. That's a great feature.

04:14 Yeah. And then this is kind of clever. The last one that I thought was clever was the,

04:19 if you're, you want to mimic being different browsers by adjusting the user agent header

04:23 request information, because, you know, sometimes you want to make sure that you're,

04:29 whether or not you're testing your stuff, you want to make sure that you can, deal with

04:32 different user agents. Or if you want to try to, if some people have, have a security stuff

04:38 on where they, they only allow certain user agents cause they don't want bots coming in. Well,

04:43 you can write your bot to be a different user agent then.

04:46 Yeah, absolutely. You could lie to them. Tell your, tell them your internet explorer six,

04:50 see what they think about that.

04:51 Yeah.

04:52 So this next item that I want to cover, I ran across last week and I thought it was really

04:57 cool. And I'm like, I've been looking for something like this for a while. So have you

05:02 heard of this library for testing? It's called pytest. Have you worked with it?

05:05 Yeah, a little bit. Yeah.

05:07 Awesome. So pytest is super clean and great. And you know, the way you express the assertions and

05:12 whatnot is you would, you want to assert something's not none. You would assert the thing is not none.

05:18 And like literally you write that code. And that's really cool for simple stuff like is not none.

05:24 But if you have to test multiple aspects of a thing, like it's not none, it is a number and it's

05:30 greater than zero, or it's between some range that can be a little bit tricky and you've kind of got to

05:35 write some code and it's not, not as descriptive or as expressive, right? That is one of the things

05:41 that I was kind of looking for is like a library that has more complex tests built in. Like, is this

05:47 thing a subtype of that? Or is this string parsable as an integer? I'd like to know that beforehand,

05:54 you know, like something like that. And I don't want to have to do the little, like the complicated,

05:58 small, but still somewhat complicated and non-obvious code in these assertions, right?

06:02 I'm also a big fan of fluent APIs. And what do you mean by fluent? I would love to see more fluent

06:08 APIs in Python, the standard library. So what I mean is a function or property that you can call

06:15 that returns the same object. Oh, okay. Sort of functional. Yeah, a little bit. So if I had say a

06:21 list, I could say list.sort.someotherlistoperation. If sort would return a list, the list that it was

06:30 called on, right? And maybe it had an order by, or I guess that's sort. If it had a filter and then you

06:36 could say dot, right? Transform or something like that, right? You could sort of chain these together

06:40 without doing multiple lines. Yeah. Right? So that's the fluent API. And so this thing I want to talk

06:46 about is something called fluent assertions. And I ran across this from Dean Egan and he was talking

06:51 about it on Twitter. And basically the idea is it has all these checks, like tons and tons of checks

06:57 built into it. I'm not sure how many, I would guess 50 different checks. Is that number complex? Is it not

07:05 complex? Is a value between these two things? Is this set? Is it a set? Is it non-empty? Does it contain

07:11 spaces? Does this string contain spaces? Is it shorter than this? Right? So you could say things

07:15 like, given an object, is it a string that contains no spaces? That is all lowercase. You could do that

07:23 as like one line, just like really clearly in this fluent API. And it throws assertion errors,

07:29 which are the same thing that you would get if you failed in assert directly. So it integrates really

07:35 well into things like pytest. That's pretty cool, right? Cool. Yeah. Yeah. So the example,

07:40 there's an example in the show notes here, and I took this from their docs. It basically says,

07:45 if you wanted to test something like given two parameters, I want to check that the value is not

07:49 none. It's an, that it's a float, that it's between zero and one, and you're given an object and it's not

07:54 none. And it's a type of something, right? That's kind of complicated. Or you can go to their API and say,

07:59 check n dot is not none dot is float dot is between. And I thought this idea is really cool,

08:06 but I don't like it so much. There's like too many words, right? So I've been working on a PR and it's

08:11 basically accepted. The guys running the project said, sure, this looks great. They've reviewed it.

08:17 And it's a simpler one and it uses properties a lot of the time. So it's a little more English,

08:23 less function he called. So you can say, is n dot not none dot float dot between parentheses zero and

08:32 one close parentheses. So the things that assert like, I guess, properties about it, like whether

08:38 it's a float or not none are just properties. And the stuff that takes arguments would be still

08:42 function calls. So I think it's a really clean way to write these test assertions in nice,

08:48 simple ways, especially if you're testing like a couple aspects, like it's not none and it's a float.

08:52 Yeah, I'm on the fence. I know that that a lot of people like this sort of a style. I like your

08:56 updates to it. I hope that goes in because that's a lot cleaner. It's a lot easier to read. So good

09:02 luck with that. I'm perfectly a fan. That sounded harsh. But no, I'm a fan of just the straight

09:09 asserts myself there. I think they're easy to read. But I think having a couple ways to do it,

09:14 that sounds neat.

09:15 What I like about it is it packages up some of the more complicated types of tests,

09:19 like the character only has, like the character, the string has some characters,

09:24 which are spaces or things like, like it's not as obvious if you've write the actual code that does

09:30 the test some of the times, right? I don't know. Anyway, that's what I like about these kinds of

09:34 APIs is the sort of English telling me what you're looking for more than the code of checking for it.

09:39 Yeah. And also you're fitting a whole bunch of stuff on one line. It's kind of nice too.

09:43 Yeah. Yeah. This is a way that you can have multiple assertions on one test without

09:46 people like, say, hey, you're doing more than one test. Well, sort of. Anyway, that's,

09:51 people can check that out. It's a pretty cool library. If that sounds useful to you,

09:54 it's already working for the check API and probably will for the is later. Cool. Cool. Now,

09:59 before we move on to the next, I want to tell you about Datadog because they're sponsoring this episode,

10:03 as they have been great supporters of the show. Let me ask you a question,

10:07 dear listener. Do you have an app in production that is slower than you like,

10:11 or its performance is all over the place? Sometimes it's fast, but sometimes it's slow

10:16 and you don't really know why. That's the most important thing is why is your app behaving this

10:20 way? Do you know what's causing it to be slow or to be kind of all over the place? And if you have

10:26 Datadog, you'll know. You can troubleshoot your app's performance with Datadog's end-to-end tracing,

10:31 use their detailed flame graphs to identify bottlenecks and latency in that finicky app of yours.

10:37 So be the hero that got your app back on track at the company and get started with a free trial at

10:42 pythonbytes.fm/Datadog. Very nice. Yeah. Thank you, Datadog. Good stuff. Also good stuff,

10:48 GitHub. Yeah, GitHub and GitHub Actions. I don't know how long they've been out of beta,

10:53 but GitHub Actions, I think, are available to everyone now. And these are different than their

10:57 webhooks, right? These are more automation workflow inside GitHub. Yeah. And GitHub's sort of by part of

11:03 the Azure Pipelines sort of stuff. I mean, GitHub's associated with Microsoft now. So Azure Pipelines

11:11 are one way to do actions on a, when you commit something or actions at an event time within GitHub.

11:18 But GitHub Actions are a way also. They're more of a lightweight pipeline thing. But for a lot of Python

11:25 projects, I think they're a very good, clean way to go because a lot of our Python projects are not.

11:31 You know, if you're building a package, they're kind of perfect. So there's an article called Python and

11:37 GitHub Actions. And it's by Hynik. And it's sort of really cool. He says he's currently recommending that

11:46 people use GitHub Actions for Python stuff. It's simple, easy integration. So how you do that?

11:53 And that's what this article is about. And he goes through running your tests through Tox,

11:57 using coverage, testing against multiple Python versions, and shows you the YAML that you have

12:04 to set up to configure GitHub Actions to do that right. And you also have to put a little bit of a,

12:08 make a change to your Tox.ini file to make sure this all works. And then I think it's good.

12:14 He was reminding people that if you've got an open source project, it's kind of nice to clean up

12:19 your old stuff. So if you've, if you are switching from some other CI system to GitHub Actions,

12:25 make sure to clean up the old stuff. And then he even goes through and tells some other things like

12:30 changes you want to make to make sure that you're hooked up to the CodeGov system and some other stuff.

12:37 And then making sure it builds on multiple operating systems, the sort of stuff you'd want to do with

12:42 continuous integration. Most of it is available through Azure or not Azure through GitHub Actions.

12:48 So that's kind of cool.

12:50 I love that it's all part of GitHub now. That's great. You know, it's, if you're already there,

12:54 it can be a pain to integrate these other systems. You can just push a few buttons or

12:58 few files and just make it run there.

13:00 Yeah.

13:01 Kind of the secret sauce is that they're really the same thing. I think the Azure Pipelines and the

13:06 GitHub Actions are all running on the same system, but the GitHub Actions is a little simpler interface

13:12 for people that aren't. I mean, Azure Pipelines is, and the Azure Workflow is powerful, but it is,

13:18 it is quite overwhelming when you get into it.

13:21 Yeah.

13:21 That whole system is pretty much all of Azure's overwhelming to me. I go there, I'm like,

13:26 why are there 400 things here? There's so many things. Like, I don't care about most of these.

13:30 What is this place?

13:30 Yeah.

13:31 Yeah. Yeah. Going back to digitalization.

13:33 Okay, cool. This next one I want to talk about touches on a sort of a similar topic as the request

13:38 one that you covered. As also the assertion one that I did. So one of the challenges of testing

13:45 your code can be when you're talking to external systems, right? I want to call the Stripe API and I got

13:51 to provide it all this information. And if you call it more than once with the same token,

13:56 it'll say, sorry, you can't do that. That token's used. So you got to go get a new token. And there's

14:00 just a lot of stuff. And if you necessarily want to be calling real live APIs inside your test,

14:06 that's going to make it quite slow potentially. And so on, right?

14:09 Yeah.

14:10 You can get charged. Like we use a geolocation service on the training site to figure out which

14:15 server to serve the video from. And that one, it's not super expensive, but we have to pay

14:20 per use. So I don't want to hammer it in continuous integration and pay more. So there's this cool

14:25 project called VCR.py. Have you heard of this?

14:27 Yeah.

14:28 Yeah. VCR.py is really cool. I heard about this from Tim Head, who was on Talk Python recently

14:33 for the binder project. And that's going to be out shortly. But the idea is that this simplifies

14:38 testing things that make HTTP requests as well as speeds it up. So all you got to do is the first

14:44 time you run it, you decorate the function. And what it's going to do is going to basically

14:50 instrument and record all the HTTP interaction, what gets sent out and then what comes back.

14:55 And it'll save that into a YAML file hanging around, which is called a cassette. Do you like

15:01 that?

15:01 Yeah.

15:02 Plug the cassette to the VCR, right?

15:03 And the next, the second and third and fourth time that you run the test, if it finds that

15:09 cassette file and the same inputs, it's like, well, you asked for this and here's your answer. And it

15:13 just replays it back to you.

15:14 Yeah. It's pretty clever.

15:15 Yeah. It's super clever. You don't have to worry about if the system is maybe slow or you've got to

15:22 set things up just right to call it because once it has that little cassette file, it's good to go.

15:26 So it lets you test these external service, test your integration with these external services

15:31 in a semi-realistic way because you're really playing back at least snapshot in time, real data

15:37 that you got from it without any effort on your part. Let's you work offline. Your tests are

15:42 completely deterministic. If it passes once, it's always going to pass because you always get the

15:46 same data back. You know, definitely speed up the execution speed because it's just throwing back

15:51 JSON that it has in a file rather than hitting an external service and all that. And if you decide,

15:56 you know what, this request is stale and out of date, all you got to do is delete that cassette

16:00 file, run your test once, it'll hit the real system and then it'll go back to playing the

16:04 new cassette.

16:05 Yeah. Nice.

16:06 Yeah. Yeah. Pretty cool. And then for people who do like pytest, there's a cool little plugin

16:11 called pytest-VCR. And then all you got to do is for your tests that might use something

16:17 like URL open or request or something, you just say pytest.mark.vcr for the test. And then that's

16:26 it. Magically, it works.

16:27 Yeah. Okay. Nice.

16:30 Yeah.

16:30 I don't know if it's really magical. I think it's very useful when it can be useful.

16:34 Yeah.

16:35 I personally don't have the experience, but I'm going to lean on somebody that does. On

16:40 episode 102 of Testing Code, I talked with Harry Percival. And part of that, we're talking

16:45 about how to set up testing an application that has external dependencies through, you know,

16:50 APIs and stuff. He does talk about both good experience with things like bcr.py and some

16:57 difficulties. Like if there needs to be timestamps or different, if you call an API twice and expect

17:04 to get something different back.

17:05 Right.

17:06 Well, this isn't going to help you. But so I recommend if you're running down this route,

17:10 then also listen to the half hour of episode 102 with Harry Percival. It'll help a lot.

17:18 Yeah. Super. We should put a link in the show notes for that.

17:20 Yeah.

17:20 To me, one of the things that I really like about this is I could go pip install Stripe or

17:26 pip install MailChimp or some other thing that I'm integrating with that who knows what kind of

17:31 complicated badness it's doing on the inside to make all of its stuff work. You know, and I don't have

17:36 to think about how am I going to mock out their internals? And if their internals change, how's that

17:41 going to affect my tests? And I can just say, I'm going to grab this higher level API that somewhere

17:47 deep in its guts does network traffic, throw this at it, and then it'll be reproducible. And to me,

17:53 that's the big appeal.

17:55 Yeah. And also speed. So like, even if you're using a test server and not incurring the, all the overhead

18:02 costs of, of the actual server, even with the test server, it's time and it's latency and you can speed

18:09 things up by caching the, the, the return values. So it's a cool idea.

18:14 Well, glad you like it. I know it's probably not something you do as much in the hardware world, but yeah, it's a cool one. What else is cool? What else you got?

18:22 I got eight cool things. I'm a sucker for listicles. If there is actually good information.

18:27 And so Jeremy Grifsky wrote the eight coolest Python programming languages features. And I was just

18:35 smiling the whole time I was reading this. It's a quick article, but it talks about a whole bunch

18:40 of features. I was reading it thinking, man, this is why I love Python. And I really miss all this stuff

18:45 when I'm writing C++ code. So there's code examples of course, in, in this, in this article, but

18:51 we've got list comprehensions. And that's something that when you first learn about comprehensions,

18:57 it's like, Oh my gosh, this is so cool. We also have, dictionary comprehensions and

19:02 other comprehensions. Now you can have, there's all sorts of stuff. Generator expressions are nice

19:08 and really helpful. Slice assignment. I sometimes forget that we can do this. So you can take like

19:15 part of a list and assign, like if you have a three values or something, you want to stick in the middle

19:20 of a list, you can assign those with slice assignment. It's pretty, pretty powerful.

19:25 Iterable unpacking. So if you've got a tuple and you want to unpack that and pass that to a function,

19:31 but as separate values, you can do that. Negative indexing. I mean, you want to grab the last thing

19:37 off of an array. You can say minus one or minus two. I love negative indexing so much. That's a

19:42 really clever feat. It's so simple. And yet it's really nice to just go, I want the thing minus one

19:49 bracket minus one. Give me that. That's the one I want. I sort of, I want minus one. I've tried to do

19:55 this in C++. It's a bad idea. So negative indexing school chaining comparisons. So one is less than X is

20:02 less than five to make sure X is between one and five. That's not something you can do in most

20:08 languages. And it's just, it's how we talk. It's how we do math and Python has it. It's nice.

20:14 He finalizes it out with f-strings, which we love f-strings. And then a whole bunch of a big list of

20:21 honorable mentions. And I was thinking as I was reading this, like this entire thing, plus his

20:26 honorable mentions at the, at the other stuff of like things I could have also talked about,

20:31 that would be a really great, just like a, an introduction to Python course of just like,

20:37 here's a half an hour of why I think Python's awesome. So it's good.

20:41 I agree. I think that would be awesome. Let's see. As I look through this, f-strings definitely stand

20:45 out as something that's awesome. Negative indexing already riffed on that. That's cool.

20:49 Feeding comparisons, list comprehensions, and I'll throw all the expressions and other comprehensions

20:56 in there. I love them, but I wish they did a little bit more. Like why can't I sort a list expression,

21:04 list comprehension, or something like that? There's just a few things where it's like, oh man,

21:09 if I could just, I find myself a lot of times, here's the comprehension. And then here's the

21:14 little bit of things that I wish it could still support. I got to do afterwards. Anyway,

21:18 it would be nice.

21:18 Interesting.

21:19 Like for example, paging, right? I would like to be able to skip. So if I'm on page five of groups

21:25 of 20, I would like to be able to skip four times 20, take 20 with this clause sorted by that and have

21:33 the sorting happen before the paging. Like that would be so nice. And it's just, you know, it's on the

21:39 cusp. So half the time I'm like, God, I love these, but why can't I, you know, whatever.

21:43 Or the little thing that I wish I could extend it a little more database and memory type of

21:47 behavior, but still great, great stuff. I would totally miss them if they weren't there. That

21:51 is for sure. Yeah. Yeah. Cool.

21:52 Actually. So slice assignments, I would, I didn't never even occurred to me that you could do that

21:57 with a language. So it's neat that you can do that, but I probably wouldn't miss them if they

22:02 weren't there because I wouldn't have expected them to be there.

22:05 You shouldn't be able to do that. Yes, exactly. Exactly. I wouldn't miss light assignment at all.

22:09 Although it is neat. You know what I definitely would not miss is bugs in my web app.

22:13 Yeah. Me either. Do you have bugs in your web apps?

22:16 Well, I always think no. And then I learned yes, but not as often, not that often.

22:21 Right.

22:21 So there's this cool project called Bento that I just learned about. Have you heard of Bento before?

22:27 Just the lunch style?

22:28 Yeah, exactly. I do love a good Bento box, but this has nothing to do with that. Maybe the name is

22:33 inspired, but other than that, no. So Bento at bento.dev, this is basically an analysis system that will

22:40 look at your Flask and coming soon, other languages, Django, SQLAlchemy, whatnot. Look at your Flask app

22:48 or your request calls and look for known bugs, especially in the security realm. So you don't

22:56 end up with little Bobby tables. This is your school calling. Did you really name your table,

23:01 your son, dash, dash, semicolon, drop, whatever? Yeah. So what the idea is you can basically

23:08 pip install this thing. You call Bento init. It's going to create a Docker container with the

23:14 analysis tools. And then it's going to run those against your Flask app at the moment. Like I said,

23:20 Django, SQLAlchemy and stuff is coming along. And it'll find things like if you have a missing JWT

23:28 token or you're missing a no opener or the content set, or if you're using requests, if you're sending

23:36 username and passwords over an HTTP, not an HTTPS request, it'll automatically detect that and tell

23:42 you. Oh, very cool.

23:43 Yeah. It's pretty nice, right?

23:43 Yeah. It's very nice. It even does like Jinja template checking and stuff.

23:47 Right. Exactly. So this is open source on GitHub and yeah, you could check it out. It looks pretty

23:52 nice. There's a little Giphy. Thank you guys. Well done on your project. There's a Giphy showing how it

23:59 works right on the page. You can just go to the GitHub repo, scroll down a tad and just watch them

24:05 find a bug, fix a bug and so on. Yeah. Very good. Cool. Cool. Cool. Anyway. So yeah, if people have

24:10 for the moment Flask apps in the future, it looks like they're coming with other things, but yeah,

24:15 you can just run this and it'll check it out. There's also a list of all the checks that they

24:19 have, which I put into the show notes. So a bunch of stuff like, you know, some of the obvious ones are

24:24 like, did you ship Flask into bug mode and stuff, but other things that are not so obvious.

24:28 Yeah. That's it for our main topics, Brian. Do you have anything you want to share with folks

24:32 where we get to the laughter, the hilarity? No, we could use a good laugh, but do you have

24:37 anything extra? We haven't talked about it yet, but I feel like it's all the tech conferences are

24:43 either canceled or they're on coronavirus watch before being cut, right? Like we've had E3,

24:49 the big game one canceled. We have the game developer conference. We had South by Southwest.

24:53 canceled some other ones. Some, I think some Facebook's F8, I think was canceled. Possibly

25:00 Google IO. I'm not sure about the one. I don't remember exactly what they said, but

25:04 PyCon's still on for the moment at the time of this recording. There's going to be an announcement

25:08 tomorrow, which may change things, but just what, I just want to remark, like what a crazy time,

25:13 both for the world, but also for tech.

25:15 Yeah, definitely crazy. I'm curious what it's going to do for, now this is totally self-centered.

25:21 I do want everybody to be healthy, but I also wonder with less people commuting,

25:26 if less people are listening to podcasts, that would be terrible.

25:29 Oh no, they've got a lot of housework. You all folks out there, you definitely got to keep

25:34 listening. Got it. No, that's, that's actually a legitimate question. Whether or not that makes

25:38 sense. Yeah.

25:39 Maybe it does. Here's some of the effects I think are going to happen. I think a lot of companies,

25:44 especially larger companies that believe you must have a meeting every Wednesday and it has to be

25:50 like two hours with this group and an hour of that group. And you must commute every day into the

25:55 office, even though you just work and through GitHub and Slack and email anyway, they're going to realize,

26:01 you know what? We don't actually have to have these big offices and we don't have to have our people

26:06 always come in. We were at least as well off and what's going to be like the work life change that

26:13 comes from that realization.

26:15 Yeah. We made sure, I mean, a year ago today, it was rare for anybody to be, to be working from

26:21 home in our company, even though the work is software for the most part. But now we've made sure that

26:28 everybody, I think we have out of like 80 people, something like that, we've got like only a handful

26:35 of people that are not set up yet to be able to work remotely. I think that's a good change actually.

26:40 I do too. It's going to be really interesting to see the knock-on effects. I think there's going to

26:44 be stuff like that, like, oh wait, we actually could work in this way or we could hire people

26:48 from other places or whatever. It's going to be interesting outside the just, you know,

26:52 the potential chaos of people getting sick and whatnot.

26:55 This has been like talking about the elephant in the room, but it's talking about the virus in the room?

26:59 Yeah. Well, I hope it's not in either of our rooms. Let's just put it like that. Like right now.

27:02 Yeah, definitely not. There's nobody else in my room. I think I'm clean.

27:06 So speaking of mysteries, how about I tell you a joke?

27:09 Oh, please.

27:10 Okay. So let me give you a definition straight out of the dictionary. Debugging. Pronounced

27:16 debugging. It's a verb. Primary definition. Being the detective in a crime movie where you are also the

27:23 murderer. Yeah. That's a good one, right? Yes. You probably get that less since you're

27:31 often coding solo, but there's times where I'm like just hot under the collar, mad about

27:37 some bug in the system and trying to figure out who did this.

27:41 Dude, it's time for some version control blame, some get blame, some version blame.

27:47 Yeah.

27:48 No.

27:49 It was me.

27:50 It was me.

27:51 Yeah. I've been there. I've been there like, oh my gosh. Now, now what do I do?

27:57 Definitely.

27:59 Yeah.

27:59 Love that.

28:00 It's good. It's good for your humility level though, right?

28:02 Yeah. And then you just remember that next time you're mad at somebody else.

28:06 Exactly.

28:07 Or doing something boneheaded.

28:10 Awesome. Well, thanks for being here. Great to chat with you as always.

28:12 Thank you. Bye.

28:13 Bye.

28:13 Thank you for listening to Python Bytes. Follow the show on Twitter via at Python Bytes. That's

28:18 Python Bytes as in B-Y-T-E-S. And get the full show notes at pythonbytes.fm. If you have a news

28:25 item you want featured, just visit pythonbytes.fm and send it our way. We're always on the lookout

28:29 for sharing something cool. On behalf of myself and Brian Okken, this is Michael Kennedy.

28:34 Thank you for listening and sharing this podcast with your friends and colleagues.

Back to show page