# coding: utf-8

"""
    Mixpeek API

    This is the Mixpeek API, providing access to various endpoints for data processing and retrieval.

    The version of the OpenAPI document: 1.3.0
    Contact: info@mixpeek.com
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""  # noqa: E501


from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator
from typing import Any, ClassVar, Dict, List, Optional
from typing_extensions import Annotated
from mixpeek.models.error_handling import ErrorHandling
from typing import Optional, Set
from typing_extensions import Self

class StageParamsCodeExecution(BaseModel):
    """
    Configuration for executing custom code in secure isolated sandboxes.  **Stage Category**: ENRICH (1-1 Enrichment)  **Transformation**: N documents → N documents (same count, expanded schema)  **Purpose**: Executes user-provided code in isolated sandboxes to compute custom enrichments for each document. The code receives all documents as a JSON array and must return a list of results matching the input length.  **When to Use**:     - Custom transformations not covered by built-in stages     - Data extraction (regex, parsing)     - Unit conversions and normalization     - Cross-document computations (relative scores, rankings)     - Prototyping custom enrichment logic     - Complex string manipulations  **When NOT to Use**:     - Simple field transformations (use json_transform)     - LLM-based enrichment (use llm_enrich)     - External API calls (use api_call stage)     - When deterministic built-in stages suffice  **Operational Behavior**:     - Creates ONE sandbox per stage execution (~200ms startup)     - Passes ALL documents as JSON array to user code     - User code must set `result` to list matching input length     - Merges results back into documents at output_field     - Supports Python, TypeScript, and JavaScript  **Template Support**:     - {{INPUT.*}}: Pipeline input parameters (evaluated before execution)     - {{CONTEXT.*}}: Execution context (namespace_id, internal_id)     - {{SECRET.*}}: Organization vault secrets (e.g., {{SECRET.api_key}})     - Documents are passed as runtime `docs` variable (NOT a template)  **Using Secrets**:     Secrets stored in your organization vault can be referenced in code and env:     - In env vars: {\"API_KEY\": \"{{SECRET.stripe_api_key}}\"}     - In code: \"api_key = '{{SECRET.my_key}}'\"  (less common, prefer env vars)     Secrets are automatically loaded from the vault and redacted in error messages.  Requirements:     - code: REQUIRED, code to execute (receives `docs`, must set `result`)     - output_field: REQUIRED, where to store computed results     - language: OPTIONAL, execution language (default: python)     - timeout_ms: OPTIONAL, execution timeout (default: 5000ms)  Examples:     Word count enrichment:         ```json         {             \"code\": \"result = [{'word_count': len(d.get('content', '').split())} for d in docs]\",             \"output_field\": \"text_stats\"         }         ```      Cross-document relative scores:         ```json         {             \"code\": \"avg = sum(d.get('score', 0) for d in docs) / len(docs)\\nresult = [{'relative': d.get('score', 0) / avg} for d in docs]\",             \"output_field\": \"score_analysis\"         }         ```
    """ # noqa: E501
    code: Optional[StrictStr] = Field(default='result = [{\'word_count\': len(d.get(\'content\', \'\').split())} for d in docs]', description="Code to execute in the sandbox. Receives 'docs' variable (list of document dicts). Must set 'result' variable to a list matching input length. Supports {{INPUT.*}}, {{CONTEXT.*}}, and {{SECRET.*}} templates.")
    language: Optional[StrictStr] = Field(default='python', description="Execution language. Python recommended for most use cases.")
    output_field: Optional[StrictStr] = Field(default='metadata.computed', description="Document field path where results are merged. Dot notation supported: 'metadata.computed'")
    result_variable: Optional[StrictStr] = Field(default='result', description="Variable name containing the output list in your code. Must be a JSON-serializable list with length == len(docs).")
    timeout_ms: Optional[Annotated[int, Field(le=30000, strict=True, ge=100)]] = Field(default=5000, description="Execution timeout in milliseconds (100ms-30s, default 5s)")
    max_output_size: Optional[Annotated[int, Field(le=1000000, strict=True, ge=1024)]] = Field(default=100000, description="Max output size in bytes (default 100KB, max 1MB)")
    env: Optional[Dict[str, StrictStr]] = Field(default=None, description="Environment variables available during execution. Supports INPUT and SECRET templates: {'API_KEY': '{{SECRET.stripe_key}}', 'USER_ID': '{{INPUT.user_id}}'}")
    on_error: Optional[ErrorHandling] = Field(default=None, description="'skip': On error, return input documents unchanged. 'raise': Fail entire pipeline on any error.")
    __properties: ClassVar[List[str]] = ["code", "language", "output_field", "result_variable", "timeout_ms", "max_output_size", "env", "on_error"]

    @field_validator('language')
    def language_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set(['python', 'typescript', 'javascript']):
            raise ValueError("must be one of enum values ('python', 'typescript', 'javascript')")
        return value

    model_config = ConfigDict(
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
    )


    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.model_dump(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
        return json.dumps(self.to_dict())

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of StageParamsCodeExecution from a JSON string"""
        return cls.from_dict(json.loads(json_str))

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias.

        This has the following differences from calling pydantic's
        `self.model_dump(by_alias=True)`:

        * `None` is only added to the output dict for nullable fields that
          were set at model initialization. Other fields with value `None`
          are ignored.
        """
        excluded_fields: Set[str] = set([
        ])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        return _dict

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of StageParamsCodeExecution from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return cls.model_validate(obj)

        _obj = cls.model_validate({
            "code": obj.get("code") if obj.get("code") is not None else 'result = [{\'word_count\': len(d.get(\'content\', \'\').split())} for d in docs]',
            "language": obj.get("language") if obj.get("language") is not None else 'python',
            "output_field": obj.get("output_field") if obj.get("output_field") is not None else 'metadata.computed',
            "result_variable": obj.get("result_variable") if obj.get("result_variable") is not None else 'result',
            "timeout_ms": obj.get("timeout_ms") if obj.get("timeout_ms") is not None else 5000,
            "max_output_size": obj.get("max_output_size") if obj.get("max_output_size") is not None else 100000,
            "env": obj.get("env"),
            "on_error": obj.get("on_error")
        })
        return _obj


