gen_ai_hub.proxy.native.google_genai.clients
index
/home/jenkins/agent/workspace/ation_generative-ai-hub-sdk_main/gen_ai_hub/proxy/native/google_genai/clients.py

 
Modules
       
httpx
google.genai.types

 
Classes
       
google.genai._interactions.BaseTransport(builtins.object)
AICoreDynamicTransport
google.genai.client.Client(builtins.object)
Client
google.genai.models.Models(google.genai._api_module.BaseModule)
Models
httpx.AsyncBaseTransport(builtins.object)
AsyncAICoreDynamicTransport

 
class AICoreDynamicTransport(google.genai._interactions.BaseTransport)
    AICoreDynamicTransport(proxy_client: gen_ai_hub.proxy.core.base.BaseProxyClient, **deployment_selector_kwargs)
 
Synchronous transport that dynamically resolves deployment URLs per request.
 
 
Method resolution order:
AICoreDynamicTransport
google.genai._interactions.BaseTransport
builtins.object

Methods defined here:
__init__(self, proxy_client: gen_ai_hub.proxy.core.base.BaseProxyClient, **deployment_selector_kwargs)
Transport constructor.
 
:param proxy_client: The proxy client used to select deployments.
:type proxy_client: BaseProxyClient
close(self)
Closes the inner transport.
get_selector_kwargs(self)
Get the deployment selector kwargs.
 
:return: The deployment selector kwargs.
:rtype: dict
handle_request(self, request: httpx.Request) -> httpx.Response
Handles the request by rewriting it to route through the appropriate AI Core deployment.
 
:param request: The original HTTPX request.
:type request: httpx.Request
:return: The HTTPX response from the AI Core deployment.
:rtype: httpx.Response

Methods inherited from google.genai._interactions.BaseTransport:
__enter__(self: 'T') -> 'T'
__exit__(self, exc_type: 'type[BaseException] | None' = None, exc_value: 'BaseException | None' = None, traceback: 'TracebackType | None' = None) -> 'None'

Data descriptors inherited from google.genai._interactions.BaseTransport:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
class AsyncAICoreDynamicTransport(httpx.AsyncBaseTransport)
    AsyncAICoreDynamicTransport(proxy_client: gen_ai_hub.proxy.core.base.BaseProxyClient, **deployment_selector_kwargs)
 
Asynchronous transport that dynamically resolves deployment URLs per request.
 
 
Method resolution order:
AsyncAICoreDynamicTransport
httpx.AsyncBaseTransport
builtins.object

Methods defined here:
__init__(self, proxy_client: gen_ai_hub.proxy.core.base.BaseProxyClient, **deployment_selector_kwargs)
Transport constructor.
 
:param proxy_client: The proxy client used to select deployments.
:type proxy_client: BaseProxyClient
async aclose(self)
Closes the inner transport.
get_selector_kwargs(self)
get the deployment selector kwargs.
 
:return: The deployment selector kwargs.
:rtype: dict
async handle_async_request(self, request: httpx.Request) -> httpx.Response
Handles the request by rewriting it to route through the appropriate AI Core deployment.
 
:param request: The original HTTPX request.
:type request: httpx.Request
:return: The HTTPX response from the AI Core deployment.
:rtype: httpx.Response

Methods inherited from httpx.AsyncBaseTransport:
async __aenter__(self: 'A') -> 'A'
async __aexit__(self, exc_type: 'type[BaseException] | None' = None, exc_value: 'BaseException | None' = None, traceback: 'TracebackType | None' = None) -> 'None'

Data descriptors inherited from httpx.AsyncBaseTransport:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
class Client(google.genai.client.Client)
    Client(vertexai: bool = True, project: str = 'placeholder', location: str = 'placeholder', deployment_id: str = '', config_id: str = '', config_name: str = '', proxy_client: gen_ai_hub.proxy.core.base.BaseProxyClient = None, timeout: int = None, **kwargs)
 
