<commit_before><commit_msg>Episode 131<commit_after>00:00:00 KENNEDY: Hello, and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds. This is Episode 131, recorded May 15, 2019. I'm <NAME>.
 
00:00:09 OKKEN: And I'm <NAME>.
 
00:00:10 KENNEDY: Hey, Brian, how ya doing?
 
00:00:10 OKKEN: I am good. How are you?
 
00:00:12 KENNEDY: Ah, I still have a little bit of a conference hangover. Two conferences in a row, and then some parties, definitely took it out of me. How about you?
 
00:00:20 OKKEN: Oh, yeah, you went to Build afterwards, how was that?
 
00:00:22 KENNEDY: It was good, I did a bunch of podcasting, met some other folks. I got to see what a different type of conference than PyCon looked like, and, yeah, it's pretty different.
 
00:00:31 OKKEN: Okay, so anybody out there from Build listening, you can invite me next year, that'd be just fine.
 
00:00:35 KENNEDY: Yeah, absolutely, absolutely. So, yeah, it was fun, it was fun to be there, but it's good to be back home from all the conferencing.
 
00:00:42 OKKEN: Yeah, it is. So let's get back into Python.
 
00:00:45 KENNEDY: Let's get into it. So, before we do, though, I want to say thank you to DigitalOcean. Check them out at pythonbytes.fm/digitalocean. More about that later. I feel like we kind of have a little bit of a PEP roundup for this episode, Brian. We've got at least three PEPs.
 
00:00:57 OKKEN: Oh do we?
 
00:00:58 KENNEDY: Yeah, we got at least three PEPs making an appearance, maybe four.
 
00:01:02 OKKEN: Okay, well the ball is rolling now with the new steering council in place, and they're kicking butt and taking names. And it's great. So, we'll start off with, I just saw this today, PEP 581 is accepted, and that is the GitHub issues for CPython. So, CPython has traditionally had its own, I think it was its own custom-made defect tracking system or something. It hasn't switched yet, but it will be switching to GitHub issues. We'll link to the PEP and also it has discussion of pros and cons, but it has been accepted. But the follow-on PEP is 588, and I'll quote <NAME> here. It's, "The migration will be a large effort, with much planning, development, and testing, and we welcome volunteers who wish to help make it a reality. I look forward to your contributions on PEP 588 and the actual work of migrating issues to GitHub." So, 588 is, okay, now that we've decided to do it, how are we going to do it? How are we going to do the migration? Man, once they figure that out, they'll probably need some help to do it. So.
 
00:02:06 KENNEDY: That's cool, and you spoke to Barry on our episode, our live episode at PyCon about becoming a core developer and ways you can help, and here it sounds like another way you can contribute to CPython without actually writing C code, potentially.
 
00:02:21 OKKEN: Yeah, I'm not afraid of C code, but I know, especially in the Python community, there's some people that don't, aren't involved with C code, so there's other places, ways to help. And this is one, yeah.
 
00:02:30 KENNEDY: Yeah, and it's one thing to write C code, it's another to write on the core of CPython itself. Right, I mean that's like, it's a super highly polished piece of software, and any change you make is, like, massive ramifications. So, right, I can see hesitancy.
 
00:02:45 OKKEN: Yeah, the entire world depends on it, no pressure!
 
00:02:47 KENNEDY: You're going to take down the Instagram influencers if you mess this up, so don't. Maybe some science and other important things as well. I think this is good, <NAME> was key in getting CPython, the source code, over to GitHub originally, and I feel like this is well overdue, right? Having the issues there means you can reference them in check-ins, it means that you get that integration for pull requests, and all sorts of stuff. It just makes a lot of sense to do this.
 
00:03:17 OKKEN: Yeah, and I have no idea what the migration path looks like, but.
 
00:03:20 KENNEDY: Yeah, I was wondering, like, are they going to copy every single issue across, or isn't this a chance to kind of clean house? Go well, if this bug comes back, it's important enough to worry about. If it doesn't, maybe it's not.
 
