{"id":7995,"date":"2020-09-14T07:35:35","date_gmt":"2020-09-14T15:35:35","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/python\/?p=7995"},"modified":"2020-09-15T15:58:06","modified_gmt":"2020-09-15T23:58:06","slug":"pylance-introduces-five-new-features-that-enable-type-magic-for-python-developers","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/python\/pylance-introduces-five-new-features-that-enable-type-magic-for-python-developers\/","title":{"rendered":"Pylance introduces five new features that enable type magic for Python developers"},"content":{"rendered":"<p>In last week\u2019s <a href=\"https:\/\/devblogs.microsoft.com\/python\/python-in-visual-studio-code-august-2020-release\/\">Pylance<\/a> update we introduced Semantic colorization, and thank you for all feedback! It was exciting for the team to bring this new feature to you. With the latest release of Pylance (version 2020.9.4) we are excited to introduce features that bring us closer to the goal of helping developers write correct Python code faster and more easily.<\/p>\n<h2>1.\u00a0\u00a0\u00a0\u00a0\u00a0 Support for recursive type aliases<\/h2>\n<p>With recursive types aliases, you can now specify types for complex scenarios in a natural, succinct, and intuitive manner. For example, expressing a structure to capture my settings for VS Code can be as simple and elegant as in the example below. For data structures that have a tree pattern, a recursive type alias offers a neat solution.<\/p>\n<pre class=\"prettyprint\">ConfigValue\u00a0=\u00a0Union[\r\n\u00a0\u00a0\u00a0\u00a0bool,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0str,\u00a0\r\n\u00a0\u00a0\u00a0\u00a0float,\r\n\u00a0\u00a0\u00a0\u00a0List[\"ConfigValue\"],\r\n\u00a0\u00a0\u00a0\u00a0Dict[str,\u00a0\"ConfigValue\"],\r\n]\r\nconfig:\u00a0List[ConfigValue]\u00a0=\u00a0[\r\n\u00a0\u00a0\u00a0\u00a0{\"python.experiments.optInto\":\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \r\n        [\"Experiment1\", \"Experiment13\", \"Experiment56\", \"Experiment106\"]},\r\n\u00a0\u00a0\u00a0\u00a0{\"python.formatting.provider\": \"black\"},\r\n\u00a0\u00a0\u00a0\u00a0{\"python.formatting.blackArgs\": [\"--line-length\", \"130\"]},\r\n\u00a0\u00a0\u00a0\u00a0{\"python.sortImports.args\": [\"-rc\", \"-sp isort.cfg\"]},\r\n]<\/pre>\n<h2>2.\u00a0\u00a0\u00a0\u00a0\u00a0 Getter and setter mismatches.<\/h2>\n<p>Property type mismatch will catch cases where getter and the setter of @property are mismatched. This is an easy mistake to make, and now Pylance can help you avoid this situation. The type analyzer will verify that the type of the \u201cvalue\u201d parameter passed to the setter is assignable to the type returned by the getter.<\/p>\n<pre class=\"prettyprint\">\u00a0\u00a0\u00a0\u00a0@property\r\n\u00a0\u00a0\u00a0\u00a0def\u00a0prop_3(self)\u00a0-&gt;\u00a0List[_T]:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0[]\r\n\r\n\u00a0\u00a0\u00a0\u00a0#\u00a0This\u00a0should\u00a0generate\u00a0an\u00a0error\u00a0because\u00a0_T\u00a0is\r\n\u00a0\u00a0\u00a0\u00a0#\u00a0not\u00a0assignable\u00a0to\u00a0List[_T].\r\n\r\n\u00a0\u00a0\u00a0\u00a0@prop_3.setter\r\n\u00a0\u00a0\u00a0\u00a0def\u00a0prop_3(self,\u00a0value:\u00a0_T)\u00a0-&gt;\u00a0None:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0pass<\/pre>\n<h2>3.\u00a0\u00a0\u00a0\u00a0\u00a0 Help with getting generics right<\/h2>\n<p>New type checks for generics will help you catch errors and give you appropriate messages that can help you correct them. PEP 484 says that a type variable should not be used in a context where it has no meaning. For example, if you annotate a local variable with the type List[T] but T is not used by the containing generic function or generic class, then T has no meaning in this context and should be flagged as an error.<\/p>\n<p>&nbsp;<\/p>\n<h2>4.\u00a0\u00a0\u00a0\u00a0\u00a0 Support for so-called &#8220;higher-kinded type variables&#8221;<\/h2>\n<p>The feature allows you to pass a generic class or function to a generic function, and the type variable solver will solve for both levels of type variables.<\/p>\n<pre class=\"prettyprint\">T = TypeVar(\"T\")\r\nU = TypeVar(\"U\")\r\n\r\ndef identity(x: T) -&gt; T:\r\n\u00a0\u00a0\u00a0\u00a0return x\r\n\r\n# fmap() requires the same type as the parameter in the callable and\r\n# the type for maybe\r\n\r\ndef fmap(f: Callable[[T], U], maybe: Optional[T]) -&gt; Optional[U]:\r\n\u00a0\u00a0\u00a0\u00a0return None\r\n\r\ndef func(x: int):\r\n\u00a0\u00a0\u00a0 y = fmap(identity, x) # Type of y is determined to be an int<\/pre>\n<p>&nbsp;<\/p>\n<h2>5.\u00a0\u00a0\u00a0\u00a0\u00a0 py.typed files are now respected when using the \u201cuseLibraryCodeForTypes\u201d setting<\/h2>\n<p>The \u201cpython.analysis.useLibraryCodeForTypes\u201d setting tells Pylance to infer type information from library code even if it does not contain type annotations.<\/p>\n<p>PEP 561 defines a special \u201cpy.typed\u201d file that library authors can include in their packages. A \u201cpy.typed\u201d file indicates that the code is properly annotated and indicates that type checkers like Pylance should use this type information.<\/p>\n<p>Previously, if the \u201cpython.analysis.useLibraryCodeForTypes\u201c setting was set to false, Pylance ignored the \u201cpy.typed\u201d file, leaving all symbols imported from that package with an \u201cunknown\u201d type. With this change, regardless of the setting for \u201cuseLibraryCodeForTypes\u201d, Pylance will parse the source files for inline annotations if the \u201cpy.typed\u201d file exists.<\/p>\n<p>I hope you find these enhancements useful, and they help you write more Pythonic code. As always, we welcome you to go to our GitHub repo (<a href=\"https:\/\/github.com\/microsoft\/pylance-release\">https:\/\/github.com\/microsoft\/pylance-release<\/a>) and submit your suggestions or issues. We look forward to hearing from you and thank you for your continued support in helping us, the the Python team at Microsoft, deliver the best developer experience for Python development.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In last week\u2019s Pylance update we introduced Semantic colorization, and thank you for all feedback! It was exciting for the team to bring this new feature to you. With the latest release of Pylance (version 2020.9.4) we are excited to introduce features that bring us closer to the goal of helping developers write correct Python [&hellip;]<\/p>\n","protected":false},"author":39608,"featured_media":10119,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-7995","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-python"],"acf":[],"blog_post_summary":"<p>In last week\u2019s Pylance update we introduced Semantic colorization, and thank you for all feedback! It was exciting for the team to bring this new feature to you. With the latest release of Pylance (version 2020.9.4) we are excited to introduce features that bring us closer to the goal of helping developers write correct Python [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/posts\/7995","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/users\/39608"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/comments?post=7995"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/posts\/7995\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/media\/10119"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/media?parent=7995"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/categories?post=7995"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/tags?post=7995"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}