paid-python 0.5.0__py3-none-any.whl → 1.0.0a0__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.
Files changed (54) hide show
  1. paid/__init__.py +33 -0
  2. paid/client.py +1 -472
  3. paid/core/client_wrapper.py +3 -2
  4. paid/customers/__init__.py +3 -0
  5. paid/customers/client.py +428 -4
  6. paid/customers/raw_client.py +594 -2
  7. paid/customers/types/__init__.py +8 -0
  8. paid/customers/types/customers_check_entitlement_request_view.py +5 -0
  9. paid/customers/types/customers_check_entitlement_response.py +22 -0
  10. paid/orders/client.py +445 -0
  11. paid/orders/raw_client.py +705 -0
  12. paid/plans/client.py +142 -0
  13. paid/plans/raw_client.py +238 -0
  14. paid/types/__init__.py +30 -0
  15. paid/types/cancel_renewal_response.py +49 -0
  16. paid/types/contact_create_for_customer.py +37 -0
  17. paid/types/invoice.py +75 -0
  18. paid/types/invoice_status.py +5 -0
  19. paid/types/payment_method.py +58 -0
  20. paid/types/payment_method_card.py +49 -0
  21. paid/types/payment_method_type.py +5 -0
  22. paid/types/payment_method_us_bank_account.py +36 -0
  23. paid/types/payment_method_us_bank_account_account_type.py +5 -0
  24. paid/types/plan_group.py +60 -0
  25. paid/types/plan_plan_products_item.py +6 -0
  26. paid/types/plan_with_features.py +69 -0
  27. paid/types/plan_with_features_features_item.py +34 -0
  28. paid/types/proration_attribute_update.py +44 -0
  29. paid/types/proration_detail.py +49 -0
  30. paid/types/proration_upgrade_response.py +73 -0
  31. paid/types/signal_v_2.py +5 -5
  32. paid/usage/client.py +6 -6
  33. {paid_python-0.5.0.dist-info → paid_python-1.0.0a0.dist-info}/METADATA +6 -4
  34. {paid_python-0.5.0.dist-info → paid_python-1.0.0a0.dist-info}/RECORD +36 -36
  35. opentelemetry/instrumentation/openai/__init__.py +0 -54
  36. opentelemetry/instrumentation/openai/shared/__init__.py +0 -399
  37. opentelemetry/instrumentation/openai/shared/audio_wrappers.py +0 -247
  38. opentelemetry/instrumentation/openai/shared/chat_wrappers.py +0 -1192
  39. opentelemetry/instrumentation/openai/shared/completion_wrappers.py +0 -292
  40. opentelemetry/instrumentation/openai/shared/config.py +0 -15
  41. opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py +0 -311
  42. opentelemetry/instrumentation/openai/shared/event_emitter.py +0 -108
  43. opentelemetry/instrumentation/openai/shared/event_models.py +0 -41
  44. opentelemetry/instrumentation/openai/shared/image_gen_wrappers.py +0 -68
  45. opentelemetry/instrumentation/openai/shared/span_utils.py +0 -0
  46. opentelemetry/instrumentation/openai/utils.py +0 -213
  47. opentelemetry/instrumentation/openai/v0/__init__.py +0 -176
  48. opentelemetry/instrumentation/openai/v1/__init__.py +0 -394
  49. opentelemetry/instrumentation/openai/v1/assistant_wrappers.py +0 -329
  50. opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py +0 -134
  51. opentelemetry/instrumentation/openai/v1/responses_wrappers.py +0 -1113
  52. opentelemetry/instrumentation/openai/version.py +0 -1
  53. {paid_python-0.5.0.dist-info → paid_python-1.0.0a0.dist-info}/LICENSE +0 -0
  54. {paid_python-0.5.0.dist-info → paid_python-1.0.0a0.dist-info}/WHEEL +0 -0
