fleet-python 0.2.69b2__tar.gz → 0.2.69b3__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 (89) hide show
  1. {fleet_python-0.2.69b2/fleet_python.egg-info → fleet_python-0.2.69b3}/PKG-INFO +1 -1
  2. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/client.py +20 -9
  3. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3/fleet_python.egg-info}/PKG-INFO +1 -1
  4. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet_python.egg-info/SOURCES.txt +1 -0
  5. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/pyproject.toml +1 -1
  6. fleet_python-0.2.69b3/tests/test_app_method.py +85 -0
  7. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/LICENSE +0 -0
  8. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/README.md +0 -0
  9. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/diff_example.py +0 -0
  10. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/dsl_example.py +0 -0
  11. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/example.py +0 -0
  12. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/exampleResume.py +0 -0
  13. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/example_account.py +0 -0
  14. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/example_action_log.py +0 -0
  15. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/example_client.py +0 -0
  16. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/example_mcp_anthropic.py +0 -0
  17. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/example_mcp_openai.py +0 -0
  18. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/example_sync.py +0 -0
  19. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/example_task.py +0 -0
  20. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/example_tasks.py +0 -0
  21. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/example_verifier.py +0 -0
  22. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/export_tasks.py +0 -0
  23. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/gemini_example.py +0 -0
  24. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/import_tasks.py +0 -0
  25. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/json_tasks_example.py +0 -0
  26. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/nova_act_example.py +0 -0
  27. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/openai_example.py +0 -0
  28. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/openai_simple_example.py +0 -0
  29. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/query_builder_example.py +0 -0
  30. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/quickstart.py +0 -0
  31. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/examples/test_cdp_logging.py +0 -0
  32. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/__init__.py +0 -0
  33. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/__init__.py +0 -0
  34. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/base.py +0 -0
  35. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/client.py +0 -0
  36. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/env/__init__.py +0 -0
  37. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/env/client.py +0 -0
  38. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/exceptions.py +0 -0
  39. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/global_client.py +0 -0
  40. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/instance/__init__.py +0 -0
  41. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/instance/base.py +0 -0
  42. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/instance/client.py +0 -0
  43. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/models.py +0 -0
  44. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/resources/__init__.py +0 -0
  45. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/resources/base.py +0 -0
  46. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/resources/browser.py +0 -0
  47. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/resources/mcp.py +0 -0
  48. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/resources/sqlite.py +0 -0
  49. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/tasks.py +0 -0
  50. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/verifiers/__init__.py +0 -0
  51. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/verifiers/bundler.py +0 -0
  52. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/_async/verifiers/verifier.py +0 -0
  53. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/base.py +0 -0
  54. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/config.py +0 -0
  55. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/env/__init__.py +0 -0
  56. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/env/client.py +0 -0
  57. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/exceptions.py +0 -0
  58. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/global_client.py +0 -0
  59. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/instance/__init__.py +0 -0
  60. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/instance/base.py +0 -0
  61. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/instance/client.py +0 -0
  62. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/instance/models.py +0 -0
  63. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/models.py +0 -0
  64. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/resources/__init__.py +0 -0
  65. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/resources/base.py +0 -0
  66. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/resources/browser.py +0 -0
  67. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/resources/mcp.py +0 -0
  68. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/resources/sqlite.py +0 -0
  69. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/tasks.py +0 -0
  70. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/types.py +0 -0
  71. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/verifiers/__init__.py +0 -0
  72. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/verifiers/bundler.py +0 -0
  73. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/verifiers/code.py +0 -0
  74. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/verifiers/db.py +0 -0
  75. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/verifiers/decorator.py +0 -0
  76. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/verifiers/parse.py +0 -0
  77. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/verifiers/sql_differ.py +0 -0
  78. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet/verifiers/verifier.py +0 -0
  79. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet_python.egg-info/dependency_links.txt +0 -0
  80. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet_python.egg-info/requires.txt +0 -0
  81. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/fleet_python.egg-info/top_level.txt +0 -0
  82. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/scripts/fix_sync_imports.py +0 -0
  83. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/scripts/unasync.py +0 -0
  84. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/setup.cfg +0 -0
  85. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/tests/__init__.py +0 -0
  86. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/tests/test_instance_dispatch.py +0 -0
  87. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/tests/test_sqlite_resource_dual_mode.py +0 -0
  88. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/tests/test_sqlite_shared_memory_behavior.py +0 -0
  89. {fleet_python-0.2.69b2 → fleet_python-0.2.69b3}/tests/test_verifier_from_string.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleet-python
