Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

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

Aperta Adatta ai principianti
#3,105 1 commento 0 reazioni 1 assegnatario Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@Venkaiahbabuneelam ci sta già lavorando.

Dal 13/10/2026.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
67/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python
Ambito
api, backend

Direzione di ricerca

Leggi _automatic_function_calling_util.py nella sezione intorno a _parse_schema_from_parameter e alla riduzione di Union con un solo membro vicino alla riga 282. Confronta Optional e la pipe-union examples nell’issue, quindi aggiungi casi di regressione a tests/types/test_types.py per i parametri Literal e di modello opzionali. Il lavoro è completato quando gli schemi generati mantengono le proprietà enum o object pur rimanendo nullable.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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?

Lingua principale
Python
Stelle
4k
Fork
1k
Merge medio
1g 6h
PR unite (30g)
88

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di googleapis/python-genai

Tutte le issue di googleapis/python-genai

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.