00:03:33 OKKEN: I've been on projects like that, that have, we've gone through a different bug tracking system, where we just said, well, we'll just leave the other one around, and if anybody really cares about moving them over, we will, but those will, sometimes cleaning up is a good thing.
 
00:03:48 KENNEDY: Yeah, I totally agree. So, how about cleaning up some code?
 
00:03:51 OKKEN: Yes, let's clean up code.
 
00:03:52 KENNEDY: So, I am a big fan of design patterns in general, the SOLID principles, all these things, I really enjoy thinking about how that influences code, and one of the things that makes me crazy when I read code is, like, ultra-nested, indented, conditional stuff. And when I see it, I feel like people write code like that because they don't believe there's another way. It's just like, well, this code is complicated, so it's indented sixteen spaces, or whatever it happens to be indented as, right? It doesn't have to be this way most of the time. So I just wanted to call out a super easy-to-implement design pattern called guard clauses or guarding clauses. So, this is if you have, like, nested stuff. I have two little examples, a bad one and a good one here in our show notes, and people can check that out. And, it's like a little checkout for a user. So, user, they've got a shopping cart, they've got some items in there, some of them are available, some of them aren't. Some of them are selected to be express shipped, some of them are not, and things like that. And so, it's got, like, if user is not None, go through their cart. If the item is available, add it. In addition to that, if the item is selected to be expressed shipped, add it. And that's just, what is that, a 30, 30 degrees down, 45 degrees down, line of code. It's not vertical, it's at an angle, probably 45, right? And every one of these is asserting a positive thing. The thing I want, if the user is good, I want to go through them. If the thing is available, I want to do this, and so on and so on. Guarding clauses basically check for the negative and bail out as soon as possible. So you could rewrite that and go, if the user is None, return empty stuff for their stuff. If it's not available, just skip through the loop with a continue and so on, and it's much simpler, and it's not just about visual code, it's not just easier to read, but it's easier to reason about. Like, if you get into one of these super nested, conditional structures, then it's really hard to think about, okay, I want this case and that case, where does that go, do I need another branch in this if, and so on. I feel like it's much easier to maintain and add to with these guarding clauses.
 
00:06:00 OKKEN: And then the example you're showing, where you're going to have in the show notes, the better one actually ends up being more lines of code. However, you're visually going to skip over the top part, 'cause you're like, oh, I'm just making sure that things are, they're right. And then in the middle, I've got highlighted just three lines of code where the actual work is. And highlighting where the real work is instead of dispersing the real work across lots of if clauses, I think that's a great idea.
 
00:06:27 KENNEDY: Yeah, thanks. I super love it. I'm linking to <NAME>'s original little article on it, which is C or JavaScript or something. But it's if statements, it's basically the same idea. As well as to one from a Go, a Medium article about line of sight programming, talking about, you can just see right down the line. Anyway, it's all pretty cool, I definitely, definitely think how those can be used. I find it's to make it a lot nicer, a lot easier to maintain this code.
 
00:06:54 OKKEN: It'll also reduce the cyclomatic complexity of your code.
 
00:06:57 KENNEDY: Yes, yes it will. And that also, probably, that's cool because it will make <NAME> happy, and his wily, but it also means it's less cognitive overhead to maintain, right? You can say, okay, I've cleared out the stuff that's not good, now we're in the good spot, and it's not indented and it's not a lot going on. You're right, it's so simple that I don't, if you're not using it, just check it out. It's great.
 
00:07:21 OKKEN: Good reminder.
 
00:07:22 KENNEDY: Speaking of if you're not using it.
 
