Python Bytes - #159 Brian's PR is merged, the src will flow

Episode Date: December 3, 2019

Topics 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)
Starting point is 00:00:00 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.
Starting point is 00:00:24 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.
Starting point is 00:00:48 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,
Starting point is 00:01:11 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
Starting point is 00:01:36 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?
Starting point is 00:02:14 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
Starting point is 00:02:44 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,
Starting point is 00:03:01 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.
Starting point is 00:03:35 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
Starting point is 00:04:04 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
Starting point is 00:04:47 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
Starting point is 00:05:03 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,
Starting point is 00:05:18 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.
Starting point is 00:05:48 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,
Starting point is 00:06:24 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.
Starting point is 00:06:39 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.
Starting point is 00:07:01 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?
Starting point is 00:07:19 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.
Starting point is 00:07:34 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
Starting point is 00:08:17 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,
Starting point is 00:08:46 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.
Starting point is 00:09:10 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
Starting point is 00:10:01 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
Starting point is 00:10:28 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
Starting point is 00:11:02 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.
Starting point is 00:11:41 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.
Starting point is 00:12:02 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.
Starting point is 00:12:31 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.
Starting point is 00:12:44 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.
Starting point is 00:13:02 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.
Starting point is 00:13:20 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.
Starting point is 00:13:43 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
Starting point is 00:14:20 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,
Starting point is 00:14:41 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.
Starting point is 00:15:01 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.
Starting point is 00:15:15 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
Starting point is 00:15:29 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
Starting point is 00:15:46 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
Starting point is 00:16:17 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
Starting point is 00:16:52 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
Starting point is 00:17:16 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.
Starting point is 00:17:28 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.
Starting point is 00:17:41 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
Starting point is 00:18:18 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,
Starting point is 00:18:34 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,
Starting point is 00:18:46 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
Starting point is 00:19:01 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
Starting point is 00:19:21 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.
Starting point is 00:19:42 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
Starting point is 00:20:00 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,
Starting point is 00:20:27 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.
Starting point is 00:20:49 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
Starting point is 00:21:12 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
Starting point is 00:21:50 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
Starting point is 00:22:06 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.
Starting point is 00:22:22 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.
Starting point is 00:22:57 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,
Starting point is 00:23:16 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
Starting point is 00:23:39 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
Starting point is 00:23:59 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.
Starting point is 00:24:28 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.
Starting point is 00:24:43 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
Starting point is 00:24:59 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
Starting point is 00:25:32 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
Starting point is 00:25:57 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
Starting point is 00:26:13 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,
Starting point is 00:26:35 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.
Starting point is 00:27:01 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.
Starting point is 00:27:15 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.
Starting point is 00:27:23 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?
Starting point is 00:27:41 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
Starting point is 00:28:08 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?
Starting point is 00:28:40 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.
Starting point is 00:29:05 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?
Starting point is 00:29:21 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.
Starting point is 00:29:44 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.
Starting point is 00:30:16 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
Starting point is 00:30:34 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
Starting point is 00:31:14 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.
Starting point is 00:31:36 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
Starting point is 00:31:51 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.
Starting point is 00:32:08 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.
Starting point is 00:32:18 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
Starting point is 00:32:32 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?
Starting point is 00:32:47 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.
Starting point is 00:32:53 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.

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.