Unified, native-feeling client that dynamically routes requests
through SAP AI Core deployments based on the requested identifiers e.g. model name.
 
 
Method resolution order:
Client
google.genai.client.Client
builtins.object

Methods defined here:
__init__(self, vertexai: bool = True, project: str = 'placeholder', location: str = 'placeholder', deployment_id: str = '', config_id: str = '', config_name: str = '', proxy_client: gen_ai_hub.proxy.core.base.BaseProxyClient = None, timeout: int = None, **kwargs)
Initializes the Client.
 
:param vertexai: to indicate Vertex AI usage, defaults to True
:type vertexai: bool, optional
:param project: the GCP project, defaults to "placeholder"
:type project: str, optional
:param location: the GCP location, defaults to "placeholder"
:type location: str, optional
:param deployment_id: the deployment identifier, defaults to ""
:type deployment_id: str, optional
:param config_id: the configuration identifier, defaults to ""
:type config_id: str, optional
:param config_name: the configuration name, defaults to ""
:type config_name: str, optional
:param proxy_client: the proxy client to use, defaults to None
:type proxy_client: BaseProxyClient, optional
:param timeout: the request timeout, defaults to None
:type timeout: int, optional

Methods inherited from google.genai.client.Client:
__del__(self) -> None
__enter__(self) -> 'Client'
__exit__(self, exc_type: Optional[Exception], exc_value: Optional[Exception], traceback: Optional[traceback]) -> None
close(self) -> None
Closes the synchronous client explicitly.
 
However, it doesn't close the async client, which can be closed using the
Client.aio.aclose() method or using the async context manager.
 
Usage:
.. code-block:: python
 
  from google.genai import Client
 
  client = Client(
      vertexai=True, project='my-project-id', location='us-central1'
  )
  response_1 = client.models.generate_content(
      model='gemini-2.0-flash',
      contents='Hello World',
  )
  response_2 = client.models.generate_content(
      model='gemini-2.0-flash',
      contents='Hello World',
  )
  # Close the client to release resources.
  client.close()

Readonly properties inherited from google.genai.client.Client:
aio
auth_tokens
batches
caches
chats
file_search_stores
files
interactions
models
operations
tunings
vertexai
Returns whether the client is using the Vertex AI API.
webhooks

Data descriptors inherited from google.genai.client.Client:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
class Models(google.genai.models.Models)
    Models(api_client_: google.genai._api_client.BaseApiClient)
 
Class that extends the original Google Models class for patch embed_content method.
 
 
Method resolution order:
Models
google.genai.models.Models
google.genai._api_module.BaseModule
builtins.object

Methods defined here:
embed_content(self, *, model: str, contents: Union[google.genai.types.Content, str, google.genai.types.File, google.genai.types.Part, list[Union[str, google.genai.types.File, google.genai.types.Part]], list[Union[google.genai.types.Content, str, google.genai.types.File, google.genai.types.Part, list[Union[str, google.genai.types.File, google.genai.types.Part]]]], google.genai.types.ContentDict, google.genai.types.FileDict, google.genai.types.PartDict, list[Union[str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict]], list[Union[google.genai.types.Content, google.genai.types.ContentDict, str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict, list[Union[str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict]]]]], config: Union[google.genai.types.EmbedContentConfig, google.genai.types.EmbedContentConfigDict, NoneType] = None) -> google.genai.types.EmbedContentResponse
Need for add model version for "gemini-embedding" model.

Methods inherited from google.genai.models.Models:
compute_tokens(self, *, model: str, contents: Union[google.genai.types.Content, str, google.genai.types.File, google.genai.types.Part, list[Union[str, google.genai.types.File, google.genai.types.Part]], list[Union[google.genai.types.Content, str, google.genai.types.File, google.genai.types.Part, list[Union[str, google.genai.types.File, google.genai.types.Part]]]], google.genai.types.ContentDict, google.genai.types.FileDict, google.genai.types.PartDict, list[Union[str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict]], list[Union[google.genai.types.Content, google.genai.types.ContentDict, str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict, list[Union[str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict]]]]], config: Union[google.genai.types.ComputeTokensConfig, google.genai.types.ComputeTokensConfigDict, NoneType] = None) -> google.genai.types.ComputeTokensResponse
Given a list of contents, returns a corresponding TokensInfo containing the
 
