Will McGugan Profile picture
May 14 18 tweets 3 min read
A while back I was struggling to manage async creep in Textual ("async creep" is the tendency for all methods to become async).

A *single method* in asyncio allowed me to reverse that decision, and prevent asyncio creep. #Python

🧵
First, the reason why I disliked asyncing all the things.

The "await" keyword is boilerplate. Its existence is mostly for the language and doesn't help the developer.
Whether you do "await foo()" or "foo()" you are invoking the function. The majority of the time the await keyword is a burden placed on the developer to remember wether it is a coroutine or not.
Now that isn't entirely accurate. Seeing those `await` keywords is an indication that Python may run some other code while awaiting for a result.
And when I'm working on framework code, that can be beneficial. And certainly a boon over writing threading code where there are no guarantees when another thread may run.
But outside of the framework, a developer building a Textual app just wants to call the function. And I don't want to force them to remember to make all their functions async, and await all of the API.
There's some great tooling that helps with this, but it's still extra to think about and type. It's almost always boilerplate.
Originally I didn't think it was possible to avoid. Textual is built on async and if you wanted to use it you would have to master asynchronous programming.

It turns out it is quite easy to avoid with that one trick that framework developers don't want you to know. 🤡
Every component in Textual has a "message pump" which is an asyncio task reading messages from an asyncio.Queue.

This Queue object has a "put_nowait" method which adds a message to the queue, but importantly is not a coroutine (hence _nowait).
Many of the Textual API functions (regular non async) call put_nowait to add a message to the queue.

This message is then picked up by an asyncio task which results on an action. It's essentially a bridge between the async and sync domains.
So most of the Textual API doesn't need to be async. Developers who aren't familiar with async and await (and there are plenty of those) could still build a Textual app.
The downside of "put_nowait" is that you can't get a response from the messages, as it will be processed in the near future, but the caller can't say when.
For Textual this doesn't seem to matter too much. The application code is independent from updating the screen. If you update something it is enough to know that the "screen" will eventually update (within a few milliseconds).
Textual API methods that do need a return value, generally don't need to do anything asynchronous anyway.
The other technique to avoid async creep is something I've talked about before.

Textual will inspect message handlers to see if they are coroutines or not. If they are, they will be awaited, otherwise its a plain old function call.
So as far as Textual is concerned both these are valid:

def on_mount(self):
...
async def on_mount(self):
...
Ultimately in Textual I would like async to be available if the developer needs it, but optional if the developer doesn't need async or doesn't understand it.
This Tweet ramble brought to you by a very smooth Papua New Guinea Arabica roast.

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with Will McGugan

Will McGugan Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @willmcgugan

Apr 19
I recently asked for folk to fill in a survey regarding terminal usage. Over 1000 of you responded!

Here are the results.

First up, how "old are you"

Really surprised that the peak was around 40-ish. And there is a fairly decent contingent over 60!
Next, "what best describes your job".

This will be heavily influenced by the list I provided. Lots of web developers.

Also shows it is impossible to narrow job titles in tech, of which there are *many*.
What is your primary language?

Perhaps not surprising, given my followers but it is Python by a mile. When I started Python, it would be rare indeed to see Python as anything but a secondary language,
Read 29 tweets
Apr 16
Been encoding videos for the new Textualize.io site. This video is going in the hero section. It's a teaser of Textual. I suspect we'll update this video from time to time when new features come online.
It looks kinda cool playing within a perspective adjusted terminal!
Recording that video was a little painful. Problems fitting it in the right aspect ration. And I kept getting a black bar at the top of the video, which I figured out was MacOS hiding the camera notch.
Read 4 tweets
Mar 25
I'm a bit obsessive about naming things in code. To the point where I hesitate to implement something because I don't have the perfect name for it.
My objects are simple nouns, my methods are verb if they act on the object, verb+noun if they act on another object, properties are always nouns.
The perfect name for something can influence the code I write, to the point where adapt my solution to fit better naming.

This fells a little perverse. Shouldn't the perfect solution be absolute priority when writing code?
Read 11 tweets
Mar 24
The next version of Rich will be able to export console output to SVG!

The attached image was produced this way (i.e. it is not a screenshot of any terminal).

It's as easy as:

console.export_svg("out.svg")

@nwkautomaniac
Rich-CLI will inherit this feature. I'm imagining a --export-svg switch that outputs an SVG of anything you print with the `rich` command.

github.com/Textualize/ric…
And so will Textual.

How cool would it be if you bind the F12 key to take a SVG screenshot of a running app?

github.com/Textualize/tex…
Read 4 tweets
Mar 24
A conversation with @njr0 on #Python typing got me thinking.

Many people (plenty of experienced devs amongst them) don't like typing.

Why is that?

🧵
One reason, which I somewhat agree with, is Python type annotations are a wee bit verbose. If Python was ever "executable pseudocode" then type annotations break that. 🤷‍♂️
I think that's fair criticism. The annotations are verbose. It's improving with recent Pythons, but it does make Python look far more "computery" than it used to.
Read 12 tweets
Mar 6
My name is Will McGugan. 👋 I am the creator of Rich and Textual, and the founder and CEO of Textualize. At the end of last year I took a year off to work on my Open-source projects and develop an idea that I believe will allow the terminal to eat some of the browser’s lunch.
Turns out this idea was compelling enough to attract some sweet sweet VC cash and I am now hiring a third Python developer to join the company.
At Textualize we offer a competitive salary, 33 days holiday a year, a health plan, and standard benefits. But more importantly, a friendly and supportive workplace that values work-life balance.
Read 24 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us on Twitter!

:(