 Please welcome Henry to the North Pay Python stage. Thanks for coming. Sorry to pull you away from your lunch. Thanks to the organizers as well for having me over here. It's really cool to get up and talk for a few minutes about something you find interesting. So, MyPy, it's just going to give you a little introduction on what the tool means and best practices now to use it. Essentially, what it is, is a tool for enforcing correct static type annotations across your Python project. For me, that's really good because I've got a bit of a love-hate relationship with Python. I'm sorry to say, that's probably not a popular thing to say at a Python conference, but it's true, I love all the libraries you've got and you can find a library for anything, and so many people have worked on it for years and years and years. But if you're writing a big, large-scale enterprise application, you do tend to get a lot of bugs in a dynamically typed language, and that can be a bit of a headache sometimes. So you've got this sort of balancing act between all these libraries that are great and then you've got this dynamically typed stuff which tends to trip you up occasionally. So, before that, I'll get the trivial stuff out of the way. So, I'm a software developer working for Romax Technology in Nottingham, UK, and I've had to just change this slide after a few days in America because some of you were getting very confused about Nottingham, and it certainly isn't Notting Hill, the 1999 classic starring Julia Roberts and Brad Pitt. Different place, guys. It is, of course, home of Robin Hood, Prince of Thieves, and much more importantly, it was the first destination for Prince Harry and Meghan Markle's royal outing. I know you guys are very into the royals, we couldn't care less, but I put it in there for you guys. Now, Suits is a great TV show, so I'm into it. Okay, so Romax, we write analysis software for mechanical engineers to help make better decisions when they design automotive products like cars and aerospace things, and in the renewable energy sector like wind turbines, we can model all the phenomena that goes in and hopefully help make some better decisions, and there's some screenshots from our software, and on the left you've got a very poorly looking gearbox which is bending, and hopefully we can help the engineers make some better decisions on why it's bending, and on the right, I have no idea what this picture is of, I just got it off our website and it looked pretty good, so... I mean, I know what that is, but I'll take it on to explain. That's what I meant to say, of course. So, I know you've just had lunch, so I've got your backs, guys. If you just listen for five minutes, the quick version will be all you need, and then for the hardcore amongst you, you can then listen to the remaining ten minutes of it, where it will be a few more details. So, five minutes listening starts now. So, in Python 3.0, Syntax was added for variable and functional type annotations. Does anyone use them? Okay. Less than I thought. So, type annotations can be pretty good. They help build the flow of what your application is supposed to do, and if you've got big functions, it helps the readability a little bit for other engineers that work on the same project. So, here's a bit of just normal Python code. Pretty standard. Of course, means I couldn't be bothered to write actually what the function did, but you just have to imagine that it's doing something correct. And then here is very straightforward. You just put a colon and then the type after variables. You can have instance variables inside a function as well. And the arrow means the function spits out a string or whatever the function is. And it can be pretty good. And as part of 3.5, I've massively increased the sort of syntax that you can add to your type annotations. And it's a very expressive thing now you can do. So, sarcasm, alert, type annotations are great. But are they great, really? If you've got nutters making functions like this that don't, you know, it's returning a flow, it's returning a dictionary, and the numbers are string. It's only really as good as your software engineers. I appreciate this as a rubbish example. But, you know, the subtleties, it's basically down to you to get it right and we're not perfect people essentially. And it can actually be more of a hindrance sometimes when you've got wrong annotations in your functions and something that was supposed to help you is actually doing the opposite. It makes things a bit more murky. So, I'm not sure what it was. I was at the sarcasm thing. Okay, I forgot I put that in there. So, enter my py, stage, stage direction, enter. It's a tool for enforcing correct type annotations across your Python project, which is amazing for me because I constantly mess things up and get it wrong. So it's like a little tool watching you back. It's developed by Guido. So, you know, it must be good. It's sponsored by Dropbox and used across their large Python code base. So, it adds a bit of credibility to it. And it's a... Anyone start using TypeScript? Okay, great. So, it's kind of analogous to the... from the JavaScript to the TypeScript thing, you know, Python to Python with mypy is a similar kind of transition. And TypeScript applications now are becoming much more robust and easily testable, and people are finding a less headache to write and maintain. And I see it as a similar thing to that. So, it's still an early development, but that doesn't mean wait till it's, you know, fully, fully done, fully fleshed out. Use it now and use what can give you straightaway. So, another very trivial worked example because we're still in the five minutes after lunch phase at this point. So, pip install mypy, obviously. And then here's a little test function. And I'm not going to let you read that long enough to work out the mistake. And then you run mypy test.py, which is that function there. And then it will tell you there's an error. Your type annotations are wrong or your function return is wrong. So, on line three of that test script, there's an incompatible return type. So, it expected a float and got a string. And that's pretty cool. So, mypy looked at what that function is on the return. It introspectively worked out that it's supposed to be returning a string and compared that with the return type that you've annotated float, and it's been like, okay, there's a problem here. And then that's highlighted it to you and you can go in and work out what's gone wrong. It keeps everything nice and correct. Okay, so go back to sleep now for the people that are still digesting. So, to really get the most use out of this, you have to look at what was added in Python 3.5 as per the PEP 484 standard, which is quite a big deal. So, before this, the only types you could really have were your own classes and the built-in stuff. So, here are a few examples. But now, there's a new typing module which is shipped as part of the standard library. And for... So, here are some of the basic things you can add, like list sets, optional things. So, optional arguments, if it's none or something else, or unions of several types put together, any str, no points for working out what that means. From the typing module, import callable iterables, you've got some interesting functional annotations you can put on stuff, which is very handy as well. So, you can still encourage us to use all the kind of dynamic-y function bits of Python as well. And then, you've got a few more of the weird things at the bottom, like any, just, obviously, if you don't care or if you want my Python to start ignoring a few things, which is a bit too dynamic, you can say, actually, this is a dynamic part of my code, this object or this function spits out any, or it isn't anything. So, you can still use that. Casting, you can, like, cast, you can force a variable to be something which is useful, and I'll talk about type-checking in a bit. So, all those things on the previous slide, you can look up this thing called the MyPy cheat sheet, and you can just Google that, and you can look up the kind of standard things. But I've used this quite a bit. So, I've got three case studies for you where it's not quite as straightforward and took me a lot of Googling to work out how to get around these things. So, case study one is dictionaries. So, the first one is straightforward. So, this is a variable annotation. So, x is a dictionary. It's the key values of strings and the types are floats. And MyPy, if you run MyPy over this, it'll be like, okay, that's cool, well done. You've got that right. You're a very talented software engineer. And then this isn't going to work because the syntax for dictionaries, the type dictionary is, all your keys are the same type and all your values are the same type. So, at the moment, the typing module doesn't let you annotate dictionaries like this on the right correctly. So, MyPy will be like, actually, that's not quite right there. You're a terrible software engineer. Throw your laptop in the bin. Go home. But it's okay because MyPy is kind of adding a few more things which will hopefully be brought into the standard library of Python soon. So, you can generate your own dictionary types. This is very much a type script type of thing where you can have a few files where you declare the types of your objects and then here's your dictionary class called person and then you can now correctly annotate your X and that will make sense and MyPy will be very happy with that. So, you can basically make your own types which are really useful if you've got custom stuff and that's pretty good. So, circuit imports. This is important for a couple of reasons. So... Sorry. Okay, so... Okay, so sometimes your variable annotate, your type annotations will lead to a circular import and you can do this thing which is if you're type checking, do your imports in there for your offending imports. And this is a bit of a hack. I agree, this doesn't look good, but we know it's a hack and it will be a hack for two reasons. One, the structure of your program isn't quite right and it's a good reason to investigate why you're getting circular imports for types and the second reason which I'll give you a bit more detail about later is that you don't have stub files generated for this thing called class A and if anyone has used C, C++, you've got header files. Yes, header files. So, stub files are Python's kind of header files and if any of you have used Python 3.5+, if you look in your site packages you'll have a thing called stub shed or type shed, something like that in there and that will be all the stub files for the standard library but outside of the standard library you don't have stub files yet so you can generate them yourself or you can download them yourself from third-party things so just be aware that you've got every time you install Python 3.5+, you've actually got this type A header file thing that's been installed in there under the hood. So, no returns. This is a common thing in Python so every function, I believe, returns none. I don't think you can actually have a Python function that returns nothing but sometimes your design intent is to really write a function that should never be used by anyone else to return nothing. It should just be a completely static thing. So, you can... This one I use quite a lot so if you've got a completely static function you can annotate it with a no return type which is really useful for assigning a non-value to a variable. MyPy will error it, essentially. So, that's... I find that pretty useful and that's the end of the case studies. So, finally, who uses things like Jenkins, Travis, GitLab CI, Git Hub CI, a few more hands, that's good. So you can add MyPy as a job to your pipeline which really makes it a lot more powerful if you just have this thing running in the background every time you commit or want to merge into master. It's pretty easy in theory. It's just like adding a linter. But you know if you've ever tried to add linting to your pipeline that if it's a big pre-existing project you'll get to this thing where on your first run you'll have like 10 million errors and you'll feel pretty overwhelmed and you might be tempted just to not bother linting your project. So I've got a few top tips for adding MyPy into your project to help that kind of getting it down to no errors a little bit easier for you. Okay, cool. So if you use GitLab CI, which I love, it's just as easy as adding a job to your YAML file like that. Just type MyPy and then your Python project in your script and it will be a job in your pipeline. So MyPy, a module name which is your module name of course the first thing you need to do is ignore the missing imports and I'm going to just pull rank on this one and say do it to start with because sometimes your third party things that don't have the type shared stuff will be missing and they'll be throwing lots of spurious errors for you. So just to start with, ignore the missing imports and you'll find that you can actually focus on the things that you can fix straight away and will improve your code more easily. The next thing I'd add once you've cleared up all the errors on the first step would be to add a strict optional which checks all your optional parameters so it'll take a little bit longer to run sometimes and it'll just basically percolate through the whole program to make sure that all your optional arguments and everything are being referenced correctly and it's just a bit more stuff to fix up usually. Next one, if you've got strict optional good, we can disallow on type depth which means MyPy doesn't enforce that you have everything annotated but if you add disallow on type depth it means no, every function you add to your project needs to have an annotation whether it turns none, whether it turns any, whether it turns a specific thing every function that gets committed to the master branch that's our policy needs to be annotated. Then if you're feeling brave you can then go a few steps further which is disallow any so that means nothing in the whole project is unannotated which I haven't done yet because I'm not a masochist but if you're feeling super super intense then go for that and I think finally, yes ignore the missing imports the final step is so if your third party libraries and your own classes that you're using you should go back and generate the stub files and there's a tool called stubgen which can generate the stubs for you or at least get you 90% of the way there without you doing any manual work so you might see a little bit of research into generating stub files for Python but it's definitely well worth it and it'll make your coding a lot better it'll make your project a lot more stable and finally any questions? Does anyone have any questions? I can run a mic over one question any question? Is there any integration with Zoop.interface? Sorry Any integration with Zoop.interface? Unfortunately I don't know what that is Zoop.interface Was it? Yeah I don't know No is the answer to that question then So I'm going to run up on stage so I can hand you a gift Everybody please give Henry a massive round of applause