Skip to content
This repository was archived by the owner on Sep 12, 2024. It is now read-only.

Commit fce392a

Browse files
amadolidypkang
authored andcommitted
[POC]: Optional Patching
1 parent eb70666 commit fce392a

File tree

2 files changed

+148
-100
lines changed

2 files changed

+148
-100
lines changed

jaclang_jaseci/jaseci/__init__.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,33 @@ class FastAPI:
1515
"""FastAPI Handler."""
1616

1717
__app__ = None
18+
__is_imported__: bool | None = None
19+
20+
@staticmethod
21+
def is_imported() -> bool:
22+
"""Check if fastapi is used."""
23+
from jaclang.plugin.feature import JacFeature as Jac
24+
from jaclang.runtimelib.machine import JacMachine
25+
26+
from ..core.architype import (
27+
EdgeArchitype,
28+
NodeArchitype,
29+
ObjectArchitype,
30+
Root,
31+
WalkerArchitype,
32+
)
33+
34+
if not isinstance(FastAPI.__is_imported__, bool):
35+
main = JacMachine.get().loaded_modules.get("__main__")
36+
FastAPI.__is_imported__ = getattr(main, "FastAPI", None) is FastAPI
37+
if FastAPI.__is_imported__:
38+
Jac.RootType = Root # type: ignore[assignment]
39+
Jac.Obj = ObjectArchitype # type: ignore[assignment]
40+
Jac.Node = NodeArchitype # type: ignore[assignment]
41+
Jac.Edge = EdgeArchitype # type: ignore[assignment]
42+
Jac.Walker = WalkerArchitype # type: ignore[assignment]
43+
44+
return FastAPI.__is_imported__
1845

1946
@classmethod
2047
def get(cls) -> _FaststAPI:

jaclang_jaseci/plugin/jaseci.py

Lines changed: 121 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
)
2121
from fastapi.responses import ORJSONResponse
2222

23-
from jaclang.plugin.default import hookimpl
23+
from jaclang.plugin.default import JacFeatureDefaults, hookimpl
2424
from jaclang.plugin.feature import JacFeature as Jac
2525
from jaclang.runtimelib.architype import DSFunc
2626

@@ -42,7 +42,8 @@
4242
WalkerAnchor,
4343
WalkerArchitype,
4444
)
45-
from ..core.context import JaseciContext
45+
from ..core.context import ExecutionContext, JaseciContext
46+
from ..jaseci import FastAPI
4647
from ..jaseci.security import authenticator
4748

4849

@@ -243,9 +244,11 @@ class JacPlugin:
243244

244245
@staticmethod
245246
@hookimpl
246-
def get_context() -> JaseciContext:
247+
def get_context() -> ExecutionContext:
247248
"""Get current execution context."""
248-
return JaseciContext.get()
249+
if FastAPI.is_imported():
250+
return JaseciContext.get()
251+
return JacFeatureDefaults.get_context()
249252

250253
@staticmethod
251254
@hookimpl
@@ -256,125 +259,150 @@ def make_architype(
256259
on_exit: list[DSFunc],
257260
) -> Type[Architype]:
258261
"""Create a new architype."""
259-
for i in on_entry + on_exit:
260-
i.resolve(cls)
261-
if not hasattr(cls, "_jac_entry_funcs_") or not hasattr(
262-
cls, "_jac_exit_funcs_"
263-
):
264-
# Saving the module path and reassign it after creating cls
265-
# So the jac modules are part of the correct module
266-
cur_module = cls.__module__
267-
cls = type(cls.__name__, (cls, arch_base), {})
268-
cls.__module__ = cur_module
269-
cls._jac_entry_funcs_ = on_entry # type: ignore
270-
cls._jac_exit_funcs_ = on_exit # type: ignore
271-
else:
272-
new_entry_funcs = OrderedDict(zip([i.name for i in on_entry], on_entry))
273-
entry_funcs = OrderedDict(
274-
zip([i.name for i in cls._jac_entry_funcs_], cls._jac_entry_funcs_)
275-
)
276-
entry_funcs.update(new_entry_funcs)
277-
cls._jac_entry_funcs_ = list(entry_funcs.values())
262+
if FastAPI.is_imported():
263+
for i in on_entry + on_exit:
264+
i.resolve(cls)
265+
if not hasattr(cls, "_jac_entry_funcs_") or not hasattr(
266+
cls, "_jac_exit_funcs_"
267+
):
268+
# Saving the module path and reassign it after creating cls
269+
# So the jac modules are part of the correct module
270+
cur_module = cls.__module__
271+
cls = type(cls.__name__, (cls, arch_base), {})
272+
cls.__module__ = cur_module
273+
cls._jac_entry_funcs_ = on_entry # type: ignore
274+
cls._jac_exit_funcs_ = on_exit # type: ignore
275+
else:
276+
new_entry_funcs = OrderedDict(zip([i.name for i in on_entry], on_entry))
277+
entry_funcs = OrderedDict(
278+
zip([i.name for i in cls._jac_entry_funcs_], cls._jac_entry_funcs_)
279+
)
280+
entry_funcs.update(new_entry_funcs)
281+
cls._jac_entry_funcs_ = list(entry_funcs.values())
278282