00:07:23 OKKEN: Yeah, so the, so, Python 3 is a thing. We've talked about it a few times in the past. There's probably a lot more people, well, I don't know. There's probably more people, some people now, still converting to Python 3, or starting to get used to it. The easy hurdles are just to start not using the stuff you can't anymore, and some of the string changes and whatever. But here's an article I ran across called Things You're Probably Not Using in Python 3 but Should. So there's a lot of new items in Python 3, but this article goes through a handful. So there's some obvious, I think obvious, of course, items, like f-strings, pathlib, and maybe data classes, I'm using 'em a lot, but, maybe, f-strings and pathlib, definitely, everybody should be using those. Those are awesome. I'm warming to type hinting a little bit more. It's feeling more natural. You know, I'm not really a zealot about it, but when I start trying to see myself start typing a comment to say what kind of stuff should go into a function, or what should be in a variable, I'm like, oh, I could just put a type hint down there, and that, it's.
 
00:08:29 KENNEDY: Exactly, exactly. Yeah, comments are deodorant, right? They go onto bad code to make it smell better. But maybe you should just make it better by putting some type hint.
 
00:08:37 OKKEN: Yeah, maybe a type hint, yeah. So, especially when I'm only intending it for the reader, I'm not using some testing tools around that. But there's some stuff that I knew about that I just kind of forgot. So I'm glad that, I'm mostly going to list three that he listed. Enumerations, with the new enum package and enum and auto methods and classes.
 
00:09:00 KENNEDY: Yeah, that's, I love enums, they're really great. I don't use them enough, but, yeah, they're super.
 
00:09:03 OKKEN: Enough, I want to use 'em a little bit more after this reminder. Also, lru_cache is built-in, it's a decorator in functools that you can use really easy memoization. So, if anybody's not familiar with lru_cache or memoization, the gist of it is you just throw this decorator on a function. If it's really functional-programming-type stuff, where you pass in some value and you get a, and that has no behavioral side effects, and it just returns some other, some value that's a one-to-one correlation between input and output, and it's called a lot, you can use memoization with lru_cache to speed it up, and it just remembers the old stuff.
 
00:09:45 KENNEDY: It's so nice. Yeah, it just says, if I see this argument come in, say, you have a number in your example, like if the number 72 comes in and the answer was 7,000, the next time it's called it just goes, that argument's 72, we know, it's not changed, the answer's going to be 7,000. Any time you have a function that basically, it's deterministic, you give it the same input, it gives you the same output, this is a super good option.
 
00:10:08 OKKEN: Yeah, especially if it's something that's time-consuming, it has to do some data crunching or something.
 
00:10:13 KENNEDY: Yep.
 
00:10:14 OKKEN: The last one I'm going to highlight, that I totally forgot about, is extended iterable unpacking. And this one you kind of have to see to get it, but, basically, for instance, if you're unpacking a list, with a three-element list, you can assign it to three variables. We know that. But if you have more than three, you can put a star in one of those things, and it'll catch all of the rest. And that's cool. There's lots of places that I could use that that I forgot about, so.
 
00:10:42 KENNEDY: And you can even do the star in the middle, right, you've got, like, head, *body, and tail, for five things, and the body is three things. Pretty awesome. When I look at this, and I think about it, obviously, there's a lot of people moving to modern Python and using it in their code, right? But just like you could come from C and write non-Pythonic Python, you could move to Python 3 and write non-Python 3-ic, I don't know, you could write code that's not idiomatic to Python 3, right? You still do everything the Python 2 style, not taking advantage of any of these things, right? Like f-strings, pathlibs, type hinting, async and await, like you said, enums, you could do none of that and still be, quote, using Python 3. So I think it's cool, a cool reminder and example of things you could do to be more idiomatically Python 3.
 
00:11:33 OKKEN: Yeah, actually when I was thinking about that, the author of this even says some of his old articles are written essentially for Python 2. And I think that's a great place for people, if they're new to, they want to start doing technical blogging and they don't really have some ideas on what to do. You can go look at some common and popular articles that are written in Python 2 style and kind of make 'em your own and do a similar article, don't copy it, but do a similar article with Python 3 syntax, and you'll probably get some hits.
 
