1. 1

    A bit late to the party, but I just thought that the people and organizations who are migrating away from Python altogether are not doing that because of the backwards-incompatible changes introduced by Python 3. As has been pointed out time and time again, migrating (or porting, or whatever other term you prefer) from Python 2 to 3 involves less effort than a full reimplementation in a different language.

    At the same time, a number of CPython developers have expressed that had they known how much friction this would introduce to the entire ecosystem, such a big break in compatibility would not have happened. In other words, people have learnt their lesson, and it’s extremely unlikely that a similar situation will happen to Python again. Any insinuations about not being able to trust Python with regards to forwards compatibility are more likely to be rooted in frustration than fact.

    I sincerely hope that most of those who have decided to abandon Python are doing it for better reasons than out of spite, because that is not exactly a rational factor to base such a decision on. Sure, the friction involved in the upgrade has likely acted as a catalyst, a contributing circumstance, but I don’t see how it could be rationally considered the single most important factor in something like that.

    1. 3

      This is probably a topic for another post, but I have a theory that in at least some organizations, a lateral move – adopting a new language/platform and rewriting existing code in it – can be sold to management as enabling something they care about (specific features, claims about performance, whatever) and thus offers a way to actually get to do all the maintenance the organization has deferred for years as part of the rewrite.

    1. 17

      The “I use arch btw” FAQ entry is hilariously disturbing.

      1. 1

        Maybe you can install a current version of LineageOS or PostmarketOS on this device to make it last a few years more, if the hardware is supported at all. Yet another reason why portable devices are in need of an entirely free software stack.

        1. 3

          The post says they would do if a root were available.

          1. 2

            Ah, I didn’t properly understand what they meant by that

            1. 1

              Happens! <3

              1. 2

                Does unlocked bootloader really equal root?

                Honest question, I put LineageOS on a Nexus 5X a while ago and the TWRP firmware asked me if I wanted root, to me that’s a sign that it wasn’t rooted at that time. Or was it rooted for the time of applying the other image and then not?

                1. 3

                  You are correct that unlocked bootloader ≠ root. Especially devices made in more recent years have made the distinction a bit more clear, and there are semi-supported ways of unlocking the bootloaders on many devices, which then in turn makes it easy to install root.

                  However, a decade ago, the situation was very different, and the typical device was locked, without the OEM providing a way to unlock. Thus, tinkerers were usually forced to look for security bugs in the firmware, and they would typically use those to obtain root, and unlock the bootloader at the same time, which is why the two terms are often conflated.

                  1. 3

                    It’s also interesting that “rooting” an iPhone is called “jailbreaking”, after the first implementation of it, which was literally called “jailbreak”.

                    1. 2

                      Very good explanation, thanks! Roughly what I had guessed (especially that nowadays a few more devices seem to be unlocked) but as I have personally not owned a lot of Android phones I never investigated a lot of details.

                      1. 1

                        Another confusing conflation of terms to be aware of if you aren’t already: carrier unlocked ≠ unlocked bootloader, but “unlocked device” is sometimes used to describe both of them.

                        1. 1

                          That’s true, but at least in Germany I hadn’t heard about “carrier locked” in many, many years. Not even sure it was a thing since Android.

          1. 2

            My email actually went to spam in Gmail, surprisingly. Luckily for me, a coworker mentioned it.

            Has anyone else had LetsEncrypt emails go to spam? Usually they don’t, but this (probably the most important one I’ve received) did.

            1. 2

              Maybe Gmail changed something, because since only a few days ago, Sentry mail has also ended up in spam for me.

              1. 6

                Consider this a reminder that Gmail cannot be considered a reliable email service that will actually deliver legitimate mail to your inbox, as anyone who’s tried to run a small-scale independent mail server following all the common best practices in the past decade would know.

                1. 2

                  People say this frequently, but it hasn’t really been my experience. Of all the third-party or company-managed email services I’ve used, Gmail has been the best by far in terms of spam going to spam and everything else going to the inbox. That’s why this mis-categorization as spam was such a surprise to me. It’s pretty rare. I suppose different people have different patterns in the sorts of emails they receive, though.

                  1. 1

                    Your experience has been generally as positive as you describe merely because the vast majority of origins of legitimate email are run by massive megacorporations. It would be vastly different if you were on the other side, trying to run your own email service, and getting falsely flagged on almost every single message that you try to send to someone. By definition, since this affects small-scale servers, from your point of view as a gmail user, the percentage of these false positives in your incoming mail will be tiny.

                    And in my personal experience, gmail is the worst in this regard – other services tend to at least have the decency to reject messages in a false positive scenario; gmail just swallows everything up and buries it in the spam box that almost nobody ever looks at.

            1. 4

              Do you think you could come up with an nginx config that responds with text/plain or application/json conditionally depending on the Accept-Encoding request headers?

              1. 9

                Something like this? (I haven’t tested it, though.)

                location /ip {
                    if ($http_accept ~ "application/json") {
                        default_type application/json;
                        return 200 "{\"ip\":\"$remote_addr\"}";
                    }
                    default_type text/plain;
                    return 200 $remote_addr;
                }
                

                Note that you want the Accept HTTP header, Accept-Encoding specifies mostly the compression used in transit.

                Hmm, and on closer look, the docs say that default_type is not valid in an if block, so if the above doesn’t work, maybe this will:

                location /ip {
                    if ($http_accept ~ "application/json") {
                        add_header Content-Type application/json;
                        return 200 "{\"ip\":\"$remote_addr\"}";
                    }
                    default_type text/plain;
                    return 200 $remote_addr;
                }
                

                One more edit.

                This turns out to be surprisingly tricky. The first version doesn’t work, for the reason described above. The second version sort of works, but for a JSON request, it returns the Content-Type header twice – for some reason, nginx insists on including the default_type even if you explicitly set the header with add_header. One workaround seems to be to install https://github.com/openresty/headers-more-nginx-module, and use more_set_headers, but that requires a rebuild of nginx. If someone has a properly working version with just plain nginx, I’d be interested, but it seems much easier to just define a separate location, like /ip.json.

                1. 3

                  I realized this using custom error pages and named locations, like this:

                  location ^~ /ip {
                      error_page 463 = @ip;
                      error_page 464 = @ip_json;
                  
                      if ($arg_json) {
                          return 464;
                      }
                      if ($http_accept = 'application/json') {
                          return 464;
                      }
                  
                      return 463;
                  }
                  
                  location @ip {
                      default_type text/plain;
                  
                      return 200 $remote_addr;
                  }
                  
                  location @ip_json {
                      default_type application/json;
                  
                      return 200 "{ \"ip\": \"$remote_addr\" }";
                  }
                  
                  1. 2

                    Ah, of course, I should have thought of internal redirects. And the trick with using a custom error code to force an internal redirect is also quite neat, I didn’t know that one. Thanks!

                    And I’m guessing it would be possible to simplify this by just directly using the default_type and return directive of @ip in the first location block; the default shouldn’t need an internal redirect.