oe-python-template-example 0.4.1__py3-none-any.whl → 0.4.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oe_python_template_example/api.py +2 -2
- oe_python_template_example/cli.py +34 -1
- oe_python_template_example/constants.py +7 -1
- oe_python_template_example/hello/__init__.py +11 -0
- oe_python_template_example/hello/_gui.py +44 -0
- oe_python_template_example/system/__init__.py +12 -1
- oe_python_template_example/system/_cli.py +64 -23
- oe_python_template_example/system/_gui.py +20 -0
- oe_python_template_example/system/_service.py +1 -0
- oe_python_template_example/utils/.vendored/bottle.py +4563 -0
- oe_python_template_example/utils/__init__.py +14 -0
- oe_python_template_example/utils/_constants.py +27 -8
- oe_python_template_example/utils/_gui.py +174 -0
- oe_python_template_example/utils/_notebook.py +61 -0
- oe_python_template_example/utils/boot.py +6 -0
- {oe_python_template_example-0.4.1.dist-info → oe_python_template_example-0.4.3.dist-info}/METADATA +51 -29
- {oe_python_template_example-0.4.1.dist-info → oe_python_template_example-0.4.3.dist-info}/RECORD +20 -15
- {oe_python_template_example-0.4.1.dist-info → oe_python_template_example-0.4.3.dist-info}/WHEEL +0 -0
- {oe_python_template_example-0.4.1.dist-info → oe_python_template_example-0.4.3.dist-info}/entry_points.txt +0 -0
- {oe_python_template_example-0.4.1.dist-info → oe_python_template_example-0.4.3.dist-info}/licenses/LICENSE +0 -0
@@ -31,7 +31,7 @@ API_BASE_URL = __base__url__
|
|
31
31
|
if not API_BASE_URL:
|
32
32
|
API_BASE_URL = f"http://{UVICORN_HOST}:{UVICORN_PORT}"
|
33
33
|
|
34
|
-
|
34
|
+
api = FastAPI(
|
35
35
|
root_path="/api",
|
36
36
|
title=TITLE,
|
37
37
|
contact={
|
@@ -76,4 +76,4 @@ for router in locate_implementations(VersionedAPIRouter):
|
|
76
76
|
|
77
77
|
# Mount all API versions to the main app
|
78
78
|
for version in API_VERSIONS:
|
79
|
-
|
79
|
+
api.mount(f"/{version}", api_instances[version])
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""CLI (Command Line Interface) of OE Python Template Example."""
|
2
2
|
|
3
3
|
import sys
|
4
|
+
from importlib.util import find_spec
|
4
5
|
|
5
6
|
import typer
|
6
7
|
|
@@ -10,9 +11,41 @@ from .utils import __version__, boot, console, get_logger, prepare_cli
|
|
10
11
|
boot(MODULES_TO_INSTRUMENT)
|
11
12
|
logger = get_logger(__name__)
|
12
13
|
|
13
|
-
cli = typer.Typer(help="Command Line Interface of ")
|
14
|
+
cli = typer.Typer(help="Command Line Interface of OE Python Template Example")
|
14
15
|
prepare_cli(cli, f"🧠 OE Python Template Example v{__version__} - built with love in Berlin 🐻")
|
15
16
|
|
17
|
+
|
18
|
+
if find_spec("nicegui") and find_spec("webview"):
|
19
|
+
|
20
|
+
@cli.command()
|
21
|
+
def gui() -> None:
|
22
|
+
"""Start graphical user interface (GUI) in native window."""
|
23
|
+
from .utils import gui_run # noqa: PLC0415
|
24
|
+
|
25
|
+
gui_run(native=True, with_api=False, title="OE Python Template Example", icon="🧠")
|
26
|
+
|
27
|
+
|
28
|
+
if find_spec("marimo"):
|
29
|
+
from typing import Annotated
|
30
|
+
|
31
|
+
import uvicorn
|
32
|
+
|
33
|
+
from .utils import create_marimo_app
|
34
|
+
|
35
|
+
@cli.command()
|
36
|
+
def notebook(
|
37
|
+
host: Annotated[str, typer.Option(help="Host to bind the server to")] = "127.0.0.1",
|
38
|
+
port: Annotated[int, typer.Option(help="Port to bind the server to")] = 8001,
|
39
|
+
) -> None:
|
40
|
+
"""Start notebook in web browser."""
|
41
|
+
console.print(f"Starting marimo notebook server at http://{host}:{port}")
|
42
|
+
uvicorn.run(
|
43
|
+
create_marimo_app(),
|
44
|
+
host=host,
|
45
|
+
port=port,
|
46
|
+
)
|
47
|
+
|
48
|
+
|
16
49
|
if __name__ == "__main__": # pragma: no cover
|
17
50
|
try:
|
18
51
|
cli()
|
@@ -1,7 +1,13 @@
|
|
1
1
|
"""Constants for the OE Python Template Example."""
|
2
2
|
|
3
|
+
from pathlib import Path
|
4
|
+
|
5
|
+
MODULES_TO_INSTRUMENT = ["oe_python_template_example.hello"]
|
6
|
+
|
3
7
|
API_VERSIONS = {
|
4
8
|
"v1": "1.0.0",
|
5
9
|
"v2": "2.0.0",
|
6
10
|
}
|
7
|
-
|
11
|
+
|
12
|
+
NOTEBOOK_FOLDER = Path(__file__).parent.parent.parent / "examples"
|
13
|
+
NOTEBOOK_APP = Path(__file__).parent.parent.parent / "examples" / "notebook.py"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
"""Homepage (index) of GUI."""
|
2
|
+
|
3
|
+
from pathlib import Path
|
4
|
+
|
5
|
+
from nicegui import ui
|
6
|
+
|
7
|
+
from oe_python_template_example.utils import BasePageBuilder, GUILocalFilePicker
|
8
|
+
|
9
|
+
from ._service import Service
|
10
|
+
|
11
|
+
|
12
|
+
async def pick_file() -> None:
|
13
|
+
"""Open a file picker dialog and show notifier when closed again."""
|
14
|
+
result = await GUILocalFilePicker(str(Path.cwd() / "examples"), multiple=True)
|
15
|
+
ui.notify(f"You chose {result}")
|
16
|
+
|
17
|
+
|
18
|
+
class PageBuilder(BasePageBuilder):
|
19
|
+
@staticmethod
|
20
|
+
def register_pages() -> None:
|
21
|
+
@ui.page("/")
|
22
|
+
def page_index() -> None:
|
23
|
+
"""Homepage of GUI."""
|
24
|
+
service = Service()
|
25
|
+
|
26
|
+
ui.button("Choose file", on_click=pick_file, icon="folder").mark("BUTTON_CHOOSE_FILE")
|
27
|
+
|
28
|
+
ui.button("Click me", on_click=lambda: ui.notify(service.get_hello_world()), icon="check").mark(
|
29
|
+
"BUTTON_CLICK_ME"
|
30
|
+
)
|
31
|
+
|
32
|
+
from importlib.util import find_spec # noqa: PLC0415
|
33
|
+
|
34
|
+
if find_spec("matplotlib") and find_spec("numpy"):
|
35
|
+
import numpy as np # noqa: PLC0415
|
36
|
+
|
37
|
+
with ui.card().tight().mark("CARD_PLOT"): # noqa: SIM117
|
38
|
+
with ui.matplotlib(figsize=(4, 3)).figure as fig:
|
39
|
+
x = np.linspace(0.0, 5.0)
|
40
|
+
y = np.cos(2 * np.pi * x) * np.exp(-x)
|
41
|
+
ax = fig.gca()
|
42
|
+
ax.plot(x, y, "-")
|
43
|
+
|
44
|
+
ui.link("Info", "/info").mark("LINK_INFO")
|
@@ -1,4 +1,4 @@
|
|
1
|
-
"""
|
1
|
+
"""System module."""
|
2
2
|
|
3
3
|
from ._api import api_routers
|
4
4
|
from ._cli import cli
|
@@ -12,6 +12,17 @@ __all__ = [
|
|
12
12
|
"cli",
|
13
13
|
]
|
14
14
|
|
15
|
+
|
16
|
+
from importlib.util import find_spec
|
17
|
+
|
18
|
+
# advertise PageBuuilder to enable auto-discovery
|
19
|
+
if find_spec("nicegui"):
|
20
|
+
from ._gui import PageBuilder
|
21
|
+
|
22
|
+
__all__ += [
|
23
|
+
"PageBuilder",
|
24
|
+
]
|
25
|
+
|
15
26
|
# Export all individual API routers so they are picked up by depdency injection (DI)
|
16
27
|
for version, router in api_routers.items():
|
17
28
|
router_name = f"api_{version}"
|
@@ -3,6 +3,7 @@
|
|
3
3
|
import json
|
4
4
|
import os
|
5
5
|
from enum import StrEnum
|
6
|
+
from importlib.util import find_spec
|
6
7
|
from typing import Annotated
|
7
8
|
|
8
9
|
import typer
|
@@ -81,29 +82,69 @@ def info(
|
|
81
82
|
console.print(yaml.dump(info, width=80, default_flow_style=False), end="")
|
82
83
|
|
83
84
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
)
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
85
|
+
if find_spec("nicegui"):
|
86
|
+
from ..utils import gui_run # noqa: TID252
|
87
|
+
|
88
|
+
@cli.command()
|
89
|
+
def serve( # noqa: PLR0913, PLR0917 # type: ignore
|
90
|
+
app: Annotated[bool, typer.Option(help="Enable web application")] = True,
|
91
|
+
api: Annotated[bool, typer.Option(help="Enable webservice API")] = True,
|
92
|
+
host: Annotated[str, typer.Option(help="Host to bind the server to")] = "127.0.0.1",
|
93
|
+
port: Annotated[int, typer.Option(help="Port to bind the server to")] = 8000,
|
94
|
+
watch: Annotated[bool, typer.Option(help="Enable auto-reload on changes of source code")] = True,
|
95
|
+
open_browser: Annotated[bool, typer.Option(help="Open app in browser after starting the server")] = False,
|
96
|
+
) -> None:
|
97
|
+
"""Start the web server, hosting the graphical web application and/or webservice API.
|
98
|
+
|
99
|
+
Args:
|
100
|
+
app (bool): Enable web application.
|
101
|
+
api (bool): Enable webservice API.
|
102
|
+
host (str): Host to bind the server to.
|
103
|
+
port (int): Port to bind the server to.
|
104
|
+
watch (bool): Enable auto-reload on changes of source code.
|
105
|
+
open_browser (bool): Open app in browser after starting the server.
|
106
|
+
"""
|
107
|
+
if api and not app:
|
108
|
+
console.print(f"Starting webservice API server at http://{host}:{port}")
|
109
|
+
# using environ to pass host/port to api.py to generate doc link
|
110
|
+
os.environ["UVICORN_HOST"] = host
|
111
|
+
os.environ["UVICORN_PORT"] = str(port)
|
112
|
+
uvicorn.run(
|
113
|
+
f"{__project_name__}.api:api",
|
114
|
+
host=host,
|
115
|
+
port=port,
|
116
|
+
reload=watch,
|
117
|
+
)
|
118
|
+
elif app:
|
119
|
+
console.print(f"Starting web application server at http://{host}:{port}")
|
120
|
+
gui_run(native=False, host=host, port=port, with_api=api, show=open_browser)
|
121
|
+
|
122
|
+
else:
|
123
|
+
|
124
|
+
@cli.command()
|
125
|
+
def serve( # type: ignore
|
126
|
+
host: Annotated[str, typer.Option(help="Host to bind the server to")] = "127.0.0.1",
|
127
|
+
port: Annotated[int, typer.Option(help="Port to bind the server to")] = 8000,
|
128
|
+
watch: Annotated[bool, typer.Option(help="Enable auto-reload on changes of source code")] = True,
|
129
|
+
) -> None:
|
130
|
+
"""Start the web server, hosting the API.
|
131
|
+
|
132
|
+
Args:
|
133
|
+
api (bool): Enable webservice API.
|
134
|
+
host (str): Host to bind the server to.
|
135
|
+
port (int): Port to bind the server to.
|
136
|
+
watch (bool): Enable auto-reload on changes of source code.
|
137
|
+
"""
|
138
|
+
console.print(f"Starting webservice API server at http://{host}:{port}")
|
139
|
+
# using environ to pass host/port to api.py to generate doc link
|
140
|
+
os.environ["UVICORN_HOST"] = host
|
141
|
+
os.environ["UVICORN_PORT"] = str(port)
|
142
|
+
uvicorn.run(
|
143
|
+
f"{__project_name__}.api:api",
|
144
|
+
host=host,
|
145
|
+
port=port,
|
146
|
+
reload=watch,
|
147
|
+
)
|
107
148
|
|
108
149
|
|
109
150
|
@cli.command()
|
@@ -0,0 +1,20 @@
|
|
1
|
+
"""Homepage (index) of GUI."""
|
2
|
+
|
3
|
+
from nicegui import ui
|
4
|
+
|
5
|
+
from ..utils import BasePageBuilder, __project_name__, __version__ # noqa: TID252
|
6
|
+
from ._service import Service
|
7
|
+
|
8
|
+
|
9
|
+
class PageBuilder(BasePageBuilder):
|
10
|
+
@staticmethod
|
11
|
+
def register_pages() -> None:
|
12
|
+
@ui.page("/info")
|
13
|
+
def page_info() -> None:
|
14
|
+
"""Homepage of GUI."""
|
15
|
+
ui.label(f"{__project_name__} v{__version__}").mark("LABEL_VERSION")
|
16
|
+
ui.json_editor({
|
17
|
+
"content": {"json": Service().info(True, True)},
|
18
|
+
"readOnly": True,
|
19
|
+
}).mark("JSON_EDITOR_INFO")
|
20
|
+
ui.link("Home", "/").mark("LINK_HOME")
|
@@ -108,6 +108,7 @@ class Service(BaseService):
|
|
108
108
|
"version": platform.python_version(),
|
109
109
|
"compiler": platform.python_compiler(),
|
110
110
|
"implementation": platform.python_implementation(),
|
111
|
+
"sys.path": sys.path,
|
111
112
|
},
|
112
113
|
"interpreter_path": sys.executable,
|
113
114
|
"command_line": " ".join(sys.argv),
|