<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alex Manson</title>
    <description>The latest articles on DEV Community by Alex Manson (@neurowinter).</description>
    <link>https://dev.to/neurowinter</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F524164%2F7318bb83-7b67-446d-b344-3bbb37557ca1.jpeg</url>
      <title>DEV Community: Alex Manson</title>
      <link>https://dev.to/neurowinter</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/neurowinter"/>
    <language>en</language>
    <item>
      <title>How to improve your Git commits with Commitizen</title>
      <dc:creator>Alex Manson</dc:creator>
      <pubDate>Mon, 03 Apr 2023 12:00:00 +0000</pubDate>
      <link>https://dev.to/neurowinter/how-to-improve-your-git-commits-with-commitizen-2a3f</link>
      <guid>https://dev.to/neurowinter/how-to-improve-your-git-commits-with-commitizen-2a3f</guid>
      <description>&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Commitizen is a CLI tool that can be used to help communicate changes made in commits to both future you and other team members. The goal of this is to stop all those commit messages of “WIP” or “fixing stuff”.&lt;/p&gt;

&lt;p&gt;There have been countless times when I know that a change in file X has causes this issue, but I have no way of knowing which commit did it. So I end up spending far too long looking through all the commits to find the right one.&lt;/p&gt;

&lt;p&gt;Commitizen also aids a team in using &lt;a href="https://semver.org/"&gt;Semantic Versioning&lt;/a&gt;as it helps you automatically up version numbers based on changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;p&gt;Why do we need yet another tool in our workflow, don’t we have enough?&lt;/p&gt;

&lt;p&gt;Git commit messages are a very under-utilized tool in the programming workflow, a lot of us will make a tonne of changes to all sorts of files, and then commit them all under a single commit. This leads to very difficult rollbacks, as you need to roll back all of them. This practice also leads to unhelpful commit messages, as the larger a change is, the harder it is to succinctly describe what is going on. Leading to terrible messages like “WIP”. Not only do these commit messages provide 0 value and seem useless, they are also a hindrance. When it comes to Code Review, you need to be able to explain your changes succinctly to the reviewer, other than sitting down and having a chat with the reviewer this can be difficult. This is where good commit messages come in and Conventional Commits.&lt;/p&gt;

&lt;p&gt;Conventional commits is a super easy specification to follow, it is basically a set of rules that help you to create meaningful commit messages. You can read more about it, and the full specification,&lt;a href="https://www.conventionalcommits.org/en/v1.0.0/#summary"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How
&lt;/h2&gt;

&lt;p&gt;Now while the above are all reasons that you should write better commits, we often say that we will follow these practices, but end up falling back into our old ways. We need a way to ensure that we follow what we have defined as best practice. Here is where Commitizen comes in!&lt;/p&gt;

&lt;p&gt;One way to change process is to make it as easy as possible. Commitizen is a super easy to use tool that will help you right good commit messages. E.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ neurowinter.github.io (fix-working-in-aws-blog) ✘ cz c
? Select the type of change you are committing refactor: A code change that neither fixes a bug nor adds a feature
? What is the scope of this change? (class or file name): (press [enter] to skip)
 _posts/2023-01-09-removing-aws-blog.md
? Write a short and imperative summary of the code changes: (lower case and no period)
 change wording for paragraph
? Provide additional contextual information about the code changes: (press [enter] to skip)

? Is this a BREAKING CHANGE? Correlates with MAJOR in SemVer No
? Footer. Information about Breaking Changes and reference issues that this commit closes: (press [enter] to skip)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have added the code you want to commit (remember you should keep your commits as small as possible) you can then run &lt;code&gt;cz c&lt;/code&gt; to create a nice git log entry to allow your fellow contributors to better understand your changes. Having to write something about what has changed forces you to keep your commits small, as when you have committed a lot of changes, you will struggle to describe the exact changes. Continue this process for some time, and it will help you not only keep your git log looking nice, but it will also help you keep your commits small.&lt;/p&gt;

