payi 0.1.0a51__py3-none-any.whl → 0.1.0a53__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 payi might be problematic. Click here for more details.

payi/_base_client.py CHANGED
@@ -63,7 +63,7 @@ from ._types import (
63
63
  ModelBuilderProtocol,
64
64
  )
65
65
  from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping
66
- from ._compat import model_copy, model_dump
66
+ from ._compat import PYDANTIC_V2, model_copy, model_dump
67
67
  from ._models import GenericModel, FinalRequestOptions, validate_type, construct_type
68
68
  from ._response import (
69
69
  APIResponse,
@@ -207,6 +207,9 @@ class BaseSyncPage(BasePage[_T], Generic[_T]):
207
207
  model: Type[_T],
208
208
  options: FinalRequestOptions,
209
209
  ) -> None:
210
+ if PYDANTIC_V2 and getattr(self, "__pydantic_private__", None) is None:
211
+ self.__pydantic_private__ = {}
212
+
210
213
  self._model = model
211
214
  self._client = client
212
215
  self._options = options
@@ -292,6 +295,9 @@ class BaseAsyncPage(BasePage[_T], Generic[_T]):
292
295
  client: AsyncAPIClient,
293
296
  options: FinalRequestOptions,
294
297
  ) -> None:
298
+ if PYDANTIC_V2 and getattr(self, "__pydantic_private__", None) is None:
299
+ self.__pydantic_private__ = {}
300
+
295
301
  self._model = model
296
302
  self._client = client
297
303
  self._options = options
@@ -518,7 +524,7 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
518
524
  # so that passing a `TypedDict` doesn't cause an error.
519
525
  # https://github.com/microsoft/pyright/issues/3526#event-6715453066
520
526
  params=self.qs.stringify(cast(Mapping[str, Any], params)) if params else None,
521
- json=json_data,
527
+ json=json_data if is_given(json_data) else None,
522
528
  files=files,
523
529
  **kwargs,
524
530
  )
payi/_client.py CHANGED
@@ -77,7 +77,7 @@ class Payi(SyncAPIClient):
77
77
  # part of our public interface in the future.
78
78
  _strict_response_validation: bool = False,
79
79
  ) -> None:
80
- """Construct a new synchronous payi client instance.
80
+ """Construct a new synchronous Payi client instance.
81
81
 
82
82
  This automatically infers the `api_key` argument from the `PAYI_API_KEY` environment variable if it is not provided.
83
83
  """
@@ -257,7 +257,7 @@ class AsyncPayi(AsyncAPIClient):
257
257
  # part of our public interface in the future.
258
258
  _strict_response_validation: bool = False,
259
259
  ) -> None:
260
- """Construct a new async payi client instance.
260
+ """Construct a new async AsyncPayi client instance.
261
261
 
262
262
  This automatically infers the `api_key` argument from the `PAYI_API_KEY` environment variable if it is not provided.
263
263
  """
payi/_version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "payi"
4
- __version__ = "0.1.0-alpha.51" # x-release-please-version
4
+ __version__ = "0.1.0-alpha.53" # x-release-please-version
payi/lib/helpers.py CHANGED
@@ -1,4 +1,3 @@
1
- from enum import Enum
2
1
  from typing import Dict, List, Union
3
2
 
4
3
  PAYI_BASE_URL = "https://api.pay-i.com"
@@ -11,12 +10,13 @@ class PayiHeaderNames:
11
10
  user_id:str = "xProxy-User-ID"
12
11
  route_as_resource:str = "xProxy-RouteAs-Resource"
13
12
  provider_base_uri = "xProxy-Provider-BaseUri"
13
+ resource_scope:str = "xProxy-Resource-Scope"
14
14
 
15
- class PayiCategories(Enum):
16
- anthropic = "system.anthropic"
17
- openai = "system.openai"
18
- azure_openai = "system.azureopenai"
19
- aws_bedrock = "system.aws.bedrock"
15
+ class PayiCategories:
16
+ anthropic:str = "system.anthropic"
17
+ openai:str = "system.openai"
18
+ azure_openai:str = "system.azureopenai"
19
+ aws_bedrock:str = "system.aws.bedrock"
20
20
 
21
21
  def create_limit_header_from_ids(limit_ids: List[str]) -> Dict[str, str]:
22
22
  if not isinstance(limit_ids, list): # type: ignore
