arize-phoenix 9.0.0__py3-none-any.whl → 9.1.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 arize-phoenix might be problematic. Click here for more details.

Files changed (21) hide show
  1. {arize_phoenix-9.0.0.dist-info → arize_phoenix-9.1.0.dist-info}/METADATA +5 -5
  2. {arize_phoenix-9.0.0.dist-info → arize_phoenix-9.1.0.dist-info}/RECORD +21 -19
  3. phoenix/server/api/input_types/ProjectFilter.py +14 -0
  4. phoenix/server/api/input_types/ProjectSort.py +17 -0
  5. phoenix/server/api/queries.py +23 -1
  6. phoenix/server/api/types/Project.py +26 -0
  7. phoenix/server/middleware/gzip.py +26 -19
  8. phoenix/server/static/.vite/manifest.json +36 -36
  9. phoenix/server/static/assets/{components-B2MWTXnm.js → components-fznwgFMD.js} +178 -170
  10. phoenix/server/static/assets/{index-Bfvpea_-.js → index-B2beJ-Dz.js} +2 -2
  11. phoenix/server/static/assets/{pages-CZ2vKu8H.js → pages-DiZbDjAl.js} +452 -405
  12. phoenix/server/static/assets/{vendor-BRDkBC5J.js → vendor-BvFaCsmL.js} +1 -1
  13. phoenix/server/static/assets/{vendor-arizeai-BvTqp_W8.js → vendor-arizeai-DJ2Xx4kZ.js} +1 -1
  14. phoenix/server/static/assets/{vendor-codemirror-COt9UfW7.js → vendor-codemirror-CC0itEC8.js} +1 -1
  15. phoenix/server/static/assets/{vendor-recharts-BoHX9Hvs.js → vendor-recharts-ZOUPDkCE.js} +1 -1
  16. phoenix/server/static/assets/{vendor-shiki-Cw1dsDAz.js → vendor-shiki-CnRwDBHX.js} +1 -1
  17. phoenix/version.py +1 -1
  18. {arize_phoenix-9.0.0.dist-info → arize_phoenix-9.1.0.dist-info}/WHEEL +0 -0
  19. {arize_phoenix-9.0.0.dist-info → arize_phoenix-9.1.0.dist-info}/entry_points.txt +0 -0
  20. {arize_phoenix-9.0.0.dist-info → arize_phoenix-9.1.0.dist-info}/licenses/IP_NOTICE +0 -0
  21. {arize_phoenix-9.0.0.dist-info → arize_phoenix-9.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arize-phoenix
3
- Version: 9.0.0
3
+ Version: 9.1.0
4
4
  Summary: AI Observability and Evaluation
5
5
  Project-URL: Documentation, https://docs.arize.com/phoenix/
6
6
  Project-URL: Issues, https://github.com/Arize-ai/phoenix/issues
@@ -48,8 +48,8 @@ Requires-Dist: scikit-learn
48
48
  Requires-Dist: scipy
49
49
  Requires-Dist: sqlalchemy[asyncio]<3,>=2.0.4
50
50
  Requires-Dist: sqlean-py>=3.45.1
51
- Requires-Dist: starlette>=0.46.0
52
- Requires-Dist: strawberry-graphql>=0.262.0
51
+ Requires-Dist: starlette
52
+ Requires-Dist: strawberry-graphql==0.267.0
53
53
  Requires-Dist: tqdm
54
54
  Requires-Dist: typing-extensions>=4.6
55
55
  Requires-Dist: uvicorn
@@ -71,7 +71,7 @@ Requires-Dist: opentelemetry-sdk; extra == 'container'
71
71
  Requires-Dist: opentelemetry-semantic-conventions; extra == 'container'
72
72
  Requires-Dist: prometheus-client; extra == 'container'
73
73
  Requires-Dist: py-grpc-prometheus; extra == 'container'
74
- Requires-Dist: strawberry-graphql[opentelemetry]==0.262.5; extra == 'container'
74
+ Requires-Dist: strawberry-graphql[opentelemetry]==0.267.0; extra == 'container'
75
75
  Requires-Dist: umap-learn; extra == 'container'
76
76
  Requires-Dist: uvloop; (platform_system != 'Windows') and extra == 'container'
77
77
  Provides-Extra: dev
@@ -102,7 +102,7 @@ Requires-Dist: pytest-postgresql; extra == 'dev'
102
102
  Requires-Dist: pytest-xdist; extra == 'dev'
103
103
  Requires-Dist: pytest==8.3.3; extra == 'dev'
104
104
  Requires-Dist: ruff==0.6.9; extra == 'dev'
105
- Requires-Dist: strawberry-graphql[debug-server,opentelemetry]==0.262.5; extra == 'dev'
105
+ Requires-Dist: strawberry-graphql[debug-server,opentelemetry]==0.267.0; extra == 'dev'
106
106
  Requires-Dist: tabulate; extra == 'dev'
107
107
  Requires-Dist: tox-uv==1.11.3; extra == 'dev'
108
108
  Requires-Dist: tox==4.18.1; extra == 'dev'
@@ -6,7 +6,7 @@ phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
6
6
  phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
7
7
  phoenix/services.py,sha256=ngkyKGVatX3cO2WJdo2hKdaVKP-xJCMvqthvga6kJss,5196
8
8
  phoenix/settings.py,sha256=x87BX7hWGQQZbrW_vrYqFR_izCGfO9gFc--JXUG4Tdk,754
9
- phoenix/version.py,sha256=fmjeF1kRBUkpbk6F_YtljM4OmJk-qNnHjds6vJCK9fc,22
9
+ phoenix/version.py,sha256=Vp3-xOXxJORjCsvHB6KEJnUB-nnX0GoyQaFKOgAuaM0,22
10
10
  phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
12
12
  phoenix/core/model.py,sha256=qBFraOtmwCCnWJltKNP18DDG0mULXigytlFsa6YOz6k,4837
@@ -109,7 +109,7 @@ phoenix/server/api/auth.py,sha256=cvKH2FQLL7PasiqZMHgu9P4qchhEG7a7P9Nxy35FoIQ,15
109
109
  phoenix/server/api/context.py,sha256=O1-mnFWcxV69r0Uw4zz_630qEdRGHiZQCPicAbrZYxo,6898
110
110
  phoenix/server/api/exceptions.py,sha256=TA0JuY2YRnj35qGuMSQ8d0ToHum9gWm9W--3fSKHrX0,1171
111
111
  phoenix/server/api/interceptor.py,sha256=ykDnoC_apUd-llVli3m1CW18kNSIgjz2qZ6m5JmPDu8,1294
112
- phoenix/server/api/queries.py,sha256=NxVJMVEPuqOcPczHSMwSOVe8i_DadYlS_r7QTjbZxZc,39679
112
+ phoenix/server/api/queries.py,sha256=LhJdTVYZX8xo0vuSzlKz5x5-I0le4byfUdCBMSSsgtw,40793
113
113
  phoenix/server/api/schema.py,sha256=fcs36xQwFF_Qe41_5cWR8wYpDvOrnbcyTeo5WNMbDsA,1702
114
114
  phoenix/server/api/subscriptions.py,sha256=TnZhdoNHMXp1NkUVLA-eB54woll7FvxtsB2pLt1dO0w,23001
115
115
  phoenix/server/api/utils.py,sha256=quCBRcusc6PUq9tJq7M8PgwFZp7nXgVAxtbw8feribY,833
@@ -192,7 +192,9 @@ phoenix/server/api/input_types/PatchAnnotationInput.py,sha256=2wxC-ibQU59I28amTx
192
192
  phoenix/server/api/input_types/PatchDatasetExamplesInput.py,sha256=_uMqkAInhLDvzUSASl6HgLNulTsekMcYzyd5J6LF90I,884
193
193
  phoenix/server/api/input_types/PatchDatasetInput.py,sha256=OURtTVY8Z_oFEDtKwT1LCMaOK5D4QYo5TVQ6mDrex-g,328
194
194
  phoenix/server/api/input_types/PerformanceMetricInput.py,sha256=4SG5AymxV2dMeCrK7eREThdt9SuC43irMYZtY-Oq-bg,658
195
+ phoenix/server/api/input_types/ProjectFilter.py,sha256=w3IimMXcNmMkrQ6h89-Yx6uh21r2wj1jci1nPZEDEhQ,260
195
196
  phoenix/server/api/input_types/ProjectSessionSort.py,sha256=qFgLmKYeyFpx7An9ZNdDNkkt7tghrG6XXruQbFLiFt8,919
197
+ phoenix/server/api/input_types/ProjectSort.py,sha256=ZTT-InFB6NvInDwLuivyHe9PxR5nsmQ8aXCHAPjZm9k,329
196
198
  phoenix/server/api/input_types/PromptTemplateOptions.py,sha256=8ZJdH1F9fExcdH9dF8SJ29WycCvtEpK-Z6dZwFO7KgQ,232
197
199
  phoenix/server/api/input_types/PromptVersionInput.py,sha256=n6zBeSkK8ZFRHTjtVx4BK--azZIxXeYETa6Cufcet2I,3743
198
200
  phoenix/server/api/input_types/SpanAnnotationFilter.py,sha256=-djfIXYCxV6sV3GPOZQUV0SPfiWDhRlTORfeQ7tCBgQ,2671
@@ -289,7 +291,7 @@ phoenix/server/api/types/MimeType.py,sha256=Zpi6zCalkSFgsvhzvOs-O1gYA04usAi9H__Q
289
291
  phoenix/server/api/types/Model.py,sha256=8UIFqMe1q-2ufBNg-gxHusV8wM1h-KbfLUeJjyVcMvQ,8081
290
292
  phoenix/server/api/types/NumericRange.py,sha256=afEjgF97Go_OvmjMggbPBt-zGM8IONewAyEiKEHRds0,192
291
293
  phoenix/server/api/types/PerformanceMetric.py,sha256=KFkmJDqP43eDUtARQOUqR7NYcxvL6Vh2uisHWU6H3ko,387
292
- phoenix/server/api/types/Project.py,sha256=91yfPnu717qVQJJaJYBkJo6YXNbNql2HC4sWSXsfBFM,22638
294
+ phoenix/server/api/types/Project.py,sha256=k83Wzs-ofzWErNT6cSYI2r1WuxBWkJMfYe9QIJXMfGI,23426
293
295
  phoenix/server/api/types/ProjectSession.py,sha256=fyfVtpUpFOTnBx8DFnH3dr7WXAssN0ooAgrQSSi7kEI,4677
294
296
  phoenix/server/api/types/ProjectTraceRetentionPolicy.py,sha256=tYy2kgalPDyuaYZr0VUHjH0YpXaiF_QOzg5yfaV_c7c,3782
295
297
  phoenix/server/api/types/Prompt.py,sha256=ccP4eq1e38xbF0afclGWLOuDpBVpNbJ3AOSRClF8yFQ,4955
@@ -328,7 +330,7 @@ phoenix/server/email/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
328
330
  phoenix/server/email/templates/password_reset.html,sha256=jv0Pe-06JloPZcubRWxPdAFHYEn9eDj_4SjmuoIwshI,441
329
331
  phoenix/server/email/templates/welcome.html,sha256=AyVsIOtpmyYwWmmkXjuEgXwkbsag4YHHKfkmOTiNo-M,316
330
332
  phoenix/server/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
331
- phoenix/server/middleware/gzip.py,sha256=N-igp8kO6QoATEa2w9n0BdxkwkB3ZLqwgnjcA-7qua0,1396
333
+ phoenix/server/middleware/gzip.py,sha256=hoznxxXdJlb6_XSyNXFz0OLd9FhtCHv6Tm0TWh0Zijk,1363
332
334
  phoenix/server/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
333
335
  phoenix/server/static/apple-touch-icon-114x114.png,sha256=xtFVXAYQnJkpUApg2D1hltSTuyO4Is4sD4A0ZkikiVU,9486
334
336
  phoenix/server/static/apple-touch-icon-120x120.png,sha256=iqZVAk634BbjJMozA8aHYyw15JjhIlIrG41FA2DFFaE,9957
@@ -340,16 +342,16 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
340
342
  phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
341
343
  phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
342
344
  phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
343
- phoenix/server/static/.vite/manifest.json,sha256=We1LFOj6nMnRbMzbxOE_1L06HVo7xXam1mg-DVoqPXA,2165
344
- phoenix/server/static/assets/components-B2MWTXnm.js,sha256=2_C-61D2pzLsgB9f16vxJfTJDB5MXzarHcLYuWFGO_4,530209
345
- phoenix/server/static/assets/index-Bfvpea_-.js,sha256=RPCq3x94S7VsuWdc0Lk7Y0wX323mvKYnPJnn_AC9kaI,60669
346
- phoenix/server/static/assets/pages-CZ2vKu8H.js,sha256=m2dfQXuAII1BGgr4CayJOJKsZ6ds0iH-hgAIj6phaRo,1013141
347
- phoenix/server/static/assets/vendor-BRDkBC5J.js,sha256=qRSj_aFoih8Zxp-Vya-CWYj-24wgjIYzQLloWW7oa8s,2661112
345
+ phoenix/server/static/.vite/manifest.json,sha256=rCaICFY-8wdiZ75U8y4-MUrDU7XdU_E669bnN9gOvAs,2165
346
+ phoenix/server/static/assets/components-fznwgFMD.js,sha256=jAoLhPiqaiMBzbdJN1OUlu9BDfzSrhyuz4FjP2o_vR4,530800
347
+ phoenix/server/static/assets/index-B2beJ-Dz.js,sha256=Wva_ZwgXqyprahFRDs4xyAdT-zSIcZvXHrMuTbxEZIE,60669
348
+ phoenix/server/static/assets/pages-DiZbDjAl.js,sha256=fd_AWgzPR_JihXaPqMjoV2BhqNsrnp8T3YQZH3G310g,1020732
349
+ phoenix/server/static/assets/vendor-BvFaCsmL.js,sha256=oNH_RaseAQvA3HmtHr-Pf40kGCueGoRsz9_1NXGIICY,2661112
348
350
  phoenix/server/static/assets/vendor-Cg6lcjUC.css,sha256=nZrkr0u6NNElFGvpWHk9GTHeGoibCXCli1bE7mXZGZg,1816
349
- phoenix/server/static/assets/vendor-arizeai-BvTqp_W8.js,sha256=oGu_hHPbWuwvQRlH6ryyXtWRUXJfysRmbz9A1UPN9JU,193248
350
- phoenix/server/static/assets/vendor-codemirror-COt9UfW7.js,sha256=UyZx84hDMEGKM9lU8O6tbzUtgwZTV7rh25Dvn00UGiQ,781264
351
- phoenix/server/static/assets/vendor-recharts-BoHX9Hvs.js,sha256=D9n3-7nfMookUbweXQd9e2CO9upBbtmFdA8hzmI6oz0,282151
352
- phoenix/server/static/assets/vendor-shiki-Cw1dsDAz.js,sha256=7tEVbYPDltuhQcLpdJ2QlMLfJuenNeHhiuB6zUjzGEI,8980312
351
+ phoenix/server/static/assets/vendor-arizeai-DJ2Xx4kZ.js,sha256=6NXeJGecPCNtx8424NHvOLPf3SyzTTjbAFvBzHb4FD4,193248
352
+ phoenix/server/static/assets/vendor-codemirror-CC0itEC8.js,sha256=AHvFAf7RbR6NiOWOyFx6_NTZIHDFntzK76dX0Biycqw,781264
353
+ phoenix/server/static/assets/vendor-recharts-ZOUPDkCE.js,sha256=tfMG__KV1jVYleooEbcXAemqhfrj7KOuyrCZI4EpmZs,282151
354
+ phoenix/server/static/assets/vendor-shiki-CnRwDBHX.js,sha256=CLDfG9Y-KpLVO-kY_W2lDG42SXjFiY8clrESzlwEjug,8980312
353
355
  phoenix/server/static/assets/vendor-three-C5WAXd5r.js,sha256=ELkg06u70N7h8oFmvqdoHyPuUf9VgGEWeT4LKFx4VWo,620975
354
356
  phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
355
357
  phoenix/server/templates/index.html,sha256=e8_jdi7Eo19SK7DI_gglkTW094D17E0VAegoMmmmvIc,4330
@@ -390,9 +392,9 @@ phoenix/utilities/project.py,sha256=auVpARXkDb-JgeX5f2aStyFIkeKvGwN9l7qrFeJMVxI,
390
392
  phoenix/utilities/re.py,sha256=6YyUWIkv0zc2SigsxfOWIHzdpjKA_TZo2iqKq7zJKvw,2081
391
393
  phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
392
394
  phoenix/utilities/template_formatters.py,sha256=gh9PJD6WEGw7TEYXfSst1UR4pWWwmjxMLrDVQ_CkpkQ,2779
393
- arize_phoenix-9.0.0.dist-info/METADATA,sha256=Xu20K4JjcUX625FlF2GkjBkCE8GglKvWw0XR9BMy2R4,25038
394
- arize_phoenix-9.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
395
- arize_phoenix-9.0.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
396
- arize_phoenix-9.0.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
397
- arize_phoenix-9.0.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
398
- arize_phoenix-9.0.0.dist-info/RECORD,,
395
+ arize_phoenix-9.1.0.dist-info/METADATA,sha256=Sk48KJiKxvgvYebRqI0JSlQ_ympN6s9lNAS9RKGkdD4,25030
396
+ arize_phoenix-9.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
397
+ arize_phoenix-9.1.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
398
+ arize_phoenix-9.1.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
399
+ arize_phoenix-9.1.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
400
+ arize_phoenix-9.1.0.dist-info/RECORD,,
@@ -0,0 +1,14 @@
1
+ from enum import Enum
2
+
3
+ import strawberry
4
+
5
+
6
+ @strawberry.enum
7
+ class ProjectFilterColumn(Enum):
8
+ name = "name"
9
+
10
+
11
+ @strawberry.input(description="The filter key and value for project connections")
12
+ class ProjectFilter:
13
+ col: ProjectFilterColumn
14
+ value: str
@@ -0,0 +1,17 @@
1
+ from enum import Enum
2
+
3
+ import strawberry
4
+
5
+ from phoenix.server.api.types.SortDir import SortDir
6
+
7
+
8
+ @strawberry.enum
9
+ class ProjectColumn(Enum):
10
+ name = "name"
11
+ endTime = "end_time"
12
+
13
+
14
+ @strawberry.input(description="The sort key and direction for project connections")
15
+ class ProjectSort:
16
+ col: ProjectColumn
17
+ dir: SortDir
@@ -43,6 +43,8 @@ from phoenix.server.api.input_types.ClusterInput import ClusterInput
43
43
  from phoenix.server.api.input_types.Coordinates import InputCoordinate2D, InputCoordinate3D
44
44
  from phoenix.server.api.input_types.DatasetSort import DatasetSort
45
45
  from phoenix.server.api.input_types.InvocationParameters import InvocationParameter
46
+ from phoenix.server.api.input_types.ProjectFilter import ProjectFilter
47
+ from phoenix.server.api.input_types.ProjectSort import ProjectColumn, ProjectSort
46
48
  from phoenix.server.api.types.AnnotationConfig import AnnotationConfig, to_gql_annotation_config
47
49
  from phoenix.server.api.types.Cluster import Cluster, to_gql_clusters
48
50
  from phoenix.server.api.types.Dataset import Dataset, to_gql_dataset
@@ -230,6 +232,8 @@ class Query:
230
232
  last: Optional[int] = UNSET,
231
233
  after: Optional[CursorString] = UNSET,
232
234
  before: Optional[CursorString] = UNSET,
235
+ sort: Optional[ProjectSort] = UNSET,
236
+ filter: Optional[ProjectFilter] = UNSET,
233
237
  ) -> Connection[Project]:
