nextpy-framework 2.4.9__tar.gz → 3.7.1__tar.gz

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.
Files changed (151) hide show
  1. nextpy_framework-3.7.1/.nextpy_framework/nextpy/__init__.py +146 -0
  2. nextpy_framework-3.7.1/.nextpy_framework/nextpy/ast_parser.py +444 -0
  3. nextpy_framework-3.7.1/.nextpy_framework/nextpy/cli.py +2934 -0
  4. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/debug/AutoDebug.py +283 -24
  5. nextpy_framework-3.7.1/.nextpy_framework/nextpy/components/debug/AutoDebug_v3.py +547 -0
  6. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/debug/DebugIcon.py +6 -6
  7. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/debug/DebugIconFixed.py +6 -6
  8. nextpy_framework-3.7.1/.nextpy_framework/nextpy/conf.py +28 -0
  9. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/config.py +5 -1
  10. nextpy_framework-3.7.1/.nextpy_framework/nextpy/core/component_renderer.py +1074 -0
  11. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/core/component_router.py +16 -22
  12. nextpy_framework-3.7.1/.nextpy_framework/nextpy/core/renderer.py +527 -0
  13. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/core/router.py +63 -22
  14. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/db.py +1 -1
  15. nextpy_framework-3.7.1/.nextpy_framework/nextpy/debug/core.py +264 -0
  16. nextpy_framework-3.7.1/.nextpy_framework/nextpy/debug/performance.py +343 -0
  17. nextpy_framework-3.7.1/.nextpy_framework/nextpy/debug/ui.py +757 -0
  18. nextpy_framework-3.7.1/.nextpy_framework/nextpy/debug/websocket.py +384 -0
  19. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/jsx_preprocessor.py +81 -4
  20. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/jsx_transformer.py +3 -0
  21. nextpy_framework-3.7.1/.nextpy_framework/nextpy/main.py +81 -0
  22. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/__init__.py +106 -0
  23. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/compiler/actions.py +431 -0
  24. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/compiler/handler_compiler.py +418 -0
  25. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/components/component.py +2371 -0
  26. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/core/__init__.py +153 -0
  27. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/core/ast_nodes.py +343 -0
  28. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/core/evaluator.py +424 -0
  29. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/core/parser.py +722 -0
  30. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/core/runtime.py +1040 -0
  31. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/devtools/language_server.py +663 -0
  32. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/devtools/language_server_lsp.py +427 -0
  33. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/devtools/psx_formatter.py +259 -0
  34. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/devtools/server_client_components.py +292 -0
  35. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/devtools/setup.py +305 -0
  36. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/hydration/__init__.py +25 -0
  37. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/hydration/decorators.py +839 -0
  38. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/hydration/engine.py +345 -0
  39. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/hydration/integration.py +224 -0
  40. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/renderer/renderer.py +111 -0
  41. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/runtime/actions_runtime.py +332 -0
  42. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/runtime/js_actions_runtime.py +354 -0
  43. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/tests/test_full_integration.py +173 -0
  44. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/tests/test_html_attribute_support.py +40 -0
  45. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/utils/helpers.py +240 -0
  46. nextpy_framework-3.7.1/.nextpy_framework/nextpy/psx/vdom/vnode.py +519 -0
  47. nextpy_framework-3.7.1/.nextpy_framework/nextpy/runtime/events.py +294 -0
  48. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/security.py +1 -1
  49. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/server/app.py +320 -36
  50. nextpy_framework-3.7.1/.nextpy_framework/nextpy/source/conf.py +28 -0
  51. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/HANDLER_REGISTRATION_SYSTEM.py +149 -0
  52. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/setup_complete.py +320 -0
  53. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_autodebug_enhanced.py +272 -0
  54. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_cli_scaffolding.py +117 -0
  55. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_colors.py +38 -0
  56. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_component_rendering.py +80 -0
  57. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_conversion.py +41 -0
  58. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_critical_fixes.py +412 -0
  59. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_demo_mode.py +79 -0
  60. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_demo_server.py +74 -0
  61. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_enhanced_handlers.py +83 -0
  62. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_extraction.py +23 -0
  63. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_final.py +82 -0
  64. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_fixes.py +128 -0
  65. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_handler_system.py +102 -0
  66. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_hydration_engine.py +143 -0
  67. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_integration.py +33 -0
  68. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_interactive_bug.py +51 -0
  69. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_migration.py +265 -0
  70. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_modular_debug.py +453 -0
  71. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_server.py +78 -0
  72. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_server_working.py +57 -0
  73. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_tailwind.py +125 -0
  74. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_tailwind_full.py +186 -0
  75. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_tailwind_integration.py +205 -0
  76. nextpy_framework-3.7.1/.nextpy_framework/nextpy/tests/test_websocket_complete.py +351 -0
  77. nextpy_framework-3.7.1/.nextpy_framework/nextpy/websocket.py +238 -0
  78. nextpy_framework-3.7.1/.nextpy_framework/nextpy_framework.egg-info/PKG-INFO +906 -0
  79. nextpy_framework-3.7.1/.nextpy_framework/nextpy_framework.egg-info/SOURCES.txt +139 -0
  80. nextpy_framework-3.7.1/PKG-INFO +906 -0
  81. nextpy_framework-3.7.1/README.md +865 -0
  82. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/pyproject.toml +1 -1
  83. nextpy_framework-2.4.9/.nextpy_framework/nextpy/__init__.py +0 -120
  84. nextpy_framework-2.4.9/.nextpy_framework/nextpy/cli.py +0 -2443
  85. nextpy_framework-2.4.9/.nextpy_framework/nextpy/core/component_renderer.py +0 -389
  86. nextpy_framework-2.4.9/.nextpy_framework/nextpy/core/renderer.py +0 -252
  87. nextpy_framework-2.4.9/.nextpy_framework/nextpy/main.py +0 -47
  88. nextpy_framework-2.4.9/.nextpy_framework/nextpy/websocket.py +0 -76
  89. nextpy_framework-2.4.9/.nextpy_framework/nextpy_framework.egg-info/PKG-INFO +0 -1589
  90. nextpy_framework-2.4.9/.nextpy_framework/nextpy_framework.egg-info/SOURCES.txt +0 -79
  91. nextpy_framework-2.4.9/PKG-INFO +0 -1589
  92. nextpy_framework-2.4.9/README.md +0 -1548
  93. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/auth.py +0 -0
  94. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/builder.py +0 -0
  95. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/__init__.py +0 -0
  96. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/feedback.py +0 -0
  97. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/form.py +0 -0
  98. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/head.py +0 -0
  99. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/hooks_provider.py +0 -0
  100. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/image.py +0 -0
  101. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/layout.py +0 -0
  102. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/link.py +0 -0
  103. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/loader.py +0 -0
  104. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/navigation.py +0 -0
  105. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/toast.py +0 -0
  106. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/ui.py +0 -0
  107. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components/visual.py +0 -0
  108. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/components.py +0 -0
  109. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/core/__init__.py +0 -0
  110. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/core/builder.py +0 -0
  111. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/core/data_fetching.py +0 -0
  112. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/core/demo_pages_simple.py +0 -0
  113. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/core/demo_router.py +0 -0
  114. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/core/sync.py +0 -0
  115. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/dev_server.py +0 -0
  116. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/dev_tools.py +0 -0
  117. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/errors.py +0 -0
  118. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/hooks.py +0 -0
  119. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/hooks_provider.py +0 -0
  120. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/hooks_provider_new.py +0 -0
  121. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/jsx.py +0 -0
  122. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/performance.py +0 -0
  123. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/plugins/__init__.py +0 -0
  124. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/plugins/base.py +0 -0
  125. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/plugins/builtin.py +0 -0
  126. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/plugins/config.py +0 -0
  127. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/plugins.py +0 -0
  128. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/py.typed +0 -0
  129. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/server/__init__.py +0 -0
  130. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/server/debug.py +0 -0
  131. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/server/middleware.py +0 -0
  132. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1/.nextpy_framework/nextpy}/tests/test_jsx_edgecases.py +0 -0
  133. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1/.nextpy_framework/nextpy}/tests/test_jsx_preprocessor.py +0 -0
  134. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1/.nextpy_framework/nextpy}/tests/test_routing.py +0 -0
  135. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1/.nextpy_framework/nextpy}/tests/test_server_features.py +0 -0
  136. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1/.nextpy_framework/nextpy}/tests/test_tailwind_up_to_date.py +0 -0
  137. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/true_jsx.py +0 -0
  138. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/utils/__init__.py +0 -0
  139. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/utils/cache.py +0 -0
  140. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/utils/email.py +0 -0
  141. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/utils/file_upload.py +0 -0
  142. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/utils/logging.py +0 -0
  143. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/utils/search.py +0 -0
  144. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/utils/seo.py +0 -0
  145. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy/utils/validators.py +0 -0
  146. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy_framework.egg-info/dependency_links.txt +0 -0
  147. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy_framework.egg-info/entry_points.txt +0 -0
  148. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy_framework.egg-info/requires.txt +0 -0
  149. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/.nextpy_framework/nextpy_framework.egg-info/top_level.txt +0 -0
  150. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/LICENSE +0 -0
  151. {nextpy_framework-2.4.9 → nextpy_framework-3.7.1}/setup.cfg +0 -0
