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


Transcript #311: Catching Memory Leaks with ... pytest?

Return to episode page view on github
Recorded on Tuesday, Nov 22, 2022.

00:00 Hello and welcome to Python Bytes where we deliver Python news and headlines directly to your earbuds.

00:04 This is episode 311 recorded November 22nd, 2022.

00:10 And I am Brian Okken.

00:11 I'm Michael Kennedy.

00:12 And I'm Merlou Cunha.

00:13 So welcome Merlou.

00:15 So tell us a little bit about yourself before we jump into the topics.

00:18 TLDR is I'm a machine learning engineer at a data and AI consultancy company called Data Roots.

00:24 I'm from Brazil, but I actually live in Belgium.

00:27 And I guess that's it.

00:29 Thanks for having me.

00:30 >> Thanks for showing up.

00:31 >> It's great to have you here.

00:32 >> Well, Michael, why don't you kick us off with the first topic?

00:35 >> All right. Let's kick it off.

00:36 I've got some fun stuff.

00:38 Let's see what Marilo thinks about this.

00:40 This is a little bit mathy, what I got going on here.

00:44 That is not the right screen. How about that screen?

00:47 This comes in from one of the big friends of the show, Brian Skin.

00:51 He sent me a tweet and it just says, "What @PythonBytes?" And it's a quote tweet from somebody here saying, "Holy latexify is the sexiest thing I've ever seen." (laughing)

01:05 And look at this.

01:06 So when, I studied a ton of math, and the symbols of mathematics are really important, and they communicate stuff like really, really quickly.

01:16 You can scan over and you see the symbol for the real numbers, or you can see the symbol for subset or infinite sum, and you're like, "I know what that means." When you translate that into Python or into computer code, it usually becomes something gnarly looking.

01:32 The example here on this tweet has a function called solve, and it's solving the quadratic equation.

01:38 I guess just for one variation of the root, not the plus minus, but that's fine.

01:42 It just says like negative b plus math dot square b star star two.

01:48 It's like symbol soup.

01:49 So this latexify thing, Letechify, letech is the language of expressing those symbols the way mathematicians would have written them in the 16th century or whatever, like the fancy flowing sum symbols and integral symbols and whatnot.

02:07 What this does is you just put a decorator onto that Python function, you say letechify.withLetech.

02:14 Letech, when you show that function in a notebook, it shows the formal mathematics of it.

02:22 >> Wow.

02:23 >> There's one that was doing, I said the quadratic equation.

02:26 Another one that says, if x is zero, return one else, return sine of x divided by x.

02:32 Then the symbols is like this branching equation, like what you would write that in LaTeX, conceptually. What do you think?

02:39 >> Wow.

02:40 >> Is that insane?

02:41 >> This is great.

02:42 >> But it just changes the level of the function, I guess.

02:45 If you call the function, it's all fine.

02:47 >> Yeah, exactly. It doesn't change the function at all.

02:49 It changes the repper or the stir.

02:51 If you do this outside of a notebook, what it prints out, let me see if I can somehow communicate this back.

02:59 If you print it out, what it returns, do I have it here? No.

03:04 Yes, there. No, that's not it.

03:06 Sorry, I don't have it. What it prints out is the LaTeX escape codes.

03:10 It'll say backslash frack.

03:14 I don't know how to write LaTeX.

03:16 I did a little bit when I was studying math, and then I'd said, "That's something I never need to remember," and shot it out of my brain.

03:24 >> Never again.

03:25 >> Yeah. Why do I need to know this?

03:26 I don't need to know this.

03:27 But yeah, so the repper is just the LaTeX escape codes, and then the notebooks see that, and then they render it as LaTeX.

03:36 >> That's pretty cool. But one of the nice things about this then is, you might have the math that you're trying to convert to code, and then you can check your answer.

03:46 You can just see, did I get it right in code?

03:50 So, it's pretty cool.

03:52 - That's really interesting.

03:53 Yeah, 'cause you round trip it, right?

03:54 - Yeah, I'm assuming people are doing this on their own code, so they're, you know.

03:58 Oh, I guess you can--

03:59 - The question about the inverse, right?

04:01 It's like, hey, if I have the math symbols, could I turn this into a Python function?

04:06 I mean, I don't see why I can't go both ways.

04:08 - Sure, true.

04:09 But I still think it would be easier to write the Python function than the latex code for rendering it.

04:14 - Yeah, that's true.

04:15 I think it's a pretty niche use case.

04:17 Well, you know, I'm sure.

04:18 - Well, I'm sure someone's gonna find a cool use case for it too, right?

04:22 - Yeah, this is pretty interesting.

04:25 We've got a couple of live comments.

04:27 Madison, hey Madison, out in the audience.

04:29 Madison's been on the show before.

04:31 I'm blown away by how libraries like this are able to make math approachable.

04:35 I wonder how this could be used with auto-generated documentation.

04:37 Very cool, I agree.

04:39 And Henry also says, I'm guessing it's working on the bytecode like Numba, but compiling it into a human language.

04:45 >> Yeah, compile it into the LaTeX escape codes.

04:48 >> Which is not human.

04:49 >> Basically.

04:49 >> Yeah.

04:50 >> Which is the opposite of unreadable, but it is text, right?

04:54 You know, related to this just as-

04:57 >> Oh, yeah. Henry tells us how it's done.

04:59 >> Okay. It's using inspect, get source, and parsing the AST.

05:03 Yeah, perfect. Another thing that's amazing, if people check out the SymPy stuff, it does some really, really interesting things like if you go say to like calculus, you take a limit here, It'll do similar outputs as well, right?

05:18 So you could put in this and it'll actually express it as symbolic math, and it won't lose precision because it solves it symbolically.

05:26 You can say like, "Factor this equation." So that's related, but this just says, "Given any arbitrary Python function not written in the symbolic form," just turn it into a LaTeX, which is pretty amazing.

05:38 So anyway, thank you, Brian Skin for pointing that out.

05:41 That is pretty neat.

05:42 One final comment, I could not get it to install on my Apple Silicon Mac, maybe that detail matters, but I couldn't get it to pip install.

05:51 Out of PyPI, I had to pip install the git plus the GitHub URL, and then it would install.

05:57 I don't know why, but if people wanna play with it, that might be necessary.

06:00 - Okay, cool. - Yeah.

06:01 Over to you, Brian.

06:02 - All right, well, while we're talking about math, I'm often working in the measurement world and where we care about prefixes a lot, and a lot of people do with big numbers or small numbers.

06:15 And this was actually suggested to us by Avram.

