#233: The Masonite Python Web Framework Transcript
00:00 Folks, it's not like the old days where there were just a couple of web frameworks for building applications with Python.
00:06 These days, there are so many web frameworks to choose from.
00:09 One of those is the Masonite web framework created by Joseph Mancusio.
00:13 Joseph is here today to tell us all about Masonite, what makes it special, its core value proposition for web developers, and much more.
00:21 This is Talk Python to Me, episode 233, recorded September 11th, 2019.
00:26 Welcome to Talk Python to Me, a weekly podcast on Python, the language, the libraries, the ecosystem, and the personalities.
00:46 This is your host, Michael Kennedy. Follow me on Twitter where I'm @mkennedy.
00:50 Keep up with the show and listen to past episodes at talkpython.fm.
00:54 And follow the show on Twitter via at Talk Python.
00:56 Joe, welcome to Talk Python to Me.
00:59 Thank you. Thanks for having me.
00:59 Yeah, it's great to have you here.
01:00 I'm really excited to talk about Masonite and sort of do a quick survey and dive into these modern web frameworks.
01:07 That's going to be a lot of fun.
01:08 I think a thousand flowers are blooming these days on the Python web framework world.
01:13 We've had some stalwart web frameworks, primarily Flask and Django, but Pyramid and before then some others like TurboGears and whatnot.
01:23 But those all have been around for a really long time and slowly growing or, you know, really slowly maturing.
01:29 And I feel just like every month there's a new interesting framework.
01:33 Yeah, yeah. I think that's exactly right.
01:35 And when I started Masonite, I thought I was doing really, really good.
01:39 And then I guess it's because I got into the ecosystem.
01:42 And then all of a sudden I saw like a whole bunch of other frameworks start like blossoming from that.
01:45 And it's probably because I just wasn't, you know, in it, in the ecosystem more.
01:50 So I just saw it more.
01:51 But yeah, there's, it seems like every, every couple of months there's something new coming up.
01:54 Yeah.
01:55 It's really positive, I think, but also creates some confusion.
01:58 We'll talk about that in a bit.
01:59 Before we get to it, though, let's start with your story.
02:01 How'd you get into programming and into Python?
02:03 I always never know which story to tell, like the long story or the short story.
02:06 But the medium story, I guess, would be that in high school, in ninth grade, I got kicked out of school for a bunch of stuff, like fighting and stuff like that.
02:13 I was a bad kid.
02:14 And I had, I was homeschooled for like eight months after that until the next school year.
02:20 And I was very, very bored.
02:23 And I didn't really know what to do.
02:24 And at the time, when I was 14, I was actually into Pokemon too.
02:29 So I was like, you know what, I'm gonna, like, I'm gonna just play this Pokemon game.
02:34 And then I got into, and I wanted to like build websites too, because I had a lot of time on my hands.
02:38 So then I got this website, you know, I started learning like C and then like C++, and I didn't really like it.
02:44 And then I was like, you know what, I'm gonna start trying to develop websites, maybe.
02:49 And then I got into PHP, because I found really good documentation.
02:54 I mean, good YouTube tutorials about PHP.
02:58 Yeah, and it seems like PHP is like a real quick and easy way into web development.
03:03 Like a lot of folks go that route, and they kind of, I don't know, graduate to like more formal languages.
03:08 Python.
03:09 Yeah.
03:09 Intermediate level, I guess there.
03:11 Formal languages.
03:12 Yeah, sure.
03:12 Yeah, so I got into PHP, and I watched, you know, the new Boston.
03:17 I don't know if you've ever seen so many tutorials.
03:19 Yeah, right.
03:20 They did a ton of tutorials and stuff.
03:21 I haven't seen a lot of stuff from them lately.
03:23 But yeah, they were on all over YouTube for a while, weren't they?
03:26 He hasn't made a video in like four years.
03:27 He sort of just dove off to 50,000.
03:28 But at the time, he was huge.
03:30 He only had like maybe 40,000, 50,000 subscribers, I think, at the time.
03:33 And now he's probably at like three or four million.
03:35 But yeah, I went from there.
03:37 And then I took sort of this Pokemon thing.
03:40 And then I used that as my base of a project to build like this website.
03:45 And then I built, you know, this website.
03:47 And I had people on Tumblr, I think it was at the time, like start using it.
03:52 And I thought it was like amazing that you could build something and have people use it.
03:56 It was like, it was crazy.
03:58 So I got into PHP.
03:59 And then from there, I really just took off PHP.
04:02 Like from like ninth grade to when I graduated high school, you know, 18 years old, I just coded nonstop.
04:09 I didn't do any homework.
04:10 I didn't do anything else besides like go to school, come home, and then just start coding.
04:15 Oh, that's pretty cool.
04:16 Like it was just your deep passion, huh?
04:18 Yeah, it just clicked.
04:20 And I had like this entrepreneurial spirit.
04:21 And I realized that I can create these websites and sort of make money from them.
04:24 I can monetize them.
04:26 I can put ads on them.
04:26 Did you have friends who were working, like making like $4 an hour minimum wage?
04:32 And you're like, you know what I'm doing?
04:34 Yes, I cut them checks.
04:35 I cut them checks for like $1.25.
04:37 And I gave it to them in class.
04:38 Yeah.
04:39 How'd you know that?
04:40 Did you, I feel like.
04:41 No, no, no.
04:42 I just mean like they had other jobs, like minimum wage jobs.
04:45 Oh, yeah, yeah, yeah, yeah.
04:46 And you had like these businesses making real money.
04:47 Yeah, yeah.
04:48 I didn't know they were actually working for you directly.
04:50 But I imagine that you probably in high school had, like I had friends.
04:53 And even for a while, I worked at like a pizza place.
04:56 I think I made like $3.25 an hour, right?
04:58 It was the minimum I could be paid, you know, to go there.
05:03 And I mean, eventually I went and did some other really wild stuff that is like super funny and
05:08 outrageous and not probably, it'll be too much of a diversion to cover now.
05:11 But it's just really funny to probably contrast like you and like high school building these
05:18 sites, you know, running interesting things and folks going, well, you know, I'm bagging
05:23 groceries.
05:24 Now there's anything wrong with that, but it's quite the contrast.
05:26 Yeah.
05:26 That's so true.
05:27 Even my stepbrother now, he does like marketing or something for like, you know, a big like
05:30 a corporate guy.
05:31 And he's like, dude, he's like, I wish when you were in the other room, just coding nonstop.
05:36 He's like, I wish I like, I did it with you.
05:38 And like, we learned coding together.
05:40 He goes now, because now you're, you know, you're off doing this job, doing this great big
05:43 project that you're, you know, your job.
05:45 And he's like, I'm sort of sitting here like at a cubicle, you know, like just banging
05:49 paperwork.
05:50 You really got into it.
05:51 It sounds like you just really independently went after PHP and Belize sites and that's,
05:56 that's super cool.
05:57 So where'd Python come from?
05:59 When I was 18, I joined the army and I came back and I was still sort of doing programming
06:03 within the army because it was, you know, it's a passion of mine.
06:05 It's a hobby.
06:06 And then when I got out, I wanted to build a POS ordering system that you see like a, like
06:12 a kiosk almost like a pizza place.
06:13 So I wanted to build that.
06:15 So I wanted to learn something new and do it.
06:18 So I picked up Python just because it was just something new.
06:22 It was cool.
06:22 They seemed to be rising at the time with like the whole data science thing and machine learning.
06:26 So I thought it was cool to sort of pick it up.
06:28 And then from there I built, I needed to pick a framework and the obvious one at the time
06:33 seemed to be Django.
06:34 So I picked up Python for about a month.
06:37 I learned on like Code Academy.
06:38 I did like all the basics and then I picked up a framework and then I started building this
06:43 thing out.
06:43 It took me about probably eight months or so to build this thing.
06:47 And then I actually said, all right, you know, I'm going to start trying to sell this
06:50 thing.
06:50 In hindsight, it was actually crap.
06:52 But at the time I thought it was super cool and I wanted to create a company.
06:56 And one of my all time goals in life is to have a 100 person software development company.
07:02 Yeah, that's a good goal.
07:03 I put that in the same ballpark as like...
07:05 It's nice.
07:05 It's concrete.
07:06 Yeah.
07:06 Yeah.
07:07 It was like Gary Vaynerchuk's like want to buy the jets sort of thing.
07:09 So I sort of put it there.
07:11 Like it probably never happened.
07:12 Even if you look at like Basecamp, like even they have like a couple dozen employees,
07:15 I think.
07:16 And they're like a huge company.
07:17 So like a hundred person software development company is gigantic.
07:19 But anyway, I digress.
07:21 So I built this thing and I even went like door to door to like businesses to try to sell
07:25 this thing.
07:26 What was that experience like?
07:27 Were they receptive?
07:28 Were they just like, what are you doing here?
07:30 Like you're from the internet.
07:32 Why are you in my place, my pizza place or whatever?
07:34 That's exactly what it was.
07:35 But actually my whole philosophy is that I'm really not afraid to fail.
07:39 And even if I fail, I learned something from it.
07:41 And it was super nerve wracking to like walk in, just cold walk into a business.
07:46 But I figured like even if I fail, like I'll probably learn something from this guy.
07:49 And what I actually learned, which was interesting is that when I went in and I asked them if they,
07:54 if you know, is your manager there?
07:55 I tried to like, I had like a whole pitch like lined out.
07:59 And they basically said that, oh no, sorry, we've already tried some and it just, it just
08:05 doesn't fit us.
08:06 And I thought that was interesting because I was walking into companies that didn't have
08:10 it, you know, online, but it makes sense that they've probably been around for five,
08:14 10 years.
08:15 And if they don't have one, they had to have tried one already.
08:18 So I use that failure to sort of repitch into, oh, I know you've tried something before,
08:25 but maybe you should try this instead.
08:27 I see.
08:28 It didn't work before.
08:29 And here's why it's going to work this time.
08:30 Right.
08:31 And something like that.
08:31 But nobody really went for it.
08:33 And I'm not really a sales guy.
08:34 I'm very introverted sometimes.
08:36 I call myself an ambivert.
08:39 So I'm like, I'm sort of introverted, but I'm extroverted in comfortable environments.
08:44 Right.
08:44 If that makes sense.
08:44 I think that describes a lot of tech people, honestly.
08:46 Yeah.
08:47 Yeah.
08:47 That's probably true.
08:48 I think this is the start with most people in general.
08:49 I mean, very few people I think that I've, I've experienced are really introverted.
08:54 Like once you get familiar with them and they get comfortable with you, they're just like off the wall.
08:58 Yeah, for sure.
08:59 This is a really cool way to get into Python.
09:01 And where did you go from there?
09:03 So from there, I learned a, I wanted to learn a new technology.
09:07 Each year I try to make it a theme.
09:10 That year I wanted to learn frameworks.
09:14 So I learned like Django and Python.
09:16 And then I wanted to, I already came from PHP.
09:19 So I wanted to learn Laravel because I never learned Laravel all the time.
09:22 So then I created a new site.
09:25 You know, us, we just have a bunch of side projects that we try to create businesses out
09:29 of.
09:29 I created a new side project, which was basically like a textbook rental service.
09:33 Okay.
09:34 And I built like a whole business model out of it and how I was going to do it.
09:38 And then I built the site in Laravel and I used like Google API and all that stuff to
09:42 try to build this thing out.
09:43 And I actually really liked Laravel.
09:45 And then from there, I worked with Laravel more and more.
09:48 And then finally I got a job locally working with Laravel at the company I work with now.
09:53 And that's what I do right now.
09:55 What are you doing day to day?
09:56 What kind of work?
09:56 Sounds like more web development.
09:58 I continue web development right now.
10:00 Day to day, I work for a wholesale military supply company.
10:05 It's actually a pretty big company.
10:07 It's like 150 person company.
10:08 The web team is probably about like six strong.
10:13 And we run this basically this multimillion dollar website that does all the wholesale
10:17 processing and all that.
10:19 I also am in charge of a four person software development team that we're working on a large
10:25 scale ERP project to basically run this whole company.
10:28 Yeah, cool.
10:29 So I'm taking a lot of those concepts and trying to come home, apply them to Masonite.
10:33 Yeah.
10:34 Excellent.
10:34 All right.
10:35 Yeah.
10:35 So let's dig into the Python web frameworks.
10:37 So speaking of Masonite, if you go look at the usage stats, we've got 40% Django, 40% Flask, plus or minus a couple in there.
10:47 A little bit down from there, we've got like Pyramid.
10:50 I think it's like 6% was the last usage I saw there.
10:53 You know, that rounds out a significant portion of what is Python and web frameworks.
10:59 But like we talked at the opening, it used to be, well, Flask, Django, which are you?
11:05 It's kind of was the greeting or whatever amongst the Python web developers, right?
11:10 The last two or three years, there have been so many different frameworks.
11:14 We have Jepronto, Sanic, Vibora, Starlet, FastAPI, Hug, Falcon.
11:21 It's not even a super clear connection.
11:23 API Star, for example.
11:25 So there's Starlette and there's FastAPI.
11:29 FastAPI?
11:30 Which one?
11:30 I think there's a handful of websites that actually use Starlette underneath.
11:36 I think Responder from Kenneth Wright, for example, is one of those.
11:40 So there's just, there's like this layering on of what people's different ideas of the Python
11:45 web world should look like.
11:47 And how would you summarize that?
11:50 You know, is that looking at trying to make type hints do interesting things?
11:54 Is that async?
11:55 What are the trends that you're seeing in all of those or, you know, kind of in general there?
11:59 So this is mildly controversial.
12:01 And I actually argue a lot with like the people inside the community.
12:04 Well, not argue, but, you know, debate a lot with people inside the community of the correct
12:08 answer is that the trend is moving towards asynchronous frameworks itself.
12:14 Like the actual framework code is built around some kind of ASBee server or asynchronous server.
12:20 That's the trend.
12:21 I'm not entirely sure I agree with the trend because I feel like it forces a lot of people
12:27 that are new to all of this to sort of see the trend and sort of prematurely optimize their
12:34 application.
12:34 So if their application is like a blog framework, for example, they're like, yeah, this blog framework,
12:40 I mean, sorry, this blog application can handle 15,000 requests per second.
12:44 But like, does it need to?
12:46 Does it really need to do that?
12:47 Like, I mean, that is really cool.
12:49 And especially if you try to like load balance across two of these applications, like you can
12:53 handle like thousands and thousands of requests per second.
12:55 But I feel like it's more of a premature optimization.
12:58 Like if you want to use and then when they when they use these frameworks, like a lot of times
13:03 they have to start writing their code with the idea of it being also asynchronous as well.
13:09 Like, you know, thread safe, I believe in this and all that stuff.
13:12 And they can't just take any any ORM off the shelf.
13:15 They have to use like an asynchronous compatible ORM.
13:19 It basically narrows down a lot of your your decision making.
13:23 And I'm not entirely sure if you need to create an API or something, some kind of small microservice,
13:29 just hit API endpoints, get information from a database.
13:32 That's 100% the way to go.
13:34 You need if you're creating a bunch of microservices, maybe for one monolithic application,
13:38 then that's 100% the way to go.
13:40 But that's not the way I like to create my applications.
13:43 Right.
13:43 Yeah.
13:44 So most people just want to create, you know, like a service like a like a SAS or something.
13:48 It's an interesting point that you bring up.
13:50 I would certainly say that there's a trend to see what the cool hot frameworks are doing
13:56 or what the amazing web companies are doing and try to emulate those way too early.
14:03 Right.
14:03 You know, you talked about these websites that you were creating.
14:05 Like when you're, let's say you're creating your, if you're creating your, your textbook rental
14:09 company, you know, you're playing it like, well, we're going to have all the campuses around
14:14 America in September.
14:16 They're all going back to school and getting their books.
14:18 It's going to be crazy.
14:19 And there's going to be all these orders.
14:19 And it's just, you know, and the reality is probably one campus.
14:25 If you were lucky joins in and it starts, you know, like it starts real slow.
14:29 Right.
14:29 And you've got all the, all the time in the world to see the analytics to, you know, you
14:34 scale your web server potentially, if you even have to like a standard web app, it can
14:40 take millions, millions of data-driven requests per month on like a $10 server before you have
14:47 to start worrying about all that stuff.
14:48 It's definitely true that you can just not worry about it for a good long while.
14:53 I mean, if you build your app poorly and it's super slow, then you're going to want those
14:56 features more.
14:57 Right.
14:57 But if you build it well, write indexes on your database and things like that, it should,
15:01 it should fly.
15:01 And it should be able to go quite a long ways until you have to worry about that.
15:04 That certainly seems like a reasonable philosophy to me.
15:07 The other one is, you know, I do training and write courses and do other presentations to
15:13 helping people learn things like web programming.
15:15 And it's super overwhelming.
15:17 As you know, I mean, you learned when you're young, so maybe it didn't feel as overwhelming.
15:20 You just like, you just like, this is how computers are.
15:23 This is what I do.
15:24 Right.
15:24 That's probably, that's probably right.
15:25 But there's HTML, there's CSS, there's databases, there's query syntax, there's Python, there's
15:32 the templating language, there's Linux, there's deployment.
15:34 I mean, there's just so many things, right?
15:36 And if you say, oh, by the way, why are you trying to learn all this for the first time?
15:39 You know, you need to learn asynchronous programming too.
15:41 So don't forget about that.
15:42 I mean, that's a tricky level.
15:44 I feel like certainly that's, it's a really great thing to have for a web framework, but
15:49 it is not necessarily a great starting point.
15:52 Right.
15:52 Yeah.
15:52 And that's what I would say on that.
15:53 tool that you should reach for if you need it.
15:55 But it's not something that you should default to just because it handles more requests per
15:59 second.
16:00 That's my take on it.
16:01 Cool.
16:01 Yeah.
16:02 So I do see like quite a number of those that I mentioned, like Starlette and Sanic and whatnot,
16:06 focusing FastAPI or whatever, focusing on this async aspect.
16:10 But another aspect that I see being used a lot is things like type annotations and some of the other Python 3 features to try to make some of those features help with the web framework, for example.
16:22 Does Masonite do any of that?
16:24 We'll probably talk about this when we get into the Masonite part.
16:27 Masonite has something called an inversion of control container, an IOC container or a service container, which utilizes type hints.
16:36 And the short answer, and we'll do the long answer later.
16:38 The short answer is basically in the controller code and the controller method, you can type hint a class and Masonite will inject that class for you.
16:47 Right.
16:48 So like this controller takes a database derived class or whatever, and then you say that as a type hint, and then the IOC container will like push that in for you.
16:57 Exactly right.
16:58 Yeah.
16:58 If you do like a sort of like a base class or something.
17:01 So if it's an instance of a database base class, then inject the base class or the database driver that you have defaulted or something like that.
17:09 Right.
17:10 What if you've registered?
17:10 Yeah.
17:11 Okay, cool.
17:12 Yeah.
17:12 Yeah.
17:12 So I think this is kind of unique and new that so many of these like last couple of years frameworks have really tried to embrace Python 3, right?
17:21 Like Python 3 has been a struggle for Flask.
17:24 They're not there anymore.
17:25 But like for a while, they had a statement saying basically, we don't work on Python 3.
17:29 Well, we probably work on Python 3, but we don't guarantee it.
17:32 Something to that effect.
17:33 Like four years ago or something like that's pretty rough statement given, you know, the date that it was.
17:38 And then, you know, Django as well, just and 2.0 drop support for Python 2.
17:43 So, you know, they've been kind of carrying that baggage around.
17:48 They can't do things like this with their API, right?
17:51 If you fundamentally said you must have type-ins, well, you know, there goes your Python 2 support, right?
17:55 Straight away.
17:56 So all these new ones, though, they seem to be coming along with like a fresh look.
18:01 So I think that's pretty cool.
18:02 Masonite, I noticed that a lot.
18:05 So like it's pretty hard to support multiple versions of Python that don't work well with each other.
18:13 So like, for example, 2.7 and 3.4, for example, to support both of those.
18:18 So what I wanted to do with Masonite was one, yeah, start with Python 3, but also only default to the latest four versions of Python.
18:28 So currently we support 3.4567 and 8's coming out soon.
18:34 And so far the tests work for 8, so that's good.
18:37 But when 8 comes out, we're going to drop support for 3.4.
18:40 Yeah, that seems reasonable.
18:41 Yeah, my philosophy basically is if you really need to create something in 3.4, then you're going to have to use Masonite 2.2.
18:49 And if you want to use the latest, this way we can sort of keep up with the trends as it goes on.
18:53 Yeah, well, for the moment, Python is released on an 18-month release cycle.
18:58 So that gives you like six years of backwards compatibility.
19:02 That should be enough.
19:03 Right, exactly.
19:04 That should be enough, I would think.
19:06 There's actually a PEP out, I forget the number, by Lucas Lange, to move to yearly releases.
19:12 But that would still be four years.
19:13 That should be good.
19:14 Yeah, yeah, definitely.
19:17 This portion of Talk Python to me is brought to you by Linode.
19:20 Are you looking for hosting that's fast, simple, and incredibly affordable?
19:23 Well, look past that bookstore and check out Linode at talkpython.fm/Linode.
19:28 That's L-I-N-O-D-E.
19:30 Plans start at just $5 a month for a dedicated server with a gig of RAM.
19:35 They have 10 data centers across the globe, so no matter where you are or where your users are, there's a data center for you.
19:41 Whether you want to run a Python web app, host a private Git server, or just a file server, you'll get native SSDs on all the machines, a newly upgraded 200 gigabit network, 24-7 friendly support, even on holidays, and a seven-day money-back guarantee.
19:55 Need a little help with your infrastructure?
19:57 They even offer professional services to help you with architecture, migrations, and more.
20:02 Do you want a dedicated server for free for the next four months?
20:05 Just visit talkpython.fm/Linode.
20:09 I'm really excited about all these web frameworks, Mason and I included.
20:12 However, I have this new problem, right?
20:16 I could go and look and see Flash Django Pyramid.
20:19 Let me compare those and sort of see the things I like or don't like about them.
20:22 And then I can look at history and say, well, it's probably this much supported, so it's probably going to be about that much market share in the future.
20:31 Flask is about 40%.
20:32 There's a good chance Flask is going to be around next year.
20:36 But I don't get that sense with these new frameworks, right?
20:39 Like, Responder was cool.
20:41 I don't know if anything has even been done with Responder in the last, you know, little bit, right?
20:47 It seemed like not a whole lot had been going on with it.
20:49 It took off in like the first like two months and then it sort of died out.
20:52 Exactly.
20:53 I mean, it is super cool and it's great that people are working with it.
20:56 But how do you think about going through these frameworks?
21:00 I mean, obviously, you're just working on Masonite.
21:02 So you're just, you know, going forward and keeping things going.
21:04 But what would you say to people out there about how they should consider the stability of one of these projects?
21:09 Is this like a super cool one month idea or is this an actual thing?
21:13 Masonite itself?
21:14 Oh, yeah.
21:15 It's definitely an actual thing.
21:16 I always sort of think about what Masonite is going to like.
21:19 Masonite is really, really cool now.
21:20 But what is it going to look like in five years?
21:22 Like, what is that Masonite going to look like?
21:24 And I sort of work towards what that's going to look like.
21:27 And then maybe in five years, I'll look for another five years and do the same thing.
21:30 But basically, what I really like about the PHP ecosystem is that a lot of the time, these frameworks, like if you look at Symphony or Laravel, there's faces to them.
21:43 There's people that you can, there's like leaders, you know, like even Django is sort of like, I don't know if it's just me, but it's sort of like this nameless, faceless organization type thing that like, like maybe like this Marvel type organization that like controls like Django.
21:58 Like, I think it has like a committee and stuff, but there's not like one specific person that I know, like, oh, they own it or something like that.
22:05 And like with Laravel, like the guy, Taylor Outwell, you know, he's all about Laravel and, you know, he works on it full time, obviously.
22:10 But I can look at him and I could look at his future and tell the future of Laravel.
22:15 So like me personally, like Masonite is going to be around for like a super, super long time.
22:20 It's, this is basically, Masonite is going to turn into my side project that turns into like, you know, that business.
22:27 Like for example, maybe that text, what that textbook rental service might've turned into.
22:31 That's going to be what Masonite is.
22:33 So, you know, once Masonite becomes profitable, either through sponsorships or partnerships or basically SaaS is around it, it'll just take off from there.
22:42 But I mean, Masonite is going to be around for super long time.
22:44 That's awesome.
22:45 One of the metrics I use is when I go to these projects, obviously I look at how many stars does it have, but also, you know, maybe when was the last commit?
22:54 Is that three years ago or is that two days ago or an hour ago, right?
22:58 Like, what does that look like?
23:00 The other one is, probably the biggest one for me is open PRs that are not being addressed or barely are being addressed.
23:10 That seems like a real big red flag to me, right?
23:12 If you go there and there's like five people who have put a bunch of work in to add some new features and they're just, all you got to do is just verify this is all right.
23:19 And then just accept it and the people running the project can't even be bothered to respond to it.
23:24 As a contributor, that's a crappy feeling, but also that's not a super good sign for the project, I don't think.
23:31 That's right.
23:31 Yeah.
23:32 So the reason I bring this up is when I go to Masonite, there's zero open issues and there's zero open PRs, which is pretty cool.
23:41 So here's like the weird thing with Masonite and maybe in future versions, this will be different.
23:46 But Masonite is really broken up into two different repositories.
23:50 So there's the Masonite repo that everybody goes to and they see has a thousand stars, but like people talked me into, actually, did people talk me into this?
23:59 I'm not sure.
23:59 But at one point I extracted all of the framework itself logic out and I just created an application.
24:06 So people can basically, when people run their craft commands and they run craft new project and it creates this project down, it actually creates that, basically a copy of that repository down onto their computer.
24:17 But if you look at, if you go to the Masonite organization and you go to the core repository, you can see the actual core code.
24:22 That's the actual real code.
24:24 Okay.
24:24 Got it.
24:25 Yeah.
24:25 That's the actual, what's actually driving the Masonite application.
24:28 Basically the Masonite that you see on the one with a thousand stars is basically just a shell of Masonite that I took all the, basically the framework code out and I made it in its own repository.
24:40 And then I made that a package that the shell basically requires.
24:44 So I basically, what I really wanted to do was take out as much.
24:48 So when I first posted Masonite on Reddit, it was at like one version 1.3 and everybody hated it.
24:54 And they said it was crap and it was dumb.
24:56 You know, typical Reddit stuff.
24:59 But the weird thing is that they were right because the original version of Masonite was like a basically one function that like did everything.
25:07 So basically from there, I extracted all the logic out and I kept that repository up because I had so many stars already.
25:14 I had like a hundred at the time or something.
25:15 And I basically created a new package and tried to make it as modular as possible.
25:22 Yeah.
25:22 That makes a lot of sense.
25:23 That sounds cool.
25:24 Seems like there's at least activity on, you know, all the various items there, which is pretty cool.
25:30 Right.
25:30 It's not like three years ago.
25:32 There's a lot of activity over there.
25:33 Hanging out there.
25:33 That's good.
25:34 All right.
25:34 So maybe we could dig into some of the features of Masonite.
25:37 You talked a little bit about why you started it, but maybe give a little bit of clarity on that.
25:43 And then let's just talk about some of its major features.
25:45 Like why would people choose it over the other frameworks and what were some of the goals there?
25:49 So I needed a winter project because I was going, you know, in college.
25:53 So I went to recess.
25:54 I needed, you know, something to do because I'm home all day and programming is a passion.
25:59 I can't just sit home and not do anything.
26:01 So I need to code something and I didn't really have anything to do.
26:03 So, and I was going through my year of learning frameworks.
26:06 So I was like, you know what, let me learn how to, you know, build a framework.
26:10 And so I looked up, you know, how to build a Python framework because that would be cool because the Laravel, I mean, the PHP ecosystem seems, was seemed to be too hard of a competition to penetrate.
26:21 Yeah.
26:21 And I saw a lot of holes that I tried to fill with Masonite in the Python community.
26:25 So I thought it'd be good to build a Python framework.
26:27 And getting a WSGI server takes like maybe seven minutes to set up and running and getting some kind of response.
26:34 You're in some kind of dynamic response, which is probably why so many pop up.
26:38 Right.
26:38 So you're basically, there's like one function you implement.
26:41 There's, they pass you the request and you return the response or something along those lines.
26:45 Yeah, exactly.
26:46 Yeah.
26:46 Yeah.
26:46 It's just a, it's just a normal WSGI application that takes two variables and then you basically return.
26:52 You use one to set the headers and then the other one to return the response.
26:55 Super simple.
26:56 So from there, I basically had it up and running and I was like, okay, well, I'm coming from Laravel.
27:01 So I think it would probably be cool to write my routes in something I'm familiar with if I'm going to start building this framework because I don't want to learn something new even though I'm building it.
27:11 So I took what I'm familiar with and I made the routes look like the modern day routes that they are now.
27:16 And I added that feature in and I was like, oh, that's pretty cool.
27:20 I mean, I wonder if I could add like controller logic too.
27:23 Like that'd be, that'd be cool.
27:24 And so I added the controller logic and the methods and, you know, swapping between different methods and calling certain classes.
27:30 I was like, oh, that'd be cool.
27:32 And I was like, what if I had something like super awesome, like, like built-in email sending support?
27:36 So like I built that in and then I tried to build it all modular.
27:39 And I basically just went from there, like a little, little bit by a little bit.
27:43 I just kept on putting more and more features in until just like out of nowhere, people started joining the community and like contributing actually.
27:51 And we basically, we teamed up me and me and a couple of early adopters and we built into something really, really cool.
28:00 And then we released 2.0 on June of 2018, I think.
28:06 And then from there, it just shot up.
28:08 It went from like 80 stars to like 500 in like a couple of days.
28:11 Wow.
28:12 That's cool.
28:12 Yeah.
28:12 Featured in the right places.
28:14 A lot of people came to check it out, huh?
28:15 Yeah.
28:16 I basically, I think I put it on Reddit and it got like 20,000 views in like three days.
28:20 And it was on the top of our Python and it was on like Hacker News, I think.
28:24 And it got like a whole bunch of, you know, tweets and stuff like that and people talking about it.
28:29 And it basically shot up from there.
28:30 Yeah.
28:30 Super.
28:31 You started out this conversation by talking about routes and the routing mechanism and controllers.
28:37 So let's maybe dig into the code story around that a little bit.
28:41 Now, talking about code in audio format is kind of not the easiest thing to do.
28:46 But if we keep it simple enough, I think we can give people an idea.
28:49 So it looks like you have some pretty interesting ideas around creating routes.
28:54 And it looks like you are sort of embracing this HTTP verb type of world as well.
29:02 Right?
29:02 So if I'm going to create some routes, I would go and create a, I would import a get.
29:07 Is that a class that I'm creating?
29:09 Or is that a function I'm calling?
29:10 No, that's a class.
29:11 A class.
29:12 So I would create like a list of classes and I would say get like a forward slash.
29:17 And then I would say welcome controller at show.
29:21 So the welcome controller is a class that is handling this request and show is a method
29:27 within it.
29:27 Or maybe welcome controller is just a module.
29:29 I don't know.
29:30 You could name it and so on.
29:31 No, that's correct.
29:31 Yep.
29:32 Yeah.
29:32 So I can create these gets and posts and it seems like a really nice way to build up
29:36 from sort of naturally understanding HTTP verbs and the way the internet and websites actually
29:42 work.
29:42 Something early on in Mason, and really in my code in general, even when like I create my
29:46 method names, these method names are like, it seems like a whole sentence long.
29:50 Because I like when I read my code, I like to read it in English.
29:53 Like I like to read it from left to right as if I'm thinking it and I want to show it to
29:58 like a little kid almost and like have him understand it basically.
30:03 Like it's just reading.
30:04 It's like reading a book almost.
30:06 So originally it was actually normally it's get.
30:09 And then inside the get, you have the URL that you want to send to, like you said, and then
30:13 the controller method.
30:14 But previously it was actually get.route.
30:17 So when I read it, it was, I want to get route.
30:22 And then I pass in the URL and stuff like that.
30:24 And you can still do that actually.
30:25 But we basically shortened it down to, yeah, just a list of get routes, post routes, option
30:31 routes, put routes, delete routes, stuff like that.
30:33 That's super cool.
30:33 How do you pass variables in through the URL here?
30:37 So I don't see any examples of that.
30:39 Like if I do this show, I probably want to show like, you know, slash some blog post with
30:47 the URL or something like that.
30:48 Yep.
30:48 So in your URL, it would be, say you want to do like a slash blog post slash maybe one
30:53 or a two, or you want that to be a dynamic.
30:55 Sure.
30:56 That'd be, that'd be fine.
30:57 It would be slash dashboard.
30:58 And then you would do another slash and then an at symbol.
31:01 And then the name of the variable that you want to retrieve later.
31:05 So maybe it's blog ID.
31:06 So it would be blog underscore ID.
31:08 And then you'd put that there and then that's, that'll be the dynamic part.
31:12 Or you can add sort of what I call regex compilers, which is basically, maybe I only want that
31:18 to be an int.
31:18 So it would be at blog ID colon int int.
31:23 So it'll only match integers or I could do strings or I could do some kind of super complex
31:29 one where I do like a website.
31:31 And then I could actually pass a website in with slashes as well.
31:34 And it'll actually match that as well.
31:36 Yeah.
31:36 You can do a lot of complex things with it.
31:38 I love that, that simple way of doing constraints for types and stuff.
31:41 Yeah.
31:42 You create really nice things like on our website, you can say talkpython.fm/ two, three,
31:47 three, I think would be this episode, right?
31:50 If I got the number right.
31:51 And that would actually only match for integers and then it'll go look that up and take you
31:55 to the real location.
31:56 So it's like a really nice way to create short sort of CLI almost feels here.
32:02 Web app.
32:02 Yeah, exactly.
32:03 I try to write everything first.
32:05 So I actually, when I created the routing engine, I actually wrote down, I don't know,
32:07 piece of paper, every single variation I could possibly write for a routing engine.
32:12 And then I basically crossed out all the crappy ones that I thought looked ugly.
32:16 And I only went with the one that looked nice.
32:18 And then I worked backwards to the actual implementation.
32:21 Like I had no idea how I was going to create this thing.
32:24 But then I worked backwards to actually creating the class and creating all that stuff.
32:27 That's how I actually write almost everything.
32:29 I want to use it this way.
32:30 I don't really know how.
32:32 Right.
32:32 We're going to make this happen somehow.
32:33 That's cool.
32:34 The other thing that you have here is you have classes.
32:37 And the classes like capture the request object.
32:40 And then you have the methods that run for the view.
32:43 And I actually really like this pattern.
32:44 I use this pattern in some of my websites as well, even though I have to kind of fight
32:49 against the grain a tad bit to make it happen.
32:51 I really like it.
32:52 And you have the word controller.
32:54 Do you consider Masonite a model view controller framework, a model view template?
32:59 I don't really even understand why there's a distinction between those things.
33:03 But it seems to be in the Python space there is.
33:05 So I do consider Masonite an MVC.
33:08 But it's not.
33:09 I try to make it not constrained to just control logic.
33:12 So I try to sort of assist the developer who's working with Masonite to sort of take a lot
33:18 of that logic and add, you know, extract it into like maybe like a mail class, which is
33:24 ejected into the controller and stuff like that.
33:26 So it's not a strict MVC, but it does use basically the wording to sort of help you
33:31 structure your code.
33:31 I like that pattern.
33:32 It's cool.
33:32 You talked about the injection stuff and I do want to cover that.
33:35 That's fairly unique in the Python space.
33:38 But before we get there, so the way that I would, if I was a Masonite developer and I
33:45 was starting a new web app based on it, I would create a virtual environment and I would pip
33:49 install some stuff, Masonite and whatnot, right?
33:51 And then I would start issuing command line or CLI behavior commands to Masonite to help scaffold
34:00 build up and start building my app.
34:01 So you could say you have this utility called craft.
34:06 Tell us about craft and some of the commands and what's the story on that?
34:09 I think it's incredible, actually.
34:10 I think that's actually what makes or breaks the framework.
34:12 So craft commands.
34:13 So think of like Django, because a lot of your listeners are probably familiar with Django.
34:17 So in Django, you might have a class based view and you might have that, you know, return a couple of templates, maybe some kind of context and stuff like that.
34:26 And then you want to create another one.
34:28 We usually end up doing is you either maybe create a new file and then instead of creating the whole class, you probably sort of copy and paste that old one that you already created into the new one.
34:37 Yeah, certainly a copy and a paste is a solid start.
34:39 Yeah, exactly.
34:40 So what craft does is it gets rid of all of that boilerplate.
34:45 So in Masonite, if you want to create a new controller with, you know, a couple of imports and you want to import the request class, the view class, you want to create a method.
34:54 What you do is you do craft controller and the controller name.
34:57 So maybe craft controller blog.
34:59 And it'll actually create you a blog controller.
35:02 It imports the request class, it imports the view class.
35:05 It makes a default show method and it type hints the view class and it type hints the request class.
35:10 Like it creates all that boilerplate for you.
35:11 And it does the same thing.
35:13 Like if I want to create a middleware, craft controller middleware, it creates me a class, imports everything I need.
35:17 What's an example of middleware?
35:19 Like why would we, why would I create one of these things?
35:21 What does it do?
35:21 A middleware?
35:22 Yeah.
35:22 In the Masonite terminology.
35:23 So a middleware is basically a piece of functionality or code that runs in between the request class or in between the incoming request and your controller method.
35:34 So for example, maybe you want to have some kind of authentication.
35:37 So if the user is not logged in, I don't even want to hit the controller.
35:41 I just want to redirect to the login page.
35:43 So I might create that.
35:44 Or maybe I want to create some kind of after middleware.
35:47 Like I want to take the HTML response and maybe minify it and then return it.
35:53 Something like that.
35:54 So you create these middleware that run in between your controller, in between the incoming request in the controller, and then in between the controller and the final response.
36:02 And you sort of inject these things.
36:04 That's actually really, really simple to work with, with Masonite.
36:07 But yeah, you just use these craft commands.
36:09 You can create, you know, migrations.
36:10 You can create jobs.
36:11 You can create listeners and tasks.
36:15 And you create all these things, all this boilerplate.
36:17 So the objective really is that I don't want to focus on writing things that aren't crucial to my application.
36:24 So if I have a thought that says, all right, I need to start sending out an email.
36:28 Let me make a new controller or something like that.
36:30 I just create the controller and I go to the controller and I'm still focused on sending out my email.
36:35 I drop down to the method and I start coding, sending out my email.
36:38 Like I never break my train of thought with what I actually need to do to get my business logic set up.
36:43 That's cool.
36:43 And it seems like it follows some really nice conventions.
36:46 So for example, you said maybe we want to create a blog controller as a show method.
36:50 So you would say craft controller blog, but it actually creates the controller, a controller class called blog controller, not just blog.
36:59 It puts it in slash app slash HTTP slash controllers, and it initializes it all correctly, right?
37:06 It has an initializer, which has a type, you know, request object that has a type annotation of requests and things like that.
37:12 Yep, exactly.
37:13 This portion of Talk Python to Me is brought to you by Datadog.
37:18 Datadog is a monitoring and analytics platform that unifies metrics, logs, and distributed traces from your Python applications.
37:25 Datadog's tracing client auto instruments popular frameworks and libraries such as Django, Flask, PostgreSQL, and AsyncIO,
37:32 so you can quickly get deep visibility into your applications.
37:35 Trace requests across service boundaries, correlate traces with logs and metrics,
37:40 and plot your application architecture with the service map.
37:43 Get started today.
37:44 Sign up for a free trial at talkpython.fm/datadog, and Datadog will send you a free t-shirt.
37:52 Yeah, one of my pet peeves around some of these projects is they give you zero guidance about any organization.
38:00 And maybe even taking it farther, like sometimes they even accentuate their ability to not have any organization or any structure.
38:08 Like, look, you don't even need that.
38:09 Look, you don't even need one file.
38:11 Just like put it in this file, and you're good.
38:13 This is where it goes.
38:14 It all just goes in here.
38:15 And like, no, it doesn't all go in there.
38:17 You're going to have, you know, so many view files or controller files.
38:23 You have, you know, 50 templates.
38:24 Like, you need organization.
38:26 And this, like, selling the lack of it as simplification seems to me like pushing at least beginners down, like, the wrong path.
38:35 Right?
38:35 So I like that your craft commands take, like, a natural structure and just say, this is the convention we use, and we're just putting it here.
38:43 Right, exactly.
38:43 And like you said, it creates that file, and then it puts that controller in it.
38:46 But it's only that one class.
38:48 And that is opinionated.
38:50 That is the way I like to work, mainly because in my VS Code editor, if I need to go to my authentication middleware.
38:59 In order to do that, you know, I hit the command P thing, and I go to authentication middleware, and I click enter, and I go to that specific class, that specific method.
39:07 I'm not, like, going into, like, some kind of middleware.py file, scrolling down a couple hundred lines so I could find that middleware class or anything like that.
39:14 Yeah, yeah.
39:15 So it's just the way I code.
39:16 I just hop around files, you know, all day until my app is done.
39:20 Man, I'm with you.
39:21 I love it.
39:22 That's the way to do it.
39:23 Having, like, these huge long files with everything crammed in there, it just means it's so hard to find.
39:28 I think the choice of editor somewhat influences the granularity of, that you're comfortable with here.
39:34 But I'm kind of, it sounds like you and I would have a similar style.
39:38 Yeah, exactly.
39:39 Like, I feel like it's almost like when you give a kid, like, a guitar, and he grows up to be a rock star.
39:44 Like, whatever sound that guitar made is probably what kind of rock he's going to play, you know?
39:49 So, like, it's almost like that.
39:51 Like, whatever editor you use probably dictates what kind of applications you're going to build.
39:54 Right, right.
39:55 Something like VS Code is very natural at handling many directories, many files, and, like, seeking between them really quickly.
40:00 Right.
40:01 The other thing that you talked about when you talked about that flow there was injecting things.
40:07 Now, I definitely think dependency injection and the open-close principle and all those things have some really interesting places in the Python world.
40:16 But I also don't see them used very often.
40:20 So, this is kind of a unique aspect of it, of what you're doing.
40:24 But so, for example, like, if I've got my show method from my blog, and maybe in order to get my blog, I have to go to my database.
40:31 And I want to work with MongoDB.
40:33 So, somewhere previously at the app startup, I said, when I asked for a database, give me the MongoDB implementation of my repository thing or my database service or whatever I called it.
40:43 Right.
40:43 So, I can go to that view method and say, you know, like, show self, comma, view, colon, view, comma, DB, colon, repository or database class or database service.
40:55 And then I'll just automatically just start getting my database instance passed into me by Masonite.
41:00 Yep.
41:01 That's exactly right.
41:01 Or what you can really do, where Masonite really shines is being able to basically swap out what I call interfaces or contracts.
41:11 So, like one of the other principles, interface segregation principle, right, where you want to really code to an interface and not to a concretion.
41:18 Yeah, we can hit all the solid principles.
41:19 Right.
41:20 Yep.
41:20 So, what you can do is you can, Python doesn't have like an implements keyword or anything.
41:24 But if you have like a base class, say you have a, what would be a good example, like a payment base class, you can type in that.
41:33 Yeah, payment service, whatever.
41:34 Sure.
41:34 Right.
41:34 Yeah, payment service.
41:35 So, you type in payment service.
41:37 And even though you have no classes called payment service, it'll find an instance of payment service and return that as well.
41:44 Right.
41:45 Maybe you wrote a class called Stripe payment service and it drives from payment service and it actually talks to the Stripe API or something like that.
41:50 And it'll just find that and inject it.
41:52 Yeah, exactly.
41:52 And what's even better, I think, is that, and this might sound confusing to people who don't understand IOC, but what also it does is when it resolves that payment service class, it'll resolve whatever is in the initializer of the payment service class as well.
42:09 So, basically ties every single class that that payment service relies on, ties it all together, initializes everything, and then returns everything as an object already set.
42:22 So, you don't know longer do you have to sort of import a class, maybe get some config variables, maybe pass it in, construct that thing, and then pass that thing into something else that needs it.
42:33 Everything just ties together sort of seamlessly.
42:36 And then you can also swap out functionality as well.
42:39 That's really what powers an IOC container.
42:41 And the funny thing with Python and IOC is that even if you Google, why doesn't Python have an IOC implementation or something like that?
42:48 I forget the Google question.
42:51 But you go there and it says, you don't need an IOC container.
42:54 I think it's like because Python is like duct typed or something.
42:58 Like it was, it almost like made no sense.
42:59 Like, like that's not really the reason for an IOC or anything like that, or even for like interfaces or anything.
43:05 So, it was very strange.
43:07 But I think IOC is more of a architectural decision that just, you have to build applications.
43:14 Like we're building this large scale ERP system at work.
43:17 There's probably going to be a two-year long project, probably thousands and thousands of classes.
43:21 And like if you didn't have an IOC, like how do you manage all those dependencies between the classes?
43:27 Like it's crazy.
43:27 It gets tricky.
43:28 That's for sure.
43:29 I would say for sure that Python does not, as a general rule, the people in the community and the libraries don't generally embrace IOC.
43:39 But yeah, I see it being really useful here.
43:42 So, that makes a lot of sense.
43:43 You know, like your payment service, your Stripe one also takes a logging framework or logging service.
43:49 And it takes a database service or something like that, right?
43:51 Like you just register them all and it all just, you just go to your view and say it takes a payment service
43:56 and you get the Stripe service all set up.
43:57 As long as they're all in the container, they all can communicate with each other.
44:01 That's cool.
44:01 And probably use that for testing as well, right?
44:03 Like you could swap out the database with like a mock database and the logging with like a null logger
44:10 that actually doesn't do anything or something like that.
44:12 Like prints.
44:13 Even Masonite itself is strictly based around this container.
44:17 So, if you want to change out the request class, for example, and you want to make it a different request class, you could just do that.
44:22 And everything else will sort of follow.
44:24 As long as you follow the contract of the class, you could just sort of swap every single piece of functionality out of Masonite and inject your own.
44:31 That's cool.
44:31 One of the challenges I've had when working with IOC is I'll be somewhere in the middle of the system
44:37 and I'll have all these dependencies that were put together by the IOC container.
44:41 And I'll be like, all right, I have no idea what actual database I have or what logging thing I have
44:47 or where it came from or any of that.
44:49 And I do see that as one of the drawbacks of IOC is it's kind of hard to see where it all gets started.
44:54 Yeah, I mean, I guess if you sort of lose yourself, then I guess you're sort of lost, I guess.
44:59 But as long as you have like a good file structure and you have like maybe good documentation on your project
45:05 and stuff like that, you can sort of, there are caveats, I'll admit.
45:09 But it's definitely a pretty good architecture.
45:12 Yeah.
45:12 One of the things I like about your craft commands is, you know, I'm a fan of things like cookie cutter.
45:17 And I think cookie cutter is a super way to get started, right?
45:20 Like the right way is not create an empty .py file and start typing it.
45:25 I don't think like, you know, I already talked about the structure, but there's also tons of static files.
45:30 There's just, there's a lot of stuff that would be nice if you could start farther from let's enter character one and get going, right?
45:37 And I think cookie cutter is a nice way to do that, right?
45:39 You could say, okay, I'm going to use, I'm going to create a flash project that's already using SQLAlchemy.
45:44 So it's got the requirements set up.
45:45 It's already got a database structure.
45:47 It's already got a connection string for SQLite database for getting started and, you know, that kind of stuff, right?
45:52 What falls apart with a lot of those systems is you get to run them once and that's it.
46:00 Right.
46:01 Right.
46:01 Like I have a super cool.
46:02 I was just about to say that.
46:03 Yeah.
46:03 I have a cool cookie cutter template that will actually generate the final code from this course I have called Python for Entrepreneurs.
46:09 And it's like super involved.
46:11 There's so much stuff going on and you can type in the name of your project and whatever and run the cookie cutter.
46:16 And it will just, boom, out drops this really well formed project that looks just like the final project of that course, but with your data in it, right?
46:24 The problem is that's great for getting my first controller or whatever is in there.
46:30 But if I want the second one, cookie cutter is not going to help me.
46:32 That's where copy and paste comes in, right?
46:34 It seems like with your craft commands, you can start out building pieces of your app and continue kind of adding to the app with that CLI.
46:43 What do you think?
46:44 Yeah, exactly.
46:44 I mean, every, when you're trying to reach for like a copy and paste, like you're wasting so much time.
46:51 And not only are you wasting time, but you're, now that you finally copied and pasted it, now you have to be like, all right, wait, what was I trying to do again?
46:57 Oh yeah, right.
46:58 Okay.
46:58 Yeah.
46:58 Sending email.
46:58 And then you sort of go back into sending email and it takes your mind off.
47:01 And it's just, it's just a massive like time suck.
47:05 And most people that use Masonite, I don't know about most people, but a lot of people that are in the Slack channel, they say, man, like I built this thing in Masonite in three days.
47:18 It would have taken me three weeks in Django.
47:19 So I actually get that a lot.
47:21 It sort of gets to the point where I almost expect it when someone comes from Django or something.
47:25 I just, I basically just wait for it.
47:27 And I think a lot of that is because all of that boilerplate code is done for you.
47:32 Like we already created controllers and if you need to create a job, you create a job, you add your logic and then you just add it to a queue.
47:38 Like it's takes five seconds.
47:40 Yeah.
47:41 It's huge.
47:41 Yeah.
47:42 That's cool.
47:42 So let's talk about some of the other things that you can make with these craft commands.
47:45 You just talked about jobs.
47:47 That sounds like an asynchronous thing.
47:48 Maybe kicking out to some kind of background worker process.
47:52 You talked about email before we've got views and templates and create templates.
47:58 So you've adopted the Jinja 2 template system.
48:01 Is that right?
48:02 Yes.
48:02 Yeah.
48:02 Do you have any other support like chameleon?
48:05 Hint, hint, chameleon?
48:06 I don't currently.
48:07 I know that one guy came to me and he said he wanted to write in pug.
48:11 I don't know if you ever heard of pug before.
48:13 No, I only know it as a dog.
48:14 Yeah, I think it's called, oh no, maybe I just kept on calling it pug, but maybe a pub or something.
48:18 But anyway, it's basically, it looks like a markdown type style.
48:22 And he wanted to write in that and it had a Jinja 2 extension.
48:26 And then from there, I basically added extension support for the views and stuff.
48:31 So you could write, you could basically write in any Jinja 2 extension language.
48:36 So it basically just compiles down into Jinja, I guess, and then gets rendered.
48:39 But as for swapping out that functionality for chameleon, it's possible.
48:44 But there's no documented way of doing it.
48:47 Sure.
48:47 But it definitely could be.
48:48 You could open an issue.
48:49 VRs are accepted, huh?
48:50 Yeah, of course.
48:51 Nice.
48:51 Background work.
48:52 Let's touch on that real quick.
48:54 That's not something every framework decides to take on for itself.
48:57 Yeah, definitely.
48:58 So a lot of the features of Masonite came by me needing it.
49:03 So basically, I'll basically add it to my application and then I'll try to extract it into a framework feature.
49:11 And one of the things I needed was sending an email and I wanted to send that asynchronously.
49:16 So I created the concept of queues and jobs.
49:19 So a job is basically just a normal, simple class that extends queueable.
49:26 And you can add your logic of sending an email.
49:29 Maybe it'll accept a parameter of an email.
49:33 And then you could take that job and then you could pass it into any queue driver that you want.
49:37 So if we want to run it asynchronously, we pass it in the asynchronous queue driver.
49:41 If we want to...
49:43 And then when I deployed to Heroku, I didn't want to run things asynchronously.
49:46 I wanted to run things through some kind of RabbitMQ server.
49:50 So I coded that driver.
49:52 And the cool thing is that in order to create a new driver, it's just a simple class that needs four methods.
49:59 And then you take that and you register it to the container and then you have that functionality.
50:06 So I created the AMQP driver, which is the protocol for RabbitMQ.
50:10 It took like maybe a night.
50:12 And then actually last night, I actually created a database driver as well.
50:16 So now you could take that same job, that email job, adds it to a database table.
50:20 You have a worker that you run as like a separate process, maybe on like a supervisor process, that will basically pull that database and then run the job.
50:30 And the cool thing about that is that you can actually delay queue jobs as well.
50:34 So you can delay it by 10 minutes.
50:36 Maybe after the user signs up, we'll send a welcome email in 10 minutes.
50:39 And then you add that and it'll basically, you know, wait 10 minutes and then it'll send the email out.
50:45 And that's the way I like to sort of counter the ASGII competition.
50:50 So, you know, going to the next page might take one second or a half a second.
50:55 But sending that email might take two seconds.
50:57 But if you send it to a queue job, you know, it only takes that half a second.
51:01 And then it'll just run in the background or in your queue server or something like that.
51:04 So I thought that was a really cool feature that I added in Masonite pretty early.
51:07 And I use it all the time.
51:09 That's cool.
51:09 Certainly, asynchronous queues and background work like that do solve a lot of the primary reasons that you need.
51:16 Some sort of direct async behavior.
51:19 I do think the database stuff, if you could have it as async, once you, and we talked about it not necessarily being a great place to start.
51:25 But once you get advanced, like it would be kind of cool.
51:28 But, you know, my sites don't have it either, right?
51:31 Like both my database access layer can't support it, nor does the framework support it.
51:36 And, you know, the thing is super, super fast.
51:39 Like, honestly, I don't understand why most websites that I work with are so crappy and slow.
51:43 Because I didn't work that hard to get mine to go fast.
51:47 Right.
51:48 It doesn't do that hard.
51:49 Anyway.
51:50 But I bet you if it was simple enough, like if you just had to create a job and then add it to the queue, which is already created for you, I bet you probably would do it.
51:57 Like creating some kind of queue background work, like a lot of Django projects probably don't.
52:01 I did end up creating this type of thing because certain types of operations might send thousands of emails on the click of a button.
52:08 And you can't wait for that to happen.
52:10 Right.
52:10 It's insane.
52:11 Right.
52:12 For example, if I like I have office hours for my courses that people can come, they take the course, they get the office hours for free.
52:17 A bunch of people signed up for those.
52:19 Right.
52:19 If I enter a new one, I can't just wait to send all those emails because it'll time out.
52:24 But other things like putting people on mailing lists.
52:27 Right.
52:27 They signed up for the site.
52:28 They said, OK, you can put me on your mailing list, but they don't need to wait for you to put them on the mail.
52:33 There's no outcome from that that they need anything from.
52:36 Right.
52:37 Exactly.
52:37 Right.
52:37 So that's a perfect example of some kind of background work.
52:40 And adding background work to Masonite literally takes about maybe 10 seconds of code once you get comfortable with it.
52:46 I tried to make every single thing as easy, as quick as possible, just to make it like this rapid application development tool that people reach for.
52:54 Yeah.
52:55 Cool.
52:55 One of the things that Django comes with is Django ORM.
52:58 And that's been really popular.
53:00 One of the things that Flask and Pyramid have eschewed, they've decided we're staying far away from, is defining a database access layer at all.
53:08 And it's like up to you.
53:10 Typically, the answer is go get Sequel Alchemy or something like Mongo Engine if you're going to talk to MongoDB or something else.
53:16 Right.
53:16 But it's up to you.
53:17 There's no guidance.
53:18 It sounds to me like with Masonite, you decided to bring along an ORM, an active record style one, which matches really well with Django ORM.
53:28 Right.
53:28 And its style, not so much with Sequel Alchemy, which is a unit of work type of one.
53:32 Why not just lean on Sequel Alchemy?
53:34 So again, it was what I wanted it to look like.
53:38 So I wanted the ORM to look like something I was comfortable with using.
53:43 And again, Masonite is sort of like a framework for me, right?
53:46 Like I knew I was going to use it.
53:47 I didn't want to build it for somebody else.
53:49 I used it.
53:49 So I built it in a way that I would like it.
53:51 And I came from Laravel, like I said.
53:54 And Laravel has something called an Eloquent ORM, which is another active record style.
53:58 And then I found Orator, which is pretty feature complete.
54:02 There's a couple of things that can be added to it.
54:04 And it was basically influenced by Eloquent.
54:06 So it was almost like perfect to bring in because it's super sleek.
54:09 You don't have to like do anything crazy.
54:12 Like getting all records is like the model name dot all.
54:15 That's it.
54:16 That's all you have to do.
54:17 Getting like where is like dot where.
54:19 And then, you know, you can maybe change some where's together.
54:22 To get the first record is, you know, dot first.
54:25 Like it's very, very sleek.
54:26 And I thought that was the same as Masonite's philosophy of doing something as quick as possible
54:31 to get what I need done.
54:33 And it also had the, what I wanted to do as well was the migrations.
54:38 So the migrations are really important.
54:39 So in Django, you have like these magic migrations that are basically, I don't even know how,
54:44 but they're somehow like taken from like model changes.
54:46 And it basically generates these things that run that you should like never edit because
54:51 that's probably bad.
54:53 And it's probably going to screw up something down the road.
54:55 Something will get out of sync.
54:56 Yeah.
54:56 In Laravel and in Orator, you want to do the migrations.
55:00 The migrations are much more explicit.
55:01 So what you're doing is you generate as this new migration and you, you know, add a couple
55:08 of table columns and there's like an up method and a down method.
55:12 And the down method just reverses what you did in the up method, which is usually defaulted
55:17 to like a sensible default, like dropping the table, which is usually what you need to do.
55:21 And that's what I wanted.
55:23 And then Orator also had that too.
55:24 So that saved like a whole lot of time.
55:27 So it just made sense to go with Orator and I used it and I integrated the migrations
55:31 process with it.
55:32 And I just really, really like Orator.
55:34 I think it's a really great ORM.
55:36 So then I just incorporated it and everybody else seems to like it.
55:40 So I guess something's good.
55:41 It looks pretty interesting.
55:42 I can certainly see how it goes with your philosophy of, you know, I wanted to look like this.
55:49 How do I make that happen?
55:50 Right.
55:50 It's a little bit, a little bit SQLAlchemy-esque in some ways, but not in others, right?
55:56 Like the way you define the model and the table names and stuff.
55:59 That's pretty cool.
55:59 One of the things I like about some of your philosophies or styles here is you could go
56:05 and say, get a user.
56:06 You could say user.find and pass a user ID and that'll give you back the user or maybe none,
56:11 right?
56:11 Yeah, it's nice and quick.
56:12 Or you could say user.find or fail and give the user ID and you either get one back or I'm
56:17 guessing you get an exception if that didn't work, right?
56:19 Yep.
56:19 Yeah.
56:20 So what I'm using, say SQLAlchemy, SQLAlchemy has a first and it has a one.
56:24 Which one of those?
56:25 He's going to throw an exception when it doesn't find it.
56:30 You know, I mean, probably one, but is one just the way I get the first one or is first
56:35 the way I get the first one?
56:36 You know what I mean?
56:37 There's just, it's just a little less.
56:39 It's very fluent.
56:40 Order is very fluent.
56:41 Obviously, once you get used to it, right?
56:43 First just gives you the first or none and so on.
56:45 But this name is super clear and I really like the style of find or fail.
56:49 Because like I said, like when I write my code, I didn't write order.
56:53 I'll admit it was already written for me, you know, written, almost written for me.
56:56 I felt like, but it reads like English and that's how I like to do it as well.
57:01 Yeah.
57:01 You also have an interesting way of setting up relationships with decorators and properties.
57:05 How does that work?
57:07 Oh yeah.
57:07 So I think this is, this is actually really cool.
57:10 So in order, if you have a user and in articles, a user has many articles and then in
57:19 article belongs to a user.
57:20 So what you can do is when you do like maybe user equals user.find1 and you get your user,
57:26 you could do user.articles.
57:28 And this is called a dynamic property.
57:30 Even though you created a method called articles and you decorated it with a has many relationship,
57:36 you fetch it by using this dynamic property.
57:39 Right.
57:39 It basically is similar to the app property syntax.
57:41 And it actually returns a collection of all the, all the articles.
57:46 Or what you could do is if maybe a user has one profile, which has one address, which has
57:54 one something else.
57:55 You could actually, when you fetch your user, you could do user.address.
58:00 Or user.profile.address.
58:02 And you could just keep on chaining these relationships.
58:04 And then eventually you get down to what you need.
58:07 Or what you do is you do user with profile address, something else.
58:14 And then you actually, what do you call eager load?
58:17 And that gets rid of the N plus one problem.
58:19 That's a big problem with ORMs.
58:21 And I think some people don't know what that is, what the N plus one problem is.
58:26 You want to take a shot at describing that for the audience?
58:29 Because personally, I am a huge fan of ORMs or in the manga world, ODMs for documents.
58:35 But these classes that map back to your data, I think it's a huge benefit.
58:38 But this is one of the problems that you need to be aware of.
58:41 And it can be one of the performance problems.
58:43 So maybe tell people about this N plus one problem in ORMs.
58:46 So let's say you get a list of 50 users.
58:49 And you want to loop through all those 50 users.
58:52 And you want to get the profile of each user, right?
58:56 Because that first one where you get the list, that's probably a single query, right?
58:59 Users.find state equals California or something like that, right?
59:03 And you get 50 results.
59:04 So there's your one.
59:05 There's your one in the N plus one.
59:07 Right.
59:07 I'll explain the problem first and then I'll explain the solution.
59:10 So the problem is if I loop through the user and I did user.profile, it's going to create
59:15 or it's going to fire a query for each time I use user.profile.
59:21 And it's going to fire a query.
59:22 So that's where the N comes in because you're looping through all 50.
59:24 Now you have 50 plus one queries.
59:26 And now you have 51 queries.
59:28 Probably slow to do that, right?
59:30 It's probably not good to do 51 queries when you could do one.
59:33 Right.
59:33 So what you do is you do user with profile find one and that eager loads, which called.
59:40 So that's two queries.
59:42 And what that does is it gets the user ID and then it does a where in on the other table.
59:48 And it basically saves that information basically in memory on that object.
59:53 So now whenever I do user.address, I already loaded that information.
59:58 So I just fetch it from some kind of dictionary or something or some kind of collection saved
01:00:02 on that user object.
01:00:03 So now it's only ever two queries that I'm doing it.
01:00:06 So it gets rid of that N plus one problem.
01:00:08 Yeah, that's perfect.
01:00:09 And it's super easy to tell if you just turn on logging, right?
01:00:13 You could tell you have an N plus one problem because you're like, whoa, why is, if you turn
01:00:17 on logging to like every time you do a query, you show me what's happening going to the
01:00:21 database, you're like, I hit this one page and there's like 20 queries.
01:00:25 Why this should be one or two?
01:00:27 What is happening, right?
01:00:28 That's probably an N plus one problem.
01:00:30 Yeah, I've gotten about 750 queries down to like 13 or something like that using like the
01:00:36 with statements.
01:00:37 Yeah, it's pretty crazy.
01:00:38 That's pretty sweet.
01:00:39 All right, Joe, I think we're getting long on time here, but this has been really fun.
01:00:44 It's clearly an opinionated framework, but I also like that you can use these craft
01:00:50 commands to kind of bring in bits and pieces as you want to or not.
01:00:53 That's cool.
01:00:54 Yeah, thank you.
01:00:55 Yeah, you bet.
01:00:55 All right.
01:00:56 So let me just ask you one really quick question, I guess, around the project itself before we
01:01:02 move off of it.
01:01:02 So are you looking for contributors?
01:01:05 People do like take it for a run?
01:01:08 People to add issues, add PRs?
01:01:11 Where's it at?
01:01:12 Yeah, I mean, we're looking for contributors all the time.
01:01:15 I mean, you could be a contributor by joining the Slack channel and saying like, hey, you
01:01:19 should have this feature.
01:01:19 And then I'll probably, you know, either code it that night or maybe a couple days later or
01:01:24 that weekend.
01:01:24 That's even contributing.
01:01:26 I mean, you didn't code, but you still contributed towards the development of the framework.
01:01:30 And Masonite's in a really unique position because it sort of is opinionated and it is
01:01:34 a Python framework.
01:01:35 So it has a lot of people coming in from different ecosystems.
01:01:38 Like people feel really comfortable coming from Ruby.
01:01:40 People feel really comfortable coming from Laravel.
01:01:43 People love it coming from Django.
01:01:45 So when they come in, they have all these like really, really unique ideas.
01:01:48 So if you're not even in the Python community, I mean, that's, I think that's even better coming
01:01:53 in because you're coming with fresh ideas that maybe people from the Python community don't
01:01:57 have yet or haven't seen.
01:01:58 So yeah, just joining the Slack channel is huge to come in.
01:02:03 If you know how to code or you go to a Python, that's great too.
01:02:06 Yeah, that's cool.
01:02:07 How old is Masonite?
01:02:08 So Masonite was developed, it started December of 2017.
01:02:12 And then in six months later, we came out with the main release, which was June of 2018.
01:02:19 So it's probably about, what is that?
01:02:22 Probably really only a year and a half old is really when it really started kicking off.
01:02:26 Cool.
01:02:27 The reason I ask is a lot of these other web projects in the Python space are very old,
01:02:31 right?
01:02:32 They, they've been around since 2005 or 2008 or something like that.
01:02:36 And as a contributor, if you want to participate in that, you're walking up to a highly polished,
01:02:41 careful, delicate balance of features and things and so many people depending upon it.
01:02:46 And if you want to make a change, it can be really hard to do minor things, right?
01:02:50 So these newer frameworks, I feel are maybe better opportunities for folks to contribute
01:02:54 because it's somewhat newer, right?
01:02:57 And it's a little more dynamic and flexible and it's not so set in stone.
01:03:02 Yeah, I think that's exactly right.
01:03:03 And even the Masonite code in general is super, super clean.
01:03:06 Almost every single method is, has doc strings that explain and where each variable comes from
01:03:12 and stuff like that.
01:03:13 So it's really, really easy to contribute.
01:03:15 And since it's fairly new, although it has like a crap ton of features and people actually like are really,
01:03:22 really impressed that it's only, you know, a year and a half old and it has dozens and dozens of features.
01:03:26 There's a lot of easy picking still that can be coded up.
01:03:29 So there's even in the issues, I usually put good first issue or I list a difficulty, easy, medium, hard.
01:03:37 I haven't done that actually with the latest issues, but normally I do that.
01:03:41 So if you want to hop in and see what kind of difficulty you're at and then go there.
01:03:45 Yeah, you can decide, oh, actually, this might be more than I want to spend to get started in this.
01:03:49 The other thing that is interesting and I noticed about your project is you're participating in the GitHub sponsor program.
01:03:57 I don't know if that's the right name for it, but it's something to that effect where folks can contribute through GitHub to Masonite, right?
01:04:04 Tell people about that.
01:04:05 So I think with that button that you see, that little sponsor button, it's really, I think it is called the GitHub sponsor button,
01:04:11 but it's really just a list of other links.
01:04:14 It's really just a button and then you could post links to like a Patreon or some kind of like patronage service.
01:04:23 So it's not anything crazy, but if you click on it, it'll show you the link to the Patreon page where you can either sign up to be a contributor.
01:04:29 If you're a company and you want to sponsor, the documentation page gets, I think, around 10,000 page views a month.
01:04:35 So if you want to go there, it's always good to contribute there as well.
01:04:39 Very cool.
01:04:40 All right.
01:04:41 Well, let me ask you the two questions before I let you get out of here.
01:04:44 Now, I think astute listeners will already know the answer to this question, but that's okay.
01:04:49 I think we kind of touched on it already.
01:04:51 But if you're going to write some Python code, what editor do you use?
01:04:54 VS Code.
01:04:54 Yeah.
01:04:55 That's a good one.
01:04:56 That's definitely got a lot of momentum behind it right now.
01:04:58 Yeah.
01:04:58 And then notable PyPI package that maybe you ran across or maybe Masonite depends upon.
01:05:05 You're like, this thing is awesome.
01:05:06 It doesn't get enough attention.
01:05:07 Maybe tell people about something like that.
01:05:09 Like, first of all, just to get out of the way, you can pip install Masonite as a thing, right?
01:05:13 Yeah.
01:05:14 So there's one notable package.
01:05:15 Can I say my own package?
01:05:16 Like a different package that I created?
01:05:18 If you want.
01:05:19 Something that I created as sort of an extension is called Masonite validation.
01:05:23 I needed, again, something extremely simple to create.
01:05:27 So to create validation.
01:05:29 And I didn't really see anything that was simple.
01:05:31 I saw like, I think something's called pillow or marshmallow or something.
01:05:34 It just wasn't what I wanted.
01:05:36 So I created this validation package.
01:05:38 And you could see it in the Masonite organization on GitHub that you could bring in.
01:05:41 And it's not just for Masonite.
01:05:43 It's for any, it's for Django or Slack or anything.
01:05:45 So you could pull it in.
01:05:46 It'll only pull in the validation part of Masonite.
01:05:49 And you can validate dictionaries.
01:05:52 You could validate multidimensional dictionaries.
01:05:54 You validate, you know, JSON responses and stuff.
01:05:56 It's a really, really cool package.
01:05:58 Okay.
01:05:58 That sounds really nice.
01:05:59 All right.
01:06:00 Final call to action.
01:06:00 People are maybe interested in checking out Masonite, interested in getting started.
01:06:04 What would you tell them?
01:06:05 So if you go to the main GitHub page, GitHub slash Masonite framework slash Masonite, you'll
01:06:11 see a link to the Slack channel.
01:06:12 Yeah.
01:06:12 And I'll link to that in the show notes as well.
01:06:14 Yeah.
01:06:14 I'll link that in the show notes.
01:06:15 Yeah.
01:06:15 The Slack channel, which is, I'm really, really responsive.
01:06:20 It's about, it's almost 350 people in that Slack channel so far.
01:06:23 Everybody's really, really friendly.
01:06:25 So you can join there.
01:06:26 And then on Twitter, at Masonite Project, I post news and tips and tricks and stuff like
01:06:34 that on Twitter as well.
01:06:35 So if you want to learn Masonite on Twitter, then you can join there.
01:06:38 All right.
01:06:38 Well, it looks like a cool framework and it has a really unique way of working with it,
01:06:42 I think.
01:06:43 And yeah, congrats on it.
01:06:44 Yeah.
01:06:45 Thank you.
01:06:45 You bet.
01:06:45 Thanks for being on the show.
01:06:46 This has been another episode of Talk Python to Me.
01:06:49 Our guest on this episode was Joseph Mancusio.
01:06:53 And it's been brought to you by Linode and Datadog.
01:06:55 Linode is your go-to hosting for whatever you're building with Python.
01:06:59 Get four months free at talkpython.fm/Linode.
01:07:02 That's L-I-N-O-D-E.
01:07:04 Datadog gives you visibility into the whole system running your code.
01:07:08 Visit talkpython.fm/Datadog and see what you've been missing.
01:07:12 They'll throw in a free t-shirt.
01:07:14 Want to level up your Python?
01:07:16 If you're just getting started, try my Python Jumpstart by Building 10 Apps course.
01:07:21 Or if you're looking for something more advanced, check out our new async course that digs into
01:07:26 all the different types of async programming you can do in Python.
01:07:29 And of course, if you're interested in more than one of these, be sure to check out our
01:07:33 Everything Bundle.
01:07:33 It's like a subscription that never expires.
01:07:35 Be sure to subscribe to the show.
01:07:38 Open your favorite podcatcher and search for Python.
01:07:40 We should be right at the top.
01:07:41 You can also find the iTunes feed at /itunes, the Google Play feed at /play,
01:07:46 and the direct RSS feed at /rss on talkpython.fm.
01:07:50 This is your host, Michael Kennedy.
01:07:52 Thanks so much for listening.
01:07:54 I really appreciate it.
01:07:55 Now get out there and write some Python code.
01:07:57 I'll see you next time.
01:08:17 Thank you.