Repository: frappe/frappe

Issue:
new app: partial installation of newly created app
When creating new app in frappe this error occurs when pip installs the newly created app.

```bash
  error: subprocess-exited-with-error
  
  × Getting requirements to build editable did not run successfully.
  │ exit code: 1
  ╰─> [27 lines of output]
      Traceback (most recent call last):
        File "/workspace/frappe-bench/env/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 353, in <module>
          main()
        File "/workspace/frappe-bench/env/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 335, in main
          json_out['return_val'] = hook(**hook_input['kwargs'])
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/workspace/frappe-bench/env/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 132, in get_requires_for_build_editable
          return hook(config_settings)
                 ^^^^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-build-env-6cbazp6h/overlay/lib/python3.11/site-packages/flit_core/buildapi.py", line 23, in get_requires_for_build_wheel
          info = read_flit_config(pyproj_toml)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-build-env-6cbazp6h/overlay/lib/python3.11/site-packages/flit_core/config.py", line 79, in read_flit_config
          return prep_toml_config(d, path)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-build-env-6cbazp6h/overlay/lib/python3.11/site-packages/flit_core/config.py", line 106, in prep_toml_config
          loaded_cfg = read_pep621_metadata(d['project'], path)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-build-env-6cbazp6h/overlay/lib/python3.11/site-packages/flit_core/config.py", line 528, in read_pep621_metadata
          md_dict.update(pep621_people(proj['authors']))
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-build-env-6cbazp6h/overlay/lib/python3.11/site-packages/flit_core/config.py", line 650, in pep621_people
          email = str(Address(person['name'], addr_spec=email))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/opt/.pyenv/versions/3.11.0/lib/python3.11/email/headerregistry.py", line 49, in __init__
          raise a_s.all_defects[0]
      email.errors.InvalidHeaderDefect: addr-spec local part with no domain
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× Getting requirements to build editable did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.
```



Discussion:

Resolving patch:
diff --git a/frappe/utils/boilerplate.py b/frappe/utils/boilerplate.py
--- a/frappe/utils/boilerplate.py
+++ b/frappe/utils/boilerplate.py
@@ -45,7 +45,7 @@ def _get_user_inputs(app_name):
 		},
 		"app_description": {"prompt": "App Description"},
 		"app_publisher": {"prompt": "App Publisher"},
-		"app_email": {"prompt": "App Email"},
+		"app_email": {"prompt": "App Email", "validator": is_valid_email},
 		"app_license": {"prompt": "App License", "default": "MIT"},
 		"create_github_workflow": {
 			"prompt": "Create GitHub Workflow action for unittests",
@@ -72,6 +72,17 @@ def _get_user_inputs(app_name):
 	return hooks
 
 
+def is_valid_email(email) -> bool:
+	from email.headerregistry import Address
+
+	try:
+		Address(addr_spec=email)
+	except Exception:
+		print("App Email should be a valid email address.")
+		return False
+	return True
+
+
 def is_valid_title(title) -> bool:
 	if not APP_TITLE_PATTERN.match(title):
 		print(


Test patch:
diff --git a/frappe/tests/test_boilerplate.py b/frappe/tests/test_boilerplate.py
--- a/frappe/tests/test_boilerplate.py
+++ b/frappe/tests/test_boilerplate.py
@@ -102,11 +102,13 @@ def test_invalid_inputs(self):
 		invalid_inputs = copy.copy(self.default_user_input).update(
 			{
 				"title": ["1nvalid Title", "valid title"],
+				"email": ["notavalidemail", "what@is@this.email", "example@example.org"],
 			}
 		)
 		with patch("sys.stdin", self.get_user_input_stream(invalid_inputs)):
 			hooks = _get_user_inputs(self.default_hooks.app_name)
 		self.assertEqual(hooks.app_title, "valid title")
+		self.assertEqual(hooks.app_email, "example@example.org")
 
 	def test_valid_ci_yaml(self):
 		yaml.safe_load(github_workflow_template.format(**self.default_hooks))