« Return to show page
Transcript for Episode #173:
Your test deserves a fluent flavor
00:00 KENNEDY: Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds. This is Episode 173. Recorded March 12th 2020. I'm Michael Kennedy,
00:11 OKKEN: and I am Brian Okken
00:12 KENNEDY: and we have one of our favorite sponsors DataDog sponsoring the show. Check them out at Pythonbytes.fm/datadog. Get a cool T-shirt, get some cool software. Tell you more about that later. You know, I think people who when they're getting started, Brian, they write basic code. But they realize that Python is so easy to use because you can just do something like `requests.get`. And hey, you have a website already like you've already downloaded, like something from an API or you downloaded something some HTML or a file. And then it's easy to forget that maybe there's more to it.
00:43 OKKEN: Yeah, I actually totally forgot there was more to it, and we know of requests is being both powerful and really easy to use. And there's a just about a 1,000,000 tutorials on how to put something together quickly with requests, So I was really thrilled to come across this article by Ah, I think it's Dani Hadovic titled “Advanced Usage of Python Requests“. He covers timeouts, retries, hooks and more and kind of. That comment is it's easy to be immediately productive with requests. But there's some really cool things that you can do that I had no idea you could do this stuff. So some of the cool tricks that he runs down, actually, all the tricks he runs down there's a `hooks` thing. You can attach a `hooks` to a session, and so you can use hooks to raise for status on every call. So `raise_for_status()` is a way you can say, Well, if if, when I request with something, if a certain status comes back, then call this other function but like a 404 or they're certain wildcard ones that you might want to like all the other ones, you might want to always calls something. So there's a way to hook that up. That's pretty cool.
01:51 KENNEDY: Oh, yeah, Nice
01:52 OKKEN: base URLs. I had no idea you could do this. This is so neat. Instead of doing like the full path to a URL for every if you're doing a whole bunch of them you can use. Ah, set up a base URL. They essentially gets prepended everything else later.
02:08 KENNEDY: Yeah, and this comes from _requests toolbelt`, which we covered before, So it like wraps and adds on to requests, which is pretty awesome. (Oh, does it? Okay,) Yeah. This is something I do all the time. When I'm writing code that tox consumes APIs or talks to APIs or whatever is it's like, here's the base URL we set. And there's usually an if statement like, Are you and development mode do this? Are you in production? Use this other URL as the base and then, you know, just do a _slash whatever_ get But for me, it's always been Oh,
02:38 OKKEN: that's a great use of base.
02:39 KENNEDY: Yeah, for me, it's I've always been like Well, okay, get base, euro plus whatever them are like Oh, yeah, it does it have the slash on the end, or does it not have the slash on the end? I need to put the slash on the, you know, timing, and it's super clear here how that works. So I really like this. Like I could totally have made use of this and I have been, so I should.
02:57 OKKEN: And then he covers things like, um, retries on failure, timeouts, timeouts with retries, a little bit of testing and marking of requests. But there's, you know, there's a lot about that.
03:08 KENNEDY: Yeah, I'm looking at the section here on time outs. I feel like, Do you think people could get frustrated with this or something? What's up with this guy in this card game man?
03:17 OKKEN: I'm not sure
03:18 KENNEDY: there's like this. Like understanding default timeouts. There's like a GIPHY of a guy. Just heave a card table of the death because he lost it playing settlers of Catan, and I'm guessing he lost
03:29 KENNEDY: anyway. It's a great great GIPHY to go along with it
03:32 OKKEN: and make sure why that is relevant to hear. But it's funny, too funny little video, But why is it relevant? I know this is the relevant to the podcast, but how is this relevant?
03:44 KENNEDY: Well, he says, it's great that stuff will just wait, but it can really frustrate you when someone's forgot to set a timeout in a halts a program in production. So I'm guessing the expression of being frustrated. (Yeah, yeah)
03:58 KENNEDY: Anyway, the one that I also thought was interesting in the base URL is cool is the retrial on failure is pretty neat, actually.
04:05 OKKEN: and then you can even customize it to say, Well, not don't try everything but certain things, You wanna make sure you're retrying.
04:11 KENNEDY: Yeah, for sure. And how many times what? Not that. That's a great future.
04:14 OKKEN: Yeah, And then, um, this is kind of clever. The last one that that was clever was the If you're you want to mimic being different browsers by adjusting the user agent header, request information Because, you know, sometimes you want to make sure that your whether or not you're testing your stuff, you want to make sure that you can deal with different user agents. Or if you want to try to see if some people have have, ah, security stuff on where they they only allow certain user agents because they don't want bots coming in. Well, you can write your bot to be a different user agent.
04:46 KENNEDY: Yeah, absolutely. You could lie to them tell you're telling your Internet Explorer 6. See what they think about that?
04:52 KENNEDY: Yeah, to this next item that I want to cover. I ran across last week and I thought it was really cool. And I'm like, I have been looking for something like this for a while.
05:02 KENNEDY: So have you heard of this library for testing? It's called PyTest. If you've worked with it?
05:06 OKKEN: Yeah, a little bit. Yeah.
05:08 KENNEDY: So pytest is super clean and great. And you know, the way you express the assertions of what? Not as you would you want to search. Something's not none. You would assert the thing is not none. And, like literally, you write that code
05:21 KENNEDY: and that's really cool for simple stuff, like `is not none`. But if you have to test multiple aspects of a thing like it's not known none, it is a number, and it's greater than zero. Or it's between some range. That could be a little bit tricky, and you kind of gotta write some code. It is not not his descriptive or his expressive right. That is one of the things that I was kind of looking for. A library that has more complex tests built in, like Is this thing a subtype? of that. Or is this string parsable as an integer. I'd like to know that beforehand. You know, like something like that. I don't wanna have to do the little, like the complicated, small but still somewhat complicated and non-obvious code in these assertions, right? I'm also a big fan of fluent APIs and
06:06 OKKEN: what do you mean by fluent?
06:07 KENNEDY: I would love to see more fluent APIs in Python. The standard library. So what I mean is a function or property that you can call that returns the same object.
06:17 OKKEN: Okay. Sort of functional.
06:19 KENNEDY: Yeah, a little bit. So if I had, say a list I could say “`list.sort` dot some other list operation”
06:27 KENNEDY: If `sort` would return a list. The list that it was called on, right? Maybe it had an `orderby` OR I guess that sort. If it had ah, `filter`. And then you say dot right transformer or something, right. You could sort of chain these together without doing multiple lines. Yeah, right. So that's the fluent API. And so this thing I want to talk about is something called fluent assertions. And I ran across this from Dean Agan and he was talking about it on Twitter. And basically the idea is it has all these checks, like tons and tons of checks built into it.
06:59 KENNEDY: I'm not sure how many I would guess...50 different checks. Is the number of complex. Is it not Complex? Is a value between these two things? Is this set? Is it a set? Is it non-empty? Does it contain spaces? Does this string contained spaces? Is it shorter than this right? So you could say things like,
07:17 KENNEDY: given an object. Is it a string that contains no spaces that is all lowercase you could do that is like one line just like really clearly in this fluid API and it returned throws assertion, errors, which are the same thing that you would get if you failed in assert directly. So it integrates really well into things like PyTest. It's pretty cool, right? Cool. Yeah. Yeah. So the example. There's an example in the doughnuts here. And I took this from their docks that basically says you wanted to test something like given to perimeters. I want to check that the body is not none it's that it's a float, that it's between 0 and 1 and you're given an object and it's not none. And it's a type of something right. That's kind of complicated. Or you go to the API and say, Check dot is not none.
08:02 KENNEDY: Thought is float that is between. And I thought this idea is really cool, but I don't like it so much. It was like too many words, right? So I've been working on a PR. And it's basically accepted. The guys running the project said, Sure, this looks great.
08:17 KENNEDY: They reviewed it,
08:18 KENNEDY: and it's a simpler one, and it uses properties a lot of the time. So it's a little more English, less functioning called.
08:25 KENNEDY: So you can say is `n.not_none.float.between(0,1)`.
08:34 KENNEDY: So the things that assert like I guess, properties about it, like whether it's a float or not, none are just properties, and the stuff that takes arguments would be still function calls. So I think it's a really clean way to write these test assertions and nice, simple ways, especially if you're testing like a couple aspects like it's not known and it's a float.
08:52 OKKEN: Yeah, I'm on the fence. I know that that a lot of people like this sort of a style. I like your updates to it. I hope that goes in cause that's a lot cleaner. It's a lot easier to read, So good luck with that. I'm perfectly.... That sounded Harsh But I know I'm a fan of just the straight asserts myself there. I think they're easy to read, but I think having a couple ways to do it sounds neat.
09:15 KENNEDY: what I like about it is it packages up some of the more complicated types of tests, like the character only hat. The string has some characters which are spaces
09:26 KENNEDY: or things like that. It's not as obvious if you've right the actual code that does the test. Some of the times right. anyway, that's what I like about these kinds of APIs is the sort of English telling me what you're looking for more than the code of checking for it.
09:40 OKKEN: Yeah, and also you have fitting a whole bunch of stuff on one line. That's kind of nice to you.
09:43 KENNEDY: Yeah, this is the way that you can have multiple assertions and one test without people, like, say, Hey, you're doing more in ones as well. It's sort of, anyway, that's, Ah, people can check that out. It's a pretty cool library. If that sounds useful to you, it's already working for the check API and probably will for the is later. Cool. Cool. Now, before we move on to the next, I want to tell you about DataDog because they're sponsoring this episode as they have been great supporters of the show. Let me ask you a question, Dear listener. Do you have an app in production that is slower than you like or its performance is all over the place. Sometimes it's fast, but sometimes it's slow and you don't really know why. That's the most important thing is why is your app behaving this way? Do you know what's causing it to be slow or to be kind of all over the place? If you have DataDog, you'll know you can troubleshoot your app performance with DataDog’s end-end tracing, use their detailed flame graphs to identify bottlenecks and Leighton See in that finicky app of your So be the hero that got your app back on track at the company and get started with a free trial at PythonBytes.fm/DataDog. Yeah, I thank you DataDog. Good. Good stuff. Also. Good stuff.
10:49 KENNEDY: GitHub.
10:49 OKKEN: Yeah GitHub and GitHub Actions. I don't know how long they been out of beta, but GitHub actions I think are available to everyone now.
10:56 KENNEDY: And these were different than their webhooks. Right? These are, more automation, workflow inside GItHub.
11:01 OKKEN: Yeah. And GitHub sort of by part of the azure pipelines sort of stuff. I mean, GitHub is associated with Microsoft now. So as your pipelines are one way to do actions on ah, when you commit something, your actions at an event time within GitHub. But GitHub Actions are a way also. They're more of a lightweight pipeline thing. But for a lot of Python projects, I think there they're very good, clean way to go because a lot of our Python projects are not, You know, if you're building a package, they're kind of perfect. So this there's an article called Python and GitHub actions, and it's by Hynek and it's sort of really cool, he says. He's currently recommending that people use GitHub actions for Python stuff. It's simple, easy integration. So So how you do that? And that's what this article's about. And he goes through running your tests through `tox` using `coverage`. Testing Using multiple Python versions and shows you the YAML you have to set up to configure GitHub actions to do that right. And you also have to put a little bit of, ah, make it changed your `tox.yaml` file to make sure this all works and then ah, I think it's good. He was reminding people that if you got an open source project, it's kind of nice to clean up your old stuff. So if you if you are switching from some other CI system to GitHub actions, make sure to clean up the old stuff. And then he even goes through and tell some other things, like changes you want to make to make sure that you're hooked up to the codecov system and some other stuff, and then making sure it builds on multiple operating systems. The sort of stuff you'd want to do with the continuous integration. Most of it is available through measure or not. Measure through, get have actions. So that's kind of cool.
12:50 KENNEDY: I love that. It's all part of GitHub now. That's great. You know, it's if you're already there could be a pain to integrate these other systems. You could just push a few buttons or a few files and just make it run there.
13:01 OKKEN: Yeah, I kind of the secret sauce is that they're really the same thing. I think the azure pipelines and the GitHub actions are all running on the same system. But the get of actions is a little simpler interface for people that aren't mean Azure pipelines is and the Azure workflows is powerful, but it is. It is quite overwhelming. You get into it?
13:22 KENNEDY: Yeah. That whole system is pretty much all of Azure is overwhelming to me. I go there And why? Why are there 400 things here? There's so many things like I don't care about most of this. what is this place? Yeah, yeah, yeah. Going back to Digital Ocean. Okay, cool. This next one, I want to talk about touches on sort of a similar topic as the requests one that you covered as also the assertion one that I did so one of the challenges of testing your code can be when you're talking to external systems,
13:50 KENNEDY: right? I want to call the stripe API and I have to Provided all this information
13:54 KENNEDY: and if you call it more than once with the same token, it'll say Sorry. You can't do that, that tokens used. So you gotta go get a new token. And there's just a lot of stuff and you necessarily want to be calling real. Live APIs inside your tests. That's gonna make it quite slow, potentially and so on. Right?
14:10 KENNEDY: You even get charged like we use the Geolocation service on the training site to figure out which server to serve the video from. And that one It's not super expensive, but we have to pay per use, so I don't want a hammer. It inconvenienced integration and pay more. Do. There's this cool project called `VCR.py`. Have you heard of this? (Yeah). Yeah, VCR.py is really cool. I heard about this from Tim Head, who was on top by then recently for the Binder project, and that's gonna be out shortly. But the idea is that this simplifies testing things that make http requests as well speeds it up. So all you gotta do is the first time you run it, it's you decorate the function and what it's gonna do is gonna
14:50 KENNEDY: basically instrument and record all the http interaction, what gets sent out and then what comes back. And it will save that into a YAML file hanging around, which is called a cassette. You like that
15:02 KENNEDY: Looks like a set to the easy are right and the next the second and third and fourth time that you run the test. If it finds that cassette file in the same inputs, it's like, Well, you asked for this And here's your answer, and it just replays it back to you.
15:15 OKKEN: Yeah, it's pretty clever.
15:16 KENNEDY: Yeah, super clever. You don't have to worry about if the system is maybe slow or you've got to set things up just right to call it, because once it has that little cassette file, it's good to go.
15:27 KENNEDY: So lets you test these external service, test your integration with these external service is in a semi realistic way because you're really playing back at least snapshot in time. Real Data that you got from it without any effort on your part. It lets you work off line. Your tests are completely deterministic. If it passes once, it's always gonna pass because you always get the same data back. You know, definitely speed up the execution speed cause it's just throwing back JSON that it has in a file rather than hitting an external service in all that. And if you decide, you know what this request is stale and out of date. All you gotta do is delete that cassette file, run your test once it will hit the real system, and then it'll go back to playing the new cassette. Yeah,
16:06 KENNEDY: yeah, yeah, Pretty cool. And then, for people who do like PyTest, there's a cool little plug in called PyTest-VCR.
16:14 KENNEDY: And then all you gotta do is for your tests that might use something like `urlopen` or `requests` or something. You say `pytest.marked.VCR`, part of the test. And then that's it. Magically, it works.
16:28 OKKEN: Yeah. Okay.
16:30 OKKEN: Nice.
16:30 KENNEDY: Yeah, I don't know
16:31 OKKEN: if it's really magical. I think it's very useful when it can be useful.
16:35 KENNEDY: Yeah,
16:35 OKKEN: I personally don't have the experience, but I'm gonna lean on somebody that does on, ah, Episode 102 of testing code. I talked with Harry Percival, and part of that we're talking about how to set up testing an application as external dependencies through, you know, APIs and stuff. He does talk about both good experience with things like VCR.py and some difficulties. Like if there needs to be time stamps or different if you call in API twice and expect to get something different back, (right) well, This isn't going to help you. So I recommend if you're running down this route, then then also listen to the half-hour of episode 102 with Harry Percival. It'll help a lot.
17:18 KENNEDY: Yeah, Super. We should put a link in the soonest that to me, one of the things that I really like about this is I could go `pip install stripe` or `pip install mailchimp` or some other thing that I'm integrating with that. Who knows what kind of complicated badness It's doing on the inside to make all of this stuff work. You know what I don't have to think about? How am I going to mock out their internals? And if their internals change, how is that going to affect my tests? And I could just say
17:45 KENNEDY: I'm gonna grab this higher level API that somewhere deep in its guts does network traffic. Throw this at it and then it'll be reproducible. And to me, that's the big appeal.
17:55 OKKEN: Yeah, and also speed. So even if you're using a test server and not incurring the all the overhead costs of of the actual server, even with the testserver it's time it's latency. And you could speed things up by caching the the return values. So it's a cool idea.
18:14 KENNEDY: Well, I'm glad you like it. I know it's probably not something you do as much in the hardware world, but, uh, yeah, it's a cool And what else is cool? What else you got?
18:22 OKKEN: I got 8 cool things. I'm a sucker for A listicles if there is actually good information.
18:28 OKKEN: And so Jeremy Gretzky wrote the eight coolest Python programming languages features and I would just smiling the whole time I was reading this. It's a quick article, but it talks about a whole bunch of features that I was reading it thinking, man, this is why I love Python and I really miss all this stuff when I'm writing C++ code. So there's code examples, of course, in this Ah, in this article, but we got list comprehensions, and that's something that when you first learn about comprehension, is it's like Oh my gosh, this is so cool. We also have a dictionary comprehensions and other comprehensions now you can have. There's all sorts of stuff. Generator expressions are nice and really helpful. Slice assignment. I sometimes forget that we can do this so you can take like part of a list and assign like, if you have ah three values or something, you want to stick in the middle of a list, you can assign those with slice assignment. It's pretty, pretty powerful, iterable unpacking. So if you've got to pull and you wanna unpack that and pass that to a function as separate values, you could do that negative indexing, and you want to grab the last thing off of an array, you can say, `[-1]` or `[-2]`.
19:40 KENNEDY: I love negative indexing so much. That's a really clever feature. It's so simple and yet it's really nice to go “I want the thing minus one `[-1]`. Give me that. That's the one I want.
19:53 KENNEDY: I saw it and I want minus one.
19:54 OKKEN: I've tried to do this in C++. It's a bad idea, so negative. Indexing is cool. Chaining comparisons. So `1 < X < 5` to make sure exes between one and five. That's not something you can do in most languages, and it's just it's how we talk. It's how we do math and Python has. It's nice, yoy know?
20:16 OKKEN: He, finalizes it out with f-strings, which we love f-strings. And then ah, whole bunch of a big list of honorable mentions. And I was thinking, as I was reading this like this entire thing, plus his honorable mentions at that the other stuff of like things I could have also talked about that would be a really great just like a an introduction to Python course of yes, like here's 1/2 an hour of why I think Python's awesome. So it's good.
20:41 KENNEDY: I agree. I think that would be awesome. I looked through this f-strings definitely stand out as some of this awesome negative indexing already riffed on that. That's cool, chaining comparisons. List comprehension is, and I'll throw all the expressions and other comprehension is in there. I love them, but I wish they did a little bit more.
21:01 KENNEDY: Why can't I sort on a list expression was comprehension
21:06 KENNEDY: or something like that. There's just a few things where it's like a man. If I could just find myself a lot of times, here's the comprehension. And then here's a little bit of things that I I wish it could still support. I gotta do afterwards anyway. It would be nice like, for example, paging right. I would like to be able to skip. So if I'm on page five of groups of 20 I would like to be able to skip `4 * 20`
21:30 KENNEDY: take 20 with this clause sorted by that and have the sorting happened before, the paging like that would be so nice and it's just, you know, it's on the customs, so half the time like I love these.
21:42 OKKEN: But why
21:42 KENNEDY: get Ideo whatever the little thing that I wish I could extend a little more database-in-memory type of behavior, but still great, great stuff. I would totally miss them if they weren't there. That is for sure. Yeah. Yeah. Cool,
21:53 OKKEN: Actually. So slice assignment. I I didn't never even occurred to me that you could do that with a language. So it's neat that you can do that. But I probably wouldn't miss him if they weren't there because I wouldn't have expected them to be there.
22:06 KENNEDY: Oh, yes, Exactly. Exactly. I would miss slice assignment. Although it is neat.
22:10 KENNEDY: You know what? I definitely would not miss? Bugs in my web app.
22:14 OKKEN: Yeah, me either. You have bugs in your web app.
22:16 KENNEDY: well, always think. No. And then I learned, yes, but not is often not that often. Right. So there's this cool project called Bento that I just learned about. Have you heard a bento before?
22:27 OKKEN: Just the lunch style.
22:29 KENNEDY: Yeah, exactly. I do love a good bento box, but it has nothing to do with that. Maybe the neighbors inspired, but there's that No. So bento at better.Dev, this is, um, basically an analysis system that will look at your flask and coming soon, other languages. Django SQLAlchemy. What? Not your flask app or your request calls and look for known bugs, especially in the security realm. So you don't end up with little Bobby tables.
22:59 KENNEDY: This is your school calling. Did you really name your son “dash, dash, semi-colon drop. Whatever?”
23:06 KENNEDY: Yeah. So what ideas? You can basically pip-install this thing
23:10 KENNEDY: you call Bento in it. It's going to create a Docker container with the analysis tools. And then it's gonna run those against your flask app. At the moment Like I said, Django and other stuff is coming along.
23:25 KENNEDY: and it'll find things like if you have a missing JWT token or you're missing a `no-opener` or the `contents` attr
23:34 KENNEDY: if you're using requests. If you're sending user name and password over an http not a https request, it'll automatically detect that and tell you ovary Cool. Yeah, pretty nice, right?
23:44 KENNEDY: Yeah,
23:44 OKKEN: it's very nice. Even does like Jinja template checking and stuff.
23:47 KENNEDY: Right? Exactly. So this is open source on GitHub and yeah, you could check it out. It looks pretty nice.
23:53 KENNEDY: Now there's a little GIPHY. Thank you, guys. Well done on your project. There's a GIPHY showing how it works right on the page. You can just go to the GitHub Repo scroll down a tad and just watch them find a bug. Fix a bug and so on. A very good cool. Cool. Cool. Anyway, so, yeah, if people have from the moment flask apps in the future, it looks like they're coming with other things.
23:53 KENNEDY: You can just run this and it'll check it out. There's also a list of all the checks that they have, which I put into the show notes. So a bunch of stuff like, you know, some of the obvious ones are like, Did you ship flask debug mode and stuff? But other things that are not so obvious, that's it for our main topics. Brian, do you have anything you want to share with? Folks? Were we get to the laughter and the hilarity.
23:53 OKKEN: Now we could use some laughter, but you haven't anything extra.
23:53 KENNEDY: We haven't talked about it yet, but I feel like it's ah all the tech conferences are either canceled or they're on Coronavirus watch for being cut right? Like we've had E3, the big game one canceled. We have the Game Developer Conference we had South-by-Southwest canceled some other ones. Some I think some Facebook's F8, I think, was canceled.
23:53 KENNEDY: Possibly Google IO, I'm not sure about the one. I don't remember exactly what they said, but PyCon on still on for the moment at the time of this recording, there's gonna be an announcement tomorrow, which may change things. But just what? I just want a remark like What a crazy time, both for the world, but also for Tech.
23:53 OKKEN: Yeah, definitely crazy. I'm curious what is going to do for Ah, now this is totally self centered. I do want everybody to be healthy, but I also wonder, with less people commuting if less people are listening to podcasts, that would be terrible.
23:53 KENNEDY: Oh, no, they've got a lot of housework. You all folks out there, You definitely got to keep listening. You got No, it's that's actually a legitimate question. Whether or not that makes sense, maybe it does. Here's some of the effects I think they're gonna happen. I think a lot of companies, especially larger companies that believe you must have a meeting every Wednesday. And it has to be like two hours with this group and an hour of that group. And you must commute every day into the office even though you just work
23:53 KENNEDY: it through, GitHub and slack and email anyway. They're going to realize, you know what? We don't actually have to have these big offices, and we don't have to have our people always come in. We were at least as well off.
23:53 KENNEDY: And what's going to be like the work life change that comes from that realization.
23:53 OKKEN: Yeah, we made sure. I mean, a year ago today, it was rare for anybody to be to be working from home in our company, even though the work is software, for the most part. But now we've made sure that everybody I think we have out of, like, 80 people something like that. We've got, like, only a handful of people that are not set up yet to be ableto work remotely. I think that's a good change. Actually,
23:53 KENNEDY: I do, too. It's gonna be really interesting to see the knock on effects. I think there's gonna be stuff like that like, Oh, wait. We actually could work in this way or we could hire people from other places or whatever it is, it's gonna be interesting outside the just, you know, with a potential chaos of people getting sick and whatnot.
23:53 OKKEN: This has been like talking about the elephant in the room, but it's talking about the virus in the room.
23:53 KENNEDY: Yeah, well, I hope it's taught in either of our rooms. It was just put it like that. Like, right now?
23:53 OKKEN: Yeah, definitely not. I mean, nobody else in my room. I think I'm clean.
23:53 KENNEDY: So speaking of mysteries,
23:53 KENNEDY: how about I tell you a joke? (Oh, please). Okay, so let me give you a definition straight out of the dictionary. Debugging
23:53 KENNEDY: pronounced debugging. It's a verb. Primary definition, being the detective in a crime movie where you are also the murderer.
23:53 KENNEDY: Yeah, it's a good one, right?
23:53 OKKEN: Yes. You probably get that less since you're you're often coding solo. But there's times where I'm, like, just hot under the collar, mad about some bug in the system and trying to figure out who did this. It
23:53 KENNEDY: is time for some version control blames him. `Git blame`. Some version blame.
23:53 KENNEDY: Yeah. No,
23:53 OKKEN: it was
23:53 KENNEDY: It was me. Yeah, I had dinner. I have been there like,
23:53 KENNEDY: Oh, gosh. Now what do I do?
23:53 KENNEDY: Definitely. Yeah, it's good. It's good for your humility level that right?
23:53 OKKEN: Yeah. And then you just remember that next time you're mad at somebody else thats really doing something boneheaded.
23:53 KENNEDY: Well, thanks for being here. Great to chat with you as always. Thank you. Thank you for listening to Python Bytes. Follow the show on Twitter via at Python Bytes. That's Python Bytes as in B Y T E S and get the full show notes at PythonBytes.fm If you have a news item even featured, just visit Python by side of him and send it our way. We're always on the lookout for sharing something cool on behalf of myself and Brian Okken. This is Michael Kennedy. Thank you for listening and sharing this podcast with your friends and colleagues.