@@ -1,247 +0,0 @@
1
- import logging
2
- import time
3
-
4
- from opentelemetry import context as context_api
5
- from opentelemetry.instrumentation.openai.shared import (
6
- _set_client_attributes,
7
- _set_request_attributes,
8
- _set_response_attributes,
9
- _set_span_attribute,
10
- metric_shared_attributes,
11
- model_as_dict,
12
- )
13
- from opentelemetry.instrumentation.openai.utils import (
14
- _with_audio_telemetry_wrapper,
15
- dont_throw,
16
- is_openai_v1,
17
- start_as_current_span_async,
18
- )
19
- from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY
20
- from opentelemetry.metrics import Counter, Histogram
21
- from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE
22
- from opentelemetry.semconv_ai import (
23
- SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY,
24
- SpanAttributes,
25
- )
26
- from opentelemetry.trace import SpanKind, Status, StatusCode
27
-
28
- SPAN_NAME = "openai.audio.transcriptions"
29
-
30
- logger = logging.getLogger(__name__)
31
-
32
-
33
- def _get_audio_duration(file):
34
- """
35
- Extract audio duration from file object.
36
- Returns duration in seconds, or None if unable to determine.
37
- """
38
- try:
39
- # Try to get duration from common audio libraries
40
- # First check if it's a file-like object with a name attribute
41
- if hasattr(file, "name"):
42
- file_path = file.name
43
- elif isinstance(file, (str, bytes)):
44
- # If it's a path string or bytes
45
- return None
46
- else:
47
- # If it's a file-like object without name, we can't easily determine duration
48
- return None
49
-
50
- # Try mutagen (supports many formats)
51
- try:
52
- from mutagen import File as MutagenFile
53
-
54
- audio = MutagenFile(file_path)
55
- if audio and hasattr(audio.info, "length"):
56
- return audio.info.length
57
- except (ImportError, Exception):
58
- pass
59
-
60
- except Exception as e:
61
- logger.debug(f"Unable to extract audio duration: {e}")
62
-
63
- return None
64
-
65
-
66
- @_with_audio_telemetry_wrapper
67
- def transcription_wrapper(
68
- tracer,
69
- duration_histogram: Histogram,
70
- exception_counter: Counter,
71
- wrapped,
72
- instance,
73
- args,
74
- kwargs,
75
- ):
76
- if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY) or context_api.get_value(
77
- SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY
78
- ):
79
- return wrapped(*args, **kwargs)
80
-
81
- with tracer.start_as_current_span(
82
- name=SPAN_NAME,
83
- kind=SpanKind.CLIENT,
84
- ) as span:
85
- _handle_request(span, kwargs, instance)
86
-
87
- try:
88
- # record time for duration
89
- start_time = time.time()
90
- response = wrapped(*args, **kwargs)
91
- end_time = time.time()
92
- except Exception as e: # pylint: disable=broad-except
93
- end_time = time.time()
94
- duration = end_time - start_time if "start_time" in locals() else 0
95
- attributes = {
96
- "error.type": e.__class__.__name__,
97
- }
98
-
99
- # if there are legal duration, record it
100
- if duration > 0 and duration_histogram:
101
- duration_histogram.record(duration, attributes=attributes)
102
- if exception_counter:
103
- exception_counter.add(1, attributes=attributes)
104
-
105
- span.set_attribute(ERROR_TYPE, e.__class__.__name__)
106
- span.record_exception(e)
107
- span.set_status(Status(StatusCode.ERROR, str(e)))
108
- span.end()
109
-
110
- raise
111
-
112
- duration = end_time - start_time
113
-
114
- _handle_response(
115
- response,
116
- span,
117
- instance,
118
- duration_histogram,
119
- duration,
120
- )
121
-
122
- return response
123
-
124
-
125
- @_with_audio_telemetry_wrapper
126
- async def atranscription_wrapper(
127
- tracer,
128
- duration_histogram: Histogram,
129
- exception_counter: Counter,
130
- wrapped,
131
- instance,
132
- args,
133
- kwargs,
134
- ):
135
- if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY) or context_api.get_value(
136
- SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY
137
- ):
138
- return await wrapped(*args, **kwargs)
139
-
140
- async with start_as_current_span_async(
141
- tracer=tracer,
142
- name=SPAN_NAME,
143
- kind=SpanKind.CLIENT,
144
- ) as span:
145
- _handle_request(span, kwargs, instance)
146
-
147
- try:
148
- # record time for duration
149
- start_time = time.time()
150
- response = await wrapped(*args, **kwargs)
151
- end_time = time.time()
152
- except Exception as e: # pylint: disable=broad-except
153
- end_time = time.time()
154
- duration = end_time - start_time if "start_time" in locals() else 0
155
- attributes = {
156
- "error.type": e.__class__.__name__,
157
- }
158
-
159
- # if there are legal duration, record it
160
- if duration > 0 and duration_histogram:
161
- duration_histogram.record(duration, attributes=attributes)
162
- if exception_counter:
163
- exception_counter.add(1, attributes=attributes)
164
-
165
- span.set_attribute(ERROR_TYPE, e.__class__.__name__)
166
- span.record_exception(e)
167
- span.set_status(Status(StatusCode.ERROR, str(e)))
168
- span.end()
169
-
170
- raise
171
-
172
- duration = end_time - start_time
173
-
174
- _handle_response(
175
- response,
176
- span,
177
- instance,
178
- duration_histogram,
179
- duration,
180
- )
181
-
182
- return response
183
-
184
-
185
- @dont_throw
186
- def _handle_request(span, kwargs, instance):
187
- _set_request_attributes(span, kwargs, instance)
188
- _set_client_attributes(span, instance)
189
-
190
- # Extract and set audio duration
191
- file_param = kwargs.get("file")
192
- if file_param:
193
- audio_duration = _get_audio_duration(file_param)
194
- if audio_duration is not None:
195
- # _set_span_attribute(
196
- # span, SpanAttributes.LLM_OPENAI_AUDIO_INPUT_DURATION_SECONDS, audio_duration
197
- # )
198
- # TODO(Ata): come back here later when semconv is published
199
- _set_span_attribute(
200
- span, 'gen_ai.openai.audio.input.duration_seconds', audio_duration
201
- )
202
- else:
203
- print("REMOVE ME : ATA-DBG : COULD NOT READ AUDIO FILE WITH MUTAGEN")
204
-
205
-
206
- @dont_throw
207
- def _handle_response(
208
- response,
209
- span,
210
- instance=None,
211
- duration_histogram=None,
212
- duration=None,
213
- ):
214
- if is_openai_v1():
215
- response_dict = model_as_dict(response)
216
- else:
217
- response_dict = response
218
-
219
- # metrics record
220
- _set_transcription_metrics(
221
- instance,
222
- duration_histogram,
223
- response_dict,
224
- duration,
225
- )
226
-
227
- # span attributes
228
- _set_response_attributes(span, response_dict)
229
-
230
-
231
- def _set_transcription_metrics(
232
- instance,
233
- duration_histogram,
234
- response_dict,
235
- duration,
236
- ):
237
- from opentelemetry.instrumentation.openai.shared import _get_openai_base_url
238
-
239
- shared_attributes = metric_shared_attributes(
240
- response_model=response_dict.get("model") or None,
241
- operation="audio.transcriptions",
242
- server_address=_get_openai_base_url(instance),
243
- )
244
-
245
- # duration metrics
246
- if duration and isinstance(duration, (float, int)) and duration_histogram:
247
- duration_histogram.record(duration, attributes=shared_attributes)