&lt;p&gt;Now that you have made some commits, you can view your git log in all of its glory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ neurowinter.github.io (commentizen-blog-post) ✘ git log | head -n 50
commit 5f8aeca4cafd413aa2e906f704a791308fbd796c
Author: NeuroWinter &amp;lt;devatneurowinterdotcom&amp;gt;
Date: Wed Jan 18 08:19:14 2023 +1300

    refactor(_posts/2023-01-09-removing-aws-blog.md): change wording for paragraph (#35)

commit 4abd7843baa6c93eed2fe8f516b544220e226906
Author: NeuroWinter &amp;lt;devatneurowinterdotcom&amp;gt;
Date: Mon Jan 9 08:36:30 2023 +1300

    fix(_posts/2023-01-09-removing-aws-blog.md): fixed link to NoReturn post (#34)

commit 50aee760139bf92020cd66fae353bdabe4637db7
Author: NeuroWinter &amp;lt;devatneurowinterdotcom&amp;gt;
Date: Mon Jan 9 08:31:06 2023 +1300

    Add link in aws blog (#33)

    * fix(_posts/2023-01-09-removing-aws-blog.md): added link to my python no return post

    * fix(_posts/2023-01-09-removing-aws-blog.md): added links to both .dev and .com sites

commit e7a79025a151b9aab3b2539ea6457fc0b15a9f71
Author: NeuroWinter &amp;lt;devatneurowinterdotcom&amp;gt;
Date: Mon Jan 9 08:18:03 2023 +1300

    fix(_posts/2023-01-09-removing-aws-blog.md): fixed wording in description (#32)

commit 50e04dd96a117abfa8a9e8977b0c5f35664a3507
Author: NeuroWinter &amp;lt;devatneurowinterdotcom&amp;gt;
Date: Sat Jan 7 20:15:35 2023 +1300

    feat(_posts/2023-01-09-removing-aws-blog.md): added post about why i stopped hosting at aws (#31)

commit 5fc12519cf0f139013c368515c53f30cd0c8a19b
Author: NeuroWinter &amp;lt;devatneurowinterdotcom&amp;gt;
Date: Fri Jan 6 21:56:47 2023 +1300

    build(tf/main.tf): updated to tf v1.3.6 (#30)

commit b918485ead4fea41c7e4e1db13ddaaf6f75e8105
Author: NeuroWinter &amp;lt;devatneurowinterdotcom&amp;gt;
Date: Fri Jan 6 17:05:46 2023 +1300

    feat(_config.yml): added linkedin link to socials for seo (#29)

[...]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that does look a lot nicer than&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;commit 6d08107ccd08f6b85140f8e77d9ea9a2bf6f5ef6
Author: NeuroWinter &amp;lt;devatneurowinterdotcom&amp;gt;
Date: Fri Oct 2 09:27:58 2020 +1300

    Show description on home page

commit 63d8f7740971e84e3d3522e7ef43dd25de3c5ceb
Author: NeuroWinter &amp;lt;devatneurowinterdotcom&amp;gt;
Date: Fri Oct 2 09:25:59 2020 +1300

    Add basic config settings

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We haven’t even gotten into the awesome version bumping features, custom templates and a range of other amazing customizations you can do. That will be for another day, I hope that this very basic overview has piqued your interest in Commitizen, and hope that you will start using it in your future projects, and if you do, be sure to check out the &lt;a href="https://commitizen-tools.github.io/commitizen/tutorials/github_actions/"&gt;GitHubActions&lt;/a&gt; or &lt;a href="https://commitizen-tools.github.io/commitizen/tutorials/gitlab_ci/"&gt;GitLab CI&lt;/a&gt; integrations.&lt;/p&gt;

&lt;p&gt;So to finalize, here are a few of the benefits of using Commentizen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Helps keep your commits small.&lt;/li&gt;
&lt;li&gt;Helps really describe what is going on in your commits.&lt;/li&gt;
&lt;li&gt;The git log is now a valuable resource.&lt;/li&gt;
&lt;li&gt;Aids in reverting changes (since you know what each commit does and is kept small).&lt;/li&gt;
&lt;li&gt;Helps with Semantic Versioning.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Why I Stopped Hosting my Blog on AWS</title>
      <dc:creator>Alex Manson</dc:creator>
      <pubDate>Sun, 08 Jan 2023 11:00:00 +0000</pubDate>
      <link>https://dev.to/neurowinter/why-i-stopped-hosting-my-blog-on-aws-2a5e</link>
      <guid>https://dev.to/neurowinter/why-i-stopped-hosting-my-blog-on-aws-2a5e</guid>
      <description>&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I originally set up this blog as a place to document some of my findings and learnings while working in the tech industry. A place to put things that I found hard to find on Google, like my post on using &lt;a href="https://dev.to%%20post_url%202021-11-12-noreturn-mistake%20%%7D"&gt;Typing NoReturn incorrectly&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I then started using this as a place to play with things, for example I am hosting this blog both on GitHub Pages, and a static site on AWS using AWS S3.&lt;/p&gt;

&lt;p&gt;In the process of doing this I started playing with Terraform, GitHub Actions and a few other things – and while it was fun and a good learning experience. I have since realized that it’s not really a good practice or a smart idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem I made for myself
&lt;/h2&gt;

&lt;p&gt;With one of the main principles of this blog for me being to document my findings and share them, so others would not have as much as a hard time as I did to find the solution. Deploying my site (at least in the way I did it) to two different domains failed in the 2nd part of that principle.&lt;/p&gt;

&lt;p&gt;While I am no SEO savant or really know that much about it, splitting your content to two different domains is always going to be a bad idea. All it does is split your traffic between two sites, and could potentially cause a fair amount of harm to your ranking on Google (if you care about that). How many times have you asked yourself “now was that company name dot com or dot net ?” and end up googling it anyway to find it. That’s what I was forcing people who read my posts to do every time. Did you find &lt;a href="https://NeuroWinter.com"&gt;NeuroWinter.com&lt;/a&gt; or &lt;a href="https://NeuroWinter.dev"&gt;NeuroWinter.dev&lt;/a&gt;? Both were hosting the exact same content.&lt;/p&gt;

&lt;h2&gt;
  
  
  How did I get here ?
&lt;/h2&gt;

&lt;p&gt;I am a tinkerer at heart and when it comes to personal projects to don’t exactly follow the “If it ain’t broke don’t fix it” mentality, I’m more of a “how can I practice this thing I learned in a low risk environment” kinda guy. So that leads me to doing all sorts of suboptimal things for the sake of practice but at the time I don’t think they are suboptimal.&lt;/p&gt;

&lt;p&gt;I like to keep things simple to start off with, and then I always manage to find ways to complicate them, but given enough time I will always default to KISS (keep it simple stupid) and that is why I ended up removing the .dev domain all together.&lt;/p&gt;

&lt;p&gt;First created my blog on GitHub Pages, as that took care of all the hard stuff for me. It made the act of having a blog super simple, all I had to do was check in new posts and bam they were live. However, I yearned to make it more complex, so to build a rod for my own back I bought NeuroWinter.dev, and started working on deploying the blog there.&lt;/p&gt;

&lt;p&gt;Since Jekyll creates a static site I thought the best place to self-host it would be using AWS S3 Static Sites. So I ended up finding a way to make it even more simple and used &lt;a href="https://github.com/cloudposse/terraform-aws-cloudfront-s3-cdn"&gt;CloudPossse terraform aws cloudfront s3 cdn&lt;/a&gt; to do all the heavy lifting for me. My final terraform was that module, setting up the providers and a variables file, nice and easy. (I have skipped the part about setting up DNS as that is covered extensively elsewhere):&lt;/p&gt;

&lt;p&gt;I then needed to find some GitHub Actions to run all this, and used the following adding my secrets to my GitHub repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Deploy

on:
  push:
    branches:
      - main

jobs:
  Terraform:
    name: Terraform Plan &amp;amp; Apply
    runs-on: ubuntu-latest
    steps:
    - name: Checkout Repo
      uses: actions/checkout@v2

    - name: Terraform Init
      run: cd tf &amp;amp;&amp;amp; terraform init
      env:
        TF_ACTION_WORKING_DIR: './tf'
        AWS_ACCESS_KEY_ID: $
        AWS_SECRET_ACCESS_KEY: $

    - name: Terraform validate
      run: cd tf &amp;amp;&amp;amp; terraform validate
      env:
        TF_ACTION_WORKING_DIR: './tf'

    - name: Terraform Apply
      run: cd tf &amp;amp;&amp;amp; terraform apply -auto-approve
      env:
        GITHUB_TOKEN: $
        TF_ACTION_WORKING_DIR: './tf'
        AWS_ACCESS_KEY_ID: $
        AWS_SECRET_ACCESS_KEY: $

  Jekyll:
    needs: ['Terraform']
    name: Build and deploy Jekyll
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v2
      - name: Build
        uses: Ealenn/jekyll-build-action@v1
      - name: Sync output to S3
        run: |
          AWS_EC2_METADATA_DISABLED=true AWS_ACCESS_KEY_ID=$ AWS_SECRET_ACCESS_KEY=$ aws s3 sync ./_site/ s3://neurowinter-prod-personal-site-origin --delete

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once it was all in the main branch I pushed some changes, and it all worked, navigating to &lt;a href="https://neurowinter.dev"&gt;NeuroWinter.dev&lt;/a&gt; showed me the exact same content as &lt;a href="https://neurowinter.com"&gt;NeuroWinter.com&lt;/a&gt; !&lt;/p&gt;

&lt;h2&gt;
  
  
  The Return to KISS
&lt;/h2&gt;

&lt;p&gt;After a while of having the site hosted in two different TLD on the net I found my self reading about SEO (How I got here I am not sure…) and found that Google may penalize you if they detect duplicate content of different domains or even different pages! — (I was not able to find a definitive source on this, and it might just be rumors on the internet.). I really had just built a rod for my own back when it comes to search ranking. Most people are worried about others copying their content and posting it as their own, I on the other hand had posted my own content in multiple places!&lt;/p&gt;

&lt;p&gt;Now there are a few ways I could have fixed this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add metadata to my .dev site to show that the .com was the canonical URL&lt;/li&gt;
&lt;li&gt;Remove the .dev domain&lt;/li&gt;
&lt;li&gt;Change the .dev domain to redirect to the .com domain&lt;/li&gt;
&lt;li&gt;Post different content on both .com and .dev&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I found that the easiest and fastest way for me to rid myself of this problem was to just change the DNS records in .dev to redirect to .com. I did this manually for now, but knowing me I will try and complicate it and do it via terraform soon. Adding canonical seemed to fix the SEO issue, but did not solve a few other problems I started seeing, I was only seeing metrics for the .com domain, I wasn’t sure which domain I had told people to go to, etc.&lt;/p&gt;

&lt;p&gt;After removing all the GitHub actions, the Terraform and adding the redirect in AWS, the whole system felt a lot simpler, it wasn’t broken in the first place, so why did I go ahead and try to fix it?&lt;/p&gt;

&lt;p&gt;This was all a lesson to Keep It Simple Stupid.&lt;/p&gt;

</description>
      <category>meta</category>
    </item>
    <item>
      <title>Python3.8 Positional-only arguments</title>
      <dc:creator>Alex Manson</dc:creator>
      <pubDate>Fri, 03 Dec 2021 11:00:00 +0000</pubDate>
      <link>https://dev.to/neurowinter/python38-positional-only-arguments-d2k</link>
      <guid>https://dev.to/neurowinter/python38-positional-only-arguments-d2k</guid>
      <description>&lt;p&gt;I have always been of the mind that explicit is much better than implicit. For this reason, I have almost always included Python’s keyword-only arguments when defining a function.&lt;/p&gt;

&lt;p&gt;My reasoning behind this is I feel that I should always know what I am passing into a function and how it’s intended to be used. Below is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
def divide(*, numerator: int, denominator: int) -&amp;gt; float:
    """
    Divide numerator by denominator, return float.
    """
    return numerator/denominator

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, you &lt;strong&gt;must&lt;/strong&gt; define which parameter use named keyword arguments, eg &lt;code&gt;divide(numerator=100, denominator=50)&lt;/code&gt;. If you try calling the function without doing this eg &lt;code&gt;divide(100,50)&lt;/code&gt;, you will get the following error: &lt;code&gt;TypeError: divide() takes 0 positional arguments but 2 were given&lt;/code&gt;. This forces the user to be explicit.&lt;/p&gt;

&lt;p&gt;However, this is only a good strategy when your variable names carry meaning like in the division example. Not all variables do carry important information. However, we can see this in many built-in python functions for example, &lt;code&gt;len&lt;/code&gt;. The name of the variable in len’s definition is &lt;code&gt;obj&lt;/code&gt;. This makes perfect sense since we are trying to find the length of an object. Because this is implicit and well-known knowledge, it would be silly to force a user to pass in&lt;code&gt;obj&lt;/code&gt; when calling &lt;code&gt;len&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now you could say, in the case of functions like &lt;code&gt;len&lt;/code&gt;, let’s just not include the keyword-only argument. Doing so means that the user does not &lt;strong&gt;have&lt;/strong&gt; to define it as a keyword, but a user still can. Giving a user the ability to do this can have some detrimental effects. It means that users can call the function in two different ways, either &lt;code&gt;len(list_object)&lt;/code&gt; or&lt;code&gt;len(obj=list_object)&lt;/code&gt;. Why not be explicit in how you want your function to be called?&lt;/p&gt;

&lt;p&gt;This is where Python3.8’s Positional-only argument comes in! As a part of &lt;a href="https://www.python.org/dev/peps/pep-0570/"&gt;PEP 570&lt;/a&gt; the &lt;code&gt;/&lt;/code&gt; argument. This argument will force all arguments preceding it, to be positional only, meaning that the user &lt;strong&gt;must&lt;/strong&gt; provide them as positional arguments and not give them as keyword arguments.&lt;/p&gt;

&lt;p&gt;It is important to remember that it is &lt;em&gt;all elements preceding the /&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Interesting bit of trivia on the choice of the &lt;code&gt;/&lt;/code&gt; character:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Alternative proposal: how about using ‘/’ ? It’s kind of the opposite of ‘*’ which means “keyword argument”, and ‘/’ is not a new character.&lt;a href="https://mail.python.org/pipermail/python-ideas/2012-March/014364.html"&gt;Guido van Rossum in 2012&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With this new tool in our tool belt, we can define functions like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def add_ints(a: int, b: int, /) -&amp;gt; int:
    """
    Add the two passed in ints and return the result.
    """
    return a+b

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the function defined above, you can only call it like this: &lt;code&gt;add_ints(1,5)&lt;/code&gt;and not like this: &lt;code&gt;add_ints(a=1, b=5)&lt;/code&gt;. If you call it like the latter way, you will get the following error:&lt;code&gt;TypeError: add_ints() got some positional-only arguments passed as keyword arguments: 'a, b'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can also use this in conjunction with the keyword-only argument for even more explicit goodness. But doing so will complicate the API into the function; forcing the user to pass in different arguments in different ways would be very frustrating.&lt;/p&gt;

&lt;p&gt;The power of the positional only shows itself when you are defining functions that are used regularly with a small argument list. We looked at the &lt;code&gt;len&lt;/code&gt;example above, which is the perfect example of where the positional only argument should be used. The goal is to reduce the effort required to parse the code mentally. If you see &lt;code&gt;"foo1bar".split(sep="1")&lt;/code&gt; that takes a little longer to read than &lt;code&gt;"foo1bar".split("1")&lt;/code&gt;. This is just because, as a collective, we are all used to the arguments for these functions.&lt;/p&gt;

&lt;p&gt;The use case for positional arguments only is relatively small, and I think it should be used very sparingly, as you run the risk of getting the function users to jump through hoops just to use your function.&lt;/p&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>I have been using Python typing’s ‘NoReturn’ wrong</title>
      <dc:creator>Alex Manson</dc:creator>
      <pubDate>Thu, 11 Nov 2021 11:00:00 +0000</pubDate>
      <link>https://dev.to/neurowinter/i-have-been-using-python-typings-noreturn-wrong-bn7</link>
      <guid>https://dev.to/neurowinter/i-have-been-using-python-typings-noreturn-wrong-bn7</guid>
      <description>&lt;p&gt;I am a huge fan of python’s new typing module which was introduced in version 3.5. The addition of this module gives us a range of tools to help people read and understand your code in the future.&lt;/p&gt;

&lt;p&gt;Since I have started using typing I have been adding argument types, and return types to almost all of my public functions. One that keeps popping up is&lt;code&gt;NoReturn&lt;/code&gt;, and as it turns out I have been using it wrong.&lt;/p&gt;

&lt;p&gt;I had completely forgotten about Python’s implicit returns. Almost no function in python actually returns nothing… In my mind for what ever reason I thought that if I don’t explicitly return something then the &lt;code&gt;NoReturn&lt;/code&gt; typing makes sense, however this is not the case.&lt;/p&gt;

&lt;p&gt;Below is an example of a function that I &lt;em&gt;thought&lt;/em&gt; should be typed as &lt;code&gt;NoReturn&lt;/code&gt;but was very wrong:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def foobar():
    print("BAZBAR")

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above function does not &lt;em&gt;explicitly&lt;/em&gt; return anything, but python will add an implicit return of &lt;code&gt;None&lt;/code&gt; when it ends. You can see this by assigning the return value of that function to a variable eg: &lt;code&gt;rtn = foobar()&lt;/code&gt; then see the type by running &lt;code&gt;type(rtn)&lt;/code&gt;, you should get &lt;code&gt;&amp;lt;class 'NoneType'&amp;gt;&lt;/code&gt; back! This is an example of python adding &lt;code&gt;return None&lt;/code&gt; at the end of your function.&lt;/p&gt;

&lt;p&gt;The goal of the &lt;code&gt;NoReturn&lt;/code&gt; type is to signify that calling this function will end all further processing, it is the point of NO RETURN! This type should be used in functions that will raise an exception, or a function that ends the program, below are a few examples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def raise_error() -&amp;gt; NoReturn:
    """
    Always raise an error.
    """
    raise RuntimeError("An Error occurred")

def quit_program() -&amp;gt; NoReturn:
   """
   Quit the process running this code.
   """ 
   import sys
   sys.exit()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I now need to go over 100s of lines of code, and fix this mistake! To fix this mistake, I will need to go though all the instances where I have put &lt;code&gt;NoReturn&lt;/code&gt;and if in reality the function ends processing, then I will leave it as it is. In most cases though I will need to replace &lt;code&gt;-&amp;gt; NoReturn&lt;/code&gt; with &lt;code&gt;-&amp;gt; None&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I could have avoided this if I just RTFM a little better!&lt;/p&gt;




&lt;p&gt;Links:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.python.org/3/library/typing.html#typing.NoReturn"&gt;https://docs.python.org/3/library/typing.html#typing.NoReturn&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Tags: Python, Typing, Mistakes&lt;/p&gt;

</description>
      <category>python</category>
    </item>
  </channel>
</rss>
