Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
de358e7
Move event definitions
binyamin555 Feb 18, 2024
4fae144
Remove module info from __main__.py
binyamin555 Feb 18, 2024
788ebf5
Add more specific plugin errors
binyamin555 Feb 18, 2024
304cc4c
Fix module manager
binyamin555 Feb 18, 2024
81e3cb9
Add `Version` alias
binyamin555 Feb 18, 2024
a378e26
Fix plugin system
binyamin555 Feb 18, 2024
8e3f215
Fix EZ core API file
binyamin555 Feb 18, 2024
5090f06
Add support for plugin entry point
binyamin555 Feb 18, 2024
23ae4b2
Make `installer.info` and `loader.info` class vars
binyamin555 Feb 18, 2024
7fb042e
Remove comments
binyamin555 Feb 18, 2024
c921ef7
Add URI class and tools
binyamin555 Feb 18, 2024
8ef3469
Add core resource types
binyamin555 Feb 18, 2024
0cb42ad
Rename script variable
neriyaco Feb 19, 2024
568698f
Merge pull request #11 from xpodev/dev/rebuild-plugin-system
neriyaco Feb 19, 2024
5db1f12
Merge branch 'main' of https://github.com/xpodev/ez-web
neriyaco Feb 19, 2024
fb4ceca
Fix ez.plugins.machinery imports
binyamin555 Feb 19, 2024
68a06cc
Temporary fix making the info types inherit BaseModel
binyamin555 Feb 19, 2024
fba7139
Merge pull request #13 from xpodev/dev/rebuild-plugin-system
neriyaco Feb 19, 2024
5fc12a7
Add base components
neriyaco Feb 20, 2024
103b269
Change request context middleware to make sense
neriyaco Feb 20, 2024
a46dd6b
Add simple api for plugins
neriyaco Feb 20, 2024
114739b
Update app.py
binyamin555 Feb 20, 2024
875c6ff
Merge pull request #15 from xpodev/dev/middleware
neriyaco Feb 20, 2024
2727747
Update __main__.py
binyamin555 Feb 20, 2024
d2da37b
Merge pull request #16 from xpodev/dev/plugins-api
neriyaco Feb 20, 2024
ffd9755
Add base components
neriyaco Feb 20, 2024
423d63e
Add page wrapping for non-page renders
neriyaco Feb 20, 2024
e7c2b62
Merge branch 'dev/jsx-integration' of https://github.com/xpodev/ez-we…
neriyaco Feb 20, 2024
a06bb10
Fix `Version` model validation and serialization
binyamin555 Feb 20, 2024
79c3d1d
Move some constants into config.py
binyamin555 Feb 20, 2024
5892214
Implement (untested) default plugin installer
binyamin555 Feb 20, 2024
4a43ac1
Update components to jsx v0.2.0
neriyaco Feb 20, 2024
064a943
Change the EZ plugin manifest filename to a constant
binyamin555 Feb 20, 2024
dc6302b
Remove old installer
binyamin555 Feb 20, 2024
95f09b8
Remove old placeholder model for plugin
binyamin555 Feb 20, 2024
1ed29bf
Remove unused imports
binyamin555 Feb 20, 2024
5ee49eb
Fix Plugins.WillLoad and Plugins.DidLoad event args
binyamin555 Feb 20, 2024
3d22fb4
Simplify info object instantiation
binyamin555 Feb 20, 2024
1d060c1
Fix import
binyamin555 Feb 20, 2024
371e956
Simplify imports
binyamin555 Feb 20, 2024
a78e116
Fix `ez.plugins.is_enabled()`
binyamin555 Feb 20, 2024
4953970
Remove comment
binyamin555 Feb 20, 2024
d4a6767
Remove unused type
binyamin555 Feb 20, 2024
0bca689
Fix * exports
binyamin555 Feb 20, 2024
7bb7e1e
Fix `ez.plugins.get_plugin_public_api_module_name() `
binyamin555 Feb 20, 2024
938b8c3
Implemenet basic default plugin installer `uninstall()`
binyamin555 Feb 20, 2024
2c2b340
Fix `uninstall()`
binyamin555 Feb 20, 2024
08226a6
Merge pull request #14 from xpodev/dev/jsx-integration
neriyaco Feb 21, 2024
2f7bcf6
Update __init__.py
binyamin555 Feb 21, 2024
c20dbb0
Merge pull request #17 from xpodev/dev/rebuild-plugin-system
neriyaco Feb 21, 2024
f64afd9
Add URI class and tools
binyamin555 Feb 18, 2024
c52dabf
Add core resource types
binyamin555 Feb 18, 2024
9bcab3d
Merge branch 'dev/add-resource-system' of github.com:xpodev/ez-web in…
neriyaco Feb 21, 2024
48af38e
Format code
neriyaco Feb 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 45 additions & 74 deletions core/ez/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
PLUGINS_DIR: Path = SITE_DIR / "plugins"
MODULE_DIR: Path = EZ_FRAMEWORK_DIR / "modules"
PLUGIN_API_DIR: Path = SITE_DIR / "lib" / "public-api" / "plugins"

