Skip to content

Commit 147435d

Browse files
authored
Merge pull request #64 from xpodev/dev/v1/implement-pages
Implement Pages
2 parents 0c19609 + 056eba8 commit 147435d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+960
-378
lines changed

Diff for: core/app/ez_app.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def __init__(self) -> None:
1616

1717
from sandbox.events.event_emitter import EventEmitter
1818

19-
self.web_app = EZWebApplication(self.app_host)
19+
self.web_app = EZWebApplication()
2020
self.event_system = EventEmitter(self.app_host)
2121

2222
module_manager_config = ModuleManagerConfig()
@@ -25,4 +25,9 @@ def __init__(self) -> None:
2525
def run(self) -> Any:
2626
self.module_manager.load_modules()
2727

28+
import ez.log as log
29+
30+
for module in self.module_manager.get_modules():
31+
log.info(f"\tLoaded module: {module.name}")
32+
2833
self.event_system.emit("App.Started")

Diff for: core/web/applications.py

+1-26
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,7 @@
11
from typing import TYPE_CHECKING
22

33
from starlette.applications import Starlette
4-
from starlette.middleware.base import BaseHTTPMiddleware
5-
6-
from .router import EZRouter
7-
8-
if TYPE_CHECKING:
9-
from sandbox.host import AppHost
10-
11-
12-
class EZMiddleware(BaseHTTPMiddleware):
13-
def __init__(self, app, host: "AppHost"):
14-
super().__init__(app)
15-
self.host = host
16-
17-
async def dispatch(self, request, call_next):
18-
with self.host.application(self.app):
19-
return await call_next(request)
204

215

226
class EZWebApplication(Starlette):
23-
ez_router: EZRouter
24-
25-
def __init__(self, app_host: "AppHost"):
26-
Starlette.__init__(self)
27-
self.app_host = app_host
28-
self._initialize()
29-
30-
def _initialize(self):
31-
self.ez_router = EZRouter()
32-
self.mount("/", self.ez_router)
7+
...

Diff for: include/ez/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
events,
1313
log,
1414
lowlevel,
15+
pages,
1516
plugins,
1617
site,
18+
templates,
1719
web,
1820
)
1921

@@ -40,7 +42,9 @@
4042
"events",
4143
"log",
4244
"lowlevel",
45+
"pages",
4346
"plugins",
4447
"site",
48+
"templates",
4549
"web",
4650
]

Diff for: include/ez/data

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../modules/data/__api__

Diff for: include/ez/jsx

-1
This file was deleted.

Diff for: include/ez/seamless

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../modules/seamless/__api__

Diff for: include/sandbox/__init__.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import warnings
2+
3+
4+
def current_application():
5+
from .host import AppHost
6+
7+
return AppHost.current_host.current_application
8+
9+
10+
def current_plugin():
11+
warnings.warn("This function should not be used yet because the plugin host was not yet refactored")
12+
13+
return current_application()

Diff for: include/sandbox/applications/application.py

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ def __init__(self, oid: ObjectID, permissions: PermissionSet) -> None:
1515
SecurityProvider.__init__(self, permissions)
1616
self._host = None
1717

18+
@property
19+
def is_root(self):
20+
if self.host is None:
21+
return False
22+
return self.host.root_application == self
23+
1824
@property
1925
def host(self) -> "AppHost | None":
2026
return self._host

Diff for: include/sandbox/host/app_host.py

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def __init__(self, context: Context | Application | Any):
3434
context = Application("root", PermissionSet())
3535
if isinstance(context, Application):
3636
context = Context(context)
37+
context.host_application._host = self
3738
self._context = context
3839
self._root = context.current_application
3940
self._apps = [self._root]

Diff for: include/sandbox/identity/oid_db.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from typing import Any, TypeAlias
1+
from typing import TYPE_CHECKING, Any, TypeAlias
22

3-
from ez.data.repository import Repository
3+
if TYPE_CHECKING:
4+
from ez.data.repository import Repository
45

56
from .object_id import ObjectID
67
from .uid import UID
@@ -14,17 +15,17 @@ class OIDCategory:
1415
def add(self, value: Any, *, oid: ObjectID | None = None) -> ObjectID:
1516
raise NotImplementedError()
1617

17-
def get(self, oid: ObjectID, path: ObjectPath) -> Repository:
18+
def get(self, oid: ObjectID, path: ObjectPath) -> "Repository":
1819
raise NotImplementedError()
1920

2021
def set(self, oid: ObjectID, path: ObjectPath, value):
2122
raise NotImplementedError()
2223

2324

2425
class OIDCategoryRepository(OIDCategory):
25-
_repository: Repository[Any]
26+
_repository: "Repository[Any]"
2627

27-
def __init__(self, name: str, repository: Repository) -> None:
28+
def __init__(self, name: str, repository: "Repository") -> None:
2829
self.name = name
2930
self._repository = repository
3031

