veris-ai 1.2.0__py3-none-any.whl → 1.3.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 veris-ai might be problematic. Click here for more details.

veris_ai/__init__.py CHANGED
@@ -5,9 +5,9 @@ from typing import Any
5
5
  __version__ = "0.1.0"
6
6
 
7
7
  # Import lightweight modules that only use base dependencies
8
- from .tool_mock import veris
9
8
  from .jaeger_interface import JaegerClient
10
9
  from .models import ResponseExpectation
10
+ from .tool_mock import veris
11
11
 
12
12
  # Lazy import for modules with heavy dependencies
13
13
  _instrument = None
@@ -34,9 +34,4 @@ def instrument(*args: Any, **kwargs: Any) -> Any: # noqa: ANN401
34
34
  return _instrument(*args, **kwargs)
35
35
 
36
36
 
37
- __all__ = [
38
- "veris",
39
- "JaegerClient",
40
- "instrument",
41
- "ResponseExpectation"
42
- ]
37
+ __all__ = ["veris", "JaegerClient", "instrument", "ResponseExpectation"]
@@ -5,12 +5,12 @@ This implementation keeps dependencies minimal while providing fully-typed
5
5
  """
6
6
 
7
7
  import json
8
- from typing import Any, Dict, List, Optional, Self
8
+ import types
9
+ from typing import Any, Self
9
10
 
10
11
  import requests
11
12
 
12
- from .models import GetTraceResponse, SearchResponse, Span, Tag, Trace
13
-
13
+ from .models import GetTraceResponse, SearchResponse, Span, Trace
14
14
 
15
15
  __all__ = ["JaegerClient"]
16
16
 
@@ -60,30 +60,27 @@ class JaegerClient: # noqa: D101
60
60
  session.headers.update(self._headers)
61
61
  return session, True
62
62
 
63
- def _span_matches_tags(self, span: Span, span_tags: Dict[str, Any]) -> bool:
63
+ def _span_matches_tags(self, span: Span, span_tags: dict[str, Any]) -> bool:
64
64
  """Check if a span matches any of the provided tags (OR logic)."""
65
65
  if not span.tags or not span_tags:
66
66
  return False
67
-
67
+
68
68
  # Convert span tags to a dict for easier lookup
69
69
  span_tag_dict = {tag.key: tag.value for tag in span.tags}
70
-
70
+
71
71
  # OR logic: return True if ANY tag matches
72
- for key, value in span_tags.items():
73
- if span_tag_dict.get(key) == value:
74
- return True
75
-
76
- return False
72
+ return any(span_tag_dict.get(key) == value for key, value in span_tags.items())
77
73
 
78
74
  def _filter_spans(
79
75
  self,
80
- traces: List[Trace],
81
- span_tags: Optional[Dict[str, Any]],
82
- span_operations: Optional[List[str]] = None
83
- ) -> List[Trace]:
84
- """
85
- Filter spans within traces based on span_tags (OR logic) and/or span_operations (OR logic).
86
- If both are provided, a span must match at least one tag AND at least one operation.
76
+ traces: list[Trace],
77
+ span_tags: dict[str, Any] | None,
78
+ span_operations: list[str] | None = None,
79
+ ) -> list[Trace]:
80
+ """Filter spans within traces based on span_tags and/or span_operations.
81
+
82
+ Uses OR logic within each filter type. If both are provided, a span must
83
+ match at least one tag AND at least one operation.
87
84
  """
88
85
  if not span_tags and not span_operations:
89
86
  return traces
@@ -109,7 +106,7 @@ class JaegerClient: # noqa: D101
109
106
  traceID=trace.traceID,
110
107
  spans=filtered_spans,
111
108
  process=trace.process,
112
- warnings=trace.warnings
109
+ warnings=trace.warnings,
113
110
  )
114
111
  filtered_traces.append(filtered_trace)
115
112
 
@@ -119,16 +116,16 @@ class JaegerClient: # noqa: D101
119
116
  # Public API
120
117
  # ---------------------------------------------------------------------
121
118
 
