arize-phoenix 11.6.1__py3-none-any.whl → 11.7.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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arize-phoenix
3
- Version: 11.6.1
3
+ Version: 11.7.0
4
4
  Summary: AI Observability and Evaluation
5
5
  Project-URL: Documentation, https://arize.com/docs/phoenix/
6
6
  Project-URL: Issues, https://github.com/Arize-ai/phoenix/issues
@@ -40,7 +40,7 @@ Requires-Dist: opentelemetry-sdk
40
40
  Requires-Dist: opentelemetry-semantic-conventions
41
41
  Requires-Dist: pandas>=1.0
42
42
  Requires-Dist: prometheus-client
43
- Requires-Dist: protobuf<6.0,>=4.25.8
43
+ Requires-Dist: protobuf>=4.25.8
44
44
  Requires-Dist: psutil
45
45
  Requires-Dist: pyarrow
46
46
  Requires-Dist: pydantic>=2.1.0
@@ -65,13 +65,13 @@ Requires-Dist: fast-hdbscan>=0.2.0; extra == 'container'
65
65
  Requires-Dist: google-generativeai; extra == 'container'
66
66
  Requires-Dist: numba>=0.60.0; extra == 'container'
67
67
  Requires-Dist: openai>=1.0.0; extra == 'container'
68
- Requires-Dist: opentelemetry-exporter-otlp; extra == 'container'
69
- Requires-Dist: opentelemetry-instrumentation-fastapi; extra == 'container'
70
- Requires-Dist: opentelemetry-instrumentation-grpc; extra == 'container'
71
- Requires-Dist: opentelemetry-instrumentation-sqlalchemy; extra == 'container'
72
- Requires-Dist: opentelemetry-proto>=1.12.0; extra == 'container'
73
- Requires-Dist: opentelemetry-sdk; extra == 'container'
74
- Requires-Dist: opentelemetry-semantic-conventions; extra == 'container'
68
+ Requires-Dist: opentelemetry-exporter-otlp==1.33.1; extra == 'container'
69
+ Requires-Dist: opentelemetry-instrumentation-fastapi==0.54b1; extra == 'container'
70
+ Requires-Dist: opentelemetry-instrumentation-grpc==0.54b1; extra == 'container'
71
+ Requires-Dist: opentelemetry-instrumentation-sqlalchemy==0.54b1; extra == 'container'
72
+ Requires-Dist: opentelemetry-proto==1.33.1; extra == 'container'
73
+ Requires-Dist: opentelemetry-sdk==1.33.1; extra == 'container'
74
+ Requires-Dist: opentelemetry-semantic-conventions==0.54b1; extra == 'container'
75
75
  Requires-Dist: prometheus-client; extra == 'container'
76
76
  Requires-Dist: py-grpc-prometheus; extra == 'container'
77
77
  Requires-Dist: strawberry-graphql[opentelemetry]==0.270.1; extra == 'container'
@@ -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=2kHfT3BNOVd4dAO1bq-syEQbHSG8oX2-7NhOwK2QREk,896
9
- phoenix/version.py,sha256=VWnuXh96XOfxTdsGBlgaKktRmz_G17IZGf8-J8ntbcs,23
9
+ phoenix/version.py,sha256=rSjRBQs9AcakQYnfj7YZFHQKbSsnq8BzM_MJeZ3UZ1M,23
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
@@ -58,8 +58,8 @@ phoenix/db/types/model_provider.py,sha256=zKYGcEQqbAxtPwnq5dL0fYPgDC8nrh_ABLBMR9
58
58
  phoenix/db/types/token_price_customization.py,sha256=LAb8IwyFJGDCje7CvcPcxNp4NOU8si5hSYaf1fyi624,857
59
59
  phoenix/db/types/trace_retention.py,sha256=fyqAQCvDiD7mpJ_WUqbPyQvuSdERof4DpKpHLJsdROk,9897
60
60
  phoenix/experiments/__init__.py,sha256=6JGwgUd7xCbGpuHqYZlsmErmYvVgv7N_j43bn3dUqsk,123