234
238
  args = ConnectionArgs(
235
239
  first=first,
@@ -237,7 +241,25 @@ class Query:
237
241
  last=last,
238
242
  before=before if isinstance(before, CursorString) else None,
239
243
  )
240
- stmt = select(models.Project).order_by(models.Project.id)
244
+ stmt = select(models.Project)
245
+
246
+ if sort and sort.col is ProjectColumn.endTime:
247
+ # For end time sorting, we need to use a correlated subquery
248
+ # The end_time comes from the Trace model, and we need to get the max end_time for
249
+ # each project
250
+ end_time_subq = (
251
+ select(func.max(models.Trace.end_time))
252
+ .where(models.Trace.project_rowid == models.Project.id)
253
+ .scalar_subquery()
254
+ )
255
+ stmt = stmt.order_by(
256
+ end_time_subq.desc() if sort.dir is SortDir.desc else end_time_subq.asc()
257
+ )
258
+ elif sort:
259
+ sort_col = getattr(models.Project, sort.col.value)
260
+ stmt = stmt.order_by(sort_col.desc() if sort.dir is SortDir.desc else sort_col.asc())
261
+ if filter:
262
+ stmt = stmt.where(getattr(models.Project, filter.col.value).ilike(f"%{filter.value}%"))
241
263
  stmt = exclude_experiment_projects(stmt)