06:20 And I think he either works on this or it's his project.

06:23 It's a project called Prefixed.

06:25 And what this does is it's just, it's a class, it provides a class called float, capital F, that is a, derives from the built-in float, and it supports scientific and IEC, which I'm not familiar with, prefixes.

06:47 So things like scientific, like K and S and things like that.

06:52 If you go look at all the metric prefixes, you've got like, there's some new ones, but N, K, mega, giga, things like that.

07:00 And it just, so it adds these onto when you print them.

07:05 So it acts just like a normal float.

07:07 Most of the time, you can use it in math equations and everything.

07:11 The interesting thing is if it is used in math equation, the result will be one of these prefix float types.

07:21 But then the nice thing about it is when you convert it to a string, it includes the little prefix thing, or the suffix, or whatever, the little micro, or K, or M, or something like that.

07:34 So I think this is actually super helpful.

07:37 I'm gonna use this right away because I, you know, I use a lot of like big and small numbers and reporting out just the huge thing or just the float is sometimes horrible to compare with.

07:48 So this is pretty cool.

07:51 - It's very clever.

07:51 I love how simple the idea is.

07:54 So you can just F string one of these floats and say colon 0.2H, and that'll convert it to its, and the age tells it to be either, you know, kila or micro or mega or, you know, whatever suffix is needed.

08:07 That's cool.

08:08 - Right, and then there's the byte example where they said, well, I'm gonna use the capital B for bytes, but that's after the formatting of the number.

08:17 And then the K comes in from the float thing.

08:20 So that's pretty cool.

08:22 One of the other things that he passed along is there's some new prefixes.

08:27 So this is apparently new.

08:30 New scientific prefixes over the last, for the first ones, new ones for the last 30 years, apparently.

08:37 So we have 10 to the 21st, which is Zeta, and 10 to the 24th, which is Yotta, and then negative is Zepto and Yocto.

08:47 So these are fun.

08:49 - Maybe, why now?

08:51 Why they decided to, like, need to have more money now need to come up with new prefixes or?

08:58 - Exactly.

08:59 - I'm not sure why we need new prefixes.

09:03 - Our microscopes can now see smaller things.

09:05 We don't have words for this, that things are this small, like.

09:08 - But national debt, maybe.

09:12 - Yeah, very possible.

09:15 - But also Avram notes that prefix does handle these new ones.

09:20 So cool, good job.

09:22 - One thing in Python too, you can put the underscore, right?

09:25 Like if you put underscore in the thousands, that also, that's something that makes it easier, I think, to read the numbers too.

09:31 That's what I was using to know.

09:32 - Yeah, like the digit grouping, yeah.

09:33 - Yeah. - Do you do that a lot?

09:35 - Not a lot, but like some, whenever I can, I do.

09:38 I think it makes it easier to distinguish how big the number is, I guess.

09:42 - I always forget to.

09:43 I just, I know it's there, but I never use it.

09:46 - I think usually it's like when I'm counting the zeros with my finger on the screen, I'm like, no, no, maybe I'll just put a underscore there.

09:52 It makes everyone's life easier.

09:54 - Yeah.

09:55 - Yeah, I've really started doing that a lot the last couple of years, but before then I didn't.

09:59 - Cool.

09:59 - Well, what is next?

10:01 - Merlo, what you got for us?

10:03 - I think that's me.

10:04 - Yeah.

10:05 - DBT, have you ever--

10:07 - First you gotta accept some cookies, hold on.

10:10 - Oh, my bad, my bad.

10:11 - Just kidding, I'm just teasing.

10:13 - I love cookies.

10:14 - I'm trying to, these cookie things drive me crazy, man.

10:16 I don't know why.

10:17 - Yeah, yeah, yeah.

10:17 I think it's like crazy how like, now that it's popping up everywhere and then you see like the data, the gathering all the time and this and this Yeah.

10:25 Yeah.

10:26 But maybe DBT.

10:27 Have you ever heard of DBT?

10:28 Is this something because in the data world in my field, it's super popular, but I don't know if it's a bubble as well.

10:33 I've never heard of it.

10:34 Michael never heard of it.

10:35 I think I've heard of it, but I couldn't tell you what it does.

10:38 So I'm basically in the same spot.

10:40 Tell us about it.

10:41 No, it's a really cool tool.

10:43 It's open source as well.

10:44 They have their cloud option, I guess.

10:46 Right.

10:47 So you can pay and they host it.

10:48 Maybe a disclaimer as well that I never, I always see it and I always want to use it, and I haven't found the use case.

10:54 So I don't have first-hand experience here.

10:56 But basically the way I would describe is that they add best practices around SQL projects.

11:01 So why am I mentioning this on Python Bytes?

11:05 It's built with Python, yay.

11:06 And the other thing too is that they actually mix Jinja with SQL stuff, right?

11:12 So you can actually do for loops, you can do stuff like that.

11:15 So you don't have to repeat every time and just change the variable.

11:18 They also have these like reference macros and stuff.

11:20 so you can actually say, okay, this comes from that table that is on that file and this comes from this.

11:25 So you can actually chain a lot of these dependencies, right, like there's a lot of projects that you have these ETL stuff, right?

11:30 So you just have to basically transform each step.

11:32 And with DBT, they actually keep track of what depends on what, and you can say, oh, I want the freshest data here, and you execute everything that needs to be executed there.

11:41 - Wow.

11:42 - Yeah, so it's super cool.

11:43 They actually support a lot of like data platforms here, right, so you see like BigQuery, Databricks, Snowflake, all these things as well.

11:50 Another thing that they also more things they do, they even have some data validation stuff, which in my field, it's a big thing too, like maybe you have an ID column that needs to be unique, cannot be null, and you wanna make sure that that always happens.

12:02 And if it doesn't happen, you wanna be flagged, right?

12:04 So that's super cool.

12:05 What else?

12:07 You also have some built-in documentation.

12:09 So once you have the dependencies, you can say, oh, show me the DAG, show me where the data comes from and what depends on what.

12:16 So that's also super cool.

12:17 And recently, actually, they actually started supporting, So like an SQL file kind of corresponds to a model, right?

12:23 Oh, cookies again.

12:25 And so they have SQL models, so that's the one, but they also started supporting Python models, right?

12:31 So this is very tight to data.

12:33 So now you can actually mix and match, right?

12:34 You can say this step, this transformation is in SQL, but this one is actually in Python, right?

12:39 So the way they don't run anything on the machine, they actually send it to the cloud.

12:42 So Snowflake has Snowpark, which is Python on its own Snowflake.

