Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.
This is episode 171, recorded February 26, 2020.
I'm Michael Kennedy.
And I'm Brian Okken.
And Brian, we have a special guest.
Yeah.
Hey, David. How are you doing? Welcome to the show.
Doing good. Thanks for having me.
Yeah, it's great to have you here.
Always nice to have a different, fresh voice to come join me and Brian,
or sometimes to replace us, depending on what we're up to.
Yeah, so great to have you here.
Also, the show is sponsored by Datadog.
Check them out at pythonbytes.fm/datadog.
Tell you more about that later.
David, let's start off with you.
Let's talk about decorators.
Do you feel like decorators are one of the more mysterious things that people work with in Python?
I think so.
You know, it's something that I think a lot of people either don't brush up against too much,
or they just sort of mysteriously appear in a framework they're using.
Right. I type app.route and it works, so I'm going to type that.
I don't know.
Exactly.
But did you know that there's actually a grammar restriction on what you can actually put in it in a decorator,
how you can actually call it?
So it's basically, I remember, it's like dotted.
I can have names that are dotted, so like flask.app.route or something like that.
Not quite right, but you know, that syntax.
And then parenthesis, I can put stuff in there or not.
Correct. Yeah.
I didn't know that there was actually so much of a restriction on this.
So right now it requires that a decorator consists of a dotted name,
optionally followed by a single function call and method call.
Right.
And there's a new PEP out that proposes relaxing these grammar restrictions a little bit.
It's PEP 614.
It's still in draft.
It was submitted, I think, February 11th.
So it's pretty recent.
Yeah, that's like 14 days old.
Yeah.
Something like that is brand new.
And so the issue goes back way back to 2004, where I guess Guido proposed these limitations.
And the use case highlighted by the PEP that they think we should change this is actually comes from the PyCube 5 library,
where say you've got a list of buttons, list button 0, button 1, etc.
And you want to, they've got a decorator that's called as a method on a class attribute on those buttons.
Right now what you can't do is say, so the decorator is called button.click.connect.
What you can't do is say, I want to do button subscript 0.click.connect.
So what you have to do is first extract one of the list items into a variable name and then access the method that way.
And what I thought was actually a strong argument for changing this was that the author points out that there's kind of a hacky way you can get around this
by you can define a function that takes a single parameter and then just returns that parameter.
And then you can wrap your object that has the decorator in it with that function to access it however you want.
I see. So basically you make like a decorator decorator that returns the decorator you hoped you could write directly, but here we go, right?
Exactly. And so you start getting into things that are way less readable than if you could just subscript that to get what you want out of that.
So the pet proposes relaxing the grammar to any valid expression.
That's kind of in quotation marks because it's really anything that you could use say as a test in like an if, lf, or while block as opposed to say something like any valid input to like the eval function.
Right, right.
You can't put a program there.
Yeah, so not everything would be allowed.
Like if you have a tuple, you couldn't with two objects x and y in it, you couldn't do like at x comma y.
Although I'm not really sure why you would be using a tuple as a decorator in the first place.
But anyways, the author went ahead and did like an implementation draft on CPython.
He's got a fork of CPython where you can actually pull this down and check it out and see how it works.
It makes sense to me.
You know, it's moving the complexity around.
It does make it more complex, but you know, these decorators that take function or take parameters that then generate other decorators that then wrap the real thing.
Those are also not super simple or obvious.
So yeah, it seems reasonable to me.
Brian, what do you think?
Sure, why not?
Let's throw some more stuff in the syntax.
Yeah, maybe we could use a walrus operator on it.
Yeah.
Actually, I had a funny run in with the walrus operator.
I was so excited.
I started using it.
I'm like, oh, this is the perfect case for it.
And I put it all together and then I rolled it out onto the server and I'm like, oh, the server, the website won't start anymore because, well, it's on Ubuntu LTS, which is running Python 369 or something like that.
And I guess I can't use the walrus operator after all.
Oh, no.
Not without, you know, changing more than I really cared.
It was like three lines of code.
I was fine.
I'll put them back.
You know, but I was like so happy.
Anyway, yes, let's not put those in decorators.
Yeah.
All right.
Well, the next thing that I found that I thought was pretty interesting, this is an article from, you know, six months ago or something like that.
It's not super brand new and fresh, but I don't, I know that we haven't talked about it and it seems really, really useful to me.
So let's start by just talking real quick about the Mac menu bar, that thing across the top.
I know it's sort of loved and hated.
It's very different than some other operating systems.
Like in Windows, your menus are stuck to your window, whereas in Mac, they're just stuck to the top for whatever active app you have.
That used to bug me.
Now I really love it, actually.
But I have all these little widgets in my menu bar.
I mean, I have a ridiculous number of widgets.
It probably spans the entire screen on a like 1600 resolution monitor.
So I had to get this app called Bartender for the menu bar.
Bartender, which I can hide away most of them that I don't care to see unless I want to access them.
But I've got stuff that shows like current bandwidth usage, total usage, VPN, resolution control, like all these cool things.
Right. So at least for me, this is like an exciting part of the OS.
And it seems like to add an app there is not too hard, but it would be nice if we could do this with Python.
Right, guys?
Yeah, it would. Yeah.
Yeah. So there's a guy named Camino Bassini.
Hopefully I got that close, close enough there.
I wrote an article called create a macOS menu bar app with Python.
And the biggest takeaway I would say from this is, wow, it is not a lot of work.
And this is not just like, hey, you can get something to appear in the menu bar.
But here's something that, you know, controls the icons that are up there as it, you know, is like enabled or disabled.
It actually compiles to a .app file that you can ship and run using Py2App and stuff.
So anyway, it's a really cool little app.
It uses some stuff that we've talked about before.
It uses Rumps.
Rumps is a funny project name.
Ridiculously uncomplicated macOS Python status bar apps.
That's Rumps.
That is a complicated name.
Yeah, but if you look at what it does, it is uncomplicated except for its name.
And then Py2App obviously takes the Python app.
You tell it the source code and the packages you need.
And you basically create a custom setup file and a custom setup action.
So you just say Python setup Py2App and boom, you have a thing you can just distribute around.
Yeah.
Cool.
And both of those dependencies are pip installable too, which is cool.
Yes, exactly.
Yeah, yeah.
It's really good.
So basically, in order to get something to show up on the menu bar with Rumps, you have to say, create an instance of an app.
So like Rumps.app, give it a name.
The example that they used was a Pomodoro timer.
So you say the name of the app, Pomodoro.
And then you can even use an emoji as the icon that'll show up there.
So they put a tomato, a little tomato emoji.
And then you call app.run and then you have your thing running up there.
Right?
Obviously, you've got to add some functionality and whatnot.
But it's really quite simple.
And I'm starting to think like, all right, what could I put up there that would be really fun?
You could do the Pomodoro.
Yeah.
I already have a Pomodoro app.
And it like syncs stuff and has a history.
And I could definitely do a Pomodoro app.
That would be fun.
What I've been thinking about, actually, is something that Brian and David, David and I were actually talking about at PyCascades was continuous deployment.
Remember that, David?
Yeah.
So I have, for the servers and stuff, it's like almost continuous deployment.
I've got to log in, run a command, and then it kicks off like a whole process of a bunch of stuff that's happening.
So I finally broke down after that and wrote the last mile or whatever.
He will to like, so now if I just, when I'm working in PyCharm and I'm ready to put something in production, I just go to the terminal in PyCharm so I'm in the right place.
And I just type prod, hit enter.
And then, you know, 36 and 60 seconds later, a whole bunch of stuff happened on the server and the new version's working, which is awesome.
But it would be kind of cool to see like a status of that stuff, like a little server thing and show me the status and the last deploys and, you know, forced deploys of like all the different apps.
That'd be fun.
Yeah.
That would be cool.
Yeah.
That's what I'm thinking.
Do you have a rollback for your production script as well?
Yeah.
Okay.
Yeah, yeah.
Well, the rollback is, so the way it works is you just commit to a certain branch and the rollback is just change what's on that branch.
Oh, okay.
Right?
So, so somehow I, I were to do something, then I go, oh crap, roll that, you know, somehow roll, you undo that commit and then just trigger it again or something like that.
So it's all based on like GitHub web hooks and push actions and whatnot.
Anyway, that's what I'm thinking about building like this.
What I would love to see is to see people build interesting things with Python and with rumps and this example here and see if somebody can get it into the Mac app store.
Oh, yeah.
I've gone on a rant before.
I hate them.
I hate the app store so much.
I used to love them, but now I'm really mad at them because they've, I've taken a lot of abuse and I still am and I don't want to go too far down it because it'll make me upset.
But I would love to see someone else try to get into the Mac app store.
Anyway, what do you guys think?
This is fun, right?
Yeah.
Looks very fun.
Yeah.
Cool.
So, Brian, this next one that you have, this is a pretty cool one about testing and code coverage.
I really like it.
Yeah.
So, it just came out like, I don't know, last week, I saw a blurb about this.
I think it was, I'm going to hopefully say this name right, Nikita Suboli.
He's the CTO of WeMake Services.
And we've heard of WeMake Services before because they do the, oh, what was it?
The design.
The linter.
The Python code style guide.
Yes, exactly.
It's pretty cool.
I think they, from, I think one of their sponsored Twitter threads that announced it to us and
let us know.
So, thank you.
But it's kind of exciting.
So, the idea is with code coverage, there are times where you have to kind of have if statements
around certain blocks of code that only run, like let's say, I mean, we used to have a lot
of two versus three stuff.
So, Python two versus three.
Some people might still have those things they need to deal with.
I don't know why.
Isn't it 2020?
Yeah, exactly.
But still, there might be, like, maybe you want to use the Walrus operator on something.
You need, like, the three six versus three eight.
Yeah.
But then, also, maybe you've got direct calls that you need different things on different
operating system, like Mac versus Windows versus Linux or something, or different versions
of third-party packages.
It just happens sometimes.
But it's usually sort of isolated, but it is a thing that makes it so that when you do
a test run with test coverage, those things aren't getting counted, and they count against
your coverage numbers.
Right.
So, a lot of times, it's trying to, like, import something, and you're not sure if it's
there or not, right?
Yeah.
So, you might say, try import, and if it works, great.
If it doesn't, then you import a different thing.
Like, the only thing I can think of right now is that mock used to be, is part of unit
test, but it didn't used to be, or something like that.
But one of the ways that we dealt with this in the past was to have your coverage numbers,
you do the testing on all the different platforms you need to, or the testing on all the different
versions of Python you need to, or whatever, and then collect all that coverage, and then
just report on that.
Because coverage has a combined way you can combine reports.
There are downsides to that, though, because, like, for instance, just during development,
you have to run all the tests multiple times, or you might not have access to the other operating
systems.
So, this new plugin for coverage allows you to write rules, some pretty cool rules and pragmas
to skip different versions or different parts of your code for excluded from coverage based
on different, you know, just a little bit of code.
And it's really pretty cool.
Yeah, I love it.
You just put a comment around that area and say hash pragma, and you put a little conditional,
right?
Like, you could define the rules for code coverage, and you say, this rule means this thing, and
it'll know whether or not it should check that, right?
It has a way to, within your coverage setup, or wherever you're putting that setup, to put
rules in place and have those rules there.
And then those rules specify a different pragmas, and then the pragmas show up in your code.
But it's really pretty clean, and I can't think of a cleaner way to do this.
So, that's pretty cool.
I like it.
Yeah.
Yeah, it looks nice.
Yeah.
Yeah, for sure.
I mean, maybe you could put some, like, plugin extension stuff into some sort of, like, into
coverage itself or something that's running coverage and say, if you see this pattern,
ignore this or somehow report on it differently.
But yeah, barring something like that, this is great.
I do want to add a couple notes on this.
I think it's, I'm a complete coverage or complete testing sort of person.
So, this will sort of hide parts of your code that you don't know are being tested.
It could potentially hide some bugs.
So, make sure that you are really testing everything.
If you have this sort of stuff in place, really test everything, probably on your CI.
Well, what if you find a part of your code that's hard to test, and you don't want the
code coverage to bug you about it?
So, you just cover that up.
Second.
Great idea.
I mean, it's just going to solve, like, it's, dude, 100% code coverage.
This is good.
Yeah.
We're good.
I think maybe you should think about it a little bit more.
I agree.
Yeah, that's not the intent.
Although, if that's what you're evaluated on at work, this may be effective.
You never know.
100% code coverage, boss.
That's right.
I don't know where this bug came from.
Speaking of good stuff as well, really quickly, I want to tell you all about Datadog.
They're sponsoring this episode, as they have so many.
So, be sure to support them, because they support us.
So, they're a cloud-scale monitoring platform that unifies metrics, logs, and traces across
all the different service boundaries.
You get to monitor your Python apps in real time, find bottlenecks with detailed flame graphs,
and trace requests as they cross service boundaries.
Plus, they're tracing client auto-instruments, many of the frameworks that you care about,
like Django, AsyncIO, and Flask.
So, you can quickly get started monitoring the performance of your Python apps.
Check them out.
Get started with a 14-day free trial, and they'll send you a cute little t-shirt.
So, check them out at pythonbytes.fm/datadog.
David, I've been thinking about Excel a lot lately and how people are moving from Excel to some of the
data science libraries.
But that can be really tricky if they've written a bunch of, like, formulas and a lot of work, right?
Yeah, it can.
A lot of logic in their Excel file.
Yeah, definitely.
I found this library called PyCell, described as a library for compiling Excel spreadsheets to Python code and visualizing them as a graph.
So, I thought this was a really interesting library that this guy had open sourced.
It comes from a problem, actually, I guess this guy had back in 2011.
He wrote a blog post about it, describing the motivation for this.
But what this does is, if you have an Excel file that has a whole bunch of formulas in it, so you're using it to, well, this guy was using it to design civilian airplanes for, like, search and rescue missions, new airplane designs.
You've got a whole bunch of formulas, they all kind of interact with each other, and it's just lots of complicated logic.
One of the big issues they had was the Excel file was getting really slow.
And so, he decided to investigate what it would take to do something in Python, but he didn't want to have to rewrite all of those formulas and go through all that logic again.
So, this will actually parse out an Excel file with it.
It'll compile it to executable Python code, and then you can actually set, like, cell values and see what the output and other values will be.
So, you can kind of do this all on the fly, and it's all happening within Python.
It's not touching Excel anymore.
It's not like one of those automation libraries or something like that, right?
No.
It's converted it to Python, and then it runs that.
Exactly.
Yeah, there's some parser built into it that'll take all the formulas and actually write Python functions that replace those formulas and can execute it.
It's using NumPy and SciPy and a whole bunch of the data science and scientific stack there to do that.
But one of the things that I thought was really cool about it was you went a step further, and once you've got all the formulas compiled, there was this big optimization problem they had to do.
He said, okay, we've got all of our formulas in here.
We've got some base parameters we've set, but we want to know, we want the airplane to actually fly.
So, how do we optimize the output to get what we need to design the aircraft properly?
So, there's a big optimization process, and he was actually able to write that in Python and have it take care of that for them and reduce the number of cases,
sorry, increase the number of cases that they could actually optimize from about 65% of all cases to about 98% and reduce the computation time down from about 10 minutes to 30 seconds to a minute with it, which was, I thought, really, really cool.
And then you can generate these graphs of, like, all the formulas and how they interact with each other and kind of explore that visually to see how one change in a variable is going to propagate through the rest of the system and everything.
So, I just thought it was a really interesting example of taking Excel and doing something with Python with it.
So, we've covered a lot of stuff about, here's a cool library to, from the outside with Python, like, sort of marionette, pull the strings of Excel and make it do stuff.
But this is, like, how do I hit escape velocity and get past Excel without starting from scratch?
Yeah, it's really cool.
Brian, what do you think?
This is cool.
I try to avoid Excel as much as I can, but, you know, if you can't, this is good.
Well, if someone gives you Excel, you just hit it with this, and you're like, all right, we're done with Excel.
That's right, Kif.
No, I think this is actually super, super cool.
So, I saw this come by as well.
I'm glad you picked it, David, because it seems like for the right group of people, this is going to be very helpful.
Yeah, I think it could also serve as an example, you know, for other use cases as well to kind of see how they did this and how you might be able to apply that same methodology to a problem specific.
Right, there's got to be stuff that's not Excel that has, like, a similar type of issue, right?
Yeah.
Yeah, cool.
Speaking of taking and applying something to your own, solving your own problems, this next one that I want to talk about is something that I actually recently released, but I think a lot of people will find helpful.
So, let me just tell you all the problem, and then you can give me your thoughts, and I'll tell you what I tried to do to fix it.
So, I feel like a lot of times when you're thinking about the websites you're building or how you're going to maintain them or have other people work on them, it's almost like this either-or story.
Either we're going to build an app that's, like, powered by the database where it has, like, structured routes.
Say, like, a bookstore has a catalog which has categories, and then in those categories there's books.
So, you have pages that represent those things by putting in details about books and tagging them with categories and whatnot.
So, that's sort of, like, the data-driven side.
Or you can be more freeform.
I just want to create landing pages and arbitrary, like, content that I write and whatnot and just structure stuff more arbitrarily.
In which case, maybe you need a CMS, like, WordPress, or you want to stay in Python, you might use Wagtail, which is built on Django, right?
You can do one or the other.
But there's not a lot of conversation about, like, I'm going to build that cool data-driven Flask app, and this part is going to be, like, WordPress, and I can just write in it.
And the challenge is, you know, a lot of times the HTML of those, the way you structure those pages, a lot is with Jinja 2 or Chameleon or Django templates or something like that, right?
So, you don't want to write that, and a lot of times you've got to restart the app to make those sort of pick up.
So, what I decided was I'm going to build a sub-template because it's not, like, it's not standalone.
It requires something like Jinja to sort of orchestrate it, but something that lets me write markdown for part of the website so it can act like a CMS and leave the other part in place so it acts like that data-driven app that I described.
What do you guys think?
Oh, yeah.
Common problem, right?
Like, it's rarely all one or all the other, and yet how do you, you know, how do you deal with that?
Do you write, like, custom HTML in the app and just restart the app?
That's not great because, well, now you're writing, like, way more just HTML and you just want to write content.
So, what I did is I came up with this thing I named markdown sub-template, and it's like a templating engine for markdown.
And what it lets you do is you write markdown files, and importantly, you can take other markdown files and import them.
So, for example, if I had a contact us section, I always wanted to say, here's our Twitter, here's our GitHub, here's our whatever, here's how you can find us.
Like, in different markdown files, I just say, import, contact us, and then it just drops in.
So, there's, like, one place you maintain that segment of your content, and it drops in and builds up, like, a tree, an object graph of markdown files.
And it also does variable replacement, and it lets you put arbitrary HTML for little bits of, like, I need this thing to have this CSS class on it, or it's just not going to work.
And markdown's not enough.
So, you know, a div with a class, and then just go back to markdown, or something to that effect.
Like, very, very limited HTML.
So, I built this.
Yeah, I'm interested in this, and I'm curious to play with it a bit.
It is not something I can use standalone?
Or can I run it standalone?
Oh, you could use it standalone, but you couldn't, I don't know that you would necessarily be able to build the website that you dreamed of standalone.
Oh, right.
The reason is, it doesn't do, like, you can't really do, like, a nav bar, and, like, you sort of could, right?
You could sort of get, but it would be just pure markdown, and that's not usually enough, right?
There's usually, like, I want to have these CSS files included, and I want to have this stuff included, but then the core of the page, I just want to write markdown files and drop them in there and have that be the content.
But I want to be able to show whether the user's logged in or not.
So, yeah, you technically could, but it's not intended for that.
I'm thinking of non-web-based stuff.
Sure, for non-web-based stuff, yeah, you could definitely take a whole bunch of markdown and convert it to HTML with, like, reused elements and whatnot.
No problem.
Yeah.
All right, cool.
And this interacts with, like, the data-driven part of a website, say?
Like, if you had...
So, imagine you've got, like, a whole bunch of different pages.
You want to be, like, landing pages or articles or something like that.
You want to let people just write the markdown, but then you want to be able to have them import the other markdown and do variable replacement and stuff.
They do all of that, but then in the data-driven part, you would just say, the contents of this page are, boom, the output of this template.
You just say, like, get HTML and just plunk it in between, like, your head with all the CSS and maybe the bottom with the JavaScript and the footer, right?
But then everything else just comes from... is driven from this.
It has logging to tell you what's happening.
It has caching, and those things are extensible.
So, for example, it has an in-memory cache, but it also has a MongoDB-backed cache that you can set up because parsing markdown turns out to be a little bit slow.
So, you can take things from, like, 200 milliseconds or so for a decent-sized page down to, like, one millisecond automatically.
Like, it automatically supports that.
You don't have to do anything.
And then also working on storage.
So, if you don't want to use files but you want to store it in the database, you'll be able to, like, change the storage engine and stuff.
So, anyway, people like this.
They can play with it.
It's really early, but PRs and contributions are welcome.
Yeah, very cool.
Cool.
Thanks.
All right, Brian.
I think this is like a dystopian continuation of your last one.
What is this?
Definitely.
It's a continuation.
So, I was actually, when I was researching the previous thing, so what was the previous thing?
The conditional coverage article and conditional coverage plug-in.
I was remembering that the WeMakeServices does the WeMakePython style guide, which is not just a style guide, but kind of some cool tools around it.
It said, we recommend using FlakeHell.
And I'm like, what's FlakeHell?
Were you like, what the hell?
Yeah, exactly.
So, I wanted to check this out.
And luckily, oddly enough, on the FlakeHell main readme doesn't highlight some of the main benefits, but there's a little blur page that I'm going to link to on from the WeMakeServices site that why they use it is for legacy first.
So, FlakeHell is a thing that wraps around FlakeHell, but FlakeHell also has lots of plug-ins and stuff.
So, what FlakeHell will do is it helps you specify which plug-ins are configured and which plug-ins will run.
Normally, FlakeHell will just run any plug-in that's installed, any FlakeHell plug-in that's installed.
So, you can control that a little bit.
So, there's that.
But then there's also, they've made improvements on how you specify configuring it.
So, you can configure it now within your PyProject.toml file.
And then there's shortcuts like wildcards and such that make it a lot easier to specify which rules you want to follow and which rules you don't.
And that makes it a little bit cleaner.
But the part that I'm really excited about is they have a thing called FlakeHell Baseline.
And so, the idea is, let's say you've decided as a team or on a project you're going to start using some linting tools from now on.
Yes, you'll have to go back and change some stuff, but you don't really want to do that right now.
You want to make sure that the style guide applies to new code.
And gradually, as you've got time, go back and fix the old stuff.
Well, the baseline will allow you to save a baseline file and then specify that in your Toml file.
And then now, when you run FlakeHell lint, it runs all of your FlakeHell tools and doesn't show you any of the old stuff.
So, if you haven't changed your code, running it right after you've done a baseline will not show you anything.
But as you start writing new code, it'll lint to the new stuff.
It lints the old stuff, too.
It just doesn't catch the same errors again.
I'm sure there's a way you can go back and, like, take out your baseline to try to fix up some old stuff.
But this is a way to move forward on a project with linting styles without having to kind of take a break and fix everything first.
That's really cool.
I mean, on a large code base with lots of history and everything, I mean, that can be super annoying.
You introduce this new tool and, oh, man, we've got thousands of errors flagged that we've got to fix before we can even move on with life.
So, I think that's fantastic.
Yeah, and often it doesn't mean we're going to fix it.
It's like, yeah, we're not going to use this because this is going to take us four weeks, all of us, and we're not doing that.
So, forget that.
I do think the name is a little bit off, though.
It should be like Flake Utopia or something because it's meant to make it better.
Yeah.
It's like you're in Flake Hell.
It's Flake Heaven.
Yes.
How do we get you out of Flake Hell?
Yeah.
I don't know.
Anyway.
I like that they've got a little snowflake inside of the flame on their logo there, too.
Is that...
Yeah, I actually didn't catch that.
Yes, it's...
Yeah.
It's very contradictory.
You don't really know.
But I do think, Brian, that this legacy thing is super important.
It does let you say, we're going to start using Flake 8 now, and we're not going to go and stop the assembly line and stop working on everything and wreck that.
It just lets us, from now on, you know, you kind of get a path on what you did before.
Now on, we're going to work with things the right way.
I like that.
That's cool.
Yeah.
Well, guys, I guess that wraps it up for our main topics this week.
Either of you got stuff you'd like to throw out there?
Quick extra thing?
Yeah.
Pi Texas 2020 is coming up.
The registration opens sometime...
Well, I guess next week, it'll be the time that the listeners are actually hearing this.
It's going to be...
Time travel and all.
It'll be about the time this show comes out, yeah?
About the time, yeah.
So you can just go to pitexas.org.
If you live in the Texas area and are interested in attending that conference, it's a lot of fun.
It's going to be May 16th and 17th in Austin, the actual conference days there.
But yeah, so register when you hear this, if you're interested.
Yeah, yeah.
Super cool.
Brian, you got anything?
I do not.
All right.
Well, I have just two quick things for you to throw out there.
One, you know, thanks to our listeners, as always.
I went on a rant about licensing, didn't I, Brian?
About GUI framework?
Yes.
And I think it is well-deserved.
However, some folks did point out my interpretation of the dual license mode of Qt wasn't quite right.
So let me see, maybe I'll get it right this time, maybe.
And it drives me crazy because I'm not 100% sure.
There's nowhere I can go and point to where this is the case.
There's like all these little different paragraphs and random pages that talk about it.
So Qt is licensed under a dual license, an LGPL license and a commercial license.
And my reading of their website was, if you're doing commercial stuff, you have to have the commercial license.
And if you're doing open source stuff, you have to have the LGPL license.
What folks are saying, I think it's probably true, is you can decide which license you decide to take it under.
You can have the LGPL or you can have the commercial if you pay for it.
And then you just have to follow the rules of those.
And if that's the right reading, which probably it is, then you can ship stuff commercially under LGPL.
Anyway, that's not my final verdict.
People can continue to look and get maybe an official word.
What would be nice if people are listening and they're like frustrated, like, well, why doesn't this guy get my licensing?
What if they had a page that said, here's a comparison side by side, like a lot of SaaS apps do.
Like, if I get this plan, can I do X?
Can I do Y?
Can I do Z?
Little checkbox, right?
You know, there's none of that.
So it's really vague.
And there's a lot of like frustration with users around licensing from their blog posts and whatnot.
That said, I think you probably can use the LGPL commercially, but don't hold me to it.
I still have questions about like, let's say I work for a big company.
Can I use Qt to write a tool that I'm not selling that it was just using internally?
I believe so.
Yeah.
I believe already they, they call that out that you can distribute it internally.
You just can't distribute it externally.
But there's weird rules.
Like if I'm a developer and I work on a commercial project, someone else is using the LGPL license.
Like they can't even look at or interact with the code that has to do with the commercial license.
It's like, there's a lot of weird knock on effects that go farther than I would think they should.
Anyway, this is way more than a quick follow up, but since it's a bit of a correction, I wanted to throw it out there.
The other one, this will be quick is I just interviewed Richard Campbell on Talk Python on something that many, many people would be interested in.
And that has not that much to do with programming actually on what we're calling a moon base geek out.
So Richard Campbell does all these like super deep dives, like into popular science stuff.
He's also a developer and a podcaster, but at various times, he'll go onto these dives and various just science, popular science projects.
And this is just a, like a take on modern space travel where we are and a whole moon base story and stuff.
So if that sounds interesting to people, check it out.
Very little like programming skill required to know all about it.
I guess I did have one extra thing I was going to tell people about.
Yeah.
Throw it out there.
So over the holidays, over December and January, I did slow down testing code down to a pretty slow dribble, but I'm back up to weekly episodes.
So if you haven't checked out testing code lately, be sure to check it out.
Yeah.
I've seen you releasing a bunch of stuff.
That's great.
You said Anthony Shaw on there, right?
About his plugin.
Yeah.
And also just app security and we're trying to release weekly.
So lots of good stuff coming up.
Very, very good.
All right.
You ready for a joke?
Yeah.
I've got actually one other one too after you're done with this one.
All right.
Super.
So this one is visual, but it doesn't need very much.
And I think a lot of people can appreciate this.
So you guys just open up that link real quick and I'll tell the joke.
So there's this programmer guy looking at his screen with his furrowed brow, clearly frustrated, just thinking, why?
Right?
It says, it doesn't work.
Why?
And then there's another picture somewhere else in time.
Exactly the same expression and pose saying, it works.
Why?
Yeah.
I don't know.
How often do you all have that feeling?
You're like, why does this work?
I just don't understand why this works.
And then you're like, why will this not work?
Right?
It's so funny.
But I think it's just, it's, it's a little too true.
So a question about this.
Is he leaning on his elbows or is that a mustache?
He's leaning on his mustache.
Yes.
Yeah.
They're connected.
Obviously.
Yeah.
Obviously.
Why?
Okay.
What's your joke, Brian?
Okay.
So this is not a nerd joke, just a dad joke.
So I went to the doctor after ingesting too much food coloring.
The doctor said I'll be okay, but I feel like I died a little inside.
Oh, very good.
I love it.
Nice.
Anyway.
Nice.
All right.
Well, thanks for the jokes and the feedback and everything.
Brian, as always.
And David, thanks for being here.
Thanks.
Yeah.
Thanks for having me.
Bye.
Yeah.
Bye.
Bye everyone.
Bye.
Thank you for listening to Python Bytes.
Follow the show on Twitter via at Python Bytes.
That's Python Bytes as in B-Y-T-E-S.
And get the full show notes at Pythonbytes.fm.
If you have a news item you want featured, just visit Pythonbytes.fm and send it our way.
We're always on the lookout for sharing something cool.
On behalf of myself and Brian Okken, this is Michael Kennedy.
Thank you for listening and sharing this podcast with your friends and colleagues.