242
264
  async with info.context.db() as session:
243
265
  projects = await session.stream_scalars(stmt)
@@ -584,6 +584,32 @@ class Project(Node):
584
584
  )
585
585
  return ProjectTraceRetentionPolicy(id=id_)
586
586
 
587
+ @strawberry.field
588
+ async def created_at(
589
+ self,
590
+ info: Info[Context, None],
591
+ ) -> datetime:
592
+ if self.db_project:
593
+ created_at = self.db_project.created_at
594
+ else:
595
+ created_at = await info.context.data_loaders.project_fields.load(
596
+ (self.project_rowid, models.Project.created_at),
597
+ )
598
+ return created_at
599
+
600
+ @strawberry.field
601
+ async def updated_at(
602
+ self,
603
+ info: Info[Context, None],
604
+ ) -> datetime:
605
+ if self.db_project:
606
+ updated_at = self.db_project.updated_at
607
+ else:
608
+ updated_at = await info.context.data_loaders.project_fields.load(
609
+ (self.project_rowid, models.Project.updated_at),
610
+ )
611
+ return updated_at
612
+
587
613
 
588
614
  INPUT_VALUE = SpanAttributes.INPUT_VALUE.split(".")
589
615
  OUTPUT_VALUE = SpanAttributes.OUTPUT_VALUE.split(".")
