A Look At – and Inside – Textual

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone and welcome to today's webinar organized by jetbrains i'm paul everett python developer advocate and i'll be your host the topic for today's webinar a look at an inside textual and i'm very happy to be joined today by will mcgugan the creator of pi file system well does every anybody ever ask you about pi file system anymore um now and again yeah it's been around for a while though it's quite an old project profile system but also rich people ask you about that a lot right all the time all the time and now because he's so busy with open source he created another super hot super sexy mega popular package called textual which will be the topic of today's webinar will is busy making python packages look pretty thanks will for joining us thank you uh a brief introduction on this will and then we're gonna spend a little bit more time on it during kind of an intermission in the middle you've had a change of job status can you explain uh yeah sure so i'm taking some time off and possibly up to a year to focus on my open source work um initially maintaining rich and developing textual and but also contributing to lots of other open source projects just trying to make myself useful in the open source community uh speaking of open source community hi everybody in chat and i will say hi everybody [Music] in chat if you see me looking over that means i'm looking over at you while i'm trying to look at will as well today's topic is textual will what is it what problem is it solving and what made you start it um so textual is a framework for creating tui's and a tui is a text user interface it's um essentially a user interface that's within a terminal so when you're working the terminal it pops up in a face that fills the whole terminal and has very familiar things to it and you know scrolling windows and buttons and panels etc and but then you can exit and go back to the terminal again and i started this because um i've been developing rich for like um that's nearly two years now and some people have wanted to use it for more more dynamic things because rich just writes static content to the terminal and people have wanted to have things which which respond to key presses and and mouse buttons and stuff and i thought well i've got a big foundation there i can take that i can take rich and then i can add a text user interface layer onto it and design quite uh beautiful applications with it and well that led me down um a big rabbit hole and it was going to be very simple just rich plus keyboard control um but it's quickly growing into something that could be quite sophisticated in fact um you have a background in web front end development right that's right yeah so um it seems like a lot of your ideas that you've already implemented but then the next set of ideas which are all of us out here on twitter keep reading your tweets thinking good god he's doing this in a terminal but a lot of this is informed by css right that's right so i'm you know my day job for a number of years has been in web development and i haven't actually built many applications in the terminal so i'm taking all my knowledge from web development and see if i can apply it to terminal and it turns out that there's quite a lot of it can i mean a lot of css a lot of web development html and soft javascript frameworks can be applied to the terminal and and used in much the same way i'm almost almost for verbatim because there's been a lot of work done um for applications in the web browser over you know last 10 years has been you know volumes of work we've learned so much about how to build interfaces um but in the terminal we're still using very old technologies like 10 plus years old even older than that um so i want to take all this newfangled stuff and see what i can pick and choose and apply to terminal and some of it has been successful and some of it hasn't uh but i think there's still stuff left that i can take from the web world and applied to terminal we'll show some of it but it isn't just uh technologies to apply it's just kind of it's also wisdom and mindset um people there are some old people in python not naming any names but me personally my idea of what was feasible in a terminal is like 20 years old i see your stuff and it never occurred to me that a mouse over a vent could be fired in a terminal yeah there's been um the terminal can do quite a lot of things um there's quite a lot of functionality built built into there and also the terminals are getting faster they use um graphics technology the same type of technology used for video games um is used to render characters in your terminal and so it can throw quite a lot of characters at your at your screen and i turned out from some experimentation i could easily do 60 frames a second in the terminal which seems bizarre to even use the term frames per second in a terminal um but it can and yeah and so i can do i can do smooth scrolling at things which um i don't see very often in the terminal just to get people oriented right there was a question right now in the chat about can we use uh the react framework for coding uis this isn't javascript this is python but it's informed by a lot of the ideas that you took from working in the web and javascript frameworks right yeah so um i've used vue quite a lot um which is um similar to to react as some similar ideas and i've taken that that whole idea of things being reactive and seeing what i can do in the terminal and there's work to be done yet but it's definitely feasible yeah we will take a look at reactive in a bit okay with that background um in place let's have some fun uh the first question is um about questions we're already taking questions hey carlton i see you just popping up we're already taking questions in the chat we'd like to make this as conversational live as possible so if you have a question go ahead and ask it i'll do my best to keep an eye on it and answer questions either as they come up or we'll pause in between demos and take things from the youtube chat so please feel free to ask whenever you want to wait till the end we'll have some pauses after each demo we'll have this intermission section where we um kind of have to chat about some of the things will's doing and then we're going to come back and do a deep dive into some of the coding techniques such as the reactive thing will was just talking about so if you have a question go ahead and ask it always the first question i joke about this this is my five trillionth webinar and i've done this same joke five trillion times in a row i will only stop when it stops working in three minutes someone's going to ask is this thing being recorded so yes it's being recorded it will be published essentially immediately but we'll also in a couple of days put on our blog post uh to give you an easy link to it uh now that we've got this all set let's begin with the first demo switch over to my screen all right good um before we get into some of these demos i'd like to kind of set the expectations a little bit will i think it's safe to say these are early days for textual things are changing a lot and not everything is there such as windows does that sound about right um yeah windows support yeah but don't have windows support yet but there's a driver system so eventually there will be a driver for windows uh but right now linux and mac os great all right and we have a question about focus switching from the keyboard when can we expect it that's what i'm working on at the moment actually um i'm implementing a kind of an outline effect and so we'll draw a green outline ideas you've got something like alt and tab and you'll see a green outline around the thing that's focused and then you tab again and it'll move to the next one and then cycle through it and so yeah let's replay that whole thing uh bill um will's willing to start work on this if he gets some sponsorship for that feature that's what we should have said and then the sponsorship comes in and you publish the thing immediately um but yes there are things that are still coming but i see in chat there are several people saying they're going to write doom in texture what do you think about that i think once you can them run doom on something then then you know it's ready it's all right it's not crazy it would be possible actually yeah if you can run it on the macbook pro touch bar you can run it in textual so quite possible yeah um let's go ahead and jump into the first demo uh this is a little bit kind of like a hello world app um i'm gonna run it in uh let me get the terminal so i actually found this earlier all right i'm going to run it in pycharm pycharm runs these things okay but they have a little bit of artifacts because we don't have a completely high fidelity terminal but i'll run most of the things in place arm so that we can step through code i'm going to go ahead and run this and you'll see it appears on the right and as i press a key uh i should actually let me start this is the line that runs everything run is a method of the class color changer color changer is a subclass of app so run comes from app and we could navigate to it and see our way around and see it's a class method interestingly enough it's not an instance method um which gets into an interesting point about where the app instance is gettable from and then once the app is run uh will this is an async i o kind of run is that correct um that's right yeah it's all async i o and under the hood um we don't see any async in a weight there but um it can run with async and away yeah yep so it goes into the event loop from async io and it's got a listener for a key press so if i come over here and i press a key let's say i press the key k is anything on the fire nothing happens but if i press the key one i will change colors if i press the key two i will change colors etc because i'm getting into this event handler and it's what is available on the event uh it is a type of something called a key so what that means is i can autocomplete and key is actually a string so is digit is a standard python method on a string that says is this value a digit and if so we're going to set the background color now we're getting into the zen of textual why in the world is assigning a value to a instance attribute causing a redraw and a color change will you want to talk about that sure okay so um background is a reactive attribute um and all you have to do is assign to it you assign a style um so in that example you'll sign um on means set the background color uh takes a a number uh for the the color you want red is one i think um and just the act of assigning it we'll do the do the refresh because there's um we'll go into the system later but that's the basic idea you update the state and then the ui will refresh accordingly and that makes for some sort of very simple um development you don't have to do um get view dot set background blah blah blah and then self.view.refresh it's just simply um you set the background and then everything will update accordingly uh a question for the audience how many of you in chat have a background in things like react or vue or other systems that have this reactive programming style where you stay change some state and later in the render cycle things get updated let's see if we we have uh some answers on that uh last question on this well we have filled in an implementation of one handler in the possible event handlers what are some other examples of event handlers um oh there's quite a few and you've got mousemove so every time you if you move the mouse uh you'll get updated coordinates and you've got enter so when the mouse moves uh from a widget onto another widget you'll get an enter and you'll get a corresponding leave and so each widget knows when the mouse cursor is moved off of it and when the mouse cursor has moved on to it and there's also events like um resize so if you resize the window and all the widgets inside the components they will be resized and then they get a resize event uh to to inform them of their their new size and there's also you can also have a custom events so um most events i've talked about are issued by the application itself by textual but you might also want to send events from one widget to another widget and that uses exactly the same system so there's quite a lot of events there's a little bit of discussion in chat about some other systems and johann says uh this kind of stuff is really verbose in other tui packages textual is light years ahead here i'll get back to the verbose part in a second there's also another point i apologize i forgot to show you the secret little check box in pycharm to get things to lay out correctly in console mode when you're have a run configuration edit your run configuration and do this check box so that in the run tool windows output it pretends to be a terminal the reason for this is kind of uh you know we're reading the kind of streaming output from your python process to do cute and interesting things like linked to lines and tracebacks so um we don't play normally we don't play by all the rules of a kind of curses model uh to finish up on will's point about on key let me see if i can do autocomplete will do you think i can do autocomplete here um maybe not i'm not sure um yes you can because you actually have app as a method which i believe or message pump one of them has a a lot of these things filled in so app has yep on key right there so we were overriding a built-in event that might not work for all the events because they are issued um dynamically so you might not have the method in the base class okay uh i will stop the actually one last thing will you mentioned about reflow right yeah this is something blew my mind this isn't the best example to show but i'll go ahead and do it and it redraws you see the i'll go really narrow watch the right hand column it's resetting its width because it's getting i presume you were saying it's getting an event right that's right i'll get a resize event and then it will lay everything out and refresh the screen yeah okay we have a couple of questions you up for a couple questions absolutely let's do it all right um what's the relation between a textual widget and a rich renderable this is from carlton oh um so the widget um handles all the events and things and the dynamic stuff the rich renderable is literally how it draws to the screen um so under the hood um the widget will have a render method and that will return a renderable which um just draws it on on the screen so basically widget for the dynamic stuff uh rich for the the static drawing to the screen stuff that's coming if i don't talk too much will actually show a demo of a custom widget and i think it will make the will's point uh correct very clear we have a question from orr carmy i have a question about the handlers could you elaborate on the decision ha ha i'm laughing because i did a video talking about this and i was on python bites talking about will's use of magic the use of specific names as opposed to decorators um so a more i guess standard approach to to these event handlers would be to have a decorator the decorator might be called handler so you might have at handler and then in brackets the event and that would be quite recognizable to python developers um but i think i did actually start down that path but what i realized is um if you've got a a key event um you're probably going to call it on key in fact i can't think of any reason why you would call it anything other than on key and the you know the name contains as much as textual needs to know on key implies is a key event so maybe i could just use that to you know to catch catch the event and that's that's less code uh less boilerplate i don't like um boilerplate uh in code and by boilerplate i mean um any character or sequence of characters which is for the machine and doesn't express what the developer's intent is so i think um def on key is absolutely enough to um express the intent what i want from it so that's why i went down that route and i i acknowledge it is it's magic but i think for a framework you've got a nice um distinction between the framework and your code and in that boundary you can get away with magic and because it is kind of a black box i mean we actually encourage people to to look at the code and but when you're developing applications and hopefully it's done so well that you don't have to worry about the magic that's happened uh to get to that point um it's just from then on it's just it's your code and some other things you did and we'll uh there was a tweet the twitter thread probably around three weeks ago where will talked about boilerplate removal and had a whole bunch of side by side and solicited opinions and you did some other things like there's a question about um is this async why do i not have async in front because you make for some things it's optional you will detect whether it was preface with async you also make it optional to have like here on this next example i could have provided an event but i don't need the event in other systems i would have had to say event because it's going to be passed to me but you actually sniff at the signature to see what it wants that's right i mean i guess um that was influenced by the fact that javascript is is like that it's more forgiving and if you don't have the async method it will just be called as a regular method and if you don't put the the parameter in the signature then it just doesn't doesn't care much about it and i know that's not familiar to python developers um you might you know you might be surprised at that but again that's um that's boilerplate if i don't await anything then the async is boilerplate it's like um i have to write it um but it doesn't really express my intent as a developer and also um if i don't need the event um i would still have to type event and so having to type that is to my mind's boilerplate yeah and i wouldn't approve of that in anywhere else actually if i saw that in a code review i'd give it a frowny um you know but when you've got a framework and the boundary is very clear between the magic and your code um i think it's excusable um i agree i i very much agree and um that that gets right on the edge of dependency injection but i think you've done it in a way that's simple and obvious let's go through rapid fire round of questions and answers so we can get back to demos um how attack type completion this is from tushar how will type completion work with runtime methods i think the answer is it won't um can you expand on that what sorry runtime how will type completion work with runtime methods i i guess custom methods uh static analysis can't get to that right um oh um yeah it um well because it's the framework that calls these methods and you never call them directly and so again you just have to rely on on textual um just working up to that point uh but once you're in the method um and uh my pine stuff can can work with what it's got i will note that um that was one of my first surprises will uh said i'm doing magic and it works with my pie which immediately got my attention um i'm a big supporter of of typing my pi and any any tools like that which can look at your code and spot errors before you do i'm massively in favor of it um so i am very much aware when i'm adding features i don't want to break any my feet my stuff but i am surprised that how dynamic um textual is and how well my pi actually manages to cope with most of it yeah okay would it make sense to have empty methods or the ones that are missing to help auto completion that's right on the edge of an abc which you didn't do for the app class yeah and that's not a bad idea so there's um some of the events and messages you define yourself um so that you won't be able to put them on the base class but you could put the the standard ones that key mouse etc on the on the base class but you also have the problem you know i've done the the sniffing where it can be async or not async if i put if i put it on the base class if i put an async on the base class um my i think my pi will complain complain if it's not async on your class so i think that might be a problem i mean it it's a good idea and i would like to like make it more auto completable so that um you don't have to look anything up and when you type it'll give you suggestions um so i'm going to look into that but it is something that is quite dynamic so it might not completely be able to work with that level of tooling for the record you have something that uses protocol right uh yeah yeah i'm a big um i like protocols over classic inheritance um you know that whole um is a relationship and um and although all that kind of that hierarchy and diamond inheritance and stuff um i'd rather not think about it and rather not ask um people using textual to have to think about it yeah um is textual asynchronous does it use async weight it does yeah um so under the hood when you do run it'll launch async io it'll run it in a task and actually every every widget every component um is an async io task that's running an event loop uh tashar we will get into renderable equal view widget equal controller later paul mcguire asks if there's any compiled or cython code any compiled c code or cython there's no not at the moment um i do plan to do that um because um i would i want textual to run on quite low powered computers the type of things that you might run things in a terminal with and my base will be like um the lowest powered raspberry pi if it works and raspberry pi then it's fast enough if it's not and i suspect i expect it won't be or it could use a bit more optimization um i'll look into um syphonizing some of the critical path code which is probably the render code that the code which is um you're calculating 60 frames per second right now it's the last thing you need yeah it actually runs at 120 frames per second um on my macbook but um i don't want to require a macbook to run it so i am going to look at optimization eventually but so far um it runs pretty well all right and then last one there's some more questions but i'll do the last one for now henry points out on key is a special name a magic string henry i agree that was the thing that i had a tough time with um and so far i've been okay with it even though in like the last 20 years of my zope pyramid etc existence i've not liked that uh so far i think the choice is pretty good in this case okay onward let's go to another example and this is one that uses a widget which brings in some machinery and what this one's going to do is when i run it i get a placeholder watch at home what happens when i mouse over it mouse focus terminal are you kidding me how can this be how can this be possible but before we dive into everything that's happening in this app will when you started textual did you know mouse over was possible um i did actually because um from h top um you know h top which shows you your processes and things and i noticed you could click things with a mouse um so i thought terminals must support mouse control so obviously i looked into it and you can switch the terminal to specific mode which means it will send um mouse events through standard input which you parse and turn into coordinates so yeah i was um knew it was possible and uh yeah added it to textual um i don't want textual to be um mouse only though i wanted to be a keyboard first um mouse should be like an adjunct something to make it a bit easier a bit more um accessible to explore um but it will be um definitely keyboard oriented eventually okay let's die let's pick this apart a little bit i'm actually going to start at the bottom this line is a keyword argument to run generates this handy little thing i've got tail minus f on this so that as stuff happens i have something to look at which tells me the framework side that's in talking to your app is able to log copiously stuff about what's going on is that a correct way to put it uh yeah absolutely um the problem with debugging text user interfaces is you can't just write stuff to the terminal and because obviously the logs would just cover all the the application um so i have um a log file which you can enable there log equals textual.log and you probably want to enable that for everything and you can tell that log um in another window in another terminal and it will show you the events so at any event which is sent like a key mouse etcetera it will write that too to the terminal and you can uh you can debug it that way yeah uh what i do for debugging i'll go ahead and show that now we'll do a much bigger example of it later is set a breakpoint this is actually how i went on my exploration i recorded two videos that i tweeted out about a look inside the code and that was the way i went on my learning journey of textual i ran this under the debugger and it stops on this break point and i can go backwards into the framework and look how did i get called and along the way what is all the stuff what's all the state at each point so for example it needed to get a callback what callback was it it was simpleapp.onmount so this is where the sniffing happened um and it called actually called that method got a result and here is the little thing will was talking about you didn't have to put we did here we put async on it but if you didn't it would go and await it for you no i'm sorry if you did it would await it for you if you didn't it would just call it so i just kept walking up walking up and seeing all the things that got to like the innermost loop so from a debugger perspective in an application like textual is a really helpful way to discover things back to the demo um well this is a like a life cycle event this isn't necessary i mean it's an event handler and we could ask for an event i suspect but this is something that happens at startup right and so anybody who's comes from a world of react and react components understands life cycle methods is that right um yeah that's right um so the the on mount event is the first event that gets shown uh when the you go into terminal mode um there's also a load event which happens before you get to terminal mode so load event you'd use to load configuration and things and when on men on mount is called you've got like the full screen terminal mode available so for example i could probably learn more about onmount by searching for um let's see in the examples [Music] in i'm wondering if they're if it's on app might be in is it in the message pump maybe um beyond applications so i'll be in the examples okay so um now on to the one that's really important what's a view if you use a specific kind of a widget um a widget is like a visual component and a view contains uh other widgets so it's used to arrange uh widgets and and there's different um layout schemes you can put them in a in a box or you can dock things um but the default is um yeah they're a dock view which allows you to um dock by dock i mean take a widget and move it to one side of the screen with a given given number of characters all right so uh my app has a instance attribute called view which is really a property and you could you could replace it with a different kind of view instead of the out-of-the-box stock view is that right um the app contains just goes with the dock view but if you wanted a different kind of view you could dock that other view so you might have it okay a grid view which you could dock into the application and have it fill the whole thing all right then what we're doing is we're docking a placeholder docking is kind of a layout concept which people who might have used tkn or something like that and packing might understand a little bit about and then placeholder is a widget so this gets into discussions about widgets and out of the box widgets and how they get docked can you talk about that real quick um so a placeholder is um to be used when you haven't implemented the widget yet but you want to see how it would arrange in the screen and um that will handle and when you when you dock it it starts an event loop so it starts an asynchio task which is um processing events and that will receive key events and an on mountain all the other events that we've talked about yeah i think of it i don't know why but it it smells a little bit to me like when i'm using css so what the hell is going on so i put borders everywhere yeah and then i can see the layout of everything and placeholder kind of makes me think of it kind of reminds me of that as like where are my boxes oh okay there's my boxes yeah yeah it's pretty much it exactly like that um so you can design your application before you've implemented all your widgets here is a better example where we have actually three placeholders i wonder if it's because i don't have enough room yeah right reflow how about that so this is the first line is docked with the edge on the left and given a size and then we dock two placeholders so the art doc can accept more than one argument uh more than one positional argument and then a set of keyword arguments and these are dot to the top and then flow top to bottom is that right that's right yeah all right great we will uh pause there and take some questions because we're really backed up on questions um okay is it a carlton asks is there a runtime costs the introspection um there is yeah um so if you do is it waitable um there is a little bit of extra work there um it's fairly negligible i think um i think i do cache it if i'm not i could do so i only have to do is awaitable once uh for every time you know the first time you access it um so i think yes there is but it wouldn't have any impact really yeah uh it would be interesting if you do go into more sniffing i have a system that i've been working on for a while that has some similar ideas and at start-up time i sniff everything and turn them into name tuples so that i don't have to sniff them ever again yeah you can do it in advance or or cache it exactly so um there is a very small runtime penalty but you can sure make that disappear via caching we will stumble carlton we will stumble across some other optimization things will does to kind of store cached information about the last value on certain things so that things that really haven't changed don't have to recompute um okay is the placeholder being rendered through something built into rich uh yeah and so the placeholder is is a rich renderable um it's a panel which has got um a pretty prettiest object which pretty prints um a regular python object um so yeah you can render exactly the same thing enrich outside of textual carlton also asks one event loop per widget why rather than a shared loop um it's so they can work independently um they can each widget can update it's only its portion of the screen and respond to its own events and doing it it's its particular um schedule and it can handle its own lifespan etc and the actual rain interest screen is done through the app and that makes sure that everything is done in a very logical order so that nothing tries to overwrite each other and stuff um but yeah i mean event loop per widget um is quite familiar if you're using uh javascript i think javascript frameworks kind of work like that okay we'll uh we'll go on to a next demo if you have any more questions uh fire em up i'll get to them after this we'll we're gonna try and speed up a little bit i'm gonna throw you a curveball because this one doesn't actually work correctly oh okay it's also i mean it's not pycharm console related it's also in the regular terminal um but still it's very useful to talk about because of our friend reactive okay so i'm going to run this and that was not suppose that wasn't the wonder if there's nothing in my code that did that um i did release an update like two days ago um i could very well approach you you feel like you feeling brave um oh okay yeah go for it what's the worst that could happen any dependencies change or anything no just a small code update all right okay can't believe all right we'll skip it we'll just talk our way through it this is an example of an app with a custom widget at the mount portion of the life cycle and we'll just talked about there's a load event in the bootstrapping there's kind of a mount phase as well in the mount phase we're going to get a list of hoverables in this case 10 of them and we're going to dock all 10 of them to the top what is a hover it is a widget so it subclasses from a mostly already made thing that has a renderable or method render which says it will return a panel and then the panel has some text that wants to display and some styling that's what i really wanted to show is um this connection to here let me see if it's let me just confirm that it's it's uh [Music] oh here all right i'll skip that that when you mouse over just this widget and what will you were just saying is because it's not one big event loop and things have kind of their local part of the tree or whatever you know when you have the focus and when you have the focus when you are when you're moused over this value will change and then in the next render loop which happens 120 times a second we're going to change our color is that the right way to put it uh yeah pretty much um yeah and how do we assign this value we just have an event when the mouse enters when the mouse leaves we change this value how in the world does this work reactive is a python descriptor which is a magical frameworky thing like meta classes and some other things in python and when you make actually will is this this is a class attribute not an instance attribute is that right um it creates an ins uh instance attribute that's right so it's bound to each each instance of hover so all of these all ten of these have a separate instance of reactive is that right um so once the magic kicks in that this is done at the python level um the instance will have a mouse over a separate mouse over for each of the hovers yeah and what it lets you do is intercept the setting and getting of an attribute value and then will bakes a whole bunch of smart textual logic behind this you don't have to think about it and then later uh python and textual call you they gather up everything that's needed everything's available in scope and they call you with things like the message target um the value that's actually being passed we can actually get if we need to we can get to the running app but this is the stuff in the python descriptor the python descriptor protocol says your descriptor can have a get an ascent but can also have a thing called a set name will can you explain the difference between set and set name um set name is called uh when python gives the attribute a name so that's so the descriptor will know what the the name of the thing is you're you're creating uh which i need um internally and so take a look at the magic that happens i say magic this isn't i mean what was that 20 lines of code this is not crazy and this is a normal thing that's been in python since python 2.2 or something descriptors when i make this assignment it is triggering this is that correct that's right yeah and look at the kinds of things will now is able to do in the background he's going to see if there was a value a second ago let's go get that to see if it's actually changed if it hasn't changed i'm not going to do any of this stuff maybe there is with will's kind of special naming thing maybe there's a validator function that needs to run on this widget so in this case will what would the name of the method be for mouseover validate underscore voiceover and it would be past an event no capacity the value um if you give it one value then it will get the new value again if you have two parameters then you'll get the old value plus the new value all right and um it will so it'll validate it it'll run that function to see if an exception is raised or something and then it will check the value and then do the magic this is the reactive system and this is where it says who is watching this value who wants to be told when it changes yeah that is really cool for a way of programming i'll jump into that and check watchers is actually a class method so it needs to be passed in its information and we'll have some policy for going to look for watchers watchers also have a watch under variable name is that right that's right yeah and same same notion um convention over configuration so if you want to watch through its watch underscore through i mean why would it be named anything else all right henry points out correctly that the set name was a pep that was in some python 3 5 or 36 or something descriptors themselves are pretty old yeah so this this whole idea of um a value actually changes and when we say change i didn't have to call check watchers i just assigned a value and stuff happened in the background and in the background it does a bunch of smart things like how do i refresh how do i repaint all that other stuff it's all part of textual's framework really got anything you want to add to that um yeah so the um the refresh doesn't happen instantly right and i know we're calling object.refresh there but what actually happens is it sets a flag that says um this object needs to be refreshed and then once um once the widget is processed all the events um it will check that flag and if it needs to refresh then it will paint the screen and the benefit of that is um first of all if you're doing a lot of work and you've modified several attributes which require a refresh uh you only get one refresh because it you only need a single refresh to repaint the screen you don't want to refresh 10 times so um people who have any background with react know the whole render loop thing is very similar you don't actually render you just say to the system next time you the next clock tick or whatever comes around here's something to do okay i'm going to stop here go through some questions and then we will do um we will skip the next two demos go to the inner meso quickly and then do some inside the code because we're behind a lot i knew i would be i know i would uh let's see do you need an async generator there instead of a non-async one perhaps and i think henry must be talking about this um no no that's um that's just constructing it so that bit doesn't need to be uh async that creates a generator of um hovers which are constructed uh henry let me know if i was pointing at the correct or the incorrect uh name tushar asks how he can help with textual guess what that is part of the intermission so if you could put both of us back on screen uh side by side and uh get rid of my screen temporarily we'll spend a couple of minutes talking about um some things about his sponsorship model all right great okay everyone in chat listen up on this part this is how you can help multiple ways you can help uh will has changed to a model where he is doing open source development and he's using github sponsorship is that correct um that's right yeah i'm trialing that i've got some sponsors already and mostly from from rich which is very much appreciated yeah i signed up for a monthly sponsorship not as much money as you deserve but it's a start uh and i was doing it for textual not rich i haven't really jumped into rich yet so with github sponsorship you can do one time or recurring well is that correct um that's right yeah you can do at one time if you just want to say thanks for a bug fix or something um or recurring if you would like to support my work uh going forward yep and kind of give your your thinking about um you know why you've made this change go into a little bit more depth about why you've made this change what you hope to prove not just for yourself but maybe is kind of a generic example that this could work um so i've made this change well for kind of multiple reasons and some of it to do with the the work itself some of it um sort of personal reasons etc um but basically well i've always enjoyed working in open source and i've worked i've done a lot of work over over uh 10 plus years of for for other people and which i do for free gladly because um i enjoy it and i want to take the opportunity to just do that full time uh people seem to really appreciate rich and now they're quite excited about textual and i'm excited about it and i would like to um do it justice um i've been doing this stuff um part time and there's some things you just really need to have um solid time on your weeks and days to do it justice um having looked at the outstanding tasks for textile it's quite daunting there is um quite a lot of it and it'll take quite some time so i would like to um devote quite a lot of time to it and um full disclosure i do think there will be some commercial applications for textual and those will be quite far down the line once it's in a more complete state and it's um got all the features you need in all the documentation and so i think the next three to six months it'll be purely me working on on textual and other open source projects um so it's an exciting opportunity for me to do something that i love and um hopefully help the the community um i should mention that i did say there'll be commercial applications hopefully down the line but texture will always be uh free and open source yep so yeah it's actually good for us if you have commercial applications because then that gives you the resources to keep giving us something awesome for free please everyone remember i mean this has become almost a crisis for open source we have all become such takers especially companies companies have become such takers that don't really want to give back why should i give back when i'm going to get it for free and then it becomes a tragedy of the commons let's use will as an example and prove that this can work with someone who deserves for it to succeed um will is not just giving us great code he's actually volunteering his time you can go to his calendly get a 30-minute slot and he'll review your code without charging you anything just as part of his year of open source so try to give them some money try to prove that this can work so that other similar things can work if you can't give money there are things in textual that will has identified i believe as good starter tickets is that right uh yeah i've added some um tickets which um someone who's not that familiar with textual could pick up and contribute to and i will be adding more of those in the future and i'm happy to um mentor anyone who wants to get started and you've got a label on them right yeah um i can't remember what it's called it might be good first issue or um it's the health wanted help one point i yeah so if you go to github.com will mcgoogan textual slash issues you will see a list of issues an already daunting list of issues and some of them have these tags on it um if you want to uh participate but don't feel comfortable yet on code will neat has kind of stubs for docs and so there's some dock stuff that could be done if you want some deeper level stuff i suspect will would like some help getting this working on windows is that right uh yeah um i will tackle that eventually um that would be a um a good one to put a help wanted tag on that yeah um that would be interesting it's not that's not an easy one um so that would be a challenge for you but there are some reference examples of similar systems that have some decent windows full screen terminals yeah yeah so um definitely prior art there's lots of other open source out there and you can um pick some of the features and things i mean um i'm a big fan of prompt toolkit um they use the author's name uh camera is it jonathan slanders um apologies have got name wrong but um his code has been a big big help writing textbooks had to figure out all the uh the terminal magic to to start um processing mouse events and things so i i refer to lots of other open source code i'm the beneficiary of open source code so yeah i very much approve of um people um not stealing because it's not stealing you're giving it away not at all one last point before we go back to my screen um you also have places where people can chat in last week or this week i think you settled on uh gitter is that right oh that's right yeah um getter dot i am so i needed a way to um correspond to people interested in textual um so we've got github discussions and github issues uh but sometimes you want a more kind of real-time conversation and i will say the discussions are pretty good there's a good number of topics in there already they get yeah i like discussions yeah they're they're very good for um sort of um in-depth technical exchanges yeah all right hey sasha could you switch back to my screen while we take two that's too fast you're supposed to take more time on that well we take two quick questions carlton asks we'll make this fast how stable would you say the public api is right now carlton you're not asking that question are you um if by stable do you mean from version to version um i would say not at all um i'm completely um because it's a zero point version some verse size you can um break things so if you're using it um pin your version numbers to right down to the last digit because um i could may change everything next version try not to freedom time for will right now freedom to change yeah and then orr asks um a question that i'd asked you last week about how should textual apps be tested um testing is still something i have to figure out i assume you mean unit tests um i have to figure out um testing with async io i think there's some um developments in the in the pi test world to do that but how you test um applications you've written with textual i've still figured that out um testing is obviously very important um so i'll be doing a lot of work in that but i'm afraid i don't have a different advanced stores yet okay let's do another demo and this time the demo is well let's just say it it's sexy it's actually sexier outside of pie chart so i'll run it outside of pipe charm then i'll run inside pie charm set to go and use a debugger set some break points and poke around in the machinery and see how things work and then we'll do the conclusion get out of here i'm going to do my terminal clear that because that's ugly should have tested that this morning and i want to actually run not clear can you believe it a desktop calculator in a terminal which reflows correctly so if i want to say two plus two your choice of colors are just appalling right um the contrast ratio over here i can't even see what it's a plus i'll say plus three on my times three equals five so this is basically the display of the calculator it's a widget all these things are widgets how do they kind of talk to each other and then how does the display get updated based on the state changes let's go take a look so i'm going to put that go back to here so i'm in the calculator app but it's actually a grid view what's a grid view it is a subclass of view which means somewhere later on down here uh it's being docked into an app so the calculator isn't the app the calculator is something docked into the view of an app it is a grid view will should we think of this like css grid it's exactly like css grid yeah i've implemented them i don't know about 70 of css grid there so um let's let's not think so much about how it looks let's instead think of this like a react application with redux and there's some state that's getting changed and then the ui redraws itself based on that state so i'll ignore all this you know colory crap and focus instead on these two class attributes display and show ac mostly i'm going to focus on display that's the thing that shows the current number and it's reactive it's an instance of reactive with an initial value of zero just for fun let's get an initial value of 10 come back over here will do you think i will see 10 i'm almost certain you will no i must set it to zero on on mount or something okay all right i should have checked that before trying so uh actually i didn't save i didn't do an explicit save i counted on pycharm doing its own save so that's we'll we'll say that that's my fault for not saving um so what's really happening here there's something called display uh-huh will with his magic naming service has something called watch under display with a dot string which tells you exactly what's happening whenever this changes this is executed so when might this be changed here you go there's an assignment there's an assignment all these assignments so what i want to do is i want to see how will is doing this so i'm going to go into the system itself and i'm going to go into let's see set under name i'm going to put a break point in here i'm just going to walk through it a little bit i'm going to run this under the debugger okay um it would actually be in here that it's starting to fire itself up but i've stopped here and the name of the thing is visible well that's one of will's things that's not my thing so i don't want to really stop here and i don't want to press go go go go a hundred times so i'm going to change this to say name equal display and say hey debugger keep going now i'm on my thing then now this is where the python descriptor protocol is actually doing its thing for set name on my thing and let's take a look at this specifically let's see what is owner owner is calculator the grid view this is the thing that blows my mind about the scriptures is i can get back to the thing it's bound to ordinarily i wouldn't be able to it's just an instance and scope i'm out of the scope now i can't get back to the class or instance that i'm bound to but question for you in the audience am i bound to the class or the instance i'll give you a hint so we'll tell the audience the answer owner is the class of calculator or the instance of calculator um it's the class i believe correct all right as i step over this stuff i just uh none of this was true because there wasn't a magic method compute under display we just had watch under display if there was a compute under display this is badass will will let you have like dynamic calculated values that are stored on the object so that once they're stashed they aren't they aren't stashed again i guess until they change or something like that all right so i skipped over all that and now i'm going to do that little dance where i've got the name and the fake name so that i can disambiguate them i'm going to store the internal name this so this would be under display is that right that's right yeah i'm going to store it on the owner and that's all pretty cool so i'm going to go down a little further and set a break point here and continue and this is one of the first assignments and i am on uh let's see the object is the instance of is a reactable well that's different than reactive so will what's reactable um that's the type um actually i believe a yeah the type that can have reactive attributes which is widgets or an app right so that kind of gives you an idea of the scoping rules for reactivity that they are within a widget or within the entire app but you can't have a widget watching another widget's values is that correct um via reactive descriptor no yeah which actually lends to the simplicity of it meaning i don't have to make a decorator to watch something i just on the thing that's being defined i put a special method yeah i think there is actually there's a watch method um which you can watch um another object's uh reactive value um but the reactive descriptor um it's only for um the attribute on that same object so a similar kind of thing we're going to in the process of setting this value we're going to see if there is a previous value and see if there's a validate function we're going to validate if necessary if the value is actually changed and in this case i think it has yep we're going to go in and we're going to fire all the watchers same thing we saw before all right uh we'll we will stop there on demos and stuff there's a lot more machinery in here we looked at compute we looked at watchers there's the message pump for the event model just at a high level can you think of a couple of other things people might be interested in the architecture um that's most interesting stuff actually the um the message pump uh watchers um i'm sure there is but i can't think of any at the moment uh we will do a couple more questions uh on the way to wrapping up if we could go ahead and switch to having will and me side by side okay a couple of comments from people saying that it's actually my fault for having a white terminal otherwise the contrast in the calculator would have been just fine it's not it's not your fault exactly um i think next time i'll explicitly set the background um to black as johann says it's a self-inflicted wound by me uh tushar points out as if the descriptors weren't enough you can magically create an arbitrary number of descriptors holy mother of magic have you ever seen that in the wild um you can create as many descriptors as you like really um i think what to share might be saying is um dynamically create programmatically create right all right and matthew points out he really liked using rich's renderable type to indicate an object as a dunder rich or a dunder rich under renderable yeah so um anything that works in rich can can work in in textual um so you can use existing uh rich components um there's quite a lot of them out there already but it's also quite easy to to build your own uh matthew also asked would tui developers benefit from setting a color scheme for their apps instead of relying on the ansi color codes yes it's going to be part of your css ideas yeah um absolutely there's there's a lot of benefits um and and setting your own color scheme um i want in the future to do things like fades um but you can't do fades uh with the ansi color scheme because you can as a um textual can't know what color you're getting and the first 16 colors don't know if you guys know this um you can ask for red but you know you might not get red or you might not get the exact same shade of red so if you want to do a fade you can't tell what the starting point is um so if you set a color theme to begin with um then people do like nice fades uh possibly crossfades things like that and in the future we'll have css and textual and that will allow you to modify not just the colors but um also things like um margin and padding and border and all that good yes will means that he actually is going to have the equivalent of a css file with css syntax instead of having to do things in python yep quite a lot can be done um yeah you can do things like um hover effects you know and some of the demos transitioning yeah hover effects transitions all sorts of or animation i should say yeah okay uh now on to the best two words in any presentation in conclusion uh before we wrap up will what's next for textual and would you like people to get involved um next thing development wise is um css that'll be the next um next week or two um i'm going to be parsing css and modifying the attributes on on widgets so that'll be interesting to see um how to get involved uh lots of ways to get involved um jumping on on the discussions if you have ideas i definitely hear about them because obviously i want to hear uh use cases what what do you think you'd want to build with this that will influence um the direction that textual goes in or jumping on um getter.i am um or yeah bugs of course i want to hear about uh bugs um just contribute um in any way that you you feel like you'd like to this really is a case where you can just contribute there's not a whole bunch of warm-up needed it's re it's all even though it's kind of just started it's well organized code and there are easy and obvious places to jump in yeah we should write them again because this could be a cool thing for python yeah and right now is the best time to uh jump in because any you know you can have quite a big impact um if you have a good idea i'm going to run with it and then more ease is more easily implemented near the beginning of the project than it is um at the end so um yeah keep it coming and if any of you are really good at python pi test async io jump right in and write some tests yeah tests uh need to be done yeah that's it's a big chunk of work um it'll be worth it because um i want textual to be super stable rich is 100 tested and it's it's really quite stable now um textual isn't i think we're still just like um five percent some of the um really simple stuff to test a low hanging fruit is tested and but a lot of the the more advanced stuff well because it's it's um unstable at the moment it's going through lots of changes it's hard to test um but still i've gotta need a lot more work in the testing going forward okay let's go ahead and wrap up will thanks for joining us for kind of this two for the price of one both beginner and intermediate uh tour through textual and really just thanks for everything you do for python thanks it's been great it's been fun now if you'd like to get more information on pycharm please go to our website at jetbrains.com if you haven't already please check our pycharm blog lots of stuff starting to happen already on our blog you can find up-to-date information about pycharm news and releases and events in addition to educational resources such as this webinar we're gonna have a good webinar in october kind of a good webinar in november it's going to be a string of good webinars we'd love your feedback on this webinar we read the survey so please contact us on twitter or if you get the email about the survey fill in the survey we will take a look at it i will actually share some of your points with will if you have any comments for him and we will send the email to the survey in just a little bit so that's all from us today thank you to our esteemed guest thank you to you our esteemed viewers and participants thanks everybody for joining hope you have a nice day thanks everyone you
Info
Channel: PyCharm by JetBrains
Views: 2,260
Rating: undefined out of 5
Keywords: pycharm, webinar, jetbrains, textual
Id: 1kTWxamIJ_k
Channel Id: undefined
Length: 76min 49sec (4609 seconds)
Published: Tue Sep 21 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.