00:12:03 KENNEDY: Yeah, for sure, or even if you really love that resource you're reading, you could send 'em a note, like, hey, I'd love to upgrade these three articles to Python 3, could I help you?
 
00:12:11 OKKEN: Oh yeah, that would be much nicer, do that.
 
00:12:13 KENNEDY: Yeah. Well, they both have their own merits, right? Speaking of merits, let me tell you about DigitalOcean. DigitalOcean is powering all of our things, which is awesome. And we talked about GitHub at the beginning. One of the big things GitHub is doing is GitHub actions. So, kind of automated workflow for things that happen, check-ins and other stuff, on GitHub. And DigitalOcean has a GitHub actions for DigitalOceans that you can install and plug in there. So you can take your workflow that's happening on GitHub and automatically use that to do things like create a new virtual machine, or push a new version to a Kubernetes, managed Kubernetes cluster, based on a push, or something like that. Right, or maybe snapshot it when a issue is filed. Who knows, but all sorts of cool stuff you can do with GitHub actions, and DigitalOcean mixed together with that, so check that out at pythonbytes.fm/digitalocean, you get $100 free credit for new users. Definitely can recommend them, they're doing good stuff. So how about some fun, Brian?
 
00:13:16 OKKEN: Yeah, we got a couple fun ones.
 
00:13:18 KENNEDY: Yeah, yeah, let's play a few games here. It's awesome that these came up just right by each other. So, I want to talk about this thing called the Python Arcade Library, which is at arcade.academy, which I didn't even know .academy was a top-level domain, but apparently, apparently it is. That's pretty awesome. So this is a library for easily building 2D games in Python that run at like 60 frames a second on OpenGL.
 
00:13:48 OKKEN: Oh, neat.
 
00:13:48 KENNEDY: That's pretty cool, right? So it's really about, this is by a guy, believe his name is <NAME>, hopefully I'm getting that right. He built this to help teach. He teaches at a college, and it helps teach his students a more visual way to learn programming. So it's not to teach game development, it's to teach programming, but because it's got a visual aspect, and not just a terminal version, you can see what you're creating more easily and see it working. So that's pretty cool, you can create, like, minesweeper games, hangman games, and in particular platformer games. So if you wanted to recreate Lemmings, or if you wanted to do Joust or whatever, you could totally use this for that.
 
00:14:26 OKKEN: Ooh, neat.
 
00:14:27 KENNEDY: Yeah, and you can check out the sample games made with that. So there's a tower defense game, I'm a sucker for tower defense. There's a little Angry Bird thing made, there's all sorts of fun stuff. There's tons of examples here, I think mostly because these are students who are taking the class, but then submitting their projects.
 
00:14:45 OKKEN: Oh, that's a great idea.
 
00:14:46 KENNEDY: Yeah, nice, right?
 
00:14:47 OKKEN: Yeah, yeah, and I like these 2D games.
 
00:14:50 KENNEDY: I do, too. Yeah, and it also includes things like physics, which is nice, 'cause it's one thing to get the graphics on the screen, but hit detection, physics, sound, all these other things are super hard, and I believe sound is still a little bit of a iffy feature here. I hear that that's tough in Python, so maybe that's a cool C extension somebody should write. I don't know, but anyway, it's all based on OpenGL, and it looks pretty cool, so definitely want to recommend that. People, check that out. Yeah, and you got a similar one. How 'about that?
 
00:15:20 OKKEN: Yeah, so I wanted to highlight a article called Teaching a Kid to Code with Pygame Zero, written by <NAME>. So this is just this guy with his kid, that likes to play video games with his kid, and thought, you know, I should try to teach him how to code. And they tried, his son did, a version of Scratch. But the worry is that Scratch is really far removed from actual coding, and the skills you build might not be transferable really easily. So he went ahead and decided to try Pygame Zero, using the Mu editor, and I guess Pygame Zero is already preinstalled in Mu, as is a Python interpreter. I didn't know that, that's kind of neat.
 
