fleet-python 0.2.66b2__tar.gz → 0.2.66b4__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.

Potentially problematic release.


This version of fleet-python might be problematic. Click here for more details.

Files changed (87) hide show
  1. {fleet_python-0.2.66b2/fleet_python.egg-info → fleet_python-0.2.66b4}/PKG-INFO +1 -1
  2. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/tasks.py +6 -9
  3. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/tasks.py +6 -9
  4. fleet_python-0.2.66b4/fleet/verifiers/parsing.py +106 -0
  5. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4/fleet_python.egg-info}/PKG-INFO +1 -1
  6. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet_python.egg-info/SOURCES.txt +1 -0
  7. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/pyproject.toml +1 -1
  8. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/LICENSE +0 -0
  9. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/README.md +0 -0
  10. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/diff_example.py +0 -0
  11. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/dsl_example.py +0 -0
  12. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/example.py +0 -0
  13. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/exampleResume.py +0 -0
  14. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/example_account.py +0 -0
  15. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/example_action_log.py +0 -0
  16. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/example_client.py +0 -0
  17. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/example_mcp_anthropic.py +0 -0
  18. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/example_mcp_openai.py +0 -0
  19. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/example_sync.py +0 -0
  20. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/example_task.py +0 -0
  21. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/example_tasks.py +0 -0
  22. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/example_verifier.py +0 -0
  23. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/export_tasks.py +0 -0
  24. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/gemini_example.py +0 -0
  25. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/import_tasks.py +0 -0
  26. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/json_tasks_example.py +0 -0
  27. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/nova_act_example.py +0 -0
  28. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/openai_example.py +0 -0
  29. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/openai_simple_example.py +0 -0
  30. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/query_builder_example.py +0 -0
  31. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/quickstart.py +0 -0
  32. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/examples/test_cdp_logging.py +0 -0
  33. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/__init__.py +0 -0
  34. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/__init__.py +0 -0
  35. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/base.py +0 -0
  36. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/client.py +0 -0
  37. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/env/__init__.py +0 -0
  38. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/env/client.py +0 -0
  39. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/exceptions.py +0 -0
  40. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/global_client.py +0 -0
  41. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/instance/__init__.py +0 -0
  42. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/instance/base.py +0 -0
  43. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/instance/client.py +0 -0
  44. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/models.py +0 -0
  45. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/resources/__init__.py +0 -0
  46. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/resources/base.py +0 -0
  47. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/resources/browser.py +0 -0
  48. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/resources/mcp.py +0 -0
  49. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/resources/sqlite.py +0 -0
  50. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/verifiers/__init__.py +0 -0
  51. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/verifiers/bundler.py +0 -0
  52. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/_async/verifiers/verifier.py +0 -0
  53. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/base.py +0 -0
  54. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/client.py +0 -0
  55. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/config.py +0 -0
  56. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/env/__init__.py +0 -0
  57. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/env/client.py +0 -0
  58. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/exceptions.py +0 -0
  59. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/global_client.py +0 -0
  60. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/instance/__init__.py +0 -0
  61. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/instance/base.py +0 -0
  62. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/instance/client.py +0 -0
  63. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/instance/models.py +0 -0
  64. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/models.py +0 -0
  65. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/resources/__init__.py +0 -0
  66. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/resources/base.py +0 -0
  67. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/resources/browser.py +0 -0
  68. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/resources/mcp.py +0 -0
  69. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/resources/sqlite.py +0 -0
  70. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/types.py +0 -0
  71. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/verifiers/__init__.py +0 -0
  72. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/verifiers/bundler.py +0 -0
  73. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/verifiers/code.py +0 -0
  74. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/verifiers/db.py +0 -0
  75. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/verifiers/decorator.py +0 -0
  76. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/verifiers/parse.py +0 -0
  77. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/verifiers/sql_differ.py +0 -0
  78. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet/verifiers/verifier.py +0 -0
  79. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet_python.egg-info/dependency_links.txt +0 -0
  80. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet_python.egg-info/requires.txt +0 -0
  81. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/fleet_python.egg-info/top_level.txt +0 -0
  82. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/scripts/fix_sync_imports.py +0 -0
  83. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/scripts/unasync.py +0 -0
  84. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/setup.cfg +0 -0
  85. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/tests/__init__.py +0 -0
  86. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/tests/test_verifier_from_string.py +0 -0
  87. {fleet_python-0.2.66b2 → fleet_python-0.2.66b4}/tests/test_verifier_security.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleet-python
3
- Version: 0.2.66b2
3
+ Version: 0.2.66b4
4
4
  Summary: Python SDK for Fleet environments
5
5
  Author-email: Fleet AI <nic@fleet.so>
6
6
  License: Apache-2.0