61
- phoenix/experiments/functions.py,sha256=QoNkMW_EamcFyDBwq4WzKkmHVXD5ZFW9MlUaGRssrTQ,38227
62
- phoenix/experiments/tracing.py,sha256=seNh9rBH-rtQe8_FPI_VJj1rbo3ADcP6wDvERkMoxNc,2858
61
+ phoenix/experiments/functions.py,sha256=iUBk6sLFkK2wHeN-cxax8tku2tFmU_pHRsjNYO0PhIk,39967
62
+ phoenix/experiments/tracing.py,sha256=X-wlgbWEzP1oHkLmjop3fGjONo6JK5a0kPXc9YYD014,2856
63
63
  phoenix/experiments/types.py,sha256=yntt6fnAny1U4Q9Y5Mm4ZYIb9319OaJovl-kyXFtGQE,23475
64
64
  phoenix/experiments/utils.py,sha256=MZ1-OnTcavk_KUtbfGqt55Fk9TGtJpYG_K71WsN-zDk,785
65
65
  phoenix/experiments/evaluators/__init__.py,sha256=CPWW1EiufLqc0JWghE4wVAPG_z6Wt4mD_-yf_4IckB4,772
@@ -108,7 +108,7 @@ phoenix/server/thread_server.py,sha256=Ea2AWreN1lwJsT2wYvGaRaiXrzBqH4kgkZpx0FO5O
108
108
  phoenix/server/types.py,sha256=j8erl9iRNaR8t0DCQG84-uDVbHy9Qnm7T2EuTtDNNsU,8013
109
109
  phoenix/server/api/README.md,sha256=Pyq1PLPgTzXAswrfIhGXrjI3Skq8it2jTVnanT6Ba4Q,1162
110
110
  phoenix/server/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
111
- phoenix/server/api/auth.py,sha256=Bf21wayr-Jrp0ZF9RgbOi9_M91eHE1Tclq9lDYtrkTU,1575
111
+ phoenix/server/api/auth.py,sha256=6GgM0l_h7mbsP7WadE3PmPmqfeLw5TUnXDEfY3m8rkk,1600
112
112
  phoenix/server/api/context.py,sha256=mqsq_8Ru50e-PxKWNTzh9zptb1PFjYFUf58uW59UYL0,8996
113
113
  phoenix/server/api/exceptions.py,sha256=TA0JuY2YRnj35qGuMSQ8d0ToHum9gWm9W--3fSKHrX0,1171
114
114
  phoenix/server/api/interceptor.py,sha256=ykDnoC_apUd-llVli3m1CW18kNSIgjz2qZ6m5JmPDu8,1294
@@ -385,16 +385,16 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
385
385
  phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
386
386
  phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
387
387
  phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
388
- phoenix/server/static/.vite/manifest.json,sha256=Z0ELXF56XCVDEWQGDD7TQYTPq8kx_J4aTeMKhEbSLns,2165
389
- phoenix/server/static/assets/components-BQP0XPOQ.js,sha256=YZJch2ZQyqeZcTQZhYs9gHCU72yDbPRX8UTg6e2RdQA,613664
390
- phoenix/server/static/assets/index-CIOCExre.js,sha256=aRnss9ReUt1vLqPd8x4HnnR_hjKSx5U8SGKWM_7g6QE,61540
391
- phoenix/server/static/assets/pages-DACgXBiR.js,sha256=2BUu0xf8BiVj6zXLSBzH3Z6woFnU4ciWzxOTgbbxs9k,1146567
392
- phoenix/server/static/assets/vendor-DRWIRkSJ.js,sha256=f56XLATSYmnWXn7652x9UsGk4jOQygtd7bfaXtI4I_o,2738792
388
+ phoenix/server/static/.vite/manifest.json,sha256=ds-n_Eo2eRbzplNS-h2Dzaj-_lbPCBYySCioOAnl4uA,2165
389
+ phoenix/server/static/assets/components-J3qjrjBf.js,sha256=Za9a7UixoZeWyxhjTMt9iJ4nPnHB7qoQp1ADPYy_gXg,613734
390
+ phoenix/server/static/assets/index-CEObsQf_.js,sha256=N77fIXIIiRijOKu6RNWX3dozZj0ewUASn1BC639Nyi0,61724
391
+ phoenix/server/static/assets/pages-CW1UdBht.js,sha256=Y9ZOHX-y5Hpdwmy_EKZULiebIsK_KQAjVwmToCvHSW4,1148455
392
+ phoenix/server/static/assets/vendor-BnPh9i9e.js,sha256=K_Ewiog0baSwYbnjeDO5efkeYEi7FRYTiRLmD4_oLaw,2738792
393
393
  phoenix/server/static/assets/vendor-WIZid84E.css,sha256=spZD2r7XL5GfLO13ln-IuXfnjAref8l6g_n_AvxxOlI,5517