00:16:06 KENNEDY: Oh that's cool, yeah, that's great.
 
00:16:07 OKKEN: And so a quote from somewhere, "Pygame Zero is intended for use in education, so that teachers can teach basic programming without needing to explain the Pygame API or write an event loop." He worked with his son, and they came up with a 29-line-of-code, including blank spaces, little game, doesn't really do much, but it teaches a lot. So he said that his son learned about naming things and variables and mutability and fiddling with constants to see how those affect the screen size and stuff like that. Writing functions that have side effects, and interacting with mouse events. So he learned quite a bit with just this little bit of code, and it's actually Python. So, that was kind of neat. And one of the things I really liked, 'cause I do want to start, I haven't worked with my kids with coding yet, but the article also includes some tips on how to behave as the adult when you're working with kids with coding. So it's good.
 
00:17:03 KENNEDY: Yeah, it's truly tricky to set up the right balance of, it's interesting but quickly becomes too hard. Or it's easy enough to get kids started, but they have expectations of something they can do with their iPhone as a game. And what you build does not necessarily match, right?
 
00:17:21 OKKEN: Yeah, and I like the tips at the end, because I'm one of those kind of people that would just say, okay, you just sit on the side, and I'll do it and you watch. That's not really teaching.
 
00:17:30 KENNEDY: Yeah, true, true, true. It's cool, though, I think these are both really fun options for teaching kids programming and building a little game. 'Cause not everybody cares about building games, but a lot of people who do, a lot of people's introduction to programming was, they wanted to build a game, programming was just what was required to make that happen, right?
 
00:17:49 OKKEN: And you can go do something else, like a useful utility that somebody might need, but how many six-year-olds really need a useful utility written in Python?
 
00:17:59 KENNEDY: Yeah, true, true, true.
 
00:18:00 OKKEN: Anyway.
 
00:18:01 KENNEDY: Cool, while we're talking about games, if kids are not quite ready for a game, but they're ready to do adventurous stuff, I guess, I want to throw a shout-out to codecombat.com. That's a super cool place. It has a free version where you basically go into these dungeons and you solve the dungeon by writing Python programs.
 
00:18:21 OKKEN: Oh, neat!
 
00:18:21 KENNEDY: And the editor has autocomplete like nobody's business. It's super, super nice. So, you have to, like, have your hero move around, you say, hero.attack and select, like, an enemy. If you type the letter a, it'll autocomplete hero.attack . I mean, it's like, really, really, beginner-friendly. So, definitely, that's maybe a first step and then one of these two that we just spoke about would be really good as well.
 
00:18:43 OKKEN: Oh, I'll also try that.
 
00:18:44 KENNEDY: Yeah, I was doing that one with my daughter, and she was super into it. She got like 50 levels in or something. 50 little dungeons. Cool, all right, so the last one, let's round it up with something a little more serious. So, we talked before about whether or not the GIL will become obsolete with the introduction of PEP 554. And this was on Episode 128, which is cool. So <NAME> wrote a cool article called Has the Python GIL Been Slain? that really digs deeply into that idea that we were touching on back then. So, the answer is kind of, maybe, I don't know. Probably, but for a limited case. So, we've got a multithreading in Python which is pretty easy but is not actually concurrent because of the GIL. We have multiprocessing, which is harder to exchange data and stuff. It carries a lot of overhead but does escape the GIL 'cause it's all these separate processes. Right, so PEP 554 introduces this idea of subinterpreters. Remember that from back then, Brian? And we speculated that maybe the ability to have multiple subinterpreters would remove the problem of the GIL. Because the GIL is not a process thing, it's an interpreter thing. It's the Global Interpreter Lock. So, if we just take and run our threads on multiple subinterpreters, there would be no GIL. Things would go potentially faster at least some of the time, right? The problem is, if you actually try to share data across those subinterpreters, things get pretty tricky. So, Anthony's article really digs into that and it talks about how you might use shared memory and IPC, which is also another feature coming to multiprocessing, but that's also kind of slow and challenging. So he highlights another PEP. So here's our fourth PEP, PEP 574, which proposes a new pickle protocol. Is that surprising?
 