3
- Version: 0.2.69b2
3
+ Version: 0.2.69b3
4
4
  Summary: Python SDK for Fleet environments
5
5
  Author-email: Fleet AI <nic@fleet.so>
6
6
  License: Apache-2.0
@@ -22,6 +22,7 @@ import json
22
22
  import logging
23
23
  import os
24
24
  from typing import List, Optional, Dict, Any, TYPE_CHECKING, Union
25
+ from urllib.parse import urlparse
25
26
 
26
27
  from .base import EnvironmentBase, SyncWrapper
27
28
  from .models import (
@@ -74,6 +75,14 @@ class SyncEnv(EnvironmentBase):
74
75
  self._client = client
75
76
  self._apps: Dict[str, InstanceClient] = {}
76
77
  self._instance: Optional[InstanceClient] = None
78
+ self._manager_url_override: Optional[str] = None # For URL mode
79
+
80
+ @property
81
+ def manager_url(self) -> str:
82
+ """Override to support URL mode where urls is None."""
83
+ if self._manager_url_override is not None:
84
+ return self._manager_url_override
85
+ return super().manager_url
77
86
 
78
87
  @property
79
88
  def instance(self) -> InstanceClient:
@@ -85,17 +94,17 @@ class SyncEnv(EnvironmentBase):
85
94
 
86
95
  def app(self, name: str) -> InstanceClient:
87
96
  if name not in self._apps:
88
- # Extract base URL by removing the current app path (e.g., /sentry/api/v1/env)
89
- # manager_url looks like: https://xxx.fleetai.com/sentry/api/v1/env
90
- base_url = self.manager_url.split("/api/v1/env")[0]
91
- # Remove the current app name (e.g., /sentry) to get the root
92
- if "/" in base_url:
93
- parts = base_url.rsplit("/", 1)
94
- if len(parts) == 2 and parts[0] != "https:/":
95
- base_url = parts[0]
97
+ # Extract scheme://netloc from manager_url, then construct /{name}/api/v1/env
98
+ # Supports all URL formats:
99
+ # https://host/api/v1/env -> https://host/{name}/api/v1/env
100
+ # https://host/sentry/api/v1/env -> https://host/{name}/api/v1/env
101
+ # http://localhost:8080/api/v1/env -> http://localhost:8080/{name}/api/v1/env
102
+ parsed = urlparse(self.manager_url)
103
+ root = f"{parsed.scheme}://{parsed.netloc}"
104
+ new_url = f"{root}/{name}/api/v1/env"
96
105
 
97
106
  self._apps[name] = InstanceClient(
98
- f"{base_url}/{name}/api/v1/env",
107
+ new_url,
99
108
  self._client.httpx_client if self._client else None,
100
109
  )
101
110
  return self._apps[name]
@@ -353,6 +362,7 @@ class Fleet:
353
362
  health=None,
354
363
  )
355
364
  env._instance = instance_client
365
+ env._manager_url_override = base_url # Set manager_url for URL mode
356
366
  return env
357
367
 
358
368
  @staticmethod
@@ -448,6 +458,7 @@ class Fleet:
448
458
  health=None,
449
459
  )
450
460
  env._instance = instance_client
461
+ env._manager_url_override = "local://" # Set manager_url for local mode
451
462
  return env
452
463
 
453
464
  def check_bundle_exists(self, bundle_hash: str) -> VerifiersCheckResponse:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleet-python
3
- Version: 0.2.69b2
3
+ Version: 0.2.69b3
4
4
  Summary: Python SDK for Fleet environments
5
5
  Author-email: Fleet AI <nic@fleet.so>
6
6
  License: Apache-2.0
@@ -80,6 +80,7 @@ fleet_python.egg-info/top_level.txt
80
80
  scripts/fix_sync_imports.py
81
81
  scripts/unasync.py
82
82
  tests/__init__.py
83
+ tests/test_app_method.py
83
84
  tests/test_instance_dispatch.py
84
85
  tests/test_sqlite_resource_dual_mode.py
85
86
  tests/test_sqlite_shared_memory_behavior.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fleet-python"
7
- version = "0.2.69b2"
7
+ version = "0.2.69b3"
8
8
  description = "Python SDK for Fleet environments"
9
9
  authors = [
10
10
  {name = "Fleet AI", email = "nic@fleet.so"},
@@ -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"])
File without changes