12:47 BigQuery has Spark and Databricks as well, right?

12:50 So basically you can mix and match these transformations here, these transformations there, but everything is like in a nice put in one place.

12:56 And because it's on Git as well, you can have CI/CD.

12:58 I think also you mentioned, I think it was you, Brian, that mentioned SQL Fluff, and SQL Fluff actually came from a DBT project as well.

13:05 So, and it's all in Python, so super cool.

13:08 - Wow, that's really neat.

13:09 So what do the Python models look like?

13:11 Are they straight Python classes or are they Pydantic or?

13:15 I have, I watch, maybe I'm a bit lazy 'cause I just watched a video and they were showing here how it works.

13:21 'Cause it's also doing a comparison, right?

13:23 Maybe this is, no, this doesn't work, does it?

13:25 - Yeah, it works.

13:26 - This works?

13:27 - Yeah, it was wrong.

13:28 - Okay, but the quality is horrible.

13:30 - That's okay.

13:31 - But in a nutshell, you have this basically.

13:32 - Yeah.

13:33 - You define a function.

13:35 Yeah, you define a function that has a dbt in a session and then you create a reference.

13:38 So reference is basically a table, right?

13:40 And you can say, and then from that point on, you can say two pandas and then you can just basically use the pandas API to transform that, right?

13:45 So there's still some caveats, right?

13:47 'Cause panda is not super performant depending on how much data you have and whatnot.

13:50 So sometimes you just probably still wanna stick to the SQL stuff, but then it opens a lot of possibilities there too, right?

13:57 So even stuff like deploying machine learning models on the SQL infrastructure and everything, so.

14:01 - Yeah, so it's kind of the same old, same old story.

14:06 Even if you're working with an ORM, sometimes you don't wanna bring all that data back to make some minor change.

14:11 but you would just do a sort of an update statement instead of pull back 10,000 models, change something and call save 10,000 times, right? Like it's probably that kind of tradeoff, but it's really cool that you can bring it back into Python this way. What are you using it for?

14:24 Like, what are you interested in using it for? - Well, I think we have a lot of these like ETL pipeline stuff, right? A lot of these, we have some data here and then we want to like basically clean it up and make sure it's all uniform and put in a dashboard, calculate some KPIs and whatnot, right? And so business people can see, are we doing better? Are we making more money or not?

14:41 And a lot of the times it's just SQL, right? It's also more accessible for a lot of people. So we stick to SQL, but there are also limitations, right? But before what I've seen is people just kind of go in the UI and just execute stuff ad hoc, right? So no versioning, nothing. And I think this kind of puts everything in one place. You can even add CI/CD because the CLI tool and everything, and just kind of make sure that everything goes to that versioned method, that let's say, I mean, and again, yeah, if you need something more fancy, right, then you can throw some Python stuff in there, but usually we try to avoid it, to be honest.

15:12 - I can imagine.

15:14 Let's see here, hold on.

15:16 Yeah, the models, the way you express the code, it's really nice looking for a SQL, which is surprising, right?

15:23 This code you write, like with customers as select these fields from this table.

15:29 - Yeah, and they have, they also have like the different macros and like people can write different macro, so like the describe function in Panda, someone can just have written that and you can import that and it's really nice to share all these things as well.

15:40 So super cool, really, really eager to give it a try, to be honest, I've been just like, try and scratch that.

15:45 - Yeah, wait, when's the next project that we get to use this on?

15:49 - Indeed, indeed, indeed.

15:51 - Yeah, all right, Brian, anything you want to add before we jump over to talking about our sponsor real quick?

15:56 - Yeah, no, let's talk about our sponsor.

15:59 - All right.

15:59 - So today's episode of Python Bytes brought to you by Microsoft for Startups Founders Hub.

16:05 The Microsoft for Startups set out to understand what startups need to be successful and created a digital platform to help you overcome those challenges and they came up with Microsoft for Startups Founders Hub.

16:16 The Founders Hub provides all founders at any stage with free resources to help solve startup challenges.

16:21 The platform provides access to expert guidance, skilled resources, mentorship, and networking connections, technology benefits, and so much more.

16:29 Founders Hub is truly open to all.

16:31 You don't need to be investor backed, but you can be.

16:33 Speed up development with free access to GitHub and the Microsoft Cloud.

16:38 You can unlock credits over time, and there's also discounts and benefits from innovative companies partnering with Founders Hub, such as OpenAI.

16:45 You'll have access to their mentorship network, which includes hundreds of mentors across a range of disciplines.

16:52 Need advice on marketing, fundraising, idea validation?

16:55 There's tons of topics, including management and coaching.

16:58 You'll be able to book one-on-one meetings with the mentors, many of whom are former founders themselves.

17:04 It's no longer about who you know.

17:06 Get critical support you need from Microsoft for Startup Founders Hub and make your ideas a reality today.

17:13 Join the program by visiting pythonbytes.fm/foundershub2022.

17:18 That link is also in your show notes.

17:20 - Yep, thanks Microsoft for keeping us going strong.

17:23 All right, what have I got next?

17:25 This one is a chain of really cool things.

17:27 So Roman Wright of Beanie fame and other things tweeted about this project that Pablo Galindo Salgado has been working on.

17:37 So Pablo was the release manager for Python 3.11.

17:40 It was part of the live stream of release and that was all fun.

17:43 But he also, I believe, works at Bloomberg where they work on memory.

17:47 And I think we spoke about memory quite a while back, Brian.

17:50 It's a memory profiling tool.

17:53 Maybe.

17:54 - Marlo, do you use profilers and that kind of stuff in your world?

17:58 - Not, I haven't used much.

18:00 Haven't had the need to be honest, not yet.

18:02 I feel like so far, there's no, try to keep it simple.

18:06 - So a lot of times profilers are about performance.

18:10 Like how fast did this code run?

18:11 And if it's slower, should I look at this loop or that loop or, you know, where do you spend your time making it faster?

18:16 'Cause it's really surprising when you look at code, you're like, this part looks complicated.

18:19 So that must be the slow part.

18:20 Like, no, that doesn't matter.

18:22 Nothing you do to that will make any difference.

18:23 You gotta look over here, right?

18:24 That kind of stuff.

18:25 But Memray, as the name would suggest, is more about memory profiling and like talking about how many of these different things have you allocated and those kinds of things.

18:35 What is coming?

18:36 Well, first, let me pull up, we have a pytest plugin, which is super cool.

18:42 So with the pytest plugin, you can do two things now.