00:20:34 OKKEN: Yeah, a little bit.
 
00:20:36 KENNEDY: A little bit, 'cause people say don't use pickle, it has all these vulnerabilities and versioning issues and whatnot. Except for it's a nice binary format, and if your goal is to just literally exchange data from subinterpreter to subinterpreter through shared memory, well, then, that's fine. That's within the runtime of a process. It should be okay, right? You're not going to hack yourself, and if you do, you deserve it. So this is a special protocol, version 5, that has support for allowing memory buffers to be handled separately from rest of the pickle stream, basically. So, all these things could be combined together to get us a cool, faster, more concurrent Python. And he answers the question when will maybe these things be here. So pickle version 5 and shared memory will probably make it to Python in 3.8, which will be October of this year, 2019, and subinterpreters may make that but they might take another version, 3.9, which, I believe, at the time, that's going to be 18 months later. Think we're still on the 18 month release cycle here.
 
00:21:38 OKKEN: Yeah. And what I really appreciate about this article isn't that there's suddenly stuff that I can use now, it's that we have been talking about the subinterpreters, and I haven't really gotten my head around really how, how that affects us, and I think this is a good jump in, a good discussion about it, so that if you're curious about this, he talks about all of the backstory and kind of where we're going from here. The where we're going from here, I think, is still kind of up in the air. I would like to see something more around a shared memory. One of the discussions is having shared memory objects that are owned by one subinterpreter at a time, so you can say, well, I'm creating this data to have another interpreter take it over.
 
00:22:21 KENNEDY: Right, I'm handing it off to you, you can have it now.
 
00:22:23 OKKEN: Yeah, and it would be nice if I didn't have to pickle that, if I could just, the data I'm creating is just normal data, but it happens to live in an area that I can hand over to a different process or something.
 
00:22:35 KENNEDY: Oh, that's interesting, basically dereference it in the current garbage collector system and rereference that information in the other one.
 
00:22:43 OKKEN: Yeah, somehow, something like that.
 
00:22:44 KENNEDY: Yeah, yeah, yeah, okay, cool.
 
00:22:45 OKKEN: There's, I'm sure, lots of smart people working on the problem. But it is neat. It's neat to see it going forward.
 
00:22:51 KENNEDY: Absolutely.
 
00:22:52 OKKEN: Plus there's a really amusing video of a breakdancer, where like six guys come out, none of 'em are doing anything, except for one, who's spinning on his head.
 
00:23:01 KENNEDY: Yeah, it's a very, I don't even know how to describe, it's a very different interpretation of how the global interpreter lock kills concurrency. Through breakdancing.
 
00:23:12 OKKEN: Yeah, through breakdancing.
 
00:23:13 KENNEDY: I knew it all along, man. The rap beat was off. That's why we can't get this thing to run in parallel. All right, cool, well, that's it for our main topics today, what else do you got that you just want to quickly chat about?
 
00:23:25 OKKEN: A couple things. PyCon seems like it just got over, but the videos are already all available. And I've already started watching them, including Ant's complexity with wily talk. And the other thing I wanted to bring up is I'm reviewing, I'm not reviewing it, but I bought the new Pragmatic Programmer book, the 20th anniversary edition. And they rewrote it, and I'm reading the testing chapter, starting there, and they bring up pytest and they're using pytest and hypothesis, and that's pretty cool.
 