payi/lib/instrument.py CHANGED
@@ -41,7 +41,7 @@ class PayiInstrumentor:
41
41
  self,
42
42
  payi: Optional[Payi],
43
43
  apayi: Optional[AsyncPayi],
44
- instruments: Union[Set[PayiCategories], None] = None,
44
+ instruments: Union[Set[str], None] = None,
45
45
  log_prompt_and_response: bool = True,
46
46
  prompt_and_response_logger: Optional[
47
47
  Callable[[str, "dict[str, str]"], None]
@@ -56,7 +56,7 @@ class PayiInstrumentor:
56
56
  self._blocked_limits: set[str] = set()
57
57
  self._exceeded_limits: set[str] = set()
58
58
 
59
- if instruments is None:
59
+ if instruments is None or "*" in instruments:
60
60
  self._instrument_all()
61
61
  else:
62
62
  self._instrument_specific(instruments)
@@ -66,7 +66,7 @@ class PayiInstrumentor:
66
66
  self._instrument_anthropic()
67
67
  self._instrument_aws_bedrock()
68
68
 
69
- def _instrument_specific(self, instruments: Set[PayiCategories]) -> None:
69
+ def _instrument_specific(self, instruments: Set[str]) -> None:
70
70
  if PayiCategories.openai in instruments or PayiCategories.azure_openai in instruments:
71
71
  self._instrument_openai()
72
72
  if PayiCategories.anthropic in instruments:
@@ -375,14 +375,18 @@ class PayiInstrumentor:
375
375
  if len(ingest_extra_headers) > 0:
376
376
  ingest["provider_request_headers"] = [PayICommonModelsAPIRouterHeaderInfoParam(name=k, value=v) for k, v in ingest_extra_headers.items()]
377
377
 
378
- provider_prompt = {}
378
+ provider_prompt: "dict[str, Any]" = {}
379
379
  for k, v in kwargs.items():
380
380
  if k == "messages":
381
381
  provider_prompt[k] = [m.model_dump() if hasattr(m, "model_dump") else m for m in v]
382
382
  elif k in ["extra_headers", "extra_query"]:
383
383
  pass
384
384
  else:
385
- provider_prompt[k] = v
385
+ try:
386
+ json.dumps(v)
387
+ provider_prompt[k] = v
388
+ except (TypeError, ValueError):
389
+ pass
386
390
 
387
391
  if self._log_prompt_and_response:
388
392
  ingest["provider_request_json"] = json.dumps(provider_prompt)
@@ -420,18 +424,28 @@ class PayiInstrumentor:
420
424
  ingest: IngestUnitsParams = {"category": category, "units": {}} # type: ignore
421
425
  ingest["resource"] = kwargs.get("model", "")
422
426
 
423
- if category == "system.openai" and instance and hasattr(instance, "_client"):
427
+ if category == PayiCategories.openai and instance and hasattr(instance, "_client"):
424
428
  from .OpenAIInstrumentor import OpenAiInstrumentor # noqa: I001
425
429
 
426
430
  if OpenAiInstrumentor.is_azure(instance):
427
- resource = extra_headers.pop(PayiHeaderNames.route_as_resource, None)
428
- if not resource:
431
+ route_as_resource = extra_headers.pop(PayiHeaderNames.route_as_resource, None)
432
+ resource_scope = extra_headers.pop(PayiHeaderNames.resource_scope, None)
433
+
434
+ if not route_as_resource:
429
435
  logging.error("Azure OpenAI route as resource not found, not ingesting")
430
436
  return await wrapped(*args, **kwargs)
431
437
 
432
- category = "system.azureopenai"
438
+ if resource_scope:
439
+ if not(resource_scope in ["global", "datazone"] or resource_scope.startswith("region")):
440
+ logging.error("Azure OpenAI invalid resource scope, not ingesting")
441
+ return wrapped(*args, **kwargs)
442
+
443
+ ingest["resource_scope"] = resource_scope
444
+
445
+ category = PayiCategories.azure_openai
446
+
433
447
  ingest["category"] = category
434
- ingest["resource"] = resource
448
+ ingest["resource"] = route_as_resource
435
449
 
436
450
  current_frame = inspect.currentframe()
437
451
  # f_back excludes the current frame, strip() cleans up whitespace and newlines
@@ -511,7 +525,7 @@ class PayiInstrumentor:
511
525
  ) -> Any:
512
526
  context = self.get_context()
513
527
 
