Skip to content

Commit 9517f49

Browse files
authored
validate app name (#1186)
1 parent 45775a7 commit 9517f49

File tree

2 files changed

+51
-5
lines changed

2 files changed

+51
-5
lines changed

piccolo/apps/app/commands/new.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import importlib
44
import os
55
import pathlib
6+
import string
67
import sys
78
import typing as t
89

@@ -33,24 +34,48 @@ def module_exists(module_name: str) -> bool:
3334
return True
3435

3536

37+
APP_NAME_ALLOWED_CHARACTERS = [*string.ascii_lowercase, *string.digits, "_"]
38+
39+
40+
def validate_app_name(app_name: str):
41+
"""
42+
Make sure the app name is something which is a valid Python package name.
43+
44+
:raises ValueError:
45+
If ``app_name`` isn't valid.
46+
47+
"""
48+
for char in app_name:
49+
if not char.lower() in APP_NAME_ALLOWED_CHARACTERS:
50+
raise ValueError(
51+
f"The app name contains a disallowed character: `{char}`. "
52+
"It must only include a-z, 0-9, and _ characters."
53+
)
54+
55+
3656
def get_app_module(app_name: str, root: str) -> str:
3757
return ".".join([*pathlib.Path(root).parts, app_name, "piccolo_app"])
3858

3959

4060
def new_app(app_name: str, root: str = ".", register: bool = False):
4161
print(f"Creating {app_name} app ...")
4262

43-
app_root = os.path.join(root, app_name)
44-
45-
if os.path.exists(app_root):
46-
sys.exit("Folder already exists - exiting.")
63+
try:
64+
validate_app_name(app_name=app_name)
65+
except ValueError as exception:
66+
sys.exit(str(exception))
4767

4868
if module_exists(app_name):
4969
sys.exit(
5070
f"A module called {app_name} already exists - possibly a builtin "
5171
"Python module. Please choose a different name for your app."
5272
)
5373

74+
app_root = os.path.join(root, app_name)
75+
76+
if os.path.exists(app_root):
77+
sys.exit("Folder already exists - exiting.")
78+
5479
os.makedirs(app_root)
5580

5681
with open(os.path.join(app_root, "__init__.py"), "w"):

tests/apps/app/commands/test_new.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33
import tempfile
44
from unittest import TestCase
55

6-
from piccolo.apps.app.commands.new import get_app_module, module_exists, new
6+
from piccolo.apps.app.commands.new import (
7+
get_app_module,
8+
module_exists,
9+
new,
10+
validate_app_name,
11+
)
712

813

914
class TestModuleExists(TestCase):
@@ -45,6 +50,22 @@ def test_new_with_clashing_name(self):
4550
)
4651

4752

53+
class TestValidateAppName(TestCase):
54+
55+
def test_validate_app_name(self):
56+
"""
57+
Make sure only app names which work as valid Python package names are
58+
allowed.
59+
"""
60+
# Should be rejected:
61+
for app_name in ("MY APP", "app/my_app", "my.app"):
62+
with self.assertRaises(ValueError):
63+
validate_app_name(app_name=app_name)
64+
65+
# Should work fine:
66+
validate_app_name(app_name="music")
67+
68+
4869
class TestGetAppIdentifier(TestCase):
4970

5071
def test_get_app_module(self):

0 commit comments

Comments
 (0)