@@ -0,0 +1,146 @@
1
+ """
2
+ NextPy - The Python Web Framdwork
3
+ File-based routing, SSR, SSG, and more with FastAPI + PSX (True JSX)
4
+ """
5
+
6
+ __version__ = "3.7.1"
7
+
8
+ from nextpy.core.router import Router, Route, DynamicRoute
9
+ from nextpy.core.renderer import Renderer
10
+ from nextpy.core.data_fetching import (
11
+ get_server_side_props,
12
+ get_static_props,
13
+ get_static_paths,
14
+ )
15
+ from nextpy.components.head import Head
16
+ from nextpy.components.link import Link
17
+ from nextpy.server.app import create_app
18
+
19
+ # Import all PSX features for easy access
20
+ from nextpy.psx import (
21
+ # Core PSX
22
+ PSXElement, PSXParser, psx, render_psx, fragment, key,
23
+ process_python_logic, runtime, SafeExpressionEngine,
24
+
25
+ # VDOM
26
+ VNode, create_element, render, update, get_vdom_metrics,
27
+
28
+ # Renderer
29
+ PSXRenderer, renderer, render_psx_component,
30
+
31
+ # Components
32
+ PSXComponent, component, class_component, ChildrenComponent,
33
+ register_component, clsx,
34
+
35
+ # React Hooks
36
+ useState, useEffect, useContext, useReducer, useRef,
37
+ useMemo, useCallback, useImperativeHandle, useLayoutEffect,
38
+ useDebugValue, useTransition, useDeferredValue, useId,
39
+
40
+ # Custom Hooks
41
+ useCounter, useToggle, useLocalStorage, useFetch, useDebounce,
42
+ useInterval, usePrevious, useAsync, useMediaQuery, useGeolocation, usePerformance,
43
+
44
+ # Event Handlers
45
+ create_onclick, create_ondblclick, create_onmousedown, create_onmouseup,
46
+ create_onmouseover, create_onmouseout, create_onmouseenter, create_onmouseleave, create_onmousemove,
47
+ create_onchange, create_onsubmit, create_onreset, create_onfocus, create_onblur,
48
+ create_oninput, create_oninvalid, create_onselect,
49
+ create_onkeydown, create_onkeyup, create_onkeypress,
50
+ create_ontouchstart, create_ontouchend, create_ontouchmove, create_ontouchcancel,
51
+ create_onload, create_onunload, create_onresize, create_onscroll,
52
+ create_ondrag, create_ondragstart, create_ondragend, create_ondragenter,
53
+ create_ondragleave, create_ondragover, create_ondrop,
54
+ create_onplay, create_onpause, create_onended, create_onvolumechange,
55
+ create_ontimeupdate, create_onseeking, create_onseeked,
56
+ create_onloadstart, create_onprogress, create_onerror, create_onabort,
57
+ create_onanimationstart, create_onanimationend, create_onanimationiteration,
58
+ create_ontransitionend, create_ontransitionrun, create_ontransitionstart,
59
+ create_onwheel, create_oncopy, create_oncut, create_onpaste,
60
+ create_onbeforeprint, create_onafterprint, create_onstorage,
61
+ create_onopen, create_onmessage, create_onclose, create_oninstall, create_onactivate,
62
+
63
+ # Utils
64
+ compile_psx, compile_psx_file, is_psx_file, PSXCompiler,
65
+ )
66
+
67
+ # Legacy hooks for backward compatibility
68
+ from nextpy.hooks import (
69
+ useState as legacy_useState,
70
+ useEffect as legacy_useEffect,
71
+ useContext as legacy_useContext,
72
+ useReducer as legacy_useReducer,
73
+ useCallback as legacy_useCallback,
74
+ useMemo as legacy_useMemo,
75
+ useRef as legacy_useRef,
76
+ useCounter as legacy_useCounter,
77
+ useToggle as legacy_useToggle,
78
+ useLocalStorage as legacy_useLocalStorage,
79
+ useFetch as legacy_useFetch,
80
+ useDebounce as legacy_useDebounce,
81
+ )
82
+
83
+ # Export everything for easy access
84
+ __all__ = [
85
+ # Core NextPy
86
+ 'Router', 'Route', 'DynamicRoute', 'Renderer', 'create_app',
87
+ 'get_server_side_props', 'get_static_props', 'get_static_paths',
88
+ 'Head', 'Link',
89
+
90
+ # PSX Core
91
+ 'PSXElement', 'PSXParser', 'psx', 'render_psx', 'fragment', 'key',
92
+ 'process_python_logic', 'runtime', 'SafeExpressionEngine',
93
+
94
+ # PSX VDOM
95
+ 'VNode', 'create_element', 'render', 'update', 'get_vdom_metrics',
96
+
97
+ # PSX Renderer
98
+ 'PSXRenderer', 'renderer', 'render_psx_component',
99
+
100
+ # PSX Components
101
+ 'PSXComponent', 'component', 'class_component', 'ChildrenComponent',
102
+ 'register_component', 'clsx',
103
+
104
+ # PSX React Hooks
105
+ 'useState', 'useEffect', 'useContext', 'useReducer', 'useRef',
106
+ 'useMemo', 'useCallback', 'useImperativeHandle', 'useLayoutEffect',
107
+ 'useDebugValue', 'useTransition', 'useDeferredValue', 'useId',
108
+
109
+ # PSX Custom Hooks
110
+ 'useCounter', 'useToggle', 'useLocalStorage', 'useFetch', 'useDebounce',
111
+ 'useInterval', 'usePrevious', 'useAsync', 'useMediaQuery', 'useGeolocation', 'usePerformance',
112
+
113
+ # PSX Event Handlers
114
+ 'create_onclick', 'create_ondblclick', 'create_onmousedown', 'create_onmouseup',
115
+ 'create_onmouseover', 'create_onmouseout', 'create_onmouseenter', 'create_onmouseleave', 'create_onmousemove',
116
+ 'create_onchange', 'create_onsubmit', 'create_onreset', 'create_onfocus', 'create_onblur',
117
+ 'create_oninput', 'create_oninvalid', 'create_onselect',
118
+ 'create_onkeydown', 'create_onkeyup', 'create_onkeypress',
119
+ 'create_ontouchstart', 'create_ontouchend', 'create_ontouchmove', 'create_ontouchcancel',
120
+ 'create_onload', 'create_onunload', 'create_onresize', 'create_onscroll',
121
+ 'create_ondrag', 'create_ondragstart', 'create_ondragend', 'create_ondragenter',
122
+ 'create_ondragleave', 'create_ondragover', 'create_ondrop',
123
+ 'create_onplay', 'create_onpause', 'create_onended', 'create_onvolumechange',
124
+ 'create_ontimeupdate', 'create_onseeking', 'create_onseeked',
125
+ 'create_onloadstart', 'create_onprogress', 'create_onerror', 'create_onabort',
126
+ 'create_onanimationstart', 'create_onanimationend', 'create_onanimationiteration',
127
+ 'create_ontransitionend', 'create_ontransitionrun', 'create_ontransitionstart',
128
+ 'create_onwheel', 'create_oncopy', 'create_oncut', 'create_onpaste',
129
+ 'create_onbeforeprint', 'create_onafterprint', 'create_onstorage',
130
+ 'create_onopen', 'create_onmessage', 'create_onclose', 'create_oninstall', 'create_onactivate',
131
+
132
+ # PSX Utils
133
+ 'compile_psx', 'compile_psx_file', 'is_psx_file', 'PSXCompiler',
134
+
135
+ # Legacy hooks
136
+ 'legacy_useState', 'legacy_useEffect', 'legacy_useContext', 'legacy_useReducer',
137
+ 'legacy_useCallback', 'legacy_useMemo', 'legacy_useRef', 'legacy_useCounter',
138
+ 'legacy_useToggle', 'legacy_useLocalStorage', 'legacy_useFetch', 'legacy_useDebounce',
139
+ ]
140
+
141
+
142
+ maintainers = [
143
+ {"name": "NextPy Team", "email": "team@nextpy.dev"}
144
+ ]
145
+
146
+ main = "nextpy.server.app:create_app"
@@ -0,0 +1,444 @@
1
+ """
2
+ NextPy AST Parser - Secure and reliable parsing using Abstract Syntax Trees
3
+ Replaces string-based evaluation with AST-based parsing for better security and performance
4
+ """
5
+
6
+ import ast
7
+ import operator
8
+ from typing import Any, Dict, List, Optional, Union
9
+ from dataclasses import dataclass
10
+
11
+
12
+ @dataclass
13
+ class ASTExpression:
14
+ """Represents a parsed AST expression in NextPy Intermediate Representation"""
15
+ type: str
16
+ operator: Optional[str] = None
17
+ left: Optional['ASTExpression'] = None
18
+ right: Optional['ASTExpression'] = None
19
+ value: Any = None
20
+ name: Optional[str] = None
21
+ args: Optional[List['ASTExpression']] = None
22
+ body: Optional[List['ASTExpression']] = None
23
+
24
+
25
+ class ASTParser:
26
+ """Converts Python AST to NextPy Intermediate Representation"""
27
+
28
+ # Safe operators mapping
29
+ OPERATORS = {
30
+ ast.Add: operator.add,
31
+ ast.Sub: operator.sub,
32
+ ast.Mult: operator.mul,
33
+ ast.Div: operator.truediv,
34
+ ast.FloorDiv: operator.floordiv,
35
+ ast.Mod: operator.mod,
36
+ ast.Pow: operator.pow,
37
+ ast.LShift: operator.lshift,
38
+ ast.RShift: operator.rshift,
39
+ ast.BitOr: operator.or_,
40
+ ast.BitXor: operator.xor,
41
+ ast.BitAnd: operator.and_,
42
+ ast.MatMult: operator.matmul,
43
+
44
+ ast.Eq: operator.eq,
45
+ ast.NotEq: operator.ne,
46
+ ast.Lt: operator.lt,
47
+ ast.LtE: operator.le,
48
+ ast.Gt: operator.gt,
49
+ ast.GtE: operator.ge,
50
+ ast.Is: operator.is_,
51
+ ast.IsNot: operator.is_not,
52
+ ast.In: lambda a, b: a in b,
53
+ ast.NotIn: lambda a, b: a not in b,
54
+
55
+ ast.And: lambda a, b: a and b,
56
+ ast.Or: lambda a, b: a or b,
57
+ ast.Not: operator.not_,
58
+ }
59
+
60
+ def __init__(self, allowed_names: Optional[Dict[str, Any]] = None):
61
+ """
62
+ Initialize AST parser with allowed names for security
63
+
64
+ Args:
65
+ allowed_names: Dictionary of allowed variable names and their values
66
+ """
67
+ self.allowed_names = allowed_names or {}
68
+
69
+ def parse_expression(self, expression: str) -> ASTExpression:
70
+ """
71
+ Parse a Python expression into NextPy IR
72
+
73
+ Args:
74
+ expression: Python expression string
75
+
76
+ Returns:
77
+ ASTExpression in NextPy IR format
78
+ """
79
+ try:
80
+ tree = ast.parse(expression, mode='eval')
81
+ return self._convert_node(tree.body)
82
+ except SyntaxError as e:
83
+ raise ValueError(f"Invalid Python syntax: {e}")
84
+ except Exception as e:
85
+ raise ValueError(f"Error parsing expression: {e}")
86
+
87
+ def parse_code(self, code: str) -> List[ASTExpression]:
88
+ """
89
+ Parse Python code into NextPy IR
90
+
91
+ Args:
92
+ code: Python code string
93
+
94
+ Returns:
95
+ List of ASTExpression in NextPy IR format
96
+ """
97
+ try:
98
+ tree = ast.parse(code, mode='exec')
99
+ return [self._convert_node(node) for node in tree.body]
100
+ except SyntaxError as e:
101
+ raise ValueError(f"Invalid Python syntax: {e}")
102
+ except Exception as e:
103
+ raise ValueError(f"Error parsing code: {e}")
104
+
105
+ def evaluate_expression(self, expression: str, context: Optional[Dict[str, Any]] = None) -> Any:
106
+ """
107
+ Safely evaluate a Python expression using AST
108
+
109
+ Args:
110
+ expression: Python expression string
111
+ context: Additional context variables
112
+
113
+ Returns:
114
+ Evaluated result
115
+ """
116
+ ast_expr = self.parse_expression(expression)
117
+ return self._evaluate_ast_expression(ast_expr, context)
118
+
119
+ def _convert_node(self, node: ast.AST) -> ASTExpression:
120
+ """Convert AST node to NextPy IR"""
121
+
122
+ if isinstance(node, ast.Constant):
123
+ return ASTExpression(
124
+ type="Literal",
125
+ value=node.value
126
+ )
127
+
128
+ elif isinstance(node, ast.Name):
129
+ # Allow all names during parsing, check during evaluation
130
+ return ASTExpression(
131
+ type="Identifier",
132
+ name=node.id
133
+ )
134
+
135
+ elif isinstance(node, ast.BinOp):
136
+ return ASTExpression(
137
+ type="BinaryExpression",
138
+ operator=self._get_operator_name(node.op),
139
+ left=self._convert_node(node.left),
140
+ right=self._convert_node(node.right)
141
+ )
142
+
143
+ elif isinstance(node, ast.UnaryOp):
144
+ return ASTExpression(
145
+ type="UnaryExpression",
146
+ operator=self._get_operator_name(node.op),
147
+ left=self._convert_node(node.operand),
148
+ right=None
149
+ )
150
+
151
+ elif isinstance(node, ast.BoolOp):
152
+ return ASTExpression(
153
+ type="LogicalExpression",
154
+ operator=self._get_operator_name(node.op),
155
+ left=self._convert_node(node.values[0]),
156
+ right=self._convert_node(node.values[1]) if len(node.values) > 1 else None
157
+ )
158
+
159
+ elif isinstance(node, ast.Compare):
160
+ if len(node.comparators) == 1:
161
+ return ASTExpression(
162
+ type="BinaryExpression",
163
+ operator=self._get_operator_name(node.ops[0]),
164
+ left=self._convert_node(node.left),
165
+ right=self._convert_node(node.comparators[0])
166
+ )
167
+ else:
168
+ # Handle chained comparisons (a < b < c)
169
+ raise ValueError("Chained comparisons not yet supported")
170
+
171
+ elif isinstance(node, ast.Call):
172
+ if isinstance(node.func, ast.Name):
173
+ func_name = node.func.id
174
+ if func_name not in self.allowed_names:
175
+ raise ValueError(f"Function '{func_name}' is not allowed")
176
+
177
+ return ASTExpression(
178
+ type="CallExpression",
179
+ name=func_name,
180
+ args=[self._convert_node(arg) for arg in node.args]
181
+ )
182
+ else:
183
+ raise ValueError("Only simple function calls are allowed")
184
+
185
+ elif isinstance(node, ast.Attribute):
186
+ return ASTExpression(
187
+ type="MemberExpression",
188
+ name=node.attr,
189
+ left=self._convert_node(node.value)
190
+ )
191
+
192
+ elif isinstance(node, ast.List):
193
+ return ASTExpression(
194
+ type="ArrayExpression",
195
+ args=[self._convert_node(elt) for elt in node.elts]
196
+ )
197
+
198
+ elif isinstance(node, ast.Dict):
199
+ keys = [self._convert_node(key) for key in node.keys]
200
+ values = [self._convert_node(value) for value in node.values]
201
+ return ASTExpression(
202
+ type="ObjectExpression",
203
+ args=[keys, values]
204
+ )
205
+
206
+ else:
207
+ raise ValueError(f"Unsupported AST node type: {type(node).__name__}")
208
+
209
+ def _get_operator_name(self, op: ast.AST) -> str:
210
+ """Get operator name from AST node"""
211
+ operator_map = {
212
+ ast.Add: "+",
213
+ ast.Sub: "-",
214
+ ast.Mult: "*",
215
+ ast.Div: "/",
216
+ ast.FloorDiv: "//",
217
+ ast.Mod: "%",
218
+ ast.Pow: "**",
219
+ ast.LShift: "<<",
220
+ ast.RShift: ">>",
221
+ ast.BitOr: "|",
222
+ ast.BitXor: "^",
223
+ ast.BitAnd: "&",
224
+
225
+ ast.Eq: "==",
226
+ ast.NotEq: "!=",
227
+ ast.Lt: "<",
228
+ ast.LtE: "<=",
229
+ ast.Gt: ">",
230
+ ast.GtE: ">=",
231
+ ast.Is: "is",
232
+ ast.IsNot: "is not",
233
+ ast.In: "in",
234
+ ast.NotIn: "not in",
235
+
236
+ ast.And: "and",
237
+ ast.Or: "or",
238
+ ast.Not: "not",
239
+
240
+ ast.UAdd: "+",
241
+ ast.USub: "-",
242
+ }
243
+
244
+ if type(op) in operator_map:
245
+ return operator_map[type(op)]
246
+ else:
247
+ raise ValueError(f"Unsupported operator: {type(op).__name__}")
248
+
249
+ def _evaluate_ast_expression(self, expr: ASTExpression, context: Optional[Dict[str, Any]] = None) -> Any:
250
+ """Evaluate ASTExpression safely"""
251
+ if context is None:
252
+ context = {}
253
+
254
+ # Merge allowed names with context
255
+ eval_context = {**self.allowed_names, **context}
256
+
257
+ if expr.type == "Literal":
258
+ return expr.value
259
+
260
+ elif expr.type == "Identifier":
261
+ if expr.name in eval_context:
262
+ return eval_context[expr.name]
263
+ else:
264
+ raise ValueError(f"Undefined variable: {expr.name}")
265
+
266
+ elif expr.type == "BinaryExpression":
267
+ left = self._evaluate_ast_expression(expr.left, context)
268
+ right = self._evaluate_ast_expression(expr.right, context)
269
+
270
+ op_func = self.OPERATORS.get(self._get_ast_operator(expr.operator))
271
+ if op_func:
272
+ return op_func(left, right)
273
+ else:
274
+ raise ValueError(f"Unsupported operator: {expr.operator}")
275
+
276
+ elif expr.type == "UnaryExpression":
277
+ operand = self._evaluate_ast_expression(expr.left, context)
278
+
279
+ if expr.operator == "not":
280
+ return not operand
281
+ elif expr.operator == "-":
282
+ return -operand
283
+ elif expr.operator == "+":
284
+ return +operand
285
+ else:
286
+ raise ValueError(f"Unsupported unary operator: {expr.operator}")
287
+
288
+ elif expr.type == "LogicalExpression":
289
+ left = self._evaluate_ast_expression(expr.left, context)
290
+
291
+ if expr.operator == "and":
292
+ # Short-circuit evaluation
293
+ if not left:
294
+ return False
295
+ right = self._evaluate_ast_expression(expr.right, context)
296
+ return bool(right)
297
+ elif expr.operator == "or":
298
+ # Short-circuit evaluation
299
+ if left:
300
+ return True
301
+ right = self._evaluate_ast_expression(expr.right, context)
302
+ return bool(right)
303
+ else:
304
+ raise ValueError(f"Unsupported logical operator: {expr.operator}")
305
+
306
+ elif expr.type == "CallExpression":
307
+ func = eval_context.get(expr.name)
308
+ if not callable(func):
309
+ raise ValueError(f"'{expr.name}' is not a function")
310
+
311
+ args = [self._evaluate_ast_expression(arg, context) for arg in expr.args]
312
+ return func(*args)
313
+
314
+ elif expr.type == "ArrayExpression":
315
+ return [self._evaluate_ast_expression(arg, context) for arg in expr.args]
316
+
317
+ elif expr.type == "ObjectExpression":
318
+ keys = expr.args[0]
319
+ values = expr.args[1]
320
+ result = {}
321
+ for i, (key_expr, value_expr) in enumerate(zip(keys, values)):
322
+ key = self._evaluate_ast_expression(key_expr, context)
323
+ value = self._evaluate_ast_expression(value_expr, context)
324
+ result[key] = value
325
+ return result
326
+
327
+ else:
328
+ raise ValueError(f"Cannot evaluate expression type: {expr.type}")
329
+
330
+ def _get_ast_operator(self, op_name: str) -> type:
331
+ """Get AST operator class from operator name"""
332
+ operator_map = {
333
+ "+": ast.Add,
334
+ "-": ast.Sub,
335
+ "*": ast.Mult,
336
+ "/": ast.Div,
337
+ "//": ast.FloorDiv,
338
+ "%": ast.Mod,
339
+ "**": ast.Pow,
340
+ "<<": ast.LShift,
341
+ ">>": ast.RShift,
342
+ "|": ast.BitOr,
343
+ "^": ast.BitXor,
344
+ "&": ast.BitAnd,
345
+
346
+ "==": ast.Eq,
347
+ "!=": ast.NotEq,
348
+ "<": ast.Lt,
349
+ "<=": ast.LtE,
350
+ ">": ast.Gt,
351
+ ">=": ast.GtE,
352
+ "is": ast.Is,
353
+ "is not": ast.IsNot,
354
+ "in": ast.In,
355
+ "not in": ast.NotIn,
356
+ }
357
+
358
+ return operator_map.get(op_name)
359
+
360
+
361
+ # Global AST parser instance with safe defaults
362
+ SAFE_PARSER = ASTParser(allowed_names={
363
+ # Built-in functions
364
+ 'len': len,
365
+ 'str': str,
366
+ 'int': int,
367
+ 'float': float,
368
+ 'bool': bool,
369
+ 'list': list,
370
+ 'dict': dict,
371
+ 'tuple': tuple,
372
+ 'set': set,
373
+ 'range': range,
374
+ 'enumerate': enumerate,
375
+ 'zip': zip,
376
+ 'map': map,
377
+ 'filter': filter,
378
+ 'sum': sum,
379
+ 'max': max,
380
+ 'min': min,
381
+ 'abs': abs,
382
+ 'round': round,
383
+ 'all': all,
384
+ 'any': any,
385
+
386
+ # Math functions
387
+ 'math': __import__('math'),
388
+
389
+ # Common constants
390
+ 'True': True,
391
+ 'False': False,
392
+ 'None': None,
393
+ })
394
+
395
+
396
+ def parse_expression_safe(expression: str, context: Optional[Dict[str, Any]] = None) -> Any:
397
+ """
398
+ Safely parse and evaluate a Python expression
399
+
400
+ Args:
401
+ expression: Python expression string
402
+ context: Additional context variables
403
+
404
+ Returns:
405
+ Evaluated result
406
+ """
407
+ return SAFE_PARSER.evaluate_expression(expression, context)
408
+
409
+
410
+ def convert_to_ir(expression: str) -> Dict[str, Any]:
411
+ """
412
+ Convert Python expression to NextPy Intermediate Representation
413
+
414
+ Args:
415
+ expression: Python expression string
416
+
417
+ Returns:
418
+ Dictionary representation of ASTExpression
419
+ """
420
+ ast_expr = SAFE_PARSER.parse_expression(expression)
421
+
422
+ def expr_to_dict(expr: ASTExpression) -> Dict[str, Any]:
423
+ result = {
424
+ 'type': expr.type
425
+ }
426
+
427
+ if expr.operator is not None:
428
+ result['operator'] = expr.operator
429
+ if expr.value is not None:
430
+ result['value'] = expr.value
431
+ if expr.name is not None:
432
+ result['name'] = expr.name
433
+ if expr.left is not None:
434
+ result['left'] = expr_to_dict(expr.left)
435
+ if expr.right is not None:
436
+ result['right'] = expr_to_dict(expr.right)
437
+ if expr.args is not None:
438
+ result['args'] = [expr_to_dict(arg) for arg in expr.args]
439
+ if expr.body is not None:
440
+ result['body'] = [expr_to_dict(node) for node in expr.body]
441
+
442
+ return result
443
+
444
+ return expr_to_dict(ast_expr)