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.

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
@@ -1,7 +0,0 @@
1
- """Fleet SDK Facet Module."""
2
-
3
- from .base import Facet
4
-
5
- __all__ = [
6
- "Facet",
7
- ]
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")