fleet-python 0.2.20__py3-none-any.whl → 0.2.22__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.

@@ -0,0 +1,143 @@
1
+ import re
2
+
3
+
4
+ def extract_function_name(function_code: str) -> str | None:
5
+ """
6
+ Extract function name from Python function code.
7
+
8
+ Handles both regular functions (def) and async functions (async def).
9
+
10
+ Args:
11
+ function_code: Python function code as a string
12
+
13
+ Returns:
14
+ The function name if found, None otherwise
15
+ """
16
+ # Pattern to match both def and async def functions
17
+ # Handles various formatting styles and type annotations
18
+ pattern = r'(?:async\s+)?def\s+(\w+)\s*\('
19
+
20
+ match = re.search(pattern, function_code)
21
+ if match:
22
+ return match.group(1)
23
+
24
+ return None
25
+
26
+
27
+ def convert_verifier_string(verifier_str: str) -> str:
28
+ """
29
+ Convert a verifier function string from the old format (env: Environment)
30
+ to the new format (before: DatabaseSnapshot, after: DatabaseSnapshot).
31
+
32
+ Args:
33
+ verifier_str: The original verifier function as a string
34
+
35
+ Returns:
36
+ The converted verifier function string
37
+ """
38
+ # First, handle escaped newlines in the input
39
+ verifier_str = verifier_str.replace('\\n', '\n')
40
+
41
+ # Extract function name, docstring, and body
42
+ # More flexible pattern that accepts both int and float return types
43
+ func_pattern = r'def\s+(\w+)\s*\(\s*env(?:\s*:\s*Environment)?\s*,?\s*final_answer(?:\s*:\s*str\s*\|\s*None)?\s*(?:=\s*None)?\s*\)\s*->\s*(?:float|int):\s*\n((?:\s*""".*?"""\s*\n)?)(.*)'
44
+ match = re.match(func_pattern, verifier_str.strip(), re.DOTALL)
45
+
46
+ if not match:
47
+ # Try with multiline pattern
48
+ func_pattern_multiline = r'def\s+(\w+)\s*\(\s*\n?\s*env(?:\s*:\s*Environment)?\s*,?\s*\n?\s*final_answer(?:\s*:\s*str\s*\|\s*None)?\s*(?:=\s*None)?\s*\n?\s*\)\s*->\s*(?:float|int):\s*\n((?:\s*""".*?"""\s*\n)?)(.*)'
49
+ match = re.match(func_pattern_multiline, verifier_str.strip(), re.DOTALL)
50
+
51
+ if not match:
52
+ raise ValueError("Could not parse verifier function. Expected format: def function_name(env: Environment, final_answer: str | None = None) -> float/int:")
53
+
54
+ func_name = match.group(1)
55
+ docstring = match.group(2).strip()
56
+ body = match.group(3)
57
+
58
+ # Find all unique env.db() calls
59
+ db_calls = re.findall(r'env\.db\("(\w+)"\)', body)
60
+ unique_db_names = list(dict.fromkeys(db_calls)) # Remove duplicates while preserving order
61
+
62
+ # Build the new function
63
+ new_func = f'''def {func_name}(
64
+ before: DatabaseSnapshot, after: DatabaseSnapshot, transcript: str | None = None
65
+ ) -> int:
66
+ class Environment:
67
+ def db(self, name: str) -> DatabaseSnapshot:'''
68
+
69
+ # Build the db method based on found database names
70
+ if unique_db_names:
71
+ conditions = []
72
+ for db_name in unique_db_names:
73
+ if db_name == "seed":
74
+ conditions.append('before if name == "seed"')
75
+ elif db_name == "current":
76
+ conditions.append('after')
77
+ else:
78
+ # Handle other database names if needed
79
+ conditions.append(f'None # Handle "{db_name}"')
80
+
81
+ if len(conditions) == 2 and "seed" in unique_db_names and "current" in unique_db_names:
82
+ new_func += f'''
83
+ return before if name == "seed" else after'''
84
+ else:
85
+ # More complex mapping if needed
86
+ new_func += f'''
87
+ if name == "seed":
88
+ return before
89
+ elif name == "current":
90
+ return after
91
+ else:
92
+ raise ValueError(f"Unknown database name: {{name}}")'''
93
+ else:
94
+ new_func += '''
95
+ return before if name == "seed" else after'''
96
+
97
+ new_func += '''
98
+
99
+ @property
100
+ def instance(self):
101
+ return self
102
+
103
+ def load(self):
104
+ pass
105
+
106
+ def verifier(env: Environment, final_answer: str | None = None) -> float:'''
107
+
108
+ if docstring:
109
+ new_func += f'\n {docstring}'
110
+
111
+ # First, find the minimum indentation in the body (excluding empty lines)
112
+ body_lines = body.splitlines()
113
+ min_indent = float('inf')
114
+ for line in body_lines:
115
+ if line.strip(): # Non-empty line
116
+ indent_len = len(line) - len(line.lstrip())
117
+ min_indent = min(min_indent, indent_len)
118
+
119
+ # If we didn't find any non-empty lines, set min_indent to 0
120
+ if min_indent == float('inf'):
121
+ min_indent = 0
122
+
123
+ # Now strip the minimum indentation and re-indent to 8 spaces
124
+ if body_lines:
125
+ indented_lines = []
126
+ for line in body_lines:
127
+ if line.strip(): # Non-empty line
128
+ # Remove the minimum indentation and add 8 spaces
129
+ stripped_line = line[min_indent:] if len(line) > min_indent else line.lstrip()
130
+ indented_lines.append(' ' + stripped_line)
131
+ else: # Empty line
132
+ indented_lines.append('')
133
+
134
+ indented_body = '\n'.join(indented_lines)
135
+ new_func += f'\n{indented_body}'
136
+
137
+ # Add the return statement
138
+ new_func += '\n\n return verifier(Environment(), transcript)'
139
+
140
+ # Replace TASK_FAILED_SCORE with 0 in the function string
141
+ new_func = new_func.replace('TASK_FAILED_SCORE', '0')
142
+
143
+ return new_func
@@ -9,14 +9,12 @@ that verifiers operate within an environment context.
9
9
 