122
- def search(
119
+ def search( # noqa: PLR0913
123
120
  self,
124
- service: Optional[str] = None,
121
+ service: str | None = None,
125
122
  *,
126
- limit: Optional[int] = None,
127
- tags: Optional[Dict[str, Any]] = None,
128
- operation: Optional[str] = None,
129
- span_tags: Optional[Dict[str, Any]] = None,
130
- span_operations: Optional[List[str]] = None,
131
- **kwargs: Any
123
+ limit: int | None = None,
124
+ tags: dict[str, Any] | None = None,
125
+ operation: str | None = None,
126
+ span_tags: dict[str, Any] | None = None,
127
+ span_operations: list[str] | None = None,
128
+ **kwargs: Any, # noqa: ANN401
132
129
  ) -> SearchResponse: # noqa: D401
133
130
  """Search traces using the *v1* ``/api/traces`` endpoint with optional span filtering.
134
131
 
@@ -137,9 +134,11 @@ class JaegerClient: # noqa: D101
137
134
  limit: Maximum number of traces to return.
138
135
  tags: Dictionary of tag filters for trace-level filtering (AND-combined).
139
136
  operation: Operation name to search for.
140
- span_tags: Dictionary of tag filters for span-level filtering (OR-combined AND-combined with span_operations).
137
+ span_tags: Dictionary of tag filters for span-level filtering.
138
+ Uses OR logic. Combined with span_operations using AND.
141
139
  Applied client-side after retrieving traces.
142
- span_operations: List of operation names to search for (OR-combined AND-combined with span_tags).
140
+ span_operations: List of operation names to search for.
141
+ Uses OR logic. Combined with span_tags using AND.
143
142
  **kwargs: Additional parameters to pass to the Jaeger API.
144
143
 
145
144
  Returns:
@@ -147,24 +146,24 @@ class JaegerClient: # noqa: D101
147
146
  with spans filtered according to span_tags if provided.
148
147
  """
149
148
  # Build params for the Jaeger API (excluding span_tags)
150
- params: Dict[str, Any] = {}
151
-
149
+ params: dict[str, Any] = {}
150
+
152
151
  if service is not None:
153
152
  params["service"] = service
154
-
153
+
155
154
  if limit is not None:
156
155
  params["limit"] = limit
157
-
156
+
158
157
  if operation is not None:
159
158
  params["operation"] = operation
160
-
159
+
161
160
  if tags:
162
161
  # Convert tags to JSON string as expected by Jaeger API
163
162
  params["tags"] = json.dumps(tags)
164
-
163
+
165
164
  # Add any additional parameters
166
165
  params.update(kwargs)
167
-
166
+
168
167
  session, should_close = self._make_session()
169
168
  try:
170
169
  url = f"{self._base_url}/api/traces"
@@ -174,18 +173,22 @@ class JaegerClient: # noqa: D101
174
173
  finally:
175
174
  if should_close:
176
175
  session.close()
177
-
176
+
178
177
  # Parse the response
179
178
  search_response = SearchResponse.model_validate(data) # type: ignore[arg-type]
180
-
179
+
181
180
  # Apply span-level filtering if span_tags is provided
182
- if span_tags or span_operations and search_response.data and isinstance(search_response.data, list):
181
+ if (
182
+ (span_tags or span_operations)
183
+ and search_response.data
184
+ and isinstance(search_response.data, list)
185
+ ):
183
186
  filtered_traces = self._filter_spans(search_response.data, span_tags, span_operations)
184
187
  search_response.data = filtered_traces
185
188
  # Update the total to reflect filtered results
186
189
  if search_response.total is not None:
187
190
  search_response.total = len(filtered_traces)
188
-
191
+
189
192
  return search_response
190
193
 
191
194
  def get_trace(self, trace_id: str) -> GetTraceResponse: # noqa: D401
@@ -225,7 +228,7 @@ class JaegerClient: # noqa: D101
225
228
  self,
226
229
  exc_type: type[BaseException] | None,
227
230
  exc: BaseException | None,
228
- tb: Any | None,
231
+ tb: types.TracebackType | None,
229
232
  ) -> None:
230
233
  """Exit the context manager."""
231
234
  # Only close if we created the session
@@ -1,9 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- import json
4
3
  from typing import Any
5
4
 
6
- from pydantic import BaseModel, Field, ConfigDict
5
+ from pydantic import BaseModel, ConfigDict, Field
7
6
 
8
7
  __all__ = [
9
8
  "Tag",
veris_ai/models.py CHANGED
@@ -5,7 +5,7 @@ from enum import Enum
5
5
 
6
6
  class ResponseExpectation(str, Enum):
7
7
  """Expected response behavior for tool mocking."""
8
-
8
+
9
9
  AUTO = "auto"
10
10
  REQUIRED = "required"
11
- NONE = "none"
11
+ NONE = "none"
veris_ai/tool_mock.py CHANGED
@@ -92,7 +92,7 @@ class VerisSDK:
92
92
  **params_dict,
93
93
  )
