diff --git a/docs/configuration.md b/docs/configuration.md index e283f0afc..658dbec62 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -12,7 +12,8 @@ Indicates the type of content being deployed. Valid values are: - `python-bokeh` - `python-dash` - `python-fastapi` -- `pyhon-flask` +- `python-flask` +- `python-gradio` - `python-shiny` - `python-streamlit` - `quarto-shiny` diff --git a/internal/inspect/detectors/all.go b/internal/inspect/detectors/all.go index 8656c0e88..e0841fd9e 100644 --- a/internal/inspect/detectors/all.go +++ b/internal/inspect/detectors/all.go @@ -37,6 +37,7 @@ func NewContentTypeDetector(log logging.Logger) *ContentTypeDetector { NewFastAPIDetector(), NewFlaskDetector(), NewDashDetector(), + NewGradioDetector(), NewStreamlitDetector(), NewBokehDetector(), NewStaticHTMLDetector(), diff --git a/internal/inspect/detectors/python.go b/internal/inspect/detectors/python.go index 548ef5601..ce6d69c60 100644 --- a/internal/inspect/detectors/python.go +++ b/internal/inspect/detectors/python.go @@ -48,6 +48,12 @@ func NewDashDetector() *PythonAppDetector { }) } +func NewGradioDetector() *PythonAppDetector { + return NewPythonAppDetector(config.ContentTypePythonGradio, []string{ + "gradio", + }) +} + func NewStreamlitDetector() *PythonAppDetector { return NewPythonAppDetector(config.ContentTypePythonStreamlit, []string{ "streamlit", diff --git a/internal/inspect/detectors/python_test.go b/internal/inspect/detectors/python_test.go index 1e31bc1ac..412586dd5 100644 --- a/internal/inspect/detectors/python_test.go +++ b/internal/inspect/detectors/python_test.go @@ -168,3 +168,27 @@ func (s *PythonSuite) TestInferTypeWithEntrypoint() { Python: &config.Python{}, }, configs[0]) } + +func (s *PythonSuite) TestInferTypeGradio() { + base := util.NewAbsolutePath("/project", afero.NewMemMapFs()) + err := base.MkdirAll(0777) + s.NoError(err) + + filename := "app.py" + err = base.Join(filename).WriteFile([]byte("import gradio\n"), 0600) + s.Nil(err) + + detector := NewGradioDetector() + configs, err := detector.InferType(base, util.RelativePath{}) + s.Nil(err) + s.Len(configs, 1) + + s.Equal(&config.Config{ + Schema: schema.ConfigSchemaURL, + Type: config.ContentTypePythonGradio, + Entrypoint: filename, + Validate: true, + Files: []string{}, + Python: &config.Python{}, + }, configs[0]) +} diff --git a/internal/schema/schemas/posit-publishing-schema-v3.json b/internal/schema/schemas/posit-publishing-schema-v3.json index 380a38384..2c6d98d6c 100644 --- a/internal/schema/schemas/posit-publishing-schema-v3.json +++ b/internal/schema/schemas/posit-publishing-schema-v3.json @@ -350,6 +350,7 @@ "python-dash", "python-fastapi", "python-flask", + "python-gradio", "python-shiny", "python-streamlit" ] diff --git a/test/sample-content/gradio/.gitignore b/test/sample-content/gradio/.gitignore new file mode 100644 index 000000000..1d17dae13 --- /dev/null +++ b/test/sample-content/gradio/.gitignore @@ -0,0 +1 @@ +.venv diff --git a/test/sample-content/gradio/app.py b/test/sample-content/gradio/app.py new file mode 100644 index 000000000..ed721e772 --- /dev/null +++ b/test/sample-content/gradio/app.py @@ -0,0 +1,12 @@ +import gradio as gr + +def greet(name, intensity): + return "Hello, " + name + "!" * int(intensity) + +demo = gr.Interface( + fn=greet, + inputs=["text", "slider"], + outputs=["text"], +) + +demo.launch() diff --git a/test/sample-content/gradio/requirements.txt b/test/sample-content/gradio/requirements.txt new file mode 100644 index 000000000..95bd14ffc --- /dev/null +++ b/test/sample-content/gradio/requirements.txt @@ -0,0 +1 @@ +gradio==5.12.0