00:23:55 KENNEDY: Oh, yeah, that's super cool. And hypothesis, that's pretty interesting, that one. All right, well I have a couple quick announcements for you all. So first of all, quick and easy one, I've been creating a bunch of different things lately. The iOS and Android apps are both out for the Talk Python training stuff, but, I just released new versions that have a couple of cool new features. So, if you have it installed, make sure you update it. If you don't have it installed, well, check it out at training.talkpython.fm. That's cool. So, Brian, I've joined you in the journey that is writing a book.
 
00:24:27 OKKEN: Yes, you're an author now.
 
00:24:28 KENNEDY: Yeah, apparently. Somehow I don't feel like I've gotten any, like, official stamp or any letter, or no little pamphlet that makes me officially an author. But, yeah, so we have a book called Effective PyCharm that's out, and it has a digital version, has a print version, it has sort of bundled stuff with some of the courses. So I'll link to that in the show notes. People can check that out at effectivepycharm.com. So that's pretty cool. And then also we just released a new course, 100 Days of Web.
 
00:24:57 OKKEN: It's pretty neat, I've started watching it. I like it.
 
00:25:00 KENNEDY: Yeah, thanks, thanks for taking, checking it out. That's awesome. So it's kind of intense. It's 28 little different web projects. So, one time you build an API in Flask. And one time we build logins with Django, and migrations with SQLAlchemy. So, all these different things you might want to do, all over, it's kind of like a super sampling of all the web stuff. So check that out, the link's in the show notes, at Talk Python training as well. All right, well, that's all, all I got for now. Do you got a joke for us?
 
00:25:27 OKKEN: I don't, but I wanted to bring up something about your course.
 
00:25:31 KENNEDY: Oh, thank you.
 
00:25:32 OKKEN: My first concern was that 100 different web projects might seem overwhelming. But it isn't that. Like you said, it's 28 projects, is that right, 28?
 
00:25:40 KENNEDY: Yeah, and there's four of them that are super short. So it's kind of 24.
 
00:25:43 OKKEN: Yeah. You can get more into it than just some quick thing that you can do in one day. I appreciate that pacing.
 
00:25:50 KENNEDY: Yeah, thanks a bunch. Yeah, we were trying to find a balance there, 'cause 100 separate projects, too small. One huge project, you don't get in enough variety of other things. So, 24, that was the slicing we came up with. All right, how 'about this. So there's a programmer going to a coffee shop, looking to get out of the cube. Can't stand being in the cube more, so get out, and there's a waiter that comes over and says, hey, welcome to the restaurant, would you like coffee or tea? The programmer says yes.
 
00:26:23 OKKEN: Yes, of course. Ah, have you done this?
 
00:26:28 KENNEDY: No, but it would sounds like it might be sort of fun.
 
00:26:31 OKKEN: Yeah, I mean, I haven't done it with coffee or tea, but I definitely think that sometimes, if somebody gives me an or question, I'll answer with yes, yes.
 
00:26:40 KENNEDY: Yeah, they mean exclusive or, don't they? Yeah, pretty awesome. All right, well.
 
00:26:47 OKKEN: Thanks a lot.
 
00:26:48 KENNEDY: You bet. Good to chat with you, and I will catch you next time around.
 
00:26:50 OKKEN: Okay, bye.
 
00:26:51 KENNEDY: Bye.
 
00:26:52 OKKEN: Thank you for listening to Python Bytes. Follow the show on Twitter via @pythonbytes. That's pythonbytes as in B-Y-T-E-S. And get the full show notes at pythonbytes.fm. If you have a news item you want featured, just visit pythonbytes.fm and send it our way. We're always on the lookout for sharing something cool. On behalf of myself and <NAME>, this is <NAME>. Thank you for listening and sharing this podcast with your friends and colleagues.
 
{'fraction_non_alphanumeric': 0.05579767564712097, 'fraction_numerical': 0.024498151082937136, 'mean_word_length': 4.093156213216748, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5069213', 'n_tokens_mistral': 8950, 'n_tokens_neox': 7988, 'n_words': 5369}