18:46 You can say pytest --memray-tests, and it'll tell you things like, you can actually set limits on how much memory can be allocated for a certain operation.

18:57 And if it exceeds that, it'll say, oh my gosh, there's something wrong.

19:00 This thing is like way over using the memory we expected.

19:03 So that's an error.

19:04 But it also gives you like a cool emoji filled summary, I guess, like total memory allocated, the number of allocations, a histogram of allocation sizes.

19:16 So like Python memory has like size classes.

19:19 when we've talked about its block arena, one other term, I'm forgetting, that it uses to organize data structures.

19:27 And then you can actually get it overall then for individual tests.

19:31 And so it'll tell you like the different things that were allocated and anyway, it's pretty insane.

19:37 Okay, so you can get that report and then you can also, where's the other one?

19:41 I think it's, where was it?

19:43 There's a place where you put a decorator and you just say on this test, if it exceeds this amount of allocation that should fail the unit test.

19:51 It's just a pytest.mark.memorylimit or something.

19:54 I don't think it's a limit or memory limit.

19:56 I can't remember exactly what it's called.

19:58 You can say, if this test exceeds one megabyte of memory allocation, then that's a failed test, which is pretty cool, right Brian?

20:05 >> That's really great.

20:07 Yeah, they have a limit memory decorator and a check leaks decorator.

20:12 >> That's the one. So the check leaks is the new thing.

20:15 And so what you can do now is you can say pytest.mark.checkleaks as a decorator on your test.

20:22 And if there's a memory leak in the code that runs during that, it will let you know.

20:26 I don't know if anyone else has tried to track down memory leaks.

20:29 I would rather track down like a multi-threaded race condition than a memory leak.

20:33 I don't want anything to do with memory leaks.

20:35 This is no fun.

20:36 And so if I can do it with a decorator, let's do it.

20:38 - Well, and also decorating your tests so you're not having to modify your code at all to do this.

20:44 I mean, the code under test, you're modifying your test code.

20:46 If at all, it looks like it gives you some benefits even with no modification.

20:51 It's pretty cool.

20:52 >> Yeah.

20:52 >> Maybe, pardon my ignorance here, but when would I worry about memory leaks in Python?

20:57 >> I think, so imagine you're writing pandas, and you've written a bunch of C code that's getting imported, and you know there's a memory leak in there somewhere.

21:09 And it's just like, okay, well, I don't really know how to...

21:13 - But then it's more like the C part is the...

21:17 - You can also have memory leaks in the sense that you expected there to be no more things allocated after the function was called, but you could have signed it to a global variable or you could have, you know, stored it, held onto a reference in some way that you weren't expecting.

21:33 So it's not a leak in the super traditional sense, but it could build up if you're you're doing something wrong in Python, but certainly outside of that.

21:41 So I think this is pretty cool.

21:42 - Really any long running service is gonna have, you're gonna be concerned about it.

21:47 There's a lot of Python applications that are short running and it just cleans up after itself when it's done.

21:53 So there's cases, long running services, also things like, maybe you care about, things that are using large amounts of data and need all of the data that they can get ahold of without wasting any.

22:06 or that's important as well.

22:09 - Makes sense.

22:10 I'm also wondering-- - Yeah, if you're right at the limit, yeah.

22:12 - No, sorry, go ahead, go ahead.

22:13 - Yeah, if you're right at the limit of like, I'm using 15 and a half gigs, and I don't have more than that, so I need that.

22:19 Or like, I just checked the TalkByThon training site, it's been running for seven days and one hour.

22:24 Like, if it had a memory leak, you know, even if it's 100 kilobyte here and there, like it could turn out to be like a big hassle.

22:31 - Okay, cool.

22:31 I'm wondering if you could use this for edge device stuff, if we don't limit the memory, 'cause we know the edge device won't have that much.

22:39 - That's actually a really good point, because if you're on one of these CircuitPython little boards, they've got like 256K of RAM, and that's very different than 16 gigs, isn't it?

22:52 - Yeah, yeah.

22:53 - Right, but yeah, so you could test your application on a larger computer and limit how much memory you give it.

22:59 - Right, yeah, I think you would wanna do that with the limit rather than the check leaks, but still.

23:04 - Yeah, but it's the same, yeah, yeah, yeah.

23:05 - Cool. - Yeah, awesome.

23:07 All right, let's see, a couple comments from the audience.

23:09 Gareth out there, hey Gareth.

23:11 Says, "I ended up writing Docker containers "that swapped out every couple hours to solve it." I mean, that's actually what a lot of people do.

23:16 They're like, you know what?

23:17 If it runs more than 12 hours, there's a problem.

23:18 So we just tell it to recycle itself.

23:21 And then Madison says, "This is so cool.

23:23 "I need memory profile line all the time "with some of the data I do work with regularly." So people are digging it.

23:27 - Cool. - Yeah, very cool.

23:29 So thank you, Roman.

23:30 I know you didn't send that to us on purpose, but you shared it with us anyway.

23:33 - Nice. - Over to you, Brian.

23:35 Okay, before I get on to the next topic, I want to point out that Henry Schreiner, I'm going to paraphrase him by saying, "Brian, you dork, you didn't even read the article." Yes, you're right, Henry, sorry.

23:47 So the new prefixes I was showing, the previous new ones in '91, when they added Yocto and Zepto, these are not the new ones.

23:57 The new ones are down here with Rana Quetta, Ronto, and Quekto.

24:04 Yes, the reason why those sounded familiar is because they've been around.

24:09 These new ones, they're the new ones.

24:11 Okay, so thanks Henry for clarifying that.

24:14 But on to the next topic is Will McGugan says, "Please steal my source code." So he wrote an article, Will McGugan wrote an article, stealing open source code from textual.

24:27 And he says, I would like to talk about a serious issue with free and open source software, stealing code.

24:35 You wouldn't steal a car, would you?

24:37 And then actually he has this funny video that he embeds about like how like digital piracy really is like stealing.

24:44 And it's sort of a funny video.

24:47 But the comment is real that like you need to, you can steal code from open source projects as long as you can.

24:55 So please read the MIT license or read the license to make sure that you can.

25:01 And in a lot of cases you can.

25:03 So like, I'm gonna give an example that I use a lot is I'll think of something that I wanna do.

25:10 Like I'm interacting with a library and maybe I don't quite get how to do that with the documentation.

25:15 I can search GitHub for projects that use that library also as an example.

25:20 And so that's a way to look at other source code how to interact with a project that maybe doesn't have the greatest documentation.

25:27 You can see how it's done.

25:29 >> I've honestly never thought to do that.

