gradio-app / gradio

Build and share delightful machine learning apps, all in Python. 🌟 Star to support our work!
http://www.gradio.app
Apache License 2.0
29.84k stars 2.22k forks source link

add code component #3421

Closed pngwn closed 1 year ago

pngwn commented 1 year ago

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.

gradio-pr-bot commented 1 year ago

🎉 The demo notebooks match the run.py files! 🎉

gradio-pr-bot commented 1 year ago

All the demos for this PR have been deployed at https://huggingface.co/spaces/gradio-pr-deploys/pr-3421-all-demos

pngwn commented 1 year ago

fixed the file output thing in 3.8

abidlabs commented 1 year ago

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:

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

.postprocess(x: str)

If you'd like @pngwn I can make a PR into this branch with these changes. (cc @aliabid94 for your thoughts as well)

pngwn commented 1 year ago

How does the user function know what language the code is if we only send the code and not the lang?

abidlabs commented 1 year ago

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.

pngwn commented 1 year ago

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.

pngwn commented 1 year ago

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.

abidlabs commented 1 year ago

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).

abidlabs commented 1 year ago

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.

pngwn commented 1 year ago

Fair enough.

abidlabs commented 1 year ago

Cool, do you want me to PR this? Or make the changes to this branch directly?

pngwn commented 1 year ago

@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

pngwn commented 1 year ago

i do not know how to write tests for components or if we normally do that, so let me know what i should do.

abidlabs commented 1 year ago

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

pngwn commented 1 year ago

Do we test with real files where needed?

abidlabs commented 1 year ago

Yes we do. We store these files in test/test_files

abidlabs commented 1 year ago

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!

pngwn commented 1 year ago

@abidlabs thanks! Will write some tests and address the comments.

pngwn commented 1 year ago
Screenshot 2023-03-09 at 18 06 36
abidlabs commented 1 year ago

Beautiful! I shoulda tweeted out that screenshot

pngwn commented 1 year ago

software ppl love darkmode for some reason

pngwn commented 1 year ago

@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.

abidlabs commented 1 year ago

LGTM this is awesome @pngwn! Thanks for handling all of the backend stuff

pngwn commented 1 year ago

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.

Screenshot 2023-03-10 at 12 12 01 Screenshot 2023-03-10 at 12 12 15

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.

pngwn commented 1 year ago

small documentation fix (thanks @freddyaboulton !). one last ci run and ill merge.