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 +1 -0
- doweb/api/browser.py +37 -0
- doweb/api/viewer.py +82 -0
- doweb/browser.py +55 -0
- doweb/config.py +21 -0
- doweb/custom.css +0 -0
- doweb/default.py +3 -0
- doweb/layout_server.py +930 -0
- doweb/py.typed +0 -0
- doweb/server_jupyter.py +60 -0
- doweb/static/bootstrap/bootstrap.bundle.min.js +7 -0
- doweb/static/bootstrap/bootstrap.bundle.min.js.map +1 -0
- doweb/static/bootstrap/bootstrap.min.css +6 -0
- doweb/static/bootstrap/bootstrap.min.css.map +1 -0
- doweb/static/bootstrap/bootstrap.min.js +7 -0
- doweb/static/bootstrap/bootstrap.min.js.map +1 -0
- doweb/static/client.css +134 -0
- doweb/static/custom.css +11905 -0
- doweb/static/img/doweb.png +0 -0
- doweb/static/viewer.js +905 -0
- doweb/templates/browser.html +27 -0
- doweb/templates/nav.html +16 -0
- doweb/templates/viewer.html +186 -0
- doweb/viewer.py +41 -0
- doweb-0.0.1.dist-info/LICENSE +21 -0
- doweb-0.0.1.dist-info/METADATA +117 -0
- doweb-0.0.1.dist-info/RECORD +29 -0
- doweb-0.0.1.dist-info/WHEEL +5 -0
- doweb-0.0.1.dist-info/top_level.txt +1 -0
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