279-
new_exit_funcs = OrderedDict(zip([i.name for i in on_exit], on_exit))
280-
exit_funcs = OrderedDict(
281-
zip([i.name for i in cls._jac_exit_funcs_], cls._jac_exit_funcs_)
282-
)
283-
exit_funcs.update(new_exit_funcs)
284-
cls._jac_exit_funcs_ = list(exit_funcs.values())
283+
new_exit_funcs = OrderedDict(zip([i.name for i in on_exit], on_exit))
284+
exit_funcs = OrderedDict(
285+
zip([i.name for i in cls._jac_exit_funcs_], cls._jac_exit_funcs_)
286+
)
287+
exit_funcs.update(new_exit_funcs)
288+
cls._jac_exit_funcs_ = list(exit_funcs.values())
285289

286-
inner_init = cls.__init__ # type: ignore
290+
inner_init = cls.__init__ # type: ignore
287291

288-
@wraps(inner_init)
289-
def new_init(self: Architype, *args: object, **kwargs: object) -> None:
290-
arch_base.__init__(self)
291-
inner_init(self, *args, **kwargs)
292+
@wraps(inner_init)
293+
def new_init(self: Architype, *args: object, **kwargs: object) -> None:
294+
arch_base.__init__(self)
295+
inner_init(self, *args, **kwargs)
292296

293-
cls.__init__ = new_init # type: ignore
294-
return cls
297+
cls.__init__ = new_init # type: ignore
298+
return cls
299+
return JacFeatureDefaults.make_architype(
300+
cls=cls, arch_base=arch_base, on_entry=on_entry, on_exit=on_exit
301+
)
295302

296303
@staticmethod
297304
@hookimpl
298305
def make_obj(
299306
on_entry: list[DSFunc], on_exit: list[DSFunc]
300307
) -> Callable[[type], type]:
301308
"""Create a new architype."""
309+
if FastAPI.is_imported():
310+
311+
def decorator(cls: Type[Architype]) -> Type[Architype]:
312+
"""Decorate class."""
313+
cls = Jac.make_architype(
314+
cls=cls,
315+
arch_base=ObjectArchitype,
316+
on_entry=on_entry,
317+
on_exit=on_exit,
318+
)
319+
return cls
302320

303-
def decorator(cls: Type[Architype]) -> Type[Architype]:
304-
"""Decorate class."""
305-
cls = Jac.make_architype(
306-
cls=cls, arch_base=ObjectArchitype, on_entry=on_entry, on_exit=on_exit
307-
)
308-
return cls
309-
310-
return decorator
321+
return decorator
322+
return JacFeatureDefaults.make_obj(on_entry=on_entry, on_exit=on_exit)
311323

312324
@staticmethod
313325
@hookimpl
314326
def make_node(
315327
on_entry: list[DSFunc], on_exit: list[DSFunc]
316328
) -> Callable[[type], type]:
317329
"""Create a obj architype."""
330+
if FastAPI.is_imported():
318331

319-
def decorator(cls: Type[Architype]) -> Type[Architype]:
320-
"""Decorate class."""
321-
cls = Jac.make_architype(
322-
cls=cls, arch_base=NodeArchitype, on_entry=on_entry, on_exit=on_exit
323-
)
324-
return cls
332+
def decorator(cls: Type[Architype]) -> Type[Architype]:
333+
"""Decorate class."""
334+
cls = Jac.make_architype(
335+
cls=cls, arch_base=NodeArchitype, on_entry=on_entry, on_exit=on_exit
336+
)
337+
return cls
325338

326-
return decorator
339+
return decorator
340+
return JacFeatureDefaults.make_node(on_entry=on_entry, on_exit=on_exit)
327341

328342
@staticmethod
329343
@hookimpl
330344
def make_edge(
331345
on_entry: list[DSFunc], on_exit: list[DSFunc]
332346
) -> Callable[[type], type]:
333347
"""Create a edge architype."""
348+
if FastAPI.is_imported():
334349

335-
def decorator(cls: Type[Architype]) -> Type[Architype]:
336-
"""Decorate class."""
337-
cls = Jac.make_architype(
338-
cls=cls, arch_base=EdgeArchitype, on_entry=on_entry, on_exit=on_exit
339-
)
340-
return cls
350+
def decorator(cls: Type[Architype]) -> Type[Architype]:
351+
"""Decorate class."""
352+
cls = Jac.make_architype(
353+
cls=cls, arch_base=EdgeArchitype, on_entry=on_entry, on_exit=on_exit
354+
)
355+
return cls
341356

