Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

FunctionDeclaration.from_callable drops enum and properties from Optional[...] parameters

Ouverte Adaptée aux débutants
#3,105 1 commentaire 0 réactions 1 personne assignée Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

@Venkaiahbabuneelam y travaille déjà.

Depuis le 13/10/2026.

Évaluation

Difficulté
2/5
Temps estimé
1-3 heures
Accessibilité débutants
67/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
python
Domaine
api, backend

Piste de recherche

Lisez _automatic_function_calling_util.py autour de _parse_schema_from_parameter et de la réduction de Union à un seul membre près de la ligne 282. Comparez Optional et l’union avec barre verticale examples dans l’issue, puis ajoutez des cas de régression à tests/types/test_types.py pour les paramètres Literal et de modèle facultatifs. Le travail est terminé lorsque les schémas générés conservent les propriétés enum ou objet tout en restant nullable.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

priority: p2 type: bug

FunctionDeclaration.from_callable keeps only the type of the inner schema when a parameter is Optional[X]. An Optional[Literal["c", "f"]] parameter becomes a nullable string with no enum. An Optional[Address] parameter becomes a bare nullable object with no properties or required. Address | None keeps them, but Literal["c", "f"] | None loses its enum too.

import json
from typing import Literal, Optional
import pydantic
from google import genai
from google.genai import types

client = genai.Client(api_key="not-a-real-key")  # no request is sent

class Address(pydantic.BaseModel):
  city: str

def unit_plain(unit: Literal["c", "f"]) -> str: ...
def unit_optional(unit: Optional[Literal["c", "f"]] = None) -> str: ...
def addr_optional(addr: Optional[Address] = None) -> str: ...
def addrs_optional(addrs: Optional[list[Address]] = None) -> str: ...
def unit_pipe(unit: Literal["c", "f"] | None = None) -> str: ...
def addr_pipe(addr: Address | None = None) -> str: ...

for f in [unit_plain, unit_optional, addr_optional, addrs_optional, unit_pipe, addr_pipe]:
  fd = types.FunctionDeclaration.from_callable(client=client, callable=f)
  (name, s), = fd.parameters.properties.items()
  print(f"{f.__name__:15}", json.dumps(s.model_dump(exclude_none=True)))
$ python -I genai_fd3.py
unit_plain      {"enum": ["c", "f"], "type": "STRING"}
unit_optional   {"nullable": true, "type": "STRING"}
addr_optional   {"nullable": true, "type": "OBJECT"}
addrs_optional  {"items": {"properties": {"city": {"type": "STRING"}}, "required": ["city"], "type": "OBJECT"}, "nullable": true, "type": "ARRAY"}
unit_pipe       {"nullable": true, "type": "STRING"}
addr_pipe       {"nullable": true, "properties": {"city": {"type": "STRING"}}, "required": ["city"], "type": "OBJECT"}
# google-genai 2.29.0 at 6a6501c (main, 2026-10-11), CPython 3.12.3, Linux x86_64

The single-member collapse in the Union branch of _parse_schema_from_parameter (_automatic_function_calling_util.py:282) copies schema.any_of[0].type and nothing else. Optional[list[...]] survives only because the lines above it copy items by hand. Copying the whole member fixes both:

       if len(schema.any_of) == 1:  # param: Union[List, None] -> Array
-        schema.type = schema.any_of[0].type
-        schema.any_of = None
+        schema = schema.any_of[0].model_copy(
+            update={'nullable': schema.nullable}
+        )
$ python -I genai_fd3.py   # with the patch
unit_plain      {"enum": ["c", "f"], "type": "STRING"}
unit_optional   {"enum": ["c", "f"], "nullable": true, "type": "STRING"}
addr_optional   {"nullable": true, "properties": {"city": {"type": "STRING"}}, "required": ["city"], "type": "OBJECT"}
addrs_optional  {"items": {"properties": {"city": {"type": "STRING"}}, "required": ["city"], "type": "OBJECT"}, "nullable": true, "type": "ARRAY"}
unit_pipe       {"enum": ["c", "f"], "nullable": true, "type": "STRING"}
addr_pipe       {"nullable": true, "properties": {"city": {"type": "STRING"}}, "required": ["city"], "type": "OBJECT"}

$ python -m pytest -q google/genai/tests/types/test_types.py google/genai/tests/types/test_future.py
95 passed, 6 skipped, 2 warnings     # same count before and after the patch
# not run: any request to the live API

This is the default use_json_schema=False path, so it hits direct from_callable callers. A function passed straight into tools=[...] takes use_json_schema=True (_transformers.py:961), where open #3074 and #3093 work. @Venkaiahbabuneelam, CONTRIBUTING.md says outside pull requests are not taken yet, so the diff above is the whole proposal. Would a test for these signatures in tests/types/test_types.py help it land?

Langage dominant
Python
Étoiles
4k
Forks
1k
Merge moyen
1 j 7 h
PR mergées (30 j)
82

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de googleapis/python-genai

Toutes les issues de googleapis/python-genai

Issues similaires

Plus d'issues Python

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.