The folks over at Astral have made some big-time impacts in the Python space with uv and Ruff.
They are back with another amazing project namedty.
You may have known it as Red Knot, but it's coming up on release time for the first version, and with its release comes a new official name, ty.
We have Charlie Marsh and Carl Meyer on the show to tell us all about this new type-checking project.
This is Talk Python to Me, episode 506, recorded May 1st, 2025.
Are you ready for your host, please?
You're listening to Michael Kennedy on Talk Python to Me.
Live from Portland, Oregon, and this segment was made with Python.
Welcome to Talk Python to Me, a weekly podcast on Python.
This is your host, Michael Kennedy.
Follow me on Mastodon, where I'm @mkennedy, and follow the podcast using @talkpython, both accounts over at fosstodon.org.
And keep up with the show and listen to over nine years of episodes at talkpython.fm.
If you want to be part of our live episodes, you can find the live streams over on YouTube.
Subscribe to our YouTube channel over at talkpython.fm/youtube and get notified about upcoming shows.
This episode is sponsored by Posit Connect from the makers of Shiny.
Publish, share, and deploy all of your data projects that you're creating using Python.
Streamlit, Dash, Shiny, Bokeh, FastAPI, Flask, Quarto, Reports, Dashboards, and APIs.
Posit Connect supports all of them.
Try Posit Connect for free by going to talkpython.fm/posit, B-O-S-I-T.
And it's brought to you by Auth0.
Auth0 is an easy-to-implement, adaptable authentication and authorization platform.
Think easy user logins, social sign-on, multi-factor authentication, and robust role-based access control. With over 30 SDKs and quick starts, Auth0 scales with your product at every stage.
Get 25,000 monthly active users for free at talkpython.fm/auth0.
Hey, Charlie. Hey, Carl. Welcome to Talk Python To Me. Awesome to have you here.
Thank
you so much for, I guess, having me back on and having Carl here too. We're really excited to be here.
Yeah, great to be here. Yes, I've had you both on before, but never together, here side by side on the screen.
Yes.
So amazing.
You folks over at Astral, you're doing things in the Python space.
You're making people talk about it, which is pretty interesting.
Yeah, that's kind of our, that's our goal.
We want to get people to talk about Python.
And so it's a good mix for what we're doing on the podcast.
Yeah, I mean, a big part of what we've been doing is just trying to like inject as much energy as we can into the Python ecosystem and like see what comes of it.
So yeah, this new project that we're working on, I think hopefully we'll
shake things up a little bit more too.
It's absolutely going to.
I was just thinking this morning, as I was realizing we were going to be talking today and not some other day, that I was using both Ruff and uv on a project, multiple projects already this morning.
And I smile every time I do.
They're both great projects.
Thank you.
I appreciate that.
I
do want to talk about uv for just a moment before we kind of go down the other side of the branch there.
But before we do either of those, it's been a while, Carl, since you've been on.
And then Charlie, not everyone listens to every episode, so maybe I'll sit on it.
Just maybe a quick round of introductions from you guys.
Charlie, you want to go first?
Yeah, sure.
Hey, I'm Charlie.
I am the founder of a company called Astral.
We build developer tools for the Python ecosystem.
So we're best known for two tools, the first of which is called Ruff.
It's a Python static analysis tool.
So it kind of looks at your code, tries to identify problems, and then in a lot of cases fix them.
It can also reformat your code.
So if you've used tools like Flake 8 or Black before, Ruff is an alternative to those kinds of tools.
And then UV, which is a Python package manager.
So if you've used tools like pip or Poetry in the past, uv would be an alternative to those tools.
It helps you manage all your dependencies, manage your Python installation itself.
So yeah, I've been working on Python tooling full-time for about two and a half years.
And Astral as a company, we're now 14, 15 people working on this stuff full-time.
So yeah, I spent all my time either thinking about Python or writing code to try to make Python better or talking to people about Python.
That's awesome.
I'm Carl Meyer.
I've been hanging around the Python community for a long time now.
Way back in the day, I used to maintain pip and VirtualEnv along with Giannis Liddell and Brian Rosner back in the day.
And for a while, I was on the Django core team, spent some time at Instagram, worked on the cinder compiler there. And then a little more than a year ago, Charlie came along and said, hey, would you like to come to Astral and build a Python type checker in Rust? And that sounded like a lot of fun. So here
I am.
I guess that's our segue into the next topic then.
Yeah, it is. And what a storied history you got there. That's awesome.
It is. Now, I want to take the second half of your sentence there, Carl, and focus on that just for a second, just the Rust side and just the tooling side. I want to talk a little bit about uv because I feel like you should shine a bit of a light on it while you two are here, even though it's not the main topic. So before we dive down the rabbit hole of the new project, let's talk just a little bit of uv. Maybe give us a bit of an update. And also I want to point out that when I said the opening statement, I think you're making people talk about Python things. pip proper got quite a big update recently. And I think a lot of these, a lot of the energy that's being put into other torrents is like, whoa, if we're going to keep doing this, we better keep up. I think you're making a lot of interesting changes. There's the new lock file. Is it pylock.toml, let's call it, I think, and Brett Cannon and crew were advocating for. So yeah, maybe give us a quick update on these things.
Yeah, we're still very focused on uv and uv continues to grow just in terms of the number of users that we have, the amount of companies that are using it, the amount of individuals that are using it.
I think I ran the numbers the other week and over the previous seven-day period, it was over 20% of PyPI traffic came from people using UV, which is just an unfathomably large number because PyPI is over 2 billion requests a day.
So that's hundreds and hundreds of millions of requests a day from people using uv.
I
mean, a lot of things have been happening.
We've been participating in some of the newer peps. So yeah, there was a lock file PEP that was accepted that Brett heroically spent a lot of time getting approved. And I'm just laughing because I also felt like I spent a lot of time, but then I just think about how much time he spent, which is so much more. And just I realized how it's just a lot of work to build consensus. So that proposal now exists. It's kind of like an upgraded requirements TXT format, a tool agnostic way to record the exact dependencies and files that you want to install.
And we
ship support for that.
What's the status on that?
Are you 100% that's ready to go?
Or is there any sort of caveats like it's tentative, it's new?
Parts
of it are technically behind the preview flag, but that just means that you'll get warned if you don't pass the preview flag.
So it exists.
I think the thing that's maybe a little tricky to convey is we still use our own uv.lock format and we view the pylock.toml as sort of like an export format or an interoperability format because it doesn't quite support everything that we need in our format.
So if you just like use uv to resolve and install and manage your dependencies, you'll still use a uv.lock, but you can export out to pylock.toml and then you could use that with other tools.
You could also like generate a pylock.toml with pip, for example, and then install from that in uv.
So it's really meant as an interoperability format with other tools, but it's supported throughout the API. And we'll try and just make that support better and better over time. And also, hopefully, if we can find time, do a few more iterations on the spec to try and expand the scope of what that format can do too.
But it's a big upgrade over requirements.txt.
A lot of people historically used requirements.txt as a quote-unquote lock file.
Like you'd write out, yeah.
And it was kind of like the best thing that we had for a while where it's just like the package equals equals the version and then maybe the hashes.
And that's just not, it's not a great interoperable format.
For one thing, it's not standardized.
There's not really a specification around it.
It's basically defined by like what pip does.
So when we have wanted support for it, We just constantly had to ask, well, how does pip handle this syntax or this grammar or this case and do that or make maybe small improvements to it if we thought we could.
The other is that it's not super secure.
The ability to put hashes in it helped a lot.
But with PyLock.toml, for example, it'll list the exact URLs that you should use.
And you can say that this package needs to come from this index and all that kind of stuff.
So it's a really nice improvement over those.
That's pretty interesting.
Yeah, I'm glad that we tried to ship support for it pretty quickly.
So I'm sure there's a lot of like, there's sort of like a long tail of things we could do to make it a little bit better, but I'm pretty happy with the state of that so far.
Fantastic. Carl, anything you want to add? I know you're not quite working on uv most of the time, probably.
I don't think I have anything to add on uv. I enjoy using it, but.
There's no uv --check types or nothing like that? No flags in there?
In the future.
Yeah, it's on the roadmap.
Nice. I will not install a package that lies about its types. This is how it's going to be.
the new version check. You
laugh, but I think that being able to integrate these tools together is actually something that we're very interested in.
Interesting. Okay. We'll
sort of get into it, but we're building a type checker and there's a lot of powerful things we could do in terms of making the type checking, like just work. If you're in a uv structured project that like uv understands and uv can manage the dependencies. There's a lot of like interesting interop that we could do between the tools. I mean, we want them to all work great standalone if you're like just using it in however way you want. But when you bring those things together, I think there are some cool opportunities to make the experience a lot more powerful and seamless.
There's definitely room to grow. It's super popular, over 50,000 GitHub stars, which is incredible, right? That's almost as many as Flask or Django has. But, you know, Armin Roeneker did a Twitter thread that said, if you're not using UV, tell me why. And there was a bunch of misconceptions and other things. So there's still room for you guys to grow, right? 100%. Where's that 80% of IPI traffic, Right. But let's talk about your new project, which I guess doesn't really show up here, but I'm going to sort of. No, it doesn't show up here. It's secret and not an announcement.
Possibly group. So I think let's start with an announcement. Let's start with an announcement.
The title of the show at the working title, the working title that I put here for, because at the time that was its name or the live stream at least is Red Knot, Ruff's new type checker. Yes.
That still lasts a week. What's going on here? Tell me about it.
When
we start a new project, we always develop it under a codename because we don't want to spend a bunch of time trying to figure out the right name up front.
It takes a lot of time to pick a name.
And so I shouldn't even say this part on the air, but like uv for a long time, for all of its development, it was called Puffin.
Puffin?
P-U-F-F-I-N?
Yeah,
yeah.
And the names are always birds.
And it's a little bit of an inside joke.
but like I didn't know that when I chose the name rough for rough that a rough is actually a kind of bird and Mika on our team after making bird jokes that I didn't understand and I thought it was just being like silly and then eventually we had a conversation where he brought up to me that it's a bird and then it finally made sense because I had no idea so now we always use birds for the code name so when we started the type checker we used the code name red knot and that's really meant to be a code name although it sort of takes on a life of its own but we're going to release type checker under a different name, which is T-Y, just the letters T-Y. So that's what we'll be publishing it on PyPI and everywhere else. And that will be, anyway, so we'll have to change the name of the show.
Yeah, we'll update it. We'll update it. Red Knot is now T-Y, it's going to be the new title. Well, now we'll see.
Yeah, you heard it here first on Talk Python.
That's right. That's awesome. Yeah. It keeps with the nice, concise names that you got. Does T-Y have anything to do with birds?
Not to my knowledge.
Maybe someone will tell us it does. I don't know. Exactly, Carl, in some language, it's like a parrot or something. I don't know.
Yeah, we like names. When we go through this exercise of trying to pick a name, I mean, it's super hard and actually probably my least favorite part of the job, which is maybe saying something. I mean, it's good that that's my least favorite part of the job.
But when we try to pick a name, we're looking for a few things. We want something that's short and ideally very easy to type. That's one of the things that we actually think about a lot.
And we want something that's kind of distinctive and in some way thematic.
So we liked ty because we could get it.
It's very short.
It's pretty distinctive.
And it ambiguously ties into lots of different things like type checking, but it's also an acronym for thank you.
And so it actually shouldn't really be clear why it's called that ideally, but
it has a bunch
of ambiguous reasons why it could be called that.
And it's incredibly easy to type.
And you get to write ty space check to detect your types, which is like somewhat invaluable.
Well, I do think that having a short CLI command is an ergonomics thing, right?
It is useful.
Yes.
I did find out this morning from David on our team who's in Germany that he was confused why we kept saying ty was easy to type because apparently on a German keyboard the Y and the Z are swapped and so the Y is kind of like way off
to the side with your pinky finger.
Wow.
So
I have to apologize in advance to all of our German keyboard users that it won't be quite as easy to type for you.
That's interesting, yeah.
So what are you guys going to do if they download it like a thousand times you'll send them like an alternate keyboard or something?
Yeah, we have multiple people on the team in Germany.
So
we'll publish a keyboard
shortcut that smobsters ZNY.
Yeah.
When I lived in Germany, one of my concerns was I was changing jobs and stuff.
I'm like, oh, please don't make me buy a MacBook here.
Please.
I can't handle the keyboard.
I got
to get one with the layout that I'm used to, which I guess that wherever you are, that probably that goes for same.
But luckily I got to keep my US layout.
I mean, we should all be using Dvorak anyway.
We're all doing it wrong in just slightly different ways.
This portion of Talk Python to Me is brought to you by the folks at Posit.
Posit has made a huge investment in the Python community lately.
Known originally for RStudio, they've been building out a suite of tools and services for Team Python.
Previously, we've talked about how Posit Connect makes it easy to deploy and share the data science assets you make with Python.
Today, I want to talk about sharing those assets securely.
If the mention of laws like HIPAA, GDPR, or even just company policies make the hair on the back of your neck stand up, you'll know you want a trusted partner to help your data become shareable, but also follow the data safety rules we all have to live by.
Posit Connect is here to help. Posit Connect lets you securely deploy and share what you build in Python with Streamlit, Dash, Plotly, Bokeh, FastAPI, Shiny, Flask, Quarto, Reports, and APIs.
Here's how. You or your IT team set up Posit Connect on a secure server within your org or on a trusted cloud service protected by your org's existing authentication system.
When you publish a piece of content, Posit Connect lets you set user-level permissions for that content, making it visible to some users, but not everyone.
You can also use Posit Connect to collect credentials from your users to pass on to data sources that your content draws from.
so you can devise dashboards and apps that show each user only what they have permission to see in your data warehouse.
So if you work on a data science team where security matters, you owe it to you and your org to check out Posit Connect.
Visit talkpython.fm/connect today and get a three-month free trial to see if it's a good fit.
That's talkpython.fm/connect.
The link is in your podcast player show notes.
Thank you to Posit for supporting Talk Python To Me.
So Red Knot is now TUI and that has been a major focus for, not the name, but the project itself has been a major focus for our team for the past, wow, a while, almost a year, maybe a little bit less. But we've been, yeah, we've been working on this for a long time. So I'm excited that we're in a position where we can finally start talking about it. I'm
excited. When I saw it, I'm like, oh, I have to have you guys on the show. We've
got to talk
about this because this is a big deal. So let's just start by talking about like why a type checker at all. We've had a couple of type checkers. There's a few benefits you can get from them, but I'll let you all riff on that a bit. Python itself is a dynamic language. Let the ducks be ducks. What are we doing here?
Python gets used in a lot of different ways.
And I think compared to the initial vision for Python back in 1990 or whenever Guido released the first version, it's used for a lot bigger projects and more sort of serious software engineering than it was maybe initially envisioned to be for. And I think when you get larger projects, larger amounts of code, larger numbers of people working on the projects.
There can be a lot of value in having some machine enforceable documentation about your intention when you wrote this function.
What were you envisioning that it should operate on?
What were you envisioning that it should return?
I know certainly when I was at Instagram and working on the very large Python code base there and thousands of developers with a lot of turnover coming in and out of that project, you can waste a lot of time digging kind of through layers and layers of code, just trying to understand even what is this variable?
Where could it come from?
What could it look like?
And a type annotation can give you that information kind of just right up front immediately.
So there can be a lot of value in that.
And certainly I don't think anyone, or at least we are not aiming to change Python into a fully statically typed language.
I don't think that would be possible or desirable.
It's great to have that flexibility for a continuum of use cases.
But for those who want to have types available and type enforcement, we can make that available where in an opt-in kind of gradual way.
There's a couple of different elements to it, all of which Carl touched on in some way, but one helps prevent you from shipping bugs, helps you write correct code.
But the other piece is, I think the types and the typing have actually played more and more of a role over time because what you end up getting is the way that the types feed into the editor experience. So it's not just about running a type checker to check that your code is correct, but I actually talked to teams that don't even run a type checker, but they still add type annotations to their code because when they add type annotations to the code, the editor is more useful to them. The auto-completion is better and they get real-time diagnostics. So even if you're not actually running a type checker on your code for whatever for whatever reason like adding types to your code can actually make you more productive by integrating with the language server in the editor so i don't know for me it's actually a really big part of how i write python i try to write pretty stupid python and do that with like a fair number of types and i find that that's what helps me like scale so i don't know i think i think the typing it's like it's useful both in the context of i want to run this in ci and like make sure that i'm not shipping code that has like obvious problems and in the context of how I make myself just like more productive when I'm like sitting in my editor writing code trying to figure out like how to implement the given function.
I was going to jump in and say that but you you articulate it very well for me I don't run a type yeah I don't run a type checker but I want my editor if I am going to the documentation for stuff that I kind of understand how it works I'm probably doing it wrong in my mind if I see star args star star kw args and I'm just like ah what am I going to do but most of the time you can just hit dot or parentheses and then there's all the information provided either the editor can detect the type somehow through some chain or you just type them there and then it's just bam bam bam and until you kind of don't understand stuff or it's really new then you maybe go to the docs but like you're saying you can just fly and I will throw out a new one that is now relevant in the last couple years if I am going to take some python code and share it with an ai of some variation some agent code generator or chat or whatever if that code has types in it it's way better because it probably doesn't have the possibility of getting the right context otherwise
yeah that's a big part and it also creates a feedback loop for if you are running like an agent or you if you're using like cursor or cloud code or one of those systems you actually create a feedback loop whereby they can iterate on the code without executing it right because they can run your code run it through a type checker, look at the diagnostics, and then modify it in turn. So it's like, I sort of think some of this stuff will potentially become like even more important, like the static, providing good static analysis, because it's your opportunity as a human to like hit the computer in a given way and inject some context. So I mean, we'll see, I could be like completely wrong about that.
But I at least find it to be really helpful in those contexts too.
Yeah, I see some comments out there in the chat that are like, yeah, same thing. I also, I liked Carl's comments that sort of for large real projects, you can opt into this. And I like, one of the powers of Python, I think, I guess, to put it this way is I feel like you can be incredibly productive and you can get a lot done with Python with a very partial understanding of what it is, like incredibly partial, right? You don't have to know what a class is, maybe not even a function, but if you can string together 10 lines of interacting with some library, you might have accomplished something that would make you, wow, I'm not a programmer, but look what it did.
And that's great that it has that level, but as it grows bigger and more serious, I've heard the comment from somebody on some podcast somewhere, like they were lamenting the fact that there's so much Python in data science, machine learning. They're like, oh, this is a language for unserious people. Well, it can be used in an unserious way, but things like this are part of like, I choose to use it in a serious way, right?
It's not a
flaw of it.
It's actually a power of it that you, when you don't need a systems level language, you don't have to write systems level code.
But when you're ready to, you can sort of progressively add on these layers and run things like Ty to check it.
Wait, is that what happened?
Do we T-Y or Ty?
What's our pronunciation?
T
-Y, Michael, come on.
No, that's funny you say that because like that's off, that is sometimes how I think about actually like what we're trying to do here, like with this company and this like set of projects the first place, which is Python is this like enormous programming ecosystem, like the largest or the second largest programming ecosystem on earth. And yet there's a lot of people who just don't take it very seriously or are constantly predicting its demise. And yet it just keeps growing. And so my approach has generally been, well, what if we just take it really seriously?
We'll just bring in the smartest people. Hopefully I'll try to recruit the smartest people I can come in and build like really serious software.
And the net effect is like, you can have an enormous impact because we build, like I was talking about UV, right?
Like we build uv and suddenly we have like, I don't know, hundreds of millions of requests running through that project a day.
And so you just think about the scope of impact because Python may not be a perfect language, but a lot of programming and technology is about path dependence, right?
Like people, it's very hard, like Python is going to continue to be used in tons of places, even if despite its problems.
And so my perspective has always been, well, how can we like meet that world where it is and like try to build really great tooling because the amount of impact, it's like a huge lever.
So yes, I feel that way about like kind of everything we build, but it was funny to hear you say it.
And we spend a lot of time now with companies that are like have hundreds and hundreds of engineers, like Python programmers working on like a single code base.
And yeah, for them also the performance is a big piece of it.
So how do they get these tools to like scale to very large projects?
And our goal is to basically build tooling that can scale to very large projects, but is also useful and helpful for people like beginners and people working on very small projects.
We want to have something in the tool that's useful and valuable to both of those demographics, which are very different.
So we often think about kind of like building for scale, but like designing for everyone.
Like we want to build a tool that can scale to like tens of millions plus lines of code.
And what is also like meets a beginner where they are and like helps them like get started and like get productive with Python.
So either one of you want to take this one, like why, so we understand why types are important, but why are you all building a type checker, right?
We have myPy, myPyRite.
Why don't I say why I decided that we should build a type checker and then we'll see what Carl says.
So I think for me, like when I, there's a couple of pieces to it.
One is like when I started working on RAP and then I started the company, there was always a vision in my mind of this like unified set of tools that we wanted to build and put together.
And we did the linter and then we did the formatter.
And the type checker was kind of like always the missing piece there of, well, if I had like a suite of static analysis tools that handled everything for my project, I would want like a lint or a formatter and a type checker.
And we didn't have that.
And I was like, I think that would really help complete the story for what we're trying to provide to people.
So one piece was, this is the experience we want of like, you can use Astral's tools.
It like gives you everything you need really to be productive with Python.
But the other piece is, this has been the thing that people have asked me for probably more than anything else ever since we released Ruff.
So I think it's natural that people would ask for it because this is like sort of in a similar space of things that you do.
Like, but everyone's saying, hey, I'm having problems with my type checker.
I'm having problems with my type checker.
When I switched to rough, I experienced this great, this change and how I work.
Can you bring that same experience to, to type checking?
And I think for me, the answer was like, yeah, we absolutely can.
I don't see any reason why we can't provide the same like level of quality of life improvement.
So, you know, part of it was I saw a big opportunity and within that opportunity, I think there were like two things that really stuck out to me.
One was performance.
And this is more about people working companies that we talk to where they're working on really large projects.
Maybe the type
checker.
Your little demo app probably is going to be fine.
Yeah, demo app's fine.
Yeah.
But like the, if you have a really, if you have a big company with a lot of people working on a Python project, this comes into play in a couple of different ways.
One is like some companies can't even really run the type checker locally anymore, or they're spending a lot of money running it on huge machines.
That's a real thing that happens.
Other times it's the language server.
the thing that lives in your editor that gets slowed down. So we'll talk to companies where like, they're like the language server can't index our project anymore. So go to definition doesn't work. Or every time I change branches.
Yeah, let me throw a little background information on there.
For people who don't know, the way your editor autocompletes, goes to definition and all that kind of stuff is there's this language server that parses and understand the code almost like an abstract syntax tree and it needs to read all the all of the code and allow you to basically use that live information as you interact with it and what you're saying charlie is if it's too big then basically it's always behind or just can't quite handle it it's always
behind or can't fit all the context into the system or
something like that and so and what you're hinting at is you might fix this yeah
we want to fix that so it's not just about building a type checker we also want to build a language server and these two things are like intimately related like pylance which is a very language server, you might not even know you're using it, but it's like the primary language server in VS Code is powered by PyRite, which is another type checker. And those tools are very interconnected. It's like when you try to autocomplete something in your editor, the editor needs to go through a process of understanding, well, what are the valid options that could fit here? And that is similar in shape to a type checking problem. So part of it was performance of seeing these huge projects and all these companies that were coming to us saying, we're having all these problems with the scaling of the tooling to our projects.
and the other was the ability to build i think like a really different experience by integrating more of our tooling like we've thought about this with rough which is a linter and then rough we have like rules that for example should only run on dictionaries and so we might need to understand like could this object be a dictionary in order to know whether we should flag a certain rule and right now we do basically like bad unreliable things to understand like is this variable could it be a dictionary? And if you kind of take that to an extreme, you could imagine we could build a much better lender if we actually had access to type information. Like if we knew what all the variables were in the program and like what types they could take on, we could give people much better information about the problems that they have. So part of it was like performance. Part of it was this opportunity to build something that I thought was really different. I
think those are the primary motivations, performance for sure. I think we're already seeing that we can be quite a lot faster than the existing type checkers. I think another thing that's become clear as we've worked on ty is that there are areas where we do want to provide a little different experience than some of the existing type checkers. And I think this connects to what we were talking about before about the way Python scales with you as a project grows and the way you can kind of start out with something quick and simple and realize it's successful and grow to make it bigger and kind of gradually opt in to stricter typing. One thing that has been part of the experience in Python typing up until now is that even though it's supposed to be something that you can gradually adopt, the reality has been that if you have a code base that's working but isn't really typed and you start to run a type checker on it, you'll probably get a pretty long list of type errors the first time that you run it. And you really have to spend a lot of time adding type annotations and even reworking the way some of your code works in order to make the type checker even happy with your code. Because the type checkers, for various reasons, they're sort of opinionated often and making kind of assumptions about, well, if you assigned an integer to this variable here, then clearly you never meant to ever assign anything else to that same variable later in the function or whatever. And so you sort of have to adjust your code to work around the assumptions the type checker is making.
And one thing that we're aiming to do with ty is to try to smooth that curve a little bit in the sense that we try not to make assumptions about what you meant and rely on what you've explicitly told us about your types so that if you run it on a code base that isn't typed, we'd like to, but that is working correctly, we'd like to not issue a bunch of false positive errors right off the bat and just start to issue errors gradually as you start to gradually add type annotations.
This portion of Talk Python to Me is brought to you by Auth0.
Do you struggle with authentication?
Sure, you can start with usernames and passwords, but what about single sign-on, social auth, integration with AI agents?
It can quickly become a major time sink, and rarely is authentication your core business.
It's just table stakes that you've got to get right before you can move on to building your actual product.
That's why you should consider Auth0.
Auth0 is an easy-to-implement, adaptable authentication and authorization platform.
Think easy user logins, social sign-on, multi-factor authentication, and robust role-based access control.
With over 30 different SDKs and quick starts, Auth0 scales with your product at every stage.
Auth0 lets you implement secure authentication and authorization for your preferred deployment environment.
You can use all of your favorite tools and frameworks, whether it's Flask, Django, FastAPI, or something else, to manage user logins, roles, and permissions.
Leave authentication to Auth0 so that you can start focusing on the features your users will love.
Auth0's latest innovation, Auth4GenAI, which is now available in developer preview.
secure your Agenic apps, and integrate with the Gen.AI ecosystem using features like user authentication for AI agents, token vault, async authorization, and FGA for RAG.
So if you're a Python developer or data scientist looking for an easy and powerful way to secure your applications, get started now with up to 25,000 monthly active users for free at talkpython.fm/auth0. That's talkpython.fm/auth0. The link is in your podcast player's show notes. Thank you to Auth0 for supporting the show. I think it makes a lot of sense. We talked about the different motivations and reasons that people might use types. And so I can certainly see why that would lead to different expectations or roles or whatever from your tools, right? If you're adding types so that your editor is better or so you can talk to AI better, you might not want it to be just super complaining at you that every little thing is wrong. I know on some of the projects that I run, I did some decorator and the decorator was just, it was super complicated because it can do both sync and async functions. And like it just somehow I got the type. It's just a little bit wrong, but I didn't ever notice it. You don't ever call the view functions directly in your code because that's what the frameworks call, right? And you put the at get on it or whatever. However, some people running that through the type checker are sending me things, say, well, look, you're getting this warning for using this decorator here. I'm just like, okay, I'm going to fix it. It's fine. And understand that. But, you know, is the type checker actually helping you to say, we expected the thing that you never called to look like this, but it looks slightly different. Like, well, tree falls in forest, no one's there kind of thing, right? I pulled up this GitHub issue here on rough. And this points at two questions I want to get to. The one on the screen is not the first one. That's the second one. Perfect. First one is, will this be part of rough or is ty its own separate uv tool install type thing?
How will I manage it, right?
We're planning to release it as a separate tool.
So you'd install it separately and uv tool install ty or uv install ty and then run it asty.
Okay,
because it came out, I feel like its motivation, as you guys are saying as well, came out of Ruff, right?
The linter and formatter.
But as you thought about it, I guess, this is actually its own thing now, right?
But if you look at all the GitHub issues, like a lot of them are on Ruff actually.
Yeah, it's currently built in the Ruff code base.
So they share a code base and that's mostly just for convenience because we share a lot of common infrastructure with Ruff.
So like the parser and the abstract syntax tree and all of that are shared between Ruff andty.
But yeah, and we initially did consider the possibility that we would develop the type checker kind of more under the covers in rough and sort of gradually start to power more and more rough lint rules with type information without really shipping a type checker per se. But we kind of debated those two options and decided that it just really seemed like there was a high demand for a type checker, a full type checker like my pyrepyrite. And we thought we could reach that goal more efficiently and quickly if we did it a little more separately from rough at the product level.
Makes sense to me. All right. Now the real question I actually have on the screen.
Will Redknot, aka ty, because that was the code name, right? Will ty be a drop-in replacement for mypy or PyRite? The
thing I'm slightly buoyed by, and Carl is in a much better position to comment on whether this is actually true, but from my perspective, at least, a focus area for typing in Python broadly as an ecosystem has been increased conformance. So trying to create rigorous specifications around how some of the typing features that are a little underspecified should work. And then ensuring that the type checkers can implement common behaviors on not all dimensions, but on some of those dimensions. I think there's still, my feeling is the intent is still that there's actually room for some subjectivity in how type checkers work, but that in a lot of areas, they actually want to standardize how things are supposed to work so that there can be less deviation.
Yeah, particularly when it comes to, yeah, particularly when it comes to typing a public API for like a library author.
I mean, if you just have your own project that you're running your type checker on, you're probably going to pick one type checker and run it.
And so it's okay if it behaves differently from some other ones.
But if you have a popular library and you want to provide types for your library, you may have some users of your library using mypy and some using PyRite.
some are going to use ty and so we need to in particular have some standardization in the type system that allows a library author to provide types for their library that will actually work for all their users and so in ty we do aim to to pass we don't yet we're not that stage yet but we do aim to pass the conformance suite for the python typing specification and be a standards conformant type checker there may be some points of tension where we have a different opinion about how some things should be done.
And we'll probably have some discussions there about changing or suggesting some possible changes to the spec in some areas, but we will aim to be conformant.
Yeah, that's excellent.
I was just messing with my rough.toml for one of my projects.
Are you going to have a tie.toml or something like that, that we can tweak the rules?
Oh yeah.
Currently we already have a not.json, which I think probably needs to become tie.json.
Or I guess it's tie.not.toml.
So it'll be tie.toml, yeah.
I think it's JSON in the web playground, probably, because,
yeah, we
have a web playground for this stuff.
And in those contexts, it's much easier to, you can have a JSON schema, so it's, like, much easier to use JSON also because it's all natively built.
Like, JavaScript just supports JSON.
Excellent.
A couple of thoughts here from the audience.
Let's jump over there.
Richard Ellison asks, this sounds awesome.
What will the client setup look like?
Will it all be server-side?
Please don't put magic into the client like PyLance does with PyRite NeoVim user here, by the way.
I wish some of our other developers here who work on the LSP stuff more were here to answer this one, but I think we're aiming to just follow the LSP standard and not put magic into the extension for, say, VS Code that wouldn't be something you could replicate on NeoVim or any other editor that uses LSP.
A
core goal for us here is like, I mean, this will, of course, be open source and permissively licensed just like our other tools.
I guess it's probably MIT right now, just by way of being in RUV.
UV is dual MIT in Apache, but RUV is MIT.
So I think that implicitly this is all MIT.
And an explicit goal here is by building an open source language server, it should be possible to use it in any editor that supports language server protocol equally well.
So if you have people on your team using NeoVim, VS Code, whatever, Zed, like any of these editors, you should be able to plug in our LSP and get an equally good experience in all of them. And I actually view that as like a big, a big advantage and kind of like reason to do this, which is that I think we can build a language server that you can use in
any editor
and have the same experience across your team and on the command line. So yes, we want it to be like, it's very intentional that we don't want there to be like any magic in the server or whatnot.
Like we want this to just be a thing that implements language server protocol that you can use from any editor that supports it.
I guess the analogy would be like Rust Analyzer, which maybe isn't actually a great analogy for this audience because it entirely depends on whether you've written Rust before.
But Rust Analyzer is the Rust language server and you can use that in any editor and that works great.
Nice.
All right.
Other question I thought was good is Andrew Alder asked, just started listening, will this be accessible as a library from the Python side.
I could be interested to be able to write scripts against types.
Yeah, we're just like laughing.
I think you go, Carl.
My answer to this one would be that I don't see any strong technical barriers to this.
We already sort of have an internal API where you can just say, given an expression in the AST, what is its type?
And so exposing that to Python should be technically not too difficult.
I think the challenges here are just prioritization of that versus other things.
and wanting to be a little careful about what we lock ourselves into API-wise.
So I would say it
should be possible, but not an immediate priority.
Sure. What about plugins or extensions or extensibility, something like that?
Plugins and extensions are somewhat unlikely.
I mean, maybe.
I think we would prioritize plugins and extensions for lint rules over type inference, which is sort of a fuzzy line to draw.
but a lot of people want plugins and extensions in rough often to do things that they want to identify certain patterns or whatnot.
And I think we would support that before we supported extensions in the type checker.
Sure, I can see things like, we want to detect this general usage pattern that is indicative of...
Yeah,
or like this library should never be imported in this part of the code base, or this function should never be called without first calling this function or something like that.
Sort of what I think of as proprietary rules.
basically, like things that are very specific to your project.
But Carl, what's the thing that David implemented, the Python typing, the import?
We have a module.
It's kind of a fake module because it doesn't exist in Python.
It just exists in the mind ofty.
It's currently called NotExtensions.
I suppose we'll probably rename it to TYExtensions.
It has a bunch of interesting tools in it that you can kind of import and use to sort of ask the type system what it thinks of the type of a certain value is or make some assertions that this type is a subtype of this other type.
So if you're kind of interested in getting into the nitty-gritty of what's happening under the hood with a type system, we do expose something you can import and use in your code to do some of those things.
It's a little different, but it's sort of vaguely at the intersection of importing something.
In
terms of plugins, I think, at least on the type checker side, there's sort of both philosophical and technical reasons to be pretty cautious, like philosophically on the type system side. I think we believe that there is value in having a specified and standardized type system that's the same for everybody. And so that you can have a project that's using one type checker and decide to switch to another one. And we don't really want to have, so plugins are kind of antithetical to that in the sense that if you have a plugin, it's clearly specific to one type checker. And then if you're relying on that plugin, well, then that's kind of a barrier to be able to switch to a different type checker.
And so I think we have a preference for having, if there's patterns that people need, we should find a way to include those in the typing specification so that all type checkers implement them rather than having them in a plugin.
And on the technical level, it's, I think, difficult for us just because what language do people write their plugins in?
If it's, I mean, is it like a shared library?
If it's written in Python or Lua or something, then potentially we lose a lot of the speed.
So I think there's a few different reasons that we are hesitant to do that.
Let's play around a little bit here.
So over at types.rought.rs, you actually have a type checker in your browser, I guess, that you can play with.
First of all, how does this run?
Is this WebAssembly?
Is this the server-side thing?
What's happening?
This is TY's Rust code compiled to WASM.
So it's literally ty running in your browser.
It also makes it very fast in your browser, which is nice.
What if I go over here and I put like a 7 or something?
I don't know what's going to happen.
That's testing against 7.
But I'm going to make it.
Moment of truth
here.
It came up as a literal of seven, which I don't want.
I saw somebody in the chat was asking about inlay type hints, and I was going to point out that they exist right here.
As soon as you type that in, it gave you a little inlay showing the type.
Define what that is.
So if I type like style.
So
like if you type style equals seven there.
Not the dot.
So you didn't type colon literal seven.
You didn't put any type annotation there.
We're just putting an inlay right into your code to show you that that's what we understand the type to be.
I see.
So this is not actually in the code, but the editor sort of deal displays it.
It's
showing you the type that the type checker inferred despite the lack of annotations.
And you could put style colon int, for example.
Even up there, you could put something.
I don't know.
Maybe put an int.
Yeah, yeah.
If I put appears, like you always have a type.
So I'll put this as a style.
I'll do it like that.
There we go.
Now I'm getting my warning.
There we go.
That's what I was expecting.
So I can just play around here.
Yeah, and then you also have an error
there on the bottom,
right?
because online 24,
because you're passing the string in.
Yeah,
you pass in underlined, but the real value is underlined.
Yeah, so I'll be sure to put this in the show notes and people can go to the playground and play around.
So you also got your not.json.
You can specify your Python version and rules can be warnings.
Yeah, and like Charlie said, that's actually specific to the web playground in the terminal, I mean, outside of the playground context, that would be a toml file, not a JSON file.
Yeah.
We spent a lot of time up front.
Thank you.
Yeah, perfect for this
screenshot.
Perfect.
We spent a lot of time up front, which makes sense, but really on the architecture and the core design of how should this all work.
And we wanted to build, we had some fairly specific design goals.
We wanted to build a type checker that could power a language server.
I would say that was the first thing that we were trying to do.
And that imposes some pretty specific, I don't know about constraints, but it really informs like kind of how you build it. Because if you think about a language server, like what happens is you open up your editor, and you open up like a file, okay, to understand like what's happening in that file, you don't necessarily have to like, look at everything in the editor, like every other file in the project, like you should be able to like quickly give people some analysis and some information just based on looking at like the current scope, and then like the things that imports, right? And kind of like figuring out like, what do I need to look at in order to answer these questions? And the thing that you also want is that if the user like edits that file, you don't want to have to reanalyze like the whole world. You want to reanalyze basically as little as possible, like maybe that file and like anything that's affected by it, et cetera, et cetera. So to like, to just like sit in a terminal and like check the types of a program is like one problem.
But building a language server is pretty different because what's happening is things are changing in real time and you want to be able to do like the minimal amount of analysis at all times to like get people the answers to the questions that they're implicitly asking.
Right. That's a per keystroke thing rather than I run a command.
From
that perspective, we needed the whole thing to be highly, I mean, the word we would use is incremental. So we're incrementally pulling in more context. Or if the user makes an edit to a file, we're recomputing just incrementally the things that might have changed and to update our view of the world.
So that informed a lot of the design.
The fact that we wanted this not only to work as a standalone tool that you run on the command line and CI, but also could power this language server experience, that ended up informing a lot of how we approached the design.
And we spent a lot of time trying to get that right and give us a good foundation for building that.
So does it do progressive stuff if there's some huge code base and it makes some changes?
Will it try to give you answers sooner than it reanalyzed everything?
Yeah,
so if you're checking a very big code base or a code base that, say, has a lot of big third-party dependencies, whichever files you actually ask us to check, we'll check that whole file.
And then each individual thing that it imports, like say you import one little constant that's just like a string or something from a massive third-party file that has a whole bunch of stuff in it.
we will literally ignore all of that file and just go straight to the one like constant the definition of that one constant that you actually imported and we'll just look at that and so that we've seen that that makes i mean it's good obviously for being incremental when you make changes but that also just gives a big speed up for just the initial cold check of a project because we're able to just ignore all the things that you aren't using that might be sitting there
in your dependencies i mean a little like tree shaking css or whatever like i know it's there but these things don't matter.
We're just going to look at the things you're actually touching.
It's like,
let's figure out exactly what we need to look at and then like go just do that work.
A
lot of how we power that is through a library called Salsa, which this is getting a little bit into the weeds of Rust, but it's also powers the Rust Analyzer, the Rust language server that I mentioned before is also powered by Salsa.
So we've been collaborating like with the Salsa team basically since the start of this project saying like, hey, like we really want to use this.
And like, here are things that we really would need and like, blah, blah.
And we've actually spent, I mean, I shouldn't speak for the team because I've done basically zero work here, but like we've been contributing back to Salsa and like investing a lot in making Salsa better.
So, and also learning from Salsa and learning from like Nico Matsakis and like the people who work on REST Analyzer and everyone else.
So it's been cool to kind of like have this community of people who cared about building language servers or other things that rely on highly incremental computation.
And that's been a big part of actually like the design and building of the type checker has been the choice to use Salsa and then our investments like back in it to try and improve it in different ways that are important to us.
But Carl can speak to that much better, that process at least.
Yeah,
I don't know if I have a lot to add to that.
I mean, I think the cool thing about Salsa and about building on top of Salsa is that it provides a very kind of abstracted general framework for incremental computation is what it's called.
So like you basically define your program or your type checker in our case as a bunch of queries and every query should have an output based on only on its input.
So it should be deterministic, right?
So like a query could be something like given the input is this assignment statement.
The output is what is the type that was assigned to the variable in that statement.
And so we kind of build up the entire program in terms of those queries.
And we can kind of build it ignoring the whole incrementality problem, like the idea that one thing might change and we don't want to analyze a bunch of stuff unnecessarily.
And Salsa just handles that for us automatically.
So if we build in terms of all of these queries, Salsa will automatically track when we're doing our initial type check of everything, which queries depended on which other queries and ultimately depended on like which file contents.
And so then if you just change one part of one file, Salsa can just flow that change through the graph of queries and figure out exactly which queries may have been affected and need to re-execute, and all the others can just be left alone.
So it allows us to kind of have that level of very fine-grained incrementality without really having to think a lot about it as we're building the type checker.
It's honestly like super cool.
Yeah, it sounds like a reactive sort of data structure almost.
You know, it just keeps itself in sync.
That's cool.
I do want to talk about the roadmap a little bit here.
And by way of introduction there, I'll ask a question from Islam here.
It says, is there a date for the release of this?
You know what, Carl?
I give you that one in your hands.
Well, thank you.
It depends what you mean by the release.
I think we are targeting a sort of general availability release where we really feel like this is ready to be used in production and could be, you can swap out mypyrePyrite for it.
And we're targeting that for sometime later this year, probably in the fall sometime.
We don't have a solid date on that yet.
We are aiming for an initial, what we would call maybe an early experimental preview alpha release.
And we're aiming...
There's a lot
of good qualifiers there.
I mean, there's definitely things that will be missing, like type system features that we won't have yet.
and there'll be bugs, et cetera.
You should expect all of that.
But it's just something to sort of play with and kind of get a little flavor of what we're trying to do.
And we're aiming to have that available so that you can install it by PyCon, which is coming up, I guess, May 16.
So by that week, we're hoping to have something out.
Yeah, a couple of weeks from right now.
Yeah,
that'll be a very early release.
I was laughing and I made Carl answer the question because I wanted to see how exactly he would describe it.
But that release, our goal there is not necessarily for people to like take it and migrate over to the tool.
It's more like to kind of, it's just kind of a milestone for, we have a thing now that we can put out there and people can play around with and see like where it's strong and where it needs work.
And we'll know, there'll be a long list of features that like aren't yet implemented, but it will be able to check some of your types and understand your code and it will be highly incremental and it will be very fast and et cetera, et cetera.
So that'll be like a very early release, but we wanted to get something out there for people to kind of play around with.
And then, yeah, from there, we'll look to do a beta a little later in the year.
And the framing there will probably be something like motivated users should be able to migrate over.
And then we'll do, again, we'll do a
general.
If you don't mind the rough edges.
Yeah, yeah.
Motivated
users is a phrase I like to use.
So, but we want to do, yeah.
I mean, hopefully we get this sort of like general available full public release a little later this year.
So that's the goal that we're working towards.
I know it's a vague timeline, but that's the goal that we're working towards.
That's how software goes.
So when you say all this stuff about timelines and things that people can try and so on, are you talking language server?
Are you talking type checker?
Both?
We're talking both.
Yeah.
No sleep for Carl.
Come on.
Yeah, sorry, Carl.
Carl, are we talking both
now?
Yeah, we're talking both.
For
the language server in particular, there's kind of a long tail of features that we want to support in the language server, just like lots of things that a great complete language server can do.
And we, to start, we're very focused on like code navigation, like a smaller number of things, like being able to go to definition, being able to do auto-completion, auto-import, all that kind of stuff.
So we're going to, the first versions of the language server will be very focused on a smaller number of features, like code navigation and the things that you need, in addition to the kind of diagnostics that you see on the screen.
So like type errors and like things are undefined.
But beyond that, the focus will be like code navigation and auto completion, auto import, those kinds of things.
And I should say that for this initial preview alpha for PyCon, the focus is really on the online playground and running it on the command line on your code.
The LSP support is there and it will be possible for you to try it out, but we're not going to really push that at this point because it's very early stages.
So we're not going to be like releasing a VS Code extension or any other editor extensions or anything at this point yet.
That'll come later.
Yeah, of course.
Got to build the foundation first.
One of the things I was thinking about when you two were talking about, well, why does it need to be fast?
Well, there's large code bases and there's the editors.
Another thing that came to mind, for me at least, was thinking about continuous integration and large teams and large code bases.
And soon as the time your CI takes to run outruns the gaps between check-ins, you're getting into a bad place where they fall further and further behind, right?
And so certainly having a good CI story seems important.
I'm guessing you guys might have thoughts about, I don't know, pre-commit hooks, CI, GitHub integration, stuff like that.
I know you have that for UV, Charlie.
Yeah, I mean, I think we want to have a good experience there.
We want to have a lot of the similar niceties that we have for Ruff.
It will like take maybe a little bit of time to get to all of them, but Ruff obviously has like a pre-commit integration.
It also has a GitHub Action.
And I think we'll probably provide basically all those things for ty as well, or at least that would be my expectation.
we haven't built them yet but the good news is we have a lot of infrastructure that we can leverage from rough for for everything really like also even like releases and like the release pipeline like thankfully we've done all this now once arguably twice because we've done uv too although like uv doesn't have quite as many of those things because they just don't make as much sense but the good news is like we've built a lot of that infrastructure already and we've been able to leverage it for for this project i think similarly like fuzzing like we can probably leverage a lot fuzzing infrastructure that we have for rough for for this program too so the good news is we've built a static analysis tool before and so we have like things we can leverage to make that happen
yeah that's cool and shout out to the uv caching github action thing that's pretty excellent yes set up uv the
biggest ci feature in my mind is performance right so like we're talking to people who are today waiting 25 or 30 minutes for feedback in ci from the type checker and we want that to be 10 to 15 seconds instead of minutes.
So it's looking at this point, like we're on track for that.
I
think it's hard for people to actually, I think people don't actually realize that, but there are Python projects out there that are taking dozens of minutes to type check.
And we want to get that down to, yeah, two seconds.
And so that's like, that's what we're aiming to do.
And I hope, I think there will be a lot of other benefits to the type checker in the language server, even for smaller projects.
That's something that we think about a lot.
Again, how can we build things that are useful and interesting and powerful for products of all shapes and sizes?
And I think having the language server that works in all these different editors and it's tightly integrated with the type checker that you run, I think that will be really helpful for people.
I think the type inference will be really powerful.
There's all these things we want to do, but the performance is a little bit of a North Star.
It's like we should be building things that are orders of magnitude faster than what else
is.
That would be on brand.
So I'm sitting here looking at this playground, and I have Python code in the browser, and you're telling me WebAssembly is checking it.
So is there a way I could actually use this if I'm doing Pyodide or PyScript type of things?
Do you have any expectations to worry about that, or is it just more CPython-like?
I mean, the ty just operates on source code, so if it's Python source, we should be able to check it.
Speaking of Pyodide, though, one cool little feature of the playground here is there should be, you see that little run arrow over on the right-hand side?
That will actually, whatever code you have in the playground that you're type checking, that will run it using Pyodide.
Yeah, you have to click the run button there.
That's
our goal.
Today we have Ruff, we have the linter, we have the formatter, and we want to build a similar experience for type checking and for the editor.
There'll be a lot of tie-ins with Ruff.
You hint at this, but if you go to the rough issue tracker, there's a lot of issues that have been raised in rough over the years that we've now basically assigned as being part of the scope of Red
Knot.
What other color could you pick for the label, right? There's a GitHub label you can go and pull them all up.
Yeah, sorry, part of ty, but the GitHub label is Red Knot.
Only
the people who were really early believers will know why the colors red are involved withty.
I
had a very incredible experience. I went to EuroRust in maybe in November of last year.
And when I was there, I gave a talk about uv. And after the talk, a bunch of people came up to me and were like, it was a Rust conference, but a bunch of people were like, hey, like, we really like your like Python tools, like blah, blah, blah. And then I like a bunch of them just brought up and started talking to me about Redknot. And I was like, what's going on here? Because we didn't, we had not talked to anyone about that project. It's never been hidden. It's been developed in the rough repo from the start, but we didn't advertise it at all. And so it was like only like really deep rough heads knew that this was even happening. And I was like, okay, this is the degree.
Incredible. We
must be doing something right. Because these people just came up to me and started talking to me about a top secret public project that we haven't advertised anywhere.
Hidden in plain sight. That's awesome. Yeah.
We did uv in a little bit of a similar way, actually, where we had two major releases. We did the initial launch, which was all the UVPIP stuff.
And then we did a bigger launch later with lock files and all this other stuff. And all that stuff was developed just in the repo. But we didn't talk about it at all until it was publicly launched.
And yet we had this steady stream of people, avid users who were testing it and giving us lots of feedback over time. So that's the attitude that we've taken, I think, here too, is we just build it in public. And some people choose to get involved and choose to use it and choose to give us feedback, but we don't really advertise it until we're kind of ready to unleash it to the world.
I guess this is a little bit of an exception, but we'll have our early experimental alpha preview release in a couple of weeks and then it will be released to the world.
Let's do a final call to action. People who maybe didn't know about it before, but now they do. Pretty excited. They might want to give you feedback or try it out or whatever. What are you telling them? If
you're highly motivated, you could go clone the rough repo and build the experimental Red Knot codename binary and run that on your project and see what works. But if you're not incredibly motivated, then you should wait several weeks and we'll have something for you that I think will be a lot more useful.
Type.rough.rs and play around with it in your web browser. That's the least motivated thing you could probably do. Thank you both for being here and
congratulations on all the projects and cranking out and the continued work. And we didn't even get to talk about an update with Python Build standalone, but thanks for that as well. It makes a lot of things really great.
This is what we love to do. We love to build stuff that hopefully people like to use as the ambitious slogan for our approach to tooling. Hopefully people like to use it.
Yeah, they'll say thank you every time they run it, every time they check their code, right?
Yeah, well,
thanks so much for having us on.
It's always a pleasure.
And yeah, well, I think this stuff's going to be launching in the next few weeks and months.
And so stay tuned.
Thanks, guys.
See you later.
Thank you.
Thanks.
This has been another episode of Talk Python to Me.
Thank you to our sponsors.
Be sure to check out what they're offering.
It really helps support the show.
This episode is sponsored by Posit Connect from the makers of Shiny.
Publish, share, and deploy all of your data projects you're creating using Python. Streamlit, Dash, Shiny, Bokeh, FastAPI, Flask, Quarto, Reports, Dashboards, and APIs. Posit Connect supports all of them. Try Posit Connect for free by going to talkpython.fm/posit, P-O-S-I-T. And it's brought to you by Auth0. Auth0 is an easy to implement adaptable authentication and authorization platform. Think easy user login, social sign-on, multi-factor authentication, and robust role-based access control. With over 30 SDKs and quick starts, Auth0 scales with your product at every stage. Get 25,000 monthly active users for free at talkpython.fm/auth0. Want to level up your Python? We have one of the largest catalogs of Python video courses over at Talk Python. Our content ranges from true beginners to deeply advanced topics like memory and async.
And best of all, there's not a subscription in sight.
Check it out for yourself at training.talkpython.fm.
Be sure to subscribe to the show, open your favorite podcast app, and search for Python.
We should be right at the top.
You can also find the iTunes feed at /itunes, the Google Play feed at /play, and the direct RSS feed at /rss on talkpython.fm.
We're live streaming most of our recordings these days.
If you want to be part of the show and have your comments featured on the air, be sure to subscribe to our YouTube channel at talkpython.fm/youtube.
This is your host, Michael Kennedy.
Thanks so much for listening.
I really appreciate it.
Now get out there and write some Python code.