EZ_ROUTE_ATTRIBUTE = "ez_web_route"

#endregion

Expand All @@ -42,30 +42,27 @@
from utilities.event import Event
from utilities.event_emitter import EventEmitter
from web.response import _EzResponse
from plugins.manager import PluginManager
from plugins.installer import PluginInstaller
from plugins.errors import UnknownPluginError
from plugins.plugin_info import PluginInfo

from web.app.app import EZApplication

sys.path.remove(str(MODULE_DIR))
del sys
from ez.errors import EZError

sys.path.remove(str(MODULE_DIR))

#endregion


#region EZ Internal


__path__ = list(__path__)


class _EZ:
ez: "_EZ | None" = None
ee: EventEmitter
app: FastAPI

plugin_events: dict[str, list[tuple[str, Callable]]]
plugin_manager: PluginManager
plugin_installer: PluginInstaller

mm: ModuleManager

Expand All @@ -78,8 +75,6 @@ def __init__(self, app: FastAPI | None = None, ee: EventEmitter | None = None) -
self.app = app or EZApplication(redirect_slashes=True)

self.plugin_events = {}
self.plugin_manager = PluginManager(PLUGINS_DIR)
self.plugin_installer = PluginInstaller(self.plugin_manager)

self.mm = ModuleManager(MODULE_DIR)

Expand All @@ -95,20 +90,24 @@ def remove_plugin_events(self, plugin: str):
del self.plugin_events[plugin]

def get_plugin_from_handler(self, handler: Callable, __Path=Path) -> str:
if not handler.__module__.startswith(self.plugin_manager.PLUGIN_PREFIX):
PLUGIN_PREFIX = "ez.current-site.plugins"
if not handler.__module__.startswith(PLUGIN_PREFIX):
return None
name = handler.__module__.removeprefix(self.plugin_manager.PLUGIN_PREFIX + ".").split(".")[0]
return self.plugin_manager.get_plugin_info(name).dir_name
name = handler.__module__.removeprefix(PLUGIN_PREFIX + ".").split(".")[0]
return name

_EZ()


def event_function(f: Callable, *, __wraps=wraps, __ez=_EZ.ez, UnkownPluginError=UnknownPluginError):
def event_function(f: Callable, *, __wraps=wraps, __ez=_EZ.ez):
import ez.plugins
from ez.plugins import UnknownPluginError

plugin = __ez.get_plugin_from_handler(f)
if not plugin:
return f
try:
plugin = __ez.plugin_manager.get_plugin(plugin)
plugin = ez.plugins.get_plugin(plugin)
except UnknownPluginError:
return f
else:
Expand All @@ -117,20 +116,31 @@ def wrapper(*args, **kwargs):
if plugin.enabled:
return f(*args, **kwargs)
return
f.__ez_plugin__ = wrapper.__ez_plugin__ = plugin.info
f.__ez_plugin__ = wrapper.__ez_plugin__ = plugin
return wrapper


def is_plugin_event_handler(f):
return callable(f) and getattr(f, "__ez_plugin__", None) is not None


def get_plugin_event_handler_info(f) -> PluginInfo:
def get_plugin_event_handler_info(f):
if not is_plugin_event_handler(f):
raise ValueError(f"Function '{f.__qualname__}' is not a plugin event handler.")
return getattr(f, "__ez_plugin__")


def extend_ez(module, alias: str = None, *, THIS=sys.modules[__name__]):
import sys
from pathlib import Path

path = Path(module.__file__)

name = alias or path.stem
setattr(THIS, alias or path.stem, module)
sys.modules[f"ez.{name}"] = module


#endregion


Expand Down Expand Up @@ -185,54 +195,6 @@ def emit(event: Event, *args, __ez=_EZ.ez, **kwargs):
#endregion


#region Plugin System


def get_plugins(__ez=_EZ.ez):
return __ez.plugin_manager.get_plugins()


def load_plugin(plugin: str, __ez=_EZ.ez):
return __ez.plugin_manager.load_plugin(plugin)


def load_plugins(__ez=_EZ.ez):
from ez.database.models.plugin import PluginModel

names = [plugin.dir_name for plugin in PluginModel.filter_by(enabled=True).all()]

return __ez.plugin_manager.load_plugins(names)


def enable_plugin(plugin: str, __ez=_EZ.ez):
return __ez.plugin_manager.enable_plugin(plugin)


def disable_plugin(plugin: str, __ez=_EZ.ez):
plugin_info = __ez.plugin_manager.get_plugin_info(plugin)
__ez.remove_plugin_events(plugin_info.dir_name)
return __ez.plugin_manager.disable_plugin(plugin)


def install_plugin(path: str | Path, __Path=Path, __ez=_EZ.ez):
if isinstance(path, str):
path = __Path(path)