@@ -300,17 +300,14 @@ def verifier_from_string(
300
300
  # This is now safe because we validated it contains only declarative code
301
301
  exec(verifier_func, globals(), local_namespace)
302
302
 
303
- # Find the function that was defined (not imported)
304
- # Functions defined via exec have co_filename == '<string>'
305
- # Imported functions have their actual module file path
306
- func_obj = None
307
- for name, obj in local_namespace.items():
308
- if inspect.isfunction(obj) and obj.__code__.co_filename == "<string>":
309
- func_obj = obj
310
- break
303
+ # Get the function by the parsed function name
304
+ func_obj = local_namespace.get(func_name)
311
305
 
312
306
  if func_obj is None:
313
- raise ValueError("No function found in verifier code")
307
+ raise ValueError(f"Function '{func_name}' not found in verifier code")
308
+
309
+ if not inspect.isfunction(func_obj):
310
+ raise ValueError(f"'{func_name}' is not a function")
314
311
 
315
312
  # Create an AsyncVerifierFunction instance with raw code
316
313
  verifier_instance = AsyncVerifierFunction(
@@ -299,17 +299,14 @@ def verifier_from_string(
299
299
  # This is now safe because we validated it contains only declarative code
300
300
  exec(verifier_func, exec_globals, local_namespace)
301
301
 
302
- # Find the function that was defined (not imported)
303
- # Functions defined via exec have co_filename == '<string>'
304
- # Imported functions have their actual module file path
305
- func_obj = None
306
- for name, obj in local_namespace.items():
307
- if inspect.isfunction(obj) and obj.__code__.co_filename == "<string>":
308
- func_obj = obj
309
- break
302
+ # Get the function by the parsed function name
303
+ func_obj = local_namespace.get(func_name)
310
304
 
311
305
  if func_obj is None:
312
- raise ValueError("No function found in verifier code")
306
+ raise ValueError(f"Function '{func_name}' not found in verifier code")
307
+
308
+ if not inspect.isfunction(func_obj):
309
+ raise ValueError(f"'{func_name}' is not a function")
313
310
 
314
311
  # Create an SyncVerifierFunction instance with raw code
315
312
  verifier_instance = SyncVerifierFunction(
@@ -0,0 +1,106 @@
1
+ """Verifier code parsing and validation utilities."""
2
+
3
+ import ast
4
+ from typing import Set
5
+
6
+
7
+ def parse_and_validate_verifier(code: str) -> str:
8
+ """Parse and validate verifier code, returning the first function name.
9
+
10
+ This function ensures that the verifier code only contains safe declarative
11
+ statements and does not execute arbitrary code during import.
12
+
13
+ Args:
14
+ code: Python code string containing the verifier function
15
+
16
+ Returns:
17
+ Name of the first function found in the code
18
+
19
+ Raises:
20
+ ValueError: If code is invalid or contains unsafe statements
21
+ SyntaxError: If code has syntax errors
22
+ """
23
+ try:
24
+ tree = ast.parse(code)
25
+ except SyntaxError as e:
26
+ raise SyntaxError(f"Syntax error in verifier code: {e}")
27
+
28
+ first_function_name = None
29
+
30
+ for node in tree.body:
31
+ # Check for function definitions
32
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
33
+ # Validate that decorators don't contain function calls
34
+ for decorator in node.decorator_list:
35
+ if _contains_call(decorator):
36
+ raise ValueError(
37
+ f"Line {node.lineno}: Function decorators with function calls "
38
+ f"are not allowed. Decorators execute during import and could "
39
+ f"run arbitrary code."
40
+ )
41
+
42
+ if first_function_name is None:
43
+ first_function_name = node.name
44
+ continue
45
+
46
+ # Allow imports
47
+ if isinstance(node, (ast.Import, ast.ImportFrom)):
48
+ continue
49
+
50
+ # Allow class definitions
51
+ if isinstance(node, ast.ClassDef):
52
+ continue
53
+
54
+ # Allow docstrings and other expression statements (but not calls)
55
+ if isinstance(node, ast.Expr):
56
+ if isinstance(node.value, ast.Constant):
57
+ # Docstring or constant expression - safe
58
+ continue
59
+ else:
60
+ # Check if it's a call or other dangerous expression
61
+ raise ValueError(
62
+ f"Line {node.lineno}: Expression statements that are not "
63
+ f"constants are not allowed at module level. Found: {ast.dump(node.value)}"
64
+ )
65
+
66
+ # Allow variable assignments, but check the value
67
+ if isinstance(node, (ast.Assign, ast.AnnAssign)):
68
+ # Check if the assignment value contains any function calls
69
+ if _contains_call(node.value if isinstance(node, ast.AnnAssign) else node.value):
70
+ raise ValueError(
71
+ f"Line {node.lineno}: Variable assignments with function calls "
72
+ f"are not allowed at module level. This prevents arbitrary code "
73
+ f"execution during import."
74
+ )
75
+ continue
76
+
77
+ # If we get here, it's an unsupported statement type
78
+ raise ValueError(
79
+ f"Line {node.lineno}: Unsupported statement type at module level: "
80
+ f"{node.__class__.__name__}. Only imports, function/class definitions, "
81
+ f"and constant assignments are allowed."
82
+ )
83
+
84
+ if first_function_name is None:
85
+ raise ValueError("No function found in verifier code")
86
+
87
+ return first_function_name
88
+
89
+
90
+ def _contains_call(node: ast.AST) -> bool:
91
+ """Recursively check if an AST node contains any Call nodes.
92
+
93
+ Args:
94
+ node: AST node to check
95
+
96
+ Returns:
97
+ True if the node or any of its children is a Call node
98
+ """
99
+ if isinstance(node, ast.Call):
100
+ return True
101
+
102
+ for child in ast.walk(node):
103
+ if isinstance(child, ast.Call):
104
+ return True
105
+
106
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleet-python
3
- Version: 0.2.66b2
3
+ Version: 0.2.66b4
4
4
  Summary: Python SDK for Fleet environments
5
5
  Author-email: Fleet AI <nic@fleet.so>
6
6
  License: Apache-2.0
@@ -70,6 +70,7 @@ fleet/verifiers/code.py
70
70
  fleet/verifiers/db.py
71
71
  fleet/verifiers/decorator.py
72
72
  fleet/verifiers/parse.py
73
+ fleet/verifiers/parsing.py
73
74
  fleet/verifiers/sql_differ.py
74
75
  fleet/verifiers/verifier.py
75
76
  fleet_python.egg-info/PKG-INFO
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fleet-python"
7
- version = "0.2.66b2"
7
+ version = "0.2.66b4"
8
8
  description = "Python SDK for Fleet environments"
9
9
  authors = [
10
10
  {name = "Fleet AI", email = "nic@fleet.so"},
File without changes