94
94
 
95
- def mock(
95
+ def mock( # noqa: C901, PLR0915
96
96
  self,
97
97
  mode: Literal["tool", "function"] = "tool",
98
98
  expects_response: bool | None = None,
@@ -100,15 +100,8 @@ class VerisSDK:
100
100
  ) -> Callable:
101
101
  """Decorator for mocking tool calls."""
102
102
 
103
- def decorator(func: Callable) -> Callable:
103
+ def decorator(func: Callable) -> Callable: # noqa: C901, PLR0915
104
104
  """Decorator for mocking tool calls."""
105
- endpoint = os.getenv("VERIS_MOCK_ENDPOINT_URL")
106
- if not endpoint:
107
- error_msg = "VERIS_MOCK_ENDPOINT_URL environment variable is not set"
108
- raise ValueError(error_msg)
109
- # Default timeout of 30 seconds
110
- timeout = float(os.getenv("VERIS_MOCK_TIMEOUT", "90.0"))
111
-
112
105
  # Check if the original function is async
113
106
  is_async = inspect.iscoroutinefunction(func)
114
107
 
@@ -148,7 +141,7 @@ class VerisSDK:
148
141
  response_expectation = ResponseExpectation.REQUIRED
149
142
  else:
150
143
  response_expectation = ResponseExpectation.AUTO
151
-
144
+
152
145
  payload = {
153
146
  "session_id": self.session_id,
154
147
  "response_expectation": response_expectation.value,
@@ -169,11 +162,16 @@ class VerisSDK:
169
162
  **kwargs: dict[str, object],
170
163
  ) -> object:
171
164
  # Check if we're in simulation mode
172
- env_mode = os.getenv("ENV", "").lower()
173
- if env_mode != "simulation":
165
+ if not self.session_id:
174
166
  # If not in simulation mode, execute the original function
175
167
  return await func(*args, **kwargs)
176
-
168
+ endpoint = os.getenv("VERIS_MOCK_ENDPOINT_URL")
169
+ if not endpoint:
170
+ error_msg = "VERIS_MOCK_ENDPOINT_URL environment variable is not set"
171
+ raise ValueError(error_msg)
172
+ # Default timeout of 30 seconds
173
+ timeout = float(os.getenv("VERIS_MOCK_TIMEOUT", "90.0"))
174
+
177
175
  logger.info(f"Simulating function: {func.__name__}")
178
176
  payload, return_type_obj = create_mock_payload(*args, **kwargs)
179
177
 
@@ -196,11 +194,16 @@ class VerisSDK:
196
194
  **kwargs: dict[str, object],
197
195
  ) -> object:
198
196
  # Check if we're in simulation mode
199
- env_mode = os.getenv("ENV", "").lower()
200
- if env_mode != "simulation":
197
+ if not self.session_id:
201
198
  # If not in simulation mode, execute the original function
202
199
  return func(*args, **kwargs)
203
-
200
+ endpoint = os.getenv("VERIS_MOCK_ENDPOINT_URL")
201
+ if not endpoint:
202
+ error_msg = "VERIS_MOCK_ENDPOINT_URL environment variable is not set"
203
+ raise ValueError(error_msg)
204
+ # Default timeout of 30 seconds
205
+ timeout = float(os.getenv("VERIS_MOCK_TIMEOUT", "90.0"))
206
+
204
207
  logger.info(f"Simulating function: {func.__name__}")
205
208
  payload, return_type_obj = create_mock_payload(*args, **kwargs)
206
209
 
@@ -228,23 +231,21 @@ class VerisSDK:
228
231
  def decorator(func: Callable) -> Callable:
229
232
  # Check if the original function is async
230
233
  is_async = inspect.iscoroutinefunction(func)
231
-
234
+
232
235
  @wraps(func)
233
236
  async def async_wrapper(
234
237
  *args: tuple[object, ...],
235
238
  **kwargs: dict[str, object],
236
239
  ) -> object:
237
- env_mode = os.getenv("ENV", "").lower()
238
- if env_mode != "simulation":
240
+ if not self.session_id:
239
241
  # If not in simulation mode, execute the original function
240
- return func(*args, **kwargs)
242
+ return await func(*args, **kwargs)
241
243
  logger.info(f"Simulating function: {func.__name__}")
242
244
  return return_value
243
-
245
+
244
246
  @wraps(func)
245
247
  def sync_wrapper(*args: tuple[object, ...], **kwargs: dict[str, object]) -> object:
