Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,32 @@ jobs:
run: ./py/bin/generate_schema_typing --ci

- name: Run serial tests
if: matrix.test-type == 'serial'
run: uv run --python ${{ matrix.python-version }} --active --isolated --directory py pytest -xvs --log-level=DEBUG .
# TODO: Re-enable serial tests for Python 3.14 when onnxruntime adds wheels.
# Track: https://github.com/microsoft/onnxruntime/issues/21292
# Skip serial tests for Python 3.14 - chromadb doesn't support it yet.
# Nox tests handle Python 3.14 with proper exclusions.
if: matrix.test-type == 'serial' && matrix.python-version != '3.14'
run: |
uv run --python ${{ matrix.python-version }} --active --isolated --directory py pytest -xvs --log-level=DEBUG .

- name: Run tox tests
if: matrix.test-type == 'tox'
run: |
clean_version=$(echo "${{ matrix.python-version }}" | tr -d '.')
uv run --directory py tox -e "py$clean_version"
# TODO: Remove --python 3.12 when onnxruntime adds Python 3.14 wheels.
# Track: https://github.com/microsoft/onnxruntime/issues/21292
# Run tox with Python 3.12 to avoid workspace compatibility issues
uv run --python 3.12 --directory py tox -e "py$clean_version"

- name: Run nox tests
if: matrix.test-type == 'nox'
run: |
uv run --directory py nox -s "tests-${{ matrix.python-version }}"
# TODO: Remove --python 3.12 when onnxruntime adds Python 3.14 wheels.
# Track: https://github.com/microsoft/onnxruntime/issues/21292
# Run nox with Python 3.12 to avoid workspace compatibility issues
# with chromadb (which doesn't support Python 3.14 yet).
# Nox will still create the test environment with the target Python version.
uv run --python 3.12 --directory py nox -s "tests-${{ matrix.python-version }}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we're actually checking python 3.12 for all tests?


python-build:
name: Build Distributions
Expand Down
115 changes: 112 additions & 3 deletions py/GEMINI.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,28 @@
# pyrefly: ignore[unexpected-keyword] - Pydantic populate_by_name=True allows schema_
schema_=options.output.json_schema if options.output else None,
```
* Move imports to the top of the file and avoid using imports inside function
definitions.
* **Import Location**: Always place all imports at the top of the file.
Do not use imports inside functions, methods, or class definitions.
This ensures:
* Faster module loading (imports are resolved once at module load time)
* Clearer dependency visibility (all dependencies visible at a glance)
* Easier refactoring and testing
* Better IDE support for auto-imports and navigation

**Wrong**:
```python
async def my_function():
from genkit.ai import Genkit # Don't import inside functions
...
```

**Correct**:
```python
from genkit.ai import Genkit # Import at module top

async def my_function():
...
```

## Generated Files & Data Model

Expand Down Expand Up @@ -94,14 +114,67 @@
* **Imports**: Import types like `Callable`, `Awaitable` from `collections.abc`,
not standard library `typing`.
* **Enums**: Use `StrEnum` instead of `(str, Enum)`.
* **Pydantic Models**: When defining Pydantic `BaseModel` classes that need
camelCase JSON serialization (for API compatibility with JavaScript):
* Use `alias_generator=to_camel` from `pydantic.alias_generators` in `model_config`
* Include `populate_by_name=True` to allow instantiation with Python snake_case names
* Do **NOT** use manual `Field(alias='camelCase')` for individual fields

This approach:
* Ensures type checkers understand the model correctly
* Allows Pythonic constructor calls with snake_case field names
* Automatically handles camelCase serialization/deserialization for JSON

**Correct:**
```python
from pydantic import BaseModel, ConfigDict
from pydantic.alias_generators import to_camel

class MyConfig(BaseModel):
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)

my_field: str | None = None
another_field: int = 0
```

**Wrong** (causes type checker errors):
```python
from pydantic import BaseModel, ConfigDict, Field

class MyConfig(BaseModel):
model_config = ConfigDict(populate_by_name=True)

my_field: str | None = Field(None, alias='myField') # Don't use manual aliases
another_field: int = Field(0, alias='anotherField')
```
* **Strictness**: Apply type hints strictly, including `-> None` for void functions.
* **Design**:
* Code against interfaces, not implementations.
* Use the adapter pattern for optional implementations.
* **Comments**:
* Use proper punctuation.
* Avoid comments explaining obvious code.
* Use `TODO: Fix this later.` format for stubs.
* **TODO Format**: All TODOs **MUST** include a GitHub issue link for tracking.
Plain `# TODO: description` comments are **NOT** allowed.