if path.suffix == ".zip":
return __ez.plugin_installer.install_from_zip(path)
elif path.is_dir():
return __ez.plugin_installer.install_from_path(path)
else:
raise ValueError("Invalid path to plugin: must be a directory or a zip file.")


def uninstall_plugin(plugin: str, __ez=_EZ.ez):
return __ez.plugin_installer.uninstall_plugin(plugin)


#endregion


#region Module System


Expand Down Expand Up @@ -268,6 +230,7 @@ async def wrapper(*args, **kwargs):
result = await handler(*args, **kwargs)
return response._auto_body(result)

setattr(wrapper, EZ_ROUTE_ATTRIBUTE, True)
__ez.app.add_api_route(route, endpoint=wrapper, methods=methods)
else:

Expand All @@ -276,6 +239,7 @@ def wrapper(*args, **kwargs):
result = handler(*args, **kwargs)
return response._auto_body(result)

setattr(wrapper, EZ_ROUTE_ATTRIBUTE, True)
__ez.app.add_api_route(route, endpoint=wrapper, methods=methods)

log.debug(f"{methods} {route} -> {handler.__name__}")
Expand Down Expand Up @@ -399,13 +363,17 @@ def _setup(__ez=_EZ.ez):

del Modules

from ez.events import Plugins
from ez.plugins import PluginEvent, __pm

emit(Plugins.WillLoad)
load_plugins()
emit(Plugins.DidLoad)
plugins = [
"test-plugin",
"title-changer"
]
emit(PluginEvent.WillLoad, plugins)
__pm.load_plugins(*plugins)
emit(PluginEvent.DidLoad, plugins)

del Plugins
del PluginEvent


def _run(setup=_setup):
Expand All @@ -430,10 +398,10 @@ def run(_run=_run):
del _EZ

del EZApplication
del PluginManager
# del PluginManager
del ModuleManager

del UnknownPluginError
# del UnknownPluginError

del FastAPI

Expand All @@ -447,7 +415,10 @@ def run(_run=_run):

del Path

del sys

__all__ = [
"EZError",
"on",
"once",
"emit",
Expand Down
8 changes: 4 additions & 4 deletions core/ez/events/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
from utilities.event import Event

from .http import HTTP
from .settings import Settings
from web.events import HTTP
from web.app.events import App
from modules.events import Modules
from plugins.events import Plugins
from ezjsx.events import TreeRenderer
# from plugins.events import Plugins
# from ezjsx.events import TreeRenderer

__all__ = [
"Event",
"HTTP",
"App",
"Modules",
"Plugins",
# "Plugins",
"Settings",
"TreeRenderer"
]
23 changes: 16 additions & 7 deletions modules/ezjsx/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,34 @@
from jsx.renderer import render
from jsx.components import Component
from jsx.html import Element
from ez.events import HTTP, TreeRenderer
from ez.events import HTTP
from .events import TreeRenderer
from . import components


@ez.on(HTTP.Out)
def render_tree(_):
if ez.request.method != "GET":
return

if isinstance(ez.response.body, (Component, Element)):
ez.emit(TreeRenderer.WillRender, ez.response.body)
result = render(ez.response.body)
ez.emit(TreeRenderer.DidRender, ez.response.body, result)
body = ez.response.body
if isinstance(body, (Component, Element)):
if not isinstance(body, components.Page):
body = components.Page(body)

ez.emit(TreeRenderer.WillRender, body)
result = render(body)
ez.emit(TreeRenderer.DidRender, body, result)
ez.response.html(result)


mount(ez._app)

__title__ = "EZ JSX Integration"
ez.extend_ez(components, "jsx")

__module_name__ = "EZ JSX Integration"
__version__ = "1.0.0"
__description__ = \
__doc__ = \
"""
This module enables the jsx library for use in EZ Web Framework.
"""
2 changes: 2 additions & 0 deletions modules/ezjsx/components/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .page import Page
from .card import Card
22 changes: 22 additions & 0 deletions modules/ezjsx/components/card.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from jsx.components import ContainerComponent
from jsx.html import Div


class Card(ContainerComponent):
def __init__(self, *children, **props):
super().__init__(*children)

class_name = props.get("class_name", [])
if isinstance(class_name, list):
class_name.append("card")
else:
class_name = [class_name, "card"]

props["class_name"] = class_name
self.props = props

def render(self):
return Div(
*self.children,
**self.props,
)
29 changes: 29 additions & 0 deletions modules/ezjsx/components/page.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from jsx.components import ContainerComponent
from jsx.html import Fragment, Html, Head, Body, Title, Link, Script


class Page(ContainerComponent):
def __init__(self, *children, title="Ez Web"):
super().__init__(*children)
self.title = title

def render(self):
return Fragment(
"<!DOCTYPE html>",
Html(
Head(
Title(self.title),
Link(
rel="stylesheet",
href="https://unpkg.com/bootstrap@5.3.2/dist/css/bootstrap.min.css",
),
Script(src="/_jsx/main.js"),
),
Body(
self.body(),
),
),
)

def body(self):
return Fragment(*self.children)
Loading