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

#173: Your test deserves a fluent flavor

Published Thu, Mar 19, 2020, recorded Thu, Mar 12, 2020

Sponsored by Datadog: pythonbytes.fm/datadog

Brian #1: Advanced usage of Python requests - timeouts, retries, hooks

  • Dani Hodovic, @DaniHodovic
  • “While it's easy to immediately be productive with requests because of the simple API, the library also offers extensibility for advanced use cases. If you're writing an API-heavy client or a web scraper you'll probably need tolerance for network failures, helpful debugging traces and syntactic sugar.”
  • Lots of cool tricks I didn’t know you could do with requests.
    • Using hooks to call raise_for_status() on every call.
    • Using sessions and setting base URLs
    • Setting default timeouts with transport adapters
    • Retry on failure, with gobs of configuration options.
    • Combining timeouts and retries
    • Debugging http requests by printing out headers or printing everything.
    • Testing and mocking requests
    • Mimicking browser behaviors by overriding the User-Agent header request

Michael #2: Fluent Assertions

  • Via Dean Agan
  • fluentcheck helps you reducing the lines of code providing a human-friendly and fluent way to make assertions.
  • Example (for now):
    def my_function(n, obj):
        assert n is not None
        assert instanceof(n, float)
        assert 0. < n < 1
        assert obj is not None
        assert isinstance(obj, MyCustomType)
    

can be

def my_function(n, obj):
    Check(n).is_not_None().is_float().is_between(0., 1.)
    Check(obj).is_not_None().is_subtype_of(MyCustomType)

With a PR I’m working on (now accepted), it’ll support:

def my_function(n, obj):
    Is(n).not_none.float.between(0., 1.)
    Is(obj).not_none.subtype_of(MyCustomType)

Brian #3: Python in GitHub Actions

  • Hynek Schlawack, @hynek
  • “for an open source Python package, … my current recommendation for most people is to switch to GitHub Actions for its simplicity and better integration.” vs Azure Pipelines.
  • Article describes how to get started and some basic configuration for:
    • Running tests through tox, including coverage, for multiple Python versions. Including yml config and tox.ini changes necessary.
    • Nice reminder to clean out old configurations for other CIs.
    • Combining coverage reports and pushing code coverage info to Codecov
    • Building the package.
    • Running twine check to check the long description.
    • Checking the install on Linux, Windows, and Mac
  • Related:

Michael #4: VCR.py

  • via Tim Head
  • VCR.py simplifies and speeds up tests that make HTTP requests.
  • The first time you run code that is inside a VCR.py context manager or decorated function, VCR.py records all HTTP interactions that take place through the libraries it supports and serializes and writes them to a flat file (in yaml format by default).
  • Intercept any HTTP requests that it recognizes from the original test run and return the responses that corresponded to those requests. This means that the requests will not actually result in HTTP traffic, which confers several benefits including:
    • The ability to work offline
    • Completely deterministic tests
    • Increased test execution speed
  • If the server you are testing against ever changes its API, all you need to do is delete your existing cassette files, and run your tests again.
  • Test and Code 102
  • pytest-vcr: pytest plugin for managing VCR.py cassettes
    @pytest.mark.vcr()
    def test_iana():
      response = urlopen('http://iana.org/domains/reserved').read()
      assert b'Example domains' in response
    

Brian #5: 8 Coolest Python Programming Language Features

  • Jeremy Grifski, @RenegadeCoder94
  • Nice reminder of why I love Python and things I miss when I use other languages.
  • The list
    • list comprehensions
    • generator expressions
    • slice assignment
    • iterable unpacking
    • negative indexing
    • dictionary comprehensions
    • chaining comparisons
    • f-strings

Michael #6: Bento

  • Find Python web-app bugs delightfully fast, without changing your workflow
  • Find bugs that matter: Checks find security and reliability bugs in your code. They’re vetted across thousands of open source projects and never nit your style.
  • Upgrade your tooling: You don’t have to fix existing bugs to adopt Bento. It’s diff-centric, finding new bugs introduced by your changes. And there’s zero config.
  • Go delightfully fast: Run Bento automatically locally or in CI. Either way, it runs offline and never sends your code anywhere.
  • Checks: https://bento.dev/checks/

Joke:

https://trello-attachments.s3.amazonaws.com/58e3f7c543422d7f3ad84f33/5e5ff5b454e93258e907753b/ecd7567c50cc0d073820bf961f489365/debugging.jpg

Episode Transcript

Collapse transcript

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

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

00:11 And I am Brian Okken.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

01:50 Oh, yeah. Nice.

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

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

02:06 prepended to everything else later.

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

02:14 requests, which is pretty awesome.

02:15 Oh, does it? Okay.

02:16 Yeah. Yeah. Yeah.

02:16 That's cool.

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

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

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

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

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

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

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

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

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

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

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

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

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

03:17 I'm not sure.

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

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

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

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

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

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

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

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

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

04:03 neat actually.

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

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

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

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

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

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

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

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

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

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

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

04:50 see what they think about that.

04:51 Yeah.

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

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

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

05:05 Yeah, a little bit. Yeah.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

09:14 that sounds neat.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

12:48 So that's kind of cool.

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

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

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

13:00 Yeah.

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

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

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

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

13:21 Yeah.

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

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

13:30 What is this place?

13:30 Yeah.

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

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

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

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

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

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

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

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

14:09 Yeah.

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

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

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

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

14:27 Yeah.

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

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

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

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

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

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

15:01 that?

15:01 Yeah.

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

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

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

15:13 just replays it back to you.

15:14 Yeah. It's pretty clever.

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

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

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

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

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

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

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

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

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

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

16:04 new cassette.

16:05 Yeah. Nice.

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

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

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

16:26 it. Magically, it works.

16:27 Yeah. Okay. Nice.

16:30 Yeah.

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

16:34 Yeah.

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

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

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

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

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

17:04 to get something different back.

17:05 Right.

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

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

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

17:20 Yeah.

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

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

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

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

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

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

17:53 that's the big appeal.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

21:18 it would be nice.

21:18 Interesting.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

22:21 Right.

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

22:27 Just the lunch style?

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

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

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

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

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

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

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

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

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

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

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

23:42 you. Oh, very cool.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

25:38 sense. Yeah.

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

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

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

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

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

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

26:13 comes from that realization.

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

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

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

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

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

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

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

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

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

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

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

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

27:09 Oh, please.

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

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

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

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

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

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

27:47 Yeah.

27:48 No.

27:49 It was me.

27:50 It was me.

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

27:57 Definitely.

27:59 Yeah.

27:59 Love that.

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

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

28:06 Exactly.

28:07 Or doing something boneheaded.

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

28:12 Thank you. Bye.

28:13 Bye.

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

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

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

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

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


Want to go deeper? Check our projects