**Correct format:**
```python
# TODO(https://github.com/firebase/genkit/issues/1234): Implement caching
```

**Short format (also accepted):**
```python
# TODO(#1234): Implement caching
```

**Wrong format (will fail CI):**
```python
# TODO: Implement caching
# TODO: Fix this later.
```

Before adding a TODO, create a GitHub issue first, then reference it.
This ensures all technical debt is tracked and prioritized.
* **Do not add section marker comments** (e.g., `# ============` banners).
Keep code clean and let structure speak for itself.
* Ensure that `bin/lint` passes without errors.
Expand Down Expand Up @@ -201,6 +274,12 @@
* Update the roadmap.md file as and when features are implemented.
* When a plugin such as a model provider is updated or changes, please also
update relevant documentation and samples.
* **Keep Directory READMEs Updated**: When adding or modifying plugins or samples,
always update the corresponding directory README files:
* **`py/plugins/README.md`**: Update when adding a new plugin. Add it to the
appropriate category table with package name, description, and features.
* **`py/samples/README.md`**: Update when adding a new sample. Add it to the
appropriate category table with description and requirements.
* Try to make running the sample flows a one-click operation by always defining
default input values.
* **IMPORTANT**: For default values to appear in the Dev UI input fields, use
Expand Down Expand Up @@ -314,6 +393,36 @@ Include the Apache 2.0 license header at the top of each file (update year as ne
# SPDX-License-Identifier: Apache-2.0
```

## Plugin Package Naming Convention

All Genkit plugins **MUST** follow the naming convention `genkit-plugin-{name}`:

| Pattern | Example | Status |
|---------|---------|--------|
| `genkit-plugin-{name}` | `genkit-plugin-google-genai` | ✅ Correct |
| `genkit-{name}-plugin` | `genkit-google-genai-plugin` | ❌ Wrong |
| `{name}-genkit-plugin` | `google-genai-genkit-plugin` | ❌ Wrong |

**Requirements:**
* Package name in `pyproject.toml` must be `genkit-plugin-{name}`
* Use lowercase with hyphens (not underscores) in package names
* The `{name}` should match the plugin directory name (e.g., `plugins/google-genai/` → `genkit-plugin-google-genai`)
* Set `requires-python = ">=3.10"` for CI compatibility
* Include Python 3.10, 3.11, and 3.12 in classifiers

**Example pyproject.toml:**
```toml
[project]
name = "genkit-plugin-example"
version = "0.1.0"
requires-python = ">=3.10"
classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
```

## Dependency Management

When updating dependencies for the Python SDK, ensure consistency across both files:
Expand Down
12 changes: 8 additions & 4 deletions py/bin/generate_schema_typing
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,23 @@ if [[ $CI_ENABLED == "true" ]] && [[ -f $TYPING_FILE ]]; then
fi

# Generate types using configuration from pyproject.toml.
uv run --directory "${TOP_DIR}/py" datamodel-codegen \
# TODO(https://github.com/microsoft/onnxruntime/issues/21292): Remove --python 3.12
# when onnxruntime adds Python 3.14 wheels.
# Note: We use --python 3.12 to avoid compatibility issues with chromadb
# which doesn't support Python 3.14 yet (onnxruntime lacks 3.14 wheels).
uv run --python 3.12 --directory "${TOP_DIR}/py" datamodel-codegen \
--formatters=ruff-check \
--formatters=ruff-format

# Sanitize the generated schema.
python3 "${TOP_DIR}/py/bin/sanitize_schema_typing.py" "${TYPING_FILE}"

# Checks and formatting.
uv run --directory "${TOP_DIR}/py" \
uv run --python 3.12 --directory "${TOP_DIR}/py" \
ruff format "${TOP_DIR}"
uv run --directory "${TOP_DIR}/py" \
uv run --python 3.12 --directory "${TOP_DIR}/py" \
ruff check --fix "${TYPING_FILE}"
uv run --directory "${TOP_DIR}/py" \
uv run --python 3.12 --directory "${TOP_DIR}/py" \
ruff format "${TOP_DIR}"

# We want to detect and raise an error when this file changes in our hooks or in
Expand Down
Loading
Loading