Skip to content

Commit 20cea91

Browse files
authored
Merge pull request #35 from eadwinCode/command_fixes
Command Directory Args Fix
2 parents a23274d + ba09718 commit 20cea91

File tree

9 files changed

+110
-30
lines changed

9 files changed

+110
-30
lines changed

ellar_cli/file_scaffolding.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def __init__(
2828
specified_directory: t.Optional[str] = None,
2929
) -> None:
3030
self._specified_directory = specified_directory
31+
3132
self._schema = schema
3233
self._ctx = ProjectScaffoldContext(Environment())
3334
self._scaffold_ellar_template_root_path = scaffold_ellar_template_root_path
@@ -79,7 +80,9 @@ def on_scaffold_completed(self) -> None:
7980

8081
def on_scaffold_started(self) -> None:
8182
for context in self._schema.context:
82-
assert self._ctx[context], f"{context} template context is missing."
83+
assert (
84+
self._ctx.get(context) is not None
85+
), f"{context} template context is missing."
8386

8487
def create_directory(
8588
self,
@@ -125,7 +128,7 @@ def _handle_directory_change(self, working_directory: str) -> str:
125128
_specified_directory = (
126129
self._specified_directory.lower() # type:ignore[union-attr]
127130
)
128-
return os.path.join(working_directory, _specified_directory)
131+
return os.path.join(str(working_directory), _specified_directory)
129132

130133
def get_templating_context(self) -> ProjectScaffoldContext:
131134
return ProjectScaffoldContext(

ellar_cli/manage_commands/create_project.py

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import os
2+
import secrets
23
import typing as t
3-
import uuid
44
from importlib import import_module
5+
from pathlib import Path
56

67
import typer
78
from ellar.common.helper.module_loading import module_dir
@@ -22,14 +23,42 @@
2223

2324

2425
class ProjectTemplateScaffold(FileTemplateScaffold):
25-
def __init__(self, ellar_cli_service: EllarCLIService, **kwargs: t.Any) -> None:
26-
super().__init__(**kwargs)
26+
def __init__(
27+
self,
28+
ellar_cli_service: EllarCLIService,
29+
working_project_name: str,
30+
working_directory: str,
31+
**kwargs: t.Any,
32+
) -> None:
33+
super().__init__(
34+
**kwargs,
35+
working_project_name=working_project_name,
36+
working_directory=working_directory,
37+
)
2738
self.ellar_cli_service = ellar_cli_service
39+
self._working_project_name = working_project_name
40+
if self._specified_directory:
41+
_cwd_path = Path(self._get_working_cwd(working_directory))
42+
self._working_directory = str(_cwd_path)
43+
else:
44+
self._working_directory = working_directory
45+
46+
self.prefix: t.Optional[str] = None
47+
if self._specified_directory and "." not in self._specified_directory:
48+
self.prefix = self._specified_directory.replace("/", ".").lower()
49+
50+
if self.prefix.startswith("."): # pragma: no cover
51+
self.prefix = self.prefix[1:]
52+
53+
if self.prefix.endswith("."): # pragma: no cover
54+
self.prefix = self.prefix[:-1]
2855

2956
def get_scaffolding_context(self, working_project_name: str) -> t.Dict:
57+
_prefix = f"{self.prefix}." if self.prefix else ""
3058
template_context = {
3159
"project_name": working_project_name,
32-
"secret_key": f"ellar_{uuid.uuid4()}",
60+
"secret_key": f"ellar_{secrets.token_hex(32)}",
61+
"config_prefix": _prefix,
3362
}
3463
return template_context
3564

@@ -60,8 +89,10 @@ def validate_project_name(self) -> None:
6089
raise EllarCLIException(message)
6190

6291
def on_scaffold_completed(self) -> None:
92+
_working_project_name = self._working_project_name
93+
6394
self.ellar_cli_service.create_ellar_project_meta(
64-
project_name=self._working_project_name
95+
project_name=_working_project_name, prefix=self.prefix
6596
)
6697
print(
6798
f"`{self._working_project_name}` project scaffold completed. To start your server, run the command below"
@@ -70,7 +101,15 @@ def on_scaffold_completed(self) -> None:
70101
print("Happy coding!")
71102

72103

73-
def create_project(ctx: typer.Context, project_name: str):
104+
def create_project(
105+
ctx: typer.Context,
106+
project_name: str,
107+
directory: t.Optional[str] = typer.Argument(
108+
None,
109+
help="The name of a new directory to scaffold the project into.",
110+
show_default=False,
111+
),
112+
):
74113
"""- Scaffolds Ellar Application -"""
75114

76115
ellar_project_meta = t.cast(t.Optional[EllarCLIService], ctx.meta.get(ELLAR_META))
@@ -86,6 +125,7 @@ def create_project(ctx: typer.Context, project_name: str):
86125
working_directory=os.getcwd(),
87126
scaffold_ellar_template_root_path=root_scaffold_template_path,
88127
ellar_cli_service=ellar_project_meta,
128+
specified_directory=directory,
89129
working_project_name=project_name.lower(),
90130
)
91131
project_template_scaffold.scaffold()

ellar_cli/manage_commands/new.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,6 @@ def is_directory_empty(self) -> bool:
8585
return True
8686

8787
def validate_project_name(self) -> None:
88-
if os.path.exists(self._working_project_name):
89-
message = "A folder with same name exist '{name}' ".format(
90-
name=self._working_project_name
91-
)
92-
raise EllarCLIException(message)
93-
9488
if not self.is_directory_empty():
9589
working_project_dir = os.path.join(
9690
self._working_directory, self._working_project_name

ellar_cli/scaffolding/project_template/project_name/server.ellar

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ from .root_module import ApplicationModule
88
application = AppFactory.create_from_app_module(
99
ApplicationModule,
1010
config_module=os.environ.get(
11-
ELLAR_CONFIG_MODULE, "{{project_name}}.config:DevelopmentConfig"
11+
ELLAR_CONFIG_MODULE, "{{config_prefix}}{{project_name}}.config:DevelopmentConfig"
1212
),
1313
global_guards=[]
1414
)

ellar_cli/scaffolding/project_template/setup.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"context": ["project_name", "secret_key"],
2+
"context": ["project_name", "secret_key", "config_prefix"],
33
"files": [
44
{
55
"name": "project_name",

ellar_cli/service.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,9 @@ def import_project_meta(
139139
)
140140
return None
141141

142-
def create_ellar_project_meta(self, project_name: str) -> None:
142+
def create_ellar_project_meta(
143+
self, project_name: str, prefix: t.Optional[str] = None
144+
) -> None:
143145
pyproject_table = EllarCLIService.read_py_project(self.py_project_path)
144146
if pyproject_table is None:
145147
raise EllarCLIException("Could not locate `pyproject.toml`")
@@ -156,12 +158,18 @@ def create_ellar_project_meta(self, project_name: str) -> None:
156158
if not ellar_py_project.has_default_project:
157159
ellar_py_project.default_project = project_name.lower()
158160

161+
_prefix = f"{prefix}." if prefix else ""
162+
159163
ellar_new_project = ellar_py_project.get_or_create_project(project_name.lower())
160164
ellar_new_project.add("project-name", project_name.lower())
161-
ellar_new_project.add("application", f"{project_name}.server:application")
162-
ellar_new_project.add("config", f"{project_name}.config:DevelopmentConfig")
163165
ellar_new_project.add(
164-
"root-module", f"{project_name}.root_module:ApplicationModule"
166+
"application", f"{_prefix}{project_name}.server:application"
167+
)
168+
ellar_new_project.add(
169+
"config", f"{_prefix}{project_name}.config:DevelopmentConfig"
170+
)
171+
ellar_new_project.add(
172+
"root-module", f"{_prefix}{project_name}.root_module:ApplicationModule"
165173
)
166174

167175
# TODO: lock pyproject.toml file

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ dependencies = [
4343
# exclude 0.11.2 and 0.11.3 due to https://github.com/sdispater/tomlkit/issues/225
4444
"tomlkit >=0.11.1,<1.0.0,!=0.11.2,!=0.11.3",
4545
"uvicorn[standard] == 0.22.0",
46-
"ellar >= 0.3.8"
46+
"ellar >= 0.4.4"
4747
]
4848

4949
[project.scripts]

tests/test_ellar_commands/test_create_project_command.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import os
22

3-
from ellar.core import App
3+
from ellar.core import App, Config
44

55
from ellar_cli.service import EllarCLIService
66

@@ -79,3 +79,27 @@ def test_create_project_command_works(tmpdir, process_runner, write_empty_py_pro
7979

8080
application = ellar_cli_service.import_application()
8181
assert isinstance(application, App)
82+
83+
84+
def test_create_project_command_works_with_specific_directory(
85+
tmpdir, process_runner, write_empty_py_project
86+
):
87+
result = process_runner(["ellar", "create-project", "ellar_project", "Another/me"])
88+
assert result.returncode == 0
89+
assert result.stdout.decode("utf8") == (
90+
"`ellar_project` project scaffold completed. To start your server, run the command below\n"
91+
"ellar --project ellar_project runserver --reload\n"
92+
"Happy coding!\n"
93+
)
94+
ellar_cli_service = EllarCLIService.import_project_meta()
95+
assert ellar_cli_service._meta.dict() == {
96+
"project_name": "ellar_project",
97+
"application": "another.me.ellar_project.server:application",
98+
"config": "another.me.ellar_project.config:DevelopmentConfig",
99+
"root_module": "another.me.ellar_project.root_module:ApplicationModule",
100+
}
101+
application = ellar_cli_service.import_application()
102+
assert isinstance(application, App)
103+
config = ellar_cli_service.get_application_config()
104+
assert isinstance(config, Config)
105+
assert ellar_cli_service.import_root_module()

tests/test_ellar_commands/test_new_command.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def test_new_command_works(tmpdir, process_runner):
2525
}
2626

2727

28-
def test_new_command_works_with_specific_directory(tmpdir, process_runner):
28+
def test_new_command_works_with_specific_directory_case_1(tmpdir, process_runner):
2929
result = process_runner(["ellar", "new", "ellar-project-new", "Another/me"])
3030
assert result.returncode == 0
3131
assert result.stdout.decode("utf8") == (
@@ -45,6 +45,17 @@ def test_new_command_works_with_specific_directory(tmpdir, process_runner):
4545
}
4646

4747

48+
def test_new_command_works_with_specific_directory_case_3(tmpdir, process_runner):
49+
_path = tmpdir / "23-August-2023"
50+
os.makedirs(_path)
51+
result = process_runner(["ellar", "new", "ellar-project-new", str(_path)])
52+
assert result.returncode == 0
53+
assert (
54+
"ellar --project ellar_project_new runserver --reload"
55+
in result.stdout.decode("utf8")
56+
)
57+
58+
4859
def test_new_command_fails_case_1(tmpdir, process_runner):
4960
result = process_runner(["ellar", "new", "ellar-project-new", "Another/me"])
5061
assert result.returncode == 0
@@ -72,13 +83,13 @@ def test_new_command_works_with_specific_directory_case_2(tmpdir, process_runner
7283
}
7384

7485

75-
def test_new_command_fails_for_existing_folder_name(tmp_path, process_runner):
76-
os.makedirs(tmp_path / "ellar-project-exist", exist_ok=True)
77-
result = process_runner(["ellar", "new", "ellar-project-exist"])
78-
assert result.returncode == 1
79-
assert result.stderr.decode("utf8") == (
80-
"Error: A folder with same name exist 'ellar-project-exist' \n"
81-
)
86+
# def test_new_command_fails_for_existing_folder_name(tmp_path, process_runner):
87+
# os.makedirs(tmp_path / "ellar-project-exist", exist_ok=True)
88+
# result = process_runner(["ellar", "new", "ellar-project-exist"])
89+
# assert result.returncode == 1
90+
# assert result.stderr.decode("utf8") == (
91+
# "Error: A folder with same name exist 'ellar-project-exist' \n"
92+
# )
8293

8394

8495
def test_new_command_fails_for_invalid_project_name(tmp_path, process_runner):

0 commit comments

Comments
 (0)