25:31 That's a great idea.

25:32 >> That's good.

25:33 >> I'll go look at the test and stuff.

25:34 I'm like, these tests suck.

25:35 There's not a single one that shows me this use case that I'm looking for.

25:39 This is brilliant.

25:41 >> I do that a lot with pytest plugins because I look at how other plugins are testing their stuff.

25:48 I'm like, how do they do it?

25:51 But so the warning there is he's not advocating for piracy.

25:55 Open source code gives you explicit permission to use it.

25:59 If you're actually just copying the whole thing, you probably should reference it and use the same license, or if you're copying large chunks.

26:07 But the MIT license, for example, says it's substantial copying.

26:11 So a little bit of copying is fine.

26:14 Will says, Textual has some cool stuff in it that you might want to look at.

26:18 So he's got a loop. He points out some things you might want to steal.

26:21 the loop first and last, so he's got a loop iterator that he's got a couple versions of it that will not only iterate through things, but it'll it'll give you, it'll note which one's the first and the last. So if you need to do something cool on something different on the first and the last one, do that.

26:40 He tweeted recently or tooted or whatever about the LRU cache as well.

26:46 So the Python's got a built-in LRU cache, but everything's global, so you can only there's limits on how you can interact with it.

26:53 So he has a more flexible LRU cache.

26:56 He's got a color class that looks pretty cool that you can convert to different color representations, that's pretty neat.

27:02 Then you know he's been working on a ton of geometry stuff, 2D geometry.

27:06 So he's like, you might want to use this for whatever 2D geometry you're using, so here's there.

27:11 So cool reminder that open source, one of the benefits of open source is you can see the source and learn from people.

27:18 >> I like it. I love your idea.

27:21 >> You've never done that. I'm like, in my dance, I just can't figure this out.

27:26 How are other people using it?

27:28 >> I just get frustrated and go into a new library.

27:30 This one sucks. I can't do this. I'm going to find another one.

27:32 >> It's not good enough.

27:33 >> Merlo, are you an open-source thief?

27:35 Do you do this kind of stuff?

27:37 >> I have to admit, yes. Yes, I am.

27:39 Stack Overflow thief, open-source thief, especially in the early days.

27:44 But I think with the rich stuff too, it's very inviting for you to steal code.

27:49 'Cause even on the rich package, right?

27:51 Like if you do Python-m rich table or whatever, you always show some really nice stuff on the terminal, right?

27:58 And I was like, how does he do that?

28:00 Or like, I think for every component, he had a little demo that you can just run.

28:04 And it's very tempting.

28:06 Even if you didn't want people to steal stuff from him, I feel like you have a hard time just keeping the thieves away, you know?

28:11 - Yeah, yeah.

28:12 Yeah, very cool.

28:13 And funny too.

28:14 I like it.

28:15 Good job.

28:16 Where are we at now?

28:18 Off to Marlow's final item.

28:21 Yes.

28:22 This one I had not heard of either and it looks pretty interesting.

28:24 Yeah, I mean, it's a, I think it kind of, it's one of the things that I saw, I was like, yeah, this makes so much sense.

28:29 Why, how come I never, I didn't think of this before.

28:32 But this is Shed.

28:33 I mean, this is a podcast, right?

28:35 So maybe, Shed is, it basically, I think it's related to like bike shedding, shed your legacy code, right?

28:43 So it's like a super set of black, right?

28:45 it black++ here. So they say here, maximally opinionated auto formatting tool, right? So it's all about configuration over convention over configuration, which is also something that I can subscribe to. They have no configuration options, but basically it's a bundling of a lot of tools, right? So they have black here, but they also have isort and with the profile black, so it doesn't clash. They also have pyupgrade, which I think you guys mentioned a couple of times, >> Yeah, we did.

29:13 >> Out of Flake as well.

29:14 Out of Flake, I didn't know actually before, but basically it removes unused imports and unused variables from your Python code.

29:23 It's like, "Yeah, that's all I wanted." >> I wish I had this last week.

29:28 >> There you go. Yeah. It's a one-stop shop, and even do like a blackened docs.

29:34 If you have doc strings or markdown or everything, it will take that, it will black format that for you.

29:38 I was like, "Yeah, this is what I wanted." >> Okay. Hold on. Black in Docs.

29:43 This is new to me too. All right.

29:44 >> Yeah. Let's see.

29:46 >> So this is black on Python blocks, a sample code blocks.

29:50 >> Yes. So if you have a restructured text, markdown, even doc strings, it will format that for you.

29:56 >> You like blackening your readme, for instance.

29:59 >> Yes.

30:00 >> Yes.

30:01 >> Oh, okay.

30:03 >> This is good.

30:04 >> So I have some stuff to talk about at the very end, just a little bit about blogging and writing and some platforms and stuff, and it's all in Markdown.

30:12 Like I could run this against all of my code samples on my blog, so basically auto-format all code in the blog.

30:19 >> That would be cool.

30:20 >> Yeah.

30:21 >> Yes. Exciting.

30:23 >> The next time I write a book, I'm totally going to use that.

30:25 >> Yeah, or if you're doing a book, yeah, I mean, absolutely.

30:28 >> So I literally just like yesterday, the day before, I was cleaning up some code.

30:34 I finally got, I don't do it clean the whole time.

30:37 I get it to work and then I look at what I did stupid.

30:41 There might be some imports laying around that I thought I needed.

30:45 Because you add an import and then you take that code out, but you sometimes forget to take the import out.

30:50 I ran black on everything, of course, and then I run Flake 8 and I'm getting errors.

30:55 I'm like, "Shoot, why didn't black just take those out?" Now I've got shed and I take those out.

31:00 >> It does it all. It's great because maybe it's the same.

31:03 You have Flake 8 is like, "Oh, yeah, unused variable, okay, they have to go there one by one, you know, it's like, it feels like there should be a nicer way, right?

31:10 Yeah, I mean, it's good.

31:12 You have to pay attention to that because your unused variable might be a typo or something.

31:17 You might think you're using it.

31:19 But that's true.

31:20 Yeah, or it's like a global variable module supposed to share with something else.

31:24 And it's a library.

31:25 But in general, I mean, you could probably put like a hash, no QA or something on it.

31:29 Well, I mean, yeah.

31:30 And also your, your, your testing.

31:32 So your tests will catch it if you delete too much.

31:34 So yeah.

31:35 - All right, well, really, really good one.

31:39 Take your code out to the shed and whip it into shape behind the shed.

31:43 - That's it.

31:44 All right.

