# coding: utf-8

"""
    Airflow API

    Airflow API. All endpoints located under ``/api/v2`` can be used safely, are stable and backward compatible. Endpoints located under ``/ui`` are dedicated to the UI and are subject to breaking change depending on the need of the frontend. Users should not rely on those but use the public ones instead.

    The version of the OpenAPI document: 2
    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 datetime import datetime
from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from typing import Optional, Set
from typing_extensions import Self

class EventLogResponse(BaseModel):
    """
    Event Log Response.
    """ # noqa: E501
    dag_display_name: Optional[StrictStr] = None
    dag_id: Optional[StrictStr] = None
    event: StrictStr
    event_log_id: StrictInt
    extra: Optional[StrictStr] = None
    logical_date: Optional[datetime] = None
    map_index: Optional[StrictInt] = None
    owner: Optional[StrictStr] = None
    run_id: Optional[StrictStr] = None
    task_id: Optional[StrictStr] = None
    try_number: Optional[StrictInt] = None
    when: datetime
    __properties: ClassVar[List[str]] = ["dag_display_name", "dag_id", "event", "event_log_id", "extra", "logical_date", "map_index", "owner", "run_id", "task_id", "try_number", "when"]

    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 EventLogResponse 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 EventLogResponse from a dict"""
        if obj is None:
            return None

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

        _obj = cls.model_validate({
            "dag_display_name": obj.get("dag_display_name"),
            "dag_id": obj.get("dag_id"),
            "event": obj.get("event"),
            "event_log_id": obj.get("event_log_id"),
            "extra": obj.get("extra"),
            "logical_date": obj.get("logical_date"),
            "map_index": obj.get("map_index"),
            "owner": obj.get("owner"),
            "run_id": obj.get("run_id"),
            "task_id": obj.get("task_id"),
            "try_number": obj.get("try_number"),
            "when": obj.get("when")
        })
        return _obj