10
10
  import functools
11
11
  import uuid
12
- import asyncio
13
12
  import logging
14
13
  import hashlib
15
- import inspect
16
- from typing import Any, Callable, Dict, Optional, List, TypeVar, Set, Union
14
+ from typing import Any, Callable, Dict, Optional, List, TypeVar, Set
17
15
 
18
16
  from .bundler import FunctionBundler
19
- from ..client import Environment
17
+ from ..client import SyncEnv
20
18
 
21
19
  logger = logging.getLogger(__name__)
22
20
 
@@ -44,7 +42,6 @@ class SyncVerifierFunction:
44
42
  ):
45
43
  self.func = func
46
44
  self.key = key
47
- self.name = key # Keep name for backward compatibility
48
45
  self.verifier_id = verifier_id or str(uuid.uuid4())
49
46
  self.extra_requirements = extra_requirements or []
50
47
  self._bundler = FunctionBundler()
@@ -65,11 +62,11 @@ class SyncVerifierFunction:
65
62
  self.verifier_id
66
63
  )
67
64
  self._bundle_sha = _get_bundle_sha(self._bundle_data)
68
- logger.debug(f"Created bundle for {self.name} with SHA: {self._bundle_sha}")
65
+ logger.debug(f"Created bundle for {self.key} with SHA: {self._bundle_sha}")
69
66
 
70
67
  return self._bundle_data, self._bundle_sha
71
68
 
72
- def _check_bundle_status(self, env: Environment) -> tuple[str, bool]:
69
+ def _check_bundle_status(self, env: SyncEnv) -> tuple[str, bool]:
73
70
  """Check if bundle needs to be uploaded and return (sha, needs_upload)."""
74
71
  bundle_data, bundle_sha = self._get_or_create_bundle()
75
72
 
@@ -93,7 +90,7 @@ class SyncVerifierFunction:
93
90
  logger.info(f"Bundle {bundle_sha[:8]}... needs to be uploaded")
94
91
  return bundle_sha, True # Upload needed
95
92
 
96
- def __call__(self, env: Environment, *args, **kwargs) -> float:
93
+ def __call__(self, env: SyncEnv, *args, **kwargs) -> float:
97
94
  """Local execution of the verifier function with env as first parameter."""
98
95
  try:
99
96
  if self._is_async:
@@ -118,15 +115,15 @@ class SyncVerifierFunction:
118
115
  raise ValueError(f"Verifier function must return a score (number). Got {type(result)}")
119
116
 
120
117
  except Exception as e:
121
- logger.error(f"Error in verifier {self.name}: {e}")
118
+ logger.error(f"Error in verifier {self.key}: {e}")
122
119
  # Return error score 0
123
120
  return 0.0
124
121
 
125
- def remote(self, env: Environment, *args, **kwargs) -> float:
122
+ def remote(self, env: SyncEnv, *args, **kwargs) -> float:
126
123
  """Remote execution of the verifier function with SHA-based bundle caching."""