514
- is_bedrock:bool = category == "system.aws.bedrock"
528
+ is_bedrock:bool = category == PayiCategories.aws_bedrock
515
529
 
516
530
  if not context:
517
531
  if is_bedrock:
@@ -539,17 +553,28 @@ class PayiInstrumentor:
539
553
  else:
540
554
  ingest["resource"] = kwargs.get("model", "")
541
555
 
542
- if category == "system.openai" and instance and hasattr(instance, "_client"):
543
- from .OpenAIInstrumentor import OpenAiInstrumentor
556
+ if category == PayiCategories.openai and instance and hasattr(instance, "_client"):
557
+ from .OpenAIInstrumentor import OpenAiInstrumentor # noqa: I001
558
+
544
559
  if OpenAiInstrumentor.is_azure(instance):
545
- resource = extra_headers.pop(PayiHeaderNames.route_as_resource, None)
546
- if not resource:
560
+ route_as_resource:str = extra_headers.pop(PayiHeaderNames.route_as_resource, None)
561
+ resource_scope:str = extra_headers.pop(PayiHeaderNames.resource_scope, None)
562
+
563
+ if not route_as_resource:
547
564
  logging.error("Azure OpenAI route as resource not found, not ingesting")
548
565
  return wrapped(*args, **kwargs)
549
566
 
550
- category = "system.azureopenai"
567
+ if resource_scope:
568
+ if not(resource_scope in ["global", "datazone"] or resource_scope.startswith("region")):
569
+ logging.error("Azure OpenAI invalid resource scope, not ingesting")
570
+ return wrapped(*args, **kwargs)
571
+
572
+ ingest["resource_scope"] = resource_scope
573
+
574
+ category = PayiCategories.azure_openai
575
+
551
576
  ingest["category"] = category
552
- ingest["resource"] = resource
577
+ ingest["resource"] = route_as_resource
553
578
 
554
579
  current_frame = inspect.currentframe()
555
580
  # f_back excludes the current frame, strip() cleans up whitespace and newlines
@@ -864,7 +889,7 @@ _instrumentor: Optional[PayiInstrumentor] = None
864
889
 
865
890
  def payi_instrument(
866
891
  payi: Optional[Union[Payi, AsyncPayi, 'list[Union[Payi, AsyncPayi]]']] = None,
867
- instruments: Optional[Set[PayiCategories]] = None,
892
+ instruments: Optional[Set[str]] = None,
868
893
  log_prompt_and_response: bool = True,
869
894
  prompt_and_response_logger: Optional[Callable[[str, "dict[str, str]"], None]] = None,
870
895
  ) -> None:
