WEBVTT 00:00.000 --> 00:15.000 Hello everybody, I want to introduce you a tenor voice cam with a topic typed HTML in Python. 00:15.000 --> 00:22.000 Get a warm applause. 00:22.000 --> 00:25.000 Hi everyone, thanks for coming to my talk. 00:25.000 --> 00:28.000 Hi, HTML in my Python. 00:28.000 --> 00:33.000 If you know of us cam, I'm the tech lead for Germany at personal colon and today. 00:33.000 --> 00:39.000 I'll talk to you a little bit about why typing is useful and how to get it in your templates. 00:39.000 --> 00:46.000 So, we'll talk about what are the motivations behind even having static typing or behind using hdpi, 00:46.000 --> 00:51.000 which is the tool that we're going to use for this and we're going to see hdpi in action. 00:51.000 --> 00:57.000 And then I'll show you some patterns for success when using it so that it's most effective and useful for you. 00:57.000 --> 01:02.000 I think it's just as important to tell you what we won't talk about today. 01:02.000 --> 01:07.000 So we won't talk about a general overview of typing in Python, we don't have the time for that. 01:07.000 --> 01:14.000 And we won't have any step-by-step guides, but please feel invited to look at the hdpi documentation, 01:14.000 --> 01:20.000 which has lots of examples, maybe also for the web framework that you're already using. 01:21.000 --> 01:31.000 And on the first-end page for this talk, you'll find also the demo application as a Python script so you can try it out yourself. 01:31.000 --> 01:33.000 Let's get into the motivations. 01:33.000 --> 01:41.000 I mean, static type checks in and on itself, at least for me, are a motivation running my pie and seeing that no issues were found in all of my source files. 01:41.000 --> 01:48.000 It's pretty awesome. And of course, why it doesn't feel awesome, it means lots of errors that would otherwise only be discovered during runtime. 01:48.000 --> 01:54.000 We can already discover them in our CI or even locally when running my pie. 01:54.000 --> 01:59.000 And when using hdpi, all of your HTML is just Python. 01:59.000 --> 02:09.000 So we can use existing tools that your editor provides or your language server provides like refactoring, for example. 02:09.000 --> 02:16.000 In particular, we're going to talk about hdpi, which does not introduce a new templating language. 02:17.000 --> 02:20.000 It's Python, as you'll see on the next slide. 02:20.000 --> 02:24.000 Hdpi itself doesn't care about typing. 02:24.000 --> 02:31.000 I think you should care about typing, but if you don't, but still want to use hdpi, that's fine, that works. 02:31.000 --> 02:37.000 And we use it at personal colon serving over 100,000 users in Sweden. 02:37.000 --> 02:44.000 So it is battle tested, it does work, and we trust it enough to use it in production, and maybe you will as well. 02:45.000 --> 02:52.000 If you scan the QR code, you'll go to the documentation, but you'll get a second chance that's scanning this at the end of the talk. 02:52.000 --> 02:57.000 I promised you it doesn't introduce a new templating language, but how does it work then? 02:57.000 --> 03:02.000 Obviously, HTML you can't just write it in your Python, and it definitely won't be typed if you do that. 03:02.000 --> 03:05.000 So how does it work? 03:06.000 --> 03:09.000 HTML attributes are specified by parentheses. 03:09.000 --> 03:18.000 So just like you would when you call a method, and children are specified using square brackets, so the get item notation. 03:18.000 --> 03:22.000 Here, I have a little example in the Ripple. 03:22.000 --> 03:32.000 So we first import hdpi as h, which is need a little shorthand if you don't want to import each element on its own, which you could also do. 03:33.000 --> 03:36.000 And then we're defining a paragraph here. 03:36.000 --> 03:43.000 As promised, we're using the calling notation to specify HTML attributes in this case the ID. 03:43.000 --> 03:50.000 And we're specifying children using the square brackets in this case it is a string, hello. 03:50.000 --> 04:00.000 And if we print that, so if we ask Python to please turn this interest string, we'll see this comes out as HTML. 04:00.000 --> 04:10.000 HTML offers lots of different shorthands, so what you could also do instead of using the calling notation to specify the ID. 04:10.000 --> 04:20.000 We could also, this shorthand we introduce specifically, you could also use CSS notation to specify all your classes and IDs. 04:20.000 --> 04:25.000 Might be useful for you, might feel natural if you already used to writing CSS. 04:25.000 --> 04:28.000 So here I added a class large as well. 04:29.000 --> 04:46.000 And I turned the explicit definition of ID equals greeting into Hashtag greeting, pound greeting, so now it becomes the ID anyway, because that's how it's as notation works. 04:46.000 --> 04:54.000 All of the standardized HTML tags, which put into hdpi for you already, so that you get auto completions. 04:54.000 --> 05:04.000 So if you import hdpi sht and then you write h dot and then something your editor will suggest all of the existing standardized HTML elements. 05:04.000 --> 05:08.000 But you're not limited to those, so you can import anything. 05:08.000 --> 05:18.000 You can custom hdml tags, which might be relevant if you want to use web components, so web components aren't a problem at all. 05:18.000 --> 05:26.000 Obviously, we don't know about all of the possible HTML tags that your framework or your web components come with. 05:26.000 --> 05:31.000 Well, we employed a little hack, which isn't really even a hack, it's just how Python works. 05:31.000 --> 05:38.000 We defined Dunderget Attra to just give you the element that you ask it for at runtime. 05:38.000 --> 05:45.000 So in this case, we're using a shoulase, large shoulase provides web components. 05:45.000 --> 05:51.000 And hdpi doesn't know about this, but we can use dot notation just as we would expect. 05:51.000 --> 06:03.000 So h dot SL underscore alert, with the attribute open equals true will turn into the SL alert web component as you would expect. 06:03.000 --> 06:12.000 A little thing that you might note here, the equals true is another shorthand, so sometimes your attributes don't have a value. 06:12.000 --> 06:18.000 They just are there and that already means something, so if you set it to true here, this is what will happen. 06:18.000 --> 06:26.000 So as you see, open doesn't have a value itself, it's just there inside the tag. 06:26.000 --> 06:33.000 The implementation, which I simplified a little bit here, also tells you tiny bit about how to go about this. 06:33.000 --> 06:46.000 Underscores in the name that you use in Python are turned into a hyphen to make it a valid HTML tag. 06:46.000 --> 06:50.000 The real implementation does a bit more validation, and if you're other fancy things, you can look at it. 06:50.000 --> 06:53.000 It's not that big, actually, Python itself. 06:53.000 --> 06:57.000 If you go to the documentation, you'll find the source code, of course. 06:57.000 --> 07:02.000 And now we'll move on to show you a few patterns of success. 07:02.000 --> 07:08.000 And it's a short little demo, and we'll start off by showing you the end result. 07:08.000 --> 07:15.000 So what is going to come out of the following examples, so that might help you to follow along a little bit. 07:15.000 --> 07:23.000 And I was thinking of an example where it is very obvious that avoidings takes by using static type checking would be very advisable. 07:23.000 --> 07:31.000 So I don't know, if you have something in consequential like it to do with everything's probably string already anyway. 07:31.000 --> 07:36.000 And if you mess something up, worst case, you need to use a piece of paper. 07:36.000 --> 07:42.000 But when it comes to a medication planner, you don't want to mix up units, for example, like milligrams and grams, 07:42.000 --> 07:44.000 could have pretty big consequences. 07:44.000 --> 07:50.000 And in general, yeah, a medication planner has just a lot more mistakes have a lot more heft. 07:50.000 --> 07:53.000 So we want to use static type checking here to avoid mistakes. 07:53.000 --> 08:01.000 Our medication planner will feature the name of the medication, the active ingredient, the amount, and where the we've taken it. 08:01.000 --> 08:07.000 So let's start out with the data, the domain of our application. 08:07.000 --> 08:16.000 We'll start at the bottom, so we have medication objects, which of course have a name, and also an active ingredient. 08:17.000 --> 08:22.000 And each active ingredient has an amount as specified in decimals. 08:22.000 --> 08:29.000 And the unit, because we don't want to mix this up, you don't want to take a few grams of some medication that you're supposed to take a few milligrams of. 08:29.000 --> 08:37.000 So really baking that in with static type checking, at least gives me a lot of peace of mind. 08:37.000 --> 08:42.000 And now we're going to write our first component, and how do we do that? 08:42.000 --> 08:44.000 We write a Python method. 08:44.000 --> 08:50.000 So a component, in this case, the medication plan, is given a list of medications. 08:50.000 --> 08:59.000 And nothing about this method is special, except for the fact what it returns, in this case, an HTTP element. 08:59.000 --> 09:07.000 And that in itself isn't even that special, but yeah, the lack of specialists is maybe something to point out here. 09:07.000 --> 09:11.000 We're using the square brackets notation to define children. 09:11.000 --> 09:18.000 So our table has a table adding, which has a name, active ingredient, amount, and taken. 09:18.000 --> 09:26.000 And we're using the call syntax here to specify the scope, so that this table becomes a little bit more accessible. 09:26.000 --> 09:29.000 And we can use native language features. 09:29.000 --> 09:37.000 So at the very bottom, you see that the table body, which, as you saw in the example, has multiple rows, 09:37.000 --> 09:48.000 we're using a Python generator expression to turn our medication list into medication table rows. 09:48.000 --> 09:55.000 And again, the lack of specialists is difficult to point it out, but we, yeah, we put the generator expression there. 09:55.000 --> 09:59.000 And what you would expect to happen will happen. 09:59.000 --> 10:04.000 And it is going to be resolved at the end into the list of table rows. 10:04.000 --> 10:07.000 What does medication to our look like? 10:07.000 --> 10:11.000 Again, it's a Python method. 10:11.000 --> 10:15.000 In this case, it has passed a medication, as you saw on the previous slide. 10:15.000 --> 10:24.000 And here, we are specifying that each table row should output the name, the name of the active ingredient and the amount. 10:24.000 --> 10:33.000 And what you'll note here is when you have nested objects like this, you will really appreciate that all of your data is still its original data. 10:33.000 --> 10:38.000 So when I write medication.a, it will suggest active ingredient. 10:38.000 --> 10:47.000 When I write a dot, it will already suggest name when I'm using the autocompletions of my editor because it knows about the structure of the data. 10:47.000 --> 10:49.000 You didn't throw away the typing yet. 10:49.000 --> 11:01.000 And of course, this again allows my Python check that you're not trying to access some attributes that are accessed or trying to convert something into a string that you can't. 11:01.000 --> 11:07.000 So you'll also get the benefits of the correctness assurance. 11:07.000 --> 11:18.000 And of course, we'll have a base template as well to throw some title into our HTML and the CSS that makes it look a little bit prettier. 11:19.000 --> 11:24.000 What I want to point out here is I didn't write the body of this method. 11:24.000 --> 11:28.000 And again, the base template is also just a method, the Python method. 11:28.000 --> 11:30.000 I didn't write it myself. 11:30.000 --> 11:37.000 I copied that from the CSS library I was using, which had a little starter template, which was an HTML. 11:37.000 --> 11:44.000 And I used HTML to HTTP, which comes with HTTP if you install it. 11:44.000 --> 11:51.000 I piped the HTML in and it prints the HTTP Python to use standard out. 11:51.000 --> 11:53.000 I just copied that through it in here. 11:53.000 --> 11:57.000 And then what I did was add the main content section. 11:57.000 --> 12:05.000 So your base template in real life probably has a few more things that you would pass to it than just the main content. 12:05.000 --> 12:11.000 For example, the title would probably be something you want to change depending on the page. 12:11.000 --> 12:16.000 Yeah, and here the main content is passed into the body. 12:16.000 --> 12:24.000 And now we're going to put it all together by turning it into a method that is specific to a framework. 12:24.000 --> 12:34.000 So what I should note here is everything you've seen before this point was completely agnostic of whether you will use it in Django and past API and Flask or as this example will show. 12:34.000 --> 12:38.000 In StarLat, it's Python. 12:38.000 --> 12:42.000 So all of these Python web frameworks will work with it. 12:42.000 --> 12:50.000 And here we call the base method, pass at the main content. 12:50.000 --> 13:01.000 And in this case it's a list of any HTTP elements, which can be a function call, a method call like the medication plan. 13:01.000 --> 13:14.000 But I can also write h.h1 in here to give the page a title or a paragraph to give the page a little warning that this is actually not medical advice. 13:14.000 --> 13:27.000 And I think it's quite neat that up until this point I could have given you a slide with any web framework in Python because all of this is compatible with each other. 13:27.000 --> 13:35.000 So yeah, if you want to give this a spin, you can take a look at the HTTP documentation by scanning the QR code. 13:35.000 --> 13:43.000 And if you have any questions, you can get in touch using the GitHub discussions, which are linked as well on the documentation. 13:43.000 --> 13:52.000 And if you want to get in touch with me, if you have any questions, I'm Athena Valskamp, you can find all of my socials behind the QR code or on my website. 13:52.000 --> 14:03.000 I'll be right there after the lightning talk. You can follow me on the Fedivers and that's all I have to tell you for today. Thanks for listening.