246
- env_mode = os.getenv("ENV", "").lower()
247
- if env_mode != "simulation":
248
+ if not self.session_id:
248
249
  # If not in simulation mode, execute the original function
249
250
  return func(*args, **kwargs)
250
251
  logger.info(f"Simulating function: {func.__name__}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: veris-ai
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: A Python package for Veris AI tools
5
5
  Project-URL: Homepage, https://github.com/veris-ai/veris-python-sdk
6
6
  Project-URL: Bug Tracker, https://github.com/veris-ai/veris-python-sdk/issues
@@ -0,0 +1,13 @@
1
+ veris_ai/__init__.py,sha256=Vp5yf9ZRchw0mmPwrRuNebI5cb2NGwpJGfr41l86q1U,1177
2
+ veris_ai/braintrust_tracing.py,sha256=0i-HR6IuK3-Q5ujMjT1FojxESRZLgqEvJ44bfJfDHaw,11938
3
+ veris_ai/models.py,sha256=6HINPxNFCakCVPcyEbUswWkXwb2K4lF0A8g8EvTMal4,213
4
+ veris_ai/tool_mock.py,sha256=U4xjINEZbtjutb_Vtr_So1ENNrU9kDROSyNUU5RL1Jc,10610
5
+ veris_ai/utils.py,sha256=3R2J9ko5t1UATiF1R6Hox9IPbtUz59EHsMDFg1-i7sk,9208
6
+ veris_ai/jaeger_interface/README.md,sha256=te5z3MWLqd2ECVV-a0MImBwTKRgQuuSuDB3bwIIsHi0,4437
7
+ veris_ai/jaeger_interface/__init__.py,sha256=d873a0zq3eUYU2Y77MtdjCwIARjAsAP7WDqGXDMWpYs,1158
8
+ veris_ai/jaeger_interface/client.py,sha256=yJrh86wRR0Dk3Gq12DId99WogcMIVbL0QQFqVSevvlE,8772
9
+ veris_ai/jaeger_interface/models.py,sha256=e64VV6IvOEFuzRUgvDAMQFyOZMRb56I-PUPZLBZ3rX0,1864
10
+ veris_ai-1.3.0.dist-info/METADATA,sha256=FD5DuzpYTZKjDmsPOb897HIMdOzS4l1UNTKh_68d29Y,13832
11
+ veris_ai-1.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
+ veris_ai-1.3.0.dist-info/licenses/LICENSE,sha256=2g4i20atAgtD5einaKzhQrIB-JrPhyQgD3bC0wkHcCI,1065
13
+ veris_ai-1.3.0.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- veris_ai/__init__.py,sha256=FkpF1jAEX9y5mZjICuxv0-uc_pTgWuCzK5D5fEQ-b8s,1195
2
- veris_ai/braintrust_tracing.py,sha256=0i-HR6IuK3-Q5ujMjT1FojxESRZLgqEvJ44bfJfDHaw,11938
3
- veris_ai/models.py,sha256=wj1avahszKrErFbWVar9xvFrp_pVkQUCaJUc_gFzu3k,216
4
- veris_ai/tool_mock.py,sha256=UO-6tYvfreLXfOxHFKFl-GJ1nI7bLoz93uuv_yBehWc,10507
5
- veris_ai/utils.py,sha256=3R2J9ko5t1UATiF1R6Hox9IPbtUz59EHsMDFg1-i7sk,9208
6
- veris_ai/jaeger_interface/README.md,sha256=te5z3MWLqd2ECVV-a0MImBwTKRgQuuSuDB3bwIIsHi0,4437
7
- veris_ai/jaeger_interface/__init__.py,sha256=d873a0zq3eUYU2Y77MtdjCwIARjAsAP7WDqGXDMWpYs,1158
8
- veris_ai/jaeger_interface/client.py,sha256=AU9qP_pzutwantcLiKaml5JW_AHrXHH7X-ALYVkbNZc,8777
9
- veris_ai/jaeger_interface/models.py,sha256=ZYL2vlJbObAiAowsashuAuT6tUV9HaEmGKuxLPi_ye8,1876
10
- veris_ai-1.2.0.dist-info/METADATA,sha256=ZmgJqKZUnL2G0ANQxX6SiYX2UK3HqeG7FjGgCttAQPM,13832
11
- veris_ai-1.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
- veris_ai-1.2.0.dist-info/licenses/LICENSE,sha256=2g4i20atAgtD5einaKzhQrIB-JrPhyQgD3bC0wkHcCI,1065
13
- veris_ai-1.2.0.dist-info/RECORD,,