payi/resources/ingest.py CHANGED
@@ -54,7 +54,7 @@ class IngestResource(SyncAPIResource):
54
54
  def bulk(
55
55
  self,
56
56
  *,
57
- events: Iterable[IngestEventParam],
57
+ events: Iterable[IngestEventParam] | NotGiven = NOT_GIVEN,
58
58
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
59
59
  # The extra values given here take precedence over values defined on the client or passed to this method.
60
60
  extra_headers: Headers | None = None,
@@ -242,7 +242,7 @@ class AsyncIngestResource(AsyncAPIResource):
242
242
  async def bulk(
243
243
  self,
244
244
  *,
245
- events: Iterable[IngestEventParam],
245
+ events: Iterable[IngestEventParam] | NotGiven = NOT_GIVEN,
246
246
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
247
247
  # The extra values given here take precedence over values defined on the client or passed to this method.
248
248
  extra_headers: Headers | None = None,
@@ -3,7 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from typing import Iterable
6
- from typing_extensions import Required, TypedDict
6
+ from typing_extensions import TypedDict
7
7
 
8
8
  from .ingest_event_param import IngestEventParam
9
9
 
@@ -11,4 +11,4 @@ __all__ = ["IngestBulkParams"]
11
11
 
12
12
 
13
13
  class IngestBulkParams(TypedDict, total=False):
14
- events: Required[Iterable[IngestEventParam]]
14
+ events: Iterable[IngestEventParam]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: payi
3
- Version: 0.1.0a51
3
+ Version: 0.1.0a53
4
4
  Summary: The official Python library for the payi API
5
5
  Project-URL: Homepage, https://github.com/Pay-i/pay-i-python
6
6
  Project-URL: Repository, https://github.com/Pay-i/pay-i-python
@@ -41,7 +41,7 @@ The Payi Python library provides convenient access to the Payi REST API from any
41
41
  application. The library includes type definitions for all request params and response fields,
42
42
  and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).
43
43
 
44
- It is generated with [Stainless](https://www.stainlessapi.com/).
44
+ It is generated with [Stainless](https://www.stainless.com/).
45
45
 
46
46
  ## Documentation
47
47
 
@@ -1,6 +1,6 @@
1
1
  payi/__init__.py,sha256=_eeZx9fx2Wp81adXh7qrpkmXCso7TiRSvIlLkQ0sQhY,2399
2
- payi/_base_client.py,sha256=NT8ScfXiqpVkHrcGbynpNlv0q20HeHeF-oxKwmXggWM,68525
3
- payi/_client.py,sha256=aUtMEmV02nTs3_pYYAR-OchCkofUHeXhhRs43tyDHLE,18760
2
+ payi/_base_client.py,sha256=ZOICzg2o9gt3MtXKHglWDFZ9aIehFRDoppVLLNleHxM,68819
3
+ payi/_client.py,sha256=nYlt5NMJwXhptCNSf_VTDGIcMCJuMQG132qzaEt89UM,18765
4
4
  payi/_compat.py,sha256=VWemUKbj6DDkQ-O4baSpHVLJafotzeXmCQGJugfVTIw,6580
5
5
  payi/_constants.py,sha256=S14PFzyN9-I31wiV7SmIlL5Ga0MLHxdvegInGdXH7tM,462
6
6
  payi/_exceptions.py,sha256=ItygKNrNXIVY0H6LsGVZvFuAHB3Vtm_VZXmWzCnpHy0,3216
@@ -11,7 +11,7 @@ payi/_resource.py,sha256=j2jIkTr8OIC8sU6-05nxSaCyj4MaFlbZrwlyg4_xJos,1088
11
11
  payi/_response.py,sha256=CfrNS_3wbL8o9dRyRVfZQ5E1GUlA4CUIUEK8olmfGqE,28777
12
12
  payi/_streaming.py,sha256=Z_wIyo206T6Jqh2rolFg2VXZgX24PahLmpURp0-NssU,10092
13
13
  payi/_types.py,sha256=2mbMK86K3W1aMTW7sOGQ-VND6-A2IuXKm8p4sYFztBU,6141
14
- payi/_version.py,sha256=2jjziS33NunQR_UCbEBJktWH8e7UFNDVKxDIbHSAi68,165
14
+ payi/_version.py,sha256=22wp7HhRLV8Mw-V1KjRV37acd4dGVzd4CFl1iogfznA,165
15
15
  payi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  payi/_utils/__init__.py,sha256=PNZ_QJuzZEgyYXqkO1HVhGkj5IU9bglVUcw7H-Knjzw,2062
17
17
  payi/_utils/_logs.py,sha256=fmnf5D9TOgkgZKfgYmSa3PiUc3SZgkchn6CzJUeo0SQ,768
@@ -27,11 +27,11 @@ payi/lib/AnthropicInstrumentor.py,sha256=h-yebG7r7cSRVM_utva55Gc4BVcoW6WGrQrDg55
27
27
  payi/lib/BedrockInstrumentor.py,sha256=4WSZLzLHMv-5U1OFr0ZErESNHTyPHn0kHATUw4HTDkQ,10072
28
28
  payi/lib/OpenAIInstrumentor.py,sha256=ZUu-Byhz7AXhvxjOMdX8tB2JOpM5sCj0KnyRB49lQg0,6881
29
29
  payi/lib/Stopwatch.py,sha256=7OJlxvr2Jyb6Zr1LYCYKczRB7rDVKkIR7gc4YoleNdE,764
30
- payi/lib/helpers.py,sha256=fcT6gAHUP77YaLmgw9HWdIyTDJPI72weUsUVDGW0CbE,2929
31
- payi/lib/instrument.py,sha256=oJdF1ocd-wbQgNF9MIZWAaGDInzbu4TRy9946GVRuvI,36302
30
+ payi/lib/helpers.py,sha256=ghW4v_ZmCfy4ImGJr1PFTPfzHYwCCtdtyq9UqKwxpGc,2967
31
+ payi/lib/instrument.py,sha256=Fk-Vh9NEhfp6UNaTAkkEgL5Kiq7nFPDwUT-EuzCMF5Y,37443
32
32
  payi/resources/__init__.py,sha256=isHGXSl9kOrZDduKrX3UenTwrdTpuKJVBjw6NYSBV20,3592
33
33
  payi/resources/billing_models.py,sha256=5w3RfGXtGlyq5vbTw6hQrx1UlzRBtlq8ArcFlf5e3TY,20152
34
- payi/resources/ingest.py,sha256=RFfN1hwUngFgHJNcMaqZ1C6Xw1Qdve81dtUgjJSOb_A,19159
34
+ payi/resources/ingest.py,sha256=GQtgomlSTaMzPqWq8r51JkxkQMrqWhePl_llKG1XsVs,19205
35
35
  payi/resources/price_modifiers.py,sha256=t-k2F_zf2FhoxiqDHAPBPvhSgTjewlJqh50y58FNMuw,13475
36
36
  payi/resources/categories/__init__.py,sha256=w5gMiPdBSzJA_qfoVtFBElaoe8wGf_O63R7R1Spr6Gk,1093
37
37
  payi/resources/categories/categories.py,sha256=FohmajDcadMXzhG3Z1HKGkbSImO7rhzQ0olZXHz8z48,16074
@@ -65,7 +65,7 @@ payi/types/cost_data.py,sha256=1i842P25SBy2sB3OWGj9LO_mMKtzmyUPBrqY_mSw01o,488
65
65
  payi/types/cost_details.py,sha256=w9p79opEG3kcsjkRRP7niaMcUswdfB4Y7HCkVTcQ1zQ,307
66
66
  payi/types/default_response.py,sha256=o617LpRsCIZHCZxAc5nVI2JQ3HPGZo4gCDvSDkxkIJ8,270
67
67
  payi/types/experience_instance_response.py,sha256=N07MH6hjs1ISHLVpR2FG-u4awsZ_GGi97UNMXAWV1yA,296
68
- payi/types/ingest_bulk_params.py,sha256=d76YwiXaNeltLS3w86ZxLzTKGa7ymGLJDSelaMQGf8Y,382
68
+ payi/types/ingest_bulk_params.py,sha256=A-IRb39d2tmVzEQqrvhlF_3si-9ufHBKYLlvdXupAHU,362
69
69
  payi/types/ingest_event_param.py,sha256=1-pr5wMiWXAGDqBmQHKdpHJy0Fk9vOQl7XTGLtcjtdI,1507
70
70
  payi/types/ingest_response.py,sha256=KZfsgUhC942QkkjDFMqjJwCRoO2vkXv-Sx3X_xjijfg,1449
71
71
  payi/types/ingest_units_params.py,sha256=QrfkSW-tFDKpn8cPbbyAOhM17W1prC-aJeXMFeGiqJI,1884
@@ -112,7 +112,7 @@ payi/types/requests/request_result.py,sha256=phYQiqhwNaR9igP-Fhs34Y-__dlT7L4wq-r
112
112
  payi/types/shared/__init__.py,sha256=-xz5dxK5LBjLnsi2LpLq5btaGDFp-mSjJ0y2qKy0Yus,264
113
113
  payi/types/shared/evaluation_response.py,sha256=ejEToMA57PUu1SldEtJ5z9r4fAO3U0tvdjbsyIoVX1s,214
114
114
  payi/types/shared/pay_i_common_models_budget_management_cost_details_base.py,sha256=XmIzJXy4zAi-mfrDvEXiYjO3qF1EvugGUl-Gijj4TA4,268
115
- payi-0.1.0a51.dist-info/METADATA,sha256=jiW2Y5pjt4_e9bMHsMGGvAczDQZrf5i-1aC4CuRRE3A,12660
116
- payi-0.1.0a51.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
117
- payi-0.1.0a51.dist-info/licenses/LICENSE,sha256=CQt03aM-P4a3Yg5qBg3JSLVoQS3smMyvx7tYg_6V7Gk,11334
118
- payi-0.1.0a51.dist-info/RECORD,,
115
+ payi-0.1.0a53.dist-info/METADATA,sha256=gY78Cxm41k39GvnmpNTrz2CGS8f8a-o5u-WTzC8eD9g,12657
116
+ payi-0.1.0a53.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
117
+ payi-0.1.0a53.dist-info/licenses/LICENSE,sha256=CQt03aM-P4a3Yg5qBg3JSLVoQS3smMyvx7tYg_6V7Gk,11334
118
+ payi-0.1.0a53.dist-info/RECORD,,