Skip to content

Commit d28e7bc

Browse files
committed
don't allow apps to be created with names the same as builtin Python modules
1 parent fbcadb0 commit d28e7bc

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

piccolo/apps/app/commands/new.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from __future__ import annotations
2+
import importlib
23
import os
34
import sys
45
import typing as t
@@ -16,13 +17,33 @@
1617
)
1718

1819

20+
def module_exists(module_name: str) -> bool:
21+
"""
22+
Check whether a Python module already exists with this name - for
23+
example, a builtin module.
24+
"""
25+
try:
26+
importlib.import_module(module_name)
27+
except ModuleNotFoundError:
28+
return False
29+
else:
30+
return True
31+
32+
1933
def new_app(app_name: str, root: str = "."):
2034
print(f"Creating {app_name} app ...")
2135

2236
app_root = os.path.join(root, app_name)
2337

2438
if os.path.exists(app_root):
2539
sys.exit("Folder already exists - exiting.")
40+
41+
if module_exists(app_name):
42+
sys.exit(
43+
f"A module called {app_name} already exists - possibly a builtin "
44+
"Python module. Please choose a different name for your app."
45+
)
46+
2647
os.mkdir(app_root)
2748

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

tests/apps/app/commands/test_new.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22
import shutil
33
from unittest import TestCase
44

5-
from piccolo.apps.app.commands.new import new
5+
from piccolo.apps.app.commands.new import new, module_exists
6+
7+
8+
class TestModuleExists(TestCase):
9+
def test_module_exists(self):
10+
self.assertEqual(module_exists("sys"), True)
11+
self.assertEqual(module_exists("abc123xyz"), False)
612

713

814
class TestNewApp(TestCase):
@@ -18,3 +24,19 @@ def test_new(self):
1824
new(app_name=app_name, root=root)
1925

2026
self.assertTrue(os.path.exists(app_path))
27+
28+
def test_new_with_clashing_name(self):
29+
"""
30+
Test trying to create an app with the same name as a builtin Python
31+
package - it shouldn't be allowed.
32+
"""
33+
root = "/tmp"
34+
app_name = "sys"
35+
36+
with self.assertRaises(SystemExit) as context:
37+
new(app_name=app_name, root=root)
38+
39+
exception = context.exception
40+
self.assertTrue(
41+
exception.code.startswith("A module called sys already exists")
42+
)

0 commit comments

Comments
 (0)