31:45 - All right, well, Brian, what else we got?

31:46 Extras?

31:47 - I got some extras.

31:48 You got some extras.

31:49 Who should go first?

31:50 - You go first.

31:51 - Okay.

31:52 Well, the thing that I've been working on is by test check.

31:56 And I finally got, and I've been talking about this for like a month, because I've been slowly pulling this into shape.

32:03 almost a complete, not really a rewrite, but I moved everything around and the code's a lot easier to read and so it makes me happy.

32:09 And I also changed the API.

32:11 So I wanted to mention to everybody that you can either use, so you can either use from pytest check, import check to get this check object, or you can stick the check object as a fixture.

32:24 And either way, you get access to everything in the library.

32:27 That's the only thing you have to do.

32:28 And for people unfamiliar, I took check is a library that allows you to have multiple failures per test.

32:34 You know, normally the recommendation is try to fail on one thing, but sometimes you need lots of data.

32:40 And I just threw in a little example that uses both.

32:43 So if like it's using HTTPS to grab the status code, and as long as the status goes 200, then I can check a whole bunch of stuff.

32:52 I can check to make sure the redirect and encoding is right and check for some stuff inside the...

32:58 I mean, these could be multiple tests, but if it really is, you're checking multiple parts of things.

33:03 And for scientific work that I'm in, measurement work that I do, I'm often checking like tons of aspects of a waveform.

33:10 And it's really just making sure the waveforms right and that rightness is multiple checks.

33:15 So use that.

33:16 Anyway, I didn't intend to break anybody, but I did break Brian's skin.

33:21 So Brian came up at the beginning of the article, but he tagged me in a GitHub issue on his project.

33:27 and I looked at it and I'm like, "Oh, I didn't intend to break that." So I fixed it this morning.

33:31 So hopefully, if anybody gets broken by this, I was not intending to break anybody, just let me know and I'll try to fix it.

33:39 >> That looks great.

33:40 >> How about you?

33:41 >> Merlo, I know you have some as well.

33:42 It goes well, sorry.

33:44 I don't know too much.

33:46 >> Maybe. Yeah, I feel like I should have opened that.

33:49 I didn't have the link up here.

33:51 But I'm talking about breaking stuff.

33:53 Flakate is not on GitLab anymore.

33:57 And I actually didn't have issues with that 'cause with pre-commit, right?

34:00 You have to specify the repo.

34:02 I already was on GitHub, but I actually heard from people, some people that they heard a lot of noise that Flake 8 is not on GitLab anymore.

34:08 And then there was also this video from Anthony that is maintaining, right?

34:11 Pre-commit and Flake 8.

34:13 He was explaining a bit 'cause why, what was the motivation from going from GitLab to GitHub?

34:17 And yeah, like what's relatable is that like, sometimes you break people's code, but it's like, it's not intention, right?

34:24 But sometimes people can get very heated over these things.

34:26 So yeah, just maybe public service announcement, change your Git repo to GitHub now for using Flakegate as a pre-commit.

34:34 - You also had mastodon.py, right?

34:36 - Yes, yes, yes, I did.

34:38 I just, sorry, I flipped the order 'cause I thought it was a segue there.

34:43 - Yeah, yeah, yeah, I wish I knew about this like a week ago or so.

34:47 That would have been awesome.

34:48 - You covered a toot, I think, right?

34:51 - Yes, we covered toot, that's right.

34:52 - Yeah, yeah, so this is, to be very honest, I wasn't the one that found this, it was my boss.

34:58 So shout out to Bart, if you're listening right now.

35:00 But this is basically just a wrapper around the Mastodon API, right?

35:04 So you don't have to do requests.

35:05 You can usually have like a nice client library there to do all these things.

35:07 So if you wanna play around, create some bots, you know, whatever, then yeah, there's a nice convenient package now for you to do it.

35:15 - Wow, this is really cool.

35:16 And it has, you know what?

35:17 Documentations that say what functions it has.

35:19 I love it.

35:19 (laughing)

35:20 - Documentation?

35:21 (laughing)

35:22 It's a dream come true.

35:23 - It doesn't have to be much, like the seven or eight lines of code that are in the readme, like gives you a really good boost, but it lets you register your app, which is one of the things if you go to the website, it'll show you which apps are registered for your access keys on Mastodon, but it won't let you create one on the website.

35:39 So it's like a simple create app, and you just give it a instance name and what file to save the access tokens over to, and boom, you're good to go.

35:46 - Yeah, have you guys already done stuff with Mastodon?

35:49 - Yeah, you know, on the stream deck, the thing that controls the stream, I already wrote that thing where I push the one button, it sends out the message automatically that this live stream is starting.

35:59 And yeah, that uses a little bit of toot and mostly just the straight API with HTTPX.

36:05 But if I'd known about this, I would've used it.

36:08 - Now we know.

36:09 - Yeah, no, thanks for sharing that.

36:10 Anything else you wanna share before we move on?

36:12 - Yes, so there are a couple more things.

36:14 But this one, this is the Brazilian EME that couldn't resist.

36:18 The World Cup started.

36:19 I don't know, are you guys soccer fans or not at all?

36:22 So we've a fun soccer team here.

36:24 We go see-- I go see with the kids and stuff in town.

36:27 Yeah, so I'm also in machine learning, so a lot of data.

36:31 And this time of the year, there's a lot of like, oh, yeah, the AI models are predicting this, this, and--

36:36 This one is one from Oxford.

36:37 So I just wanted to give a quick shout out here.

36:39 So they have a video on YouTube as well, which is cool.

36:42 They explain the math.

36:43 And I will go on a limb here and say they use Python because they even mention Matplotlib and whatnot.

36:47 But this is basically just a big excuse to say that they predict Brazil to win.

36:51 So if this doesn't happen, it's all rigged.

36:55 The math supports this.

36:56 So Brazil must win this World Cup.

36:58 And anything that is not there, I'm going to be extremely disappointed.

37:01 This is really cool.

37:04 People are always looking for realistic examples to learn and explore libraries and tools.

37:09 And if you're into soccer and you care about the World Cup, this is great.

37:12 Yeah, I think if you...

37:14 Yeah, there's people, people are very creative.

37:16 I feel like there's a lot of uses for it.

37:18 Well, I'm sure this will happen because there's absolutely no corruption in soccer.

37:21 So yeah, yeah, for sure.

37:22 Yeah, not at all.

37:25 Not at all.

37:26 Cool.

37:27 Should I just keep going or you want to take over?

37:30 If you got more items?

37:32 Yeah, keep going.

