fleet-python 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl
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.
Potentially problematic release.
This version of fleet-python might be problematic. Click here for more details.
- examples/browser_control_example.py +51 -0
- fleet/__init__.py +4 -16
- fleet/base.py +74 -0
- fleet/client.py +115 -279
- fleet/env/__init__.py +3 -25
- fleet/env/base.py +50 -318
- fleet/env/client.py +241 -0
- fleet/env/models.py +127 -0
- fleet/models.py +109 -0
- fleet/resources/base.py +23 -0
- fleet/resources/browser.py +18 -0
- fleet/resources/sqlite.py +41 -0
- {fleet_python-0.1.0.dist-info → fleet_python-0.2.0.dist-info}/METADATA +2 -1
- fleet_python-0.2.0.dist-info/RECORD +19 -0
- fleet/config.py +0 -125
- fleet/env/factory.py +0 -446
- fleet/facets/__init__.py +0 -7
- fleet/facets/base.py +0 -223
- fleet/facets/factory.py +0 -29
- fleet/manager_client.py +0 -177
- fleet_python-0.1.0.dist-info/RECORD +0 -17
- {fleet_python-0.1.0.dist-info → fleet_python-0.2.0.dist-info}/WHEEL +0 -0
- {fleet_python-0.1.0.dist-info → fleet_python-0.2.0.dist-info}/licenses/LICENSE +0 -0
- {fleet_python-0.1.0.dist-info → fleet_python-0.2.0.dist-info}/top_level.txt +0 -0
fleet/env/factory.py
DELETED
|
@@ -1,446 +0,0 @@
|
|
|
1
|
-
"""Fleet SDK Environment Factory."""
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
from typing import Dict, Optional, Any, List, Union, Tuple
|
|
5
|
-
from datetime import datetime
|
|
6
|
-
|
|
7
|
-
from .base import Environment, EnvironmentConfig, RemoteEnvironment
|
|
8
|
-
from ..exceptions import FleetEnvironmentError, FleetAuthenticationError
|
|
9
|
-
from ..config import get_config, FleetConfig
|
|
10
|
-
from ..client import FleetAPIClient, EnvDetails, InstanceRequest
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
# Registry of available environment types with versioning
|
|
14
|
-
ENVIRONMENT_REGISTRY: Dict[str, Dict[str, Dict[str, str]]] = {
|
|
15
|
-
"browser": {
|
|
16
|
-
"chrome-desktop": {
|
|
17
|
-
"v1": "web_browser",
|
|
18
|
-
"v2": "web_browser",
|
|
19
|
-
"latest": "v2"
|
|
20
|
-
},
|
|
21
|
-
"firefox-desktop": {
|
|
22
|
-
"v1": "web_browser",
|
|
23
|
-
"latest": "v1"
|
|
24
|
-
},
|
|
25
|
-
"safari-desktop": {
|
|
26
|
-
"v1": "web_browser",
|
|
27
|
-
"latest": "v1"
|
|
28
|
-
},
|
|
29
|
-
"chrome-mobile": {
|
|
30
|
-
"v1": "mobile_browser",
|
|
31
|
-
"latest": "v1"
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
"database": {
|
|
35
|
-
"postgres": {
|
|
36
|
-
"v1": "database",
|
|
37
|
-
"latest": "v1"
|
|
38
|
-
},
|
|
39
|
-
"mysql": {
|
|
40
|
-
"v1": "database",
|
|
41
|
-
"latest": "v1"
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
"file-system": {
|
|
45
|
-
"unix": {
|
|
46
|
-
"v1": "file_system",
|
|
47
|
-
"latest": "v1"
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
"api": {
|
|
51
|
-
"rest": {
|
|
52
|
-
"v1": "api",
|
|
53
|
-
"latest": "v1"
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class EnvironmentInstance:
|
|
60
|
-
"""Represents a live environment instance."""
|
|
61
|
-
|
|
62
|
-
def __init__(
|
|
63
|
-
self,
|
|
64
|
-
instance_id: str,
|
|
65
|
-
env_key: str,
|
|
66
|
-
status: str,
|
|
67
|
-
created_at: str,
|
|
68
|
-
metadata: Optional[Dict[str, Any]] = None
|
|
69
|
-
):
|
|
70
|
-
self.instance_id = instance_id
|
|
71
|
-
self.env_key = env_key
|
|
72
|
-
self.status = status
|
|
73
|
-
self.created_at = created_at
|
|
74
|
-
self.metadata = metadata or {}
|
|
75
|
-
|
|
76
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
77
|
-
"""Convert instance to dictionary representation."""
|
|
78
|
-
return {
|
|
79
|
-
"instance_id": self.instance_id,
|
|
80
|
-
"env_key": self.env_key,
|
|
81
|
-
"status": self.status,
|
|
82
|
-
"created_at": self.created_at,
|
|
83
|
-
"metadata": self.metadata,
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def _parse_environment_spec(environment_spec: str) -> Tuple[str, Optional[str]]:
|
|
88
|
-
"""Parse environment specification into name and version.
|
|
89
|
-
|
|
90
|
-
Args:
|
|
91
|
-
environment_spec: Environment specification in format:
|
|
92
|
-
- "name:version" (e.g., "fira:v1.2.5")
|
|
93
|
-
- "name" (defaults to None, will use environment's default version)
|
|
94
|
-
|
|
95
|
-
Returns:
|
|
96
|
-
Tuple of (name, version)
|
|
97
|
-
|
|
98
|
-
Raises:
|
|
99
|
-
FleetEnvironmentError: If the specification format is invalid
|
|
100
|
-
"""
|
|
101
|
-
if ":" in environment_spec:
|
|
102
|
-
name, version = environment_spec.split(":", 1)
|
|
103
|
-
return name, version
|
|
104
|
-
else:
|
|
105
|
-
return environment_spec, None
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
async def make(
|
|
112
|
-
environment_spec: str,
|
|
113
|
-
version: Optional[str] = None,
|
|
114
|
-
region: Optional[str] = None,
|
|
115
|
-
**kwargs: Any,
|
|
116
|
-
) -> Environment:
|
|
117
|
-
"""Create a Fleet environment.
|
|
118
|
-
|
|
119
|
-
Args:
|
|
120
|
-
environment_spec: Environment specification in format:
|
|
121
|
-
- "name:version" (e.g., "fira:v1.2.5")
|
|
122
|
-
- "name" (e.g., "fira" - uses default version)
|
|
123
|
-
version: Optional version to override any version in environment_spec
|
|
124
|
-
region: Optional AWS region (defaults to "us-west-1")
|
|
125
|
-
**kwargs: Additional configuration options
|
|
126
|
-
|
|
127
|
-
Returns:
|
|
128
|
-
Environment instance
|
|
129
|
-
|
|
130
|
-
Raises:
|
|
131
|
-
FleetEnvironmentError: If environment specification is invalid
|
|
132
|
-
FleetAuthenticationError: If API key is missing or invalid
|
|
133
|
-
FleetConfigurationError: If configuration is invalid
|
|
134
|
-
"""
|
|
135
|
-
# Parse the environment specification
|
|
136
|
-
env_name, parsed_version = _parse_environment_spec(environment_spec)
|
|
137
|
-
|
|
138
|
-
# Use explicit version parameter if provided, otherwise use parsed version
|
|
139
|
-
final_version = version or parsed_version
|
|
140
|
-
|
|
141
|
-
# Load configuration from environment variables
|
|
142
|
-
config = get_config(**kwargs)
|
|
143
|
-
|
|
144
|
-
# API key is required
|
|
145
|
-
if not config.api_key:
|
|
146
|
-
raise FleetAuthenticationError(
|
|
147
|
-
"API key is required. Set FLEET_API_KEY environment variable."
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
# Create environment configuration
|
|
151
|
-
env_config = EnvironmentConfig(
|
|
152
|
-
environment_type=env_name,
|
|
153
|
-
api_key=config.api_key,
|
|
154
|
-
base_url=config.base_url,
|
|
155
|
-
metadata=kwargs,
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
# Add version to metadata if specified
|
|
159
|
-
if final_version:
|
|
160
|
-
env_config.metadata["version"] = final_version
|
|
161
|
-
|
|
162
|
-
# Add region to metadata if specified
|
|
163
|
-
if region:
|
|
164
|
-
env_config.metadata["region"] = region
|
|
165
|
-
|
|
166
|
-
# Create API client and create instance
|
|
167
|
-
async with FleetAPIClient(config) as client:
|
|
168
|
-
try:
|
|
169
|
-
# Create instance request
|
|
170
|
-
instance_request = InstanceRequest(
|
|
171
|
-
env_key=env_name,
|
|
172
|
-
version=final_version,
|
|
173
|
-
region=region,
|
|
174
|
-
**kwargs
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
# Create the instance
|
|
178
|
-
instance_response = await client.create_instance(instance_request)
|
|
179
|
-
|
|
180
|
-
# Create environment instance with the created instance
|
|
181
|
-
env = RemoteEnvironment(env_config, instance_response=instance_response)
|
|
182
|
-
|
|
183
|
-
# Initialize environment
|
|
184
|
-
await _initialize_environment(env)
|
|
185
|
-
|
|
186
|
-
return env
|
|
187
|
-
|
|
188
|
-
except Exception as e:
|
|
189
|
-
raise FleetEnvironmentError(f"Failed to create environment instance: {e}")
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
async def get(
|
|
193
|
-
instance_id: str,
|
|
194
|
-
**kwargs: Any,
|
|
195
|
-
) -> Environment:
|
|
196
|
-
"""Hydrate an environment from one that is already running.
|
|
197
|
-
|
|
198
|
-
Args:
|
|
199
|
-
instance_id: ID of the running environment instance to connect to
|
|
200
|
-
**kwargs: Additional configuration options
|
|
201
|
-
|
|
202
|
-
Returns:
|
|
203
|
-
Environment instance connected to the running environment
|
|
204
|
-
|
|
205
|
-
Raises:
|
|
206
|
-
FleetEnvironmentError: If instance is not found or not accessible
|
|
207
|
-
FleetAuthenticationError: If API key is missing or invalid
|
|
208
|
-
FleetConfigurationError: If configuration is invalid
|
|
209
|
-
"""
|
|
210
|
-
# Load configuration from environment variables
|
|
211
|
-
config = get_config(**kwargs)
|
|
212
|
-
|
|
213
|
-
if not config.api_key:
|
|
214
|
-
raise FleetAuthenticationError(
|
|
215
|
-
"API key is required. Set FLEET_API_KEY environment variable."
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
# Create API client
|
|
219
|
-
async with FleetAPIClient(config) as client:
|
|
220
|
-
try:
|
|
221
|
-
# Get instance details from API
|
|
222
|
-
instance_response = await client.get_instance(instance_id)
|
|
223
|
-
|
|
224
|
-
# Create environment configuration based on instance details
|
|
225
|
-
env_config = EnvironmentConfig(
|
|
226
|
-
environment_type=instance_response.env_key,
|
|
227
|
-
api_key=config.api_key,
|
|
228
|
-
base_url=config.base_url,
|
|
229
|
-
metadata=kwargs,
|
|
230
|
-
)
|
|
231
|
-
|
|
232
|
-
# Create environment instance with existing instance ID
|
|
233
|
-
env = RemoteEnvironment(env_config, instance_id=instance_id)
|
|
234
|
-
|
|
235
|
-
# Initialize environment
|
|
236
|
-
await _initialize_environment(env)
|
|
237
|
-
|
|
238
|
-
return env
|
|
239
|
-
|
|
240
|
-
except Exception as e:
|
|
241
|
-
raise FleetEnvironmentError(f"Failed to get environment instance {instance_id}: {e}")
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
async def list_instances(
|
|
245
|
-
status: Optional[str] = None,
|
|
246
|
-
env_key_filter: Optional[str] = None,
|
|
247
|
-
**kwargs: Any,
|
|
248
|
-
) -> List[EnvironmentInstance]:
|
|
249
|
-
"""Get a directory of all live environment instances.
|
|
250
|
-
|
|
251
|
-
Args:
|
|
252
|
-
status: Filter by instance status (e.g., 'running', 'paused', 'stopped')
|
|
253
|
-
env_key_filter: Filter by environment key (e.g., 'fira', 'dropbox')
|
|
254
|
-
**kwargs: Additional query parameters
|
|
255
|
-
|
|
256
|
-
Returns:
|
|
257
|
-
List of EnvironmentInstance objects representing live instances
|
|
258
|
-
|
|
259
|
-
Raises:
|
|
260
|
-
FleetAuthenticationError: If API key is missing or invalid
|
|
261
|
-
FleetAPIError: If API request fails
|
|
262
|
-
FleetConfigurationError: If configuration is invalid
|
|
263
|
-
"""
|
|
264
|
-
# Load configuration from environment variables
|
|
265
|
-
config = get_config(**kwargs)
|
|
266
|
-
|
|
267
|
-
if not config.api_key:
|
|
268
|
-
raise FleetAuthenticationError(
|
|
269
|
-
"API key is required. Set FLEET_API_KEY environment variable."
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
# Create API client
|
|
273
|
-
async with FleetAPIClient(config) as client:
|
|
274
|
-
try:
|
|
275
|
-
# Get all instances from API
|
|
276
|
-
instances = await client.list_instances(status=status)
|
|
277
|
-
|
|
278
|
-
# Convert to EnvironmentInstance objects and apply filters
|
|
279
|
-
result = []
|
|
280
|
-
for instance in instances:
|
|
281
|
-
# Apply environment key filter if specified
|
|
282
|
-
if env_key_filter and instance.env_key != env_key_filter:
|
|
283
|
-
continue
|
|
284
|
-
|
|
285
|
-
env_instance = EnvironmentInstance(
|
|
286
|
-
instance_id=instance.instance_id,
|
|
287
|
-
env_key=instance.env_key,
|
|
288
|
-
status=instance.status,
|
|
289
|
-
created_at=instance.created_at,
|
|
290
|
-
metadata={
|
|
291
|
-
"version": instance.version,
|
|
292
|
-
"region": instance.region,
|
|
293
|
-
"team_id": instance.team_id,
|
|
294
|
-
"urls": instance.urls.model_dump(),
|
|
295
|
-
"health": instance.health,
|
|
296
|
-
}
|
|
297
|
-
)
|
|
298
|
-
result.append(env_instance)
|
|
299
|
-
|
|
300
|
-
return result
|
|
301
|
-
|
|
302
|
-
except Exception as e:
|
|
303
|
-
raise FleetEnvironmentError(f"Failed to list instances: {e}")
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
async def list_envs(**kwargs: Any) -> List[EnvDetails]:
|
|
307
|
-
"""Get list of available environments from Fleet service.
|
|
308
|
-
|
|
309
|
-
Args:
|
|
310
|
-
**kwargs: Additional query parameters
|
|
311
|
-
|
|
312
|
-
Returns:
|
|
313
|
-
List of EnvDetails objects with environment details
|
|
314
|
-
|
|
315
|
-
Raises:
|
|
316
|
-
FleetAuthenticationError: If API key is missing or invalid
|
|
317
|
-
FleetAPIError: If API request fails
|
|
318
|
-
"""
|
|
319
|
-
# Load configuration from environment variables
|
|
320
|
-
config = get_config(**kwargs)
|
|
321
|
-
|
|
322
|
-
if not config.api_key:
|
|
323
|
-
raise FleetAuthenticationError(
|
|
324
|
-
"API key is required. Set FLEET_API_KEY environment variable."
|
|
325
|
-
)
|
|
326
|
-
|
|
327
|
-
# Create API client
|
|
328
|
-
async with FleetAPIClient(config) as client:
|
|
329
|
-
# Get available environments from API - no fallback
|
|
330
|
-
environments = await client.list_environments()
|
|
331
|
-
return environments
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
def list_environments() -> List[str]:
|
|
335
|
-
"""List all available environment specifications.
|
|
336
|
-
|
|
337
|
-
Returns:
|
|
338
|
-
List of environment specifications in format "category/name:version"
|
|
339
|
-
"""
|
|
340
|
-
env_specs = []
|
|
341
|
-
for category, names in ENVIRONMENT_REGISTRY.items():
|
|
342
|
-
for name, versions in names.items():
|
|
343
|
-
for version in versions.keys():
|
|
344
|
-
if version != "latest": # Don't include "latest" in the list
|
|
345
|
-
env_specs.append(f"{category}/{name}:{version}")
|
|
346
|
-
|
|
347
|
-
return sorted(env_specs)
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
def list_categories() -> List[str]:
|
|
351
|
-
"""List all available environment categories.
|
|
352
|
-
|
|
353
|
-
Returns:
|
|
354
|
-
List of category names
|
|
355
|
-
"""
|
|
356
|
-
return list(ENVIRONMENT_REGISTRY.keys())
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
def list_names(category: str) -> List[str]:
|
|
360
|
-
"""List all available environment names in a category.
|
|
361
|
-
|
|
362
|
-
Args:
|
|
363
|
-
category: Environment category
|
|
364
|
-
|
|
365
|
-
Returns:
|
|
366
|
-
List of environment names in the category
|
|
367
|
-
|
|
368
|
-
Raises:
|
|
369
|
-
FleetEnvironmentError: If category is not found
|
|
370
|
-
"""
|
|
371
|
-
if category not in ENVIRONMENT_REGISTRY:
|
|
372
|
-
available_categories = ", ".join(ENVIRONMENT_REGISTRY.keys())
|
|
373
|
-
raise FleetEnvironmentError(
|
|
374
|
-
f"Unknown environment category: {category}. "
|
|
375
|
-
f"Available categories: {available_categories}"
|
|
376
|
-
)
|
|
377
|
-
|
|
378
|
-
return list(ENVIRONMENT_REGISTRY[category].keys())
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
def list_versions(category: str, name: str) -> List[str]:
|
|
382
|
-
"""List all available versions for an environment.
|
|
383
|
-
|
|
384
|
-
Args:
|
|
385
|
-
category: Environment category
|
|
386
|
-
name: Environment name
|
|
387
|
-
|
|
388
|
-
Returns:
|
|
389
|
-
List of available versions (excluding "latest")
|
|
390
|
-
|
|
391
|
-
Raises:
|
|
392
|
-
FleetEnvironmentError: If category or name is not found
|
|
393
|
-
"""
|
|
394
|
-
if category not in ENVIRONMENT_REGISTRY:
|
|
395
|
-
available_categories = ", ".join(ENVIRONMENT_REGISTRY.keys())
|
|
396
|
-
raise FleetEnvironmentError(
|
|
397
|
-
f"Unknown environment category: {category}. "
|
|
398
|
-
f"Available categories: {available_categories}"
|
|
399
|
-
)
|
|
400
|
-
|
|
401
|
-
if name not in ENVIRONMENT_REGISTRY[category]:
|
|
402
|
-
available_names = ", ".join(ENVIRONMENT_REGISTRY[category].keys())
|
|
403
|
-
raise FleetEnvironmentError(
|
|
404
|
-
f"Unknown environment name: {name} in category {category}. "
|
|
405
|
-
f"Available names: {available_names}"
|
|
406
|
-
)
|
|
407
|
-
|
|
408
|
-
versions = [v for v in ENVIRONMENT_REGISTRY[category][name].keys() if v != "latest"]
|
|
409
|
-
return sorted(versions)
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
def is_environment_supported(environment_spec: str) -> bool:
|
|
413
|
-
"""Check if an environment specification is supported.
|
|
414
|
-
|
|
415
|
-
Args:
|
|
416
|
-
environment_spec: Environment specification to check
|
|
417
|
-
|
|
418
|
-
Returns:
|
|
419
|
-
True if the environment is supported, False otherwise
|
|
420
|
-
"""
|
|
421
|
-
try:
|
|
422
|
-
env_name, version = _parse_environment_spec(environment_spec)
|
|
423
|
-
# For now, we'll just check if we can parse it successfully
|
|
424
|
-
# In the future, we could validate against the API
|
|
425
|
-
return True
|
|
426
|
-
except FleetEnvironmentError:
|
|
427
|
-
return False
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
async def _initialize_environment(env: Environment) -> None:
|
|
431
|
-
"""Initialize an environment after creation.
|
|
432
|
-
|
|
433
|
-
Args:
|
|
434
|
-
env: Environment instance to initialize
|
|
435
|
-
"""
|
|
436
|
-
# Perform any necessary initialization
|
|
437
|
-
# This could include:
|
|
438
|
-
# - Validating API key
|
|
439
|
-
# - Setting up HTTP client
|
|
440
|
-
# - Registering default facets
|
|
441
|
-
# - Performing health checks
|
|
442
|
-
|
|
443
|
-
pass
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
fleet/facets/__init__.py
DELETED
fleet/facets/base.py
DELETED
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
"""Fleet SDK Base Facet Classes."""
|
|
2
|
-
|
|
3
|
-
from abc import ABC, abstractmethod
|
|
4
|
-
from typing import Any, Dict, Optional, TYPE_CHECKING
|
|
5
|
-
from urllib.parse import urlparse
|
|
6
|
-
|
|
7
|
-
if TYPE_CHECKING:
|
|
8
|
-
from ..env.base import Environment
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class Facet(ABC):
|
|
12
|
-
"""Base class for all facets in Fleet environments."""
|
|
13
|
-
|
|
14
|
-
def __init__(self, uri: str, environment: "Environment"):
|
|
15
|
-
self.uri = uri
|
|
16
|
-
self.environment = environment
|
|
17
|
-
self._parsed_uri = urlparse(uri)
|
|
18
|
-
self._scheme = self._parsed_uri.scheme
|
|
19
|
-
self._netloc = self._parsed_uri.netloc
|
|
20
|
-
self._path = self._parsed_uri.path
|
|
21
|
-
self._params = self._parsed_uri.params
|
|
22
|
-
self._query = self._parsed_uri.query
|
|
23
|
-
self._fragment = self._parsed_uri.fragment
|
|
24
|
-
|
|
25
|
-
@property
|
|
26
|
-
def scheme(self) -> str:
|
|
27
|
-
"""Get the URI scheme (e.g., 'sqlite', 'browser', 'file')."""
|
|
28
|
-
return self._scheme
|
|
29
|
-
|
|
30
|
-
@property
|
|
31
|
-
def netloc(self) -> str:
|
|
32
|
-
"""Get the URI network location."""
|
|
33
|
-
return self._netloc
|
|
34
|
-
|
|
35
|
-
@property
|
|
36
|
-
def path(self) -> str:
|
|
37
|
-
"""Get the URI path."""
|
|
38
|
-
return self._path
|
|
39
|
-
|
|
40
|
-
@abstractmethod
|
|
41
|
-
async def initialize(self) -> None:
|
|
42
|
-
"""Initialize the facet."""
|
|
43
|
-
pass
|
|
44
|
-
|
|
45
|
-
@abstractmethod
|
|
46
|
-
async def close(self) -> None:
|
|
47
|
-
"""Close the facet and clean up resources."""
|
|
48
|
-
pass
|
|
49
|
-
|
|
50
|
-
def __repr__(self) -> str:
|
|
51
|
-
return f"{self.__class__.__name__}(uri='{self.uri}')"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class DatabaseFacet(Facet):
|
|
55
|
-
"""Base class for database facets."""
|
|
56
|
-
|
|
57
|
-
@abstractmethod
|
|
58
|
-
async def exec(self, query: str, params: Optional[Dict[str, Any]] = None) -> Any:
|
|
59
|
-
"""Execute a database query.
|
|
60
|
-
|
|
61
|
-
Args:
|
|
62
|
-
query: SQL query to execute
|
|
63
|
-
params: Query parameters
|
|
64
|
-
|
|
65
|
-
Returns:
|
|
66
|
-
Query result
|
|
67
|
-
"""
|
|
68
|
-
pass
|
|
69
|
-
|
|
70
|
-
@abstractmethod
|
|
71
|
-
async def fetch(self, query: str, params: Optional[Dict[str, Any]] = None) -> Any:
|
|
72
|
-
"""Fetch results from a database query.
|
|
73
|
-
|
|
74
|
-
Args:
|
|
75
|
-
query: SQL query to execute
|
|
76
|
-
params: Query parameters
|
|
77
|
-
|
|
78
|
-
Returns:
|
|
79
|
-
Query results
|
|
80
|
-
"""
|
|
81
|
-
pass
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
class BrowserFacet(Facet):
|
|
85
|
-
"""Base class for browser facets."""
|
|
86
|
-
|
|
87
|
-
@abstractmethod
|
|
88
|
-
async def get_dom(self) -> Dict[str, Any]:
|
|
89
|
-
"""Get the current DOM structure.
|
|
90
|
-
|
|
91
|
-
Returns:
|
|
92
|
-
DOM structure as dictionary
|
|
93
|
-
"""
|
|
94
|
-
pass
|
|
95
|
-
|
|
96
|
-
@abstractmethod
|
|
97
|
-
async def get_element(self, selector: str) -> Optional[Dict[str, Any]]:
|
|
98
|
-
"""Get an element by CSS selector.
|
|
99
|
-
|
|
100
|
-
Args:
|
|
101
|
-
selector: CSS selector
|
|
102
|
-
|
|
103
|
-
Returns:
|
|
104
|
-
Element data or None if not found
|
|
105
|
-
"""
|
|
106
|
-
pass
|
|
107
|
-
|
|
108
|
-
@abstractmethod
|
|
109
|
-
async def get_elements(self, selector: str) -> list[Dict[str, Any]]:
|
|
110
|
-
"""Get elements by CSS selector.
|
|
111
|
-
|
|
112
|
-
Args:
|
|
113
|
-
selector: CSS selector
|
|
114
|
-
|
|
115
|
-
Returns:
|
|
116
|
-
List of element data
|
|
117
|
-
"""
|
|
118
|
-
pass
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
class FileFacet(Facet):
|
|
122
|
-
"""Base class for file system facets."""
|
|
123
|
-
|
|
124
|
-
@abstractmethod
|
|
125
|
-
async def read(self, path: str) -> bytes:
|
|
126
|
-
"""Read file contents.
|
|
127
|
-
|
|
128
|
-
Args:
|
|
129
|
-
path: File path
|
|
130
|
-
|
|
131
|
-
Returns:
|
|
132
|
-
File contents as bytes
|
|
133
|
-
"""
|
|
134
|
-
pass
|
|
135
|
-
|
|
136
|
-
@abstractmethod
|
|
137
|
-
async def write(self, path: str, content: bytes) -> None:
|
|
138
|
-
"""Write file contents.
|
|
139
|
-
|
|
140
|
-
Args:
|
|
141
|
-
path: File path
|
|
142
|
-
content: Content to write
|
|
143
|
-
"""
|
|
144
|
-
pass
|
|
145
|
-
|
|
146
|
-
@abstractmethod
|
|
147
|
-
async def list_dir(self, path: str) -> list[str]:
|
|
148
|
-
"""List directory contents.
|
|
149
|
-
|
|
150
|
-
Args:
|
|
151
|
-
path: Directory path
|
|
152
|
-
|
|
153
|
-
Returns:
|
|
154
|
-
List of file/directory names
|
|
155
|
-
"""
|
|
156
|
-
pass
|
|
157
|
-
|
|
158
|
-
@abstractmethod
|
|
159
|
-
async def exists(self, path: str) -> bool:
|
|
160
|
-
"""Check if file or directory exists.
|
|
161
|
-
|
|
162
|
-
Args:
|
|
163
|
-
path: File or directory path
|
|
164
|
-
|
|
165
|
-
Returns:
|
|
166
|
-
True if exists, False otherwise
|
|
167
|
-
"""
|
|
168
|
-
pass
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
class APIFacet(Facet):
|
|
172
|
-
"""Base class for API facets."""
|
|
173
|
-
|
|
174
|
-
@abstractmethod
|
|
175
|
-
async def get(self, path: str, params: Optional[Dict[str, Any]] = None) -> Any:
|
|
176
|
-
"""Make a GET request.
|
|
177
|
-
|
|
178
|
-
Args:
|
|
179
|
-
path: API endpoint path
|
|
180
|
-
params: Query parameters
|
|
181
|
-
|
|
182
|
-
Returns:
|
|
183
|
-
API response
|
|
184
|
-
"""
|
|
185
|
-
pass
|
|
186
|
-
|
|
187
|
-
@abstractmethod
|
|
188
|
-
async def post(self, path: str, data: Optional[Dict[str, Any]] = None) -> Any:
|
|
189
|
-
"""Make a POST request.
|
|
190
|
-
|
|
191
|
-
Args:
|
|
192
|
-
path: API endpoint path
|
|
193
|
-
data: Request data
|
|
194
|
-
|
|
195
|
-
Returns:
|
|
196
|
-
API response
|
|
197
|
-
"""
|
|
198
|
-
pass
|
|
199
|
-
|
|
200
|
-
@abstractmethod
|
|
201
|
-
async def put(self, path: str, data: Optional[Dict[str, Any]] = None) -> Any:
|
|
202
|
-
"""Make a PUT request.
|
|
203
|
-
|
|
204
|
-
Args:
|
|
205
|
-
path: API endpoint path
|
|
206
|
-
data: Request data
|
|
207
|
-
|
|
208
|
-
Returns:
|
|
209
|
-
API response
|
|
210
|
-
"""
|
|
211
|
-
pass
|
|
212
|
-
|
|
213
|
-
@abstractmethod
|
|
214
|
-
async def delete(self, path: str) -> Any:
|
|
215
|
-
"""Make a DELETE request.
|
|
216
|
-
|
|
217
|
-
Args:
|
|
218
|
-
path: API endpoint path
|
|
219
|
-
|
|
220
|
-
Returns:
|
|
221
|
-
API response
|
|
222
|
-
"""
|
|
223
|
-
pass
|
fleet/facets/factory.py
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"""Fleet SDK Facet Factory."""
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
|
-
from urllib.parse import urlparse
|
|
5
|
-
|
|
6
|
-
from .base import Facet
|
|
7
|
-
from ..exceptions import FleetFacetError
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
from ..env.base import Environment
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def create_facet(uri: str, environment: "Environment") -> Facet:
|
|
14
|
-
"""Create a facet based on the URI scheme.
|
|
15
|
-
|
|
16
|
-
Args:
|
|
17
|
-
uri: URI identifying the facet (e.g., 'sqlite://crm', 'browser://dom')
|
|
18
|
-
environment: Environment instance
|
|
19
|
-
|
|
20
|
-
Returns:
|
|
21
|
-
Facet instance
|
|
22
|
-
|
|
23
|
-
Raises:
|
|
24
|
-
NotImplementedError: Facet implementations are not yet available
|
|
25
|
-
"""
|
|
26
|
-
parsed = urlparse(uri)
|
|
27
|
-
scheme = parsed.scheme.lower()
|
|
28
|
-
|
|
29
|
-
raise NotImplementedError(f"Facet implementation for scheme '{scheme}' not yet available")
|