diff --git a/README.de.md b/README.de.md new file mode 100644 index 0000000..49836c3 --- /dev/null +++ b/README.de.md @@ -0,0 +1,121 @@ +# [Client Side Python](https://github.com/europanite/client_side_python "Client Side Python") + +[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +![OS](https://img.shields.io/badge/OS-Linux%20%7C%20macOS%20%7C%20Windows-blue) +[![CI](https://github.com/europanite/client_side_python/actions/workflows/ci.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/ci.yml) +[![Frontend Tests via Docker](https://github.com/europanite/client_side_python/actions/workflows/docker.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/docker.yml) +[![Deploy Expo Web to GitHub Pages](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml) + +![React Native](https://img.shields.io/badge/react_native-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB) +![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) +![Jest](https://img.shields.io/badge/-jest-%23C21325?style=for-the-badge&logo=jest&logoColor=white) +![Expo](https://img.shields.io/badge/expo-1C1E24?style=for-the-badge&logo=expo&logoColor=#D04A37) + +

+ 🇺🇸 English | + 🇯🇵 日本語 | + 🇨🇳 简体中文 | + 🇪🇸 Español | + 🇧🇷 Português (Brasil) | + 🇰🇷 한국어 | + 🇩🇪 Deutsch | + 🇫🇷 Français +