127
124
  if self._is_async:
128
125
  raise NotImplementedError(
129
- f"Async verifier '{self.name}' cannot be executed remotely. "
126
+ f"Async verifier '{self.key}' cannot be executed remotely. "
130
127
  "The remote execution environment only supports synchronous functions. "
131
128
  "Please provide a synchronous version of your verifier."
132
129
  )
@@ -223,7 +220,7 @@ Remote traceback:
223
220
  except:
224
221
  raise RuntimeError(full_message)
225
222
 
226
- def _get_env_id(self, env: Environment) -> str:
223
+ def _get_env_id(self, env: SyncEnv) -> str:
227
224
  """Generate a unique identifier for the environment."""
228
225
  # Use instance base URL or similar unique identifier
229
226
  if hasattr(env, 'instance') and hasattr(env.instance, 'base_url'):
@@ -298,4 +295,4 @@ def verifier(
298
295
  verifier_uuid
299
296
  )
300
297
 
301
- return decorator
298
+ return decorator
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleet-python
3
- Version: 0.2.20
3
+ Version: 0.2.22
4
4
  Summary: Python SDK for Fleet environments
5
5
  Author-email: Fleet AI <nic@fleet.so>
6
6
  License: Apache-2.0
@@ -1,5 +1,5 @@
1
1
  examples/diff_example.py,sha256=zXEPFC-_Ap_uEihf0Shs5R7W7Pq1I5i_Y_KC-TYxyQw,5643
2
- examples/dsl_example.py,sha256=tYHfSyuyhJUSL-nKDhMA4hgZgDVNQkF5RRJLof6H_WY,7163
2
+ examples/dsl_example.py,sha256=ApdJ8Dj4ZSHyE04M6pMFhWoACdkuvUSVKfEymSPs9Oc,7190
3
3
  examples/example.py,sha256=SAz5iPxca8n9MvnHVoWHI7GCaTgJwkegX78rMutF9gE,1082
4
4
  examples/example_action_log.py,sha256=XrLqFNS8hD-K6nKVSohYi6oJkYotLCZJYJsGSbHuqEc,627
5
5
  examples/example_client.py,sha256=70HKEhz_Gb79YcvKQauCPdS08AAwjo9unt2dh1jN_Oo,1030
@@ -15,53 +15,55 @@ examples/openai_example.py,sha256=I2vk_SJN9BkSRQCYRJfbtGJ-HJ2xzQj-lOjwqmLos5M,82
15
15
  examples/openai_simple_example.py,sha256=I42ytIwv0INgDO39pp1MOQSqsJz2YYH8GeNNBaUtq3A,1748
16
16
  examples/query_builder_example.py,sha256=Q3lUBETHpu1aS2FXAO79ADYqCxOjMMMZNgCcFVapiII,3918
17
17
  examples/quickstart.py,sha256=1VT39IRRhemsJgxi0O0gprdpcw7HB4pYO97GAYagIcg,3788
18
- fleet/__init__.py,sha256=9EsG068VCTqCCyBA2jw8IMLw4_oFkWLhtY394CtjEgM,2234
18
+ fleet/__init__.py,sha256=m_Y_HYmMPWfWzUgt-jvm1ZP9kLeRlhy3sjNb0IDMWME,2284
19
19
  fleet/base.py,sha256=0yYuMN0lBkrfTTZBt5NQp5112xWgziuWEk4GuHJB1wE,9189
20
- fleet/client.py,sha256=HrHkxQMk9_2GsyG7_edauKets3xySglCUuXW3WtXmTE,28263
20
+ fleet/client.py,sha256=SDrq3gfmbAa-F-wmewHN7PyoUc2SWKy2DdaYmJHx1dk,11591
21
21
  fleet/config.py,sha256=zd19st83NJdW9DdOq7Irpc0x-iUnMad0JOtAr_nD5DM,273
22
22
  fleet/exceptions.py,sha256=fUmPwWhnT8SR97lYsRq0kLHQHKtSh2eJS0VQ2caSzEI,5055
23
- fleet/models.py,sha256=YMHFAgBF4OqoAOv-arHze3bPDDZ5DAzb3CXhVLF6pPw,9019
24
- fleet/tasks.py,sha256=w-0vVGfEuCWRHMEJ73SN141J7Lz2pD_0v-nNG4TyJTU,1645
23
+ fleet/models.py,sha256=gH3hpQM5awRqagSGPIsjOleB8AdFND8E4s9ZkZc5c_0,11372
24
+ fleet/tasks.py,sha256=Zxz1qAq4C7MT1ZuqIeGp6gf6RCAYSkFDQtm6Je5UEk4,1644
25
25
  fleet/types.py,sha256=eXeI8BFmiU5hln0PVvJbUZs7BSjl6wSqAtN9zaJT6yY,652
