doweb 0.0.1__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.
doweb/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "0.0.1"
doweb/api/browser.py ADDED
@@ -0,0 +1,37 @@
1
+ from itertools import chain
2
+ from pathlib import Path
3
+
4
+ from fastapi import APIRouter, Request
5
+ from fastapi.responses import HTMLResponse
6
+ from fastapi.templating import Jinja2Templates
7
+ from starlette.templating import _TemplateResponse
8
+
9
+ from ..config import Config
10
+
11
+ # from . import __version__ as version
12
+
13
+ router = APIRouter()
14
+ templates = Jinja2Templates(
15
+ directory=(Path(__file__).parent.parent / "templates").resolve()
16
+ )
17
+
18
+
19
+ @router.get("/", response_class=HTMLResponse)
20
+ async def file_browser(
21
+ request: Request,
22
+ ) -> _TemplateResponse:
23
+ settings: Config = router.dependencies[0].dependency() # type: ignore[misc]
24
+ files = chain(
25
+ settings.fileslocation.glob("**/*.gds"), settings.fileslocation.glob("**/*.oas")
26
+ )
27
+ return templates.TemplateResponse(
28
+ "browser.html",
29
+ {
30
+ "request": request,
31
+ "folder_files": [
32
+ file.relative_to(settings.fileslocation) for file in files
33
+ ],
34
+ "page_name": f"File Browser Root: {settings.fileslocation}",
35
+ "root": settings.fileslocation,
36
+ },
37
+ )
doweb/api/viewer.py ADDED
@@ -0,0 +1,82 @@
1
+ from pathlib import Path
2
+ from typing import Annotated
3
+
4
+ from fastapi import APIRouter, Depends, Request
5
+ from fastapi.exceptions import HTTPException
6
+ from fastapi.responses import HTMLResponse
7
+ from fastapi.templating import Jinja2Templates
8
+ from pydantic import BaseModel
9
+ from starlette.templating import _TemplateResponse
10
+
11
+ from .. import __version__ as version
12
+
13
+ router = APIRouter()
14
+ templates = Jinja2Templates(
15
+ directory=(Path(__file__).parent.parent / "templates").resolve()
16
+ )
17
+
18
+
19
+ class FileView(BaseModel):
20
+ file: Path
21
+ cell: str | None = None
22
+ layer_props: str | None = None
23
+ rdb: str | None = None
24
+
25
+
26
+ @router.get("/view", response_class=HTMLResponse)
27
+ async def file_view_static(
28
+ request: Request, params: Annotated[FileView, Depends()]
29
+ ) -> _TemplateResponse:
30
+ settings = router.dependencies[0].dependency() # type: ignore[misc]
31
+ _file = settings.fileslocation / f"{params.file}"
32
+
33
+ exists = _file.is_file() and _file.stat().st_mode
34
+
35
+ if not exists:
36
+ raise HTTPException(
37
+ status_code=404,
38
+ detail=f'No file found with name "{_file}".'
39
+ " It doesn't exist or is not accessible",
40
+ )
41
+
42
+ return await show_file(request, layout_params=params)
43
+
44
+
45
+ async def show_file(request: Request, layout_params: FileView) -> _TemplateResponse:
46
+ root_path = request.scope["root_path"]
47
+
48
+ match request.url.scheme:
49
+ case "https":
50
+ ws_scheme = "wss://"
51
+ case "http":
52
+ ws_scheme = "ws://"
53
+ case other:
54
+ raise HTTPException(status_code=406, detail=f"Unknown scheme {other}")
55
+
56
+ if request.url.port is not None:
57
+ url = (
58
+ ws_scheme
59
+ + (request.url.hostname or "localhost")
60
+ + ":"
61
+ + str(request.url.port)
62
+ + root_path
63
+ )
64
+ else:
65
+ url = ws_scheme + (request.url.hostname or "localhost") + root_path
66
+
67
+ template_params = {
68
+ "request": request,
69
+ "url": url,
70
+ }
71
+
72
+ template_params["params"] = layout_params.model_dump(mode="json", exclude_none=True)
73
+
74
+ return templates.TemplateResponse(
75
+ "viewer.html",
76
+ template_params,
77
+ )
78
+
79
+
80
+ @router.get("/status")
81
+ async def doweb_status() -> dict[str, str | int]:
82
+ return {"server": "doweb", "version": version}
doweb/browser.py ADDED
@@ -0,0 +1,55 @@
1
+ from pathlib import Path
2
+
3
+ from fastapi import Depends, FastAPI
4
+ from fastapi.staticfiles import StaticFiles
5
+ from pydantic import ValidationError
6
+
7
+ from . import config
8
+ from .api.browser import router as browser_router
9
+ from .api.viewer import router as viewer_router
10
+ from .layout_server import LayoutViewServerEndpoint
11
+
12
+
13
+ def get_app(fileslocation: Path | str | None = None, editable: bool = False) -> FastAPI:
14
+ if fileslocation is None:
15
+ try:
16
+ _settings = config.Config()
17
+ except ValidationError:
18
+ raise ValueError(
19
+ "To start the Kweb please set the environment "
20
+ "variable DOWEB_FILESLOCATION to a path in your filesystem."
21
+ " Alternatively, you can set the filepath in the get_app function."
22
+ )
23
+
24
+ else:
25
+ _settings = config.Config(fileslocation=fileslocation, editable=editable)
26
+
27
+ def settings() -> config.Config:
28
+ return _settings
29
+
30
+ staticfiles = StaticFiles(directory=Path(__file__).parent / "static")
31
+
32
+ # app = FastAPI(routes=[WebSocketRoute("/ws", endpoint=LayoutViewServerEndpoint)])
33
+
34
+ app = FastAPI()
35
+ viewer_router.dependencies.insert(0, Depends(settings))
36
+ browser_router.dependencies.insert(0, Depends(settings))
37
+
38
+ _settings = settings()
39
+
40
+ class BrowserLayoutViewServerEndpoint(
41
+ LayoutViewServerEndpoint,
42
+ root=_settings.fileslocation,
43
+ editable=editable,
44
+ add_missing_layers=_settings.add_missing_layers,
45
+ meta_splitter=_settings.meta_splitter,
46
+ ):
47
+ pass
48
+
49
+ app.add_websocket_route("/ws", BrowserLayoutViewServerEndpoint)
50
+ viewer_router.dependencies.insert(0, Depends(settings))
51
+ app.include_router(viewer_router)
52
+ app.include_router(browser_router)
53
+ app.mount("/static", staticfiles, name="doweb_static")
54
+
55
+ return app
doweb/config.py ADDED
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+
5
+ import pydantic
6
+ from pydantic_settings import BaseSettings, SettingsConfigDict
7
+
8
+
9
+ class Config(BaseSettings):
10
+ model_config = SettingsConfigDict(env_prefix="doweb_", env_nested_delimiter="_")
11
+ fileslocation: Path
12
+ meta_splitter: str = ":"
13
+ editable: bool = False
14
+ add_missing_layers: bool = True
15
+ max_rdb_limit: int = 100
16
+ """Maximum rdb errors the client can request."""
17
+
18
+ @pydantic.field_validator("fileslocation")
19
+ @classmethod
20
+ def resolvefileslocation(cls, v: Path | str) -> Path:
21
+ return Path(v).expanduser().resolve()
doweb/custom.css ADDED
File without changes
doweb/default.py ADDED
@@ -0,0 +1,3 @@
1
+ from doweb.browser import get_app
2
+
3
+ app = get_app()