+ + +> **Note** +> This is a translated version of this README. The English version (`README.md`) is the source of truth. + +!["web_ui"](./assets/images/web_ui.png) + + [PlayGround](https://europanite.github.io/client_side_python/) + +Ein browserbasiertes Python-Playground, das vollständig clientseitig läuft. + +--- + +## Überblick + +Client Side Python ist ein **browserbasiertes Python-Playground auf Basis von Pyodide**. +Der gesamte Python-Code wird **vollständig innerhalb deines Browser-Tabs ausgeführt** (WebAssembly, kein Backend), sodass dein Code deine Maschine nie verlässt. + +Dadurch eignet es sich gut für: + +- Das schnelle Ausprobieren kleiner Python-Snippets +- Das Vorführen von Python-Grundlagen im Unterricht oder in Workshops +- Das Experimentieren mit einfachen numerischen oder Skript-Aufgaben in einer sicheren Sandbox +- Das Zeigen, wie WebAssembly + Pyodide „echtes“ Python in den Browser bringen können + +--- + +## Funktionen + +- **Vollständig clientseitige Ausführung** + - Verwendet [Pyodide](https://pyodide.org), um CPython in WebAssembly auszuführen. + - Standardmäßig sind weder Server, Datenbank noch Authentifizierung erforderlich. + +- **Einfacher Code-Editor + Konsole** + - Textbereich für Python-Code. + - Konsolenbereich, der `stdout` und `stderr` anzeigt. + - Schaltflächen: **Run**, **Stop**, **Clear**, **Load Sample**, **Copy Output**. + +- **Sanfter „Stop“-Mechanismus** + - Die Ausführung ist mit einem Soft-Cancel-Token umhüllt. + - Wenn du **Stop** drückst, wird der aktuelle Lauf logisch abgebrochen, sodass verspätete Ergebnisse ignoriert werden, anstatt die UI zu beschädigen. + +- **Responsives Web-UI** + - Erstellt mit **Expo / React Native Web** und **Material UI**-Komponenten. + - Das Layout passt sich an unterschiedliche Viewport-Größen an (Desktop / Tablet). + +- **Deterministische CI über Docker** + - Jest-Tests laufen in einem Docker-Container mit `docker-compose.test.yml`. + - GitHub-Actions-Workflows für CI und Docker-basierte Tests sind enthalten. + +- **Automatische Bereitstellung auf GitHub Pages** + - Ein GitHub-Actions-Workflow baut das Expo-Web-Bundle und veröffentlicht es für den Branch `main` auf GitHub Pages. + +--- + +## Funktionsweise + +Beim ersten Laden der App passiert Folgendes: + +1. Pyodide wird von einem CDN geladen. +2. Die Pyodide-Laufzeit wird initialisiert und `runPythonAsync` wird verfügbar gemacht. +3. Benutzerdefinierte Handler für `stdout` und `stderr` werden angebunden, damit Python-Ausgaben in die Konsole auf der Seite gestreamt werden. +4. Ein einfaches Ausführungs-Token wird verwendet, um einen **soft Stop** zu implementieren: + - Jeder Lauf erhöht eine interne `execId`. + - Wenn ein Lauf mit einer veralteten `execId` endet, wird seine Ausgabe verworfen. + - Dadurch wird verhindert, dass veraltete Ergebnisse älterer Läufe die Konsole verschmutzen. + +All das geschieht **im Browser**, ganz ohne Backend-API-Aufrufe. + +--- + +## 🚀 Erste Schritte + +### 1. Voraussetzungen +- [Docker](https://www.docker.com/) und [Docker Compose](https://docs.docker.com/compose/) + +### 2. Alle Services bauen und starten: + +```bash +# set environment variables: +export REACT_NATIVE_PACKAGER_HOSTNAME=${YOUR_HOST} + +# Build the image +docker compose build + +# Run the container +docker compose up +``` + +### 3. Testen: +```bash +docker compose -f docker-compose.test.yml up --build --exit-code-from frontend_test +``` + +--- + +# License +- Apache License 2.0 diff --git a/README.es.md b/README.es.md new file mode 100644 index 0000000..f8512ec --- /dev/null +++ b/README.es.md @@ -0,0 +1,121 @@ +# [Client Side Python](https://github.com/europanite/client_side_python "Client Side Python") + +[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +![OS](https://img.shields.io/badge/OS-Linux%20%7C%20macOS%20%7C%20Windows-blue) +[![CI](https://github.com/europanite/client_side_python/actions/workflows/ci.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/ci.yml) +[![Frontend Tests via Docker](https://github.com/europanite/client_side_python/actions/workflows/docker.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/docker.yml) +[![Deploy Expo Web to GitHub Pages](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml) + +![React Native](https://img.shields.io/badge/react_native-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB) +![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) +![Jest](https://img.shields.io/badge/-jest-%23C21325?style=for-the-badge&logo=jest&logoColor=white) +![Expo](https://img.shields.io/badge/expo-1C1E24?style=for-the-badge&logo=expo&logoColor=#D04A37) + +

+ 🇺🇸 English | + 🇯🇵 日本語 | + 🇨🇳 简体中文 | + 🇪🇸 Español | + 🇧🇷 Português (Brasil) | + 🇰🇷 한국어 | + 🇩🇪 Deutsch | + 🇫🇷 Français +

+ + +> **Note** +> This is a translated version of this README. The English version (`README.md`) is the source of truth. + +!["web_ui"](./assets/images/web_ui.png) + + [PlayGround](https://europanite.github.io/client_side_python/) + +Un playground de Python del lado del cliente y basado en el navegador. + +--- + +## Descripción general + +Client Side Python es un **playground de Python basado en el navegador e impulsado por Pyodide**. +Todo el código Python se ejecuta **por completo dentro de tu pestaña del navegador** (WebAssembly, sin backend), por lo que tu código nunca sale de tu máquina. + +Esto lo hace útil para: + +- Probar rápidamente pequeños fragmentos de código Python +- Demostrar conceptos básicos de Python en una clase o taller +- Experimentar con tareas numéricas o de scripting sencillas en un entorno aislado y seguro +- Mostrar cómo WebAssembly + Pyodide pueden llevar Python “real” al navegador + +--- + +## Características + +- **Ejecución totalmente del lado del cliente** + - Usa [Pyodide](https://pyodide.org) para ejecutar CPython en WebAssembly. + - No requiere servidor, base de datos ni autenticación por defecto. + +- **Editor de código simple + consola** + - Área de texto para código Python. + - Área de consola que muestra `stdout` y `stderr`. + - Botones: **Run**, **Stop**, **Clear**, **Load Sample**, **Copy Output**. + +- **Mecanismo de “Stop” suave** + - La ejecución está envuelta en un token de cancelación suave. + - Cuando pulsas **Stop**, la ejecución actual se cancela lógicamente para que los resultados tardíos se ignoren en lugar de romper la interfaz. + +- **Interfaz web responsive** + - Construida con **Expo / React Native Web** y componentes de **Material UI**. + - El diseño se adapta a distintos tamaños de viewport (escritorio / tablet). + +- **CI determinista con Docker** + - Las pruebas de Jest se ejecutan dentro de un contenedor Docker usando `docker-compose.test.yml`. + - Se incluyen workflows de GitHub Actions para CI y pruebas basadas en Docker. + +- **Despliegue automático en GitHub Pages** + - Un workflow de GitHub Actions compila el bundle web de Expo y lo publica en GitHub Pages para la rama `main`. + +--- + +## Cómo funciona + +En la primera carga, la aplicación: + +1. Obtiene Pyodide desde una CDN. +2. Inicializa el runtime de Pyodide y expone `runPythonAsync`. +3. Adjunta handlers personalizados para `stdout` y `stderr` para que la salida de Python se envíe en streaming a la consola integrada. +4. Usa un token de ejecución simple para implementar un **soft Stop**: + - Cada ejecución incrementa un `execId` interno. + - Si una ejecución finaliza con un `execId` desactualizado, su salida se descarta. + - Esto evita que resultados obsoletos de ejecuciones anteriores contaminen la consola. + +Todo esto sucede **en el navegador**, sin llamadas a ninguna API backend. + +--- + +## 🚀 Primeros pasos + +### 1. Requisitos previos +- [Docker](https://www.docker.com/) y [Docker Compose](https://docs.docker.com/compose/) + +### 2. Compila e inicia todos los servicios: + +```bash +# set environment variables: +export REACT_NATIVE_PACKAGER_HOSTNAME=${YOUR_HOST} + +# Build the image +docker compose build + +# Run the container +docker compose up +``` + +### 3. Pruebas: +```bash +docker compose -f docker-compose.test.yml up --build --exit-code-from frontend_test +``` + +--- + +# License +- Apache License 2.0 diff --git a/README.fr.md b/README.fr.md new file mode 100644 index 0000000..9b3c669 --- /dev/null +++ b/README.fr.md @@ -0,0 +1,121 @@ +# [Client Side Python](https://github.com/europanite/client_side_python "Client Side Python") + +[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +![OS](https://img.shields.io/badge/OS-Linux%20%7C%20macOS%20%7C%20Windows-blue) +[![CI](https://github.com/europanite/client_side_python/actions/workflows/ci.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/ci.yml) +[![Frontend Tests via Docker](https://github.com/europanite/client_side_python/actions/workflows/docker.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/docker.yml) +[![Deploy Expo Web to GitHub Pages](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml) + +![React Native](https://img.shields.io/badge/react_native-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB) +![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) +![Jest](https://img.shields.io/badge/-jest-%23C21325?style=for-the-badge&logo=jest&logoColor=white) +![Expo](https://img.shields.io/badge/expo-1C1E24?style=for-the-badge&logo=expo&logoColor=#D04A37) + +

+ 🇺🇸 English | + 🇯🇵 日本語 | + 🇨🇳 简体中文 | + 🇪🇸 Español | + 🇧🇷 Português (Brasil) | + 🇰🇷 한국어 | + 🇩🇪 Deutsch | + 🇫🇷 Français +

+ + +> **Note** +> This is a translated version of this README. The English version (`README.md`) is the source of truth. + +!["web_ui"](./assets/images/web_ui.png) + + [PlayGround](https://europanite.github.io/client_side_python/) + +Un playground Python côté client, accessible directement dans le navigateur. + +--- + +## Vue d’ensemble + +Client Side Python est un **playground Python basé sur le navigateur et propulsé par Pyodide**. +Tout le code Python s’exécute **entièrement dans votre onglet de navigateur** (WebAssembly, sans backend), donc votre code ne quitte jamais votre machine. + +Cela le rend utile pour : + +- Tester rapidement de petits extraits de code Python +- Présenter les bases de Python en classe ou en atelier +- Expérimenter des tâches numériques simples ou du scripting dans un sandbox sécurisé +- Montrer comment WebAssembly + Pyodide peuvent apporter du Python “réel” dans le navigateur + +--- + +## Fonctionnalités + +- **Exécution entièrement côté client** + - Utilise [Pyodide](https://pyodide.org) pour exécuter CPython dans WebAssembly. + - Aucun serveur, aucune base de données et aucune authentification ne sont requis par défaut. + +- **Éditeur de code simple + console** + - Zone de texte pour le code Python. + - Zone de console affichant `stdout` et `stderr`. + - Boutons : **Run**, **Stop**, **Clear**, **Load Sample**, **Copy Output**. + +- **Mécanisme de “Stop” souple** + - L’exécution est encapsulée dans un token d’annulation souple. + - Lorsque vous appuyez sur **Stop**, l’exécution en cours est annulée de façon logique, de sorte que les résultats tardifs soient ignorés au lieu de casser l’interface. + +- **Interface web responsive** + - Construite avec **Expo / React Native Web** et des composants **Material UI**. + - La mise en page s’adapte à différentes tailles de viewport (desktop / tablette). + +- **CI déterministe via Docker** + - Les tests Jest s’exécutent dans un conteneur Docker à l’aide de `docker-compose.test.yml`. + - Des workflows GitHub Actions sont fournis pour la CI et les tests basés sur Docker. + +- **Déploiement automatique vers GitHub Pages** + - Un workflow GitHub Actions construit le bundle web Expo et le publie sur GitHub Pages pour la branche `main`. + +--- + +## Fonctionnement + +Lors du premier chargement, l’application : + +1. Récupère Pyodide depuis un CDN. +2. Initialise le runtime Pyodide et expose `runPythonAsync`. +3. Attache des gestionnaires personnalisés pour `stdout` et `stderr` afin que la sortie Python soit diffusée dans la console intégrée à la page. +4. Utilise un jeton d’exécution simple pour implémenter un **soft Stop** : + - Chaque exécution incrémente un `execId` interne. + - Si une exécution se termine avec un `execId` obsolète, sa sortie est ignorée. + - Cela empêche les résultats périmés d’anciennes exécutions de polluer la console. + +Tout cela se passe **dans le navigateur**, sans aucun appel à une API backend. + +--- + +## 🚀 Bien démarrer + +### 1. Prérequis +- [Docker](https://www.docker.com/) et [Docker Compose](https://docs.docker.com/compose/) + +### 2. Construire et démarrer tous les services : + +```bash +# set environment variables: +export REACT_NATIVE_PACKAGER_HOSTNAME=${YOUR_HOST} + +# Build the image +docker compose build + +# Run the container +docker compose up +``` + +### 3. Tester : +```bash +docker compose -f docker-compose.test.yml up --build --exit-code-from frontend_test +``` + +--- + +# License +- Apache License 2.0 diff --git a/README.ja.md b/README.ja.md new file mode 100644 index 0000000..d50b1f0 --- /dev/null +++ b/README.ja.md @@ -0,0 +1,121 @@ +# [Client Side Python](https://github.com/europanite/client_side_python "Client Side Python") + +[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +![OS](https://img.shields.io/badge/OS-Linux%20%7C%20macOS%20%7C%20Windows-blue) +[![CI](https://github.com/europanite/client_side_python/actions/workflows/ci.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/ci.yml) +[![Frontend Tests via Docker](https://github.com/europanite/client_side_python/actions/workflows/docker.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/docker.yml) +[![Deploy Expo Web to GitHub Pages](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml) + +![React Native](https://img.shields.io/badge/react_native-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB) +![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) +![Jest](https://img.shields.io/badge/-jest-%23C21325?style=for-the-badge&logo=jest&logoColor=white) +![Expo](https://img.shields.io/badge/expo-1C1E24?style=for-the-badge&logo=expo&logoColor=#D04A37) + +

+ 🇺🇸 English | + 🇯🇵 日本語 | + 🇨🇳 简体中文 | + 🇪🇸 Español | + 🇧🇷 Português (Brasil) | + 🇰🇷 한국어 | + 🇩🇪 Deutsch | + 🇫🇷 Français +

+ + +> **Note** +> This is a translated version of this README. The English version (`README.md`) is the source of truth. + +!["web_ui"](./assets/images/web_ui.png) + + [PlayGround](https://europanite.github.io/client_side_python/) + +ブラウザ上で動作するクライアントサイドの Python プレイグラウンド。 + +--- + +## 概要 + +Client Side Python は、**Pyodide を利用したブラウザベースの Python プレイグラウンド**である。 +すべての Python コードは **ブラウザタブ内で完結して実行される**(WebAssembly、バックエンドなし)ため、コードがマシンの外に出ることはない。 + +そのため、次のような用途に向いている。 + +- 小さな Python スニペットをすばやく試す +- 授業やワークショップで Python の基礎を実演する +- 安全なサンドボックスで簡単な数値処理やスクリプト作業を試す +- WebAssembly + Pyodide によって“本物の” Python をブラウザに持ち込めることを示す + +--- + +## 特長 + +- **完全なクライアントサイド実行** + - [Pyodide](https://pyodide.org) を使用して、WebAssembly 上で CPython を実行する。 + - デフォルトではサーバー、データベース、認証は不要。 + +- **シンプルなコードエディタ + コンソール** + - Python コード用のテキストエリア。 + - `stdout` と `stderr` を表示するコンソール領域。 + - ボタン: **Run**, **Stop**, **Clear**, **Load Sample**, **Copy Output**。 + +- **ソフトな“Stop”機構** + - 実行はソフトキャンセルトークンでラップされる。 + - **Stop** を押すと、現在の実行は論理的にキャンセルされ、遅れて返ってきた結果は UI を壊す代わりに無視される。 + +- **レスポンシブな Web UI** + - **Expo / React Native Web** と **Material UI** コンポーネントで構築。 + - レイアウトは異なるビューポートサイズ(デスクトップ / タブレット)に適応する。 + +- **Docker による決定的な CI** + - Jest テストは `docker-compose.test.yml` を使って Docker コンテナ内で実行される。 + - GitHub Actions のワークフローが CI と Docker ベースのテスト用に用意されている。 + +- **GitHub Pages への自動デプロイ** + - GitHub Actions ワークフローが Expo Web バンドルをビルドし、`main` ブランチ向けに GitHub Pages へ公開する。 + +--- + +## 仕組み + +初回ロード時に、アプリは次の処理を行う。 + +1. CDN から Pyodide を取得する。 +2. Pyodide ランタイムを初期化し、`runPythonAsync` を公開する。 +3. Python の出力をページ内コンソールへストリーミングするために、`stdout` と `stderr` 用のカスタムハンドラを接続する。 +4. シンプルな実行トークンを使って、**soft Stop** を実装する。 + - 実行のたびに内部 `execId` をインクリメントする。 + - 古い `execId` を持つ実行が完了した場合、その出力は破棄される。 + - これにより、古い実行結果がコンソールを汚染するのを防ぐ。 + +これらはすべて **ブラウザ内** で行われ、バックエンド API の呼び出しは一切発生しない。 + +--- + +## 🚀 はじめに + +### 1. 前提条件 +- [Docker](https://www.docker.com/) と [Docker Compose](https://docs.docker.com/compose/) + +### 2. すべてのサービスをビルドして起動する + +```bash +# set environment variables: +export REACT_NATIVE_PACKAGER_HOSTNAME=${YOUR_HOST} + +# Build the image +docker compose build + +# Run the container +docker compose up +``` + +### 3. テスト +```bash +docker compose -f docker-compose.test.yml up --build --exit-code-from frontend_test +``` + +--- + +# License +- Apache License 2.0 diff --git a/README.ko.md b/README.ko.md new file mode 100644 index 0000000..9bc72c0 --- /dev/null +++ b/README.ko.md @@ -0,0 +1,121 @@ +# [Client Side Python](https://github.com/europanite/client_side_python "Client Side Python") + +[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +![OS](https://img.shields.io/badge/OS-Linux%20%7C%20macOS%20%7C%20Windows-blue) +[![CI](https://github.com/europanite/client_side_python/actions/workflows/ci.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/ci.yml) +[![Frontend Tests via Docker](https://github.com/europanite/client_side_python/actions/workflows/docker.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/docker.yml) +[![Deploy Expo Web to GitHub Pages](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml) + +![React Native](https://img.shields.io/badge/react_native-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB) +![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) +![Jest](https://img.shields.io/badge/-jest-%23C21325?style=for-the-badge&logo=jest&logoColor=white) +![Expo](https://img.shields.io/badge/expo-1C1E24?style=for-the-badge&logo=expo&logoColor=#D04A37) + +

+ 🇺🇸 English | + 🇯🇵 日本語 | + 🇨🇳 简体中文 | + 🇪🇸 Español | + 🇧🇷 Português (Brasil) | + 🇰🇷 한국어 | + 🇩🇪 Deutsch | + 🇫🇷 Français +

+ + +> **Note** +> This is a translated version of this README. The English version (`README.md`) is the source of truth. + +!["web_ui"](./assets/images/web_ui.png) + + [PlayGround](https://europanite.github.io/client_side_python/) + +브라우저에서 실행되는 클라이언트 사이드 기반 Python 플레이그라운드. + +--- + +## 개요 + +Client Side Python은 **Pyodide로 구동되는 브라우저 기반 Python 플레이그라운드**이다. +모든 Python 코드는 **브라우저 탭 내부에서 완전히 실행되며**(WebAssembly, 백엔드 없음), 따라서 코드가 사용자의 컴퓨터 밖으로 나가지 않는다. + +이 도구는 다음과 같은 용도에 적합하다. + +- 작은 Python 스니펫을 빠르게 시험해 보기 +- 수업이나 워크숍에서 Python 기초를 시연하기 +- 안전한 샌드박스에서 간단한 수치 계산이나 스크립트 작업을 실험하기 +- WebAssembly + Pyodide가 브라우저에 “진짜” Python을 어떻게 가져올 수 있는지 보여주기 + +--- + +## 기능 + +- **완전한 클라이언트 사이드 실행** + - [Pyodide](https://pyodide.org)를 사용해 WebAssembly에서 CPython을 실행한다. + - 기본적으로 서버, 데이터베이스, 인증이 필요 없다. + +- **간단한 코드 에디터 + 콘솔** + - Python 코드를 위한 텍스트 영역. + - `stdout` 및 `stderr`를 표시하는 콘솔 영역. + - 버튼: **Run**, **Stop**, **Clear**, **Load Sample**, **Copy Output**. + +- **부드러운 “Stop” 메커니즘** + - 실행은 소프트 취소 토큰으로 감싸져 있다. + - **Stop**을 누르면 현재 실행이 논리적으로 취소되며, 늦게 도착한 결과는 UI를 망가뜨리는 대신 무시된다. + +- **반응형 웹 UI** + - **Expo / React Native Web**과 **Material UI** 컴포넌트로 구축되었다. + - 레이아웃은 다양한 뷰포트 크기(데스크톱 / 태블릿)에 맞게 조정된다. + +- **Docker를 통한 결정적 CI** + - Jest 테스트는 `docker-compose.test.yml`을 사용해 Docker 컨테이너에서 실행된다. + - CI 및 Docker 기반 테스트를 위한 GitHub Actions 워크플로가 제공된다. + +- **GitHub Pages로 자동 배포** + - GitHub Actions 워크플로가 Expo 웹 번들을 빌드하고 `main` 브랜치용 GitHub Pages에 게시한다. + +--- + +## 동작 방식 + +앱이 처음 로드되면 다음 작업을 수행한다. + +1. CDN에서 Pyodide를 가져온다. +2. Pyodide 런타임을 초기화하고 `runPythonAsync`를 노출한다. +3. Python 출력이 페이지 내 콘솔로 스트리밍되도록 `stdout` 및 `stderr`용 커스텀 핸들러를 연결한다. +4. 간단한 실행 토큰을 사용해 **soft Stop**을 구현한다. + - 각 실행마다 내부 `execId`가 증가한다. + - 오래된 `execId`를 가진 실행이 끝나면 해당 출력은 버려진다. + - 이를 통해 이전 실행의 오래된 결과가 콘솔을 오염시키는 것을 막는다. + +이 모든 과정은 **브라우저 내부**에서 이루어지며, 백엔드 API 호출은 전혀 필요하지 않다. + +--- + +## 🚀 시작하기 + +### 1. 사전 요구 사항 +- [Docker](https://www.docker.com/) 및 [Docker Compose](https://docs.docker.com/compose/) + +### 2. 모든 서비스를 빌드하고 시작하기: + +```bash +# set environment variables: +export REACT_NATIVE_PACKAGER_HOSTNAME=${YOUR_HOST} + +# Build the image +docker compose build + +# Run the container +docker compose up +``` + +### 3. 테스트: +```bash +docker compose -f docker-compose.test.yml up --build --exit-code-from frontend_test +``` + +--- + +# License +- Apache License 2.0 diff --git a/README.md b/README.md index 5ec3b44..f25dff1 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,19 @@ ![Jest](https://img.shields.io/badge/-jest-%23C21325?style=for-the-badge&logo=jest&logoColor=white) ![Expo](https://img.shields.io/badge/expo-1C1E24?style=for-the-badge&logo=expo&logoColor=#D04A37) +At the top of every file, include this language selector: + +

+ 🇺🇸 English | + 🇯🇵 日本語 | + 🇨🇳 简体中文 | + 🇪🇸 Español | + 🇧🇷 Português (Brasil) | + 🇰🇷 한국어 | + 🇩🇪 Deutsch | + 🇫🇷 Français +

+ !["web_ui"](./assets/images/web_ui.png) [PlayGround](https://europanite.github.io/client_side_python/) diff --git a/README.pt-BR.md b/README.pt-BR.md new file mode 100644 index 0000000..e20b65e --- /dev/null +++ b/README.pt-BR.md @@ -0,0 +1,121 @@ +# [Client Side Python](https://github.com/europanite/client_side_python "Client Side Python") + +[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +![OS](https://img.shields.io/badge/OS-Linux%20%7C%20macOS%20%7C%20Windows-blue) +[![CI](https://github.com/europanite/client_side_python/actions/workflows/ci.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/ci.yml) +[![Frontend Tests via Docker](https://github.com/europanite/client_side_python/actions/workflows/docker.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/docker.yml) +[![Deploy Expo Web to GitHub Pages](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml) + +![React Native](https://img.shields.io/badge/react_native-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB) +![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) +![Jest](https://img.shields.io/badge/-jest-%23C21325?style=for-the-badge&logo=jest&logoColor=white) +![Expo](https://img.shields.io/badge/expo-1C1E24?style=for-the-badge&logo=expo&logoColor=#D04A37) + +

+ 🇺🇸 English | + 🇯🇵 日本語 | + 🇨🇳 简体中文 | + 🇪🇸 Español | + 🇧🇷 Português (Brasil) | + 🇰🇷 한국어 | + 🇩🇪 Deutsch | + 🇫🇷 Français +

+ + +> **Note** +> This is a translated version of this README. The English version (`README.md`) is the source of truth. + +!["web_ui"](./assets/images/web_ui.png) + + [PlayGround](https://europanite.github.io/client_side_python/) + +Um playground de Python baseado em navegador e executado no lado do cliente. + +--- + +## Visão geral + +Client Side Python é um **playground de Python baseado em navegador, alimentado por Pyodide**. +Todo o código Python é executado **inteiramente dentro da aba do navegador** (WebAssembly, sem backend), então seu código nunca sai da sua máquina. + +Isso o torna útil para: + +- Testar rapidamente pequenos trechos de código Python +- Demonstrar conceitos básicos de Python em sala de aula ou workshops +- Experimentar tarefas simples de cálculo numérico ou scripting em um sandbox seguro +- Mostrar como WebAssembly + Pyodide podem levar Python “de verdade” para o navegador + +--- + +## Recursos + +- **Execução totalmente no lado do cliente** + - Usa [Pyodide](https://pyodide.org) para executar CPython em WebAssembly. + - Nenhum servidor, banco de dados ou autenticação é necessário por padrão. + +- **Editor de código simples + console** + - Área de texto para código Python. + - Área de console que mostra `stdout` e `stderr`. + - Botões: **Run**, **Stop**, **Clear**, **Load Sample**, **Copy Output**. + +- **Mecanismo de “Stop” suave** + - A execução é encapsulada com um token de cancelamento suave. + - Quando você pressiona **Stop**, a execução atual é logicamente cancelada para que resultados tardios sejam ignorados em vez de quebrar a UI. + +- **Interface web responsiva** + - Construída com **Expo / React Native Web** e componentes do **Material UI**. + - O layout se adapta a diferentes tamanhos de viewport (desktop / tablet). + +- **CI determinístico via Docker** + - Os testes com Jest são executados em um contêiner Docker usando `docker-compose.test.yml`. + - Workflows do GitHub Actions são fornecidos para CI e testes baseados em Docker. + +- **Deploy automático no GitHub Pages** + - Um workflow do GitHub Actions compila o bundle web do Expo e o publica no GitHub Pages para a branch `main`. + +--- + +## Como funciona + +Na primeira carga, o aplicativo: + +1. Busca o Pyodide a partir de uma CDN. +2. Inicializa o runtime do Pyodide e expõe `runPythonAsync`. +3. Anexa handlers personalizados para `stdout` e `stderr`, para que a saída do Python seja transmitida para o console na página. +4. Usa um token de execução simples para implementar um **soft Stop**: + - Cada execução incrementa um `execId` interno. + - Se uma execução terminar com um `execId` desatualizado, sua saída será descartada. + - Isso evita que resultados antigos contaminem o console. + +Tudo isso acontece **no navegador**, sem nenhuma chamada a APIs de backend. + +--- + +## 🚀 Primeiros passos + +### 1. Pré-requisitos +- [Docker](https://www.docker.com/) e [Docker Compose](https://docs.docker.com/compose/) + +### 2. Compile e inicie todos os serviços: + +```bash +# set environment variables: +export REACT_NATIVE_PACKAGER_HOSTNAME=${YOUR_HOST} + +# Build the image +docker compose build + +# Run the container +docker compose up +``` + +### 3. Teste: +```bash +docker compose -f docker-compose.test.yml up --build --exit-code-from frontend_test +``` + +--- + +# License +- Apache License 2.0 diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 0000000..73b9dda --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,121 @@ +# [Client Side Python](https://github.com/europanite/client_side_python "Client Side Python") + +[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +![OS](https://img.shields.io/badge/OS-Linux%20%7C%20macOS%20%7C%20Windows-blue) +[![CI](https://github.com/europanite/client_side_python/actions/workflows/ci.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/ci.yml) +[![Frontend Tests via Docker](https://github.com/europanite/client_side_python/actions/workflows/docker.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/docker.yml) +[![Deploy Expo Web to GitHub Pages](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml/badge.svg)](https://github.com/europanite/client_side_python/actions/workflows/deploy-pages.yml) + +![React Native](https://img.shields.io/badge/react_native-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB) +![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) +![Jest](https://img.shields.io/badge/-jest-%23C21325?style=for-the-badge&logo=jest&logoColor=white) +![Expo](https://img.shields.io/badge/expo-1C1E24?style=for-the-badge&logo=expo&logoColor=#D04A37) + +

+ 🇺🇸 English | + 🇯🇵 日本語 | + 🇨🇳 简体中文 | + 🇪🇸 Español | + 🇧🇷 Português (Brasil) | + 🇰🇷 한국어 | + 🇩🇪 Deutsch | + 🇫🇷 Français +

+ + +> **Note** +> This is a translated version of this README. The English version (`README.md`) is the source of truth. + +!["web_ui"](./assets/images/web_ui.png) + + [PlayGround](https://europanite.github.io/client_side_python/) + +一个基于浏览器、完全运行在客户端的 Python Playground。 + +--- + +## 概览 + +Client Side Python 是一个**由 Pyodide 驱动的浏览器端 Python Playground**。 +所有 Python 代码都**完全在你的浏览器标签页中运行**(WebAssembly,无后端),因此你的代码不会离开本机。 + +这使它非常适合以下场景: + +- 快速试验小型 Python 代码片段 +- 在课堂或工作坊中演示 Python 基础 +- 在安全沙箱中尝试简单的数值计算或脚本任务 +- 展示 WebAssembly + Pyodide 如何将“真正的” Python 带到浏览器中 + +--- + +## 功能 + +- **完全客户端执行** + - 使用 [Pyodide](https://pyodide.org) 在 WebAssembly 中运行 CPython。 + - 默认无需服务器、数据库或身份验证。 + +- **简洁的代码编辑器 + 控制台** + - 用于编写 Python 代码的文本区域。 + - 显示 `stdout` 和 `stderr` 的控制台区域。 + - 按钮:**Run**、**Stop**、**Clear**、**Load Sample**、**Copy Output**。 + +- **软性“Stop”机制** + - 执行过程被封装在一个软取消令牌中。 + - 当你按下 **Stop** 时,当前执行会在逻辑上被取消,延迟返回的结果会被忽略,而不会破坏 UI。 + +- **响应式 Web UI** + - 使用 **Expo / React Native Web** 和 **Material UI** 组件构建。 + - 布局可适配不同视口尺寸(桌面 / 平板)。 + +- **通过 Docker 实现确定性的 CI** + - Jest 测试使用 `docker-compose.test.yml` 在 Docker 容器中运行。 + - 提供了用于 CI 和基于 Docker 测试的 GitHub Actions 工作流。 + +- **自动部署到 GitHub Pages** + - GitHub Actions 工作流会构建 Expo Web bundle,并将其发布到 `main` 分支对应的 GitHub Pages。 + +--- + +## 工作原理 + +应用首次加载时,会执行以下操作: + +1. 从 CDN 获取 Pyodide。 +2. 初始化 Pyodide 运行时,并暴露 `runPythonAsync`。 +3. 挂载 `stdout` 和 `stderr` 的自定义处理器,以便将 Python 输出流式写入页面内控制台。 +4. 使用简单的执行令牌实现 **soft Stop**: + - 每次运行都会递增内部 `execId`。 + - 如果某次运行结束时对应的是过期的 `execId`,其输出将被丢弃。 + - 这样可以防止旧运行结果污染控制台。 + +这一切都发生在**浏览器中**,无需任何后端 API 调用。 + +--- + +## 🚀 快速开始 + +### 1. 前置条件 +- [Docker](https://www.docker.com/) 和 [Docker Compose](https://docs.docker.com/compose/) + +### 2. 构建并启动所有服务: + +```bash +# set environment variables: +export REACT_NATIVE_PACKAGER_HOSTNAME=${YOUR_HOST} + +# Build the image +docker compose build + +# Run the container +docker compose up +``` + +### 3. 测试: +```bash +docker compose -f docker-compose.test.yml up --build --exit-code-from frontend_test +``` + +--- + +# License +- Apache License 2.0