26
26
  fleet/_async/__init__.py,sha256=AJWCnuo7XKja4yBb8fK2wX7ntciLXQrpzdRHwjTRP6M,62
27
27
  fleet/_async/base.py,sha256=s0rYOtXsMJeitOvpa-Oh8ciLV226p_TIPp3fplzWvV4,9209
28
- fleet/_async/client.py,sha256=yyNawgGro2sfFh0ok7DtbjnyxaBGrHg9RtTFEISvwdE,10581
28
+ fleet/_async/client.py,sha256=jByARVSmtsOS9Qlukwij_exPzIQW5TBMtIGKnLqlF00,11924
29
29
  fleet/_async/exceptions.py,sha256=fUmPwWhnT8SR97lYsRq0kLHQHKtSh2eJS0VQ2caSzEI,5055
30
+ fleet/_async/models.py,sha256=gH3hpQM5awRqagSGPIsjOleB8AdFND8E4s9ZkZc5c_0,11372
30
31
  fleet/_async/tasks.py,sha256=w-0vVGfEuCWRHMEJ73SN141J7Lz2pD_0v-nNG4TyJTU,1645
31
32
  fleet/_async/env/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
33
  fleet/_async/env/client.py,sha256=PQGKcvnVTr3o2KNsgQM7ZBqaCjimv-wEn-XiYGm44Ko,753
33
34
  fleet/_async/instance/__init__.py,sha256=PtmJq8J8bh0SOQ2V55QURz5GJfobozwtQoqhaOk3_tI,515
34
35
  fleet/_async/instance/base.py,sha256=3qUBuUR8OVS36LzdP6KyZzngtwPKYO09HoY6Ekxp-KA,1625
35
- fleet/_async/instance/client.py,sha256=5fd_ABdlpmWIrDrOVnSs2XUUoXwcfvrV1LflLd7sqjw,5760
36
+ fleet/_async/instance/client.py,sha256=2ZNoBxRJXDQc8fohCLy_RNo-wmuUKXzJo5RZQeCQnkQ,6069
36
37
  fleet/_async/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
38
  fleet/_async/resources/base.py,sha256=ZFx2I9L7px-Z8LvbPUZJtbtajpqUn1yS1NFbZZutP9Q,668
38
39
  fleet/_async/resources/browser.py,sha256=oldoSiymJ1lJkADhpUG81ViOBDNyppX1jSoEwe9-W94,1369
39
- fleet/_async/resources/sqlite.py,sha256=d1wRLUIPIrKO6YaRaq3luPPQW_SjyRG1RJI67unu9jM,26633
40
+ fleet/_async/resources/sqlite.py,sha256=DvDLRI5dJ7_v4WkHw-Zday1M_FQUdzAqUCy9FtfOY8w,26636
40
41
  fleet/_async/verifiers/__init__.py,sha256=Z2Ic77mw6-mhF5CmVrucmDnAGSTAtiejR_eZjTjPPA0,447
41
42
  fleet/_async/verifiers/bundler.py,sha256=A4yR3wBOcVZYFAv87CD58QlJn6L4QXeilrasnVm8n74,26185
42
- fleet/_async/verifiers/verifier.py,sha256=ImrpduuEZFEvBeiKBxGN-cHXNLz6hWJGipVM90qfjdA,12242
43
+ fleet/_async/verifiers/verifier.py,sha256=fhy1bs_n0Ki2xDtisZI86McIZ09-v5WUFo5tZCBRsvA,12153
43
44
  fleet/env/__init__.py,sha256=yYk657kVDnMWYbuPS_2o0kpVC99AYD85o5WG1jCaWSY,531
44
- fleet/env/client.py,sha256=HwJ-xCg3oZMJ48nP9_EaHk4Rao-na9myPX9X5JxYMbo,644
45
+ fleet/env/client.py,sha256=pG5S1ylDN0pqUGQtRqayDSnYI7ZVpCFvTbtC4LuMRts,628
45
46
  fleet/instance/__init__.py,sha256=-Anms7Vw_FO8VBIvwnAnq4rQjwl_XNfAS-i7bypHMow,478
46
47
  fleet/instance/base.py,sha256=OYqzBwZFfTX9wlBGSG5gljqj98NbiJeKIfFJ3uj5I4s,1587