37:32 I have.

37:33 I have two more.

37:35 Sorry.

37:36 I know you said I could have more than two.

37:37 So that's what this whole section is about.

37:40 One.

37:42 So for me as a data scientist or machine learning engineer, we use a lot of notebooks, right?

37:46 And I think they have their place in data science, but there are some tools that don't play very nicely with it.

37:51 And I think in Git diffs or PRs, they don't play so nicely.

37:56 So this is, I think it's public preview, I want to say, but I haven't actually seen this, but now GitHub is going to start supporting notebook diffs.

38:03 So if you have a pull request, they're going to have a nicer rendering of the notebook here and you can actually see what the differences are.

38:09 And I think before there was a tool called ReviewNB that you could add to GitHub, but But yeah, now they're just going to start supporting it.

38:17 So I haven't seen how it looks, but I'm pretty excited about this too.

38:20 One less headache for me.

38:21 Yeah, that's excellent.

38:22 Because before the diff would just be like, here's the diff of the JSON file.

38:25 You're like, no, that's not what it was.

38:27 And also JSON is just JSON, just key value.

38:29 So if you just change the order of some keys, it's just like, yeah, you have a lot of changes, but you don't care.

38:34 Yeah.

38:35 Oh, this looks really useful.

38:36 Yeah.

38:37 And maybe one last, if that's okay.

38:39 Yeah.

38:40 Just pull this here.

38:41 This is Lancer.

38:42 So it's another CLI tool.

38:43 about linting before, right?

38:45 So this is another kind of linting.

38:47 And I say kind of, 'cause so, you know black-- - Some definition of linting or clean up, yeah.

38:56 - So this is like black, almost like black, but it's the opposite.

38:59 So instead of making your code look nice, it would just make it like a hideous, but working mess, right?

39:04 So these are some of the features.

39:06 It turns all your comments to pitbull lyrics or something safe for work, depending if you want.

39:11 It takes all your variable names and mix into like animal sounds and horribly similar looking characters.

39:17 So like bark underscore bark underscore 0 0 0 0.

39:22 It adds white spaces.

39:24 It adds completely irrelevant comments and the code still runs after these improvements.

39:29 So here's an example.

39:30 - I love it.

39:31 - Yeah.

39:33 You have here some comments and everything.

39:34 So before like nicely formatted and then afterwards you see some comments like a bada bing bada boom, you know.

39:40 There's nothing like Miami heat.

39:42 some alpha characters in your variable names.

39:44 So pretty good stuff.

39:47 Again, I must say I haven't used this, but this is a tool that I'm not as excited to use.

39:52 - I mean, there's always times that you need to send out your code to different places and you would rather share it less than more.

40:01 Thinking of like if you make a desktop app and you got to send out the code for that or whatever, and you would want to obfuscate it.

40:08 You want to make it harder for people to just pick it up and like do stuff.

40:12 you could hit it with this, they'd be like, yeah, no, no, we're just not doing that.

40:15 - So my favorite one's on the screen is the adding obvious comments, like setting the value of some.

40:22 That wasn't in the original and it's just funny to, I mean, that's actually not gibberish, it's just useless.

40:33 - It's really good.

40:38 The comments out in the live stream are really great as well, people are enjoying it.

40:43 One of them is it's great for Twitter employees.

40:45 You can maximize your lines of code for review as it's coming up.

40:48 Then you just print it out and you take it, and sidebar, like if somebody says print out my code so we can review it, they're not equipped to review the code that you may have written.

40:58 Like if the word print involves in evaluating code, like no, all right, I don't think so.

41:02 So leave that where that is.

41:05 But you could put this on top of like, yeah, I'm kind of funky when I write codes.

41:09 It's a little different.

41:10 Let's get used to, let's, yeah, I just, it's a farm.

41:13 It's a code farm.

41:14 Oink, oink, oink.

41:16 - Yeah, you can have two sets of books, kinda.

41:19 You got your real repo and then you use this to put it into the actual one that you submit.

41:26 And you're like, I understand it.

41:27 I don't know what your problem is.

41:29 - It works on my machine.

41:30 - I kinda wanna run this on a large code base.

41:35 Like something really complicated.

41:38 Squash all the commits, force push.

41:41 - Like textual, fine.

41:44 Release it as textual oink oink or something.

41:46 - Yes, I love it.

41:50 - Cool.

41:50 - All right, well this was a good find.

41:52 Awesome, thanks.

41:53 All right, I'll make mine quick here.

41:54 So a new YouTube video, I talked about how you can install the Mastodon web app on your iPad as a native app, as well as on your desktop.

42:03 So if you're doing that kind of stuff, not there.

42:07 Basically, they just released Mastodon 4 a couple days ago, and all the apps don't have features like edit and some of the other features that are there because they're like months behind.

42:18 And so if you install the web app as an app, then guess what?

42:21 It looks like an app, it acts like an app, but it has like zero latency.

42:24 So as soon as something is released on the website, you get it, which is pretty cool.

42:27 So people can check that out.

42:29 I saw Madison in the audience, she sent over a call for proposals, calling all Pythonistas, if you will, for PyCascades.

42:38 So PyCascades is back in person this year in Vancouver, BC.

42:41 It goes from Vancouver to Seattle to Portland and cycles through that there.

42:46 But so this year, it's going to be in Vancouver.

42:49 So if you want to go up there and talk, be part of the conference, good conference.

42:53 So call for proposals are open there.

42:55 Yeah, but they're not open for very much longer.

42:57 So jump on that.

42:59 I don't remember what the date is, but...

43:00 It closes Wednesday 30th.

43:04 So what is that?

43:04 - Yeah, eight days. - Well, Wednesday, yeah, next Wednesday.

43:06 Yeah, eight days.

43:08 And Madison, and if you're in the audience, thank you.

43:10 Is put it in person this time, and we really value the first time speakers in atypical talks.

43:15 So get out there and put yourself out there and get into public speaking.

43:19 It's not a huge conference, but it's big enough, couple hundred people, three, 400 people, fun time.

43:24 This is just really quick and fun.

43:27 You know, if you're on a Mac, you're not as likely to get viruses sent your way that would actually be able to do something like 90% of viruses are written for Windows.

43:35 But what's a really interesting fact, I just, if you do have a Mac, it turns out 50% of all macOS malware comes from one single app.

43:43 Can you believe that?

43:44 - What is it, Safari?

43:46 - No, it's MacKeeper.

43:49 So if you have MacKeeper, it like organizes your files, and it'll like clean up your junky cache and stuff.