394
- phoenix/server/static/assets/vendor-arizeai-DUhQaeau.js,sha256=FtPCxnjNFpPwea0mcq1qokn2T5MQWpp-yxL-_ZbaUZw,181769
395
- phoenix/server/static/assets/vendor-codemirror-D_6Q6Auv.js,sha256=poYtDd52iZVllnYDEqBUCz9n3h9o8DWzIsfhpP1q9pU,781264
396
- phoenix/server/static/assets/vendor-recharts-BNBwj7vz.js,sha256=mskT3kobCNuJlVio5idqsqw0dJ-v94a9D0wXmKHV94o,282150
397
- phoenix/server/static/assets/vendor-shiki-k1qj_XjP.js,sha256=fQi82DMPyJAp6Ng4MlL1THL26gUcYKDOM6XB5-JpoqE,8980312
394
+ phoenix/server/static/assets/vendor-arizeai-Cr9o_Iu_.js,sha256=kybhi48Pux2UUA1gfmDGLDkwRbWyLwwAIS_F7pUMOXE,176579
395
+ phoenix/server/static/assets/vendor-codemirror-k3zCIjlN.js,sha256=zuUSept08wa_k0xCJ-XtMhLVyerrbRZKXkn5Qxtd8GQ,781264
396
+ phoenix/server/static/assets/vendor-recharts-BdblEuGB.js,sha256=JjY_9IvRxXNz-fXWV-ddK4BzNOejSLq0ql_lOacO8Ec,282150
397
+ phoenix/server/static/assets/vendor-shiki-DPtuv2M4.js,sha256=8JbN-Qx5EiaQw_FgHLDqVhDsJ7gDgCFJDQXrZ8imczY,8980312
398
398
  phoenix/server/static/assets/vendor-three-C5WAXd5r.js,sha256=ELkg06u70N7h8oFmvqdoHyPuUf9VgGEWeT4LKFx4VWo,620975
399
399
  phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
400
400
  phoenix/server/templates/index.html,sha256=rTdJZOlbZmm1dMCrHWikAwcecZDxduPU5zCFd2h2cbs,6819
@@ -435,9 +435,9 @@ phoenix/utilities/project.py,sha256=auVpARXkDb-JgeX5f2aStyFIkeKvGwN9l7qrFeJMVxI,
435
435
  phoenix/utilities/re.py,sha256=6YyUWIkv0zc2SigsxfOWIHzdpjKA_TZo2iqKq7zJKvw,2081
436
436
  phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
437
437
  phoenix/utilities/template_formatters.py,sha256=gh9PJD6WEGw7TEYXfSst1UR4pWWwmjxMLrDVQ_CkpkQ,2779
438
- arize_phoenix-11.6.1.dist-info/METADATA,sha256=5JiWDztlZRih80SHXlGCpT4_o4iiEF-JG9xpKtDD3Jg,27761
439
- arize_phoenix-11.6.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
440
- arize_phoenix-11.6.1.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
441
- arize_phoenix-11.6.1.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
442
- arize_phoenix-11.6.1.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
443
- arize_phoenix-11.6.1.dist-info/RECORD,,
438
+ arize_phoenix-11.7.0.dist-info/METADATA,sha256=zbc4IVpy2eyDH5X8918cyrIj3FgCFtlXtyE_4nP_QIU,27804
439
+ arize_phoenix-11.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
440
+ arize_phoenix-11.7.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
441
+ arize_phoenix-11.7.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
442
+ arize_phoenix-11.7.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
443
+ arize_phoenix-11.7.0.dist-info/RECORD,,
@@ -10,7 +10,7 @@ from copy import deepcopy
10
10
  from dataclasses import replace