47
- fleet/instance/client.py,sha256=TgW2aGloF9qj_jloZQBKd62rRsrbBKPD7FmXXDdHBJU,5944
48
+ fleet/instance/client.py,sha256=4x-3IZZNwlK02OJLKp7mhSymRgXk8NToRCDU3ZuDnJ0,5891
48
49
  fleet/instance/models.py,sha256=ZTiue0YOuhuwX8jYfJAoCzGfqjLqqXRLqK1LVFhq6rQ,4183
49
50
  fleet/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
51
  fleet/resources/base.py,sha256=203gD54NP1IvjuSqFo-f7FvrkhtjChggtzrxJK7xf2E,667
51
- fleet/resources/browser.py,sha256=OEqfNYPAptANza0T8K7UEn6nI7JnzlCICFMW8r2r83Q,1367
52
+ fleet/resources/browser.py,sha256=hRNM0YMsVQUAraZGNi_B-KXxLpuddy4ntoEDFSw7czU,1295
52
53
  fleet/resources/mcp.py,sha256=lDMyY4pMC3Khwp2Wycc6Ds6KeLAUOgHkDnmztuAnXm8,1872
53
- fleet/resources/sqlite.py,sha256=oaDeH0fWw94HPJk4EC-FSb08zv-wwicYqm9iSwbHzig,46280
54
- fleet/verifiers/__init__.py,sha256=-dm2x0wC8UbfGcMCbPtjb0-LospGUhD-S3Pm4oha6BY,445
54
+ fleet/resources/sqlite.py,sha256=FeAykW7T0Pol7ckDLCtcjJDHDTI7y9ilWp7fnw4tuM8,26266
55
+ fleet/verifiers/__init__.py,sha256=9sRqYEjPN-EGMhytkw0Q68vay7azmpY9TvkBJQ3_8Os,489
55
56
  fleet/verifiers/bundler.py,sha256=A4yR3wBOcVZYFAv87CD58QlJn6L4QXeilrasnVm8n74,26185
56
57
  fleet/verifiers/code.py,sha256=EOi6ES8Zdzlm9iybRFaJmz9t2W4Ulo2wrCdbEBqxzbc,47
57
58
  fleet/verifiers/db.py,sha256=tssmvJjDHuBIy8qlL_P5-UdmEFUw2DZcqLsWZ8ot3Xw,27766
58
59
  fleet/verifiers/decorator.py,sha256=Q-KHhicnIYFwX7FX_VZguzNfu8ZslqNUeWxcS2CwNVY,3386
60
+ fleet/verifiers/parse.py,sha256=FYbzgX86dLAxoAZ3jXfu6zRPlNxgzjTkhO3yxMC0hZ4,5261
59
61
  fleet/verifiers/sql_differ.py,sha256=dmiGCFXVMEMbAX519OjhVqgA8ZvhnvdmC1BVpL7QCF0,6490
60
- fleet/verifiers/verifier.py,sha256=C5L24M7VBHWKaWlryC1EdW1g7keZBGzVSjgXC_SlpXA,12205
61
- fleet_python-0.2.20.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
62
+ fleet/verifiers/verifier.py,sha256=-iEnLi4BOpqMV8tJgSPcTi_mGWM3vMJiAYTmaJolo2c,12080
63
+ fleet_python-0.2.22.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
62
64
  scripts/fix_sync_imports.py,sha256=BIQfnaOoQ7bwR1c-pDqH9ifN47W1bwL7OafWVXZNkuA,4368
63
65
  scripts/unasync.py,sha256=--Fmaae47o-dZ1HYgX1c3Nvi-rMjcFymTRlJcWWnmpw,725
64
- fleet_python-0.2.20.dist-info/METADATA,sha256=wIh4xvnKfS40EBPWcJbl9206egZ0xZVTt3Zcq1fRKb8,3297
65
- fleet_python-0.2.20.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
66
- fleet_python-0.2.20.dist-info/top_level.txt,sha256=_3DSmTohvSDf3AIP_BYfGzhwO1ECFwuzg83X-wHCx3Y,23
67
- fleet_python-0.2.20.dist-info/RECORD,,
66
+ fleet_python-0.2.22.dist-info/METADATA,sha256=jktRiagpdxi-xyw-RiDk4csZI9FagVeJ1t3eTJQN9uU,3297
67
+ fleet_python-0.2.22.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
68
+ fleet_python-0.2.22.dist-info/top_level.txt,sha256=_3DSmTohvSDf3AIP_BYfGzhwO1ECFwuzg83X-wHCx3Y,23
69
+ fleet_python-0.2.22.dist-info/RECORD,,