| 247 | |
| 248 | |
| 249 | class ExperimentSerializer(serializers.ModelSerializer): # type: ignore[type-arg] |
| 250 | # Annotated with the common base type so ExperimentListSerializer can |
| 251 | # override the field with a read-only representation. |
| 252 | metrics: serializers.BaseSerializer[Any] = ExperimentMetricInlineSerializer( |
| 253 | many=True, |
| 254 | required=False, |
| 255 | write_only=True, |
| 256 | ) |
| 257 | experiment_rollout: Any = ExperimentRolloutSerializer( |
| 258 | required=False, write_only=True |
| 259 | ) |
| 260 | |
| 261 | class Meta: |
| 262 | model = Experiment |
| 263 | fields = ( |
| 264 | "id", |
| 265 | "feature", |
| 266 | "name", |
| 267 | "hypothesis", |
| 268 | "status", |
| 269 | "metrics", |
| 270 | "experiment_rollout", |
| 271 | "created_at", |
| 272 | "updated_at", |
| 273 | "started_at", |
| 274 | "ended_at", |
| 275 | ) |
| 276 | read_only_fields = ( |
| 277 | "id", |
| 278 | "status", |
| 279 | "created_at", |
| 280 | "updated_at", |
| 281 | "started_at", |
| 282 | "ended_at", |
| 283 | ) |
| 284 | |
| 285 | def validate_feature(self, feature: Any) -> Any: |
| 286 | if feature.type != MULTIVARIATE: |
| 287 | raise serializers.ValidationError( |
| 288 | "Experiments can only be created for multivariate flags." |
| 289 | ) |
| 290 | environment: Environment | None = self.context.get("environment") |
| 291 | if environment and feature.project_id != environment.project_id: |
| 292 | raise serializers.ValidationError( |
| 293 | "Feature does not belong to this environment's project." |
| 294 | ) |
| 295 | return feature |
| 296 | |
| 297 | def validate(self, attrs: dict[str, Any]) -> dict[str, Any]: |
| 298 | if self.instance is not None and "feature" in attrs: |
| 299 | raise serializers.ValidationError( |
| 300 | {"feature": "Cannot change the feature of an existing experiment."} |
| 301 | ) |
| 302 | if self.instance is not None and "metrics" in attrs: |
| 303 | raise serializers.ValidationError( |
| 304 | {"metrics": "Cannot change the metrics of an existing experiment."} |
| 305 | ) |
| 306 | if self.instance is not None and "experiment_rollout" in attrs: |
nothing calls this directly
no test coverage detected
searching dependent graphs…