mseep-agentops 0.4.18__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 (94) hide show
  1. agentops/__init__.py +488 -0
  2. agentops/client/__init__.py +5 -0
  3. agentops/client/api/__init__.py +71 -0
  4. agentops/client/api/base.py +162 -0
  5. agentops/client/api/types.py +21 -0
  6. agentops/client/api/versions/__init__.py +10 -0
  7. agentops/client/api/versions/v3.py +65 -0
  8. agentops/client/api/versions/v4.py +104 -0
  9. agentops/client/client.py +211 -0
  10. agentops/client/http/__init__.py +0 -0
  11. agentops/client/http/http_adapter.py +116 -0
  12. agentops/client/http/http_client.py +215 -0
  13. agentops/config.py +268 -0
  14. agentops/enums.py +36 -0
  15. agentops/exceptions.py +38 -0
  16. agentops/helpers/__init__.py +44 -0
  17. agentops/helpers/dashboard.py +54 -0
  18. agentops/helpers/deprecation.py +50 -0
  19. agentops/helpers/env.py +52 -0
  20. agentops/helpers/serialization.py +137 -0
  21. agentops/helpers/system.py +178 -0
  22. agentops/helpers/time.py +11 -0
  23. agentops/helpers/version.py +36 -0
  24. agentops/instrumentation/__init__.py +598 -0
  25. agentops/instrumentation/common/__init__.py +82 -0
  26. agentops/instrumentation/common/attributes.py +278 -0
  27. agentops/instrumentation/common/instrumentor.py +147 -0
  28. agentops/instrumentation/common/metrics.py +100 -0
  29. agentops/instrumentation/common/objects.py +26 -0
  30. agentops/instrumentation/common/span_management.py +176 -0
  31. agentops/instrumentation/common/streaming.py +218 -0
  32. agentops/instrumentation/common/token_counting.py +177 -0
  33. agentops/instrumentation/common/version.py +71 -0
  34. agentops/instrumentation/common/wrappers.py +235 -0
  35. agentops/legacy/__init__.py +277 -0
  36. agentops/legacy/event.py +156 -0
  37. agentops/logging/__init__.py +4 -0
  38. agentops/logging/config.py +86 -0
  39. agentops/logging/formatters.py +34 -0
  40. agentops/logging/instrument_logging.py +91 -0
  41. agentops/sdk/__init__.py +27 -0
  42. agentops/sdk/attributes.py +151 -0
  43. agentops/sdk/core.py +607 -0
  44. agentops/sdk/decorators/__init__.py +51 -0
  45. agentops/sdk/decorators/factory.py +486 -0
  46. agentops/sdk/decorators/utility.py +216 -0
  47. agentops/sdk/exporters.py +87 -0
  48. agentops/sdk/processors.py +71 -0
  49. agentops/sdk/types.py +21 -0
  50. agentops/semconv/__init__.py +36 -0
  51. agentops/semconv/agent.py +29 -0
  52. agentops/semconv/core.py +19 -0
  53. agentops/semconv/enum.py +11 -0
  54. agentops/semconv/instrumentation.py +13 -0
  55. agentops/semconv/langchain.py +63 -0
  56. agentops/semconv/message.py +61 -0
  57. agentops/semconv/meters.py +24 -0
  58. agentops/semconv/resource.py +52 -0
  59. agentops/semconv/span_attributes.py +118 -0
  60. agentops/semconv/span_kinds.py +50 -0
  61. agentops/semconv/status.py +11 -0
  62. agentops/semconv/tool.py +15 -0
  63. agentops/semconv/workflow.py +69 -0
  64. agentops/validation.py +357 -0
  65. mseep_agentops-0.4.18.dist-info/METADATA +49 -0
  66. mseep_agentops-0.4.18.dist-info/RECORD +94 -0
  67. mseep_agentops-0.4.18.dist-info/WHEEL +5 -0
  68. mseep_agentops-0.4.18.dist-info/licenses/LICENSE +21 -0
  69. mseep_agentops-0.4.18.dist-info/top_level.txt +2 -0
  70. tests/__init__.py +0 -0
  71. tests/conftest.py +10 -0
  72. tests/unit/__init__.py +0 -0
  73. tests/unit/client/__init__.py +1 -0
  74. tests/unit/client/test_http_adapter.py +221 -0
  75. tests/unit/client/test_http_client.py +206 -0
  76. tests/unit/conftest.py +54 -0
  77. tests/unit/sdk/__init__.py +1 -0
  78. tests/unit/sdk/instrumentation_tester.py +207 -0
  79. tests/unit/sdk/test_attributes.py +392 -0
  80. tests/unit/sdk/test_concurrent_instrumentation.py +468 -0
  81. tests/unit/sdk/test_decorators.py +763 -0
  82. tests/unit/sdk/test_exporters.py +241 -0
  83. tests/unit/sdk/test_factory.py +1188 -0
  84. tests/unit/sdk/test_internal_span_processor.py +397 -0
  85. tests/unit/sdk/test_resource_attributes.py +35 -0
  86. tests/unit/test_config.py +82 -0
  87. tests/unit/test_context_manager.py +777 -0
  88. tests/unit/test_events.py +27 -0
  89. tests/unit/test_host_env.py +54 -0
  90. tests/unit/test_init_py.py +501 -0
  91. tests/unit/test_serialization.py +433 -0
  92. tests/unit/test_session.py +676 -0
  93. tests/unit/test_user_agent.py +34 -0
  94. tests/unit/test_validation.py +405 -0
