fleet-python 0.2.66b2__py3-none-any.whl → 0.2.105__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.
- examples/export_tasks.py +16 -5
- examples/export_tasks_filtered.py +245 -0
- examples/fetch_tasks.py +230 -0
- examples/import_tasks.py +140 -8
- examples/iterate_verifiers.py +725 -0
- fleet/__init__.py +128 -5
- fleet/_async/__init__.py +27 -3
- fleet/_async/base.py +24 -9
- fleet/_async/client.py +938 -41
- fleet/_async/env/client.py +60 -3
- fleet/_async/instance/client.py +52 -7
- fleet/_async/models.py +15 -0
- fleet/_async/resources/api.py +200 -0
- fleet/_async/resources/sqlite.py +1801 -46
- fleet/_async/tasks.py +122 -25
- fleet/_async/verifiers/bundler.py +22 -21
- fleet/_async/verifiers/verifier.py +25 -19
- fleet/agent/__init__.py +32 -0
- fleet/agent/gemini_cua/Dockerfile +45 -0
- fleet/agent/gemini_cua/__init__.py +10 -0
- fleet/agent/gemini_cua/agent.py +759 -0
- fleet/agent/gemini_cua/mcp/main.py +108 -0
- fleet/agent/gemini_cua/mcp_server/__init__.py +5 -0
- fleet/agent/gemini_cua/mcp_server/main.py +105 -0
- fleet/agent/gemini_cua/mcp_server/tools.py +178 -0
- fleet/agent/gemini_cua/requirements.txt +5 -0
- fleet/agent/gemini_cua/start.sh +30 -0
- fleet/agent/orchestrator.py +854 -0
- fleet/agent/types.py +49 -0
- fleet/agent/utils.py +34 -0
- fleet/base.py +34 -9
- fleet/cli.py +1061 -0
- fleet/client.py +1060 -48
- fleet/config.py +1 -1
- fleet/env/__init__.py +16 -0
- fleet/env/client.py +60 -3
- fleet/eval/__init__.py +15 -0
- fleet/eval/uploader.py +231 -0
- fleet/exceptions.py +8 -0
- fleet/instance/client.py +53 -8
- fleet/instance/models.py +1 -0
- fleet/models.py +303 -0
- fleet/proxy/__init__.py +25 -0
- fleet/proxy/proxy.py +453 -0
- fleet/proxy/whitelist.py +244 -0
- fleet/resources/api.py +200 -0
- fleet/resources/sqlite.py +1845 -46
- fleet/tasks.py +113 -20
- fleet/utils/__init__.py +7 -0
- fleet/utils/http_logging.py +178 -0
- fleet/utils/logging.py +13 -0
- fleet/utils/playwright.py +440 -0
- fleet/verifiers/bundler.py +22 -21
- fleet/verifiers/db.py +985 -1
- fleet/verifiers/decorator.py +1 -1
- fleet/verifiers/verifier.py +25 -19
- {fleet_python-0.2.66b2.dist-info → fleet_python-0.2.105.dist-info}/METADATA +28 -1
- fleet_python-0.2.105.dist-info/RECORD +115 -0
- {fleet_python-0.2.66b2.dist-info → fleet_python-0.2.105.dist-info}/WHEEL +1 -1
- fleet_python-0.2.105.dist-info/entry_points.txt +2 -0
- tests/test_app_method.py +85 -0
- tests/test_expect_exactly.py +4148 -0
- tests/test_expect_only.py +2593 -0
- tests/test_instance_dispatch.py +607 -0
- tests/test_sqlite_resource_dual_mode.py +263 -0
- tests/test_sqlite_shared_memory_behavior.py +117 -0
- fleet_python-0.2.66b2.dist-info/RECORD +0 -81
- tests/test_verifier_security.py +0 -427
- {fleet_python-0.2.66b2.dist-info → fleet_python-0.2.105.dist-info}/licenses/LICENSE +0 -0
- {fleet_python-0.2.66b2.dist-info → fleet_python-0.2.105.dist-info}/top_level.txt +0 -0
fleet/verifiers/decorator.py
CHANGED
fleet/verifiers/verifier.py
CHANGED
|
@@ -53,6 +53,7 @@ class SyncVerifierFunction:
|
|
|
53
53
|
verifier_id: Optional[str] = None,
|
|
54
54
|
sha256: Optional[str] = None,
|
|
55
55
|
raw_code: Optional[str] = None,
|
|
56
|
+
verifier_runtime_version: Optional[str] = None,
|
|
56
57
|
):
|
|
57
58
|
self.func = func
|
|
58
59
|
self.key = key
|
|
@@ -63,6 +64,7 @@ class SyncVerifierFunction:
|
|
|
63
64
|
self._bundle_data: Optional[bytes] = None # Cached bundle data
|
|
64
65
|
self._raw_code: Optional[str] = raw_code # Store raw code if provided
|
|
65
66
|
self._is_async = inspect.iscoroutinefunction(func)
|
|
67
|
+
self.verifier_runtime_version = verifier_runtime_version
|
|
66
68
|
|
|
67
69
|
# Copy function metadata
|
|
68
70
|
functools.update_wrapper(self, func)
|
|
@@ -90,9 +92,9 @@ class SyncVerifierFunction:
|
|
|
90
92
|
|
|
91
93
|
self._bundle_data = zip_buffer.getvalue()
|
|
92
94
|
self._bundle_sha = _get_bundle_sha(self._bundle_data)
|
|
93
|
-
logger.debug(
|
|
94
|
-
|
|
95
|
-
)
|
|
95
|
+
# logger.debug(
|
|
96
|
+
# f"Created bundle from raw code for {self.key} with SHA: {self._bundle_sha}"
|
|
97
|
+
# )
|
|
96
98
|
else:
|
|
97
99
|
# Try to create bundle from function source
|
|
98
100
|
try:
|
|
@@ -100,9 +102,9 @@ class SyncVerifierFunction:
|
|
|
100
102
|
self.func, self.extra_requirements, self.verifier_id
|
|
101
103
|
)
|
|
102
104
|
self._bundle_sha = _get_bundle_sha(self._bundle_data)
|
|
103
|
-
logger.debug(
|
|
104
|
-
|
|
105
|
-
)
|
|
105
|
+
# logger.debug(
|
|
106
|
+
# f"Created bundle for {self.key} with SHA: {self._bundle_sha}"
|
|
107
|
+
# )
|
|
106
108
|
except OSError as e:
|
|
107
109
|
# Can't create bundle - no source and no raw code
|
|
108
110
|
raise OSError(f"Cannot create bundle for {self.key}: {e}")
|
|
@@ -115,20 +117,21 @@ class SyncVerifierFunction:
|
|
|
115
117
|
|
|
116
118
|
# If bundle_data is empty, we're using server-side bundle
|
|
117
119
|
if not bundle_data:
|
|
118
|
-
logger.debug(f"Using server-side bundle {bundle_sha[:8]}...")
|
|
120
|
+
# logger.debug(f"Using server-side bundle {bundle_sha[:8]}...")
|
|
119
121
|
return bundle_sha, False # No upload needed, server has it
|
|
120
122
|
|
|
121
123
|
# Always check if bundle exists on server
|
|
122
124
|
try:
|
|
123
125
|
exists = env.check_bundle_exists(bundle_sha)
|
|
124
126
|
if exists.success:
|
|
125
|
-
logger.info(f"Bundle {bundle_sha[:8]}... found on server")
|
|
127
|
+
# logger.info(f"Bundle {bundle_sha[:8]}... found on server")
|
|
126
128
|
return bundle_sha, False # Found on server, no upload needed
|
|
127
129
|
except Exception as e:
|
|
128
|
-
logger.warning(f"Failed to check bundle existence: {e}")
|
|
130
|
+
# logger.warning(f"Failed to check bundle existence: {e}")
|
|
131
|
+
pass
|
|
129
132
|
|
|
130
133
|
# Bundle not found on server - upload needed
|
|
131
|
-
logger.info(f"Bundle {bundle_sha[:8]}... needs to be uploaded")
|
|
134
|
+
# logger.info(f"Bundle {bundle_sha[:8]}... needs to be uploaded")
|
|
132
135
|
return bundle_sha, True # Upload needed
|
|
133
136
|
|
|
134
137
|
def __call__(self, env: "SyncEnv", *args, **kwargs) -> float:
|
|
@@ -158,7 +161,7 @@ class SyncVerifierFunction:
|
|
|
158
161
|
)
|
|
159
162
|
|
|
160
163
|
except Exception as e:
|
|
161
|
-
logger.error(f"Error in verifier {self.key}: {e}")
|
|
164
|
+
# logger.error(f"Error in verifier {self.key}: {e}")
|
|
162
165
|
# Return error score 0
|
|
163
166
|
return 0.0
|
|
164
167
|
|
|
@@ -190,7 +193,7 @@ class SyncVerifierFunction:
|
|
|
190
193
|
try:
|
|
191
194
|
return float(result)
|
|
192
195
|
except (ValueError, TypeError):
|
|
193
|
-
logger.warning(f"Could not convert result to float: {result}")
|
|
196
|
+
# logger.warning(f"Could not convert result to float: {result}")
|
|
194
197
|
return 0.0
|
|
195
198
|
|
|
196
199
|
def _raise_remote_error(self, error_info: Dict[str, Any]):
|
|
@@ -249,7 +252,7 @@ Remote traceback:
|
|
|
249
252
|
|
|
250
253
|
if needs_upload:
|
|
251
254
|
# Need to upload bundle to S3
|
|
252
|
-
logger.info(f"Uploading bundle {bundle_sha[:8]}... for {self.key}")
|
|
255
|
+
# logger.info(f"Uploading bundle {bundle_sha[:8]}... for {self.key}")
|
|
253
256
|
bundle_data, _ = self._get_or_create_bundle()
|
|
254
257
|
|
|
255
258
|
response = env.execute_verifier_remote(
|
|
@@ -261,14 +264,15 @@ Remote traceback:
|
|
|
261
264
|
args_array=args_array,
|
|
262
265
|
kwargs=kwargs,
|
|
263
266
|
needs_upload=True,
|
|
267
|
+
verifier_runtime_version=self.verifier_runtime_version,
|
|
264
268
|
)
|
|
265
269
|
|
|
266
|
-
logger.debug(f"Bundle {bundle_sha[:8]}... uploaded successfully")
|
|
270
|
+
# logger.debug(f"Bundle {bundle_sha[:8]}... uploaded successfully")
|
|
267
271
|
return response
|
|
268
272
|
|
|
269
273
|
else:
|
|
270
274
|
# Bundle already available - execute without upload
|
|
271
|
-
logger.info(f"Bundle {bundle_sha[:8]}... already cached for {self.key}")
|
|
275
|
+
# logger.info(f"Bundle {bundle_sha[:8]}... already cached for {self.key}")
|
|
272
276
|
response = env.execute_verifier_remote(
|
|
273
277
|
bundle_data=b"", # Empty bundle since it's cached
|
|
274
278
|
bundle_sha=bundle_sha,
|
|
@@ -278,15 +282,16 @@ Remote traceback:
|
|
|
278
282
|
args_array=args_array,
|
|
279
283
|
kwargs=kwargs,
|
|
280
284
|
needs_upload=False,
|
|
285
|
+
verifier_runtime_version=self.verifier_runtime_version,
|
|
281
286
|
)
|
|
282
287
|
return response
|
|
283
288
|
|
|
284
289
|
except Exception as e:
|
|
285
290
|
# Check if error indicates bundle not found and retry with upload
|
|
286
291
|
if self._is_bundle_not_found_error(e) and not needs_upload:
|
|
287
|
-
logger.info(
|
|
288
|
-
|
|
289
|
-
)
|
|
292
|
+
# logger.info(
|
|
293
|
+
# f"Bundle {bundle_sha[:8]}... not found on server, uploading..."
|
|
294
|
+
# )
|
|
290
295
|
bundle_data, _ = self._get_or_create_bundle()
|
|
291
296
|
response = env.execute_verifier_remote(
|
|
292
297
|
bundle_data=bundle_data,
|
|
@@ -297,10 +302,11 @@ Remote traceback:
|
|
|
297
302
|
args_array=args_array,
|
|
298
303
|
kwargs=kwargs,
|
|
299
304
|
needs_upload=True,
|
|
305
|
+
verifier_runtime_version=self.verifier_runtime_version,
|
|
300
306
|
)
|
|
301
307
|
return response
|
|
302
308
|
else:
|
|
303
|
-
logger.error(f"Error in remote execution of {self.key}: {e}")
|
|
309
|
+
# logger.error(f"Error in remote execution of {self.key}: {e}")
|
|
304
310
|
raise
|
|
305
311
|
|
|
306
312
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fleet-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.105
|
|
4
4
|
Summary: Python SDK for Fleet environments
|
|
5
5
|
Author-email: Fleet AI <nic@fleet.so>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -26,6 +26,9 @@ Requires-Dist: httpx-retries>=0.4.0
|
|
|
26
26
|
Requires-Dist: typing-extensions>=4.0.0
|
|
27
27
|
Requires-Dist: modulegraph2>=0.2.0
|
|
28
28
|
Requires-Dist: cloudpickle==3.1.1
|
|
29
|
+
Provides-Extra: cli
|
|
30
|
+
Requires-Dist: typer>=0.9.0; extra == "cli"
|
|
31
|
+
Requires-Dist: rich>=10.0.0; extra == "cli"
|
|
29
32
|
Provides-Extra: dev
|
|
30
33
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
31
34
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
@@ -35,12 +38,22 @@ Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
|
35
38
|
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
36
39
|
Requires-Dist: unasync>=0.6.0; extra == "dev"
|
|
37
40
|
Requires-Dist: python-dotenv>=1.1.1; extra == "dev"
|
|
41
|
+
Requires-Dist: typer>=0.9.0; extra == "dev"
|
|
42
|
+
Requires-Dist: rich>=10.0.0; extra == "dev"
|
|
38
43
|
Provides-Extra: playwright
|
|
39
44
|
Requires-Dist: playwright>=1.40.0; extra == "playwright"
|
|
45
|
+
Provides-Extra: eval
|
|
46
|
+
Requires-Dist: aiohttp>=3.9.0; extra == "eval"
|
|
47
|
+
Requires-Dist: google-genai>=1.0.0; extra == "eval"
|
|
48
|
+
Requires-Dist: mcp==1.24.0; python_version >= "3.10" and extra == "eval"
|
|
40
49
|
Dynamic: license-file
|
|
41
50
|
|
|
42
51
|
# Fleet SDK
|
|
43
52
|
|
|
53
|
+
[](https://pypi.org/project/fleet-python/)
|
|
54
|
+
[](https://pypi.org/project/fleet-python/)
|
|
55
|
+
[](https://pypi.org/project/fleet-python/)
|
|
56
|
+
|
|
44
57
|
The Fleet Python SDK provides programmatic access to Fleet's environment infrastructure.
|
|
45
58
|
|
|
46
59
|
## Installation
|
|
@@ -51,6 +64,20 @@ Install the Fleet SDK using pip:
|
|
|
51
64
|
pip install fleet-python
|
|
52
65
|
```
|
|
53
66
|
|
|
67
|
+
### Alpha/Pre-release Versions
|
|
68
|
+
|
|
69
|
+
To install the latest alpha or pre-release version:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install --pre fleet-python
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
To install a specific alpha version:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install fleet-python==0.2.64-alpha1
|
|
79
|
+
```
|
|
80
|
+
|
|
54
81
|
## API Key Setup
|
|
55
82
|
|
|
56
83
|
Fleet requires an API key for authentication. You can obtain one from the [Fleet Platform](https://fleetai.com/dashboard/api-keys).
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
examples/diff_example.py,sha256=iLlpBW_NBjzXBqlvYwjx74uxYZkMGJfea6s3tJhvuNY,5684
|
|
2
|
+
examples/dsl_example.py,sha256=yFLgM-Was4-w575xJgPk9DIBmXa34hLJsIB4XwTADOE,7252
|
|
3
|
+
examples/example.py,sha256=yn9mqS2yJ6896s25btnJx9-_SLLbyS-Fu-SIcas6jok,1081
|
|
4
|
+
examples/exampleResume.py,sha256=hzdL9QfYtwlje5geWS2cgWgjcnLX4UtXSAd-92F66Lw,7044
|
|
5
|
+
examples/example_account.py,sha256=t5_Tnr7DcLYfNpEAbuBySQIqsqiQQGySuiItIghCjAM,225
|
|
6
|
+
examples/example_action_log.py,sha256=pwvLro_Fkrw4DII002bHGuWfoZ6QRvUMDD9BnMqJgLQ,622
|
|
7
|
+
examples/example_client.py,sha256=M9Mfi1FcD2LtSDVk89R_-tgG98swvDYy4qx2zVayJ-0,1025
|
|
8
|
+
examples/example_mcp_anthropic.py,sha256=WzQipN6ryPYuiGcvYmaTget4Hn421ijMS6xDYWwrVyE,2619
|
|
9
|
+
examples/example_mcp_openai.py,sha256=xhqJd2-mnQs4-ZmydGrX7pPs7_X5i-YFqkO1cr3L-5g,480
|
|
10
|
+
examples/example_sync.py,sha256=EkuWmUzB1ZsBJQk6ZRflB793rKsuRHeSg5HJZHVhBB0,975
|
|
11
|
+
examples/example_task.py,sha256=dhG6STAkNsTdHs9cO1RFH9WfuvRmq5bRC211hTeFrk8,7088
|
|
12
|
+
examples/example_tasks.py,sha256=xTL8UWVAuolSX6swskfrAcmDrLIzn45dJ7YPWCwoEBU,514
|
|
13
|
+
examples/example_verifier.py,sha256=0vwNITIG3m4CkSPwIxNXcGx9TqrxEsCGqK2A8keKZMM,2392
|
|
14
|
+
examples/export_tasks.py,sha256=JMNCMuAPxAzBm0B0JY7BZTHRBBBqsL7WWdLo9IRrdNk,3694
|
|
15
|
+
examples/export_tasks_filtered.py,sha256=FypvBrtNHOqnxuYTJ-gbb13raYAdnpPQDPySs3-dAgI,7726
|
|
16
|
+
examples/fetch_tasks.py,sha256=3A4F0OSUTwUddTOoDNlI-CSxeOnpl3E3zHBh0Qsw9A8,6865
|
|
17
|
+
examples/gemini_example.py,sha256=qj9WDazQTYNiRHNeUg9Tjkp33lJMwbx8gDfpFe1sDQo,16180
|
|
18
|
+
examples/import_tasks.py,sha256=QaapnE3lO68nrRRr0fB5n_NaDsIsQjgv1cbH60bBdUQ,16576
|
|
19
|
+
examples/iterate_verifiers.py,sha256=XbMWyWKAYKJSufVPehG3C_JeSC7ZVXw2_s1KzIMnGVs,25435
|
|
20
|
+
examples/json_tasks_example.py,sha256=CYPESGGtOo0fmsDdLidujTfsE4QlJHw7rOhyVqPJ_Ls,5329
|
|
21
|
+
examples/nova_act_example.py,sha256=rH23Lp74Okf0rn8ynMdWjK2aviEf5NLPH4k_53Pyxho,831
|
|
22
|
+
examples/openai_example.py,sha256=dEWERrTEP5xBiGkLkQjBQGd2NqoxX6gcW6XteBPsWFQ,8231
|
|
23
|
+
examples/openai_simple_example.py,sha256=HmiufucrAZne7tHq9uoEsDWlEhjNC265bQAyIGBRU2o,1745
|
|
24
|
+
examples/query_builder_example.py,sha256=-cOMfWGNifYfYEt_Ds73XpwATZvFDL6F4KTkVxdMjzg,3951
|
|
25
|
+
examples/quickstart.py,sha256=1VT39IRRhemsJgxi0O0gprdpcw7HB4pYO97GAYagIcg,3788
|
|
26
|
+
examples/test_cdp_logging.py,sha256=AkCwQCgOTQEI8w3v0knWK_4eXMph7L9x07wj9yIYM10,2836
|
|
27
|
+
fleet/__init__.py,sha256=A2DiarJ8g0IABXtnH1AlTrVuSSwHXQSCexUS5i_pyqc,7798
|
|
28
|
+
fleet/base.py,sha256=J3joFnaxzx4Wr5UYHY0ME17ML2jRWU8VeXEniuDogx4,10066
|
|
29
|
+
fleet/cli.py,sha256=arX1E-fjLXtcV3tVVkPHfEXxl7FDn4zRmf0ssXlXaMg,40104
|
|
30
|
+
fleet/client.py,sha256=maxdDJQzs_30O0bbYRBrIXULJwr3TK2WV3ObgeQ1VK4,68855
|
|
31
|
+
fleet/config.py,sha256=n_wh9Sahu3gGE7nHJ7kqNFUH1qDiBtF4bgZq9MvIBMU,319
|
|
32
|
+
fleet/exceptions.py,sha256=YqhQonZlxGdLP1HD0DNdKs9Q9BuyeYvK3pc6Glhpl14,5352
|
|
33
|
+
fleet/global_client.py,sha256=frrDAFNM2ywN0JHLtlm9qbE1dQpnQJsavJpb7xSR_bU,1072
|
|
34
|
+
fleet/models.py,sha256=AwCAoIypInbZoz-SCI1vuPktwB5kO7k3RqNRJGU2RCY,25924
|
|
35
|
+
fleet/tasks.py,sha256=vWiAIvRuo-n32pdH14XYo5NVEc6yeUWkqlnC0nGcIxg,21634
|
|
36
|
+
fleet/types.py,sha256=L4Y82xICf1tzyCLqhLYUgEoaIIS5h9T05TyFNHSWs3s,652
|
|
37
|
+
fleet/_async/__init__.py,sha256=CPMG5GSFyFDN2CL1lZ_RXEoy1nWnkGqOiMhYVxNOnR4,9116
|
|
38
|
+
fleet/_async/base.py,sha256=jtNofzMjT8QVSuDHOGmluYi5pEW4RVwOz7338mPxw0Q,9631
|
|
39
|
+
fleet/_async/client.py,sha256=bXsavcwOa1kyi6AGpioDyGK2Cj4eQ4WWB4YmNNK5EQ0,65278
|
|
40
|
+
fleet/_async/exceptions.py,sha256=fUmPwWhnT8SR97lYsRq0kLHQHKtSh2eJS0VQ2caSzEI,5055
|
|
41
|
+
fleet/_async/global_client.py,sha256=4WskpLHbsDEgWW7hXMD09W-brkp4euy8w2ZJ88594rQ,1103
|
|
42
|
+
fleet/_async/models.py,sha256=sCpTZHEfoOvcKv0gLlXGc92XzbfskHe7CKvzEOhNvns,14176
|
|
43
|
+
fleet/_async/tasks.py,sha256=29ODUC-a5a5yye9B2HrIOpRwKlc2yhF8Du_KE2DSDmY,21603
|
|
44
|
+
fleet/_async/env/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
45
|
+
fleet/_async/env/client.py,sha256=FqetvDlABeHLaAc8UF_m_2OFEhXy4ZqH7ly_Nh8p3uA,3479
|
|
46
|
+
fleet/_async/instance/__init__.py,sha256=PtmJq8J8bh0SOQ2V55QURz5GJfobozwtQoqhaOk3_tI,515
|
|
47
|
+
fleet/_async/instance/base.py,sha256=3qUBuUR8OVS36LzdP6KyZzngtwPKYO09HoY6Ekxp-KA,1625
|
|
48
|
+
fleet/_async/instance/client.py,sha256=eV_KxJ-8FX1KQcQd1FIEuPax6atHcTcFbuAf5U_Q4R4,7961
|
|
49
|
+
fleet/_async/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
50
|
+
fleet/_async/resources/api.py,sha256=qlM1Ab3LNe1r7Hx27es4CRK565ZLVaJQeEtZKCe9cM0,6260
|
|
51
|
+
fleet/_async/resources/base.py,sha256=UfrenxUqcpL8SgYGOo8o8HgRvv2-ZO5G2Cdo91ofEdg,664
|
|
52
|
+
fleet/_async/resources/browser.py,sha256=oldoSiymJ1lJkADhpUG81ViOBDNyppX1jSoEwe9-W94,1369
|
|
53
|
+
fleet/_async/resources/mcp.py,sha256=TLEsLiFhfVfZFs0Fu_uDPm-h4FPdvqgQblYqs-PTHhc,1720
|
|
54
|
+
fleet/_async/resources/sqlite.py,sha256=RiSMkruGpAWzU19fWCczvx76Ht4yevFqdhcaGjTzuSM,106472
|
|
55
|
+
fleet/_async/verifiers/__init__.py,sha256=1WTlCNq4tIFbbXaQu5Bf2WppZq0A8suhtZbxMTSOwxI,465
|
|
56
|
+
fleet/_async/verifiers/bundler.py,sha256=9aWWXFsovBPcndE06IATn5jaeli5fRORAYeenF9heN0,26264
|
|
57
|
+
fleet/_async/verifiers/verifier.py,sha256=iSa-rO-E1R3IQTFS9Z7jbQvQVtsDkilITQP9IIQU2JA,14556
|
|
58
|
+
fleet/agent/__init__.py,sha256=BuiElLoL_OTq_tmEMD85Zc1x3x9iUerYM7TxLpD22aI,737
|
|
59
|
+
fleet/agent/orchestrator.py,sha256=ciZFctuv_MOmn_IoK021YpDsPLvuG40YLywsX-oA2j4,30308
|
|
60
|
+
fleet/agent/types.py,sha256=SjJbMju13EPjTPnH7igv860RhCIIKCIQnGEgc8GnHZM,1476
|
|
61
|
+
fleet/agent/utils.py,sha256=VNhyIFwTKizl00ccqXdhh6s3DYZxPy55PMXgYhTLNX4,1171
|
|
62
|
+
fleet/agent/gemini_cua/Dockerfile,sha256=hYsbLu5vJron9zsYZcFj09JgKrZ-MUXiUShg_TOmWsI,1314
|
|
63
|
+
fleet/agent/gemini_cua/__init__.py,sha256=EqjnPPhWWUI3Gk5FrWKfajVYPn_nlO6tTl_jPdeHSXU,205
|
|
64
|
+
fleet/agent/gemini_cua/agent.py,sha256=OFzivTnUHCKqHqD2iXLADxtgVlJBvMkWrYLBw5EByG8,30191
|
|
65
|
+
fleet/agent/gemini_cua/requirements.txt,sha256=dOM2T5EVihE6FUSQNIMtcegeKtEpir5b3KD2fF28ZF0,82
|
|
66
|
+
fleet/agent/gemini_cua/start.sh,sha256=KIagmkBMKAUvwZA25jOIQXju4L-lSLppfpsQvR8m7zg,888
|
|
67
|
+
fleet/agent/gemini_cua/mcp/main.py,sha256=yXoZoWWvHJPnGAOQz-2zkFqlm1twOXLsUSlEKTT6Su4,3413
|
|
68
|
+
fleet/agent/gemini_cua/mcp_server/__init__.py,sha256=AJSApqzVShZfsLLDCKhCicfys0rvsbXAQMXXH2Z7usc,131
|
|
69
|
+
fleet/agent/gemini_cua/mcp_server/main.py,sha256=wSUdLwdmUtLRGqBzgPQAQu62gGdx9oPDjXywW1DQG8k,3350
|
|
70
|
+
fleet/agent/gemini_cua/mcp_server/tools.py,sha256=wfveimMkU0sTqoquotvSbOdb_yDG7DyVeZHHWk0opGo,6462
|
|
71
|
+
fleet/env/__init__.py,sha256=BVPZ4AYTznL6AYNrVmjr1yLF16qBcT1U56jWwF7AJ5o,964
|
|
72
|
+
fleet/env/client.py,sha256=N9oF2hGSNmfVacTnyQhIEocoN3BA5fMa-arbpVeNi-E,3221
|
|
73
|
+
fleet/eval/__init__.py,sha256=ng9V-KTsdW-bOOyF7UUGvABA9x0npeuYzMdS3MUd4nQ,389
|
|
74
|
+
fleet/eval/uploader.py,sha256=UUuoWJASwEqlP-YkzscX7ssiKRSAEVqC4YcCvSBBrWQ,7210
|
|
75
|
+
fleet/instance/__init__.py,sha256=CyWUkbGAK-DBPw4DC4AnCW-MqqheGhZMA5QSRVu-ws4,479
|
|
76
|
+
fleet/instance/base.py,sha256=OYqzBwZFfTX9wlBGSG5gljqj98NbiJeKIfFJ3uj5I4s,1587
|
|
77
|
+
fleet/instance/client.py,sha256=LB_Tiljah91haV6-WK2Vx0XDOYx94KploOlfQDmkjok,7737
|
|
78
|
+
fleet/instance/models.py,sha256=AZX-8WceLtfBtu6J54_N6vq1XjLQrtI1UbnyfNyIMu4,4199
|
|
79
|
+
fleet/proxy/__init__.py,sha256=XoDk8k2TOTap1IU0ErfP-YUTTi7_u42xEmOzkBHZt8o,551
|
|
80
|
+
fleet/proxy/proxy.py,sha256=VKpTGgJ7iFfUQkfkNw1eVTqmMHhULV70Eb-iB7SpeVY,15972
|
|
81
|
+
fleet/proxy/whitelist.py,sha256=3lKrfwaUgf8GyXalRDpgoB9MORnmEh7Nt4LF-h-M_PY,6721
|
|
82
|
+
fleet/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
83
|
+
fleet/resources/api.py,sha256=7YQcATXjhNeEbrIDXqSMerGywxefcRz8luqrObfcsl8,6066
|
|
84
|
+
fleet/resources/base.py,sha256=AXZzT0_yWHkT497q3yekfr0xsD4cPGMCC6y7C43TIkk,663
|
|
85
|
+
fleet/resources/browser.py,sha256=hRNM0YMsVQUAraZGNi_B-KXxLpuddy4ntoEDFSw7czU,1295
|
|
86
|
+
fleet/resources/mcp.py,sha256=c6O4vVJnXANuHMGMe4IPxgp4zBEbFaGm6_d9e6j8Myc,1695
|
|
87
|
+
fleet/resources/sqlite.py,sha256=RpfAkMPAiqYQSnpB258lomPfaFtDIVVF_ERS2ycfLtU,107242
|
|
88
|
+
fleet/utils/__init__.py,sha256=cZdaIU4KWr_xQFDpShTC2P_XVLYrlDFSBTQwWzfDQ2o,255
|
|
89
|
+
fleet/utils/http_logging.py,sha256=N1qRwOHA4nTe-3JOy-2J9AK0eneWAfv9s66qnyU_Vnw,6332
|
|
90
|
+
fleet/utils/logging.py,sha256=-F_JbGIAaIt_WqVJC0ch4iog4WWFQDJgUS2vxg3YH0A,319
|
|
91
|
+
fleet/utils/playwright.py,sha256=UZrlJJC5z3deQfvSAo03g-ajNkN52b333gBjqvQ6Qa0,15546
|
|
92
|
+
fleet/verifiers/__init__.py,sha256=GntS8qc3xv8mm-cku1t3xjvOll5jcc5FuiVqQgR4Y6Q,458
|
|
93
|
+
fleet/verifiers/bundler.py,sha256=9aWWXFsovBPcndE06IATn5jaeli5fRORAYeenF9heN0,26264
|
|
94
|
+
fleet/verifiers/code.py,sha256=A1i_UabZspbyj1awzKVQ_HRxgMO3fU7NbkxYyTrp7So,48
|
|
95
|
+
fleet/verifiers/db.py,sha256=CwuEaH1xpLdzhH3OpP0Fb5PAezIp4WhAMX4Kvo1WcCU,73138
|
|
96
|
+
fleet/verifiers/decorator.py,sha256=RuTjjDijbicNfMSjA7HcTpKueEki5dzNOdTuHS7UoZs,3262
|
|
97
|
+
fleet/verifiers/parse.py,sha256=qz9AfJrTbjlg-LU-lE8Ciqi7Yt2a8-cs17FdpjTLhMk,8550
|
|
98
|
+
fleet/verifiers/sql_differ.py,sha256=TqTLWyK3uOyLbitT6HYzYEzuSFC39wcyhgk3rcm__k8,6525
|
|
99
|
+
fleet/verifiers/verifier.py,sha256=iqGevW7dSd0J5RdRQjpu-zioy_FYAXnzMfkuB3-QmO0,14601
|
|
100
|
+
fleet_python-0.2.105.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
101
|
+
scripts/fix_sync_imports.py,sha256=X9fWLTpiPGkSHsjyQUDepOJkxOqw1DPj7nd8wFlFqLQ,8368
|
|
102
|
+
scripts/unasync.py,sha256=vWVQxRWX8SRZO5cmzEhpvnG_REhCWXpidIGIpWmEcvI,696
|
|
103
|
+
tests/__init__.py,sha256=Re1SdyxH8NfyL1kjhi7SQkGP1mYeWB-D6UALqdIMd8I,35
|
|
104
|
+
tests/test_app_method.py,sha256=kg2IiL75cH-HmsTMS3_wDL39dAesgfv_AT6jVthd5J4,3159
|
|
105
|
+
tests/test_expect_exactly.py,sha256=BFw7a7REl0L_B6gGCIeOPb6seot-WIFu9kHdBjCNbgk,149614
|
|
106
|
+
tests/test_expect_only.py,sha256=uVAwbZYk05nqoQmrTc2FFJ9MLAGXweuVGfM_wT6rk-s,89536
|
|
107
|
+
tests/test_instance_dispatch.py,sha256=CvU4C3LBIqsYZdEsEFfontGjyxAZfVYyXnGwxyIvXOc,23065
|
|
108
|
+
tests/test_sqlite_resource_dual_mode.py,sha256=Mh8jBd-xsIGDYFsOACKKK_5DXMUYlFFS7W-jaY6AjG4,8734
|
|
109
|
+
tests/test_sqlite_shared_memory_behavior.py,sha256=fKx_1BmLS3b8x-9pMgjMycpnaHWY8P-2ZuXEspx6Sbw,4082
|
|
110
|
+
tests/test_verifier_from_string.py,sha256=Lxi3TpFHFb-hG4-UhLKZJkqo84ax9YJY8G6beO-1erM,13581
|
|
111
|
+
fleet_python-0.2.105.dist-info/METADATA,sha256=NwO9s7UsvR__0HlJ4HrVmePEKQk8ovLDR_64Se4cfGI,4240
|
|
112
|
+
fleet_python-0.2.105.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
113
|
+
fleet_python-0.2.105.dist-info/entry_points.txt,sha256=qKIQ326cHR5WyCd16QnrW-1DpcT0YyxVRDb3IlTyzTA,39
|
|
114
|
+
fleet_python-0.2.105.dist-info/top_level.txt,sha256=qb1zIbtEktyhRFZdqVytwg54l64qtoZL0wjHB4bUg3c,29
|
|
115
|
+
fleet_python-0.2.105.dist-info/RECORD,,
|
tests/test_app_method.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Unit tests for SyncEnv.app() method URL handling."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from unittest.mock import Mock, patch
|
|
5
|
+
from fleet.client import Fleet
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestAppMethod:
|
|
9
|
+
"""Test SyncEnv.app() method with different URL formats."""
|
|
10
|
+
|
|
11
|
+
@pytest.fixture
|
|
12
|
+
def fleet_client(self):
|
|
13
|
+
"""Create a Fleet client with mocked HTTP client."""
|
|
14
|
+
with patch("fleet.client.default_httpx_client") as mock_client:
|
|
15
|
+
mock_client.return_value = Mock()
|
|
16
|
+
client = Fleet(api_key="test_key")
|
|
17
|
+
client.client.request = Mock()
|
|
18
|
+
return client
|
|
19
|
+
|
|
20
|
+
def test_app_with_existing_app_path(self, fleet_client):
|
|
21
|
+
"""Test app() with URL that already has an app path like /sentry."""
|
|
22
|
+
# Create instance with a URL that has an existing app path
|
|
23
|
+
env = fleet_client.instance("https://example.com/sentry/api/v1/env")
|
|
24
|
+
|
|
25
|
+
# Access jira app
|
|
26
|
+
jira_client = env.app("jira")
|
|
27
|
+
|
|
28
|
+
# Check the constructed URL
|
|
29
|
+
assert jira_client.base_url == "https://example.com/jira/api/v1/env", \
|
|
30
|
+
f"Expected https://example.com/jira/api/v1/env, got {jira_client.base_url}"
|
|
31
|
+
|
|
32
|
+
def test_app_without_app_path(self, fleet_client):
|
|
33
|
+
"""Test app() with URL that has no app path (just /api/v1/env)."""
|
|
34
|
+
# Create instance with a URL without an app path
|
|
35
|
+
env = fleet_client.instance("https://example.com/api/v1/env")
|
|
36
|
+
|
|
37
|
+
# Access jira app
|
|
38
|
+
jira_client = env.app("jira")
|
|
39
|
+
|
|
40
|
+
# Check the constructed URL
|
|
41
|
+
assert jira_client.base_url == "https://example.com/jira/api/v1/env", \
|
|
42
|
+
f"Expected https://example.com/jira/api/v1/env, got {jira_client.base_url}"
|
|
43
|
+
|
|
44
|
+
def test_app_with_different_app_names(self, fleet_client):
|
|
45
|
+
"""Test app() with multiple different app names."""
|
|
46
|
+
env = fleet_client.instance("https://example.com/api/v1/env")
|
|
47
|
+
|
|
48
|
+
jira = env.app("jira")
|
|
49
|
+
sentry = env.app("sentry")
|
|
50
|
+
github = env.app("github")
|
|
51
|
+
|
|
52
|
+
assert jira.base_url == "https://example.com/jira/api/v1/env"
|
|
53
|
+
assert sentry.base_url == "https://example.com/sentry/api/v1/env"
|
|
54
|
+
assert github.base_url == "https://example.com/github/api/v1/env"
|
|
55
|
+
|
|
56
|
+
def test_app_caching(self, fleet_client):
|
|
57
|
+
"""Test that app() caches InstanceClient instances."""
|
|
58
|
+
env = fleet_client.instance("https://example.com/api/v1/env")
|
|
59
|
+
|
|
60
|
+
# Call app("jira") twice
|
|
61
|
+
jira1 = env.app("jira")
|
|
62
|
+
jira2 = env.app("jira")
|
|
63
|
+
|
|
64
|
+
# Should return the same cached instance
|
|
65
|
+
assert jira1 is jira2
|
|
66
|
+
|
|
67
|
+
def test_app_with_localhost(self, fleet_client):
|
|
68
|
+
"""Test app() with localhost URLs."""
|
|
69
|
+
env = fleet_client.instance("http://localhost:8080/api/v1/env")
|
|
70
|
+
|
|
71
|
+
jira = env.app("jira")
|
|
72
|
+
|
|
73
|
+
assert jira.base_url == "http://localhost:8080/jira/api/v1/env"
|
|
74
|
+
|
|
75
|
+
def test_app_with_port(self, fleet_client):
|
|
76
|
+
"""Test app() with URLs that include port numbers."""
|
|
77
|
+
env = fleet_client.instance("https://example.com:9000/api/v1/env")
|
|
78
|
+
|
|
79
|
+
jira = env.app("jira")
|
|
80
|
+
|
|
81
|
+
assert jira.base_url == "https://example.com:9000/jira/api/v1/env"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if __name__ == "__main__":
|
|
85
|
+
pytest.main([__file__, "-v"])
|