@@ -1,7 +1,7 @@
1
- from starlette.datastructures import Headers
1
+ from typing import Iterable, Iterator
2
+
2
3
  from starlette.middleware.gzip import GZipMiddleware as _GZipMiddleware
3
- from starlette.middleware.gzip import GZipResponder, IdentityResponder
4
- from starlette.types import ASGIApp, Receive, Scope, Send
4
+ from starlette.types import Receive, Scope, Send
5
5
 
6
6
 
7
7
  class GZipMiddleware(_GZipMiddleware):
@@ -10,24 +10,31 @@ class GZipMiddleware(_GZipMiddleware):
10
10
 
11
11
  This middleware adds a check to exclude multipart/mixed content types from compression,
12
12
  which is important for streaming responses where compression could interfere with delivery.
13
-
14
- The middleware will use the IdentityResponder (no compression) when:
15
- 1. The client doesn't support gzip compression, or
16
- 2. The response is a multipart/mixed content type
17
13
  """
18
14
 
19
15
  async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
20
- if scope["type"] != "http":
21
- await self.app(scope, receive, send)
22
- return
23
-
24
- headers = Headers(scope=scope)
25
- responder: ASGIApp
26
- if "gzip" not in headers.get("Accept-Encoding", "") or "multipart/mixed" in headers.get(
27
- "Accept", ""
16
+ if (
17
+ scope.get("type") == "http"
18
+ and isinstance(headers := scope.get("headers"), Iterable)
19
+ and _is_multipart(headers)
28
20
  ):
29
- responder = IdentityResponder(self.app, self.minimum_size)
30
- else:
31
- responder = GZipResponder(self.app, self.minimum_size, compresslevel=self.compresslevel)
21
+ scope["headers"] = list(_remove_accept_encoding(headers))
22
+ await super().__call__(scope, receive, send)
23
+
24
+
25
+ def _is_multipart(
26
+ headers: Iterable[tuple[bytes, bytes]],
27
+ ) -> bool:
28
+ try:
29
+ for k, v in headers:
30
+ if k.decode().lower() == "accept" and "multipart/mixed" in v.decode().lower():
31
+ return True
32
+ except Exception:
33
+ pass
34
+ return False
35
+
32
36
 
33
- await responder(scope, receive, send)
37
+ def _remove_accept_encoding(
38
+ headers: Iterable[tuple[bytes, bytes]],
39
+ ) -> Iterator[tuple[bytes, bytes]]:
40
+ return (kv for kv in headers if kv[0].decode().lower() != "accept-encoding")
@@ -1,28 +1,28 @@
1
1
  {
2
- "_components-B2MWTXnm.js": {
3
- "file": "assets/components-B2MWTXnm.js",
2
+ "_components-fznwgFMD.js": {
3
+ "file": "assets/components-fznwgFMD.js",
4
4
  "name": "components",
5
5
  "imports": [
6
- "_vendor-BRDkBC5J.js",
7
- "_pages-CZ2vKu8H.js",
8
- "_vendor-arizeai-BvTqp_W8.js",
9
- "_vendor-codemirror-COt9UfW7.js",
6
+ "_vendor-BvFaCsmL.js",
7
+ "_pages-DiZbDjAl.js",
8
+ "_vendor-arizeai-DJ2Xx4kZ.js",
9
+ "_vendor-codemirror-CC0itEC8.js",
10
10
  "_vendor-three-C5WAXd5r.js"
11
11
  ]
12
12
  },
13
- "_pages-CZ2vKu8H.js": {
14
- "file": "assets/pages-CZ2vKu8H.js",
13
+ "_pages-DiZbDjAl.js": {
14
+ "file": "assets/pages-DiZbDjAl.js",
15
15
  "name": "pages",
16
16
  "imports": [
17
- "_vendor-BRDkBC5J.js",
18
- "_vendor-arizeai-BvTqp_W8.js",
19
- "_components-B2MWTXnm.js",
20
- "_vendor-codemirror-COt9UfW7.js",
21
- "_vendor-recharts-BoHX9Hvs.js"
17
+ "_vendor-BvFaCsmL.js",
18
+ "_vendor-arizeai-DJ2Xx4kZ.js",
19
+ "_components-fznwgFMD.js",
20
+ "_vendor-codemirror-CC0itEC8.js",
21
+ "_vendor-recharts-ZOUPDkCE.js"
22
22
  ]
23
23
  },
24
- "_vendor-BRDkBC5J.js": {
25
- "file": "assets/vendor-BRDkBC5J.js",
24
+ "_vendor-BvFaCsmL.js": {
25
+ "file": "assets/vendor-BvFaCsmL.js",
26
26
  "name": "vendor",
27
27
  "imports": [
28
28
  "_vendor-three-C5WAXd5r.js"
@@ -35,33 +35,33 @@
35
35
  "file": "assets/vendor-Cg6lcjUC.css",
36
36
  "src": "_vendor-Cg6lcjUC.css"
37
37
  },
38
- "_vendor-arizeai-BvTqp_W8.js": {
39
- "file": "assets/vendor-arizeai-BvTqp_W8.js",
38
+ "_vendor-arizeai-DJ2Xx4kZ.js": {
39
+ "file": "assets/vendor-arizeai-DJ2Xx4kZ.js",
40
40
  "name": "vendor-arizeai",
41
41
  "imports": [
42
- "_vendor-BRDkBC5J.js"
42
+ "_vendor-BvFaCsmL.js"
43
43
  ]
44
44
  },
45
- "_vendor-codemirror-COt9UfW7.js": {
46
- "file": "assets/vendor-codemirror-COt9UfW7.js",
45
+ "_vendor-codemirror-CC0itEC8.js": {
46
+ "file": "assets/vendor-codemirror-CC0itEC8.js",
47
47
  "name": "vendor-codemirror",
48
48
  "imports": [
49
- "_vendor-BRDkBC5J.js",
50
- "_vendor-shiki-Cw1dsDAz.js"
49
+ "_vendor-BvFaCsmL.js",
50
+ "_vendor-shiki-CnRwDBHX.js"
51
51
  ]
52
52
  },
53
- "_vendor-recharts-BoHX9Hvs.js": {
54
- "file": "assets/vendor-recharts-BoHX9Hvs.js",
53
+ "_vendor-recharts-ZOUPDkCE.js": {
54
+ "file": "assets/vendor-recharts-ZOUPDkCE.js",
55
55
  "name": "vendor-recharts",
56
56
  "imports": [
57
- "_vendor-BRDkBC5J.js"
57
+ "_vendor-BvFaCsmL.js"
58
58
  ]
59
59
  },
60
- "_vendor-shiki-Cw1dsDAz.js": {
61
- "file": "assets/vendor-shiki-Cw1dsDAz.js",
60
+ "_vendor-shiki-CnRwDBHX.js": {
61
+ "file": "assets/vendor-shiki-CnRwDBHX.js",
62
62
  "name": "vendor-shiki",
63
63
  "imports": [
64
- "_vendor-BRDkBC5J.js"
64
+ "_vendor-BvFaCsmL.js"
65
65
  ]
66
66
  },
67
67
  "_vendor-three-C5WAXd5r.js": {
@@ -69,19 +69,19 @@
69
69
  "name": "vendor-three"
70
70
  },
71
71
  "index.tsx": {
72
- "file": "assets/index-Bfvpea_-.js",
72
+ "file": "assets/index-B2beJ-Dz.js",
73
73
  "name": "index",
74
74
  "src": "index.tsx",
75
75
  "isEntry": true,
76
76
  "imports": [
77
- "_vendor-BRDkBC5J.js",
78
- "_vendor-arizeai-BvTqp_W8.js",
79
- "_pages-CZ2vKu8H.js",
80
- "_components-B2MWTXnm.js",
77
+ "_vendor-BvFaCsmL.js",
78
+ "_vendor-arizeai-DJ2Xx4kZ.js",
79
+ "_pages-DiZbDjAl.js",
80
+ "_components-fznwgFMD.js",
81
81
  "_vendor-three-C5WAXd5r.js",
82
- "_vendor-codemirror-COt9UfW7.js",
83
- "_vendor-shiki-Cw1dsDAz.js",
84
- "_vendor-recharts-BoHX9Hvs.js"
82
+ "_vendor-codemirror-CC0itEC8.js",
83
+ "_vendor-shiki-CnRwDBHX.js",
84
+ "_vendor-recharts-ZOUPDkCE.js"
85
85
  ]
86
86
  }
87
87
  }