Diff for: modules/data/__api__/__init__.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from typing import TYPE_CHECKING
2+
3+
4+
if TYPE_CHECKING:
5+
from modules.data import providers
6+
from modules.data.providers import DataProviderBase, ModelProvider, get_provider, get_or_create_provider
7+
8+
else:
9+
from . import providers
10+
11+
from .providers import DataProviderBase, ModelProvider, get_provider, get_or_create_provider
File renamed without changes.
File renamed without changes.
File renamed without changes.

Diff for: modules/data/__api__/providers.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from typing import TYPE_CHECKING
2+
3+
4+
if TYPE_CHECKING:
5+
from modules.data.providers import (
6+
DataProviderBase,
7+
ModelProvider,
8+
get_provider,
9+
get_provider_type,
10+
get_or_create_provider
11+
)
12+
else:
13+
from ..providers import (
14+
DataProviderBase,
15+
ModelProvider,
16+
get_provider,
17+
get_provider_type,
18+
get_or_create_provider
19+
)
20+
21+
22+
__all__ = [
23+
"DataProviderBase",
24+
"ModelProvider",
25+
"get_provider",
26+
"get_provider_type",
27+
"get_or_create_provider",
28+
]
File renamed without changes.

Diff for: modules/data/__init__.py

Whitespace-only changes.

Diff for: modules/data/__main__.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .providers import primitives as _
2+
3+
4+

Diff for: modules/data/configurable.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from typing import Any, Generic, Self, TypeVar, get_args, get_origin
2+
3+
from pydantic import BaseModel
4+
5+
6+
T = TypeVar("T", bound=BaseModel)
7+
8+
9+
class Configurable(Generic[T]):
10+
config: T
11+
12+
def __init__(self, config: T):
13+
self.config = config
14+
15+
def save(self) -> dict[str, Any]:
16+
return self.config.model_dump()
17+
18+
@classmethod
19+
def load(cls, config: dict) -> Self:
20+
for base in cls.__bases__:
21+
origin = get_origin(base)
22+
if isinstance(origin, type) and issubclass(origin, Configurable):
23+
args = get_args(base)
24+
if len(args) != 1:
25+
raise ValueError(f"Configurable class {cls} has more than one type argument")
26+
config_cls = args[0]
27+
if isinstance(config_cls, TypeVar):
28+
raise ValueError(f"Cannot load Configurable class {cls} with a type argument that is a TypeVar")
29+
if not issubclass(config_cls, BaseModel):
30+
raise ValueError(f"Configurable class {cls} has a type argument that is not a subclass of BaseModel")
31+
config: BaseModel = config_cls.model_validate(config)
32+
return cls(config)
33+
raise ValueError(f"Configurable class {cls} does not have a base class that is a subclass of Configurable")

Diff for: modules/data/providers/__init__.py

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from .provider import (
2+
ModelProvider,
3+
DataProviderBase,
4+
get_provider,
5+
get_provider_type,
6+
get_or_create_provider,
7+
)
8+
from .primitives import (
9+
StringProvider,
10+
BooleanProvider,
11+
Config,
12+
)
13+
14+
15+
__all__ = [
16+
"ModelProvider",
17+
"DataProviderBase",
18+
"get_provider",
19+
"get_provider_type",
20+
"get_or_create_provider",
21+
22+
"StringProvider",
23+
"BooleanProvider",
24+
"Config",
25+
]

Diff for: modules/data/providers/primitives.py

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from typing import Any, ClassVar, Generic, TypeVar
2+
3+
from pydantic import RootModel
4+
5+
from .provider import DataProviderBase
6+
7+
from seamless.html import Input
8+
9+
10+
_T = TypeVar("_T")
11+
12+
13+
class Config(RootModel[_T], Generic[_T]):
14+
...
15+
16+
17+
class _ValueProvider(DataProviderBase[_T], Generic[_T]):
18+
DEFAULT: ClassVar[Any]
19+
20+
def __init__(self, value: _T):
21+
self.value = value
22+
23+
def provide(self) -> _T:
24+
return self.value
25+
26+
@classmethod
27+
def default(cls):
28+
return cls(cls.DEFAULT)
29+
30+
@classmethod
31+
def load(cls, config: _T):
32+
return cls(config)
33+
34+
35+
class StringProvider(_ValueProvider[str], data_type=str):
36+
DEFAULT = ""
37+
38+
def render_input(self):
39+
return Input(type="text", value=self.value)
40+
41+
42+
class IntegerProvider(_ValueProvider[int], data_type=int):
43+
DEFAULT = 0
44+
45+
def render_input(self):
46+
return Input(type="number", value=self.value)
47+
48+
49+
class BooleanProvider(_ValueProvider[bool], data_type=bool):
50+
DEFAULT = False
51+
52+
def render_input(self):
53+
return Input(type="checkbox", checked=self.value)

0 commit comments

Comments
 (0)