list of tokens and list of token ids.
 
This method is not supported by the Gemini Developer API.
 
Args:
  model (str): The model to use.
  contents (list[shared.Content]): The content to compute tokens for.
 
Usage:
 
.. code-block:: python
 
  response = client.models.compute_tokens(
      model='gemini-2.0-flash',
      contents='What is your name?',
  )
  print(response)
  # tokens_info=[TokensInfo(role='user', token_ids=['1841', ...],
  # tokens=[b'What', b' is', b' your', b' name', b'?'])]
count_tokens(self, *, model: str, contents: Union[google.genai.types.Content, str, google.genai.types.File, google.genai.types.Part, list[Union[str, google.genai.types.File, google.genai.types.Part]], list[Union[google.genai.types.Content, str, google.genai.types.File, google.genai.types.Part, list[Union[str, google.genai.types.File, google.genai.types.Part]]]], google.genai.types.ContentDict, google.genai.types.FileDict, google.genai.types.PartDict, list[Union[str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict]], list[Union[google.genai.types.Content, google.genai.types.ContentDict, str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict, list[Union[str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict]]]]], config: Union[google.genai.types.CountTokensConfig, google.genai.types.CountTokensConfigDict, NoneType] = None) -> google.genai.types.CountTokensResponse
Counts the number of tokens in the given content.
 
Multimodal input is supported for Gemini models.
 
Args:
  model (str): The model to use for counting tokens.
  contents (list[types.Content]): The content to count tokens for.
  config (CountTokensConfig): The configuration for counting tokens.
 
Usage:
 
.. code-block:: python
 
  response = client.models.count_tokens(
      model='gemini-2.0-flash',
      contents='What is your name?',
  )
  print(response)
  # total_tokens=5 cached_content_token_count=None
delete(self, *, model: str, config: Union[google.genai.types.DeleteModelConfig, google.genai.types.DeleteModelConfigDict, NoneType] = None) -> google.genai.types.DeleteModelResponse
edit_image(self, *, model: str, prompt: str, reference_images: list[typing.Union[google.genai.types._ReferenceImageAPI, google.genai.types._ReferenceImageAPIDict]], config: Union[google.genai.types.EditImageConfig, google.genai.types.EditImageConfigDict, NoneType] = None) -> google.genai.types.EditImageResponse
Edits an image based on a text description and configuration.
 
