grasp-sdk 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.
- grasp_sdk-0.1.0/MANIFEST.in +30 -0
- grasp_sdk-0.1.0/PKG-INFO +201 -0
- grasp_sdk-0.1.0/README.md +154 -0
- grasp_sdk-0.1.0/build_and_publish.py +135 -0
- grasp_sdk-0.1.0/example_simple.py +138 -0
- grasp_sdk-0.1.0/example_usage.py +100 -0
- grasp_sdk-0.1.0/grasp_sdk/__init__.py +262 -0
- grasp_sdk-0.1.0/grasp_sdk/models/__init__.py +78 -0
- grasp_sdk-0.1.0/grasp_sdk/sandbox/chrome-stable.mjs +381 -0
- grasp_sdk-0.1.0/grasp_sdk/sandbox/chromium.mjs +378 -0
- grasp_sdk-0.1.0/grasp_sdk/sandbox/jsconfig.json +22 -0
- grasp_sdk-0.1.0/grasp_sdk/services/__init__.py +8 -0
- grasp_sdk-0.1.0/grasp_sdk/services/browser.py +414 -0
- grasp_sdk-0.1.0/grasp_sdk/services/sandbox.py +583 -0
- grasp_sdk-0.1.0/grasp_sdk/utils/__init__.py +31 -0
- grasp_sdk-0.1.0/grasp_sdk/utils/auth.py +227 -0
- grasp_sdk-0.1.0/grasp_sdk/utils/config.py +150 -0
- grasp_sdk-0.1.0/grasp_sdk/utils/logger.py +233 -0
- grasp_sdk-0.1.0/grasp_sdk.egg-info/PKG-INFO +201 -0
- grasp_sdk-0.1.0/grasp_sdk.egg-info/SOURCES.txt +44 -0
- grasp_sdk-0.1.0/grasp_sdk.egg-info/dependency_links.txt +1 -0
- grasp_sdk-0.1.0/grasp_sdk.egg-info/entry_points.txt +2 -0
- grasp_sdk-0.1.0/grasp_sdk.egg-info/not-zip-safe +1 -0
- grasp_sdk-0.1.0/grasp_sdk.egg-info/requires.txt +21 -0
- grasp_sdk-0.1.0/grasp_sdk.egg-info/top_level.txt +2 -0
- grasp_sdk-0.1.0/py.typed +2 -0
- grasp_sdk-0.1.0/pyproject.toml +127 -0
- grasp_sdk-0.1.0/requirements.txt +15 -0
- grasp_sdk-0.1.0/setup.cfg +4 -0
- grasp_sdk-0.1.0/setup.py +69 -0
- grasp_sdk-0.1.0/test_install.py +87 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Include documentation and configuration files
|
|
2
|
+
include README.md
|
|
3
|
+
include LICENSE
|
|
4
|
+
include requirements.txt
|
|
5
|
+
include pyproject.toml
|
|
6
|
+
include setup.py
|
|
7
|
+
|
|
8
|
+
# Include all Python source files
|
|
9
|
+
recursive-include . *.py
|
|
10
|
+
recursive-include . *.pyi
|
|
11
|
+
|
|
12
|
+
# Include type stubs
|
|
13
|
+
recursive-include . py.typed
|
|
14
|
+
|
|
15
|
+
# Include sandbox scripts
|
|
16
|
+
recursive-include grasp_sdk/sandbox *.mjs
|
|
17
|
+
recursive-include grasp_sdk/sandbox *.js
|
|
18
|
+
recursive-include grasp_sdk/sandbox *.json
|
|
19
|
+
|
|
20
|
+
# Exclude development and build files
|
|
21
|
+
exclude .gitignore
|
|
22
|
+
exclude .env*
|
|
23
|
+
recursive-exclude . __pycache__
|
|
24
|
+
recursive-exclude . *.pyc
|
|
25
|
+
recursive-exclude . *.pyo
|
|
26
|
+
recursive-exclude . .pytest_cache
|
|
27
|
+
recursive-exclude . .mypy_cache
|
|
28
|
+
recursive-exclude . *.egg-info
|
|
29
|
+
recursive-exclude . build
|
|
30
|
+
recursive-exclude . dist
|
grasp_sdk-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: grasp_sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for Grasp E2B - Browser automation and sandbox management
|
|
5
|
+
Home-page: https://github.com/grasp-team/grasp-e2b
|
|
6
|
+
Author: Grasp Team
|
|
7
|
+
Author-email: Grasp Team <team@grasp.com>
|
|
8
|
+
Project-URL: Homepage, https://github.com/grasp-team/grasp-e2b
|
|
9
|
+
Project-URL: Bug Reports, https://github.com/grasp-team/grasp-e2b/issues
|
|
10
|
+
Project-URL: Source, https://github.com/grasp-team/grasp-e2b
|
|
11
|
+
Project-URL: Documentation, https://docs.grasp.com
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
|
|
24
|
+
Classifier: Topic :: System :: Emulators
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
Requires-Dist: aiohttp>=3.9.0
|
|
28
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
29
|
+
Requires-Dist: typing-extensions>=4.8.0
|
|
30
|
+
Requires-Dist: e2b>=1.5.0
|
|
31
|
+
Requires-Dist: e2b-code-interpreter>=1.5.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
35
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
38
|
+
Provides-Extra: browser
|
|
39
|
+
Requires-Dist: playwright>=1.40.0; extra == "browser"
|
|
40
|
+
Provides-Extra: websocket
|
|
41
|
+
Requires-Dist: websockets>=12.0; extra == "websocket"
|
|
42
|
+
Provides-Extra: validation
|
|
43
|
+
Requires-Dist: pydantic>=2.5.0; extra == "validation"
|
|
44
|
+
Dynamic: author
|
|
45
|
+
Dynamic: home-page
|
|
46
|
+
Dynamic: requires-python
|
|
47
|
+
|
|
48
|
+
# Grasp SDK - Python Implementation
|
|
49
|
+
|
|
50
|
+
🐍 Python implementation of Grasp SDK for E2B platform providing secure command execution and browser automation in isolated cloud environments.
|
|
51
|
+
|
|
52
|
+
## 🚀 Features
|
|
53
|
+
|
|
54
|
+
- **Secure Execution**: Run commands and scripts in isolated E2B sandboxes
|
|
55
|
+
- **Browser Automation**: Control Chromium browsers with Playwright integration
|
|
56
|
+
- **Async/Await Support**: Full async/await support for modern Python development
|
|
57
|
+
- **Type Safety**: Complete type hints with Pydantic models
|
|
58
|
+
- **WebSocket Communication**: Real-time communication with sandbox environments
|
|
59
|
+
- **Multi-language Support**: Compatible with Node.js/TypeScript version
|
|
60
|
+
|
|
61
|
+
## 📦 Installation
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Install from PyPI (when published)
|
|
65
|
+
pip install grasp-sdk
|
|
66
|
+
|
|
67
|
+
# Install from source
|
|
68
|
+
pip install -e .
|
|
69
|
+
|
|
70
|
+
# Install with development dependencies
|
|
71
|
+
pip install -e ".[dev]"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## 🔧 Quick Start
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
import asyncio
|
|
78
|
+
from grasp_sdk import GraspServer
|
|
79
|
+
|
|
80
|
+
async def main():
|
|
81
|
+
# Initialize Grasp server
|
|
82
|
+
server = GraspServer({
|
|
83
|
+
"key": api_key,
|
|
84
|
+
"timeout": 30000,
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
# Start sandbox
|
|
89
|
+
await server.start()
|
|
90
|
+
|
|
91
|
+
# Execute command
|
|
92
|
+
result = await server.execute_command("echo 'Hello from Python!'")
|
|
93
|
+
print(f"Output: {result.stdout}")
|
|
94
|
+
|
|
95
|
+
# Browser automation
|
|
96
|
+
browser_task = await server.create_browser_task()
|
|
97
|
+
await browser_task.navigate("https://example.com")
|
|
98
|
+
screenshot = await browser_task.screenshot("example.png")
|
|
99
|
+
|
|
100
|
+
finally:
|
|
101
|
+
# Clean up
|
|
102
|
+
await server.close()
|
|
103
|
+
|
|
104
|
+
if __name__ == "__main__":
|
|
105
|
+
asyncio.run(main())
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## 🏗️ Architecture
|
|
109
|
+
|
|
110
|
+
The Python implementation mirrors the Node.js/TypeScript version:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
py-src/
|
|
114
|
+
├── __init__.py # Main package exports
|
|
115
|
+
├── grasp_server.py # Main GraspServer class
|
|
116
|
+
├── services/ # Core services
|
|
117
|
+
│ ├── __init__.py
|
|
118
|
+
│ ├── sandbox_service.py # E2B sandbox management
|
|
119
|
+
│ └── browser_service.py # Browser automation
|
|
120
|
+
├── types/ # Type definitions
|
|
121
|
+
│ └── __init__.py
|
|
122
|
+
├── utils/ # Utilities
|
|
123
|
+
│ ├── __init__.py
|
|
124
|
+
│ ├── config.py # Configuration management
|
|
125
|
+
│ ├── logger.py # Logging utilities
|
|
126
|
+
│ └── auth.py # Authentication
|
|
127
|
+
├── cli/ # Command line interface
|
|
128
|
+
│ ├── __init__.py
|
|
129
|
+
│ └── main.py
|
|
130
|
+
└── tests/ # Test suite
|
|
131
|
+
└── ...
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 🔑 Environment Variables
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# Required
|
|
138
|
+
E2B_API_KEY=your_e2b_api_key_here
|
|
139
|
+
|
|
140
|
+
# Optional
|
|
141
|
+
GRASP_LOG_LEVEL=info
|
|
142
|
+
GRASP_TIMEOUT=30000
|
|
143
|
+
GRASP_TEMPLATE=python
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## 🧪 Development
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Install development dependencies
|
|
150
|
+
pip install -e ".[dev]"
|
|
151
|
+
|
|
152
|
+
# Run tests
|
|
153
|
+
pytest
|
|
154
|
+
|
|
155
|
+
# Format code
|
|
156
|
+
black .
|
|
157
|
+
isort .
|
|
158
|
+
|
|
159
|
+
# Type checking
|
|
160
|
+
mypy .
|
|
161
|
+
|
|
162
|
+
# Linting
|
|
163
|
+
flake8 .
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## 📚 API Reference
|
|
167
|
+
|
|
168
|
+
### GraspServer
|
|
169
|
+
|
|
170
|
+
Main class for interacting with E2B sandboxes and browser automation.
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
class GraspServer:
|
|
174
|
+
def __init__(self, config: ISandboxConfig = None)
|
|
175
|
+
async def start(self) -> None
|
|
176
|
+
async def close(self) -> None
|
|
177
|
+
async def execute_command(self, command: str, options: ICommandOptions = None) -> CommandResult
|
|
178
|
+
async def execute_script(self, script_path: str, options: IScriptOptions = None) -> CommandResult
|
|
179
|
+
async def create_browser_task(self, config: IBrowserConfig = None) -> BrowserTask
|
|
180
|
+
def get_sandbox_status(self) -> SandboxStatus
|
|
181
|
+
def get_sandbox_id(self) -> str
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 🤝 Compatibility
|
|
185
|
+
|
|
186
|
+
This Python implementation provides the same API surface as the Node.js/TypeScript version, ensuring:
|
|
187
|
+
|
|
188
|
+
- **Feature Parity**: All features available in both implementations
|
|
189
|
+
- **API Consistency**: Same method names and behavior
|
|
190
|
+
- **Type Safety**: Equivalent type definitions using TypedDict and Pydantic
|
|
191
|
+
- **Error Handling**: Consistent error types and messages
|
|
192
|
+
|
|
193
|
+
## 📄 License
|
|
194
|
+
|
|
195
|
+
MIT License - see the [LICENSE](../LICENSE) file for details.
|
|
196
|
+
|
|
197
|
+
## 🔗 Related
|
|
198
|
+
|
|
199
|
+
- [Node.js/TypeScript Implementation](../src/)
|
|
200
|
+
- [E2B Platform](https://e2b.dev/)
|
|
201
|
+
- [Playwright Python](https://playwright.dev/python/)
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Grasp SDK - Python Implementation
|
|
2
|
+
|
|
3
|
+
🐍 Python implementation of Grasp SDK for E2B platform providing secure command execution and browser automation in isolated cloud environments.
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
|
|
7
|
+
- **Secure Execution**: Run commands and scripts in isolated E2B sandboxes
|
|
8
|
+
- **Browser Automation**: Control Chromium browsers with Playwright integration
|
|
9
|
+
- **Async/Await Support**: Full async/await support for modern Python development
|
|
10
|
+
- **Type Safety**: Complete type hints with Pydantic models
|
|
11
|
+
- **WebSocket Communication**: Real-time communication with sandbox environments
|
|
12
|
+
- **Multi-language Support**: Compatible with Node.js/TypeScript version
|
|
13
|
+
|
|
14
|
+
## 📦 Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Install from PyPI (when published)
|
|
18
|
+
pip install grasp-sdk
|
|
19
|
+
|
|
20
|
+
# Install from source
|
|
21
|
+
pip install -e .
|
|
22
|
+
|
|
23
|
+
# Install with development dependencies
|
|
24
|
+
pip install -e ".[dev]"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 🔧 Quick Start
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
import asyncio
|
|
31
|
+
from grasp_sdk import GraspServer
|
|
32
|
+
|
|
33
|
+
async def main():
|
|
34
|
+
# Initialize Grasp server
|
|
35
|
+
server = GraspServer({
|
|
36
|
+
"key": api_key,
|
|
37
|
+
"timeout": 30000,
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
# Start sandbox
|
|
42
|
+
await server.start()
|
|
43
|
+
|
|
44
|
+
# Execute command
|
|
45
|
+
result = await server.execute_command("echo 'Hello from Python!'")
|
|
46
|
+
print(f"Output: {result.stdout}")
|
|
47
|
+
|
|
48
|
+
# Browser automation
|
|
49
|
+
browser_task = await server.create_browser_task()
|
|
50
|
+
await browser_task.navigate("https://example.com")
|
|
51
|
+
screenshot = await browser_task.screenshot("example.png")
|
|
52
|
+
|
|
53
|
+
finally:
|
|
54
|
+
# Clean up
|
|
55
|
+
await server.close()
|
|
56
|
+
|
|
57
|
+
if __name__ == "__main__":
|
|
58
|
+
asyncio.run(main())
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 🏗️ Architecture
|
|
62
|
+
|
|
63
|
+
The Python implementation mirrors the Node.js/TypeScript version:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
py-src/
|
|
67
|
+
├── __init__.py # Main package exports
|
|
68
|
+
├── grasp_server.py # Main GraspServer class
|
|
69
|
+
├── services/ # Core services
|
|
70
|
+
│ ├── __init__.py
|
|
71
|
+
│ ├── sandbox_service.py # E2B sandbox management
|
|
72
|
+
│ └── browser_service.py # Browser automation
|
|
73
|
+
├── types/ # Type definitions
|
|
74
|
+
│ └── __init__.py
|
|
75
|
+
├── utils/ # Utilities
|
|
76
|
+
│ ├── __init__.py
|
|
77
|
+
│ ├── config.py # Configuration management
|
|
78
|
+
│ ├── logger.py # Logging utilities
|
|
79
|
+
│ └── auth.py # Authentication
|
|
80
|
+
├── cli/ # Command line interface
|
|
81
|
+
│ ├── __init__.py
|
|
82
|
+
│ └── main.py
|
|
83
|
+
└── tests/ # Test suite
|
|
84
|
+
└── ...
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## 🔑 Environment Variables
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Required
|
|
91
|
+
E2B_API_KEY=your_e2b_api_key_here
|
|
92
|
+
|
|
93
|
+
# Optional
|
|
94
|
+
GRASP_LOG_LEVEL=info
|
|
95
|
+
GRASP_TIMEOUT=30000
|
|
96
|
+
GRASP_TEMPLATE=python
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## 🧪 Development
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Install development dependencies
|
|
103
|
+
pip install -e ".[dev]"
|
|
104
|
+
|
|
105
|
+
# Run tests
|
|
106
|
+
pytest
|
|
107
|
+
|
|
108
|
+
# Format code
|
|
109
|
+
black .
|
|
110
|
+
isort .
|
|
111
|
+
|
|
112
|
+
# Type checking
|
|
113
|
+
mypy .
|
|
114
|
+
|
|
115
|
+
# Linting
|
|
116
|
+
flake8 .
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## 📚 API Reference
|
|
120
|
+
|
|
121
|
+
### GraspServer
|
|
122
|
+
|
|
123
|
+
Main class for interacting with E2B sandboxes and browser automation.
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
class GraspServer:
|
|
127
|
+
def __init__(self, config: ISandboxConfig = None)
|
|
128
|
+
async def start(self) -> None
|
|
129
|
+
async def close(self) -> None
|
|
130
|
+
async def execute_command(self, command: str, options: ICommandOptions = None) -> CommandResult
|
|
131
|
+
async def execute_script(self, script_path: str, options: IScriptOptions = None) -> CommandResult
|
|
132
|
+
async def create_browser_task(self, config: IBrowserConfig = None) -> BrowserTask
|
|
133
|
+
def get_sandbox_status(self) -> SandboxStatus
|
|
134
|
+
def get_sandbox_id(self) -> str
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## 🤝 Compatibility
|
|
138
|
+
|
|
139
|
+
This Python implementation provides the same API surface as the Node.js/TypeScript version, ensuring:
|
|
140
|
+
|
|
141
|
+
- **Feature Parity**: All features available in both implementations
|
|
142
|
+
- **API Consistency**: Same method names and behavior
|
|
143
|
+
- **Type Safety**: Equivalent type definitions using TypedDict and Pydantic
|
|
144
|
+
- **Error Handling**: Consistent error types and messages
|
|
145
|
+
|
|
146
|
+
## 📄 License
|
|
147
|
+
|
|
148
|
+
MIT License - see the [LICENSE](../LICENSE) file for details.
|
|
149
|
+
|
|
150
|
+
## 🔗 Related
|
|
151
|
+
|
|
152
|
+
- [Node.js/TypeScript Implementation](../src/)
|
|
153
|
+
- [E2B Platform](https://e2b.dev/)
|
|
154
|
+
- [Playwright Python](https://playwright.dev/python/)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Build and publish script for grasp_sdk package.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python build_and_publish.py --build-only # Only build the package
|
|
7
|
+
python build_and_publish.py --test # Upload to TestPyPI
|
|
8
|
+
python build_and_publish.py --prod # Upload to PyPI
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import os
|
|
13
|
+
import subprocess
|
|
14
|
+
import sys
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def run_command(cmd: str, check: bool = True) -> subprocess.CompletedProcess:
|
|
19
|
+
"""Run a shell command and return the result."""
|
|
20
|
+
print(f"Running: {cmd}")
|
|
21
|
+
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
|
22
|
+
|
|
23
|
+
if check and result.returncode != 0:
|
|
24
|
+
print(f"Error running command: {cmd}")
|
|
25
|
+
print(f"stdout: {result.stdout}")
|
|
26
|
+
print(f"stderr: {result.stderr}")
|
|
27
|
+
sys.exit(1)
|
|
28
|
+
|
|
29
|
+
return result
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def clean_build_dirs():
|
|
33
|
+
"""Clean previous build artifacts."""
|
|
34
|
+
print("Cleaning build directories...")
|
|
35
|
+
dirs_to_clean = ['build', 'dist', 'grasp_sdk.egg-info']
|
|
36
|
+
|
|
37
|
+
for dir_name in dirs_to_clean:
|
|
38
|
+
if os.path.exists(dir_name):
|
|
39
|
+
run_command(f"rm -rf {dir_name}")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def build_package():
|
|
43
|
+
"""Build the package."""
|
|
44
|
+
print("Building package...")
|
|
45
|
+
|
|
46
|
+
# Install build dependencies
|
|
47
|
+
run_command("pip install --upgrade build twine")
|
|
48
|
+
|
|
49
|
+
# Build the package
|
|
50
|
+
run_command("python -m build")
|
|
51
|
+
|
|
52
|
+
print("Package built successfully!")
|
|
53
|
+
print("Built files:")
|
|
54
|
+
if os.path.exists('dist'):
|
|
55
|
+
for file in os.listdir('dist'):
|
|
56
|
+
print(f" - dist/{file}")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def upload_to_testpypi():
|
|
60
|
+
"""Upload package to TestPyPI."""
|
|
61
|
+
print("Uploading to TestPyPI...")
|
|
62
|
+
run_command("python -m twine upload --repository testpypi dist/*")
|
|
63
|
+
print("Package uploaded to TestPyPI successfully!")
|
|
64
|
+
print("Install with: pip install --index-url https://test.pypi.org/simple/ grasp_sdk")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def upload_to_pypi():
|
|
68
|
+
"""Upload package to PyPI."""
|
|
69
|
+
print("Uploading to PyPI...")
|
|
70
|
+
|
|
71
|
+
# Confirm before uploading to production
|
|
72
|
+
response = input("Are you sure you want to upload to PyPI? (yes/no): ")
|
|
73
|
+
if response.lower() != 'yes':
|
|
74
|
+
print("Upload cancelled.")
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
run_command("python -m twine upload dist/*")
|
|
78
|
+
print("Package uploaded to PyPI successfully!")
|
|
79
|
+
print("Install with: pip install grasp_sdk")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def check_package():
|
|
83
|
+
"""Run package checks."""
|
|
84
|
+
print("Running package checks...")
|
|
85
|
+
|
|
86
|
+
# Check if required files exist
|
|
87
|
+
required_files = ['README.md', 'pyproject.toml', 'setup.py', '__init__.py']
|
|
88
|
+
for file in required_files:
|
|
89
|
+
if not os.path.exists(file):
|
|
90
|
+
print(f"Warning: {file} not found")
|
|
91
|
+
|
|
92
|
+
# Check package with twine
|
|
93
|
+
if os.path.exists('dist'):
|
|
94
|
+
run_command("python -m twine check dist/*")
|
|
95
|
+
|
|
96
|
+
print("Package checks completed.")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def main():
|
|
100
|
+
parser = argparse.ArgumentParser(description='Build and publish grasp_sdk package')
|
|
101
|
+
parser.add_argument('--build-only', action='store_true', help='Only build the package')
|
|
102
|
+
parser.add_argument('--test', action='store_true', help='Upload to TestPyPI')
|
|
103
|
+
parser.add_argument('--prod', action='store_true', help='Upload to PyPI')
|
|
104
|
+
parser.add_argument('--check', action='store_true', help='Run package checks only')
|
|
105
|
+
|
|
106
|
+
args = parser.parse_args()
|
|
107
|
+
|
|
108
|
+
# Change to script directory
|
|
109
|
+
script_dir = Path(__file__).parent
|
|
110
|
+
os.chdir(script_dir)
|
|
111
|
+
|
|
112
|
+
if args.check:
|
|
113
|
+
check_package()
|
|
114
|
+
return
|
|
115
|
+
|
|
116
|
+
# Clean and build
|
|
117
|
+
clean_build_dirs()
|
|
118
|
+
build_package()
|
|
119
|
+
check_package()
|
|
120
|
+
|
|
121
|
+
if args.build_only:
|
|
122
|
+
print("Build completed. Use --test or --prod to upload.")
|
|
123
|
+
elif args.test:
|
|
124
|
+
upload_to_testpypi()
|
|
125
|
+
elif args.prod:
|
|
126
|
+
upload_to_pypi()
|
|
127
|
+
else:
|
|
128
|
+
print("Package built successfully!")
|
|
129
|
+
print("Next steps:")
|
|
130
|
+
print(" - Test upload: python build_and_publish.py --test")
|
|
131
|
+
print(" - Production upload: python build_and_publish.py --prod")
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
if __name__ == '__main__':
|
|
135
|
+
main()
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Grasp SDK Python 简单示例
|
|
4
|
+
|
|
5
|
+
这个示例展示了如何在没有 API key 的情况下测试 grasp_sdk 的基本功能。
|
|
6
|
+
注意:这个示例主要用于测试包的导入和基本结构,实际的浏览器功能需要有效的 API key。
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import os
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
from grasp_sdk import GraspServer, launch_browser
|
|
15
|
+
from grasp_sdk.models import IBrowserConfig, ISandboxConfig
|
|
16
|
+
print("✅ grasp_sdk 导入成功")
|
|
17
|
+
except ImportError as e:
|
|
18
|
+
print(f"❌ 导入 grasp_sdk 失败: {e}")
|
|
19
|
+
exit(1)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
async def test_basic_functionality():
|
|
23
|
+
"""测试基本功能(不需要实际启动浏览器)"""
|
|
24
|
+
|
|
25
|
+
print("\n🧪 测试基本功能...")
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
# 测试 GraspServer 实例化
|
|
29
|
+
server = GraspServer()
|
|
30
|
+
print("✅ GraspServer 实例创建成功")
|
|
31
|
+
|
|
32
|
+
# 测试获取状态
|
|
33
|
+
status = server.get_status()
|
|
34
|
+
print(f"✅ 服务器状态: {status}")
|
|
35
|
+
|
|
36
|
+
# 测试获取沙箱 ID
|
|
37
|
+
sandbox_id = server.get_sandbox_id()
|
|
38
|
+
print(f"✅ 沙箱 ID: {sandbox_id}")
|
|
39
|
+
|
|
40
|
+
print("\n✅ 基本功能测试通过")
|
|
41
|
+
|
|
42
|
+
except Exception as e:
|
|
43
|
+
print(f"❌ 基本功能测试失败: {e}")
|
|
44
|
+
raise
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
async def test_with_mock_config():
|
|
48
|
+
"""使用模拟配置测试(不实际连接)"""
|
|
49
|
+
|
|
50
|
+
print("\n🔧 测试配置功能...")
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
# 创建模拟的浏览器配置
|
|
54
|
+
browser_config: IBrowserConfig = {
|
|
55
|
+
'cdpPort': 9222,
|
|
56
|
+
'headless': True,
|
|
57
|
+
'launchTimeout': 30000,
|
|
58
|
+
'args': ['--disable-web-security'],
|
|
59
|
+
'envs': {'TEST': 'true'}
|
|
60
|
+
}
|
|
61
|
+
print("✅ 浏览器配置创建成功")
|
|
62
|
+
|
|
63
|
+
# 创建模拟的沙箱配置
|
|
64
|
+
sandbox_config: ISandboxConfig = {
|
|
65
|
+
'key': 'mock_api_key',
|
|
66
|
+
'templateId': 'playwright-pnpm-template',
|
|
67
|
+
'timeout': 300000,
|
|
68
|
+
'debug': False
|
|
69
|
+
}
|
|
70
|
+
print("✅ 沙箱配置创建成功")
|
|
71
|
+
|
|
72
|
+
print("\n✅ 配置功能测试通过")
|
|
73
|
+
|
|
74
|
+
except Exception as e:
|
|
75
|
+
print(f"❌ 配置功能测试失败: {e}")
|
|
76
|
+
raise
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def test_imports():
|
|
80
|
+
"""测试所有重要模块的导入"""
|
|
81
|
+
|
|
82
|
+
print("\n📦 测试模块导入...")
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
# 测试服务模块
|
|
86
|
+
from grasp_sdk.services import BrowserService, SandboxService
|
|
87
|
+
print("✅ 服务模块导入成功")
|
|
88
|
+
|
|
89
|
+
# 测试工具模块
|
|
90
|
+
from grasp_sdk.utils import get_config, get_logger
|
|
91
|
+
print("✅ 工具模块导入成功")
|
|
92
|
+
|
|
93
|
+
# 测试模型模块
|
|
94
|
+
from grasp_sdk.models import SandboxStatus
|
|
95
|
+
print("✅ 模型模块导入成功")
|
|
96
|
+
|
|
97
|
+
print("\n✅ 所有模块导入测试通过")
|
|
98
|
+
|
|
99
|
+
except ImportError as e:
|
|
100
|
+
print(f"❌ 模块导入测试失败: {e}")
|
|
101
|
+
raise
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
async def main():
|
|
105
|
+
"""主函数:运行所有测试"""
|
|
106
|
+
|
|
107
|
+
print("🎯 Grasp SDK Python 简单功能测试")
|
|
108
|
+
print("=" * 50)
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
# 1. 测试导入
|
|
112
|
+
test_imports()
|
|
113
|
+
|
|
114
|
+
# 2. 测试基本功能
|
|
115
|
+
await test_basic_functionality()
|
|
116
|
+
|
|
117
|
+
# 3. 测试配置
|
|
118
|
+
await test_with_mock_config()
|
|
119
|
+
|
|
120
|
+
print("\n" + "=" * 50)
|
|
121
|
+
print("🎉 所有测试通过!")
|
|
122
|
+
print("\n💡 提示:")
|
|
123
|
+
print(" - 要运行完整的浏览器自动化示例,请使用 example_usage.py")
|
|
124
|
+
print(" - 确保设置了有效的 GRASP_KEY 环境变量")
|
|
125
|
+
print(" - 安装 Playwright:pip install playwright && playwright install")
|
|
126
|
+
|
|
127
|
+
except Exception as e:
|
|
128
|
+
print(f"\n❌ 测试失败: {e}")
|
|
129
|
+
print("\n🔍 故障排除:")
|
|
130
|
+
print(" 1. 确保 grasp-sdk 已正确安装")
|
|
131
|
+
print(" 2. 检查 Python 版本(需要 3.8+)")
|
|
132
|
+
print(" 3. 查看完整错误信息以获取更多详情")
|
|
133
|
+
raise
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
if __name__ == '__main__':
|
|
137
|
+
# 运行测试
|
|
138
|
+
asyncio.run(main())
|