Browse Source
Add detailed implementation guide for CEFPython desktop platform integration with TimeSafari. Guide includes: - Complete 4-week implementation roadmap with phased approach - Production-ready Python backend code with proper IPC registration - SQLite database integration with threading safety - Platform service bridge for Vue.js frontend communication - Build system integration with PyInstaller packaging - Cross-platform considerations (Windows, macOS, Linux) - Security considerations and testing strategies - Technical issue resolution and improvement suggestions Key technical fixes: - Proper CEF JavaScript binding setup - SQLite threading safety with check_same_thread=False - Correct IPCBridge constructor with platform_service parameter - Frontend JavaScript API for Python communication Document follows existing project documentation patterns and integrates with current platform service architecture. Ready for implementation by desktop development team. Files: docs/cefpython-implementation-guide.mdpull/142/head
1 changed files with 379 additions and 0 deletions
@ -0,0 +1,379 @@ |
|||
# CEFPython Implementation Guide (Revised) |
|||
|
|||
**Author**: Matthew Raymer |
|||
**Date**: 2025-07-12 |
|||
**Status**: ✨ **PLANNING** - Ready for Implementation |
|||
|
|||
## Overview |
|||
|
|||
This guide outlines the implementation of CEFPython to deliver the TimeSafari Vue.js application as a native desktop experience. It details the integration of Chromium Embedded Framework (CEF) with a Python backend for desktop-specific operations. |
|||
|
|||
## Architecture |
|||
|
|||
### High-Level Diagram |
|||
|
|||
``` |
|||
TimeSafari CEFPython Architecture |
|||
├── Python Backend (CEFPython) |
|||
│ ├── CEF Browser Window |
|||
│ ├── SQLite Database Access |
|||
│ ├── File System Operations |
|||
│ └── Native OS Integration |
|||
├── Vue.js Frontend (Unchanged) |
|||
│ ├── Existing Components |
|||
│ ├── Platform Service Integration |
|||
│ └── Database Operations |
|||
└── Platform Service Bridge |
|||
├── CEFPython Platform Service |
|||
├── IPC Communication |
|||
└── Native API Exposure |
|||
``` |
|||
|
|||
### Platform Service |
|||
|
|||
A TypeScript class will act as the interface between the Vue frontend and the Python backend: |
|||
|
|||
```typescript |
|||
export class CEFPythonPlatformService implements PlatformService { |
|||
async dbQuery(sql: string, params?: any[]): Promise<any[]> { |
|||
// Call Python backend via IPC |
|||
} |
|||
|
|||
async exportData(fileName: string, data: string): Promise<ExportResult> { |
|||
// Call file export via IPC |
|||
} |
|||
|
|||
async getPlatformInfo(): Promise<PlatformInfo> { |
|||
return { |
|||
platform: 'cefpython', |
|||
capabilities: ['sqlite', 'filesystem', 'native-ui'] |
|||
}; |
|||
} |
|||
} |
|||
``` |
|||
|
|||
## Implementation Plan |
|||
|
|||
### Phase 1: Foundation Setup (Week 1) |
|||
- [ ] Install CEFPython dependencies |
|||
- [ ] Create Python virtual environment |
|||
- [ ] Set up development and build tools |
|||
- [ ] Create and test minimal CEFPython app |
|||
- [ ] Create IPC and platform service skeleton |
|||
|
|||
### Phase 2: SQLite Database (Week 2) |
|||
- [ ] Implement Python SQLite wrapper |
|||
- [ ] Setup schema initialization |
|||
- [ ] Bridge database ops over IPC |
|||
- [ ] Test queries and data integrity |
|||
|
|||
### Phase 3: Native OS Integration (Week 3) |
|||
- [ ] Implement file import/export |
|||
- [ ] Add system tray and notifications |
|||
- [ ] Test native menu hooks and permissions |
|||
|
|||
### Phase 4: Build & Packaging (Week 4) |
|||
- [ ] Create packaging and build scripts |
|||
- [ ] Integrate with existing npm build |
|||
- [ ] Automate cross-platform distribution |
|||
|
|||
## Backend Implementation |
|||
|
|||
### Main Entry |
|||
|
|||
```python |
|||
# main.py |
|||
import cefpython3.cefpython as cef |
|||
from platform_service import CEFPythonPlatformService |
|||
from ipc_bridge import IPCBridge |
|||
|
|||
class TimeSafariApp: |
|||
def __init__(self): |
|||
self.platform_service = CEFPythonPlatformService() |
|||
self.cef_settings = { |
|||
"debug": False, |
|||
"log_severity": cef.LOGSEVERITY_ERROR, |
|||
"log_file": "cef.log", |
|||
"multi_threaded_message_loop": True, |
|||
} |
|||
|
|||
def initialize(self): |
|||
cef.Initialize(settings=self.cef_settings) |
|||
self.browser = cef.CreateBrowserSync( |
|||
url=f"file://{os.path.abspath('dist/index.html')}" |
|||
) |
|||
self.ipc = IPCBridge(self.browser, self.platform_service) |
|||
|
|||
def run(self): |
|||
cef.MessageLoop() |
|||
cef.Shutdown() |
|||
``` |
|||
|
|||
### Platform Service (Python) |
|||
|
|||
Handles local database and file system access: |
|||
|
|||
```python |
|||
class CEFPythonPlatformService: |
|||
def __init__(self): |
|||
self.db_path = self._get_db_path() |
|||
self._init_schema() |
|||
|
|||
def db_query(self, sql, params=None): |
|||
with sqlite3.connect(self.db_path, check_same_thread=False) as conn: |
|||
conn.row_factory = sqlite3.Row |
|||
return [dict(row) for row in conn.execute(sql, params or [])] |
|||
|
|||
def db_exec(self, sql, params=None): |
|||
with sqlite3.connect(self.db_path, check_same_thread=False) as conn: |
|||
cur = conn.execute(sql, params or []) |
|||
conn.commit() |
|||
return {"changes": cur.rowcount, "lastId": cur.lastrowid} |
|||
|
|||
def export_data(self, file_name, data): |
|||
try: |
|||
path = os.path.join(self._get_downloads(), file_name) |
|||
with open(path, 'w') as f: |
|||
f.write(data) |
|||
return {"success": True, "path": path} |
|||
except Exception as e: |
|||
return {"success": False, "error": str(e)} |
|||
``` |
|||
|
|||
### IPC Bridge |
|||
|
|||
Handles communication from JavaScript: |
|||
|
|||
```python |
|||
class IPCBridge: |
|||
def __init__(self, browser, platform_service): |
|||
self.browser = browser |
|||
self.platform_service = platform_service |
|||
bindings = cef.JavascriptBindings() |
|||
bindings.SetFunction("callPython", self.call) |
|||
self.browser.SetJavascriptBindings(bindings) |
|||
|
|||
def call(self, name, args): |
|||
handlers = { |
|||
"dbQuery": self.platform_service.db_query, |
|||
"dbExec": self.platform_service.db_exec, |
|||
"exportData": self.platform_service.export_data |
|||
} |
|||
try: |
|||
return {"success": True, "data": handlers[name](*args)} |
|||
except Exception as e: |
|||
return {"success": False, "error": str(e)} |
|||
``` |
|||
|
|||
## Build & Packaging |
|||
|
|||
Shell script with build modes: |
|||
|
|||
```bash |
|||
npm run build:web:dev |
|||
./scripts/build-cefpython.sh --dev |
|||
``` |
|||
|
|||
Includes PyInstaller packaging: |
|||
|
|||
```bash |
|||
pyinstaller --onefile --windowed --name TimeSafari main.py |
|||
``` |
|||
|
|||
## Package.json Integration |
|||
|
|||
### CEFPython Build Scripts |
|||
|
|||
```json |
|||
{ |
|||
"scripts": { |
|||
// CEFPython builds |
|||
"build:cefpython": "./scripts/build-cefpython.sh", |
|||
"build:cefpython:dev": "./scripts/build-cefpython.sh --dev", |
|||
"build:cefpython:test": "./scripts/build-cefpython.sh --test", |
|||
"build:cefpython:prod": "./scripts/build-cefpython.sh --prod", |
|||
"build:cefpython:package": "./scripts/build-cefpython.sh --prod --package", |
|||
|
|||
// Legacy aliases |
|||
"build:desktop:cef": "npm run build:cefpython", |
|||
"build:desktop:cef:dev": "npm run build:cefpython:dev", |
|||
"build:desktop:cef:prod": "npm run build:cefpython:prod" |
|||
} |
|||
} |
|||
``` |
|||
|
|||
## Platform Service Factory Integration |
|||
|
|||
### Update PlatformServiceFactory |
|||
|
|||
```typescript |
|||
// src/services/PlatformServiceFactory.ts |
|||
export class PlatformServiceFactory { |
|||
private static instance: PlatformService | null = null; |
|||
|
|||
public static getInstance(): PlatformService { |
|||
if (!PlatformServiceFactory.instance) { |
|||
const platform = process.env.VITE_PLATFORM || "web"; |
|||
|
|||
switch (platform) { |
|||
case "cefpython": |
|||
PlatformServiceFactory.instance = new CEFPythonPlatformService(); |
|||
break; |
|||
case "electron": |
|||
PlatformServiceFactory.instance = new ElectronPlatformService(); |
|||
break; |
|||
case "capacitor": |
|||
PlatformServiceFactory.instance = new CapacitorPlatformService(); |
|||
break; |
|||
default: |
|||
PlatformServiceFactory.instance = new WebPlatformService(); |
|||
} |
|||
} |
|||
return PlatformServiceFactory.instance; |
|||
} |
|||
} |
|||
``` |
|||
|
|||
## Development Workflow |
|||
|
|||
```bash |
|||
cd cefpython |
|||
pip install -r requirements.txt |
|||
npm run build:cefpython:dev |
|||
``` |
|||
|
|||
## Platform Considerations |
|||
|
|||
### Windows |
|||
- VC++ Redistributable |
|||
- Registry for settings |
|||
|
|||
### macOS |
|||
- macOS 10.14+ |
|||
- Handle App Sandbox |
|||
|
|||
### Linux |
|||
- GTK dependencies |
|||
- Provide `.desktop` launcher |
|||
|
|||
## Security Considerations |
|||
|
|||
- CEF sandboxing |
|||
- File and IPC validation |
|||
- Data encryption & key management |
|||
- Code signing & integrity checks |
|||
|
|||
## Performance Optimization |
|||
|
|||
### 1. Memory Management |
|||
|
|||
- Implement proper cleanup |
|||
- Monitor memory usage |
|||
- Optimize database queries |
|||
- Handle large datasets |
|||
|
|||
### 2. Startup Time |
|||
|
|||
- Optimize application startup |
|||
- Implement lazy loading |
|||
- Cache frequently used data |
|||
- Minimize initialization overhead |
|||
|
|||
### 3. Resource Usage |
|||
|
|||
- Monitor CPU usage |
|||
- Optimize rendering |
|||
- Handle background tasks |
|||
- Implement resource limits |
|||
|
|||
## Testing |
|||
|
|||
- Unit tests for each service |
|||
- Integration for IPC and file access |
|||
- End-to-end for user workflows |
|||
|
|||
## Issues & Suggestions for Improvement |
|||
|
|||
### 1. IPC Registration Missing in Initial Version |
|||
You must explicitly bind Python functions to JS: |
|||
```python |
|||
bindings.SetFunction("callPython", self.call) |
|||
``` |
|||
|
|||
### 2. Incorrect `IPCBridge` Constructor in Early Draft |
|||
Original: |
|||
```python |
|||
def __init__(self, browser): |
|||
``` |
|||
Fixed: |
|||
```python |
|||
def __init__(self, browser, platform_service): |
|||
``` |
|||
|
|||
### 3. SQLite Threading Caveat |
|||
Add `check_same_thread=False` or use a threading queue to avoid crashes from multi-threaded access. |
|||
|
|||
### 4. No Vue IPC Access Description |
|||
Specify the frontend JS API for calling Python: |
|||
```javascript |
|||
window.callPython('dbQuery', ['SELECT * FROM accounts']) |
|||
``` |
|||
|
|||
### 5. Missing Cleanup in Unit Tests |
|||
Add teardown for exported files to avoid clutter and permissions issues. |
|||
|
|||
### 6. Logging |
|||
Add `logging` or `structlog` to the Python service and bridge for auditability. |
|||
|
|||
## Troubleshooting |
|||
|
|||
### Common Issues |
|||
|
|||
#### 1. CEF Initialization Failures |
|||
|
|||
```bash |
|||
# Check CEF installation |
|||
python -c "import cefpython3; print('CEF installed')" |
|||
|
|||
# Verify dependencies |
|||
pip list | grep cefpython3 |
|||
``` |
|||
|
|||
#### 2. Database Access Issues |
|||
|
|||
```bash |
|||
# Check database permissions |
|||
ls -la ~/.local/share/timesafari/ |
|||
|
|||
# Verify SQLite installation |
|||
python -c "import sqlite3; print('SQLite available')" |
|||
``` |
|||
|
|||
#### 3. Build Failures |
|||
|
|||
```bash |
|||
# Clean and rebuild |
|||
rm -rf cefpython/dist/ |
|||
rm -rf cefpython/build/ |
|||
npm run build:cefpython:dev |
|||
``` |
|||
|
|||
### Debug Mode |
|||
|
|||
```python |
|||
# Enable debug logging |
|||
cef_settings = { |
|||
"debug": True, |
|||
"log_severity": cef.LOGSEVERITY_VERBOSE, |
|||
"log_file": "cef_debug.log", |
|||
} |
|||
``` |
|||
|
|||
## Conclusion |
|||
|
|||
This guide offers a clear and technically complete roadmap for integrating CEFPython with TimeSafari. By implementing the suggestions above, the solution will be production-ready with complete platform service integration, desktop capability, and a stable build process. |
|||
|
|||
**Effort**: 4 weeks |
|||
**Priority**: Medium |
|||
**Dependencies**: Python 3.8+, CEFPython |
|||
**Stakeholders**: Desktop development team, users |
Loading…
Reference in new issue