Args:
  model (str): The model to use.
  prompt (str): A text description of the edit to apply to the image.
    reference_images (list[Union[RawReferenceImage, MaskReferenceImage,
    ControlReferenceImage, StyleReferenceImage, SubjectReferenceImage]): The
    reference images for editing.
  config (EditImageConfig): Configuration for editing.
 
Usage:
 
.. code-block:: python
 
  from google.genai.types import RawReferenceImage, MaskReferenceImage
 
  raw_ref_image = RawReferenceImage(
    reference_id=1,
    reference_image=types.Image.from_file(IMAGE_FILE_PATH),
  )
 
  mask_ref_image = MaskReferenceImage(
    reference_id=2,
    config=types.MaskReferenceConfig(
        mask_mode='MASK_MODE_FOREGROUND',
        mask_dilation=0.06,
    ),
  )
  response = client.models.edit_image(
    model='imagen-3.0-capability-001',
    prompt='man with dog',
    reference_images=[raw_ref_image, mask_ref_image],
    config=types.EditImageConfig(
        edit_mode= "EDIT_MODE_INPAINT_INSERTION",
        number_of_images= 1,
        include_rai_reason= True,
    )
  )
  response.generated_images[0].image.show()
  # Shows a man with a dog instead of a cat.
generate_content(self, *, model: str, contents: Union[google.genai.types.Content, google.genai.types.ContentDict, str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict, list[Union[str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict]], list[Union[google.genai.types.Content, google.genai.types.ContentDict, str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict, list[Union[str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict]]]]], config: Union[google.genai.types.GenerateContentConfig, google.genai.types.GenerateContentConfigDict, NoneType] = None) -> google.genai.types.GenerateContentResponse
Makes an API request to generate content using a model.
 
For the `model` parameter, supported formats for Vertex AI API include:
- The Gemini model ID, for example: 'gemini-2.0-flash'
- The full resource name starts with 'projects/', for example:
  'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash'
- The partial resource name with 'publishers/', for example:
  'publishers/google/models/gemini-2.0-flash' or
- `/` separated publisher and model name, for example:
  'google/gemini-2.0-flash'
 
For the `model` parameter, supported formats for Gemini API include:
- The Gemini model ID, for example: 'gemini-2.0-flash'
- The model name starts with 'models/', for example:
  'models/gemini-2.0-flash'
- For tuned models, the model name starts with 'tunedModels/',
  for example:
  'tunedModels/1234567890123456789'
 
Some models support multimodal input and output.
 
Built-in MCP support is an experimental feature.
 
Usage:
 
.. code-block:: python
 
  from google.genai import types
  from google import genai
 
  client = genai.Client(
      vertexai=True, project='my-project-id', location='us-central1'
  )
 
  response = client.models.generate_content(
    model='gemini-2.0-flash',
    contents='''What is a good name for a flower shop that specializes in
      selling bouquets of dried flowers?'''
  )
  print(response.text)
  # **Elegant & Classic:**
  # * The Dried Bloom
  # * Everlasting Florals
  # * Timeless Petals
 
  response = client.models.generate_content(
    model='gemini-2.0-flash',
    contents=[
      types.Part.from_text(text='What is shown in this image?'),
      types.Part.from_uri(file_uri='gs://generativeai-downloads/images/scones.jpg',
      mime_type='image/jpeg')
    ]
  )
  print(response.text)
  # The image shows a flat lay arrangement of freshly baked blueberry
  # scones.
generate_content_stream(self, *, model: str, contents: Union[google.genai.types.Content, google.genai.types.ContentDict, str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict, list[Union[str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict]], list[Union[google.genai.types.Content, google.genai.types.ContentDict, str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict, list[Union[str, google.genai.types.File, google.genai.types.FileDict, google.genai.types.Part, google.genai.types.PartDict]]]]], config: Union[google.genai.types.GenerateContentConfig, google.genai.types.GenerateContentConfigDict, NoneType] = None) -> Iterator[google.genai.types.GenerateContentResponse]
Makes an API request to generate content using a model and yields the model's response in chunks.
 
For the `model` parameter, supported formats for Vertex AI API include:
- The Gemini model ID, for example: 'gemini-2.0-flash'
- The full resource name starts with 'projects/', for example:
  'projects/my-project-id/locations/us-central1/publishers/google/models/gemini-2.0-flash'
- The partial resource name with 'publishers/', for example:
  'publishers/google/models/gemini-2.0-flash' or
- `/` separated publisher and model name, for example:
  'google/gemini-2.0-flash'
 
For the `model` parameter, supported formats for Gemini API include:
- The Gemini model ID, for example: 'gemini-2.0-flash'
- The model name starts with 'models/', for example:
  'models/gemini-2.0-flash'
- For tuned models, the model name starts with 'tunedModels/',
  for example:
  'tunedModels/1234567890123456789'
 
Some models support multimodal input and output.
 
Built-in MCP support is an experimental feature.
 
Usage:
 
.. code-block:: python
 
  from google.genai import types
  from google import genai
 
  client = genai.Client(
      vertexai=True, project='my-project-id', location='us-central1'
  )
 
  for chunk in client.models.generate_content_stream(
    model='gemini-2.0-flash',
    contents='''What is a good name for a flower shop that specializes in
      selling bouquets of dried flowers?'''
  ):
    print(chunk.text)
  # **Elegant & Classic:**
  # * The Dried Bloom
  # * Everlasting Florals
  # * Timeless Petals
 
  for chunk in client.models.generate_content_stream(
    model='gemini-2.0-flash',
    contents=[
      types.Part.from_text('What is shown in this image?'),
      types.Part.from_uri('gs://generativeai-downloads/images/scones.jpg',
      'image/jpeg')
    ]
  ):
    print(chunk.text)
  # The image shows a flat lay arrangement of freshly baked blueberry
  # scones.
generate_images(self, *, model: str, prompt: str, config: Union[google.genai.types.GenerateImagesConfig, google.genai.types.GenerateImagesConfigDict, NoneType] = None) -> google.genai.types.GenerateImagesResponse
Generates images based on a text description and configuration.
 
Args:
  model (str): The model to use.
  prompt (str): A text description of the images to generate.
  config (GenerateImagesConfig): Configuration for generation.
 
Usage:
 
.. code-block:: python
 
  response = client.models.generate_images(
    model='imagen-3.0-generate-002',
    prompt='Man with a dog',
    config=types.GenerateImagesConfig(
        number_of_images= 1,
        include_rai_reason= True,
    )
  )
  response.generated_images[0].image.show()
  # Shows a man with a dog.
generate_videos(self, *, model: str, prompt: Optional[str] = None, image: Union[google.genai.types.Image, google.genai.types.ImageDict, NoneType] = None, video: Union[google.genai.types.Video, google.genai.types.VideoDict, NoneType] = None, source: Union[google.genai.types.GenerateVideosSource, google.genai.types.GenerateVideosSourceDict, NoneType] = None, config: Union[google.genai.types.GenerateVideosConfig, google.genai.types.GenerateVideosConfigDict, NoneType] = None) -> google.genai.types.GenerateVideosOperation
Generates videos based on an input (text, image, or video) and configuration.
 
The following use cases are supported:
1. Text to video generation.
2a. Image to video generation (additional text prompt is optional).
2b. Image to video generation with frame interpolation (specify last_frame
in config).
3. Video extension (additional text prompt is optional)
 
Args:
  model: The model to use.
  prompt: The text prompt for generating the videos. Optional for image to
    video and video extension use cases. This argument is deprecated, please
    use source instead.
  image: The input image for generating the videos. Optional if prompt is
    provided. This argument is deprecated, please use source instead.
  video: The input video for video extension use cases. Optional if prompt
    or image is provided. This argument is deprecated, please use source
    instead.
  source: The input source for generating the videos (prompt, image, and/or
    video)
  config: Configuration for generation.
 
Usage:
 
  ```
  operation = client.models.generate_videos(
      model="veo-2.0-generate-001",
      source=types.GenerateVideosSource(
          prompt="A neon hologram of a cat driving at top speed",
      ),
  )
  while not operation.done:
      time.sleep(10)
      operation = client.operations.get(operation)
 
  operation.result.generated_videos[0].video.uri
  ```
get(self, *, model: str, config: Union[google.genai.types.GetModelConfig, google.genai.types.GetModelConfigDict, NoneType] = None) -> google.genai.types.Model
list(self, *, config: Union[google.genai.types.ListModelsConfig, google.genai.types.ListModelsConfigDict, NoneType] = None) -> google.genai.pagers.Pager[google.genai.types.Model]
Makes an API request to list the available models.
 
If `query_base` is set to True in the config or not set (default), the
API will return all available base models. If set to False, it will return
all tuned models.
 
Args:
  config (ListModelsConfigOrDict): Configuration for retrieving models.
 
Usage:
 
.. code-block:: python
 
  response=client.models.list(config={'page_size': 5})
  print(response.page)
  # [Model(name='projects/./locations/./models/123', display_name='my_model'
 
  response=client.models.list(config={'page_size': 5, 'query_base': True})
  print(response.page)
  # [Model(name='publishers/google/models/gemini-2.0-flash-exp' ...
recontext_image(self, *, model: str, source: Union[google.genai.types.RecontextImageSource, google.genai.types.RecontextImageSourceDict], config: Union[google.genai.types.RecontextImageConfig, google.genai.types.RecontextImageConfigDict, NoneType] = None) -> google.genai.types.RecontextImageResponse
Recontextualizes an image.
 
There is one type of recontextualization currently supported:
1) Virtual Try-On: Generate images of persons modeling fashion products.
 