342-
return decorator
357+
return decorator
358+
return JacFeatureDefaults.make_edge(on_entry=on_entry, on_exit=on_exit)
343359

344360
@staticmethod
345361
@hookimpl
346362
def make_walker(
347363
on_entry: list[DSFunc], on_exit: list[DSFunc]
348364
) -> Callable[[type], type]:
349365
"""Create a walker architype."""
366+
if FastAPI.is_imported():
367+
368+
def decorator(cls: Type[Architype]) -> Type[Architype]:
369+
"""Decorate class."""
370+
cls = Jac.make_architype(
371+
cls=cls,
372+
arch_base=WalkerArchitype,
373+
on_entry=on_entry,
374+
on_exit=on_exit,
375+
)
376+
populate_apis(cls)
377+
return cls
350378

351-
def decorator(cls: Type[Architype]) -> Type[Architype]:
352-
"""Decorate class."""
353-
cls = Jac.make_architype(
354-
cls=cls, arch_base=WalkerArchitype, on_entry=on_entry, on_exit=on_exit
355-
)
356-
populate_apis(cls)
357-
return cls
358-
359-
return decorator
379+
return decorator
380+
return JacFeatureDefaults.make_walker(on_entry=on_entry, on_exit=on_exit)
360381

361382
@staticmethod
362383
@hookimpl
363-
def report(expr: Any) -> Any: # noqa: ANN401
384+
def report(expr: Any) -> None: # noqa:ANN401
364385
"""Jac's report stmt feature."""
365-
JaseciContext.get().reports.append(expr)
386+
if FastAPI.is_imported():
387+
JaseciContext.get().reports.append(expr)
388+
return
389+
JacFeatureDefaults.report(expr=expr)
366390

367391
@staticmethod
368392
@hookimpl
369393
def get_root() -> Root:
370394
"""Jac's assign comprehension feature."""
371-
return JaseciContext.get_root()
395+
if FastAPI.is_imported():
396+
return JaseciContext.get_root()
397+
return JacFeatureDefaults.get_root() # type:ignore[return-value]
372398

373399
@staticmethod
374400
@hookimpl
375401
def get_root_type() -> Type[Root]:
376402
"""Jac's root getter."""
377-
return Root
403+
if FastAPI.is_imported():
404+
return Root
405+
return JacFeatureDefaults.get_root_type() # type:ignore[return-value]
378406

379407
@staticmethod
380408
@hookimpl
@@ -384,32 +412,25 @@ def build_edge(
384412
conn_assign: tuple[tuple, tuple] | None,
385413
) -> Callable[[NodeAnchor, NodeAnchor], EdgeArchitype]:
386414
"""Jac's root getter."""
387-
conn_type = conn_type if conn_type else GenericEdge
388-
389-
def builder(source: NodeAnchor, target: NodeAnchor) -> EdgeArchitype:
390-
edge = conn_type() if isinstance(conn_type, type) else conn_type
391-
edge.__attach__(source, target, is_undirected)
392-
if conn_assign:
393-
for fld, val in zip(conn_assign[0], conn_assign[1]):
394-
if hasattr(edge, fld):
395-
setattr(edge, fld, val)
396-
else:
397-
raise ValueError(f"Invalid attribute: {fld}")
398-
if source.persistent or target.persistent:
399-
edge.__jac__.save()
400-
target.save()
401-
source.save()
402-
return edge
403-
404-
return builder
405-
406-
407-
##########################################################
408-
# NEED TO TRANSFER TO PLUGIN #
409-
##########################################################
410-
411-
Jac.RootType = Root # type: ignore[assignment]
412-
Jac.Obj = ObjectArchitype # type: ignore[assignment]
413-
Jac.Node = NodeArchitype # type: ignore[assignment]
414-
Jac.Edge = EdgeArchitype # type: ignore[assignment]
415-
Jac.Walker = WalkerArchitype # type: ignore[assignment]
415+
if FastAPI.is_imported():
416+
conn_type = conn_type if conn_type else GenericEdge
417+
418+
def builder(source: NodeAnchor, target: NodeAnchor) -> EdgeArchitype:
419+
edge = conn_type() if isinstance(conn_type, type) else conn_type
420+
edge.__attach__(source, target, is_undirected)
421+
if conn_assign:
422+
for fld, val in zip(conn_assign[0], conn_assign[1]):
423+
if hasattr(edge, fld):
424+
setattr(edge, fld, val)
425+
else:
426+
raise ValueError(f"Invalid attribute: {fld}")
427+
if source.persistent or target.persistent:
428+
edge.__jac__.save()
429+
target.save()
430+
source.save()
431+
return edge
432+
433+
return builder
434+
return JacFeatureDefaults.build_edge( # type:ignore[return-value]
435+
is_undirected=is_undirected, conn_type=conn_type, conn_assign=conn_assign
436+
)

0 commit comments

Comments
 (0)