Closed pngwn closed 1 year ago
🎉 The demo notebooks match the run.py files! 🎉
All the demos for this PR have been deployed at https://huggingface.co/spaces/gradio-pr-deploys/pr-3421-all-demos
fixed the file output thing in 3.8
Spent some time thinking about how the Code
component should handle preprocessing/postprocessing because one of the nice things about Gradio components when used as an input is that they pass data into user functions in very intuitive ways:
gr.Textbox()
sends as a stringgr.Image()
(in default conditions) sends as a numpy arraygr.Dataframe
(by default) sends as a pandas dataframe. Similarly, your function can return data in the most convenient format for you and the output component will be able to infer how to display it. The user doesn't need to worry about putting the data in the correct dictionary format, as is the case right now with the Code
component, for both the input and output case.
So here's what I propose for the preprocessing and postprocessing function for gr.Code
component instead:
.preprocess(x): -> str
Code
component should only send the code string to the user function. This is going to be the most intuitive format for most users. If we want to keep the same payload from the frontend to the backend, that is fine, but in the .preprocess()
function, we should only send the string back.Code()
should accept a parameter called lang
that can be used to set the language. It can be updated using Code.update()
analogous to the other components parameters. .postprocess(x: str)
Code
component's postprocess should accept just a regular string. Again, for most users, this is going to be the most intuitive format. The Code
component should check if this string is an existing filepath and if so, treat it as such. Otherwise, it should assume it's a code string. We use this logic in a few places inside the codebase (such as here) and hasn't caused any issues.output_format
, which can be filepath
or code
. If provided, it takes precedence instead of the postprocess() method inferring the format.If you'd like @pngwn I can make a PR into this branch with these changes. (cc @aliabid94 for your thoughts as well)
How does the user function know what language the code is if we only send the code and not the lang?
Well the language has to be set somewhere in the backend, right? In demo/code
, you would read it from the Dropdown
. In other cases, the user would set the language using the lang
parameter in Code
so they would already know what the language is.
Likewise how does would an output code component know what language to display the provided code as (as code string not filepath), if that information isn't there.
I guess, feels clunky to map everything together like that when we already have all information in one component. I don't think sending the language to a code viewer / editor is unintuitive at all, quite the opposite. Users would expect to be able to pass code and the lang directly as that is data not app state imo.
In the output side, if you are working with a single language, you would instantiate the code component with that language, gr.Code(lang=lang)
and your function is very simple, it just returns a string.
If you are working with multiple languages, you would return gr.Code.update(code_string, lang=lang)
.
Dictionaries are annoying to work with in Python -- they don't have any typing info so a user couldn't easily know what keys a dictionaries are expected to have. They'd have to look up the docs to figure out the expected keys, etc. Even gr.Code.update()
is better since at least you have the type hints.
Fair enough.
Cool, do you want me to PR this? Or make the changes to this branch directly?
@abidlabs Sorry was sleeping when you asked, I attempted it myself. It works as far as I can tell but I dunno if i missed anything.
I don't think we need a custom preprocess if we're just delivering the content as is (a string) but maybe I'm wrong.
I just made the frontend + backend match because the frontend doesn't care how it receives the code/ lang, nor does it need to receive the lang every time we pass the code. So i just made it accept the code alone matching postprocess.
I added a static field languages
to gr.Code
which lists the supported languages. You can see it used in demo/code
. I think it is helpful to programatically get a list of supported languages.
I do not know how to document static attributes with docstrings, according to google it isn't possible cos guido didn't like the proposal but maybe there is a way.
I made some UI tweaks, made the download + copy buttons work. If there is a language selected they should use it as the file extension. If it is an unknown language then it just creates .txt
i do not know how to write tests for components or if we normally do that, so let me know what i should do.
i do not know how to write tests for components or if we normally do that, so let me know what i should do.
We do, we basically just ensure that .preprocess()
, .postprocess()
, .serialize()
, .deserialize()
are working as expected. I'm happy to write them if you'd like, or you can look at the other tests in test/test_components.py
as a template
Do we test with real files where needed?
Yes we do. We store these files in test/test_files
Beautiful component @pngwn! Everything works as expected and the copy/download are great touches as well
I've put some relatively minor suggestions on the backend above, but otherwise LGTM!
@abidlabs thanks! Will write some tests and address the comments.
Beautiful! I shoulda tweeted out that screenshot
software ppl love darkmode for some reason
@abidlabs I have added the interactive kwarg, added the generate_sample
method, and written some tests.
The component is pretty simple on the backend so they are quite basic to make sure it doesn't do something stupid but lmk if anything else is needed.
LGTM this is awesome @pngwn! Thanks for handling all of the backend stuff
Addressed most comments.
The padding of the code-mirror instance now computes its value from the style values of the block-label. Updating those variables will now update the padding for the code container.
Obviously these styles are absurd but just to show it working.
I tried the primary colour for the copy/download feedback but orange just looks like a warning. I've just use the default background colours instead.
Still waiting for elaboration on the file issue, so I can address it.
small documentation fix (thanks @freddyaboulton !). one last ci run and ill merge.
Adds code component.
Closes #1014. Closes #3423.
Still have a bunch of cleanup to do but thought I'd pop this here for testing + feedback.
Check out
demo/code
.