Skip to content

Commit 87edc53

Browse files
committed
fixed runserver command
1 parent ede3cc5 commit 87edc53

File tree

22 files changed

+273
-69
lines changed

22 files changed

+273
-69
lines changed

ellar_cli/click/util.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import click
66
from ellar.threading import execute_coroutine_with_sync_worker
77

8-
from ellar_cli.constants import ELLAR_META, ELLAR_PROJECT_NAME
8+
from ellar_cli.constants import ELLAR_META
99
from ellar_cli.service import EllarCLIService
1010

1111

@@ -52,9 +52,6 @@ async def _run_with_application_context(
5252

5353
@click.pass_context
5454
def decorator(__ctx: click.Context, *args: t.Any, **kwargs: t.Any) -> t.Any:
55-
meta_: t.Optional[EllarCLIService] = EllarCLIService.import_project_meta(
56-
__ctx.meta.get(ELLAR_PROJECT_NAME)
57-
)
5855
meta_ = __ctx.meta.get(ELLAR_META)
5956

6057
def _get_command_args(*ar: t.Any, **kw: t.Any) -> t.Any:

ellar_cli/main.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ def app_cli(ctx: click.Context, project: str) -> None:
5151

5252

5353
app_cli.command(name="new")(new_command)
54-
app_cli.command(context_settings={"auto_envvar_prefix": "UVICORN"})(runserver)
54+
app_cli.command(
55+
context_settings={"auto_envvar_prefix": "UVICORN"}, with_app_context=False
56+
)(runserver)
5557
app_cli.command(name="create-project")(create_project)
5658
app_cli.command(name="create-module")(create_module)

ellar_cli/manage_commands/runserver.py

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import typing as t
55
from datetime import datetime
66

7-
import ellar
7+
from ellar import __version__ as ellar_version
88
from ellar.app import current_config
99
from ellar.common.utils.enums import create_enums_from_list
1010
from uvicorn import config as uvicorn_config
@@ -322,13 +322,6 @@
322322
default=None,
323323
help="For h11, the maximum number of bytes to buffer of an incomplete event.",
324324
)
325-
@eClick.option(
326-
"--factory",
327-
is_flag=True,
328-
default=False,
329-
help="Treat APP as an application factory, i.e. a () -> <ASGI app> callable.",
330-
show_default=True,
331-
)
332325
@eClick.pass_context
333326
def runserver(
334327
ctx: eClick.Context,
@@ -376,7 +369,6 @@ def runserver(
376369
use_colors: bool,
377370
# app_dir: str,
378371
h11_max_incomplete_event_size: int | None,
379-
factory: bool,
380372
):
381373
"""- Starts Uvicorn Server -"""
382374
ellar_project_meta = t.cast(t.Optional[EllarCLIService], ctx.meta.get(ELLAR_META))
@@ -389,9 +381,7 @@ def runserver(
389381
"No available project found. please create ellar project with `ellar create-project 'project-name'`"
390382
)
391383

392-
application_import_string = (
393-
None if factory else ellar_project_meta.project_meta.application
394-
)
384+
application_import_string = ellar_project_meta.project_meta.application
395385

396386
log_config = current_config.LOGGING_CONFIG
397387
_log_level = current_config.LOG_LEVEL
@@ -443,16 +433,15 @@ def runserver(
443433
"ssl_ciphers": ssl_ciphers,
444434
"headers": [header.split(":", 1) for header in headers],
445435
"use_colors": use_colors,
446-
"factory": factory,
436+
"factory": ellar_project_meta.is_app_callable(),
447437
# "app_dir": application_import_string.split(':')[0].replace('.', '/'),
448438
}
449439

450440
now = datetime.now().strftime("%B %d, %Y - %X")
451-
version = ellar.__version__
452441
print(
453442
f"\nStarting Uvicorn server...\n"
454443
f"{now}\n"
455-
f"Ellar version {version}, using settings {current_config.config_module!r}\n"
444+
f"Ellar version {ellar_version}, using settings {current_config.config_module!r}\n"
456445
)
457446

458447
uvicorn_run(application_import_string, **init_kwargs)
Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,33 @@
11
import os
22

3-
from ellar.app import AppFactory
3+
from ellar.app import App, AppFactory
44
from ellar.common.constants import ELLAR_CONFIG_MODULE
55
from ellar.core import LazyModuleImport as lazyLoad
66
# from ellar.openapi import OpenAPIDocumentModule, OpenAPIDocumentBuilder, SwaggerUI
77

8-
application = AppFactory.create_from_app_module(
9-
lazyLoad("{{project_name}}.root_module:ApplicationModule"),
10-
config_module=os.environ.get(
11-
ELLAR_CONFIG_MODULE, "{{config_prefix}}{{project_name}}.config:DevelopmentConfig"
12-
),
13-
global_guards=[]
14-
)
158

16-
# uncomment this section if you want API documentation
9+
def bootstrap() -> App:
10+
application = AppFactory.create_from_app_module(
11+
lazyLoad("{{project_name}}.root_module:ApplicationModule"),
12+
config_module=os.environ.get(
13+
ELLAR_CONFIG_MODULE, "{{config_prefix}}{{project_name}}.config:DevelopmentConfig"
14+
),
15+
global_guards=[]
16+
)
1717

18-
# document_builder = OpenAPIDocumentBuilder()
19-
# document_builder.set_title('{{project_name | capitalize}} Title') \
20-
# .set_version('1.0.2') \
21-
# .set_contact(name='Author Name', url='https://www.author-name.com', email='[email protected]') \
22-
# .set_license('MIT Licence', url='https://www.google.com')
23-
#
24-
# document = document_builder.build_document(application)
25-
# module = OpenAPIDocumentModule.setup(
26-
# document=document,
27-
# docs_ui=SwaggerUI(),
28-
# guards=[]
29-
# )
30-
# application.install_module(module)
18+
# uncomment this section if you want API documentation
19+
20+
# document_builder = OpenAPIDocumentBuilder()
21+
# document_builder.set_title('{{project_name | capitalize}} Title') \
22+
# .set_version('1.0.2') \
23+
# .set_contact(name='Author Name', url='https://www.author-name.com', email='[email protected]') \
24+
# .set_license('MIT Licence', url='https://www.google.com')
25+
#
26+
# document = document_builder.build_document(application)
27+
# module = OpenAPIDocumentModule.setup(
28+
# document=document,
29+
# docs_ui=SwaggerUI(),
30+
# guards=[]
31+
# )
32+
# application.install_module(module)
33+
return application

ellar_cli/service.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import asyncio
12
import functools
23
import os
34
import typing as t
@@ -183,7 +184,7 @@ def create_ellar_project_meta(
183184
ellar_new_project = ellar_py_project.get_or_create_project(project_name.lower())
184185
ellar_new_project.add("project-name", project_name.lower())
185186
ellar_new_project.add(
186-
"application", f"{_prefix}{project_name}.server:application"
187+
"application", f"{_prefix}{project_name}.server:bootstrap"
187188
)
188189
ellar_new_project.add(
189190
"config", f"{_prefix}{project_name}.config:DevelopmentConfig"
@@ -212,11 +213,33 @@ def write_py_project(path: str, content: Table) -> None:
212213
def import_application(self) -> "App":
213214
assert self._meta
214215
if "App" not in self._store:
215-
self._store["App"] = t.cast(
216-
"App", import_from_string(self._meta.application)
217-
)
216+
self._store["App"] = t.cast(App, import_from_string(self._meta.application))
217+
218+
if not isinstance(self._store["App"], App):
219+
# if its factory, we resolve the factory.
220+
app_instance = self._store["App"]()
221+
222+
if isinstance(app_instance, t.Coroutine):
223+
raise EllarCLIException(
224+
"Coroutine Application Bootstrapping is not supported."
225+
)
226+
self._store["App"] = app_instance
227+
218228
return self._store["App"] # type:ignore[no-any-return]
219229

230+
def is_app_callable(self) -> bool:
231+
assert self._meta
232+
233+
app = import_from_string(self._meta.application)
234+
res = not isinstance(app, App)
235+
236+
if res and asyncio.iscoroutinefunction(app):
237+
raise EllarCLIException(
238+
"Coroutine Application Bootstrapping is not supported."
239+
)
240+
241+
return res
242+
220243
def import_configuration(self) -> t.Type["Config"]:
221244
assert self._meta
222245
if "Config" not in self._store:

tests/sample_app/example_project/core/__init__.py

Whitespace-only changes.

tests/sample_app/example_project/domain/__init__.py

Whitespace-only changes.

tests/sample_app/example_project/tests/conftest.py

Whitespace-only changes.

tests/sample_app/example_project_2/apps/__init__.py

Whitespace-only changes.

tests/sample_app/example_project_2/core/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)