11
11
  from datetime import datetime, timezone
12
12
  from itertools import product
13
- from typing import Any, Literal, Optional, Union, cast
13
+ from typing import TYPE_CHECKING, Any, Literal, Optional, Union, cast
14
14
  from urllib.parse import urljoin
15
15
 
16
16
  import httpx
@@ -65,6 +65,41 @@ from phoenix.trace.attributes import flatten
65
65
  from phoenix.utilities.client import VersionedAsyncClient, VersionedClient
66
66
  from phoenix.utilities.json import jsonify
67
67
 
68
+ if TYPE_CHECKING:
69
+ from phoenix.client.resources.datasets import Dataset as ClientDataset
70
+
71
+
72
+ def _convert_client_dataset(new_dataset: "ClientDataset") -> Dataset:
73
+ """
74
+ Converts Dataset objects from `phoenix.client` to Dataset objects compatible with experiments.
75
+ """
76
+ examples_dict: dict[str, Example] = {}
77
+ for example_data in new_dataset.examples:
78
+ legacy_example = Example(
79
+ id=example_data["id"],
80
+ input=example_data["input"],
81
+ output=example_data["output"],
82
+ metadata=example_data["metadata"],
83
+ updated_at=datetime.fromisoformat(example_data["updated_at"]),
84
+ )
85
+ examples_dict[legacy_example.id] = legacy_example
86
+
87
+ return Dataset(
88
+ id=new_dataset.id,
89
+ version_id=new_dataset.version_id,
90
+ examples=examples_dict,
91
+ )
92
+
93
+
94
+ def _is_new_client_dataset(dataset: Any) -> bool:
95
+ """Check if dataset is from new client (has list examples)."""
96
+ try:
97
+ from phoenix.client.resources.datasets import Dataset as _ClientDataset
98
+
99
+ return isinstance(dataset, _ClientDataset)
100
+ except ImportError:
101
+ return False
102
+
68
103
 
69
104
  def _phoenix_clients() -> tuple[httpx.Client, httpx.AsyncClient]:
70
105
  return VersionedClient(
@@ -85,7 +120,7 @@ RateLimitErrors: TypeAlias = Union[type[BaseException], Sequence[type[BaseExcept
85
120
 
86
121
 
87
122
  def run_experiment(
88
- dataset: Dataset,
123
+ dataset: Union[Dataset, Any], # Accept both legacy and new client datasets
89
124
  task: ExperimentTask,
90
125
  evaluators: Optional[Evaluators] = None,
91
126
  *,
@@ -166,11 +201,20 @@ def run_experiment(
166
201
  RanExperiment: The results of the experiment and evaluation. Additional evaluations can be
167
202
  added to the experiment using the `evaluate_experiment` function.
168
203
  """
204
+ # Auto-convert client Dataset objects to legacy format
205
+ normalized_dataset: Dataset
206
+ if _is_new_client_dataset(dataset):
207
+ normalized_dataset = _convert_client_dataset(cast("ClientDataset", dataset))
208
+ else:
209
+ normalized_dataset = dataset
210
+
169
211
  task_signature = inspect.signature(task)
170
212
  _validate_task_signature(task_signature)
171
213
 
172
- if not dataset.examples:
173
- raise ValueError(f"Dataset has no examples: {dataset.id=}, {dataset.version_id=}")
214
+ if not normalized_dataset.examples:
215
+ raise ValueError(
216
+ f"Dataset has no examples: {normalized_dataset.id=}, {normalized_dataset.version_id=}"
217
+ )
174
218
  # Add this to the params once supported in the UI
175
219
  repetitions = 1
176
220
  assert repetitions > 0, "Must run the experiment at least once."
@@ -179,7 +223,7 @@ def run_experiment(
179
223
  sync_client, async_client = _phoenix_clients()
180
224
 
181
225
  payload = {
182
- "version_id": dataset.version_id,
226
+ "version_id": normalized_dataset.version_id,
183
227
  "name": experiment_name,
184
228
  "description": experiment_description,
185
229
  "metadata": experiment_metadata,
@@ -187,23 +231,23 @@ def run_experiment(
187
231
  }
188
232
  if not dry_run:
189
233
  experiment_response = sync_client.post(
190
- f"/v1/datasets/{dataset.id}/experiments",
234
+ f"/v1/datasets/{normalized_dataset.id}/experiments",
191
235
  json=payload,
192
236
  )
193
237
  experiment_response.raise_for_status()
194
238
  exp_json = experiment_response.json()["data"]
195
239
  project_name = exp_json["project_name"]
196
240
  experiment = Experiment(
197
- dataset_id=dataset.id,
198
- dataset_version_id=dataset.version_id,
241
+ dataset_id=normalized_dataset.id,
242
+ dataset_version_id=normalized_dataset.version_id,
199
243
  repetitions=repetitions,
200
244
  id=exp_json["id"],
201
245
  project_name=project_name,
202
246
  )
203
247
  else:
204
248
  experiment = Experiment(
205
- dataset_id=dataset.id,
206
- dataset_version_id=dataset.version_id,
249
+ dataset_id=normalized_dataset.id,
250
+ dataset_version_id=normalized_dataset.version_id,
207
251
  repetitions=repetitions,
208
252
  id=DRY_RUN,
209
253
  project_name="",
@@ -216,18 +260,18 @@ def run_experiment(
216
260
  print("🧪 Experiment started.")
217
261
  if dry_run:
218
262
  examples = {
219
- (ex := dataset[i]).id: ex
220
- for i in pd.Series(range(len(dataset)))
221
- .sample(min(len(dataset), int(dry_run)), random_state=42)
263
+ (ex := normalized_dataset[i]).id: ex
264
+ for i in pd.Series(range(len(normalized_dataset)))
265
+ .sample(min(len(normalized_dataset), int(dry_run)), random_state=42)
222
266
  .sort_values()
223
267
  }
224
268
  id_selection = "\n".join(examples)
225
269
  print(f"🌵️ This is a dry-run for these example IDs:\n{id_selection}")
226
- dataset = replace(dataset, examples=examples)
270
+ normalized_dataset = replace(normalized_dataset, examples=examples)
227
271
  else:
228
- dataset_experiments_url = get_dataset_experiments_url(dataset_id=dataset.id)
272
+ dataset_experiments_url = get_dataset_experiments_url(dataset_id=normalized_dataset.id)
229
273
  experiment_compare_url = get_experiment_url(
230
- dataset_id=dataset.id,
274
+ dataset_id=normalized_dataset.id,
231
275
  experiment_id=experiment.id,
232
276
  )
233
277
  print(f"📺 View dataset experiments: {dataset_experiments_url}")
@@ -497,7 +541,7 @@ def run_experiment(
497
541
 
498
542
  test_cases = [
499
543
  TestCase(example=deepcopy(ex), repetition_number=rep)
500
- for ex, rep in product(dataset.examples.values(), range(1, repetitions + 1))
544
+ for ex, rep in product(normalized_dataset.examples.values(), range(1, repetitions + 1))
501
545
  ]
502
546
  task_runs, _execution_details = executor.run(test_cases)
503
547
  print("✅ Task runs completed.")
@@ -513,7 +557,7 @@ def run_experiment(
513
557
  task_runs.append(ExperimentRun.from_dict(run))
514
558
 
515
559
  # Check if we got all expected runs
516
- expected_runs = len(dataset.examples) * repetitions
560
+ expected_runs = len(normalized_dataset.examples) * repetitions
517
561
  actual_runs = len(task_runs)
518
562
  if actual_runs < expected_runs:
519
563
  print(
@@ -521,12 +565,14 @@ def run_experiment(
521
565
  "completed successfully."
522
566
  )
523
567
 
524
- params = ExperimentParameters(n_examples=len(dataset.examples), n_repetitions=repetitions)
568
+ params = ExperimentParameters(
569
+ n_examples=len(normalized_dataset.examples), n_repetitions=repetitions
570
+ )
525
571
  task_summary = TaskSummary.from_task_runs(params, task_runs)
526
572
  ran_experiment: RanExperiment = object.__new__(RanExperiment)
527
573
  ran_experiment.__init__( # type: ignore[misc]
528
574
  params=params,
529
- dataset=dataset,
575
+ dataset=normalized_dataset,
530
576
  runs={r.id: r for r in task_runs if r is not None},
531
577
  task_summary=task_summary,
532
578
  **_asdict(experiment),
@@ -8,7 +8,7 @@ from typing import Any, Optional
8
8
 
9
9
  from opentelemetry.sdk.resources import Resource
10
10
  from opentelemetry.sdk.trace import ReadableSpan
11
- from opentelemetry.trace import INVALID_TRACE_ID
11
+ from opentelemetry.trace import INVALID_SPAN_ID
12
12
  from wrapt import apply_patch, resolve_path, wrap_function_wrapper
13
13
 
14
14
 
@@ -29,7 +29,7 @@ class SpanModifier:
29
29
  Args:
30
30
  span: ReadableSpan: the span to modify
31
31
  """
32
- if (ctx := span._context) is None or ctx.span_id == INVALID_TRACE_ID:
32
+ if (ctx := span._context) is None or ctx.span_id == INVALID_SPAN_ID:
33
33
  return
34
34
  span._resource = span._resource.merge(self._resource)
35
35
 
@@ -29,7 +29,7 @@ class IsLocked(Authorization):
29
29
  message = "Operations that write or modify data are locked"
30
30
 
31
31
  def has_permission(self, source: Any, info: Info, **kwargs: Any) -> bool:
32
- return not info.context.db.should_not_insert_or_update
32
+ return not (info.context.db.should_not_insert_or_update or info.context.locked)
33
33
 
34
34
 
35
35
  MSG_ADMIN_ONLY = "Only admin can perform this action"
@@ -1,28 +1,28 @@
1
1
  {
2
- "_components-BQP0XPOQ.js": {
3
- "file": "assets/components-BQP0XPOQ.js",
2
+ "_components-J3qjrjBf.js": {
3
+ "file": "assets/components-J3qjrjBf.js",
4
4
  "name": "components",
5
5
  "imports": [
6
- "_vendor-DRWIRkSJ.js",
7
- "_pages-DACgXBiR.js",
8
- "_vendor-arizeai-DUhQaeau.js",
9
- "_vendor-codemirror-D_6Q6Auv.js",
6
+ "_vendor-BnPh9i9e.js",
7
+ "_pages-CW1UdBht.js",
8
+ "_vendor-arizeai-Cr9o_Iu_.js",
9
+ "_vendor-codemirror-k3zCIjlN.js",
10
10
  "_vendor-three-C5WAXd5r.js"
11
11
  ]
12
12
  },
13
- "_pages-DACgXBiR.js": {
14
- "file": "assets/pages-DACgXBiR.js",
13
+ "_pages-CW1UdBht.js": {
14
+ "file": "assets/pages-CW1UdBht.js",
15
15
  "name": "pages",
16
16
  "imports": [
17
- "_vendor-DRWIRkSJ.js",
18
- "_vendor-arizeai-DUhQaeau.js",
19
- "_components-BQP0XPOQ.js",
20
- "_vendor-codemirror-D_6Q6Auv.js",
21
- "_vendor-recharts-BNBwj7vz.js"
17
+ "_vendor-BnPh9i9e.js",
18
+ "_vendor-arizeai-Cr9o_Iu_.js",
19
+ "_components-J3qjrjBf.js",
20
+ "_vendor-codemirror-k3zCIjlN.js",
21
+ "_vendor-recharts-BdblEuGB.js"
22
22
  ]
23
23
  },
24
- "_vendor-DRWIRkSJ.js": {
25
- "file": "assets/vendor-DRWIRkSJ.js",
24
+ "_vendor-BnPh9i9e.js": {
25
+ "file": "assets/vendor-BnPh9i9e.js",
26
26
  "name": "vendor",
27
27
  "imports": [
28
28
  "_vendor-three-C5WAXd5r.js"
@@ -35,33 +35,33 @@
35
35
  "file": "assets/vendor-WIZid84E.css",
36
36
  "src": "_vendor-WIZid84E.css"
37
37
  },
38
- "_vendor-arizeai-DUhQaeau.js": {
39
- "file": "assets/vendor-arizeai-DUhQaeau.js",
38
+ "_vendor-arizeai-Cr9o_Iu_.js": {
39
+ "file": "assets/vendor-arizeai-Cr9o_Iu_.js",
40
40
  "name": "vendor-arizeai",
41
41
  "imports": [
42
- "_vendor-DRWIRkSJ.js"
42
+ "_vendor-BnPh9i9e.js"
43
43
  ]
44
44
  },
45
- "_vendor-codemirror-D_6Q6Auv.js": {
46
- "file": "assets/vendor-codemirror-D_6Q6Auv.js",
45
+ "_vendor-codemirror-k3zCIjlN.js": {
46
+ "file": "assets/vendor-codemirror-k3zCIjlN.js",
47
47
  "name": "vendor-codemirror",
48
48
  "imports": [
49
- "_vendor-DRWIRkSJ.js",
50
- "_vendor-shiki-k1qj_XjP.js"
49
+ "_vendor-BnPh9i9e.js",
50
+ "_vendor-shiki-DPtuv2M4.js"
51
51
  ]
52
52
  },
53
- "_vendor-recharts-BNBwj7vz.js": {
54
- "file": "assets/vendor-recharts-BNBwj7vz.js",
53
+ "_vendor-recharts-BdblEuGB.js": {
54
+ "file": "assets/vendor-recharts-BdblEuGB.js",
55
55
  "name": "vendor-recharts",
56
56
  "imports": [
57
- "_vendor-DRWIRkSJ.js"
57
+ "_vendor-BnPh9i9e.js"
58
58
  ]
59
59
  },
60
- "_vendor-shiki-k1qj_XjP.js": {
61
- "file": "assets/vendor-shiki-k1qj_XjP.js",
60
+ "_vendor-shiki-DPtuv2M4.js": {
61
+ "file": "assets/vendor-shiki-DPtuv2M4.js",
62
62
  "name": "vendor-shiki",
63
63
  "imports": [
64
- "_vendor-DRWIRkSJ.js"
64
+ "_vendor-BnPh9i9e.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-CIOCExre.js",
72
+ "file": "assets/index-CEObsQf_.js",
73
73
  "name": "index",
74
74
  "src": "index.tsx",
75
75
  "isEntry": true,
76
76
  "imports": [
77
- "_vendor-DRWIRkSJ.js",
78
- "_vendor-arizeai-DUhQaeau.js",
79
- "_pages-DACgXBiR.js",
80
- "_components-BQP0XPOQ.js",
77
+ "_vendor-BnPh9i9e.js",
78
+ "_vendor-arizeai-Cr9o_Iu_.js",
79
+ "_pages-CW1UdBht.js",
80
+ "_components-J3qjrjBf.js",
81
81
  "_vendor-three-C5WAXd5r.js",
82
- "_vendor-codemirror-D_6Q6Auv.js",
83
- "_vendor-shiki-k1qj_XjP.js",
84
- "_vendor-recharts-BNBwj7vz.js"
82
+ "_vendor-codemirror-k3zCIjlN.js",
83
+ "_vendor-shiki-DPtuv2M4.js",
84
+ "_vendor-recharts-BdblEuGB.js"
85
85
  ]
86
86
  }
87
87
  }