43:56 But apparently it has to take over so much permissions, and it is like, it can get, I guess, plug in or I don't know what it does, but people can like plug into this and make it to all sorts of horrible stuff.

44:07 So 50% of all malware is written for Mackeeper.

44:10 So if you have Mackeeper, maybe unhave it.

44:17 I recently as a Sunday launched a new website that I hope will bring me back to writing some more.

44:24 We'll see about how that goes.

44:25 But here I'm, I'm trying a new philosophy on, on blogging, Brian, I don't know how you feel about it, but I have a blog, been doing it for a long time, but like I looked, the last article I wrote was like 2020. I'm like, oh, that's not so good. And the reason is I would always try to write like 2000 word posts that are really, and I'm like, but I could post to Twitter and mass it on all day. And it's like, I can just do that. That's no problem. I don't like fall behind on Twitter. I'm like, well, that's because these really should be super short posts. So I have, I've got this new website that I wrote that are just super short, you know, fits on a page type of articles that people can go and check out.

45:01 So yeah, some of the people, some people are promoting like today I learned things, but short and why not?

45:07 I mean, if you think it, if you think it's going to be a thread, write a blog post.

45:12 Exactly.

45:13 Yeah.

45:14 Yeah.

45:15 Cool.

45:16 So all of these are written and this is all based on Hugo, which is a just learned about it, but a ridiculously cool static site generator.

45:22 Either of you played with Hugo?

45:23 I use it.

45:24 I love it.

45:25 So python test.com is written on Hugo.

45:28 It's ridiculous, right?

45:29 No, Merlo.

45:30 You haven't.

45:30 Sorry.

45:31 Yeah, no, I haven't used it, but I heard of it.

45:33 Yeah.

45:33 Yeah.

45:33 I heard nice things.

45:34 Yeah.

45:34 So you basically just go to your directory of markdown files and images.

45:38 Hugo dash D server or whatever.

45:40 And then as you write, you have your, your web page open in your browser and automatically sees the markdown file changes or the CSS changes, regenerates it and refreshes your browser.

45:50 Just so your browser could be just over there and it's just periodically as you make changes, it instantly refreshes.

45:56 So you don't even go and refresh the page.

45:58 You see how that you just write and the browser just watches and, and reloads.

46:02 It's cool.

46:02 Yeah.

46:02 And I, so you got it so that you just, you just push it, push your changes to get hub or your repo for, and it just appears on your website.

46:10 Exactly.

46:11 Yeah, exactly.

46:13 So that was my, my next thing is then I set up a Netlify free account with CDN SSL, custom domain name.

46:19 Push.

46:19 It just has a prod branch that I connected it to.

46:21 And when I pushed a prod, boom, it just goes there instantly.

46:24 So anyway, people are looking at that, that is super cool.

46:26 - Push to prod, oh that's kind of cool.

46:29 I just edit on prod, so.

46:30 (laughing)

46:31 - I just log in, I edit over SSH.

46:34 - Yeah.

46:35 - Just edit on the server, the server is the backup.

46:37 Anyway, I have stuff on the screen, but there are no more backups, that's just stuff I pulled up while we were talking.

46:41 So no more extras I mean.

46:42 So yeah, fun stuff.

46:44 People check out the blog website and the video and apply for speaking at PyCascades.

46:51 - Nice.

46:52 I feel like Lancer also was like already really funny, but do you have anything else funny for us or?

46:57 - I do, although I somehow forgot to pull them up on the screen.

47:00 So give me just a second here.

47:01 There's two, these are really good, okay?

47:04 These are pretty epic.

47:06 So this one is called, I think Merlo, you'll really like this one 'cause it has to do with like algorithms and data science.

47:14 And it's called Messing with the Algorithm.

47:16 And it shows this dude here, don't mind the thing at the bottom.

47:19 I have no idea what that's about.

47:21 But see there's this guy whose face is blurred out in the UK, I think, I can't remember where this was.

47:26 No, Berlin.

47:27 And he's got a wagon, like a little red wagon that you pull behind you, full of 99 phones.

47:34 Now what he did is he got them all running Google Maps and left them open and started walking down the street real slow and notice his neighborhood is now red on the map and he got it so he thinks there's a traffic jam and he'll send cars around his neighborhood.

47:47 - Nice.

47:49 I wanna get one of these so bad and whenever I take my dog for a walk, just walk with the wagon behind me too.

47:55 - This is no cars.

47:56 - Yeah, so good, isn't it?

47:59 - Yeah, this guy's so ahead of our time.

48:01 He's just like--

48:02 - Oh, he's so brilliant.

48:03 - Yeah, he's working out for his neighbors.

48:05 - Yeah, the next one here is gonna take a little bit of, I gotta set the stage, give me a second to set the history.

48:11 Have you heard, you've heard about these motivational posters?

48:14 You go to like a dentist's office, it'll be like an eagle soaring over like a sunset.

48:18 Like if you don't spread your wings, you'll never soar as high as you could or something cheesy like that.

48:22 - Yeah, it's pretty small clusters.

48:24 - Yes, exactly.

48:25 There's a company called Despair.

48:26 And Despair creates these but like in reverse.

48:30 They're called the demotivators.

48:31 - Yeah, nice.

48:32 - So have you seen these?

48:33 - No.

48:34 - Okay, so here's one like Solutions.

48:36 And what does it say?

48:36 It has like a Rube Goldbergian type looking thing here.

48:40 And it says, "Solutions, this is what happens "when the problem solver gets paid by the hour." (laughing)

48:47 It's just out of control.

48:48 Here's one.

48:49 What is this?

48:50 It's a frog wearing with a snail on its head.

48:52 It says, "Collaborate so the best of us have to carry the rest of us." It's just like, they're really...

48:59 All right.

49:01 So that brings us to...

49:02 I feel like this is a Brian Skin show a little bit.

49:04 This tweet that he shared here, and it has the latexify thing, but recursion.

49:13 And for the recursion, it has that demotivator.

49:15 There's a picture that said recursion. Here we go again, and then embedded in that is the recursion. Here we go again It's like that. Yeah, like your screen share you see your own screen. Yeah, so it's kind of like that poster but for recursion Yeah I kind of feel bad that people people that don't get the recursion joke because they can't even look it up because it just It's redirected. It just keeps going like I the definition is the definition. It's right. Nice. All right Well, that's what I got for you all. Well, thanks everybody Thanks, Michael, of course, and thanks, Merlo, for coming on the show.

49:45 Thanks for having me. It was great.

49:47 Yeah, you bet. Bye, everyone.

Back to show page