reactxpy 0.1.0__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.
@@ -0,0 +1,2 @@
1
+ include src/*.cpp
2
+ include src/*.h
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: reactxpy
3
+ Version: 0.1.0
4
+ Summary: ReactXPy compiler for web applications.
5
+ Author: Anish Kumar
6
+ Dynamic: author
7
+ Dynamic: summary
@@ -0,0 +1,152 @@
1
+ # šŸš€ ReactXPy (Python Syntax for React)
2
+
3
+ Welcome to **ReactXPy**, a revolutionary framework that bridges the elegance of Python with the raw power of the React component ecosystem. ReactXPy is an ultra-fast, C++ based transpiler that allows developers to write feature-rich, interactive web applications using clean and readable Python syntax, entirely eliminating the configuration hell of modern JavaScript bundles.
4
+
5
+ If you love Python's indentation-based readability but need the dynamic, component-driven architecture of React, ReactXPy gives you both without needing Webpack, Vite, Babel, or Node.js running on your machine.
6
+
7
+ ---
8
+
9
+ ## ✨ Core Features (v2)
10
+
11
+ - **Pure Python Syntax for Components:** Define your UI components using standard `def ComponentName(props):` definitions, free of brackets and JavaScript boilerplate.
12
+ - **Native Inline JSX:** Seamlessly blend standard HTML/JSX tags directly inside your Python functions. The C++ parser intelligently distinguishes Python control flow from DOM declarations.
13
+ - **State & Hooks Engine (NEW):** ReactXPy v2 natively supports React Hooks! Utilize `useState` and `useEffect` with standard Python assignments and lambdas.
14
+ - **Dynamic Props & Interpolation:** Pass data across components naturally using `{props.value}` syntax. Evaluate complex math or logic inside interpolations instantly.
15
+ - **Native Event Handling:** Bind Python functions directly to DOM events like `onClick={triggerFunc}` without dealing with `this` binding or context scoping.
16
+ - **Powerful Conditional Rendering:** Drive UI states with intuitive boolean logic such as `{isActive && <div class="badge">Online</div>}` right inside the tree.
17
+ - **Zero-Dependency CLI Scaffold:** Get started in zero seconds. The built-in `create-reactxpy-app` generator instantly architectures a complete project for you.
18
+ - **Cross-Platform C++ Core:** The transpiler is compiled natively onto your machine (Windows `.exe`, macOS, or Linux) enabling lightning-fast, concurrent build times.
19
+ - **Local Dev Server Hook:** ReactXPy ships with a multi-threaded, hot-reloading native Python watcher (`dev.py`), replacing the need for NPM servers.
20
+
21
+ ---
22
+
23
+ ## šŸ“¦ Installation
24
+
25
+ ReactXPy is distributed globally via standard Python pip packages. Before beginning, ensure you are running Python 3.7+.
26
+
27
+ To install the framework globally onto your machine:
28
+
29
+ ```bash
30
+ pip install reactxpy
31
+ ```
32
+
33
+ Verify your installation was successful and the native C++ binary was compiled by checking the CLI tool:
34
+
35
+ ```bash
36
+ reactxpy --version
37
+ # Output: reactxpy version 0.1.0
38
+ ```
39
+
40
+ ---
41
+
42
+ ## šŸ› ļø Quick Start
43
+
44
+ ReactXPy ships with a state-of-the-art interactive CLI to generate standalone applications mimicking the best practices of modern frontend development.
45
+
46
+ 1. **Scaffold a Project**
47
+ Run the project generator from anywhere in your terminal:
48
+
49
+ ```bash
50
+ create-reactxpy-app my-awesome-app
51
+ ```
52
+
53
+ 2. **Launch the Live Server**
54
+ Navigate into your new application and execute the pure-Python hot reloader:
55
+ ```bash
56
+ cd my-awesome-app
57
+ python3 dev.py
58
+ ```
59
+
60
+ **That's it!** The `dev.py` script automatically watches your `src/` directory for filesystem changes. It instantly hot-recompiles your `.reactxpy` components into deeply-linked browser-safe Javascript bundles (`dist/bundle.js`) and serves it live at `http://localhost:3000`.
61
+
62
+ ---
63
+
64
+ ## šŸ“– Comprehensive Syntax Guide
65
+
66
+ ### 1. Components & Standard JSX
67
+
68
+ ReactXPy treats components naturally. You declare them identically to standard Python functions. When you return HTML DOM tags, the compiler natively intercepts it and translates the structure into optimized `React.createElement` syntax trees.
69
+
70
+ ```python
71
+ # Greet.reactxpy
72
+ def Greet(name):
73
+ return <div class="greeting-card">
74
+ <h3>Hello {name}!</h3>
75
+ <p>Welcome to the ReactXPy ecosystem.</p>
76
+ </div>
77
+ ```
78
+
79
+ ### 2. State Hooks (`useState` & `useEffect`)
80
+
81
+ ReactXPy v2 fully embraces the React runtime. You can manage encapsulated component states easily by destructuring `useState` tuples, and orchestrate browser lifecycle features like API calls or Local Storage using `useEffect`.
82
+
83
+ ```python
84
+ # CounterApp.reactxpy
85
+ def CounterApp():
86
+ # Native Python Tuple Destructuring
87
+ count, setCount = useState(0)
88
+
89
+ # Persist the count to the browser's storage whenever the `count` dependency updates
90
+ useEffect(lambda: localStorage.setItem("clicks", JSON.stringify(count)), [count])
91
+
92
+ def triggerIncrement():
93
+ setCount(count + 1)
94
+
95
+ return <div class="counter-panel">
96
+ <p>Total Clicks: {count}</p>
97
+ <button onClick={triggerIncrement}>Increment Value</button>
98
+ </div>
99
+ ```
100
+
101
+ ### 3. Conditional UI & Component Composition
102
+
103
+ ReactXPy supports infinitely nested component architectures. You can import modules seamlessly without Node syntax. It also securely translates HTML attributes (like `class`) into DOM-safe syntax (`className`) automatically.
104
+
105
+ ```python
106
+ # App.reactxpy
107
+ import CounterApp
108
+
109
+ def App():
110
+ isAdmin = True
111
+
112
+ return <main class="dashboard-wrapper">
113
+ <h1>Admin Control Panel</h1>
114
+
115
+ {isAdmin && <div class="secure-badge">Verified Session</div>}
116
+
117
+ <div class="widgets">
118
+ <CounterApp />
119
+ </div>
120
+ </main>
121
+ ```
122
+
123
+ ---
124
+
125
+ ## āš™ļø How the Architecture Works
126
+
127
+ 1. **Native OS Compilation:** When you `pip install reactxpy`, your computer leverages its local `g++` compiler to build a hyper-optimized `.exe` (Windows) or binary (Unix) of the ReactXPy transpiler directly within your Python packages folder.
128
+ 2. **Lexical Analysis Engine:** The C++ compiler scans your `.reactxpy` files. It fundamentally understands the boundary between Python variable assignments, indentations, scopes, and HTML tag delimiters.
129
+ 3. **AST Transpilation:** The framework safely merges Javascript operators (like `||` and `&&`), mathematical calculations, and JSX scopes into raw, standalone Javascript mappings.
130
+ 4. **Dependency-Free Bundle:** The compiler bridges your states via a lightweight `runtime.js` hook memory wrapper. It drops ES module syntax entirely—so you don't even need a server! You can double-click `index.html` directly from a USB stick and the app will flawlessly function offline in standard browsers.
131
+
132
+ ---
133
+
134
+ ## šŸ”® Development Roadmap
135
+
136
+ ReactXPy is an actively maintained open-source framework. The current horizon features include:
137
+
138
+ - [x] Transpilation of Standard JSX directly to `React` API calls.
139
+ - [x] Interactive State Management (`useState` Hooks).
140
+ - [x] Application Lifecycle Memory (`useEffect` Hooks).
141
+ - [x] Zero-Dependency Build Pipelines (`build.py` & `dev.py`).
142
+ - [x] Native Microsoft Windows (`.exe`) Subprocess Compilation.
143
+ - [ ] List Comprehension Syntax (e.g., `<item for item in array>`).
144
+ - [ ] Asynchronous API Fetching (`async/await` components).
145
+ - [ ] Deep Integrated Server-Side Python Routing.
146
+
147
+ ---
148
+
149
+
150
+ ### License
151
+
152
+ MIT License - Have fun building!
@@ -0,0 +1,3 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
File without changes
@@ -0,0 +1,36 @@
1
+ import os
2
+ import sys
3
+ import subprocess
4
+
5
+ def main():
6
+ # Handle version flags directly in the wrapper
7
+ if len(sys.argv) > 1 and sys.argv[1] in ["-v", "--version"]:
8
+ print("reactxpy version 0.1.0")
9
+ sys.exit(0)
10
+
11
+ # Find the compiled C++ compiler binary relative to this script
12
+ current_dir = os.path.dirname(os.path.abspath(__file__))
13
+ is_windows = sys.platform == "win32"
14
+ binary_name = "reactxpy_compiler.exe" if is_windows else "reactxpy_compiler"
15
+ compiler_path = os.path.join(current_dir, binary_name)
16
+
17
+ if not os.path.exists(compiler_path):
18
+ print(f"Error: ReactXPy compiler binary not found at {compiler_path}")
19
+ print("Please ensure the package was built correctly.")
20
+ sys.exit(1)
21
+
22
+ # Pass all arguments directly to the C++ compiler
23
+ args = [compiler_path] + sys.argv[1:]
24
+
25
+ try:
26
+ # Replaces the current process with the compiler
27
+ if is_windows:
28
+ sys.exit(subprocess.call(args))
29
+ else:
30
+ os.execv(compiler_path, args)
31
+ except OSError as e:
32
+ print(f"Failed to execute compiler: {e}")
33
+ sys.exit(1)
34
+
35
+ if __name__ == "__main__":
36
+ main()
@@ -0,0 +1,375 @@
1
+ import os
2
+ import sys
3
+
4
+ def create_file(path, content):
5
+ with open(path, 'w') as f:
6
+ f.write(content.strip() + '\n')
7
+ print(f"Created {path}")
8
+
9
+ def main():
10
+ if len(sys.argv) > 1 and sys.argv[1] in ["-h", "--help"]:
11
+ print("Usage: create-reactxpy-app [project-name]")
12
+ print("\\nOptions:")
13
+ print(" -h, --help Show this help message and exit.")
14
+ print(" -v, --version Show the version of create-reactxpy-app.")
15
+ print("\\nExample:")
16
+ print(" create-reactxpy-app my-new-project")
17
+ sys.exit(0)
18
+
19
+ if len(sys.argv) > 1 and sys.argv[1] in ["-v", "--version"]:
20
+ print("create-reactxpy-app version 0.1.0")
21
+ sys.exit(0)
22
+
23
+ print("\\033[0;34mWelcome to create-reactxpy-app! Let's scaffold your new project.\\033[0m\\n")
24
+
25
+ project_name = ""
26
+ if len(sys.argv) > 1:
27
+ project_name = sys.argv[1]
28
+
29
+ while not project_name:
30
+ try:
31
+ project_name = input("? What is your project named? ")
32
+ except (KeyboardInterrupt, EOFError):
33
+ print("\\nOperation cancelled.")
34
+ sys.exit(1)
35
+
36
+ project_name = project_name.strip()
37
+ if not project_name:
38
+ print("Error: Project name cannot be empty.")
39
+ sys.exit(1)
40
+
41
+ if os.path.exists(project_name):
42
+ print(f"Error: Directory '{project_name}' already exists.")
43
+ sys.exit(1)
44
+
45
+ print(f"\\nšŸš€ Creating a new ReactXPy project in {os.path.abspath(project_name)}...")
46
+
47
+ # Create directory structure
48
+ dirs = [
49
+ project_name,
50
+ os.path.join(project_name, "public"),
51
+ os.path.join(project_name, "src"),
52
+ os.path.join(project_name, "src", "components"),
53
+ os.path.join(project_name, "runtime")
54
+ ]
55
+
56
+ for d in dirs:
57
+ os.makedirs(d, exist_ok=True)
58
+
59
+ # App.pysx
60
+ app_pysx = """
61
+ import CounterApp
62
+
63
+ def App():
64
+ isAdmin = true
65
+
66
+ return <main class="dashboard-wrapper">
67
+ <h1>Admin Control Panel</h1>
68
+
69
+ {isAdmin && <div class="secure-badge">Verified Session</div>}
70
+
71
+ <div class="widgets">
72
+ <CounterApp />
73
+ </div>
74
+ </main>
75
+ """
76
+
77
+ # CounterApp.pysx
78
+ counterapp_pysx = """
79
+ def CounterApp():
80
+ count, setCount = useState(0)
81
+
82
+ useEffect(lambda: localStorage.setItem("clicks", JSON.stringify(count)), [count])
83
+
84
+ return <div class="counter-panel">
85
+ <p>Total Clicks: {count}</p>
86
+ <button onClick={lambda: setCount(count + 1)}>Increment Value</button>
87
+ </div>
88
+ """
89
+
90
+ # runtime.js
91
+ runtime_js = """
92
+ // runtime/runtime.js
93
+
94
+ // -----------------------------
95
+ // Hook wrappers (simple bridge)
96
+ // -----------------------------
97
+ function useState(initial) {
98
+ return React.useState(initial);
99
+ }
100
+
101
+ function useEffect(effect, deps) {
102
+ return React.useEffect(effect, deps);
103
+ }
104
+
105
+ // -----------------------------
106
+ // App runner
107
+ // -----------------------------
108
+ function run(App) {
109
+
110
+ const rootElement =
111
+ document.getElementById("root") ||
112
+ document.body;
113
+
114
+ const root = ReactDOM.createRoot(rootElement);
115
+
116
+ root.render(
117
+ React.createElement(App)
118
+ );
119
+ }
120
+
121
+ // -----------------------------
122
+ // Global API
123
+ // -----------------------------
124
+ window.ReactXPy = {
125
+ run,
126
+ useState,
127
+ useEffect
128
+ };
129
+ """
130
+
131
+ # index.html
132
+ index_html = """
133
+ <!DOCTYPE html>
134
+ <html>
135
+ <head>
136
+ <meta charset="UTF-8">
137
+ <title>ReactXPy App</title>
138
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
139
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
140
+ <link rel="stylesheet" href="./style.css">
141
+ </head>
142
+ <body>
143
+ <div id="root"></div>
144
+ <script src="../runtime/runtime.js"></script>
145
+ <script src="../dist/bundle.js"></script>
146
+ <script>
147
+ ReactXPy.run(App);
148
+
149
+ // Live Reload Hook
150
+ let currentVersion = null;
151
+ setInterval(() => {
152
+ fetch('/version').then(res => res.text()).then(version => {
153
+ if (currentVersion === null) currentVersion = version;
154
+ else if (currentVersion !== version) location.reload();
155
+ }).catch(() => {});
156
+ }, 1000);
157
+ </script>
158
+ </body>
159
+ </html>
160
+ """
161
+
162
+ # style.css
163
+ style_css = """
164
+ :root {
165
+ --bg-main: #f8fafc;
166
+ --card-bg: #ffffff;
167
+ --text-primary: #0f172a;
168
+ --text-secondary: #64748b;
169
+ --accent: #4f46e5;
170
+ --accent-hover: #4338ca;
171
+ --success-bg: #dcfce7;
172
+ --success-text: #166534;
173
+ }
174
+
175
+ body {
176
+ margin: 0;
177
+ font-family: 'Inter', system-ui, -apple-system, sans-serif;
178
+ background-color: var(--bg-main);
179
+ color: var(--text-primary);
180
+ display: flex;
181
+ justify-content: center;
182
+ padding-top: 60px;
183
+ }
184
+
185
+ .dashboard-wrapper {
186
+ background: var(--card-bg);
187
+ padding: 40px;
188
+ border-radius: 16px;
189
+ box-shadow: 0 10px 25px rgba(0,0,0,0.05);
190
+ text-align: center;
191
+ max-width: 400px;
192
+ width: 100%;
193
+ }
194
+
195
+ h1 {
196
+ font-size: 1.5rem;
197
+ margin-top: 0;
198
+ margin-bottom: 12px;
199
+ }
200
+
201
+ .secure-badge {
202
+ display: inline-block;
203
+ background: var(--success-bg);
204
+ color: var(--success-text);
205
+ padding: 6px 12px;
206
+ border-radius: 20px;
207
+ font-size: 0.85rem;
208
+ font-weight: 600;
209
+ margin-bottom: 30px;
210
+ }
211
+
212
+ .counter-panel {
213
+ background: #f1f5f9;
214
+ padding: 24px;
215
+ border-radius: 12px;
216
+ }
217
+
218
+ .counter-panel p {
219
+ font-size: 1.25rem;
220
+ font-weight: 600;
221
+ margin-top: 0;
222
+ color: var(--text-secondary);
223
+ }
224
+
225
+ button {
226
+ background: var(--accent);
227
+ color: white;
228
+ border: none;
229
+ padding: 12px 24px;
230
+ border-radius: 8px;
231
+ font-weight: 600;
232
+ font-size: 1rem;
233
+ cursor: pointer;
234
+ transition: 0.2s;
235
+ width: 100%;
236
+ }
237
+
238
+ button:hover {
239
+ background: var(--accent-hover);
240
+ transform: translateY(-2px);
241
+ }
242
+ """
243
+
244
+ # build.py
245
+ build_py = """
246
+ import os
247
+ import subprocess
248
+ from pathlib import Path
249
+
250
+ def main():
251
+ print("šŸš€ Building ReactXPy App...")
252
+
253
+ os.makedirs("dist", exist_ok=True)
254
+ compiled_files = []
255
+
256
+ from shutil import which
257
+ if which("reactxpy") is None:
258
+ print("āŒ Error: reactxpy compiler not found. Please install the reactxpy pip package globally.")
259
+ return
260
+
261
+ for file in Path("src").rglob("*.pysx"):
262
+ basename = file.stem
263
+ output_path = f"dist/{basename}.js"
264
+
265
+ print(f"⚔ Compiling: {file} -> {output_path}")
266
+ subprocess.run(["reactxpy", str(file), "-o", output_path], check=True)
267
+ compiled_files.append(output_path)
268
+
269
+ if compiled_files:
270
+ print("\\nšŸ”— Linking into dist/bundle.js...")
271
+ subprocess.run(["reactxpy", "--bundle"] + compiled_files + ["dist/bundle.js"], check=True)
272
+ print("\\nāœ… Success! Build complete.")
273
+ else:
274
+ print("āŒ Error: No .pysx files found in src directory.")
275
+
276
+ if __name__ == "__main__":
277
+ main()
278
+ """
279
+
280
+ # dev.py
281
+ dev_py = """
282
+ import os
283
+ import sys
284
+ import time
285
+ import subprocess
286
+ import threading
287
+ from pathlib import Path
288
+
289
+ BUILD_VERSION = 1
290
+
291
+ def get_mtimes():
292
+ mtimes = {}
293
+ for p in Path("src").rglob("*.pysx"):
294
+ mtimes[str(p)] = p.stat().st_mtime
295
+ return mtimes
296
+
297
+ def serve():
298
+ from http.server import SimpleHTTPRequestHandler
299
+ from socketserver import TCPServer
300
+
301
+ class QuietHandler(SimpleHTTPRequestHandler):
302
+ def log_message(self, format, *args):
303
+ pass # Keep terminal clean
304
+
305
+ def do_GET(self):
306
+ if self.path == '/version':
307
+ self.send_response(200)
308
+ self.send_header('Content-type', 'text/plain')
309
+ self.send_header('Access-Control-Allow-Origin', '*')
310
+ self.end_headers()
311
+ self.wfile.write(str(BUILD_VERSION).encode())
312
+ else:
313
+ super().do_GET()
314
+
315
+ TCPServer.allow_reuse_address = True
316
+ try:
317
+ httpd = TCPServer(("", 3000), QuietHandler)
318
+ print("🌐 Live Server running at http://localhost:3000/public/index.html")
319
+ httpd.serve_forever()
320
+ except OSError as e:
321
+ print(f"āŒ Could not start dev server: {e}")
322
+ sys.exit(1)
323
+
324
+ def main():
325
+ global BUILD_VERSION
326
+ print("šŸš€ Starting ReactXPy Live Development Server...")
327
+ subprocess.run([sys.executable, "build.py"], check=False)
328
+
329
+ server_thread = threading.Thread(target=serve, daemon=True)
330
+ server_thread.start()
331
+
332
+ print("šŸ‘€ Watching for file changes in src/ directory...")
333
+ last_mtimes = get_mtimes()
334
+
335
+ try:
336
+ while True:
337
+ time.sleep(0.5)
338
+ current_mtimes = get_mtimes()
339
+
340
+ if current_mtimes != last_mtimes:
341
+ print("\\n✨ File change detected! Rebuilding...")
342
+ subprocess.run([sys.executable, "build.py"], check=False)
343
+ last_mtimes = current_mtimes
344
+ BUILD_VERSION += 1
345
+
346
+ except KeyboardInterrupt:
347
+ print("\\nšŸ›‘ Stopping dev server...")
348
+ sys.exit(0)
349
+
350
+ if __name__ == "__main__":
351
+ main()
352
+ """
353
+
354
+ create_file(os.path.join(project_name, "src", "App.pysx"), app_pysx)
355
+ create_file(os.path.join(project_name, "src", "components", "CounterApp.pysx"), counterapp_pysx)
356
+ create_file(os.path.join(project_name, "runtime", "runtime.js"), runtime_js)
357
+ create_file(os.path.join(project_name, "public", "index.html"), index_html)
358
+ create_file(os.path.join(project_name, "public", "style.css"), style_css)
359
+
360
+ build_script = os.path.join(project_name, "build.py")
361
+ create_file(build_script, build_py)
362
+
363
+ dev_script = os.path.join(project_name, "dev.py")
364
+ create_file(dev_script, dev_py)
365
+
366
+ os.chmod(build_script, 0o755) # Make executable
367
+ os.chmod(dev_script, 0o755)
368
+
369
+ print(f"\\nāœ… Project '{project_name}' created successfully!")
370
+ print("\\nNext steps:")
371
+ print(f" cd {project_name}")
372
+ print(" python3 dev.py")
373
+
374
+ if __name__ == "__main__":
375
+ main()
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: reactxpy
3
+ Version: 0.1.0
4
+ Summary: ReactXPy compiler for web applications.
5
+ Author: Anish Kumar
6
+ Dynamic: author
7
+ Dynamic: summary
@@ -0,0 +1,24 @@
1
+ MANIFEST.in
2
+ README.md
3
+ pyproject.toml
4
+ setup.py
5
+ reactxpy/__init__.py
6
+ reactxpy/cli.py
7
+ reactxpy/create_app.py
8
+ reactxpy.egg-info/PKG-INFO
9
+ reactxpy.egg-info/SOURCES.txt
10
+ reactxpy.egg-info/dependency_links.txt
11
+ reactxpy.egg-info/entry_points.txt
12
+ reactxpy.egg-info/not-zip-safe
13
+ reactxpy.egg-info/top_level.txt
14
+ src/ast.h
15
+ src/generator.cpp
16
+ src/generator.h
17
+ src/lexer.cpp
18
+ src/lexer.h
19
+ src/linker.cpp
20
+ src/linker.h
21
+ src/main.cpp
22
+ src/parser.cpp
23
+ src/parser.h
24
+ src/test_parser.cpp
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ create-reactxpy-app = reactxpy.create_app:main
3
+ reactxpy = reactxpy.cli:main
@@ -0,0 +1 @@
1
+ reactxpy
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+