Python Bytes - #159 Brian's PR is merged, the src will flow
Episode Date: December 3, 2019Topics covered in this episode: Final type flit 2 Pint 8 great pytest plugins * 11 new web frameworks* Raise Better Exceptions in Python Extras Joke See the full show notes for this episode on t...he website at pythonbytes.fm/159
Transcript
Discussion (0)
Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.
This is episode 159, recorded November 26, 2019.
I'm Brian Ocken.
And I'm Michael Kennedy.
And this episode is brought to you by DigitalOcean.
Thank you, DigitalOcean. More about them later.
Michael, what are we talking about right away?
You know, I'm a big fan of type annotations, and I don't know how I missed this one.
I can't remember what I was reading.
It was something we covered on a show recently, and it was talking about the final type annotation.
I'm like, wait a minute, what?
There's a final?
As in, with object-oriented programming, you know, there's like abstract methods, virtual
methods that can be overridden, protected types, and some of those things appear in
Python, abstract method, for example,
but others don't, such as protected or internal.
Another thing that until very recently did not appear in Python is a final type saying,
this class cannot be overridden or this method cannot be overridden in a type hierarchy.
But now you can.
Oh, cool.
And this is actually already in Python 3.8,
if I'm reading this right.
So this is PEP 591.
Its status is accepted,
and its Python version is 3.8.
So I have not actually had a chance to test this out.
But yeah, it looks like it is part of it.
And, you know, because it has to do with typing,
of course, Guido van Rossum is the BDFL delegate,
which is kind of interesting
he's his own delegate in a sense but now the steering council is there it's a little bit
different but yeah so he was part of this and it adds a final type so i can say this class
cannot be derived from this method should not be overridden and those sound pretty straightforward
but as far as i can tell from the use cases they
put in the pep it's something that is very very close to a constant value as well what do you
mean so one of the things i can do is i can put an at final decorator on a class and then if i try
to derive from it the type decorator will give me an error saying you cannot draw you cannot inherit
from final class whatever right yeah if i put it on a method and then I try to have a derived class that replaces that method
effectively, like implicitly overriding it, I'll get an error that says cannot override
final method foo, whatever, right?
It was first defined.
But I can also say that there's a variable called rate, which is final and it equals
3000.
And if I try to set it to another value, like rate equals 300,
the type checker will give me an error say cannot assign to a final attribute. Okay,
or I can go to a class and I can put that on a field. And if I try to change the field,
like if I have a class called base and it has a default ID, if I say base dot default ID equals
something other than what it was initially set to error cannot override final attribute. So the
error doesn't say this is a constant value,
you cannot do this, but it's like a constant.
Yeah, okay, that's nice.
It's interesting, right?
Well, I guess it totally makes sense
because overriding, like deriving from a class or something
is kind of similar.
Certainly changing the name,
like the redefining the method in a base class
is like replacing the name of it. Andining the the method in a base class is like replacing the name
of it and so the implementation seems to just catch straight up attributes as well just you
know probably with not much extra work if any yeah so this is all the stuff that i'm telling you
this is all type checker magic this is not real right this is not real, right? This is not runtime behavior. Right.
But, you know, I suspect that tooling like PyCharm, for example,
if you tried to set that, it would like turn it like yellowish and say,
warning, this is a problem here.
And already if your editor tells you not to do it,
your continuous integration maybe checks these things.
I think you're in a pretty good place.
And I think that more and more we're going to see as the years come on that people's workflow is just going to include
type checkers with their code, with large projects at least.
Yeah, at least with large projects. I agree. Cool. Well, I'm pretty excited about this.
I was really surprised to see that was in 3.8, but I'm happy to spread
the news about PEP 591. How about you? You've got some numbers that
are incrementing as well,
huh? Yes. So, Flit, have we talked about packaging? No, I don't think we have. Enough,
not enough. Let's keep going. I'm almost positive we've covered Flit before. Yeah,
we certainly discussed it, if not made it its own pure topic. We've definitely talked about it. Right. So, one of the beefs I had with flit which was just a minor thing so flit makes it so easy so that you can like super easy so if you got some
code that you want to share with somebody you just install flit and say flit init and essentially it
does the right thing to create a package for you you don't have to read up on setup tools or
anything it just kind of works oh that's interesting it's like npm init sort of. Okay. I don't know what that
is, but I'll believe you. That creates a
good job of like an npm package. Yeah, yeah.
The news right now is flit2 is here.
So when initially playing
with flit, I noticed a lot
of quirks with it. So you, for instance,
you couldn't use a source directory to put
your source code in it. Your package
needed to be a top-level directory
or just a module.
That was actually a pull request that I did
to try to get the source directory added to Flit.
And now it's in, so it's in too.
But it also wouldn't...
That's awesome.
Yeah.
So when playing with it now also,
it used to be that it really assumed
you were going to be in a Git repository.
That's fine,
except for when you're just playing with stuff, sometimes you're not. you're just trying yeah you just i want to just try this out i'm not
committed yet to this even working let's just see what happens right right flit now does work without
if you're not in a git it determines what files to include in a package with git stuff with you
know what's in and get and what's not in git and i don't know how it works when you're not in a Git repo,
but right now it does work if you're just playing around.
If you don't have anything checked in, it still works, and that's pretty handy.
I mean, I definitely want everybody to use version control,
but if you're just trying this out, you can now, and it's really cool.
And there's a whole bunch of improvements.
I'm linking to the release notes or the history.
It's just sort of,
if you've tried it before and were frustrated, try it again. The caveats I'd like to say is this kind of a lightweight packaging system, it does not work for compiled code. So it's not
built yet to deal with compiled parts of it. Right. If I had like some Cython bits or something,
doesn't deal with that.
Doesn't.
And then there's a couple other reasons why you might not want to use this.
But for, I think, the 80% case where people are just trying to share some Python code
with each other, this is the way to go.
Okay.
That sounds super cool.
Yeah.
One of the other things that I love in the second version is your email address is optional
now.
It used to be required,
but you're not required to put an email address in PyPI,
so why require it for these tools?
Yeah, that makes a lot of sense.
Yay, so now my big beef with the flat not supporting source is
I'm done with that beef.
You know what, this is a super cool example as well, right?
It's one thing to just complain and say,
you know what, this thing is crappy
or it doesn't work the way I want or something.
It's another to say,
and I'll help to make a difference, right?
So like the reason it supports it
is your PR was merged in, right?
That's awesome.
Yeah, and it also, it doesn't add any,
I didn't add any flags, didn't add anything.
It's just within the init part of it.
It detects that your code is in a source directory and it just uses that.
Yeah, super. Nice work.
You know what else is cool?
DigitalOcean.
DigitalOcean is very cool.
DigitalOcean is making Kubernetes easier with their DigitalOcean container registry Registry and OneClick apps. After building your app into Docker containers,
you'll often want to store container images in a centralized location called a container registry.
From there, you can pull images into a Kubernetes cluster or a VM,
whether it's a development, testing, staging, or production environment.
While you can post your containers images into the open
internet freely using services like Docker Hub, clearly you don't want to do that with confidential
software or, you know, your own private stuff. So DigitalOcean introduced a new managed service
called DigitalOcean Container Registry, and it's now available in early access mode. So DigitalOcean Container Registry is simple, private, secure, and fast.
And you can get started using it by going to pythonbytes.fm
slash DigitalOcean.
Cool.
I feel like this next item that I want us to talk about,
I feel like we talked about it before,
but I went back and I searched and I couldn't find anything about it.
So if we covered it like three years ago,
we're going to cover it again.
Nonetheless,
it deserves to be covered because it's really cool.
This comes to us from Andrew Simon and it's called pint.
So how many cups is in a pint or two pints go into cups? Is there like how many gallons go in there?
And if I had to convert that to liters or milligrams,
like what would like,
I don't know.
All these questions are completely unknown to me without like some chart and a calculator or Google.
And I suspect they are to a lot of folks mixing some form of units, even if they're in the same system, like meters and millimeters can be tricky, right? So this pint thing, its job is to basically apply units to numbers and calculations in Python. Okay. Okay. So I'm sure you took physics and, you know,
in physics or maybe the chemistry, like your professor would tell you, like, you cannot just
tell me the number is seven. You have to say seven, what you have to put units on this number,
or this number doesn't really tell us
what what the answer is or what we're working with right and so pint lets you do that it has
all these different types of measurements it has like energy and you know like joules and it has
distance and weight and all these these different types of things even wavelength it'll help you
like convert wavelength types of measurements and stuff.
So if you've got some numbers you need to add together, like for example,
it's super easy to add two meters and five inches and get the right answer in
the units that you want. Oh, that's cool. Yeah. Super cool. Right.
So I'm linking to basically a Python document that has a TXT ending on
GitHub. So read that however you want when you get to it.
It's a little unformatted,
but it shows you all the different units
and types of units that you can work with, right?
It knows what a desagram or a desameter is
and all those different types of things.
So I just want to share a quote that's on the homepage there
that talks on the pint, read the docs.
So it talks about the Mars Climate Orbiter. And it said the MCO
has determined, this is an orbiter that went around Mars until it didn't go around Mars anymore,
and it hit Mars, I believe. It met Mars in an unfortunate way. It said the MCO Mission
Investigation Board, MIB, I'm guessing that's what that stands for,
has determined the root cause for the loss of the MCO spacecraft was a failure to use metric units
in the coding of the ground software file Small Forces.
Used in trajectory models, specifically the thruster performance data in English units
instead of metric units was used in the software application titled SM underscore forces, hence orbiter meet planet.
So, yeah, you know, this is not the type of code I write a lot.
So it's not directly useful for me, but I've studied science a bunch.
And it seems if it is the kind of code you write, it's very simple and very powerful.
Yeah.
One of the things I like about it is it's not that the unit's separate
so that you can look these up.
It stores the values.
It just has values with units associated with it,
and so you can pass them around and use them in other places,
and all the math operators work on it.
I mean, if you really want to, you kind of have to know the units anyway.
One other way to do that people often use is suffixing variable names with what the units are.
But then there's nothing telling the software that it has to comply with that.
It's just convention at that point.
But so if you're, especially with mission critical stuff, I think this is a really great idea.
Absolutely.
So the way you would create like three meters is you would create an instance of a unit registry,
and then you would just take the number three times meter.
Yeah.
And now it's a three meter quantity.
So they override what the multiplication thing means.
And yeah, it's pretty cool.
It's clear.
You can add different units together, like meters and centimeters together,
and it just works right.
And that's great.
Yep.
Nice and simple. Yep. Nice and simple.
Speaking of simple.
I got to say that the unit thing that you linked to, it has, I didn't know this,
that yada is 1 times 10 to the 24th.
So yada, yada, yada is a really big number.
I had no idea.
That's a huge number.
How interesting.
What a cool piece of trivia.
Yeah.
Okay.
Speaking of a bunch of numbers and great things.
We're going to take a look at some PyTest plugins.
So Jeff Triplett wrote an article called Eight Great PyTest Plugins.
And there was even some fun stuff for me.
I'll just list them quickly.
There's a couple that I'll highlight.
So PyTest Sugar.
So sweet.
It's just a fun one that changes the output.
But it isn't just fun. It changes the output so it looks kind of nice.
You get green check marks and stuff instead of the dots. At the progress bar.
Yeah, progress bar. But it also shows failing tests
instantly instead of waiting to the end or something. So that's nice.
It's cool. PyTest-cov hooks into the coverage so that you can
more succinctly check your coverage on your
code using PyTest. I use that. It works great. The next one
which I hadn't heard of before is called PyTest-picked.
And this is like a brilliant idea.
So if you've ran your pytest code you know you think
your stuff is good but what this one does is you're working on your code and if you're using
git you've got modified and unstaged and uncommitted code within your repo that's the stuff that
probably the new bugs are in so what pytestTestPick does is it tests files that,
it runs tests that use the files
that have been changed since your last commit.
That is super cool.
And it probably runs your test code
that have been changed since your last commit.
But what I would love to see,
and maybe it does this, you tell me if you know,
is if it would look at the coverage data
and it would rerun the tests that were covered by your tests,
the files that were covered by your tests but then changed,
it would rerun those tests that covered it.
Oh, did I get it wrong?
Does it just run?
I think it just straight up runs the files.
It's just like if your tests have changed.
Yeah, I'm pretty sure.
It says the tagline is
runs the test related to the unstaged files.
So, not sure.
Yeah, yeah, not sure.
I'll have to try that one out.
Report back.
Yeah, we definitely got to try it.
My first impression from looking at it
is it runs the tests that were changed,
not the code that was changed,
covered by the test.
But yeah, we'll report back.
Both of them are interesting.
They're both very interesting, yes.
Already, I think it is a super cool idea
and I love it. If it does the second
thing I said, then I'll love it even more.
Yeah, okay.
The next one is PyTest Instafail.
Modifies the default
output so that failures show up
immediately. Right now,
if you run PyTest, if you just run it with no
options, you get a bunch of dots for all your passes. You will see the F for the fails, but you
don't get the output right away, like what the traceback is. And so if you really want to like
start debugging before your test suite is done, Instafail might be the thing for you to show your
failures right away, the details of your failures. Now, for people that really think that PyTest
is already giving you too much information,
PyTest TLDR is hilarious,
but it's actually quite useful,
and it will kind of remove some of the stuff
from the PyTest output,
some of the boilerplate that comes at the top and bottom
and also just kind of reduces the output.
It's kind of nice. And this is by Freakboy. Kenneth, I'm going to get this wrong. Keith Russell McGee.
Yeah, that's it. Now, next one is PyTest XDIST. A lot of people think of XDIST as the way to run
all your tests in parallel. You can run them on multiple processors. The surprising thing is you
can also run them on uh not just multiple processors but
multiple instruments or multiple machines you can have them uh spawn into other computers to
run tests which is really cool but you can also do things like loop on fail and and just perpetual
you can just have this things just keep running so that's pretty cool that is cool just periodically
just say tried it tried it it, tried it until it turns
green. Yeah, especially if you're actively
working on a fix, why not just have that
pop up whenever it's done.
Nice. The last two are PyTest
Django and Django Test Plus
are both
things that will help you if you're
testing Django, which is not
surprising that this came
from Jeff Triplett because
he's a Django guy.
So yeah, very cool ones.
I like these.
Although I feel like you cheated, Brian.
I mean, we're supposed to cover like six things each show.
And here you've covered eight.
Eight great PyTest plugins.
Come on.
Like who would do that?
You know, I told you I was sucker for link bait articles.
So listicles.
Yeah, for sure.
Well, the next one I have is 11 new web frameworks.
Oh, and you're
giving me a bad time not for long though no i think it's great it's cool to touch on a bunch
of those little things real quickly now people know that i do a bunch of web development and
i'm a fan of web frameworks and for a long time we had kind of the mainstays blast django and so on but recently and i feel like two things both the type hints and the async
capable asgi servers those two things have created just like a blossoming of all these different
types because they're like well if we got to rewrite it so that it supports async and await
or if we're going to rewrite it so i can use type hints to like grab stuff out of the query string
let's just go crazy and create all these new frameworks.
And well,
11 new ones is what we get actually more than that.
Cause there's,
there's some that are not listed.
Some we've spoken about some we haven't spoken about,
but I've heard of,
and some I've not even heard of.
So it's pretty cool.
I'll just go down the list really quick.
One of the things that's interesting.
If you look at a lot of these frameworks,
a lot of them are flask inspired and like,
you know,
the,
you create an app and then you do app.decorator, app.route
to define it and stuff like that.
A lot of them have adopted the Flask
API without actually
being Flask or coming from
Flask. Anyway, so the number one
is Sanic, which is a
web server framework
meant to go fast. And this one is
mostly focused around enabling async and await.
That's pretty cool.
Probably the most widely used,
at least in terms of other projects,
for the ASGI, the async type of frameworks, is Starlet.
So Starlet is cool.
It comes from, I believe, Tom Christie
and folks who are involved with the Django REST framework.
And it's a lightweight ASGI framework, which is great for high-performance async and await
services.
And you can either use it as its own web framework, or it's interesting as a foundation.
For example, Responder is built atop it.
I believe FastAPI maybe as well.
Yeah, I think so.
Yeah.
So there's a bunch of things that are derived from it. That's pretty cool. And both
those first two are Flask-like.
Masonite, I had Joseph
from the Masonite team on TalkPython
not long ago, and it's interesting.
This is not an async and
await framework. It's like a
standard framework like Flask or Django, at least
at the moment. But what makes it unique
is it has this command line
tool that lets you do things to
the project called craft. So the craft CLI is like what makes this kind of unique.
That was a really good episode with that interview. And I like the example of somebody
bringing in good ideas from other languages and helping out the Python community with that.
Yeah, thanks. I agree. It was definitely fun to talk to Joseph.
So for example, like with a lot of these projects,
you create the project and then you're on your own, right?
It's like, okay, well, I use maybe cookie cutter
or some other technique to create the project.
And now I've got to write every little bit.
But with Masonite, you can actually go and say,
now add this model or go add these other things
and it'll continue to let you evolve it
using these sort of starter cookie cutter type things.
So it's cool.
Fast API, if I was building an API these days,
I would definitely, definitely look at this.
Fast modern framework for building APIs with Python 3.6
based on type hints, that's cool.
Responder, this is from Kenneth Wrights.
It's based on Starlet. And its
primary reason for existing is to bring the niceties both from flask and Falcon over into
a single framework. That's cool. Molten, which is a minimal extensible fast framework for building
HTTP API's with Python. And it's sort of magic. One of its magic things is it can automatically validate
requests according to schemas. So you're building API takes a JSON document, it can validate that
by saying this is what this method takes, it takes an integer, and it has this thing in the JSON
document and so on. It's pretty cool. Gepronto, another one of the async and await frameworks,
this one's based on UV loop and Pico HTTP parser, so it's super
super fast. Basically, its foundation is
all C. Klein, have
you ever heard of Klein? No. Me either.
But apparently it's a micro framework
for Python, and
it's got an incredibly
small API like Bottle
or Flask. Speaking of Flask,
there's Cort. This is the one that's closest to
Flask because it is literally a superset of Flask. It's so compatible it even takes Flask. Speaking of Flask, there's Cort. This is the one that's closest to Flask because it is literally a superset of
Flask. It's so compatible, it even
takes Flask extensions and
just runs those. But the difference
here is it adds Async and Await
to Flask. So if you have a
Flask app, you do a find and replace the word
Flask with Cort, and now you can use Async
and Await in Flask. That's pretty cool. That's cool.
Black Sheep, we talked a little bit about that.
This one is inspired by Flask in ASP asp.net core one of its bits of magic is it automatically
supports binding request values into variables either by convention or type annotation so i
could have a view method and it takes a a username and it takes a product ID. And I could put a little decorator that says the username comes from, I don't know, a cookie or something,
and the product ID comes from the query string.
And it'll automatically go and pull those all together
and just pass them as arguments.
That's pretty cool.
And finally, wrap this up, is Cyclone,
another one I've never heard of,
but it's a framework that implements the Tornado API
and the Twisted protocol to bridge Tornado's elegant API
and Twisted's event loop,
enabling a vast number of protocols.
So very, very cool.
Yeah, so unlike my list,
you should not use all of these at once.
No, yeah, your list would be great.
If you try to use all these at once,
yeah, you're just going to mess things up.
It's not good.
Like pick one or maybe two. Maybe if you apis and you've got a web framework but you
probably don't even need to do that just pick one or you could end up with like crashes and exceptions
all sorts of error messages yeah one of the things that there's an application i'm thinking of doing
that i assumed i would i don't want want to go crazy with the microarchitecture,
what are those things called?
Micro-frameworks?
Not the micro-frameworks,
but like the whole bunch of microservices, that's it.
Oh, yes.
However, things like FastAPI and stuff
make it so easy to write the API part
that I am thinking about doing like a two-level thing
of doing a FastAPI and then a web interface based
on that. It's just two services. It seems totally reasonable. Yeah, it seems fine. And with Nginx
and stuff, you can put it under the same domain and just put like proxies to different parts of
your app based on like slash API or not slash API. Oh, cool. So the deployment is really easy.
It's a good thing I have friends like you.
Yeah, that's right.
Happy to help.
So next up, I want to talk about exceptions.
Like I am exceptional and you're exceptional.
We're all exceptional.
Everyone's special.
We're all snowflakes.
Yes.
This is a nice article that just came out this November
called Raise Better Exceptions in Python.
So this is just sort of a
I guess kind of like a
public service announcement. Actually
kind of a nice article though about
when you're raising exceptions,
you know, you throw an assert
in sometimes
to be like, I should
really never get here. But exceptions
are not really unexpected
things. They should be your
software should handle it it's really bad if you're if your software is not handling exceptions
at the top level however often exceptions will happen if like you're raising from a trial you
try some stuff you grab a value error or something and then you raise a more meaningful exception
that's a pattern that's
often used the article is really pointing at just don't put like uh f strings with value stuff
within your just all within one string as a value error or any sort of just don't just like try to
bundle it all together the point is most exceptions unless you've mucked something up in the init,
most exceptions take a
unlimited number of parameters.
So if you want to raise an
exception with a whole bunch of values for
your exception handler to
be able to introspect and
use, just put them
in more parameters in the list of the
constructor to the exception.
That's super cool, and honestly honestly I didn't know about this.
This is great because
the example is if I raise a
value error and the message is the value
is too small, it's like okay great so
now what? Maybe you can't even get back to
what the value was because the
way it got passed around or
it wasn't in a variable so what can you
report on that value? Could you log
the value?
Whatever, right?
But you can just say, here's the message, comma, thing one, thing two, thing three, thing four,
and it just appears in the exception.args later, and you can deal with it in your catch clause.
It's great. Right, and some people will realize that, but not realizing that you can put them as parameters,
but realize that you want to know the value.
So they'll try to put the value in a string.
But that depends on the repper function or the stir function being valid.
And maybe that's the thing that blew up in the first place.
Exactly.
It's simple, but it's going to be really handy.
Yeah.
Love it.
All right.
Well, that's it for our main items.
You got anything extra you want to chat about quick?
Yeah, I did.
It showed up on your list, but I'm going to bring it up anyway.
So I was reading around on realpython.com and I came across this thing.
I don't know.
There was this guy that was being interviewed.
It said a Python community interview with Brian Ocken.
Yep.
I did that thing.
Awesome.
That's cool.
Yeah.
So if people want to learn more about you, they can go check out this interview on RealPython, right?
One of my favorite questions and answers is the question of,
how did you get into testing?
And really, I never did.
I've always been a software engineer,
so that was a fun question to answer.
That's cool.
Anything else?
Yeah, I got two more things that I want to talk about.
One of them comes from Brett Cannon, sort of.
It also had you appearing on this little list of mine that I've got.
So Brett Cannon put out a poll, and the poll said,
if you typically keep your virtual environment locally with your code, as I do,
like so at the top level of your project folder, what do you call it?
Is it venv?
Is it.env? Is it.venv? Is it dot env? Is it dot venv? Is it
something else? And so on. And that's pretty interesting. You can see the polls straight up
no dot venv is what came up the most. And that's what I've migrated towards these days, mostly
because some of the tooling works better than the hidden ones or dot EMV, but you know, you've got some replies in here and all sorts of stuff,
but the one that caught my eye the most,
and I think maybe you commented on it was from Brian here as in Brian skin.
And he said,
I actually use the ability to change the prompt name,
right?
So normally the,
when you activate that virtual environment,
it would just say parentheses V and V and you're like, okay, super.
So something somewhere in my entire computer is different about Python, but which, right?
But if you do dash dash prompt equals, you can give it a name so that when you activate it,
it says, you know, like Python Bytes web app or whatever it is you want.
Yeah, I always use that.
You do? That's cool.
Yeah, because otherwise all my virtual environments are named V-E-N-V,
and that's boring.
That's quite boring.
So, yeah, it's pretty cool, and you can even pair that with, like,
the read command and then take that.
So when you create the virtual environment,
you could set up a script that will ask,
what do you want your prompt to be called?
And then it'll just put it into the virtual environment,
so when it activates it, it converts it over to that, which is pretty cool.
So my request is, I haven't actually requested this yet,
but I would like it to be the name of the directory that the virtual environment is in.
Not the VENV one, but the parent directory.
Yes, that would actually almost always be the right answer, wouldn't it?
Yeah, it's usually my project name.
That's what I want to know.
So that's what I'd like. And then Al Swigert said, I use V-E-N-V. Al said he uses dot V-E-N-V
for the reason that you shouldn't muck with it. It's just there, but you shouldn't change it.
And I'm frustrated that he's right. And I think I'm going to try using it with a dot from now on,
or for at least a little
while and see what I think.
Yeah.
The reason I like not having the dot is that when I'm in the Finder, if I go over there,
I could see, okay, this one already has a virtual environment set up.
I haven't been on this project.
It was in GitHub.
It's been like six months.
I come back to it.
Like, do I need to create a virtual environment or is there already one here?
I just go activate.
So in Finder, you can't see the dot files no it hides them that that's hidden oh I guess I use command
line more than anything else yeah yeah so if you want to see them in finder you have to go into the
dot folder and then you can say open dot or open that folder and then it'll like be half grade out
in finder but if you just browse to a project you won't know whether or not it has a virtual
environment if it's a dot something okay anyway it's not a huge benefit but that's why i kind of stopped
using the dot which i had been before so for the the subset of people that are on max but don't
like a command line i also like the command line but i don't exclusively use it right okay okay
yeah anyway this is um a whole long discussion
about this and i thought it was actually pretty interesting all the the threads there yeah yeah
pretty cool all right last thing i told you about a new course last time right yeah well since then
i wrote another course and uh recorded it and i think this one's going to be really fun for people
as well i wanted to write a course for people who are team leads who are decision makers at their company,
and they're trying to decide,
or they're working with their team to decide,
like, should we adopt Python,
or is Python the right thing for this project or not?
So I wrote a course called
Python for Decision Makers and Business Leaders.
If you need ammunition to help sell Python
in your organization,
or if you want to know, like,
maybe when it's not the best choice,
like, this talks to all those things.
And it also looks at, like, the job market
and hiring developers and all kinds of random
stuff that I think those groups
would care about. So, anyway, another course is
coming shortly. That's really cool. Yeah, thanks.
I might want to do an alternate course
of Python for indecisive cogs.
You might want to
work on the name. It might not attract.
You know what?
I am an indecisive cog.
I will.
Maybe.
Yeah, yeah, maybe.
Maybe.
Anyway, it was a lot of fun to put together, and it'll be out pretty soon.
Okay.
You got a joke for us?
I got something for you.
You can tell me whether it's a joke.
So this comes to us from Daniel Pope.
He didn't send it in.
I just found it on the internet, and it was his joke.
So I'm going to at least. It came through him, so
I'm going to share it. This one is
about farm implements.
What is a tractor's
least favorite programming language?
I don't know. What? Rust.
That's bad, right?
Definitely a groaner.
That reminds me.
How do you tell when a
joke is a bad joke?
When it's fully grown?
Oh, that's a good one.
I like it.
Thanks a lot.
Yeah, yeah.
Thanks for being here, Brian.
It's fun.
Bye.
Yeah, bye.
Thank you for listening to Python Bytes.
Follow the show on Twitter 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.
This is Brian Ocken, and on behalf of myself and Michael Kennedy,
thank you for listening and sharing this podcast with your friends and colleagues.