content: """
  All the structures coming from/to the Kubernetes API.
  
  The usage of these classes is spread over the codebase, so they are extracted
  into a separate module of such type definitions.
  
  For strict type-checking, they are detailed to the per-field level
  (e.g. `TypedDict` instead of just ``Mapping[Any, Any]``) --
  as used by the framework. The operators can use arbitrary fields at runtime,
  which are not declared in the type definitions at type-checking time.
  
  In case the operators are also type-checked, type casting can be used
  (without `cast`, this code fails at type-checking, though works at runtime)::
  
      from typing import cast
      import kopf
  
      class MyMeta(kopf.Meta):
          unknownField: str
  
      @kopf.on.create('zalando.org', 'v1', 'kopfexamples')
      def create_fn(*args, meta: kopf.Meta, **kwargs):
          meta = cast(MyMeta, meta)
          print(meta['unknownField'])
  
  .. note::
  
      There is a strict separation of objects coming from/to the Kubernetes API
      and from (but not to) the users:
  
      The Kubernetes-originated objects are dicts or dict-like custom classes.
      The framework internally expect them to be such. Arbitrary 3rd-party
      classes are not supported and are not delivered to the handlers.
  
      The user-originated objects can be either one of the Kubernetes-originated
      framework-supported types (dicts/dict-like), or a 3rd-party class,
      such as from ``pykube-ng``, ``kubernetes`` client, etc -- as long as it is
      supported by the framework's object-processing functions.
  
      In the future, extra classes can be added for the user-originated objects
      and object-processing functions. The internal dicts will remain the same.
  """
  
  from typing import Any, Mapping, MutableMapping, Union, List, Optional, cast
  
  from typing_extensions import TypedDict, Literal
  
  from kopf.structs import dicts
  
  #
  # Everything marked "raw" is a plain unwrapped unprocessed data as JSON-decoded
  # from Kubernetes API, usually as retrieved in watching or fetching API calls.
  # "Input" is a parsed JSON as is, while "event" is an "input" without "errors".
  # All non-used payload falls into `Any`, and is not type-checked.
  #
  
  # ``None`` is used for the listing, when the pseudo-watch-stream is simulated.
  RawInputType = Literal[None, 'ADDED', 'MODIFIED', 'DELETED', 'ERROR']
  RawEventType = Literal[None, 'ADDED', 'MODIFIED', 'DELETED']
  
  
  class RawMeta(TypedDict, total=False):
      uid: str
      name: str
      namespace: str
      labels: Mapping[str, str]
      annotations: Mapping[str, str]
      finalizers: List[str]
      resourceVersion: str
      deletionTimestamp: str
      creationTimestamp: str
      selfLink: str
  
  
  class RawBody(TypedDict, total=False):
      apiVersion: str
      kind: str
      metadata: RawMeta
      spec: Mapping[str, Any]
      status: Mapping[str, Any]
  
  
  # A special payload for type==ERROR (this is not a connection or client error).
  class RawError(TypedDict, total=False):
      apiVersion: str     # usually: Literal['v1']
      kind: str           # usually: Literal['Status']
      metadata: Mapping[Any, Any]
      code: int
      reason: str
      status: str
      message: str
  
  
  # As received from the stream before processing the errors and special cases.
  class RawInput(TypedDict, total=True):
      type: RawInputType
      object: Union[RawBody, RawError]
  
  
  # As passed to the framework after processing the errors and special cases.
  class RawEvent(TypedDict, total=True):
      type: RawEventType
      object: RawBody
  
  
  #
  # Body/Meta essences only contain the fields relevant for object diff tracking.
  # They are presented to the user as part of the diff's `old`/`new` fields & kwargs.
  # Added for stricter type checking, to differentiate from the actual Body/Meta.
  #
  
  
  class MetaEssence(TypedDict, total=False):
      labels: MutableMapping[str, str]
      annotations: MutableMapping[str, str]
  
  
  class BodyEssence(TypedDict, total=False):
      metadata: MetaEssence
      spec: MutableMapping[str, Any]
  
  
  #
  # Enhanced dict-wrappers for easier typed access to well-known typed fields,
  # with live view of updates and changes in the root body (for daemon's)
  # Despite they are just MappingViews with no extensions, they are separated
  # for stricter typing of arguments.
  #
  
  
  class Meta(dicts.MappingView[str, Any]):
  
      def __init__(self, __src: "Body") -> None:
          super().__init__(__src, 'metadata')
          self._labels: dicts.MappingView[str, str] = dicts.MappingView(self, 'labels')
          self._annotations: dicts.MappingView[str, str] = dicts.MappingView(self, 'annotations')
  
      @property
      def labels(self) -> dicts.MappingView[str, str]:
          return self._labels
  
      @property
      def annotations(self) -> dicts.MappingView[str, str]:
          return self._annotations
  
      @property
      def uid(self) -> Optional[str]:
          return cast(Optional[str], self.get('uid', None))
  
      @property
      def name(self) -> Optional[str]:
          return cast(Optional[str], self.get('name', None))
  
      @property
      def namespace(self) -> Optional[str]:
          return cast(Optional[str], self.get('namespace', None))
  
      @property
      def creation_timestamp(self) -> Optional[str]:
          return cast(Optional[str], self.get('creationTimestamp', None))
  
      @property
      def deletion_timestamp(self) -> Optional[str]:
          return cast(Optional[str], self.get('deletionTimestamp', None))
  
  
  class Spec(dicts.MappingView[str, Any]):
      def __init__(self, __src: "Body") -> None:
          super().__init__(__src, 'spec')
  
  
  class Status(dicts.MappingView[str, Any]):
      def __init__(self, __src: "Body") -> None:
          super().__init__(__src, 'status')
  
  
  class Body(dicts.ReplaceableMappingView[str, Any]):
  
      def __init__(self, __src: Mapping[str, Any]) -> None:
          super().__init__(__src)
          self._meta = Meta(self)
          self._spec = Spec(self)
          self._status = Status(self)
  
      @property
      def metadata(self) -> Meta:
          return self._meta
  
      @property
      def meta(self) -> Meta:
          return self._meta
  
      @property
      def spec(self) -> Spec:
          return self._spec
  
      @property
      def status(self) -> Status:
          return self._status
  
  
  #
  # Other API types, which are not body parts.
  #
  
  class ObjectReference(TypedDict, total=False):
      apiVersion: str
      kind: str
      namespace: Optional[str]
      name: str
      uid: str
  
  
  class OwnerReference(TypedDict, total=False):
      controller: bool
      blockOwnerDeletion: bool
      apiVersion: str
      kind: str
      name: str
      uid: str
  
  
  def build_object_reference(
          body: Body,
  ) -> ObjectReference:
      """
      Construct an object reference for the events.
  
      Keep in mind that some fields can be absent: e.g. ``namespace``
      for cluster resources, or e.g. ``apiVersion`` for ``kind: Node``, etc.
      """
      ref = dict(
          apiVersion=body.get('apiVersion'),
          kind=body.get('kind'),
          name=body.get('metadata', {}).get('name'),
          uid=body.get('metadata', {}).get('uid'),
          namespace=body.get('metadata', {}).get('namespace'),
      )
      return cast(ObjectReference, {key: val for key, val in ref.items() if val})
  
  
  def build_owner_reference(
          body: Body,
  ) -> OwnerReference:
      """
      Construct an owner reference object for the parent-children relationships.
  
      The structure needed to link the children objects to the current object as a parent.
      See https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/
  
      Keep in mind that some fields can be absent: e.g. ``namespace``
      for cluster resources, or e.g. ``apiVersion`` for ``kind: Node``, etc.
      """
      ref = dict(
          controller=True,
          blockOwnerDeletion=True,
          apiVersion=body.get('apiVersion'),
          kind=body.get('kind'),
          name=body.get('metadata', {}).get('name'),
          uid=body.get('metadata', {}).get('uid'),
      )
      return cast(OwnerReference, {key: val for key, val in ref.items() if val})
  