Args:
  model (str): The model to use.
  source (RecontextImageSource): An object containing the source inputs
    (prompt, person_image, product_images) for image recontext. prompt is
    behind an allowlist. person_image is required. product_images is
    required. Only one product image is supported currently.
  config (RecontextImageConfig): Configuration for recontextualization.
 
Usage:
 
  ```
  virtual_try_on_response = client.models.recontext_image(
      model="virtual-try-on-001",
      source=types.RecontextImageSource(
          person_image=types.Image.from_file(IMAGE1_FILE_PATH),
          product_images=[types.ProductImage.from_file(IMAGE2_FILE_PATH)],
      ),
      config=types.RecontextImageConfig(
          number_of_images=1,
      ),
  )
  image = virtual_try_on_response.generated_images[0].image
  ```
segment_image(self, *, model: str, source: Union[google.genai.types.SegmentImageSource, google.genai.types.SegmentImageSourceDict], config: Union[google.genai.types.SegmentImageConfig, google.genai.types.SegmentImageConfigDict, NoneType] = None) -> google.genai.types.SegmentImageResponse
Segments an image, creating a mask of a specified area.
 
Args:
  model (str): The model to use.
  source (SegmentImageSource): An object containing the source inputs
    (prompt, image, scribble_image) for image segmentation. The prompt is
    required for prompt mode and semantic mode, disallowed for other modes.
    scribble_image is required for the interactive mode, disallowed for
    other modes.
  config (SegmentImageConfig): Configuration for segmentation.
 
