1. -6

    It’s literally called 0.19. Do you know what a zero at the beginning of a version number means? Christ.

    EDIT: more nuanced view below. I stand by what I said here though.

    1. 6

      The issue is nothing in the way the language is marketed points at this.

      You can start at http://elm-lang.org/ and end up installing the language before you even find out what version you’re installing and there’s certainly no mention of how unstable the language is release-to-release, not from the website, nor from its proponents. It’ll also take you a while before you discover its more complex limitations (e.g. the things you used to need modules for) and by that time you may already be heavily invested.

      1. 3

        That is fairly bad. I’d hesitate before saying that people shouldn’t make pretty websites for things that are still in development, but they should certainly point out that they’re still in development.

        Still, it looks like this is less an issue of being unstable and more an issue of people relying on implementation details. Changing implementation details marked as being implementation details you shouldn’t rely on isn’t really that bad. It’s certainly not bad for the web. In the Linux kernel it’d be a sin. I guess a language falls more on the kernel side than the average web library side of being careful about stability.

    1. 5

      I find it interesting that the author uses AST rewriting to convert |. I’ve seen approaches in the past which just use a filler object (like foo | into | bar, into being the filler) which has a special __or__ method that does the piping.

      I personally have experimented with a simple function just called pype() which also does some magic to avoid the need for lambda functions, see here.

      EDIT: I did a quick writeup of my solution.

      1. 7

        I always just reduced the value over the reverse of callables. It made higher order stuff, particularly data transforms, a lot easier to read. The code I used at my last job is open sourced here (the thread() function): https://github.com/curiosity/yunobuiltin/blob/develop/yunobuiltin.py#L444

        We used pipeline() more than thread(), which takes only callables (no value) and returns a callables. It is functional composition with the order reversed such that the callables are applied from left to right.

        The nice advantage of using the ast is that you can get much closer to Clojure’s -> and friends. By working from a compiler hook (the ast transformer), you wouldn’t need to use partial/rpartial/lambda as much. The downside is that it is quite a bit more complicated than a one liner.

        1. 2

          That is very nice and clean, though I don’t really like lambdas in Python, they feel super verbose for what they are. I wish there was Haskell-style partial application.

        2. 6

          I’d considered that approach as well, but I wanted to avoid needing a wrapper for the leftmost expression and I also wanted to avoid needing to partially apply functions.

          Take the 3rd example from the post:

          Users.find_all() | group_by_category(max=5) | print()
          

          without transforming the ast that’d have to look something like:

          pipe(Users.find_all()) | partial(group_by_category, max=5) | print
          
        1. 5

          $HOME – I released a new version of molten this weekend. The highlight being websocket support; I don’t really need websockets for anything in particular but I realised I’d never read the spec before so my inner yak shaver took over and did what he does best. This week, I’m probably going to give Dramatiq a little love since folks have opened a couple of PRs I haven’t had a chance to look at yet.

          $WORK – I’m going to be working on coming up with new ways to make it easier for folks to integrate with our product.

          1. 1

            Where does molten fit on the flask -> pyramid -> django spectrum of complexity / included batteries?

            1. 1

              I would say the core framework is simpler (in the sense of fewer, less coupled components) than flask:

              • API-focused,
              • no external dependencies other than typing-extensions and typing-inspect which are tiny,
              • no global request context,
              • no blueprints,
              • no CLI,
              • no development server,
              • no sessions or templating.

              It does, however, have everything you would need to build and API w/o bringing in other dependencies. The molten.contrib package then lays more functionality (sessions, templates, ORM, etc.) on top of that (and more dependencies!).

              I would probably place it somewhere between flask and pyramid.

              1. 1

                Cool, sounds interesting. I think not having a development server might raise the barrier to entry, though. Every time I’ve started something with flask or pyramid it’s been with the development server. Sometimes that’s even enough for small internal projects or throwaways.

                Blueprints have been one of the most confusing things in flask for me (though it’s been a few years since I tried to use them, maybe they’re better now).

          1. 6

            I’d use Dramatiq with APScheduler, but I wrote the former so I’m biased!

            1. 2

              Was definitely also looking at Dramatiq! Can you explain why one needs both APScheduler and Dramatiq?

              I also nearly missed the Cron-like scheduling in the cookbook when I looked at the Scheduling Messages portion of the guide.

              1. 2

                APScheduler (or something like it) is necessary if you want to execute tasks at regular intervals (i.e. “cron-like scheduling”) since Dramatiq doesn’t have anything built-in to do that. Of course, you can also just use cron instead of APScheduler. :D

            1. 9

              Current job (small team):

              • Commit and push changes
              • Concourse CI picks those changes up and
                1. if they’re not tagged, it runs the unit tests and stops
                2. if they’re tagged, it runs the unit tests and continues
              • It builds docker images and pushes them to ECR
              • It deploys those images to ECS in the staging environment
              • We monitor the changes in staging (metrics are scraped by Prometheus w/ graphing from Grafana)
              • If everything looks good in staging we push a button in Concourse to send the images to ECS in the prod environment

              Concourse build pipeline definition, tasks and scripts are defined in the repo and infra is managed with Terraform (which Concourse runs). It took me about three days to set everything up and it has been running smoothly ever since (~6 months).

              To roll back, we just re-run older deployment jobs.

              We don’t have a dedicated QA team. Everyone tests their own changes or asks someone else on the team for help and we have an extensive unit test suite.

              Side projects (just me):

              • ./scripts/deploy runs tests and deploys either to GAE or Heroku and that’s it.
              1. 1

                Same, but Jenkins and Datadog. It just works.

                1. 2

                  Oh, using the tags to decide whether to deploy or not is a niiiice idea, I’ll steal it.

              1. 4

                I’m Bogdan and I sometimes write about Python.

                Link: https://defn.io

                1. 5

                  Improving the docs and releasing molten 0.2.0. The main focus of this release is going to be Python 3.7 and OpenAPI support (the framework now bundles the Swagger UI and can automatically generate OpenAPI documents).

                  1. 3

                    Molten looks neat. Especially request validation based on schema classes looks like it would eliminate so much validation code. Nice work!

                    1. 2

                      Thanks!

                  1. 2

                    I played around with it and molten is awesome. Still not sure, whether type hints are pythonic or not, but this gave me another tilt towards finding it perfectly suitable, especially for the web dev use case.

                    1. 1

                      This specific usage of the type annotations is nice in terms of visual clutter, but I think that it will require extra cognitive work to understand and write the code.

                      1. 4

                        I disagree, type hints are awesome especially for things like this.

                        Usually, when your route takes e.g. a user_id you either have to use the right regex (in Django’s urls.py) or remember to validate it yourself in every route. Screw up once -> boom.

                        Molten, similar to Rocket for Rust, makes sure that you’re handler is only called when the passed user_id is a valid integer (assuming user_id: int).

                        This becomes even more valuable with more complex types.

                        1. 1

                          I agree that type hints can be useful to make sure that these kinds of bugs are taken care of easily. But the way it is used in the Todo example is that the TodoManager class is passed as an annotation in the methods “list_todos” and “get_todos” . Why not just use a keyword argument for this?

                          1. 1

                            Why not just use a keyword argument for this?

                            That “just” makes the problem seem less complicated than it really is! :D

                            Let’s say you’re using a framework like falcon that doesn’t provide DI support out of the box. Assuming you wanted to

                            1. be able to swap out the implementation of todo manager easily in your tests and
                            2. avoid global state and mocking,

                            then your API might look something like this:

                            from falcon import API
                            
                            # Define Database and TodoManager here...
                            
                            class TodosResource:
                              def __init__(self, todo_manager):
                                self.todo_manager = todo_manager
                            
                              def on_get(self, req, resp):
                                resp.media = self.todo_manager.get_all()
                            
                            
                            def setup_app(db_impl=Database, todo_manager_impl=TodoManager):
                                db = db_impl()
                                todo_manager = todo_manager_impl(db)
                            
                                app = API()
                                app.add_route("/todos", TodosResource(todo_manager))
                                return app
                            
                            # In your entrypoint:
                            app = setup_app()
                            
                            # In your tests:
                            app = setup_app(db_impl=StubDatabase)
                            

                            This isn’t bad and it’s explicit, but manually configuring the dependency tree can get quite hairy over time and when a particular component’s dependencies change, rather than only changing that component’s code to depend on different deps, you’ll have to also change all of the places where the dependency tree is constructed (not a huge deal if you have this sort of setup_app function like I’ve got above, but not a particularly fun thing to do either way). Another downside here is that it’s not immediately clear what components the TodosResource.get method relies on from its header.

                            If, instead, you use type annotations to do the wiring for you then you get the best of all worlds in exchange for a little bit of magic (that, in my experience, people get used to fairly quickly).

                            I hope that makes sense!

                          2. 1

                            Yeah, I was reminded a lot of Rocket when I was reading the examples. Which is a good thing. There are a lot of things in Rocket I wish I was able to do more transparently in Django.

                      1. 3

                        This looks interesting, and makes good use of typing. It also looks similar to Apistar, which is another python framework for APIs that also uses typing. Could you please describe the differences between these two? I’ve been using Apistar for a project for a while and it works great so far.

                        1. 3

                          Thanks! I tried to do that on the motivation page. Basically, I wanted more control over the component lifecycle (molten lets you define which components are cacheable (reused during a single request) and which are singletons), I think apistar’s hooks are super clunky and, as an apistar user myself, this announcement kind of scared me, especially after the huge 0.3 to 0.4 transition.

                          1. 3

                            I’m sorry, I was so amazed by all the examples on the homepage that I’ve missed the “motivation” link.

                            That explains it to me, thank you. I also wasent aware of the change of focus re. Apistar, I’m still running 0.3 but I share your concern.

                            I’ll definitively have a thorough look at Molten and will give porting my API over to it a try.

                        1. 5

                          Coming from the DM, I had a hard time finding the gofundme link. Just in case others are as dense as I am, here it is: https://www.gofundme.com/lobsters-emoji-adoption

                          1. 2

                            It took me a moment to realize the link is the story link for this story. I’m just not used to seeing the announce tag on a link!

                            1. 2

                              Or on a primarily text post!

                          1. 5

                            @home: Preparing to release version 0.12 of Dramatiq. I want to improve some parts of the docs and some of the supporting material. I may even do a little intro screencast.

                            EDIT: I ended up recording that screencast 🎉

                            1. 2

                              nice job on the recording, I have tried a few in the past and was never satisfied with the result. What recording software/hardware do you use?

                              1. 3

                                Thanks! I used ScreenFlow to record the video and Moom to size up the windows beforehand to 1280x720pt (2560x1440px) and many, many takes. When exporting the video I chose to do it at 1440p to avoid scaling artefacts. For the audio I used my apple earbuds in a fairly tall, echoey room and it shows :D

                            1. 3

                              @home: working on a Django app/integration for Dramatiq. It’ll have a run command and task module auto-discovery built-in, as well as an optional admin interface to manage tasks.

                              @work: pairing w/ some people to improve our local dev. story.

                              1. 1

                                What exactly do you mean by “local dev story”?

                              1. 1

                                If I understand the docs, it seems like it’s on me, the user, to deploy and manage the code the workers run. It would be great (and a differentiating feature) if dramatiq could handle this – e.g., if the workers were dumb and ran code distributed by the submitter. Deploying code to dozens or hundreds of workers is always what makes these things painful to use.

                                1. 1

                                  IIRC Cloud Haskell works in the way you propose. While interesting, I don’t think it’s a model I’d adopt for a dynamic language. At least not for your average SaaS workload!

                                1. 1

                                  Dramatiq is licensed under the AGPL

                                  Now I have three options:

                                  • Make the codebase at work opensource (lol)
                                  • Violate AGPL on purpose
                                  • Use any of the other Redis-based task queues

                                  I really don’t get what the author is trying to achieve with choosing a license like this.

                                  1. 13

                                    You could also buy a license.

                                    1. 1

                                      Ah, that makes sense. I didn’t see that, shame on me.

                                    2. 4

                                      I think commercial backing of some sort or another is the only way we can sustainably develop open source software long term and dual licensing seemed like the lowest friction way to get started. I’ll have to highlight that fact a little better in the docs! :D

                                      1. 2

                                        You are right of course. Other message frameworks like sidekiq seem to do alright: https://github.com/mperham/sidekiq

                                        The challenge here is that Celery is in pretty great shape for a free solution. On the other hand Python’s support for high concurrency is changing rapidly so who knows maybe there’s room for a new player in this market.

                                        1. 2

                                          I’ve never met anyone IRL who’s worked with Celery and didn’t run into problems, so there’s definitely room for improvement in this area.

                                          1. 2

                                            It works like a charm with RabbitMQ as a backend. The rest is pretty experimental and breaks, especially at high volume. (I’ve been using Celery for >5 years)

                                            1. 4

                                              I’ve been using Celery professionally for about 3 years and dramatiq tries to solve many of the issues I’ve encountered using it. Some stuff that immediately springs to mind:

                                              • Celery doesn’t support task prioritization. You have to deploy multiple sets of workers in order to prioritize queues.
                                              • Celery has poor support for delayed tasks. Delayed tasks go on the same queue that normal tasks go on and they’re simply pulled into worker memory until they can be executed. This makes it hard to autoscale workers by queue size.
                                              • Celery acks tasks as soon as they’re pulled by a worker by default. This is easy to change, but a bad default. Dramatiq doesn’t let you change this: tasks are only ever acked when they’re done processing.
                                              • Celery tasks are not retried on error by default.
                                              • Celery’s not well suited for integration testing. You’re expected to unit test tasks and to turn eager evaluation on for integration tests, but even then task exceptions will be swallowed by default. Dramatiq provides an in-memory stub broker specifically for this use case.
                                              • The source code is spread across 3 different projects (celery, billiard and kombu) and it’s impenetrable. Its usage of runtime stack frame manipulation leads to heisenbugs.
                                              • It’s easy for some of its more advanced “canvas” features to drop tasks.

                                              All of the above are things that are first-class in dramatiq and there are definitely other things I’m not thinking of right now. That’s not to say that celery is bad, but I think we can do better and that’s why I made dramatiq. :D

                                              1. 1

                                                Considering your experience, I was wondering what’s your take on rq? (others who used it, are obviously welcomed to chime in too)

                                                1. 1

                                                  I don’t have much experience with RQ since it is Redis-only and I’ve generally preferred to use RabbitMQ as a message broker. However, a few things that seem like disadvantages to me with RQ are:

                                                  • Messages are pickled so it’s strictly limited to Python and pickled messages are potentially exploitable. This also means you may sometimes send bigger messages than you intended over the network purely by accident.
                                                  • Queue prioritisation is handled like it is in Celery: you have to spawn different sets of workers.
                                                  • It forks for every job, so it’s slightly slower and forks that are killed b/c they’ve surpassed their time limits can leak DB connections if you’re not careful. I understand this may be swappable behaviour, however.
                                                  • Similar to Celery, there isn’t a good integration testing story for RQ.

                                                  Because I’ve criticised both Celery and RQ at this point, I feel it’s important that I mention a couple areas where they’re both currently better than dramatiq:

                                                  • the obvious one: it’s newer than either of those and is less likely to be familiar to users. The extension ecosystem for dramatiq is nonexistent (though I will be releasing integration packages for Django and Flask soon!)
                                                  • dramatiq doesn’t store task results and doesn’t offer a way to retrieve them. Adding that sort of functionality is trivial using middleware, but it’s not there ootb so if you absolutely need something like that and you don’t care about the things I have mentioned so far then you should look at Celery or RQ instead.
                                                  1. 1

                                                    Thank you for taking the time to post this!

                                                    There are two other areas that bother me personally:

                                                    • Python 3 only. While I would love to switch to Python 3, still need to maintain a large project in Python 2.
                                                    • The AGPL license. The above project is open source too, but I want to keep it BSD licensed to stay “friendly” towards potential users. Ironically, for a commercial project I would worry less about your license of choice, as I wouldn’t mind buying the commercial license when needed.

                                                    I share @jscn’s sentiment about Celery. I I was wondering if RQ, despite the above disadvantages might be more stable. At least their codebase should easier to grok (single repo)…

                                                    1. 1

                                                      Python 3 only. While I would love to switch to Python 3, still need to maintain a large project in Python 2.

                                                      I’m considering adding Python 2 support, but it’s a hard thing to balance what with 2.x getting EOL’d in a little less than 2 and a half years.

                                                      The AGPL license. The above project is open source too, but I want to keep it BSD licensed to stay “friendly” towards potential users. Ironically, for a commercial project I would worry less about your license of choice, as I wouldn’t mind buying the commercial license when needed.

                                                      Understandable.

                                                2. 1

                                                  Sure, that’s true. Did you ever look at https://github.com/RichardKnop/machinery that project is still really early. Probably much easier to compete with.

                                          2. 1

                                            beanstalkd, NSQ, resque, celery, huey, … — pretty much everything in this space is non-GPL. So “use any other queue thing” will definitely be a very popular option :)

                                            1. 5

                                              So “use any other queue thing” will definitely be a very popular option :)

                                              That’s perfectly fine! I just want those people that get value out of my work to contribute back in some way. If someone makes a cost-benefit analysis and decides that they’d rather use celery over dramatiq because they prefer the cheaper option (although it’s worth mentioning that I give out free comm. licenses for one year per company) then that’s their prerogative. I’ll still be around a year later when they realise their mistake ;).

                                          3. 2

                                            Trying to achieve you not using this at work? That’s usually what I’m going for when I choose AGPL

                                          1. 3

                                            This is cool, congrats! I’m going to play around with using it as a broker in dramatiq this weekend :D. A couple questions:

                                            From what I can tell, a lot of things Faktory does overlap with things RabbitMQ provides ootb. How are you planning to differentiate long term?

                                            Is the protocol documented anywhere? I haven’t been able to find anything. The best I could find was this file in the Ruby client.

                                            1. 1

                                              The wiki has some protocol docs. Right now, the wiki + faktory_worker_{go,ruby} are the things to look into.

                                            1. 1

                                              I’m been working on a Django app for Dramatiq and making small improvements to it in the process.

                                              1. 5

                                                I might be the only person in this thread who likes the new keyboard. I use a 2017 15” Macbook Pro with Touchbar for work and find the keyboard easier to type on than my 2015 13” Macbook Pro. I like the reduced travel distance and what I perceive as a louder click when typing.

                                                The thing that changed my life, however, is setting CAPS LOCK to be ESC. I’ve done it across all of my computers now and would not have done so without Apple giving me a nudge when removing the physical ESC key on the Touchbar Macs. I don’t miss CAPS LOCK at all and the travel distance to ESC is so much more pleasing.

                                                I do have problems with my hand sometimes brushing the touchpad if I’ve not positioned my wrists correctly. That’s a little aggravating but I’m largely over it now in the ~4 months I’ve been using this machine. Turns out I never really used the media keys much except for volume and pause/play so I don’t mind the touchbar and the extra info it can provide in many modern apps I use (e.g. Chrome, Outlook).

                                                To each their own?

                                                1. 4

                                                  I can totally see switching caps lock to be esc on the touch bar model. However, people who use the CTRL key a lot, like people running Windows or Linux or spend their day inside the terminal in macOS, might find it useful to swap CTRL and Caps Lock. Vim users might then want to start using CTRL+C instead of Esc to enter normal mode.

                                                  Especially people on MacBooks or Lenovos where the Fn and CTRL keys are all wrong should consider swapping the buttons if they ever use CTRL for anything.

                                                  1. 6

                                                    Set caps lock to BOTH Ctrl and Esc!

                                                    X11: xcape (like this)
                                                    Windows: AutoHotkey (like this)
                                                    macOS: karabiner-elements

                                                    1. 1

                                                      Is there a High Sierra work around?

                                                      1. 3

                                                        I haven’t tried it (I’m still on Sierra) so can’t confirm, but the Karabiner Elements repo suggests it works on High Sierra. Karabiner Elements still has far fewer features than Karabiner though.

                                                        1. 2

                                                          There wasn’t, the last time I checked.

                                                          1. 2

                                                            A shame. I’m still on 10.11 and I won’t upgrade because my workflow depends on karabiner.

                                                      2. 3

                                                        Just a warning for potential users of this setup: ^C and Esc aren’t exactly the same in vim. A major difference is entering text [count] amount of times (like 3i or 4A): hitting ^C to enter normal mode will only insert the new text once.

                                                        1. 2

                                                          That’s true. My .vimrc has the following lines to make ^C act as Esc in normal and insert mode:

                                                          nmap <C-c> <ESC>
                                                          imap <C-c> <ESC>
                                                          
                                                          1. 3

                                                            You could use C-[ instead. It’ll work everywhere without any mappings and is equivalent to ESC.

                                                      3. 1

                                                        Yeah, I concur. I like the new keyboard, even coming from a cherry MX green keeb on my desktop.

                                                      1. 6

                                                        I’ve been using fish for a couple of years now and I love it not only because of its batteries-included nature (I have a few custom functions I wrote, but otherwise I’ve been basically running vanilla fish from the beginning), but also because of how damn fast it is while providing all of these great features out of the box. For bash utility compat. there’s bass but I’ve never really had to use it. virtualfish is a fantastic replacement for virtualenvwrapper.

                                                        1. 7

                                                          I do not like this electron fad.

                                                          1. 7

                                                            I had to make certain I had at least 16gb of RAM in all my future computers because of Electron/node-webkit-app-whatever. As it is, I’m using 12 gb just sitting here, no compiles.

                                                            Culprits according to gnome-system-monitor sorted by memory? Chrome, Chrome, Chrome, Spotify, Chrome, Slack, Slack, Chrome, Chrome, Slack, Slack, Chrome, Chrome, Chrome (on and on for a whole page)

                                                            1. 3

                                                              I hope it’s just a fad and that it dies off as soon as possible, but I think it’s unlikely that it will.

                                                              1. 1

                                                                It’s not going to die off. Javscript is eating the world, one chunk at a time.

                                                                I guess this means I should get off my butt and actually learn the silly language sometime soon. I’ve been doubling down on my Python mastery :)

                                                              2. 3

                                                                I’m generally in agreement, but this is one of the cases in which Electron is perfectly reasonable… The project is a web browser after all, so the weight of Chromium is not going to waste.

                                                              1. -2

                                                                Python is dead

                                                                Update: Why the downvote? It’s quite obvious to me that Python is not a language you can trust going forward and there are plenty of good alternatives out there (Go, Swift, Nim, Elixir, etc). Why they have destroyed a perfectly nice language is beyond me.

                                                                1. 5

                                                                  Saying “X is dead” in the technology world is pretty much a no-op. It’s a statement devoid of any actual purpose other than trying to make a splash.

                                                                  Want proof? Google “Java is dead” and then actually look at just HOW MUCH JAVA is being written every day, all the time, in enterprise environments.

                                                                  1. 0

                                                                    I don’t claim that Python is dead because I don’t like it. The opposite is true, but why put a lot of time and effort into learning a language that is degrading and where the maintainers obviously don’t care about the users. I am looking for alternatives and I think a lot of people are. That’s why I believe it’s dead. Golang looks promising.

                                                                    1. 3

                                                                      a language that is degrading

                                                                      Have you looked at the new Python 3 stuff? Things have been getting awesome, especially with Python 3.5 and beyond.

                                                                      1. 1

                                                                        I guess I haven’t really %]

                                                                  2. 5

                                                                    By some measures, python is currently the third most popular language on github, behind Javascript and Java: https://octoverse.github.com/. Just saying “Python is dead” is low-effort. Please back up your extraordinary claims or expect downvotes.

                                                                    1. 1

                                                                      Fair enough.

                                                                    2. [Comment removed by author]

                                                                      1. 1

                                                                        Python quiz: does a datetime test true or false?

                                                                        I’m curious where you were going with this. datetime values are True in both Python 2 and 3, as you would expect. Are you saying they shouldn’t be? Or that it’s ambiguous? Or something else?

                                                                        1. [Comment removed by author]

                                                                          1. 1

                                                                            That issue is with regard to time not datetime (bool(datetime(2016,12,6,0,0)) is True) and that behavior both intentional and in line with what you’d generally expect: the time type’s “zero” value is falsy. I think there are many things to complain about when it comes to Python (and I like the language!) but this is not one of them.

                                                                            1. 1

                                                                              in line with what you’d generally expect

                                                                              It most certainly is not, which is why that bug was declared as such and fixed. Midnight is not “zero time” in any meaningful sense.

                                                                              I agree that bug isn’t really serious criticism of Python; it’s a design decision that was insufficiently well-considered early on, then eventually revisited and changed. There are tons such in any language, and this one is only notable for sounding silly in summary.

                                                                            2. 1

                                                                              IMO some types can be coerced to a logical type legitimately and others can’t. I’d prefer that datettime.time objects raised TypeError instead.

                                                                          2. 1

                                                                            IMO Python is hated by so many hard core programmers because it’s not meant for you. It’s meant to be the programming language for the rest of us, and that shows in its design.

                                                                            1. 1

                                                                              Who do you mean by “the rest of us”? Have you ever tried to format a Unicode string in Python 3?

                                                                              1. 1

                                                                                u = ‘abcdé’ u ‘abcdé’

                                                                                Next problem?

                                                                                (Note: I realize this isn’t what you’re talking about, but - glib calls to glib :)

                                                                                1. 1

                                                                                  I guess I was trying to make the point that Python 3 isn’t that great for noobs either - despite being used a lot as an introduction language.

                                                                                  1. 1

                                                                                    I disagree, and would argue that universities and other teaching programs all around the world use Python as their intro to programming languages for a reason.