Spaces:
Sleeping
Sleeping
Commit ·
6e05841
1
Parent(s): 2a26f8e
Update deployment result link and download flow
Browse files- app.py +24 -21
- utils/converter.py +3 -2
- utils/file_handler.py +2 -0
- utils/validator.py +8 -4
app.py
CHANGED
|
@@ -47,6 +47,9 @@ class SpaceCreatorApp:
|
|
| 47 |
try:
|
| 48 |
if os.path.exists(file_path):
|
| 49 |
os.remove(file_path)
|
|
|
|
|
|
|
|
|
|
| 50 |
except:
|
| 51 |
pass
|
| 52 |
self.temp_files = []
|
|
@@ -92,14 +95,27 @@ class SpaceCreatorApp:
|
|
| 92 |
def process_step2(self, hf_token, space_name, deploy_mode):
|
| 93 |
"""Step 2: Deploy to Hugging Face"""
|
| 94 |
try:
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
status = self._create_status_message("info", "Skipping deployment as requested.")
|
| 97 |
-
return None, status, 2
|
| 98 |
|
| 99 |
# Validate deployment inputs
|
| 100 |
validation_errors = validate_inputs(None, hf_token, space_name, "Deploy")
|
| 101 |
if validation_errors:
|
| 102 |
-
return None, self._format_errors(validation_errors), 2
|
| 103 |
|
| 104 |
# Deploy to Hugging Face
|
| 105 |
deploy_url = deploy_to_space(hf_token, space_name, self.generated_files)
|
|
@@ -111,25 +127,12 @@ class SpaceCreatorApp:
|
|
| 111 |
|
| 112 |
status = self._create_status_message("success",
|
| 113 |
f"Deployment successful! Space URL: {deploy_url}")
|
| 114 |
-
|
| 115 |
-
|
|
|
|
| 116 |
except Exception as e:
|
| 117 |
error_msg = self._create_status_message("error", f"Deployment failed: {str(e)}")
|
| 118 |
-
return None, error_msg, 2
|
| 119 |
-
|
| 120 |
-
def _extract_code(self, input_text, input_file):
|
| 121 |
-
"""Extract code from text or file"""
|
| 122 |
-
code_content = ""
|
| 123 |
-
if input_file is not None:
|
| 124 |
-
file_content = read_file_content(input_file)
|
| 125 |
-
if input_file.name.endswith('.ipynb') if hasattr(input_file, 'name') else False:
|
| 126 |
-
with tempfile.NamedTemporaryFile(mode='w', suffix='.ipynb', delete=False, encoding='utf-8') as tmp:
|
| 127 |
-
tmp.write(file_content)
|
| 128 |
-
tmp_path = tmp.name
|
| 129 |
-
try:
|
| 130 |
-
code_content = parse_notebook(tmp_path)
|
| 131 |
-
finally:
|
| 132 |
-
os.unlink(tmp_path)
|
| 133 |
else:
|
| 134 |
code_content = file_content
|
| 135 |
elif input_text.strip():
|
|
@@ -1136,7 +1139,7 @@ def create_app():
|
|
| 1136 |
deploy_btn.click(
|
| 1137 |
fn=app.process_step2,
|
| 1138 |
inputs=[hf_token, space_name, deploy_mode],
|
| 1139 |
-
outputs=[full_package_download, status_output, current_step]
|
| 1140 |
).then(
|
| 1141 |
fn=lambda step: (gr.update(visible=step==1), gr.update(visible=step==2), gr.update(visible=step==3)),
|
| 1142 |
inputs=[current_step],
|
|
|
|
| 47 |
try:
|
| 48 |
if os.path.exists(file_path):
|
| 49 |
os.remove(file_path)
|
| 50 |
+
parent_dir = os.path.dirname(file_path)
|
| 51 |
+
if parent_dir and os.path.isdir(parent_dir) and not os.listdir(parent_dir):
|
| 52 |
+
os.rmdir(parent_dir)
|
| 53 |
except:
|
| 54 |
pass
|
| 55 |
self.temp_files = []
|
|
|
|
| 95 |
def process_step2(self, hf_token, space_name, deploy_mode):
|
| 96 |
"""Step 2: Deploy to Hugging Face"""
|
| 97 |
try:
|
| 98 |
+
deploy_mode = deploy_mode or ""
|
| 99 |
+
download_only = deploy_mode in ("📥 Download Only", "Download Only")
|
| 100 |
+
deploy_space = deploy_mode in ("🚀 Deploy to Hugging Face Space", "Deploy to Hugging Face Space")
|
| 101 |
+
|
| 102 |
+
if download_only:
|
| 103 |
+
zip_bytes = create_zip_archive(self.generated_files)
|
| 104 |
+
zip_path = save_individual_file("gradio_app_full_package.zip", zip_bytes, binary=True)
|
| 105 |
+
self.temp_files.append(zip_path)
|
| 106 |
+
|
| 107 |
+
status = self._create_status_message("success",
|
| 108 |
+
"Download package ready! Use the ZIP download button below.")
|
| 109 |
+
return zip_path, status, 3, ""
|
| 110 |
+
|
| 111 |
+
if not deploy_space:
|
| 112 |
status = self._create_status_message("info", "Skipping deployment as requested.")
|
| 113 |
+
return None, status, 2, ""
|
| 114 |
|
| 115 |
# Validate deployment inputs
|
| 116 |
validation_errors = validate_inputs(None, hf_token, space_name, "Deploy")
|
| 117 |
if validation_errors:
|
| 118 |
+
return None, self._format_errors(validation_errors), 2, ""
|
| 119 |
|
| 120 |
# Deploy to Hugging Face
|
| 121 |
deploy_url = deploy_to_space(hf_token, space_name, self.generated_files)
|
|
|
|
| 127 |
|
| 128 |
status = self._create_status_message("success",
|
| 129 |
f"Deployment successful! Space URL: {deploy_url}")
|
| 130 |
+
link_markdown = f"[Open your newly deployed Space]({deploy_url})"
|
| 131 |
+
return zip_path, status, 3, link_markdown
|
| 132 |
+
|
| 133 |
except Exception as e:
|
| 134 |
error_msg = self._create_status_message("error", f"Deployment failed: {str(e)}")
|
| 135 |
+
return None, error_msg, 2, ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
else:
|
| 137 |
code_content = file_content
|
| 138 |
elif input_text.strip():
|
|
|
|
| 1139 |
deploy_btn.click(
|
| 1140 |
fn=app.process_step2,
|
| 1141 |
inputs=[hf_token, space_name, deploy_mode],
|
| 1142 |
+
outputs=[full_package_download, status_output, current_step, deployment_status]
|
| 1143 |
).then(
|
| 1144 |
fn=lambda step: (gr.update(visible=step==1), gr.update(visible=step==2), gr.update(visible=step==3)),
|
| 1145 |
inputs=[current_step],
|
utils/converter.py
CHANGED
|
@@ -275,11 +275,12 @@ All dependencies are listed in requirements.txt
|
|
| 275 |
def create_basic_app_template(input_code: str) -> str:
|
| 276 |
"""Create a basic, guaranteed-valid app.py template"""
|
| 277 |
code_snippet = input_code[:1000]
|
|
|
|
| 278 |
|
| 279 |
return f'''import gradio as gr
|
| 280 |
|
| 281 |
# Original code snippet
|
| 282 |
-
{
|
| 283 |
|
| 284 |
# Gradio interface
|
| 285 |
def process_input(input_text):
|
|
@@ -317,7 +318,7 @@ with gr.Blocks(title="Generated Application", theme=gr.themes.Soft()) as demo:
|
|
| 317 |
|
| 318 |
if __name__ == "__main__":
|
| 319 |
demo.launch(share=False)
|
| 320 |
-
'''
|
| 321 |
|
| 322 |
|
| 323 |
def create_basic_template(input_code: str) -> Dict[str, str]:
|
|
|
|
| 275 |
def create_basic_app_template(input_code: str) -> str:
|
| 276 |
"""Create a basic, guaranteed-valid app.py template"""
|
| 277 |
code_snippet = input_code[:1000]
|
| 278 |
+
commented_code = '\n'.join(f'# {line}' if line.strip() else '#' for line in code_snippet.splitlines())
|
| 279 |
|
| 280 |
return f'''import gradio as gr
|
| 281 |
|
| 282 |
# Original code snippet
|
| 283 |
+
{commented_code}
|
| 284 |
|
| 285 |
# Gradio interface
|
| 286 |
def process_input(input_text):
|
|
|
|
| 318 |
|
| 319 |
if __name__ == "__main__":
|
| 320 |
demo.launch(share=False)
|
| 321 |
+
'''}]}
|
| 322 |
|
| 323 |
|
| 324 |
def create_basic_template(input_code: str) -> Dict[str, str]:
|
utils/file_handler.py
CHANGED
|
@@ -39,6 +39,8 @@ def read_file_content(file_obj) -> str:
|
|
| 39 |
elif isinstance(file_obj, (str, Path)):
|
| 40 |
path = Path(file_obj)
|
| 41 |
if path.exists():
|
|
|
|
|
|
|
| 42 |
return path.read_text(encoding='utf-8', errors='ignore')
|
| 43 |
except Exception as e:
|
| 44 |
print(f"Error reading file: {e}")
|
|
|
|
| 39 |
elif isinstance(file_obj, (str, Path)):
|
| 40 |
path = Path(file_obj)
|
| 41 |
if path.exists():
|
| 42 |
+
if path.stat().st_size > 10 * 1024 * 1024:
|
| 43 |
+
raise ValueError("Uploaded file exceeds the 10MB limit.")
|
| 44 |
return path.read_text(encoding='utf-8', errors='ignore')
|
| 45 |
except Exception as e:
|
| 46 |
print(f"Error reading file: {e}")
|
utils/validator.py
CHANGED
|
@@ -28,15 +28,19 @@ def validate_inputs(
|
|
| 28 |
errors.append("Invalid Groq API Key format")
|
| 29 |
|
| 30 |
# Hugging Face Token validation for deployment
|
| 31 |
-
if mode == "Deploy"
|
| 32 |
-
if not hf_token
|
|
|
|
|
|
|
| 33 |
errors.append("Hugging Face token should start with 'hf_'")
|
| 34 |
elif len(hf_token) < 10:
|
| 35 |
errors.append("Invalid Hugging Face token format")
|
| 36 |
|
| 37 |
# Space Name validation for deployment
|
| 38 |
-
if mode == "Deploy"
|
| 39 |
-
if
|
|
|
|
|
|
|
| 40 |
errors.append("Space name must be 3-30 characters")
|
| 41 |
elif not re.match(r'^[a-z0-9-]+$', space_name):
|
| 42 |
errors.append("Space name can only contain lowercase letters, numbers, and hyphens")
|
|
|
|
| 28 |
errors.append("Invalid Groq API Key format")
|
| 29 |
|
| 30 |
# Hugging Face Token validation for deployment
|
| 31 |
+
if mode == "Deploy":
|
| 32 |
+
if not hf_token:
|
| 33 |
+
errors.append("Hugging Face Token is required for deployment")
|
| 34 |
+
elif not hf_token.startswith('hf_'):
|
| 35 |
errors.append("Hugging Face token should start with 'hf_'")
|
| 36 |
elif len(hf_token) < 10:
|
| 37 |
errors.append("Invalid Hugging Face token format")
|
| 38 |
|
| 39 |
# Space Name validation for deployment
|
| 40 |
+
if mode == "Deploy":
|
| 41 |
+
if not space_name:
|
| 42 |
+
errors.append("Space name is required for deployment")
|
| 43 |
+
elif len(space_name) < 3 or len(space_name) > 30:
|
| 44 |
errors.append("Space name must be 3-30 characters")
|
| 45 |
elif not re.match(r'^[a-z0-9-]+$', space_name):
|
| 46 |
errors.append("Space name can only contain lowercase letters, numbers, and hyphens")
|