Usage:
 
  ```
  response = client.models.segment_image(
      model="image-segmentation-001",
      source=types.SegmentImageSource(
          image=types.Image.from_file(IMAGE_FILE_PATH),
      ),
  )
 
  mask_image = response.generated_masks[0].mask
  ```
update(self, *, model: str, config: Union[google.genai.types.UpdateModelConfig, google.genai.types.UpdateModelConfigDict, NoneType] = None) -> google.genai.types.Model
upscale_image(self, *, model: str, image: Union[google.genai.types.Image, google.genai.types.ImageDict], upscale_factor: str, config: Union[google.genai.types.UpscaleImageConfig, google.genai.types.UpscaleImageConfigDict, NoneType] = None) -> google.genai.types.UpscaleImageResponse
Makes an API request to upscale a provided image.
 
Args:
  model (str): The model to use.
  image (Image): The input image for upscaling.
  upscale_factor (str): The factor to upscale the image (x2 or x4).
  config (UpscaleImageConfig): Configuration for upscaling.
 
Usage:
 
.. code-block:: python
 
  from google.genai.types import Image
 
  IMAGE_FILE_PATH="my-image.png"
  response=client.models.upscale_image(
      model='imagen-3.0-generate-001',
      image=types.Image.from_file(IMAGE_FILE_PATH),
      upscale_factor='x2',
  )
  response.generated_images[0].image.show()
  # Opens my-image.png which is upscaled by a factor of 2.

Methods inherited from google.genai._api_module.BaseModule:
__init__(self, api_client_: google.genai._api_client.BaseApiClient)
Initialize self.  See help(type(self)) for accurate signature.

Readonly properties inherited from google.genai._api_module.BaseModule:
vertexai

Data descriptors inherited from google.genai._api_module.BaseModule:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
Data
        Optional = typing.Optional
Union = typing.Union