@@ -0,0 +1,49 @@
1
+ Metadata-Version: 2.4
2
+ Name: mseep-agentops
3
+ Version: 0.4.18
4
+ Summary: Observability and DevTool Platform for AI Agents
5
+ Home-page: https://github.com/mseep
6
+ Author: mseep
7
+ Author-email: support@skydeck.ai
8
+ Maintainer: mseep
9
+ Maintainer-email: support@skydeck.ai
10
+ Keywords: mseep
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Requires-Python: >=3.6
15
+ Description-Content-Type: text/plain
16
+ License-File: LICENSE
17
+ Requires-Dist: requests<3.0.0,>=2.0.0
18
+ Requires-Dist: psutil<7.0.1,>=5.9.8
19
+ Requires-Dist: termcolor<2.5.0,>=2.3.0
20
+ Requires-Dist: PyYAML<7.0,>=5.3
21
+ Requires-Dist: packaging<25.0,>=21.0
22
+ Requires-Dist: httpx<0.29.0,>=0.24.0
23
+ Requires-Dist: opentelemetry-sdk==1.29.0; python_version < "3.10"
24
+ Requires-Dist: opentelemetry-sdk>1.29.0; python_version >= "3.10"
25
+ Requires-Dist: opentelemetry-api==1.29.0; python_version < "3.10"
26
+ Requires-Dist: opentelemetry-api>1.29.0; python_version >= "3.10"
27
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.29.0; python_version < "3.10"
28
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http>1.29.0; python_version >= "3.10"
29
+ Requires-Dist: ordered-set<5.0.0,>=4.0.0
30
+ Requires-Dist: wrapt<2.0.0,>=1.0.0
31
+ Requires-Dist: opentelemetry-instrumentation==0.50b0; python_version < "3.10"
32
+ Requires-Dist: opentelemetry-instrumentation>=0.50b0; python_version >= "3.10"
33
+ Requires-Dist: opentelemetry-semantic-conventions==0.50b0; python_version < "3.10"
34
+ Requires-Dist: opentelemetry-semantic-conventions>=0.50b0; python_version >= "3.10"
35
+ Dynamic: author
36
+ Dynamic: author-email
37
+ Dynamic: classifier
38
+ Dynamic: description
39
+ Dynamic: description-content-type
40
+ Dynamic: home-page
41
+ Dynamic: keywords
42
+ Dynamic: license-file
43
+ Dynamic: maintainer
44
+ Dynamic: maintainer-email
45
+ Dynamic: requires-dist
46
+ Dynamic: requires-python
47
+ Dynamic: summary
48
+
49
+ Package managed by MseeP.ai
@@ -0,0 +1,94 @@
1
+ agentops/__init__.py,sha256=YvY0zsWTEpAhAZOrcb2T2dDs2PxJv-q8rUPuqgdpY0k,18788
2
+ agentops/config.py,sha256=7eu3crglngSeKK0fQ_pFsHGiOjr1gPCaqual8VP0hCA,10090
3
+ agentops/enums.py,sha256=mRvxU_EFzcfXAmlc0vEj2RBe8An0FnIF-3jZdw3ZMa0,980
4
+ agentops/exceptions.py,sha256=HjHLvB20ZadA4ZGsmMlQxh-SVhPYQLFzKv0Q_1Ujbx8,1177
5
+ agentops/validation.py,sha256=Dsxsoa7RbRagcXK56fCWWqgQ5OyUdbM2KjIQjHUp5XA,13294
6
+ agentops/client/__init__.py,sha256=9ot9lZs-zqk50W3zT87Bgql9Cb77mvCaXNpl2x3IhPs,120
7
+ agentops/client/client.py,sha256=jaqzPYSi2Jyyd0Nxjzo97aerN9gsGTIqG4Gjgam0vXQ,10667
8
+ agentops/client/api/__init__.py,sha256=LJJfrjVmm7weWrIRkc28WcV0iogSxU6XR49rOGv7wfI,1906
9
+ agentops/client/api/base.py,sha256=-SkPZyfR1W0KsCpn05u2F0cMfyc5OXEuRkE859DL66g,4439
10
+ agentops/client/api/types.py,sha256=GOhpOPnZF1QCYJ-_qZudbHayD8l6hebJDImZFJGYElk,407
11
+ agentops/client/api/versions/__init__.py,sha256=nyZyYD0dY2I8B7opmIxExlBQnH26lVGWgVXc1zDwi3I,254
12
+ agentops/client/api/versions/v3.py,sha256=MvClQ6_G2DiXCUNIFv36d_wNidKtIQsAt-rRv8Yng0M,2067
13
+ agentops/client/api/versions/v4.py,sha256=PsexNJ5h_AwJXbaKn-6ftoW480ZkHMM3u7ow0vocRfg,3532
14
+ agentops/client/http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ agentops/client/http/http_adapter.py,sha256=M4LHvj8LFFptHSy-60LHLi_oTBWl1D7Y4_Bsq5W0P4U,4351
16
+ agentops/client/http/http_client.py,sha256=O9fggGMgqs5eyKF9jEUAgSoBlbPHvxk0lWQTiOQpuxw,8661
17
+ agentops/helpers/__init__.py,sha256=0YVuyl6CVYUiL5mpkPbsADj_Z_4rgSE8XzCK4OuE0p0,1075
18
+ agentops/helpers/dashboard.py,sha256=T80flB8GlB4ubPj61mB-seAuDTj4lYTa_U-WDstDg4Q,1552
19
+ agentops/helpers/deprecation.py,sha256=Ndv0FVa52OznNUu_lAOrF698IrIFL-EF_alrRqXtDpw,1573
20
+ agentops/helpers/env.py,sha256=cENhgB4QBSG-aZuENI15wUajskT4xLbSZ4NSQj5_tF0,1215
21
+ agentops/helpers/serialization.py,sha256=1XSCfkZGl51R1FQ4NXYu9ceYuDa4Almp0n7ECgHKI5o,3896
22
+ agentops/helpers/system.py,sha256=4DEnWHMu6ulgIAzSt6bzNFa_O7nzwcCp8Me5zVWD3bg,4872
23
+ agentops/helpers/time.py,sha256=XyCknaPCgDBI-FM-n-2lfKJwXUsMPvHzWlK8hc5RPaU,301
24
+ agentops/helpers/version.py,sha256=3kErXu8dtC27L_3BVG1RFbfO4OKtHMgusHxLz-5s5uI,1056
25
+ agentops/instrumentation/__init__.py,sha256=084qkc1Kggo4PPVc5q2GpUbYk-2RoX5O0nLsd7EoN20,25486
26
+ agentops/instrumentation/common/__init__.py,sha256=CYgIOTPUbxpLh47kjeLwLxhLZVA0lpZM9uzJCkr_c40,2287
27
+ agentops/instrumentation/common/attributes.py,sha256=WelUjg80CQKKNENAipz2t9vuSIUNuQ6Rdz_poxovRck,9337
28
+ agentops/instrumentation/common/instrumentor.py,sha256=qOaukvOjXRWN0ltw0eupsVZkWfMoESX0oFK-U1IK5JY,4926
29
+ agentops/instrumentation/common/metrics.py,sha256=sRHuKKTBttU8LE1VTuoU6jLv7d9U2dGvMRC96fr4zQU,3885
30
+ agentops/instrumentation/common/objects.py,sha256=zpMJTsTNDJ-Qgjzqke47uDDYexlmwpGQC83opdmHnkI,982
31
+ agentops/instrumentation/common/span_management.py,sha256=WluRQTrFwFNtVsERfT2Q4W6xntwPsupyfhwLEVSFwMk,6090
32
+ agentops/instrumentation/common/streaming.py,sha256=rSjGhsN8k-so0YjyoqFVtpCeateeApwu5jqOB_De0B0,8085
33
+ agentops/instrumentation/common/token_counting.py,sha256=ZRrmgcR3YCT568l3MU9GH8eb4wO1qu31d0ohWJAkxy8,6502
34
+ agentops/instrumentation/common/version.py,sha256=6HIqtkLEKql_OkpQo1rbOitwTFGWEmlgSVYjXaybi0E,2474
35
+ agentops/instrumentation/common/wrappers.py,sha256=utVwTHxjhS4wCsjPPWtGlFaBy-sBpd4mzy9-I9ftLp0,8242
36
+ agentops/legacy/__init__.py,sha256=8aiLMhFFuzpm_EvwXHAj4mWvYODkBvWFePOjWcBZffc,9749
37
+ agentops/legacy/event.py,sha256=mLlDOaI_WWVOF0uHLYWU0PG5UY3VM8qcux2LCCALcv8,5892
38
+ agentops/logging/__init__.py,sha256=xIz15LVBsdaMzZze-K-vf3z0v467vAz87Khq46Jr7KA,228
39
+ agentops/logging/config.py,sha256=KnX3W1YplmqpuI3j3gAbmuegr3wUsffl2avC2JeDg24,3168
40
+ agentops/logging/formatters.py,sha256=dgi78SUc_yQpL5iga99LNone6OqKeDi-Brgf6ZHjdwY,1062
41
+ agentops/logging/instrument_logging.py,sha256=WurISKObv0eK70FCHw_21V3Dw_OPbQ7smmD_71qPl34,2870
42
+ agentops/sdk/__init__.py,sha256=W9SBzJ9dLnbqaSbsJJ2vmJXMtsWDHttdx2FHdWsjE3s,657
43
+ agentops/sdk/attributes.py,sha256=eSZnHaTRdYFOkoCECuuXPS8Wl-tNM4hZaE6dpDrofAc,4521
44
+ agentops/sdk/core.py,sha256=FdxI0qRfyoppST3WBJYF16kmBsX52PMdTwaq254P7Mk,23993
45
+ agentops/sdk/exporters.py,sha256=lDsydlo-mU4C8_7M4WZ8v5n71pjkYkGIHaViWJkaoJA,3145
46
+ agentops/sdk/processors.py,sha256=kAp70nj_tnO32J-7C9thY0BSS2Ku7qje2qCrH_giO0Y,2451
47
+ agentops/sdk/types.py,sha256=7RMcA65zwiv5zx2-g8z8abtui2UVqpaNujJa7ItY6Yg,889
48
+ agentops/sdk/decorators/__init__.py,sha256=aq1mcjyG6HqxbJIP3JhgjwE_DU1-vKseroWFpbWDg_c,1936
49
+ agentops/sdk/decorators/factory.py,sha256=yR8Z5cS2l2W8ehPwvAP2rt3bASHXygW4Th4Cj9GcWDs,26621
50
+ agentops/sdk/decorators/utility.py,sha256=TxL9hYucmFqiCBOGQ4xaLejBQCjJDo_SaP8qRR3Hkh0,8005
51
+ agentops/semconv/__init__.py,sha256=DxZe_8vlZMsOjlDGGVxysfScfHlRIXHZLOfwyrJLjiA,1357
52
+ agentops/semconv/agent.py,sha256=55fv7BTbYBa_NokK80QBfrloZBx_NyVODhNMaMUaNWQ,1086
53
+ agentops/semconv/core.py,sha256=RI9p6fnSROWjdSI6WolHGrxeoyhNjQy1P5aqmklBxa0,609
54
+ agentops/semconv/enum.py,sha256=oxlWfUyrowFixJDq3fLzbRi9PQQZqr7MU93Ho3oYAKE,215
55
+ agentops/semconv/instrumentation.py,sha256=YKMfXoKS5zDmUHYXwrWKSlVomts9x9sTB4XCwHAnJZA,470
56
+ agentops/semconv/langchain.py,sha256=YIxGgyCWpDMkkNbs5916PBr7-uVFk-dyRICMoPka2Zs,2015
57
+ agentops/semconv/message.py,sha256=YbFwx2ccCs-lrbaeW6kFAF0UhruieGAACdzSQBBJM_M,3644
58
+ agentops/semconv/meters.py,sha256=DCEH0oD745E78k-iEvGmTJjQLIAg3Bkxd_gApvQt8zw,1099
59
+ agentops/semconv/resource.py,sha256=MAj8hHSPrHGGCaMbz1C4Lm0CkJ_JR3BLXto4FKbnmWE,1377
60
+ agentops/semconv/span_attributes.py,sha256=hyTW7KsLB9sp-HDEvbCUiBlkfGXoC5sKMaSSHbcd6JI,5102
61
+ agentops/semconv/span_kinds.py,sha256=NjvowyBDKkWiNW6xND4wuWMYGGcUIxB4bb5xWzTkijc,1564
62
+ agentops/semconv/status.py,sha256=dQ6q-B-kEPWqSPNV7VHF7gojtMgbC-nGvLP_kZe5McY,195
63
+ agentops/semconv/tool.py,sha256=lW1GQWMuMn449TC-Kz-CQCZy7bC76U7fwUbsihWkhSs,514
64
+ agentops/semconv/workflow.py,sha256=N7WsN9DgOPd3lZulS9MJeJRv4zeVnUwC8ZRl0fUbD5o,4290
65
+ mseep_agentops-0.4.18.dist-info/licenses/LICENSE,sha256=zWW9oSZpJVAMBUk-iWOCWBk7c7ITYX2BUU-feXmjKYU,1068
66
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
+ tests/conftest.py,sha256=JqkAW8DASuGo8kKnc3reM-AUHVu40rbxp5Ko_vUv3bw,156
68
+ tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
+ tests/unit/conftest.py,sha256=xXtm0ej-As6TQdCMg6JWuxIMbGqIcar9s_c4VPL34nY,1205
70
+ tests/unit/test_config.py,sha256=OWbUvB5-a39bnAJIBYCP5tg0tozYwQA3gCfGCCHYWW8,2811
71
+ tests/unit/test_context_manager.py,sha256=abmPx2Xi0wyRCyWK2Hiq1ykpS0RCgtFHQWRLV2I6ufg,31724
72
+ tests/unit/test_events.py,sha256=nr8DQdhZffW52Eq_Q713G8V5T6LzsVMGhi-w0PdKR1U,657
73
+ tests/unit/test_host_env.py,sha256=991m9TL-AIDs2w-mhWGin043p9Ygp0DrysRG3g1hhWk,1777
74
+ tests/unit/test_init_py.py,sha256=ZsLjj5TOi25uIJn1cOrVeeE1ZEQeyK7o-se17g31RP4,19813
75
+ tests/unit/test_serialization.py,sha256=xKJLpP5CwFJHnJ6Ipog_BxjHycSgJuucZ2rlpngrq_g,13817
76
+ tests/unit/test_session.py,sha256=n9qSNIums64NRPd4cTHbr2OraozFRwexj7PD5tn4_Hk,24303
77
+ tests/unit/test_user_agent.py,sha256=nV02OvG6DCbLYW1I70ty-gtZMrARNHy6wtY7ehgHFig,1329
78
+ tests/unit/test_validation.py,sha256=GgBZGiiOo5tKaQOva2WsHh44xboMsqop9o_37ldKlRQ,16248
79
+ tests/unit/client/__init__.py,sha256=wTTEld19ez6ToxcPNsz6CyTm4edP8SLrav0NUNrFjB4,50
80
+ tests/unit/client/test_http_adapter.py,sha256=pMSCfT0Zk7X-LsGsFRiDDtdgfxnXQpyT3h6ifE7VxMc,9316
81
+ tests/unit/client/test_http_client.py,sha256=qFWzntM1-aLV03xBFjeEVB7fQ-ZTkBZ5gYV1y-KsWgA,7699
82
+ tests/unit/sdk/__init__.py,sha256=pSE-h4UCp-teG9p-a4T0aXHdSCVuVQhw1gyVq-T57JQ,27
83
+ tests/unit/sdk/instrumentation_tester.py,sha256=_LYJRP-SEmfb9FUcAYrzdgC3JbC-gFF-y2-Z3PT_1Ck,7011
84
+ tests/unit/sdk/test_attributes.py,sha256=a4ecfgdoaVpj41upEzNR92_oXsuGU0uTxUx6vMW2_Ng,16759
85
+ tests/unit/sdk/test_concurrent_instrumentation.py,sha256=B047ExN8CJgp_AVCrYWV-rgaKS76NIkFVhRcdjoSovg,20606
86
+ tests/unit/sdk/test_decorators.py,sha256=CQ1OXOmYfJKfPpfBQuSGfXf578YRX0XXkq6AnecY9IY,31492
87
+ tests/unit/sdk/test_exporters.py,sha256=7rnw3UIi1uZWni9wVd99jb7Rayk1v3y0Z_eUp3TvZeU,10091
88
+ tests/unit/sdk/test_factory.py,sha256=ju7CyyV1vyL6TqGGRq4YfqMDpp-jrP918z7GEIgTQuo,47627
89
+ tests/unit/sdk/test_internal_span_processor.py,sha256=Sbs_4QHtQMYqcNUS6yHtRmI7JUXFSpwpShooVOrH8AY,15917
90
+ tests/unit/sdk/test_resource_attributes.py,sha256=476tVAr4Q-EyyNtBtbkRgA02EMuAGju3NSj9iFLAl8Q,1415
91
+ mseep_agentops-0.4.18.dist-info/METADATA,sha256=Zn6ty9CDZJEApqphvjX5c1R4DBrzLZhvSfFyRgYrEMo,1868
92
+ mseep_agentops-0.4.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
93
+ mseep_agentops-0.4.18.dist-info/top_level.txt,sha256=UrI_CYrHsaaH2rfrGxmVR9jKHfHV2lv1HVENlV8xEeI,15
94
+ mseep_agentops-0.4.18.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 AgentOps-AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ agentops
2
+ tests
tests/__init__.py ADDED
File without changes
tests/conftest.py ADDED
@@ -0,0 +1,10 @@
1
+ import pytest
2
+
3
+
4
+ @pytest.fixture
5
+ def runtime():
6
+ class _BagOfGoodies(object):
7
+ config_mock_applied = False
8
+ pass
9
+
10
+ yield _BagOfGoodies()
tests/unit/__init__.py ADDED
File without changes
@@ -0,0 +1 @@
1
+ """Unit tests for the agentops.client package."""
@@ -0,0 +1,221 @@
1
+ """Tests for the HTTP adapter classes."""
2
+
3
+ from urllib3.util import Retry
4
+
5
+ from agentops.client.http.http_adapter import BaseHTTPAdapter
6
+
7
+ # from agentops.client.auth_manager import AuthManager
8
+
9
+
10
+ class TestBaseHTTPAdapter:
11
+ """Tests for the BaseHTTPAdapter class."""
12
+
13
+ def test_init_with_default_params(self):
14
+ """Test that the adapter initializes with default parameters."""
15
+ adapter = BaseHTTPAdapter()
16
+
17
+ # Verify the adapter was created with the expected parameters
18
+ assert adapter.poolmanager is not None
19
+
20
+ # Check that max_retries was set
21
+ assert adapter.max_retries is not None
22
+ assert isinstance(adapter.max_retries, Retry)
23
+ assert adapter.max_retries.total == 3
24
+ assert adapter.max_retries.backoff_factor == 0.1
25
+ assert adapter.max_retries.status_forcelist == [500, 502, 503, 504]
26
+
27
+ def test_init_with_custom_params(self):
28
+ """Test that the adapter initializes with custom parameters."""
29
+ custom_retry = Retry(total=5, backoff_factor=0.5, status_forcelist=[429, 500, 502, 503, 504])
30
+
31
+ adapter = BaseHTTPAdapter(pool_connections=20, pool_maxsize=300, max_retries=custom_retry)
32
+
33
+ # Verify the adapter was created with the expected parameters
34
+ assert adapter.poolmanager is not None
35
+
36
+ # Check that max_retries was set to our custom value
37
+ assert adapter.max_retries is custom_retry
38
+ assert adapter.max_retries.total == 5
39
+ assert adapter.max_retries.backoff_factor == 0.5
40
+ assert adapter.max_retries.status_forcelist == [429, 500, 502, 503, 504]
41
+
42
+
43
+ # class TestAuthenticatedHttpAdapter:
44
+ # """Tests for the AuthenticatedHttpAdapter class."""
45
+ #
46
+ # @pytest.fixture
47
+ # def auth_manager(self):
48
+ # """Create an AuthManager for testing."""
49
+ # return AuthManager(token_endpoint="https://api.example.com/auth/token")
50
+ #
51
+ # @pytest.fixture
52
+ # def token_fetcher(self):
53
+ # """Create a token fetcher function for testing."""
54
+ # return mock.Mock(return_value={"token": "test-token", "project_id": "test-project"})
55
+ #
56
+ # def test_init(self, auth_manager, token_fetcher):
57
+ # """Test that the adapter initializes correctly."""
58
+ # adapter = AuthenticatedHttpAdapter(
59
+ # auth_manager=auth_manager,
60
+ # api_key="test-api-key",
61
+ # token_fetcher=token_fetcher
62
+ # )
63
+ #
64
+ # # Verify the adapter was created with the expected parameters
65
+ # assert adapter.auth_manager is auth_manager
66
+ # assert adapter.api_key == "test-api-key"
67
+ # assert adapter.token_fetcher is token_fetcher
68
+ #
69
+ # # Verify it's a subclass of BaseHTTPAdapter
70
+ # assert isinstance(adapter, BaseHTTPAdapter)
71
+ #
72
+ # def test_add_headers(self, auth_manager, token_fetcher):
73
+ # """Test that add_headers adds authentication headers to the request."""
74
+ # # Setup
75
+ # adapter = AuthenticatedHttpAdapter(
76
+ # auth_manager=auth_manager,
77
+ # api_key="test-api-key",
78
+ # token_fetcher=token_fetcher
79
+ # )
80
+ #
81
+ # # Mock the auth manager methods
82
+ # auth_manager.maybe_fetch = mock.Mock(return_value={"token": "test-token", "project_id": "test-project"})
83
+ # auth_manager.prepare_auth_headers = mock.Mock(return_value={
84
+ # "Authorization": "Bearer test-token",
85
+ # "Content-Type": "application/json; charset=UTF-8",
86
+ # "X-Agentops-Api-Key": "test-api-key"
87
+ # })
88
+ #
89
+ # # Create a request
90
+ # request = requests.Request('GET', 'https://api.example.com/test').prepare()
91
+ #
92
+ # # Call add_headers
93
+ # modified_request = adapter.add_headers(request)
94
+ #
95
+ # # Verify the auth manager methods were called
96
+ # auth_manager.maybe_fetch.assert_called_once_with("test-api-key", token_fetcher)
97
+ # auth_manager.prepare_auth_headers.assert_called_once_with("test-api-key")
98
+ #
99
+ # # Verify the headers were added to the request
100
+ # assert modified_request.headers["Authorization"] == "Bearer test-token"
101
+ # assert modified_request.headers["Content-Type"] == "application/json; charset=UTF-8"
102
+ # assert modified_request.headers["X-Agentops-Api-Key"] == "test-api-key"
103
+ #
104
+ # def test_send_success(self, auth_manager, token_fetcher, mocker: MockerFixture):
105
+ # """Test that send successfully sends a request."""
106
+ # # Setup
107
+ # adapter = AuthenticatedHttpAdapter(
108
+ # auth_manager=auth_manager,
109
+ # api_key="test-api-key",
110
+ # token_fetcher=token_fetcher
111
+ # )
112
+ #
113
+ # # Mock the add_headers method
114
+ # mocker.patch.object(adapter, 'add_headers', side_effect=lambda r, **kw: r)
115
+ #
116
+ # # Mock the parent send method
117
+ # mock_response = mock.Mock(spec=requests.Response)
118
+ # mock_response.status_code = 200
119
+ # mocker.patch.object(BaseHTTPAdapter, 'send', return_value=mock_response)
120
+ #
121
+ # # Mock the is_token_expired_response method
122
+ # auth_manager.is_token_expired_response = mock.Mock(return_value=False)
123
+ #
124
+ # # Create a request
125
+ # request = requests.Request('GET', 'https://api.example.com/test').prepare()
126
+ #
127
+ # # Call send
128
+ # response = adapter.send(request)
129
+ #
130
+ # # Verify the response
131
+ # assert response is mock_response
132
+ # assert response.status_code == 200
133
+ #
134
+ # # Verify the methods were called
135
+ # adapter.add_headers.assert_called_once()
136
+ # BaseHTTPAdapter.send.assert_called_once()
137
+ # auth_manager.is_token_expired_response.assert_called_once_with(mock_response)
138
+ #
139
+ # def test_send_with_token_refresh(self, auth_manager, token_fetcher, mocker: MockerFixture):
140
+ # """Test that send refreshes the token if it's expired."""
141
+ # # Setup
142
+ # adapter = AuthenticatedHttpAdapter(
143
+ # auth_manager=auth_manager,
144
+ # api_key="test-api-key",
145
+ # token_fetcher=token_fetcher
146
+ # )
147
+ #
148
+ # # Mock the add_headers method
149
+ # mocker.patch.object(adapter, 'add_headers', side_effect=lambda r, **kw: r)
150
+ #
151
+ # # Mock the parent send method to return a 401 response first, then a 200 response
152
+ # expired_response = mock.Mock(spec=requests.Response)
153
+ # expired_response.status_code = 401
154
+ #
155
+ # success_response = mock.Mock(spec=requests.Response)
156
+ # success_response.status_code = 200
157
+ #
158
+ # mocker.patch.object(
159
+ # BaseHTTPAdapter,
160
+ # 'send',
161
+ # side_effect=[expired_response, success_response]
162
+ # )
163
+ #
164
+ # # Mock the auth manager methods
165
+ # auth_manager.is_token_expired_response = mock.Mock(return_value=True)
166
+ # auth_manager.clear_token = mock.Mock()
167
+ # auth_manager.maybe_fetch = mock.Mock(return_value={"token": "new-token", "project_id": "test-project"})
168
+ #
169
+ # # Create a request
170
+ # request = requests.Request('GET', 'https://api.example.com/test').prepare()
171
+ #
172
+ # # Call send
173
+ # response = adapter.send(request)
174
+ #
175
+ # # Verify the auth manager methods were called
176
+ # auth_manager.is_token_expired_response.assert_called_once_with(expired_response)
177
+ # auth_manager.clear_token.assert_called_once()
178
+ # auth_manager.maybe_fetch.assert_called_once_with("test-api-key", token_fetcher)
179
+ #
180
+ # # Verify the response is the success response
181
+ # assert response is success_response
182
+ #
183
+ # def test_send_with_token_refresh_failure(self, auth_manager, token_fetcher, mocker: MockerFixture):
184
+ # """Test that send handles token refresh failures gracefully."""
185
+ # # Setup
186
+ # adapter = AuthenticatedHttpAdapter(
187
+ # auth_manager=auth_manager,
188
+ # api_key="test-api-key",
189
+ # token_fetcher=token_fetcher
190
+ # )
191
+ #
192
+ # # Mock the add_headers method
193
+ # mocker.patch.object(adapter, 'add_headers', side_effect=lambda r, **kw: r)
194
+ #
195
+ # # Mock the parent send method to return a 401 response
196
+ # expired_response = mock.Mock(spec=requests.Response)
197
+ # expired_response.status_code = 401
198
+ #
199
+ # mocker.patch.object(BaseHTTPAdapter, 'send', return_value=expired_response)
200
+ #
201
+ # # Mock the auth manager methods
202
+ # auth_manager.is_token_expired_response = mock.Mock(return_value=True)
203
+ # auth_manager.clear_token = mock.Mock()
204
+ # auth_manager.maybe_fetch = mock.Mock(side_effect=AgentOpsApiJwtExpiredException("Failed to refresh token"))
205
+ #
206
+ # # Create a request
207
+ # request = requests.Request('GET', 'https://api.example.com/test').prepare()
208
+ #
209
+ # # Call send
210
+ # response = adapter.send(request)
211
+ #
212
+ # # Verify the response is the original 401 response
213
+ # assert response is expired_response
214
+ # assert response.status_code == 401
215
+ #
216
+ # # Verify the methods were called
217
+ # adapter.add_headers.assert_called_once() # Only called for initial request
218
+ # BaseHTTPAdapter.send.assert_called_once() # Only called for initial request
219
+ # auth_manager.is_token_expired_response.assert_called_once_with(expired_response)
220
+ # auth_manager.clear_token.assert_called_once()
221
+ # auth_manager.maybe_fetch.assert_called_once_with("test-api-key", token_fetcher)
@@ -0,0 +1,206 @@
1
+ # """Tests for the HttpClient class."""
2
+ #
3
+ # import pytest
4
+ # import requests
5
+ # from unittest import mock
6
+ # from pytest_mock import MockerFixture
7
+ #
8
+ # from agentops.client.http.http_client import HttpClient
9
+ # from agentops.client.http.http_adapter import AuthenticatedHttpAdapter, BaseHTTPAdapter
10
+ # from agentops.client.auth_manager import AuthManager
11
+ #
12
+ #
13
+ # class TestHttpClient:
14
+ # """Tests for the HttpClient class."""
15
+ #
16
+ # def test_get_session_creates_new_session_if_none_exists(self):
17
+ # """Test that get_session creates a new session if none exists."""
18
+ # # Reset the session to ensure we're testing from a clean state
19
+ # HttpClient._session = None
20
+ #
21
+ # # Call get_session
22
+ # session = HttpClient.get_session()
23
+ #
24
+ # # Verify a session was created
25
+ # assert session is not None
26
+ # assert isinstance(session, requests.Session)
27
+ #
28
+ # # Verify the session has the expected adapters
29
+ # assert any(isinstance(adapter, BaseHTTPAdapter) for adapter in session.adapters.values())
30
+ #
31
+ # # Verify the session has the expected headers
32
+ # assert "Content-Type" in session.headers
33
+ # assert "Connection" in session.headers
34
+ # assert "Keep-Alive" in session.headers
35
+ #
36
+ # def test_get_session_returns_existing_session(self):
37
+ # """Test that get_session returns the existing session if one exists."""
38
+ # # Create a session
39
+ # HttpClient._session = None
40
+ # session1 = HttpClient.get_session()
41
+ #
42
+ # # Call get_session again
43
+ # session2 = HttpClient.get_session()
44
+ #
45
+ # # Verify the same session was returned
46
+ # assert session2 is session1
47
+ #
48
+ # def test_get_authenticated_session_creates_new_session(self):
49
+ # """Test that get_authenticated_session creates a new authenticated session."""
50
+ # # Call get_authenticated_session
51
+ # session = HttpClient.get_authenticated_session(
52
+ # endpoint="https://api.example.com",
53
+ # api_key="test-api-key"
54
+ # )
55
+ #
56
+ # # Verify a session was created
57
+ # assert session is not None
58
+ # assert isinstance(session, requests.Session)
59
+ #
60
+ # # Verify the session has the expected adapters
61
+ # assert any(isinstance(adapter, AuthenticatedHttpAdapter) for adapter in session.adapters.values())
62
+ #
63
+ # # Verify the session has the expected headers
64
+ # assert "Content-Type" in session.headers
65
+ # assert "Connection" in session.headers
66
+ # assert "Keep-Alive" in session.headers
67
+ #
68
+ # def test_get_authenticated_session_with_custom_token_fetcher(self, mocker: MockerFixture):
69
+ # """Test that get_authenticated_session accepts a custom token fetcher."""
70
+ # # Create a mock token fetcher
71
+ # mock_token_fetcher = mock.Mock(return_value="test-token")
72
+ #
73
+ # # Call get_authenticated_session with the custom token fetcher
74
+ # session = HttpClient.get_authenticated_session(
75
+ # endpoint="https://api.example.com",
76
+ # api_key="test-api-key",
77
+ # token_fetcher=mock_token_fetcher
78
+ # )
79
+ #
80
+ # # Verify a session was created
81
+ # assert session is not None
82
+ # assert isinstance(session, requests.Session)
83
+ #
84
+ # # Get the adapter
85
+ # adapter = next(adapter for adapter in session.adapters.values()
86
+ # if isinstance(adapter, AuthenticatedHttpAdapter))
87
+ #
88
+ # # Verify the adapter has the custom token fetcher
89
+ # assert adapter.token_fetcher is mock_token_fetcher
90
+ #
91
+ # def test_request_get(self, mocker: MockerFixture):
92
+ # """Test that request makes a GET request."""
93
+ # # Mock the session
94
+ # mock_session = mock.Mock()
95
+ # mock_get = mock.Mock()
96
+ # mock_session.get = mock_get
97
+ #
98
+ # # Mock get_session to return our mock session
99
+ # mocker.patch.object(HttpClient, "get_session", return_value=mock_session)
100
+ #
101
+ # # Call request
102
+ # HttpClient.request(
103
+ # method="get",
104
+ # url="https://api.example.com/test",
105
+ # headers={"X-Test": "test"},
106
+ # timeout=10
107
+ # )
108
+ #
109
+ # # Verify the session method was called with the expected arguments
110
+ # mock_get.assert_called_once_with(
111
+ # "https://api.example.com/test",
112
+ # headers={"X-Test": "test"},
113
+ # timeout=10,
114
+ # allow_redirects=False
115
+ # )
116
+ #
117
+ # def test_request_post(self, mocker: MockerFixture):
118
+ # """Test that request makes a POST request."""
119
+ # # Mock the session
120
+ # mock_session = mock.Mock()
121
+ # mock_post = mock.Mock()
122
+ # mock_session.post = mock_post
123
+ #
124
+ # # Mock get_session to return our mock session
125
+ # mocker.patch.object(HttpClient, "get_session", return_value=mock_session)
126
+ #
127
+ # # Call request
128
+ # HttpClient.request(
129
+ # method="post",
130
+ # url="https://api.example.com/test",
131
+ # data={"test": "data"},
132
+ # headers={"X-Test": "test"},
133
+ # timeout=10
134
+ # )
135
+ #
136
+ # # Verify the session method was called with the expected arguments
137
+ # mock_post.assert_called_once_with(
138
+ # "https://api.example.com/test",
139
+ # json={"test": "data"},
140
+ # headers={"X-Test": "test"},
141
+ # timeout=10,
142
+ # allow_redirects=False
143
+ # )
144
+ #
145
+ # def test_request_put(self, mocker: MockerFixture):
146
+ # """Test that request makes a PUT request."""
147
+ # # Mock the session
148
+ # mock_session = mock.Mock()
149
+ # mock_put = mock.Mock()
150
+ # mock_session.put = mock_put
151
+ #
152
+ # # Mock get_session to return our mock session
153
+ # mocker.patch.object(HttpClient, "get_session", return_value=mock_session)
154
+ #
155
+ # # Call request
156
+ # HttpClient.request(
157
+ # method="put",
158
+ # url="https://api.example.com/test",
159
+ # data={"test": "data"},
160
+ # headers={"X-Test": "test"},
161
+ # timeout=10
162
+ # )
163
+ #
164
+ # # Verify the session method was called with the expected arguments
165
+ # mock_put.assert_called_once_with(
166
+ # "https://api.example.com/test",
167
+ # json={"test": "data"},
168
+ # headers={"X-Test": "test"},
169
+ # timeout=10,
170
+ # allow_redirects=False
171
+ # )
172
+ #
173
+ # def test_request_delete(self, mocker: MockerFixture):
174
+ # """Test that request makes a DELETE request."""
175
+ # # Mock the session
176
+ # mock_session = mock.Mock()
177
+ # mock_delete = mock.Mock()
178
+ # mock_session.delete = mock_delete
179
+ #
180
+ # # Mock get_session to return our mock session
181
+ # mocker.patch.object(HttpClient, "get_session", return_value=mock_session)
182
+ #
183
+ # # Call request
184
+ # HttpClient.request(
185
+ # method="delete",
186
+ # url="https://api.example.com/test",
187
+ # headers={"X-Test": "test"},
188
+ # timeout=10
189
+ # )
190
+ #
191
+ # # Verify the session method was called with the expected arguments
192
+ # mock_delete.assert_called_once_with(
193
+ # "https://api.example.com/test",
194
+ # headers={"X-Test": "test"},
195
+ # timeout=10,
196
+ # allow_redirects=False
197
+ # )
198
+ #
199
+ # def test_request_unsupported_method(self):
200
+ # """Test that request raises an error for unsupported methods."""
201
+ # # Call request with an unsupported method
202
+ # with pytest.raises(ValueError, match="Unsupported HTTP method: patch"):
203
+ # HttpClient.request(
204
+ # method="patch",
205
+ # url="https://api.example.com/test"
206
+ # )